moving objects

Started by
7 comments, last by Fil 19 years, 3 months ago
Hey, I know this question has probably been asked a thousand times already, but I can't find a answer to the problem I'm facing. Before I start, I'm an engineering student so I should have a fair knowledge of maths. I already had a camera class (with some help from "introduction to 3d game programming with directx 9.0" from D. Luna) which allowed me to move freely in the world i created. I thought I understood how everything worked, which I find very important, I'm not somebody who just copy-pastes code, I also want to know what I'm doing. The next thing I wanted to do was adding objects that moved. So I took the camera class, which exists of 4 vectors; a position (I know this is mathematically not correct), a right vector, up vector, and look vector. The class then calculates a transformation matrix from these vectors. I'll post some code to clarify this:


#include "movingobject.h"

MovingObject::MovingObject()
{
	_pos   = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
	_right = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
	_up    = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
	_look  = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
}

void MovingObject::getPosition(D3DXVECTOR3* pos)
{
	*pos = _pos;
}

void MovingObject::setPosition(D3DXVECTOR3* pos)
{
	_pos = *pos;
}

void MovingObject::getRight(D3DXVECTOR3* right)
{
	*right = _right;
}

void MovingObject::getUp(D3DXVECTOR3* up)
{
	*up = _up;
}

void MovingObject::getLook(D3DXVECTOR3* look)
{
	*look = _look;
}

void MovingObject::walk(float units)
{
	_pos += _look * units;
}

void MovingObject::strafe(float units)
{
	_pos += _right * units;
}

void MovingObject::fly(float units)
{
	_pos += _up * units;
}

void MovingObject::pitch(float angle)
{
	D3DXMATRIX T;

	D3DXMatrixRotationAxis(&T, &_right,	angle);

	// rotate _up and _look around _right vector
	D3DXVec3TransformCoord(&_up,&_up, &T);
	D3DXVec3TransformCoord(&_look,&_look, &T);


}

void MovingObject::yaw(float angle)
{
	D3DXMATRIX T;

	D3DXMatrixRotationAxis(&T, &_up, angle);

	// rotate _right and _look around _up or y-axis
	D3DXVec3TransformCoord(&_right,&_right, &T);
	D3DXVec3TransformCoord(&_look,&_look, &T);
}

void MovingObject::roll(float angle)
{
	D3DXMATRIX T;
	D3DXMatrixRotationAxis(&T, &_look,	angle);

	// rotate _up and _right around _look vector
	D3DXVec3TransformCoord(&_right,&_right, &T);
	D3DXVec3TransformCoord(&_up,&_up, &T);
}

void MovingObject::getObjectMatrix(D3DXMATRIX* V)
{
	D3DXVec3Normalize(&_look, &_look);

	D3DXVec3Cross(&_up, &_look, &_right);
	D3DXVec3Normalize(&_up, &_up);

	D3DXVec3Cross(&_right, &_up, &_look);
	D3DXVec3Normalize(&_right, &_right);

	float x = D3DXVec3Dot(&_right, &_pos);
	float y = D3DXVec3Dot(&_up, &_pos);
	float z = D3DXVec3Dot(&_look, &_pos);

	(*V)(0,0) = _right.x; (*V)(0, 1) = _up.x; (*V)(0, 2) = _look.x; (*V)(0, 3) = 0.0f;
	(*V)(1,0) = _right.y; (*V)(1, 1) = _up.y; (*V)(1, 2) = _look.y; (*V)(1, 3) = 0.0f;
	(*V)(2,0) = _right.z; (*V)(2, 1) = _up.z; (*V)(2, 2) = _look.z; (*V)(2, 3) = 0.0f;
	(*V)(3,0) = x;        (*V)(3, 1) = y;     (*V)(3, 2) = z;       (*V)(3, 3) = 1.0f;
}


(header file not included, it would not be very useful would it) Every object that has to move inherits from this class (MovingObject) en on drawing the object the world matrix is transformed using the matrix calculated from the vectors. The problem is, I can move the object by changing the position, but when I try pitch, yaw or roll the object it doesn't move around it's own axis but describes a circle. Which I don't understand because I rotate it around it's own axis, so there's no need to translate it first to the origin? I know I'm probably just making some very stupid beginners fault, but could somebody point me to a good tutorial about moving objects or tell me what to do because i really want to understand this. Thank you for all the help, and for this great forum which has learned me a lot already
Advertisement
You rotate around the local axis but the object is not centered in the origin and it's moving, so you have to translate it first to the origin.

(If at present you move the object and make rotations you would see the object describing a circle with a radius that is proportional to the distance of the object by the origin and other strange effects).

Hope that's help. :)
Fil (il genio)
ok, but when i have a look, up and right vector which i rotate around eachother why does it matter in that case what my position is? and how, when i have those three vectors and my position vector do i calculate my transformation matrix, is the above code correct?

Thanks for your reply, i know you can only rotate an object around it's own axis when it is at the origin, but i thought i did that by using those three vectors.

so i'm kind off lost at the moment
I've looked to your code a little more. The last raw of the matrix should be
_pos.x, _pos.y, _pos.z, 1.0 (last line of code). That's the 3d position in world coordinate of your object. I cannot figure out what kind of results you have with x,y,z (strange dot product, IMO). Anyway you don't use that matrix in the part of code you posted so I move on rotation procedures. You are not using _pos so your rotation are around the origin. The vector you use are applyed only at origin of axes (def of vector: v=(v.x,v.y,v.z) is an arrow starting from origin end ending at the 3d point (v.x,v.y,v.z)). Your rotation must happen at the origin of your model, so the need of translation to origin _prior_ to rotations (and of course post translation to move your object when it really has to be).

I hope you see what I mean. :)
Fil (il genio)
thank you very much fil, you were right, it are strange dots products, if i leave them out the pitch is correct, i thought they were necessary to get the correct position

aka

TransMatrix = | 1 0 0 0 | * | rx ux dx 0 |
| 0 1 1 0 | | ry uy dy 0 |
| 0 0 1 0 | | rz uz dz 0 |
| -px -py -pz 1 | | 0 0 0 1 |

= | rx ux dx 0 |
| ry uy dy 0 |
| rz uz dz 0 |
| -p*r -p*u -p*d 1 |


where r is right vector, u up vector and d direction (look) vector

so why is this not correct? if i don't do the dot product, will my resulting position not be totally screwed up?

thank you for you help so far, but i want to understand this as it probably is one of the most important parts in 3d programming
auch, the matrices got screwed up :p
Your matrix mult is not between 2 matrix!! Your second matrix is the rotation about an arbitrary axis centered at the origin. You need a post multiply of inverse translation matrix:
Mt * (Mx * My * Mz * M(pitch) * Mz^-1 * My^-1 * Mx^-1) * Mt^-1
where Mt= translation
Mx (My, Mz) rotation about x (y,z) axis
M(pitch) your rotation
superscript -1 indicates an inverse matrix.

You forgot Mt^-1. :-)
Fil (il genio)
thank you for your patience fil, i got it now, and if there is something i don't understand i still have this forum to fall back on :-). At least now i got a class i can use on every object that has to be moved and most important, i understand how it works (i still have a long way to go, but thanks to your help i'm starting to see some light at the end of the tunnel, which brings me to the next thing i have to implement in my engine, lighting, but that's another story :-p)
I'm happy to have been of help for you :-)

You are right at trying to understand how things work. It's the best way to learn (there are too many people that do cut&paste stuff without understanding why their code works! ;))

Bye and good luck for lighting! ;)
Fil (il genio)

This topic is closed to new replies.

Advertisement