I am trying to animate a 3D sphere in Irrlicht with WASD. The moving part works properly, but the rotation does not work. As long as I press only W / S or A / D it works. If I mix them up or start from a different point, the rotation spins.
Declaration
scene::ISceneNode* ballSceneNode = sceneManager->addSphereSceneNode(5);
if (ballSceneNode) {
ballSceneNode->setPosition(core::vector3df(0, 0, 100));
ballSceneNode->setMaterialTexture(0, driver->getTexture("media/ball.bmp"));
ballSceneNode->setMaterialFlag(video::EMF_LIGHTING, false);
}
Main Loop
core::vector3df ballRotation = ballSceneNode->getRotation();
core::vector3df ballRotation = ballSceneNode->getPosition();
if(receiver.isKeyDown(irr::KEY_KEY_W)) {
ballPosition.Z += movement;
ballRotation.X++;
} else if(receiver.isKeyDown(irr::KEY_KEY_S)) {
ballPosition.Z -= movement;
ballRotation.X--;
}
if(receiver.isKeyDown(irr::KEY_KEY_A)) {
ballPosition.X -= movement;
ballRotation.Z++;
} else if(receiver.isKeyDown(irr::KEY_KEY_D)) {
ballPosition.X += movement;
ballRotation.Z--;
}
ballSceneNode->setPosition(ballPosition);
ballSceneNode->setRotation(ballRotation);
I have read about that you need core::matrix4
for rotation or better to say that it would be helpful / easier and maybe also correct, but I do not know how to use it.
EDIT
if(receiver.isKeyDown(irr::KEY_KEY_W)) {
ballPosition.Z += movement;
cameraPosition.Z += movement;
core::quaternion test;
test.fromAngleAxis(xAxisAngle, core::vector3df(1,0,0));
xAxisAngle += 0.1f;
test.normalize();
core::vector3df rot;
test.toEuler(rot);
ballSceneNode->setRotation(rot * core::RADTODEG);
} else if(receiver.isKeyDown(irr::KEY_KEY_S)) {
ballPosition.Z -= movement;
cameraPosition.Z -= movement;
core::quaternion test;
test.fromAngleAxis(xAxisAngle, core::vector3df(1,0,0));
xAxisAngle -= 0.1f;
test.normalize();
core::vector3df rot;
test.toEuler(rot);
ballSceneNode->setRotation(rot * core::RADTODEG);
}
if(receiver.isKeyDown(irr::KEY_KEY_A)) {
ballPosition.X -= movement;
cameraPosition.X -= movement;
core::quaternion test;
test.fromAngleAxis(zAxisAngle, core::vector3df(0,0,1));
zAxisAngle += 0.1f;
test.normalize();
core::vector3df rot;
test.toEuler(rot);
ballSceneNode->setRotation(rot * core::RADTODEG);
} else if(receiver.isKeyDown(irr::KEY_KEY_D)) {
ballPosition.X += movement;
cameraPosition.X += movement;
core::quaternion test;
test.fromAngleAxis(zAxisAngle, core::vector3df(0,0,1));
zAxisAngle -= 0.1f;
test.normalize();
core::vector3df rot;
test.toEuler(rot);
ballSceneNode->setRotation(rot * core::RADTODEG);
}
xAxisAngle
and zAxisAngle
are just f32 with default value 0.
Now the problem is: W W D (jumping to original state and loosing the 2 W's)
Mixing rotations using euler angles is always strange because the order in which you apply the rotations matters. Look into using quaternions or building a rotation matrix from an orthogonal basis. There's lots of information on doing these tasks on the Internet and in graphics related textbooks.