Rotating model around directional vector

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
WizardofChaos
Posts: 21
Joined: Tue Jan 11, 2022 8:43 pm

Rotating model around directional vector

Post by WizardofChaos »

Hi there! I'm having trouble rotating a model around a directional vector.
What I have is a method to determine the "forward" vector:

Code: Select all

vector3df Ship::getForward()
{
	if (node) {
		matrix4 mat = node->getRelativeTransformation();
		return vector3df(-mat[8], -mat[9], -mat[10]).normalize();
	}
	return vector3df(0, 0, 0);
}
...and similar ones for other directions, up, left, right, etc. This works fine for velocity, which I'm doing with a simplistic force/mass thing:

Code: Select all

void Ship::accelerateForward()
{
	force += (getForward() * maxSpeed) - velocity;
}

//in the position updating function
	vector3df acceleration = force / mass;
	if (acceleration.getLength() > 0) {
		acceleration = acceleration.normalize() * std::min(acceleration.getLength(), maxForce);
	}
	velocity += acceleration * time;
	if (velocity.getLength() > 0) {
		velocity = velocity.normalize() * std::min(velocity.getLength(), maxSpeed);
	}
	vector3df pos = node->getPosition() + (velocity * time);

So the forward vector is the local Z axis. I'm having trouble applying a similar system to rotation, though, with a rotational force, and I think it's how the vector gets translated to the Euler angles that setRotation wants. Any ideas on how I can translate the one into the other? Essentially, how can I rotate a model properly around a local axis with a directional vector like the one I have? Do I need a different way to get the local axis or is it just a translation problem?
Local man gets so irritated with modern space sims that he starts writing his own
CuteAlien
Admin
Posts: 10021
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Rotating model around directional vector

Post by CuteAlien »

One way is go over matrices in between.

So first create a rotation matrix for current rotation.

Code: Select all

irr::core::matrix4 currentRotation;
currentRotation.setRotationDegrees(node->getRotation());
Then create a matrix for your local rotation simply around your original forward vector. You seem to have z as forward, so it would be:

Code: Select all

irr::core::matrix4 matLocalRot;
matLocalRot.setRotationDegrees(irr::core::vector3df(0,0,rotationAngle));
Now you combine those - which matrix multiplication does. Multiplication basically does mean - do this matrix first - then the next one (order matters!).

Code: Select all

irr::core::matrix4 combinedRotation = currentRotation*matLocalRot;
And back to euler:

Code: Select all

irr::core::vector3df newRotation = combinedRotation.getRotationDegrees();
There are more ways to solve this. For example you can also directly create the rotation matrix in the already rotated coordinate system.
Then it would be something like:

Code: Select all

irr::core::vector3df axisZ(0,0,1);
currentRotation.rotateVect(axisZ); // find z-axis in rotated coordinate system (or directly use matrix as you do above, but be careful about scaling)
irr::core::matrix4 matRotZ;
matRotZ.setRotationAxisRadians(rotationAngle*irr::core::DEGTORAD, axisZ);
When you add that one to the existing rotation matrix (which you get same way as above), this time the order is other way round:

Code: Select all

irr::core::matrix4 combinedRotation = matRotZ*currentRotation;
Sometimes going over quaternions is also helpful. You can think of quaternions more or less as a rotations around an axis. They tend to be nice when it comes to interpolating between rotations which can be useful for stuff like fading out rotations.


Ok... I hope I didn't mess up anything ^_^
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
WizardofChaos
Posts: 21
Joined: Tue Jan 11, 2022 8:43 pm

Re: Rotating model around directional vector

Post by WizardofChaos »

Ah, this helped out a lot! Thank you very much. Searching the forums a bit more found your previous implementation of the problem here:
viewtopic.php?f=1&t=51546#top

...which worked a treat. So, for anyone else looking, the code looks like this:

Code: Select all

void Ship::yawLeft()
{
	rotForce.Y -= maxRotSpeed - rotVelocity.Y;
}
...then your usual acceleration / velocity stuff that I posted above, but using CuteAlien's code from the link (minus the bool on local rotations, since I needed it to be exclusively local):

Code: Select all

vector3df newRot = rotateAxesXYZToEuler(node->getRotation(), (rotVelocity * time));
The force and acceleration and velocity are all kept as their basic XYZ in local coordinates until I need to actually update the rotation. Thank you again!
Local man gets so irritated with modern space sims that he starts writing his own
Post Reply