Page 2 of 2

Posted: Wed Aug 29, 2007 9:32 am
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:

Posted: Wed Aug 29, 2007 11:41 am
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;
}

Posted: Wed Aug 29, 2007 12:04 pm
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.

Posted: Wed Aug 29, 2007 1:28 pm
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;
}

Posted: Wed Aug 29, 2007 2:13 pm
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?

Posted: Wed Aug 29, 2007 2:35 pm
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; 

Posted: Wed Aug 29, 2007 2:42 pm
by USE.IRR
Yes I see :roll:

But

Code: Select all

matrix2 *=matrix1;
give one rotation not two.

Posted: Wed Aug 29, 2007 3:11 pm
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.

Posted: Wed Aug 29, 2007 3:33 pm
by USE.IRR
thanks I understand you.

:)

Posted: Wed Aug 29, 2007 4:01 pm
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:

Posted: Wed Aug 29, 2007 5:17 pm
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.

Posted: Wed Aug 29, 2007 5:25 pm
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?