Continual Rotation: Torque or Quaternions?

Hey all,



I am trying to get an object to rotate about the x-axis. This i have no issue doing, but I am only getting one full rotation before it stops. I am using Quaternions modeled somewhat after the HelloAnimation code for the revolving lightNode. However, I am not moving the object in any way other than around the x-axis.



Should I use Torque rather than Quaternions? If so, point me in the right direction to find a tutorial or something please.



If I should continue using Quaternions, what should I do to keep it rotating?



Thanks!

Not sure if you're still looking for an answer for this, but for anyone who stumbles across this:



I found the easiest way to rotate around a single axis without having to deal with quaternions is to use KeyNodeRotateRightAction (or left, or up, etc).


//Simulate an InputActionEvent
InputActionEvent rotateEvent = new InputActionEvent();
rotateEvent.setTime(interpolation);

//Invoke a KeyNodeRotateRightAction using the simulated InputActionEvent.
KeyNodeRotateRightAction rotateRight = new KeyNodeRotateRightAction(Node, 0.1f);

//Rotate around an axis.  GetRotationColumn can be called with 0 or 1 also for other axis.
rotateRight.setLockAxis(curPlanet.getLocalRotation().getRotationColumn(2));
rotateRight.performAction(rotateEvent);



Again, it doesn't have to be KeyNodeRotateRightAction.  The Javadocs specify an action for all six directions.

In the HelloAnimation example you can perpetuate the rotation by configuring the SpatialTransformer like this:



st.setRepeatType(SpatialTransformer.RT_WRAP);



Alternatively, you can drive the animation by overriding simpleUpdate() assuming you extend from SimpleGame. The sample below still relies on a quaternion to express the rotation but performs the interpolation without a SpatialTransformer:



import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingSphere;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jme.scene.shape.Sphere;

public class RotateDemo extends SimpleGame
{
   public static void main(String[] args)
   {
      RotateDemo app = new RotateDemo();
      app.setConfigShowMode(ConfigShowMode.AlwaysShow);
      app.start();
   }

   // 360 degrees 10 seconds
   private final static float ROTATION_RATE = FastMath.TWO_PI / 10;

   private final Vector3f axis = new Vector3f(1, 0, 0);

   private Node pivot;

   private float radians;

   private final Quaternion rotateQuat = new Quaternion();

   private Sphere sphere;

   @Override
   protected void simpleInitGame()
   {
      display.setTitle("RotateDemo");
      sphere = new Sphere("sphere", 20, 20, 10);
      sphere.setModelBound(new BoundingSphere());
      sphere.updateModelBound();
      pivot = new Node("pivot");
      pivot.attachChild(sphere);
      rootNode.attachChild(pivot);
   }

   @Override
   protected void simpleUpdate()
   {
      radians += ROTATION_RATE * tpf;
      radians = radians > FastMath.TWO_PI ? 0 : radians;
      rotateQuat.fromAngleAxis(radians, axis);
      pivot.setLocalRotation(rotateQuat);
   }
}

I don't know why the thread author can't use Quaternions to rotate continually.

If you have the following instance variables:


private Node node = new Node("Node");
private float angle = 0;
private Quaternion quat = new Quaternion();


Where node is attached to the rootNode (and has something visible attached to it, if you want to see what's going on!).

Then you should be able to do this in your update method:

angle += .001;
quat.fromAngleAxis(angle, Vector3f.UNIT_X);
node.setLocalRotation(quat);


Note that you need to increase the angle every step, or it won't rotate, since the angle represents a specific angle around the specified axis so you get the same quaternion if you use the same angle and axis.

Another possible way without the need to create an additional node:



      float[] deg = rootNode.getLocalRotation().toAngles(null);
      node.getLocalRotation().fromAngles(deg[0]+rot_deg*FastMath.DEG_TO_RAD, deg[1], deg[2]);



in the first line you get all the degrees in rad values (don't know how expensive this method is as there are some calculations)
in the second line you add something (rot_deg is a degree-value that you have to translate in radians with FastMath.DEG_TO_RAD-multi) to the first angle. I'm not sure right now which parameter represents what axis. This you might try out.


oh… wow… this is from a while ago.



i had previously fixed that problem. i posted before i thought the problem through.  :smiley:



good for reference, though.  :smiley: