Ios Scenekit平移二维到仅正交三维的水平平移
我有一个关于3D编程的数学问题,我希望你能帮助我 我正试图创建一个三维游戏使用Scenekit等轴测角度 此代码创建我的正交摄影机:Ios Scenekit平移二维到仅正交三维的水平平移,ios,math,3d,translation,scenekit,Ios,Math,3d,Translation,Scenekit,我有一个关于3D编程的数学问题,我希望你能帮助我 我正试图创建一个三维游戏使用Scenekit等轴测角度 此代码创建我的正交摄影机: var cameraNode = SCNNode() cameraNode.camera = SCNCamera() cameraNode.name = "Camera" cameraNode.position = SCNVector3Make(-5.0, -5.0, 10.0) cameraNode.eulerAngles = SCNVector3Make(PI
var cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.name = "Camera"
cameraNode.position = SCNVector3Make(-5.0, -5.0, 10.0)
cameraNode.eulerAngles = SCNVector3Make(PI / 3.0, 0.0, -PI / 4.0)
cameraNode.camera?.usesOrthographicProjection = true
cameraNode.camera?.orthographicScale = 7.0
scene.rootNode.addChildNode(cameraNode)
现在我想使用平移手势移动相机,产生滚动的感觉。要做到这一点,相机不应该垂直移动,而应该水平移动。屏幕上的触摸位置和3D世界中未投影的位置在移动时应保持不变
我考虑将二维转换计算为三维差分,忽略垂直分量。这段代码实际上可以工作,几乎可以产生所需的结果,但速度不正确。如果我摇摄,相机似乎会加速,并且反应不正确:
var previousTranslation = CGPointMake(0.0, 0.0)
func pan(gesture: UIPanGestureRecognizer)
{
let view = self.view as SCNView
let translation = gesture.translationInView(view)
let location = gesture.locationInView(view)
let diffTrans = translation - previousTranslation
previousTranslation = translation
let cameraNode = scene.rootNode.childNodeWithName("Camera", recursively: false)
let worldPointTrans = view.unprojectPoint(SCNVector3Make(-Float(diffTrans.x), -Float(diffTrans.y), 0.0))
let worldPoint0 = view.unprojectPoint(SCNVector3Make(0.0, 0.0, 0.0))
var diff = worldPointTrans - worldPoint0
diff.x = diff.x / Float(cameraNode!.camera!.orthographicScale)
diff.y = diff.y / Float(cameraNode!.camera!.orthographicScale)
diff.z = 0
cameraNode?.position += diff
}
有人知道一种复杂的方法,可以忽略垂直轴,将屏幕平移计算成水平三维平移吗
提前感谢:)
编辑:
pan现在可以进行水平翻译。但不是垂直方向,因为我将z轴上的差值设置为零。我找到了自己的解决方案 我正在计算手势开始位置(P1-P2)处的光线和平移位置(Q1-Q2)处的光线。现在我有两条光线,让它们都与XY平面相交,以接收点P0和Q0 P0和Q0的差异是未投影的翻译 这种技术应该也适用于非正交相机,但我还没有测试过 在我看来,这是可行的,但如果有人能从数学上证实这一假设,我会很高兴读到:) 代码如下:
var previousLocation = SCNVector3(x: 0, y: 0, z: 0)
func pan(gesture: UIPanGestureRecognizer)
{
let view = self.view as SCNView
let translation = gesture.translationInView(view)
let location = gesture.locationInView(view)
let secLocation = location + translation
let P1 = view.unprojectPoint(SCNVector3(x: Float(location.x), y: Float(location.y), z: 0.0))
let P2 = view.unprojectPoint(SCNVector3(x: Float(location.x), y: Float(location.y), z: 1.0))
let Q1 = view.unprojectPoint(SCNVector3(x: Float(secLocation.x), y: Float(secLocation.y), z: 0.0))
let Q2 = view.unprojectPoint(SCNVector3(x: Float(secLocation.x), y: Float(secLocation.y), z: 1.0))
let t1 = -P1.z / (P2.z - P1.z)
let t2 = -Q1.z / (Q2.z - Q1.z)
let x1 = P1.x + t1 * (P2.x - P1.x)
let y1 = P1.y + t1 * (P2.y - P1.y)
let P0 = SCNVector3Make(x1, y1,0)
let x2 = Q1.x + t1 * (Q2.x - Q1.x)
let y2 = Q1.y + t1 * (Q2.y - Q1.y)
let Q0 = SCNVector3Make(x2, y2, 0)
var diffR = Q0 - P0
diffR *= -1
let cameraNode = view.scene!.rootNode.childNodeWithName("Camera", recursively: false)
switch gesture.state {
case .Began:
previousLocation = cameraNode!.position
break;
case .Changed:
cameraNode?.position = previousLocation + diffR
break;
default:
break;
}
}
我已经计算了等距平移的方程式,代码如下
//camera pan ISOMETRIC logic
func pan(gesture: UIPanGestureRecognizer) {
let view = self.sceneView as SCNView
let cameraNode = view.scene!.rootNode.childNode(withName: "Camera", recursively: false)
let translation = gesture.translation(in: view)
let constant: Float = 30.0
var translateX = Float(translation.y)*sin(.pi/4.0)/cos(.pi/3.0)-Float(translation.x)*cos(.pi/4.0)
var translateY = Float(translation.y)*cos(.pi/4.0)/cos(.pi/3.0)+Float(translation.x)*sin(.pi/4.0)
translateX = translateX / constant
translateY = translateY / constant
switch gesture.state {
case .began:
previousLocation = cameraNode!.position
break;
case .changed:
cameraNode?.position = SCNVector3Make((previousLocation.x + translateX), (previousLocation.y + translateY), (previousLocation.z))
break;
default:
break;
}
}
要正确缩放,需要使用屏幕高度作为正交缩放的变量。我在这里使用的缩放比例是30倍放大,注意30也用于上面代码中的常数
let screenSize: CGRect = UIScreen.main.bounds
let screenHeight = screenSize.height
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.name = "Camera"
let cameraDist = Float(20.0)
let cameraPosX = cameraDist*(-1.0)*cos(.pi/4.0)*cos(.pi/6.0)
let cameraPosY = cameraDist*(-1.0)*sin(.pi/4.0)*cos(.pi/6.0)
let cameraPosZ = cameraDist*sin(.pi/6)
cameraNode.position = SCNVector3Make(cameraPosX, cameraPosY, cameraPosZ)
cameraNode.eulerAngles = SCNVector3Make(.pi / 3.0, 0.0, -.pi / 4.0)
cameraNode.camera?.usesOrthographicProjection = true
cameraNode.camera?.orthographicScale = Double(screenHeight)/(2.0*30.0) //30x magnification constant. larger number = larger object
scene.rootNode.addChildNode(cameraNode)
你从不使用“diffTrans”。当您取消保护(而不是“翻译”)时,您不想使用“diffTrans”吗?否则你会在每次迭代中积累翻译。谢谢你指出这一点!我尝试了很多不同的方法,但我没有看到那个错误。它解决了水平平移的问题,但没有解决垂直平移的问题,因为世界平移中不需要的垂直部分请查看答案rickster的答案:他在结尾有一条关于在相机平面与“世界”不同时处理非投影的注释。这可能是一个有用的起点。@MalcolmDwyer谢谢你的链接!我会尝试使用它,但它似乎不适用于我的情况,就像他在帖子末尾说的,如果相机旋转,这是不工作的!!如果你知道的话,你能帮我吗