我正在开发一个使用Cocos3d的iPhone应用程序。我在XZ平面(y = 0)上画了一个场景。现在,当用户用两个手指触摸屏幕时,我想围绕XZ平面上的指定点旋转场景;旋转点将是两个接触点的中心。
我首先将两个触摸点投影到3D场景中,通过找到CC3Ray(从相机发出并经过触摸点)和XZ平面之间的交点。现在我有了XZ平面上的两个点,我可以计算旋转点(这将是这两个点之间的中点)。
为了围绕这个点旋转场景,我将它添加到父节点。现在我要做的就是通过中点坐标的负值平移它,将它的父点旋转一个角度,然后再通过中点坐标将它平移回来
这是我使用的代码(在ccTouchesMoved方法):
// Assuming that the root is a CC3Node and it is the scene that I need to rotate
// and middle refers to the center of rotation
[root translateBy:cc3v(-middle.x, 0, -middle.z)];
[root.parent rotateByAngle:30 aroundAxis:cc3v(0, 1, 0)];
[root translateBy:cc3v(middle.x, 0, middle.z)];
但是,我无法围绕中点旋转场景。有人能帮我解决这个问题吗?
谢谢!
编辑:我还尝试在ccTouchesBegan方法中添加这些代码行:
[root translateBy:CC3VectorNegate(middle)];
[self.cc3Scene.activeCamera translateBy:CC3VectorNegate(middle)];
在ccTouchesMoved:
[root rotateByAngle:angle aroundAxis:cc3v(0, 1, 0)];
它只在用户第一次触摸屏幕时起作用,然后,每当他/她再次触摸屏幕时,就会发生不必要的翻译!我认为问题是与ccTouchesBegan方法
在任意一个节点上,旋转、平移和缩放变换是相互独立的。它们分别应用于节点的剩余姿态,并且彼此不累积。这样,控制节点的开发人员就可以很自然地看到交互。换句话说,在游戏过程中,在角色移动后旋转角色,在位置旋转角色,而不是围绕翻译位置旋转角色。类似地,无论节点之前是如何旋转的,转换节点都会转换它。
这与获取单个矩阵并累积变换到它的控制不同,这就是基于矩阵的旋转-围绕远点技术的工作原理。
但是,您可以通过以下方式有效地围绕不是其原点的位置旋转节点:
- 将局部旋转位置转换为全局坐标空间。
- 正常旋转节点
- 将(现在旋转的)本地旋转位置转换为全局坐标空间。
- 对齐步骤1 &3通过两个位置之间的差异来翻译节点。
可以执行步骤1 &3使用节点的globalTransformMatrix
。以上步骤的代码如下:
CC3Vector gblRotLocBefore = [aNode.globalTransformMatrix transformLocation: rotationLoc];
[aNode rotateByAngle: angle aroundAxis: kCC3VectorUnitYPositive];
CC3Vector gblRotLocAfter = [aNode.globalTransformMatrix transformLocation: rotationLoc];
[aNode translateBy: CC3VectorDifference(gblRotLocBefore, gblRotLocAfter)];
使用这种技术,您不需要涉及节点的父节点。