1

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)

user1118321
  • 25,567
  • 4
  • 55
  • 86
Niklas
  • 23,674
  • 33
  • 131
  • 170

1 Answers1

1

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.

Nicolas Louis Guillemot
  • 1,570
  • 1
  • 10
  • 23
  • 1
    For `quaternions`, google for an implementation or copy the math into code. I can't explain the math well. For the `rotation matrix`, it's simple: A rotation matrix is made of 3 unit vectors that form an orthogonal basis. For example, the identity rotation is [1,0,0;0,1,0;0,0,1], each row corresponding to the unit vectors x,y,z. To make other rotations, write in each row what the corresponding unit vector's direction is in the new space. For example, rotating by 90 degrees counter-clockwise about Z+ is [0,1,0;-1,0,0;0,0,1] – Nicolas Louis Guillemot Sep 11 '13 at 23:37
  • 1
    If my explanation makes no sense, I recommend reading the relevant chapters in a computer graphics textbook or a 3D game programming book (like Game Engine Architecture) – Nicolas Louis Guillemot Sep 11 '13 at 23:39
  • 1
    You can multiply quaternions together to combine them, like transformation matrices. You need to store the quaternion and concatenate the new ones as they come. Then at the end always rotate using that accumulated quaternion converted to a rotation matrix. – Nicolas Louis Guillemot Sep 12 '13 at 00:46