[Quaternion] It's doesn't work (yes i have rtfm!)

Dear jME users!



Currently i had tried to make smooth rotation to a wanted direction.

It's work, but just a little: The object rotate to the wanted direction, but not smoothly…



Here is my code, call in each updateWorldData(time):



                    if(wantsLookTo!=null) {
         //Retrieve object current direction
         direction = getWorldRotation().getRotationColumn(2);
         
         //Retrieve wanted direction
         Vector3f wantedDirection = wantsLookTo.subtract(getWorldTranslation());
         
         //Retrieve wanted quaternion
         Quaternion dest = new Quaternion();
         if(!wantedDirection.cross(Vector3f.UNIT_Y).equals(Vector3f.ZERO)) {
            dest.lookAt(wantedDirection, Vector3f.UNIT_Y);
         } else {
            dest.lookAt(wantedDirection, Vector3f.UNIT_Z);   
         }
         
         //We get the current angle between direction and wantedDirection
         float currentAngle = FastMath.abs(direction.angleBetween(wantedDirection));
         
         //We compute the amount of slerp interpolation btw each quaternion
         float amnt = Math.min(1.0f,  ((getMaxRotateCount()*time)/currentAngle)  );
   
         //Compute rotation
         getLocalRotation().slerp(dest, amnt); //Vecteur courant!         
      }



What's wrong?

Thanks in advance!

Have you verified that

amnt

contains valid values? You seem to be using slerp correctly, but the problem could still be in in the interpolation value…

The code seems alright, as long as getMaxRotateCount() is the rotation speed in radians per second and time is the time per frame.



It could be easier to figure out if it was possible to run the rotation in a simple test.


The object rotate to the wanted direction, but not smoothly...

Can you give me more details on what happens when it rotates.

In some case my model jump to the wanted direction in one frame  :expressionless:



but I think I've solved:



Here:


float currentAngle = FastMath.abs(direction.angleBetween(wantedDirection));



I've update by this:

float currentAngle = FastMath.acos(dest.dot(getWorldRotation()));



This is another way to find angle between each direction, but I don't understand why in some case the first make problems (for my experience if anyone have an answer, i will appreciate so ;))
anykeyh said:

In some case my model jump to the wanted direction in one frame  :|

but I think I've solved:

Here:

float currentAngle = FastMath.abs(direction.angleBetween(wantedDirection));



I've update by this:

float currentAngle = FastMath.acos(dest.dot(getWorldRotation()));



This is another way to find angle between each direction, but I don't understand why in some case the first make problems (for my experience if anyone have an answer, i will appreciate so ;))


anglebetween method assumes that both of the vectors are normalized, check api.

I am new myself to jMonkey but was playing around with rotations and Quats. I did something like this to rotate an object to a given direction



        if( m_hasNewDirection )
        {
            //Retrieve current direction
            fromDirection = getWorldRotation().getRotationColumn(2);
           
            //Retrieve wanted direction
            toDirection = m_lookAt.subtract(getWorldTranslation());
            toDirection.normalizeLocal();

            fromDirection.cross( toDirection, m_rotationAxis );
            m_rotationAxis.normalizeLocal();

            m_rotationAngle = fromDirection.angleBetween( toDirection );
            m_deltaAngle = m_rotationAngle;

            m_fromQuat.lookAt( fromDirection, m_rotationAxis );
            m_toQuat.lookAt( toDirection, m_rotationAxis );           

            m_hasNewDirection = false;
        }
       
        if( m_deltaAngle > 0 )
        {
            deltaAngle = m_rotationSpeed*time;
            if( deltaAngle < m_deltaAngle )
            {
                m_deltaAngle -= deltaAngle;
            }
            else
            {
                m_deltaAngle = 0;
            }
            m_rotQuat.set( getLocalRotation() );
            m_rotQuat.slerp( m_fromQuat,
                             m_toQuat,
                             (1 - m_deltaAngle/m_rotationAngle) );           
            direction = m_rotQuat.getRotationColumn(2);
            upVector = getWorldRotation().getRotationColumn(1);
            getLocalRotation().lookAt( direction,
                                       upVector );               
        }       



This worked for my simple test :). Just had a simple object always follow the camera with its look.