Rotating a rotated node weird axis result...

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
iLLuSia
Posts: 5
Joined: Fri Jun 01, 2012 11:40 pm

Re: Rotating a rotated node weird axis result...

Post by iLLuSia »

hi, i'm new here and i have no experience with irrlicht whatsoever, so if my post is senseless, then plz delete it and don't kill me.

in raw openGL, when you rotate something, there's a matrix multiplication going on. if you rotate twice, the results can be different, because the multiplication isn't commutative, means A*B is NOT equal to B*A. it looks like, the rotation axes have been rotated as well with the first rotation (or second one, dunno :? ). i guessed, you might have the same problem here. though i haven't any answer in irrlicht-code, some raw openGL code might help you:

Code: Select all

     
GLfloat M[16];
switch (key)
{
            case GLUT_KEY_LEFT: 
                                glGetFloatv(GL_MODELVIEW_MATRIX , M );
                                glLoadIdentity();
                                glRotatef(angle,0,0,1); 
                                glMultMatrixf(M);
                                break;
            ...
 
the matrix after the first rotation needs to be saved and the second rotation done to the original picture, then they have to be multiplied, so you have always A*B and never B*A ( i didn't get it, thats just what my teacher said... :roll: ). it looks the same for the other directions: right, up, down.
but if you're looking onto an area from above, you might wanna remove the matrix storage in the left/right directions, that might look more natural.
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Rotating a rotated node weird axis result...

Post by robmar »

To explain, I have 700 nodes with 700 meshes. Think of a massive virtual fish tank with random created fish using a whole range of models scrounged from all sorts of sites.

But I´d also like other people to be able to use this software with whatever model they have, and orientate it without having to remodel it in software they might not have.

And with that many nodes and meshes, it needs to be very efficient, but also flexible for users.
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Rotating a rotated node weird axis result...

Post by robmar »

I've used SMSO's code snippet to create a ball-role animator, but the call to updateAbsolutePosition if used in the Animate function, occasionaly returns a run of incorrect values, causing an otherwise perfect role to suffer wobbles.

Any ideas as to what might cause this type of problem?

Code: Select all

 
         // Role object in any direction of travel
        // We have the direction of travel vector, which we rotate 90deg on its Y axis to give us the spin axis needed for forward rolling.
        // We then use quarternion math to produce the required rotation
 
       pObject->GetSceneNode()->updateAbsolutePosition();   // Added this but didn't solve the problem
 
       irr::core::vector3df vec = m_vec;  // Travel vector
        vec.rotateXZBy( 90.f, irr::core::vector3df(0,0,0) );    // Rotate direction vector to role axis position
 
        m_matrix = pObject->GetSceneNode()->getAbsoluteTransformation();   // If used here, not in constructor, returns "off" values occasionaly
 
        TRACE( "Input vector= %f, %f, %f\n", vec.X, vec.Y, vec.Z );
 
        m_matrix.rotateVect( vec ); // Set axis in local space as rotate vector
        TRACE( "Output vector= %f, %f, %f\n", vec.X, vec.Y, vec.Z );
        vec.normalize();
 
        TRACE( "Output norm vector= %f, %f, %f\n", vec.X, vec.Y, vec.Z );
 
        // Calculate role angle for current position of travel = ( distance-travelled / ball-circumference ) * 360.f;  ball-circumference = PI * 2R;
        float fAngle;
        float fracMov = fDistanceTravelled / fDistanceToTravel;
        float fMul = pObject->m_fDim1;
        if ( fMul == 0.f )   // User speed modifier
                fMul = 1.f;
        core::aabbox3df mBB;
        mBB = pObject->GetSceneNode()->getTransformedBoundingBox();
        float fWidth = ( mBB.MaxEdge.X - mBB.MinEdge.X );
        float fCirum = irr::core::PI * fWidth;
        fAngle = ( fmodf( fDistanceTravelled, ( fCirum * fMul ) ) / ( fCirum * fMul ) ) * 360.f;
 
        core::quaternion q;
        q.fromAngleAxis( fAngle * core::DEGTORAD, vec );
 
        m_af3Spin = q.getMatrix().getRotationDegrees();
 
        //TRACE( "fAngle= %f, fracdis %f, distance= %f, travelled %f \n", fAngle, fracMov, fTravelDistance, fDistanceTravelled );
        //TRACE( "finalRot= %f, %f, %f\n", m_af3Spin.X, m_af3Spin.Y, m_af3Spin.Z );
        //TRACE( "finalRot= %f, %f, %f\n", m_af3Spin.X, m_af3Spin.Y, m_af3Spin.Z );
 
        pObject->GetSceneNode()->setRotation( m_af3Spin );
 
 
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Rotating a rotated node weird axis result...

Post by robmar »

Below is a simple ball-rotation animator that adjusts the rotation speed of a ball as it moves along a path.

It's based on smso's code snippet above, but I've had problems because if I call the matrix initializer or getabsolute position each frame, it sometimes gets incorrect values, which is strange because when OnAminate gets called, within drawAll, no other code is running that could interfere with the scene or transformation (as far as I know).

Any way here is the code. One of the things I've tried to do is add an offset vector, to allow the end of travel rotation of the ball to be adjusted so the the balls could role into a position and have any part of their texture image face up, like if the ball had a face on it, so it would roll in and the face would be the right way up, hence the offset vector. Given the math, the offsets would require the rotation vector to be recalculated... my head hurts, tomorrow...!

I'd like to develop this into flexible quarternian rotation class for things like ball roll with offset, node rotation + offset from any starting rotation, etc., which I think maybe would be quite useful for new game developers.

Code: Select all

 
// Constructor code
{
...
        // Set constant for ball rolling
        core::aabbox3df mBB;
        mBB = pObject->GetSceneNode()->getTransformedBoundingBox();   // Get wifth, diameter of ball, as scalling, etc., varies between node types, this seemed the obvious way.
        float fWidth = mBB.MaxEdge.X - mBB.MinEdge.X;
        m_fCirum = irr::core::PI * fWidth;
 
        // Set matrix for ball roll
        m_matrix = pObject->GetSceneNode()->getAbsoluteTransformation();    // This function returns occasional wrong data in bursts every few seconds causing the ball to wobble erratically, don't know why!
}
 
// Animate callback
{
...
 
//      pObject->GetSceneNode()->updateAbsolutePosition();      // This picks up occasional bursts of incorrect data causing ball to wobble erratically. Placed in constructor solves problem.
 
        // Role object in any direction of travel
        // We have the direction of travel vector, which we rotate 90deg on its Y axis to give us the spin axis needed for forward rolling.
        // We then use quarternion math to produce the required rotation
 
        //m_matrix = pObject->GetSceneNode()->getAbsoluteTransformation();      // Moved to constructor as values jump during runtime, no idea why though!!
 
        irr::core::vector3df vec = m_vec;       // Set to dir of travel
        vec.rotateXZBy( 90.f + pObject->m_rect.max3d.Y, irr::core::vector3df(0,0,0) );  // Rotate dir vector to ball-role axis position + offset, tangent to dir of travel.
 
        // core::vector3df yaxis(0.0f, 1.0f, 0.0f); // yaxis in world space
        m_matrix.rotateVect( vec ); // Convert vec to current transform
        vec.normalize();
 
        // Calculate role angle.
        // To fix rotation to circumference and speed, angle = (( total-distance / ball-circumference ) * ( total-distance-travelled / total-distance ) ) * 360.f;  Note: Ball-circumference = PI * 2R;
        float fAngle;
 
                // m_rotAngle.X is just a control to allow auto-ball-spin related to size, or fixed constant rotation.  m_rotAngle.Y is a float var to allow user adjustment of the rotation speed.
        if ( m_rotAngle.X < 0.f )
        {
                // Match rotation to circumference/distance moved in this step
                float fMul = m_rotAngle.Y;      // Rotation multipler, allows speed to be adjusted
                if ( fMul == 0.f )
                        fMul = 1.f;
                fAngle = ( fDistanceTravelled / fDistanceToTravel ) * ( fDistanceToTravel / m_fCirum ) * fMul * 360.f;  // Sets rotation to size of object's circumference and distance travelled
        }
        else
        {
                fAngle = ( fDistanceTravelled / fDistanceToTravel ) * m_rotAngle.X * 360.f;     // Step rotation based distance travelled and user constant
        }
 
        if ( fabs( fAngle ) >= 360.f )
                fAngle = fmodf( fAngle, 360.f );
 
        m_q.fromAngleAxis( ( fAngle + pObject->m_rect.max3d.X ) * core::DEGTORAD, vec );        // Rotate ball on vec axis by fAngle + offset
 
        m_af3Spin = m_q.getMatrix().getRotationDegrees();
 
        pObject->GetSceneNode()->setRotation( m_af3Spin );
}
 
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Rotating a rotated node weird axis result...

Post by robmar »

I've been trying to post a code example for a rolling ball using SMSO's quarternian snippet that works really well, but suffers occasional wobbles as the absolute transform matric call picks up bad data at times, but my posts are being deleted.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: Rotating a rotated node weird axis result...

Post by hybrid »

I don't think that they are deleted, they are simply not submitted. At least according to the moderator log, the only activity of the last 4 weeks regarding your login was a post that you deleted yourself. Code postings are sometimes not accepted due to special character sequences in the code, or due to excessive length. Please try posting a different version.
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Rotating a rotated node weird axis result...

Post by robmar »

I tried earlier today to post a simple text line mentioning what I was trying to post, the code for a rolling ball animation, but even that, although the site said the posting was accepted, it didn't show up. I'll do it again with this text "Having problems posting here for some reason!".
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Rotating a rotated node weird axis result...

Post by robmar »

Having problems posting here for some reason! / typical, computers! Now it works again!!! :lol:
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Rotating a rotated node weird axis result...

Post by robmar »

Why can I not post here???
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: Rotating a rotated node weird axis result...

Post by hybrid »

Well, you posted three times now...
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Rotating a rotated node weird axis result...

Post by robmar »

Here's is a simple use of SMSO's snippet using quarternians to manage a rolling ball animation.

Constructor of animation:

Code: Select all

 
        // Set constant for ball rolling - NOTE If I place these calls in the animation main routine, they occasionally report a burst of wrong values causing the ball to wobble erratically, don't know why!!!
        core::aabbox3df mBB;
        mBB = pObject->GetSceneNode()->getTransformedBoundingBox();
        float fWidth = mBB.MaxEdge.X - mBB.MinEdge.X;
        m_fCirum = irr::core::PI * fWidth;
 
        // Set matrix for ball roll
        m_matrix = pObject->GetSceneNode()->getAbsoluteTransformation();
 
Main animator code:

Code: Select all

 
                        
        // Roll object in any direction of travel
        // We have the direction of travel vector, which we rotate 90deg on its Y axis to give us the spin axis needed for forward rolling.
        // We then use quarternion math to produce the required rotation
 
        //m_matrix = pObject->GetSceneNode()->getAbsoluteTransformation();      // Moved to constructor as values jump around occasionally during runtime causing fits of wobbles!!!!!  What could cause this?
 
        irr::core::vector3df vec = m_vec;       // Set to dir of travel
        vec.rotateXZBy( 90.f + pObject->m_rect.max3d.Y, irr::core::vector3df(0,0,0) );  // Rotate dir vector to ball-role axis position + offset, tangent to dir of travel.
 
//      TRACE( "Input vector= %f, %f, %f\n", vec.X, vec.Y, vec.Z );
 
        // core::vector3df yaxis(0.0f, 1.0f, 0.0f); // yaxis in world space
        m_matrix.rotateVect( vec ); // Convert vec to current transform
        vec.normalize();
 
//      TRACE( "Output norm vector= %f, %f, %f\n", vec.X, vec.Y, vec.Z );
 
        // Calculate role angle.
        // To fix rotation to circumference and speed, angle = (( total-distance / ball-circumference ) * ( total-distance-travelled / total-distance ) ) * 360.f;  Note: Ball-circumference = PI * 2R;
        float fAngle;
        if ( m_rotAngle.X < 0.f )
        {
                float fMul = m_rotAngle.Y;      // Match rotation to circumference/distance moved in this step
                if ( fMul == 0.f )
                        fMul = 1.f;
                fAngle = ( fDistanceTravelled / fDistanceToTravel ) * ( fDistanceToTravel / m_fCirum ) * fMul * 360.f;
        }
        else
        {
                fAngle = ( fDistanceTravelled / fDistanceToTravel ) * m_rotAngle.X * 360.f;     // Step rotation based distance travelled and user constant
        }
 
        if ( fabs( fAngle ) >= 360.f )
                fAngle = fmodf( fAngle, 360.f );
 
        m_q.fromAngleAxis( ( fAngle + pObject->m_rect.max3d.X ) * core::DEGTORAD, vec );        // Rotate ball on vec axis by fAngle + offset
 
        m_af3Spin = m_q.getMatrix().getRotationDegrees();
 
        pObject->GetSceneNode()->setRotation( m_af3Spin );
 
This code works but I'm bothered that something is interfering with the calls getTransformedBoundingBox and getAbsoluteTransformation if made during each animation call. What could cause this, as the OnAnimate call from within DrawAll is at a point where no other code is interfering. Any ideas as to what I could check to see what's affecting the transforms?

Also, given this code, how best to add offset rotations to the balls so that when they roll into their end stops, they show any mapped image face forwards?
smso
Posts: 246
Joined: Fri Jun 04, 2010 3:28 pm
Location: Hong Kong

Re: Rotating a rotated node weird axis result...

Post by smso »

Is it possible to provide a complete function or, even better, a short compilable example?

Regards,
smso
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Rotating a rotated node weird axis result...

Post by robmar »

You can drop the code straight into the CSceneAnimatorFlyStraight class, the only thing I forgot to comment was that m_rotAngle.X is just a control variable to select auto roll calculation, or fixed roll with speed variable.

m_vec is the direction of travel, and just replace the GetSceneNode with the node used in the animator.

Travel distance is distance travelled at point of call into Animate, and total distance to travel, all available in the FlyStraight animator.

This changes the flystraight animator into, if you use a switch variable, a flystraight, and flystraight plus roll.
Post Reply