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.

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

Postby iLLuSia » Sat Jun 02, 2012 12:04 am

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:

cpp 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.
iLLuSia
 
Posts: 5
Joined: Fri Jun 01, 2012 11:40 pm

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

Postby robmar » Sun Jun 03, 2012 12:21 pm

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: 565
Joined: Sun Aug 14, 2011 11:30 pm

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

Postby robmar » Sat Jun 23, 2012 4:35 pm

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?

cpp 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: 565
Joined: Sun Aug 14, 2011 11:30 pm

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

Postby robmar » Sun Jun 24, 2012 2:07 am

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.

cpp 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: 565
Joined: Sun Aug 14, 2011 11:30 pm

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

Postby robmar » Mon Jun 25, 2012 9:03 am

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.
robmar
 
Posts: 565
Joined: Sun Aug 14, 2011 11:30 pm

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

Postby hybrid » Mon Jun 25, 2012 9:09 am

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.
hybrid
Admin
 
Posts: 13946
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany

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

Postby robmar » Mon Jun 25, 2012 9:52 am

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: 565
Joined: Sun Aug 14, 2011 11:30 pm

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

Postby robmar » Mon Jun 25, 2012 9:53 am

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

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

Postby robmar » Mon Jun 25, 2012 10:38 am

Why can I not post here???
robmar
 
Posts: 565
Joined: Sun Aug 14, 2011 11:30 pm

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

Postby hybrid » Mon Jun 25, 2012 11:05 am

Well, you posted three times now...
hybrid
Admin
 
Posts: 13946
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany

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

Postby robmar » Mon Jun 25, 2012 11:27 am

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

Constructor of animation:

cpp 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:

cpp 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?
robmar
 
Posts: 565
Joined: Sun Aug 14, 2011 11:30 pm

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

Postby smso » Tue Jun 26, 2012 9:27 am

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

Regards,
smso
smso
 
Posts: 218
Joined: Fri Jun 04, 2010 3:28 pm
Location: Hong Kong

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

Postby robmar » Tue Jun 26, 2012 9:35 am

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.
robmar
 
Posts: 565
Joined: Sun Aug 14, 2011 11:30 pm

Previous

Return to Beginners Help

Who is online

Users browsing this forum: Google [Bot], Masterhawk, zerochen and 1 guest