Domanda

I am developing an iPhone application that uses Cocos3d. I have drawn a scene in the XZ plane ( y = 0 ). Now, I want to rotate the scene around a specified point in the XZ plane, whenever the user touches the screen with two fingers; the rotation point will be the center of the two touch points.

I started by projecting the two touch points to the 3D scene, by finding the intersecting between the CC3Ray (issued from the camera and passing by the touch point) and the XZ plane. Now that I have the two points in the XZ plane, I can calculate the rotation point (that will be the middle point between these two points).

In order to rotate the scene around this point, I have added it to a parent node. Now all I have to do is to translate it by the negation of the coordinates of the middle point, rotate its parent by the angle, and translate it back by the coordinates of middle point.

Here is the code that I am using (in the ccTouchesMoved method):

// 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)];

However, I am not able to rotate the scene around the middle point. Can anyone help me to resolve this problem?

Thank you!

Edit:

I also tried to add these lines of codes in the ccTouchesBegan method:

[root translateBy:CC3VectorNegate(middle)];
[self.cc3Scene.activeCamera translateBy:CC3VectorNegate(middle)];

And in the ccTouchesMoved:

[root rotateByAngle:angle aroundAxis:cc3v(0, 1, 0)];

It works only for the first time the user touches the screen, and then, whenever he/she touches it again, a unwanted translation is happening! I think the problem is with the ccTouchesBegan method.

È stato utile?

Soluzione

On any one node, rotation, translation, and scale transforms are independent of each other. They are each applied to the rest pose of the node, and are not accummulative with each other. This is so that interaction appears natural and expected by the developer controlling the node. In other words, during gameplay, rotating a character after it has been moved, rotates the character in place, not around a translated location. Similarly, translating a node translates it regardless of how the node has previously been rotated.

This is different control than taking a single matrix and accumulating transforms into it, which is how the matrix-based rotate-around-a-distant-point technique works.

However, you can effectively rotate a node around a location that is not its origin by:

  1. Transforming the local rotation location to the global coordinate space.
  2. Rotating the node as normal.
  3. Transforming the (now rotated) local rotation location to the global coordinate space.
  4. Align the rotation locations found in steps 1 & 3 by translating the node by the difference between the two locations.

You can perform steps 1 & 3 using the node's globalTransformMatrix. Code for the steps above is as follows:

CC3Vector gblRotLocBefore = [aNode.globalTransformMatrix transformLocation: rotationLoc];
[aNode rotateByAngle: angle aroundAxis: kCC3VectorUnitYPositive];
CC3Vector gblRotLocAfter = [aNode.globalTransformMatrix transformLocation: rotationLoc];
[aNode translateBy: CC3VectorDifference(gblRotLocBefore, gblRotLocAfter)];

Using this technique, you do not need to involve the node's parent.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top