3D Rotational Movement?

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.
Post Reply
elkar
Posts: 8
Joined: Tue Jan 13, 2009 10:02 pm

3D Rotational Movement?

Post by elkar »

I was wondering how it would be possible to do 3D Rotational Movement with Irrlicht. I found this link: http://www.allegro.cc/forums/thread/594212/712639. In the second post it talks about using the sin and cos functions, but it's for 2D rotational movement. How would I translate this to 3D coordinates? I've been fiddling around with it for a while, but just can't get my node to move the direction it's facing. All thanks is appreciated, and sorry if the answer is an easy one.
nathanf534
Posts: 199
Joined: Tue Dec 09, 2008 2:55 am

Post by nathanf534 »

If you want to be able to move the node, a certain direction, such as forward, you can use a function i made:

Code: Select all

vector3df move(ISceneNode* node,int direction,float speed,bool move){
     vector3df newPos;
     if(direction==FORWARD){
         vector3df facing( sin( ( node->getRotation().Y + 0.0f ) * PI/180.0f ),  -tan( (node->getRotation().X + 0.0f ) * PI/180.0f ), cos( ( node->getRotation().Y + 0.0f ) * PI/180.0f ) ); 
         facing.normalize(); 
         newPos = (facing*speed) + node->getPosition(); 
     }  
     if(direction==BACK){
          vector3df facing( sin( ( node->getRotation().Y + 180.0f ) * PI/180.0f ), 0, cos( (node->getRotation().Y + 180.0f ) * PI/180.0f ) ); 
          facing.normalize(); 
          newPos = (facing*speed) + node->getPosition(); 
     }
     if(direction==RIGHT){
          vector3df facing( sin( (node->getRotation().Y + 90.0f ) * PI/180.0f ),0, cos( (node->getRotation().Y + 90.0f ) * PI/180.0f ) ); 
          facing.normalize(); 
          newPos = (facing*speed) + node->getPosition(); 
     }
     if(direction==LEFT){
         vector3df facing( sin( ( node->getRotation().Y - 90.0f ) * PI/180.0f ), 0, cos( (node->getRotation().Y - 90.0f ) * PI/180.0f ) ); 
         facing.normalize(); 
         newPos = (facing*speed) + node->getPosition(); 
     }
     if(move) node->setPosition(newPos);
     return newPos;
}
you will need to define:

Code: Select all

const int BACK=1;
const int LEFT=2;
const int FORWARD=3;
const int RIGHT=4;
i believe this works, but i havn't used the function in a while.
The function returns the position of the node, after it moved, or if you input "move" as true, it will move it for you.
edit: it only moves it along the x and z axis, unless you are moving forward, then it moves it on all 3 axis.
while(signatureEmpty){cout<<wittyComment();}
elkar
Posts: 8
Joined: Tue Jan 13, 2009 10:02 pm

Thanks

Post by elkar »

Thanks, I'll see if I can get it to work. Be right back :D

Ok, after compiling it, it kind of works. My camera is looking from behind the character's head, and this looks like it's meant for an overhead view. Also, simply turning moves the character forward. I got to go to bed, so I'll leave my code so you can see if anything is wrong.

Code: Select all

#include <irrlicht.h>
#include <math.h>
#include <stdio.h>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

const int BACK=1;
const int LEFT=2;
const int FORWARD=3;
const int RIGHT=4;

class MyEventReceiver : public IEventReceiver
{
public:
	// This is the one method that we have to implement
	virtual bool OnEvent(const SEvent& event)
	{
		// Remember whether each key is down or up
		if (event.EventType == EET_KEY_INPUT_EVENT)
			KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;

		return false;
	}

	// This is used to check whether a key is being held down
	virtual bool IsKeyDown(EKEY_CODE keyCode) const
	{
		return KeyIsDown[keyCode];
	}

	MyEventReceiver()
	{
		for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
			KeyIsDown[i] = false;
	}

private:
	// We use this array to store the current state of each key
	bool KeyIsDown[KEY_KEY_CODES_COUNT];
};

vector3df move(ISceneNode* node,int direction,float speed,bool move){
     vector3df newPos;
     if(direction==FORWARD){
         vector3df facing( sin( ( node->getRotation().Y + 0.0f ) * PI/180.0f ),  -tan( (node->getRotation().X + 0.0f ) * PI/180.0f ), cos( ( node->getRotation().Y + 0.0f ) * PI/180.0f ) );
         facing.normalize();
         newPos = (facing*speed) + node->getPosition();
     }
     if(direction==BACK){
          vector3df facing( sin( ( node->getRotation().Y + 180.0f ) * PI/180.0f ), 0, cos( (node->getRotation().Y + 180.0f ) * PI/180.0f ) );
          facing.normalize();
          newPos = (facing*speed) + node->getPosition();
     }
     if(direction==RIGHT){
          vector3df facing( sin( (node->getRotation().Y + 90.0f ) * PI/180.0f ),0, cos( (node->getRotation().Y + 90.0f ) * PI/180.0f ) );
          facing.normalize();
          newPos = (facing*speed) + node->getPosition();
     }
     if(direction==LEFT){
         vector3df facing( sin( ( node->getRotation().Y - 90.0f ) * PI/180.0f ), 0, cos( (node->getRotation().Y - 90.0f ) * PI/180.0f ) );
         facing.normalize();
         newPos = (facing*speed) + node->getPosition();
     }
     if(move) node->setPosition(newPos);
     return newPos;
}

int main(int argc, char** argv)
{
    MyEventReceiver receiver;

    //Create the main device for the game
    IrrlichtDevice *device =
        createDevice(EDT_OPENGL, dimension2d<s32>(640, 480), 16,
            false, false, false, &receiver);

    //Set the window caption
    device->setWindowCaption(L"Psychic Demo");

    //Create all of the environments for the game
    IVideoDriver* driver = device->getVideoDriver();
    ISceneManager* smgr = device->getSceneManager();
    IGUIEnvironment* guienv = device->getGUIEnvironment();

    //Create the head
    ISceneNode* head = smgr->addSphereSceneNode();

    //Create the body
    ISceneNode* body = smgr->addSphereSceneNode();

    //Create one hand
    ISceneNode* hand1 = smgr->addSphereSceneNode();

    //Create the other hand
    ISceneNode* hand2 = smgr->addSphereSceneNode();

    //Create one foot
    ISceneNode* foot1 = smgr->addSphereSceneNode();

    //Create the other foot
    ISceneNode* foot2 = smgr->addSphereSceneNode();

    //Test cube
    ISceneNode* cube = smgr->addCubeSceneNode();
    cube->setPosition(vector3df(30, 0, 0));

    //Set stuff for head
    if (head)
    {
        head->setMaterialFlag(EMF_LIGHTING, true);
        head->setMaterialTexture(0, driver->getTexture("./textures/dummy.bmp"));
        head->setScale(vector3df(0.8, 0.8, 0.8));
        head->setPosition(vector3df(0,0,0));
    }

    //Set stuff for the body
    if (body)
    {
        body->setParent(head);
        body->setMaterialFlag(EMF_LIGHTING, true);
        body->setMaterialTexture(0, driver->getTexture("./textures/dummy.bmp"));
        body->setScale(vector3df(1, 1.8, 1));
        body->setPosition(head->getPosition() + vector3df(0, -15, 0));
    }

    //Stuff for hand1
    if (hand1)
    {
        hand1->setParent(head);
        hand1->setMaterialFlag(EMF_LIGHTING, true);
        hand1->setMaterialTexture(0, driver->getTexture("./textures/dummy.bmp"));
        hand1->setScale(vector3df(0.5, 0.5, 0.5));
        hand1->setPosition(head->getPosition() + vector3df(0, -16, -8));
    }

    //Stuff for hand2
    if (hand2)
    {
        hand2->setParent(head);
        hand2->setMaterialFlag(EMF_LIGHTING, true);
        hand2->setMaterialTexture(0, driver->getTexture("./textures/dummy.bmp"));
        hand2->setScale(vector3df(0.5, 0.5, 0.5));
        hand2->setPosition(head->getPosition() + vector3df(0, -16, 8));
    }

    //Stuff for foot1
    if (foot1)
    {
        foot1->setParent(head);
        foot1->setMaterialFlag(EMF_LIGHTING, true);
        foot1->setMaterialTexture(0, driver->getTexture("./textures/dummy.bmp"));
        foot1->setScale(vector3df(0.5, 0.5, 0.5));
        foot1->setPosition(head->getPosition() + vector3df(0, -27, 6));
    }

    //Stuff for foot2
    if (foot2)
    {
        foot2->setParent(head);
        foot2->setMaterialFlag(EMF_LIGHTING, true);
        foot2->setMaterialTexture(0, driver->getTexture("./textures/dummy.bmp"));
        foot2->setScale(vector3df(0.5, 0.5, 0.5));
        foot2->setPosition(head->getPosition() + vector3df(0, -27, -6));
    }

    //Create the camera
    ICameraSceneNode* camera = smgr->addCameraSceneNode(0, vector3df(-50, 0, 0), vector3df(head->getPosition()));
    camera->setParent(head);
    camera->setTarget(head->getPosition());

    //Hide or show the mouse cursor
    device->getCursorControl()->setVisible(true);

    while(device->run())
    {
        //Detect mouse key presses
        if (receiver.IsKeyDown(KEY_KEY_W))
        {
            head->setPosition(move(head, FORWARD ,0.5, true));
        }
        if (receiver.IsKeyDown(KEY_KEY_S))
        {
            head->setPosition(move(head, BACK, 0.5, true));
        }
        if (receiver.IsKeyDown(KEY_KEY_A))
        {
            head->setRotation(move(head, LEFT, 0.5, true));
        }
        if (receiver.IsKeyDown(KEY_KEY_D))
        {
            head->setRotation(move(head, RIGHT, 0.5, true));
        }

        camera->setTarget(head->getPosition());

        driver->beginScene(true, true, SColor(0,200,200,200));

        smgr->drawAll();
        guienv->drawAll();

        driver->endScene();
    }

    device->drop();

    return 0;
}
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

Irrlicht 1.5 has vector3d::rotationToDirection() which will turn 3 Euler angles (i.e. an Irrlicht rotation) into a direction vector.

You can specify which way is "forwards". We've assumed that your models are facing towards +Z (i.e. 0,0,1) but you can specify any forward orientation that you like.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
robertgarand
Posts: 69
Joined: Fri Feb 22, 2008 6:47 pm
Location: montreal
Contact:

Found only one way to do complete 3d rotation

Post by robertgarand »

Hi,
I worked a LOT on 3d rotation independant on all axis, the only way is to use matrix with small steps rotations, you cannot call a final rotation because of gimbal lock.
look at this sample code from this thread:

http://irrlicht.sourceforge.net/phpBB2 ... p?t=31866

Code: Select all


//Update of events action on rotation of vaissel
 irr::core::vector3df rolls(0.f,0.f,0.f);
 ...
switch (key)
{
...
///acitvate attitude controls
    case KEY_LEFT: {log_str.append(L"thrustinL",15);
    rolls.Z+=roll_speed;
    actual_rot.Z+=roll_speed;
    rotate(rolls,vaisseau);
    make_thrust(ps[1]);break;}
...other keys

//to make actual rotation on vaissel node
void vaissel::rotate(irr::core::vector3df &rotation, scene::ISceneNode * node)
{    irr::core::matrix4 m;
    m.setRotationDegrees(node->getRotation());
    irr::core::matrix4 n;
    n.setRotationDegrees(rotation);
    m *= n;
    node->setRotation( m.getRotationDegrees() );
    node->updateAbsolutePosition();
} 
If you need any further infos, tell me.
Robert
If it can't be writen, it can't exist
elkar
Posts: 8
Joined: Tue Jan 13, 2009 10:02 pm

OK

Post by elkar »

How could I use the rotationToDirection function? It seems pretty basic and promising. Thanks for all the help so far!

EDIT

Muahahaha! I got it to work! My code is as follows:

Code: Select all

#include <irrlicht.h>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

class MyEventReceiver : public IEventReceiver
{
public:
	// This is the one method that we have to implement
	virtual bool OnEvent(const SEvent& event)
	{
		// Remember whether each key is down or up
		if (event.EventType == EET_KEY_INPUT_EVENT)
			KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;

		return false;
	}

	// This is used to check whether a key is being held down
	virtual bool IsKeyDown(EKEY_CODE keyCode) const
	{
		return KeyIsDown[keyCode];
	}

	MyEventReceiver()
	{
		for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
			KeyIsDown[i] = false;
	}

private:
	// We use this array to store the current state of each key
	bool KeyIsDown[KEY_KEY_CODES_COUNT];
};

int main(int argc, char** argv)
{
    MyEventReceiver receiver;

    //Create the main device for the game
    IrrlichtDevice *device =
        createDevice(EDT_OPENGL, dimension2d<s32>(640, 480), 16,
            false, false, false, &receiver);

    //Set the window caption
    device->setWindowCaption(L"Psychic Demo");

    //Create all of the environments for the game
    IVideoDriver* driver = device->getVideoDriver();
    ISceneManager* smgr = device->getSceneManager();
    IGUIEnvironment* guienv = device->getGUIEnvironment();

    //Create the head
    ISceneNode* head = smgr->addSphereSceneNode();

    //Create the body
    ISceneNode* body = smgr->addSphereSceneNode();

    //Create one hand
    ISceneNode* hand1 = smgr->addSphereSceneNode();

    //Create the other hand
    ISceneNode* hand2 = smgr->addSphereSceneNode();

    //Create one foot
    ISceneNode* foot1 = smgr->addSphereSceneNode();

    //Create the other foot
    ISceneNode* foot2 = smgr->addSphereSceneNode();

    //Test cube
    ISceneNode* cube = smgr->addCubeSceneNode();
    cube->setPosition(vector3df(30, 0, 0));

    //Set stuff for head
    if (head)
    {
        head->setMaterialFlag(EMF_LIGHTING, true);
        head->setMaterialTexture(0, driver->getTexture("./textures/dummy.bmp"));
        head->setScale(vector3df(0.8, 0.8, 0.8));
        head->setPosition(vector3df(0,0,0));
    }

    //Set stuff for the body
    if (body)
    {
        body->setParent(head);
        body->setMaterialFlag(EMF_LIGHTING, true);
        body->setMaterialTexture(0, driver->getTexture("./textures/dummy.bmp"));
        body->setScale(vector3df(1, 1.8, 1));
        body->setPosition(head->getPosition() + vector3df(0, -15, 0));
    }

    //Stuff for hand1
    if (hand1)
    {
        hand1->setParent(head);
        hand1->setMaterialFlag(EMF_LIGHTING, true);
        hand1->setMaterialTexture(0, driver->getTexture("./textures/dummy.bmp"));
        hand1->setScale(vector3df(0.5, 0.5, 0.5));
        hand1->setPosition(head->getPosition() + vector3df(0, -16, -8));
    }

    //Stuff for hand2
    if (hand2)
    {
        hand2->setParent(head);
        hand2->setMaterialFlag(EMF_LIGHTING, true);
        hand2->setMaterialTexture(0, driver->getTexture("./textures/dummy.bmp"));
        hand2->setScale(vector3df(0.5, 0.5, 0.5));
        hand2->setPosition(head->getPosition() + vector3df(0, -16, 8));
    }

    //Stuff for foot1
    if (foot1)
    {
        foot1->setParent(head);
        foot1->setMaterialFlag(EMF_LIGHTING, true);
        foot1->setMaterialTexture(0, driver->getTexture("./textures/dummy.bmp"));
        foot1->setScale(vector3df(0.5, 0.5, 0.5));
        foot1->setPosition(head->getPosition() + vector3df(0, -27, 6));
    }

    //Stuff for foot2
    if (foot2)
    {
        foot2->setParent(head);
        foot2->setMaterialFlag(EMF_LIGHTING, true);
        foot2->setMaterialTexture(0, driver->getTexture("./textures/dummy.bmp"));
        foot2->setScale(vector3df(0.5, 0.5, 0.5));
        foot2->setPosition(head->getPosition() + vector3df(0, -27, -6));
    }

    //Create the camera
    ICameraSceneNode* camera = smgr->addCameraSceneNode(0, vector3df(0, -50, 0), vector3df(head->getPosition()));
    camera->setParent(head);
    camera->setTarget(head->getPosition());

    //Hide or show the mouse cursor
    device->getCursorControl()->setVisible(true);

    while(device->run())
    {
        vector3df headrotation = head->getRotation();
        float vx = cos((headrotation.Y + 90) / 180 * 3.14159265) * 1;
        float vy = sin((headrotation.Y + 90) / 180 * 3.14159265) * 1;

        //Detect mouse key presses
        if (receiver.IsKeyDown(KEY_KEY_W))
        {
            head->setPosition(head->getPosition() + vector3df(vy, 0, vx));
        }
        if (receiver.IsKeyDown(KEY_KEY_S))
        {
            head->setPosition(head->getPosition() + vector3df(vy * -1, 0, vx * -1));
        }
        if (receiver.IsKeyDown(KEY_KEY_A))
        {
            head->setRotation(head->getRotation() + vector3df(0, 1, 0));
        }
        if (receiver.IsKeyDown(KEY_KEY_D))
        {
            head->setRotation(head->getRotation() + vector3df(0, -1, 0));
        }

        camera->setTarget(head->getPosition());

        driver->beginScene(true, true, SColor(0,200,200,200));

        smgr->drawAll();
        guienv->drawAll();

        driver->endScene();
    }

    device->drop();

    return 0;
}
Post Reply