Matrix rotation

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
speedy15453
Posts: 22
Joined: Tue Nov 09, 2010 7:03 pm
Location: ohiio

Matrix rotation

Post by speedy15453 »

Hello,

I was hoping someone could help.

I have a node positioned at (0,0,0) and would like to rotate it around x,y,z axis' and also around an axis 45 degree between x,y (diagonal)

I've been trying to translate code for my IDE but I need more input to do the translation. I have been using setRotation but it sucks.

Could someone help by posting the simplest code for a node to do a rotation around a point 45 degrees between x,y (with comments ) vs. a rotation around the x axis (using matrix4)
Only after disaster can we be resurrected.
speedy15453
Posts: 22
Joined: Tue Nov 09, 2010 7:03 pm
Location: ohiio

Picture

Post by speedy15453 »

Image
Only after disaster can we be resurrected.
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

I'm confused by what you're trying to say and show. If you're looking for a different way of representing rotations, take a look at quaternions.
speedy15453
Posts: 22
Joined: Tue Nov 09, 2010 7:03 pm
Location: ohiio

I have been looking at quaternions

Post by speedy15453 »

I am using realbasic and an irrlicht plugin called Franklin3d.
I have not done any coding for about 20 years.
I understand quaternions a little.
I am having trouble converting code or suggestions, that others have posted because:

1. It's has too much going on, ie. several nodes being moved and rotated.
or nodes being the camera and more.
and so many other things.

2. I have to figure out what's going on and then rewrite the code so it
works with my version of irrlicht, in my IDE RealBasic.
(very minor differences = big bugs)

3. I was hoping that someone could give me an example of code to rotate
one node(no distance from center) using matrix4 and /or quaternions.
Just one node, doing one function. So I can figure out where my
syntax error is, or why the method does not exist, or why I need to
use the value returned. Small differences but it is very difficult to debug
with so much going on. I have tried so many variations of sample code
I'm just trying to dumb it down.

4. setRotation is not an option for many reasons.

5. Any help would be appreciated.

The main rotation I need to learn is around the "axis" between x,y.

Did I just make this more confusing?
Last edited by speedy15453 on Tue Nov 30, 2010 9:09 pm, edited 1 time in total.
Only after disaster can we be resurrected.
Mikhail9
Posts: 54
Joined: Mon Jun 29, 2009 8:41 am

Post by Mikhail9 »

The hardest thing here is trying to think about and visualize it... at least for me. I end up just having to trust the math, which works fine.

The direct way to do it is to use the matrix4 class. That way you can rotate an arbitrary amount about any arbitrary axis without having to worry about things like gimbal lock.

All of the math is here: http://inside.mines.edu/~gmurray/Arbitr ... ation.html

You really only need the last section of that document, but they walk you through the entire thing. Some of their variables may be zero in your case, which means that horrific matrix will reduce to something manageable.

Once you have your magic matrix, you can use a mesh manipulator and pass the matrix to its transform method.
speedy15453
Posts: 22
Joined: Tue Nov 09, 2010 7:03 pm
Location: ohiio

I love the link.

Post by speedy15453 »

Thanks Mikhail9,

The link you provided is very helpful.

I am still have problems just getting started with the code.
I'm going to mess around for the next couple of days.
I think it may all be just syntax in my IDE.

I'll post some code if I have any success.


Thanks!
Only after disaster can we be resurrected.
blAaarg
Posts: 94
Joined: Tue Mar 02, 2010 9:11 pm
Location: SoCal

Post by blAaarg »

I had this sitting around for a while. I cleaned it up some, added better comments and it does show how to use quaternions in a simple context. However, it does not work so well for quaternion axes which match any of the global axes. I can think of a quick and dirty solution to avoid allowing the quaternion's axis from matching the global ones but that seems hacky.

My question is: Is this in the nature of quaternions, is it a bug, or am I using this wrong? (Okay, maybe that's three questions). Any help would be appreciated. :)



Code: Select all


#include <iostream>
#include <irrlicht.h>

using namespace irr;

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

#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#pragma comment(linker, "/subsystem:console /ENTRY:mainCRTStartup")/*windows*/
#endif

int main()
{
	// ************
	// quick set up
	IrrlichtDevice *device = createDevice( video::EDT_OPENGL, dimension2d<u32>(640, 480), 16, false, false, false, 0);

	if (!device)
		return 1;

	device->setWindowCaption(L"Quaternion Rotation Test");

	IVideoDriver* driver = device->getVideoDriver();
	ISceneManager* smgr = device->getSceneManager();
	IGUIEnvironment* guienv = device->getGUIEnvironment();

	guienv->addStaticText(L"The yellow line is the axis of rotation.", rect<s32>(10,10,260,22), true);



	// ***************************************
	// Let's set up the meshes and scene node, et al.

	// create a set of axes that show rotation
	IAnimatedMesh* xArrow = smgr->addArrowMesh( "xArrow", SColor(255,60,40,40), SColor(255,255,0,0) );
	xArrow->setMaterialFlag(EMF_LIGHTING, false);
	IAnimatedMesh* yArrow = smgr->addArrowMesh( "yArrow", SColor(255,40,60,40), SColor(255,0,255,0) );
	yArrow->setMaterialFlag(EMF_LIGHTING, false);
	IAnimatedMesh* zArrow = smgr->addArrowMesh( "zArrow", SColor(255,40,40,100), SColor(255,0,0,255) );
	zArrow->setMaterialFlag(EMF_LIGHTING, false);
	ISceneNode* gizmo = smgr->addEmptySceneNode();	

	if (gizmo)
	{
		IMeshSceneNode* right   = smgr->addMeshSceneNode(xArrow, gizmo, -1, vector3df(0), vector3df(0,0,-90), vector3df(10,25,10));
		IMeshSceneNode* up      = smgr->addMeshSceneNode(yArrow, gizmo, -1, vector3df(0), vector3df(0,0,0), vector3df(10,25,10));
		IMeshSceneNode* forward = smgr->addMeshSceneNode(zArrow, gizmo, -1, vector3df(0), vector3df(90,0,0), vector3df(10,25,10));
		gizmo->setMaterialFlag(EMF_LIGHTING, false);
	}
	else
		return 0;


	// this is just used for output to the console
	vector3df nodeRot;

	//ICameraSceneNode* cam = smgr->addCameraSceneNodeMaya();
	ICameraSceneNode* cam = smgr->addCameraSceneNode(0, vector3df(0,0,-50), vector3df(0,0,30));
	if (cam)
		cam->setTarget( gizmo->getAbsolutePosition() );

	// this will be used to create a yellow line that shows the quaternion's axis of rotation
	SMaterial someMaterial;
	someMaterial.Lighting = false;
	someMaterial.DiffuseColor = SColor(255,255,255,0);
	someMaterial.Thickness = 2;


	// ***************************************
	// Let's set up the quaternions, matrices, et al.

	// Here's the axis of rotation. Quaternion's need to have them normalized or strange stuff happens.
	vector3df axis(1,1,0);	// or whatever. Note: vector3df(0,1,0) gives NaNs, other axis aligned vectors only give half rotations :-/
	axis.normalize();


	// Multiple rotations of different amounts and/or around different axes can be set into different 
	// quaternions which can then be multiplied into each other to accumulate arbitrary (i.e. local) rotations.
	// The order in which they are multiplied matters strongly!     ( (quatM * quatN) != (quatN * quatM) )
	// In this example, we're only using one quaternion/rotation, though.

	// This quat represents a single (set) rotation of some degrees (converted to radians, as necessary).
	quaternion quatAxisRoll;
	quatAxisRoll.fromAngleAxis (15 * DEGTORAD, axis );

	// Once we've accumulated all our quaternions through multiplication we'll need to convert them to a matrix.
	// This stays the same throughout this program, so rotation is not frame rate independent. For that, you
	// can reset the quaternion or use slerp().
	matrix4 rotationMtxFromQuat( quatAxisRoll.getMatrix() );

	// We can use that to set the node rotation directly to the same position every frame, but if we want to 
	// animate the node we'll need a matrix for the node's rotation so that we can multiply our rotationMtxFromQuat into it.
	matrix4 currentRotMtx;	// of the node


	// ************
	// start 'er up!

	while(device->run())
	{
		// find node's current rotation
		currentRotMtx = gizmo->getAbsoluteTransformation();

		// alter it by our rotation (note the order of multiplication)
		currentRotMtx *= rotationMtxFromQuat;

		// apply the new, accumulated rotation
		gizmo->setRotation( currentRotMtx.getRotationDegrees() );

		// this is just for checking the console output
		nodeRot = gizmo->getRotation();
		std::cout << "\nRotX: " << nodeRot.X << "\nRotY: " << nodeRot.Y << "\nRotZ: " << nodeRot.Z << "\n\n";
	
		// draw everything
		driver->beginScene(true, true, SColor(255,50,50,140));

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

			// draw axis
			driver->setMaterial(someMaterial);
			driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
			driver->draw3DLine( -axis * 25, axis * 25, SColor(255, 255, 255, 0)  );

		driver->endScene();

		device->sleep(100, false);
	}

	device->drop();

	return 0;
}
"Computers don't make mistakes! What they do they do on purpose!!"

-Dale Gribble
Post Reply