[SOLVED] Turn arround an Axis?

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.
USE.IRR
Posts: 32
Joined: Sat Jul 28, 2007 12:24 pm

Post by USE.IRR »

with this code every thing will go OK.

Code: Select all


...
   f32 rotationSpeed2 = 1.1f;
   f32 rotation2 = 0.0f;
...

...
rotation2 += rotationSpeed2;
...

...
core::matrix4 matrix2;
matrix2.setRotationDegrees(core::vector3df (0 ,rotation2 , 0) );

planet->setRotation(matrix2.getRotationDegrees());
...

:lol:
Image
Image
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

Well, probably not. I think your code would not work if you rotate your planet axis. You need to use something like my turn function:

Code: Select all

#include <irrlicht.h>
using namespace irr;

int main()
{
    IrrlichtDevice *device = createDevice( video::EDT_OPENGL, 
        core::dimension2d<s32>(640, 480), 32, false, false, false, 0);
    
    video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();
	
	smgr->addCameraSceneNode(0, core::vector3df(0,0,-30), core::vector3df(0,0,0));
	
	scene::ISceneNode *planet = smgr->addCubeSceneNode();
	planet->setMaterialFlag(video::EMF_LIGHTING ,false);
	
	f32 pRotationSpeed = 0.1f;
	f32 pRrotation = 0.0f;
	core::vector3df planetAxisRotation(30,-3,45);
	planet->setRotation(planetAxisRotation);
	
	while(device->run())
    {
        driver->beginScene(true, true, video::SColor(255,100,101,140));
        
        pRrotation += pRotationSpeed;
        
        core::matrix4 matrix1;
        matrix1.setRotationDegrees(planetAxisRotation);
        
        core::matrix4 matrix2;
        matrix2.setRotationDegrees( core::vector3df(0, pRrotation, 0) );
        
        matrix1 *= matrix2;
        
        planet->setRotation( matrix1.getRotationDegrees() );

		smgr->drawAll();

		driver->endScene();
    }
    device->drop();
    
    return 0;
}
USE.IRR
Posts: 32
Joined: Sat Jul 28, 2007 12:24 pm

Post by USE.IRR »

arras wrote:Well, probably not. I think your code would not work if you rotate your planet axis.
I'm sure, my code is working fine and my planet do the two rotations : the relative rotation (arround it self) and the global rotation (arround the star).

Your code animates the cube by the result of the two animations which is one rotation around the resulting axis.
Image
Image
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

OK, then what about this:

Code: Select all

#include <irrlicht.h>
using namespace irr;

int main()
{
    IrrlichtDevice *device = createDevice( video::EDT_OPENGL, 
        core::dimension2d<s32>(640, 480), 32, false, false, false, 0);
    
    video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();
	
	smgr->addCameraSceneNode(0, core::vector3df(0,0,-30), core::vector3df(0,0,0));
	
	scene::ISceneNode *star = smgr->addSphereSceneNode();
	star->setMaterialFlag(video::EMF_LIGHTING ,false);
	star->setRotation(core::vector3df(-0,0,10));
	
	scene::ISceneNode *planet = smgr->addCubeSceneNode(3.0f);
	planet->setMaterialFlag(video::EMF_LIGHTING ,false);
	
	f32 radius = 20.0f;
	f32 rotationSpeed = 0.1f;
	f32 rotation = 0.0f;
	
	f32 pRotationSpeed = 0.1f;
	f32 pRrotation = 0.0f;
	core::vector3df planetAxisRotation(30,-3,45);
	planet->setRotation(planetAxisRotation);
	
	while(device->run())
    {
        driver->beginScene(true, true, video::SColor(255,100,101,140));
        
        // rotate around star axis
        
        rotation += rotationSpeed;
        
        core::vector3df pos = core::vector3df(0,0,radius);
        
        core::matrix4 matrix;
        matrix.setRotationDegrees(core::vector3df (0 ,rotation , 0) );
        matrix.rotateVect(pos);
        
        matrix = star->getAbsoluteTransformation();
        matrix.rotateVect(pos);
        
        planet->setPosition(pos + star->getPosition());
        
        // rotate around planet axis
        
        pRrotation += pRotationSpeed;
        
        core::matrix4 matrix1;
        matrix1.setRotationDegrees(planetAxisRotation);
        
        core::matrix4 matrix2;
        matrix2.setRotationDegrees( core::vector3df(0, pRrotation, 0) );
        
        matrix1 *= matrix2;
        
        planet->setRotation( matrix1.getRotationDegrees() );

		smgr->drawAll();

		driver->endScene();
    }
    device->drop();
    
    return 0;
}
USE.IRR
Posts: 32
Joined: Sat Jul 28, 2007 12:24 pm

Post by USE.IRR »

Code: Select all

        
core::matrix4 matrix1;
matrix1.setRotationDegrees(planetAxisRotation);
        
core::matrix4 matrix2;
matrix2.setRotationDegrees( core::vector3df(0, pRrotation, 0) );
        
matrix1 *= matrix2;
        
planet->setRotation( matrix1.getRotationDegrees() );


The code is working.
Why using two rotation (matrix1 and matrix2) to make one rotation?
Image
Image
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

If you do:

Code: Select all

matrix2.setRotationDegrees(core::vector3df (0 ,rotation2 ,0) );
planet->setRotation(matrix2.getRotationDegrees());
It's the same as if you did:

Code: Select all

planet->setRotation(core::vector3df (0 ,rotation2 ,0)
since you did nothing with your matrix ...rotation you feed in to matrix is the same you retreive.

Waht you want however is to combine two rotations ...rotation of planet axis and rotation around that axis which would animate planet. Therefore:

Code: Select all

matrix1.setRotationDegrees(planetAxisRotation);
matrix2.setRotationDegrees( core::vector3df(0, pRrotation, 0) );    
matrix1 *= matrix2; 
USE.IRR
Posts: 32
Joined: Sat Jul 28, 2007 12:24 pm

Post by USE.IRR »

Yes I see :roll:

But

Code: Select all

matrix2 *=matrix1;
give one rotation not two.
Image
Image
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

yes, but thats what you want ...global rotation of your plane made of two combined rotations. Irrlicht use Euler angles to represent rotation which basicly mean that if you say:

Code: Select all

node->setRotation(vector3df(10,20,30))
node is firsth rotated 10 degrees around X axis ...not only node but its axes along with it. Then 20 degree rotation is caried around Y axis ...which was already rotated by pervious rotation and 30 degree rotation is caried last around Z axis ...which was of course already rotated twice by pervious rotations. (I am not entirely sure obout order of rotations irrlicht use, can be Z->Y->X)

What you want to acomplish is firsth to rotate your planet (10,20,30) ...which let say is planet axis rotation and then rotate it by say 40 degrees around its Y axis (your animation) which would be rotation (0,40,0).

Firsth thing to come in mind is that you simply add 20 + 40 on place of Y rotation: node->setRotation(vector3df(10, 20+40=60, 30))

But that is entirely wrong. If you read what I wrote about Euler angles you see that to rotate (10,60,30) is not the same as if you would firsth rotate (10,20,30) and then add (0,40,0) rotation. This can be done by creating two rotation matrices, then multiply them. You can acomplish the same using quaternions.
USE.IRR
Posts: 32
Joined: Sat Jul 28, 2007 12:24 pm

Post by USE.IRR »

thanks I understand you.

:)
Image
Image
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

hmm, looks prety interesting... ;)
I'm wondering if/how this can be used to correct the animateNode(...) function of the CSceneNodeAnimatorFlyCircle class ??? :shock:
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

Well I think problem is in this code:

Code: Select all

void CSceneNodeAnimatorFlyCircle::animateNode(ISceneNode* node, u32 timeMs)
{
	if ( 0 == node )
		return;

	const f32 t = (timeMs-StartTime) * Speed;

	core::vector3df circle(Radius * sinf(t), 0, Radius * cosf(t));
	circle = circle.crossProduct ( Direction );

	node->setPosition(Center + circle);
}
If you know what cross product of two vectors is, it must be clear for you that node afected by this code would cicle around only if Direction = vector3df(0,1,0) or vector3df(0,-1,0) ...in all other cases result will not be cicle.

Its because vector circle is defined always in x-z plane: (Radius * sinf(t), 0, Radius * cosf(t))

I dont understand why Direction was made to be one of the parameters of createFlyCircleAnimator() function since if set to anything diferent than default walue it brake animation.
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

I was not testing this code but if I understand what cicle animator should do something like this may work:

Code: Select all

void CSceneNodeAnimatorFlyCircle::animateNode(ISceneNode* node, u32 timeMs)
{
   if ( 0 == node )
      return;

   const f32 t = (timeMs-StartTime) * Speed;

   core::vector3df circle(Radius * sinf(t), 0, Radius * cosf(t));
   
   core::matrix4 m;
   m.setRotationDegrees(Direction);
   m.rotateVect(circle);

   node->setPosition(Center + circle);
}
[EDIT] well I tested it and it seems to work with the exception that Direction is rather Rotation. Means Direction of (0,1,0) is Rotation of (0,0,0) and Direction of (1,0,0) is Rotation of (0,0,90). Means rotation of Y axis. As there is no easy one line function which get rotation from direction vector, there is no easy way to get original fly cicle function work as it was intended.

For all those good in high school math:
Is it possible to get rotation out of direction vector using matrices? ...would it be possible to create such function for matrix4 class?
Post Reply