1
\$\begingroup\$

I'm using jMonkeyEngine to develop a game. I'm good at scripting, but math usually goes over my head. I tried the Wiki page for Quaternion, but I was far too confused to figure this out myself :P

My goal

I have a sphere with physics enabled, and I want to have it rotate based on mouse axis movement. I've got listeners set up properly so that in this method:

void roll(int axis, float tpf) {
    Quaternion rot = this.getPhysicsRotation();
    switch(axis) {
        case MouseInput.AXIS_X:
            // Rotate here
            break;
        case MouseInput.AXIS_Y:
            // Rotate here
            break;
    }
}

an axis and a value (+/-) will be provided. Once I figure out how to modify Quaternions, I'll just use RigidBodyControl.setPhysicsRotation(Quaternion) to update the rotation.

My Problem

I'm clueless about Quaternions.. I don't even know what method I'd be using. I assume Quaternion.add() or .mult() will be necessary.

Someone please help! Here's a link to jme's Quaternion class for reference.

Solution

From Zoltan's answer:

void roll(int axis, float tpf) {
    tpf *= 10;
    System.out.println("roll("+axis+","+tpf+")");
    switch(axis) {
        case MouseInput.AXIS_Y:
            Quaternion quaternion = new Quaternion();
            this.setPhysicsRotation(getPhysicsRotation().mult(quaternion.fromAngleAxis(tpf, Vector3f.UNIT_X)));
            break;
        case MouseInput.AXIS_X:
            Quaternion q = new Quaternion();
            this.setPhysicsRotation(getPhysicsRotation().mult(q.fromAngleAxis(tpf, Vector3f.UNIT_Y)));
            break;
    }
}

I'm not quite sure why case:MouseInput had to be swapped, but it works this way so.. shrug

\$\endgroup\$
4
  • \$\begingroup\$ Don't have time for a full answer, but when working with quaternions it's pretty common to author your input data as euler angles (see Quaternion.fromAngles(float, float, float)). So generate a quaternion using an euler angle that you determine from your mouse input, then you'll probably want to do a multiply with the current angle. \$\endgroup\$
    – Tetrad
    Commented Oct 20, 2011 at 22:17
  • 3
    \$\begingroup\$ "but math usually goes over my head." If that's the case, are you sure you want to program graphics? It's basically all math. \$\endgroup\$ Commented Oct 20, 2011 at 23:13
  • \$\begingroup\$ Did you look at this answer? \$\endgroup\$ Commented Oct 20, 2011 at 23:15
  • 2
    \$\begingroup\$ Nicol, there's nothing wrong with attempting something new.. I've already learned a lot. Tetrad, I'll try and play with that when I'm back at my computer and get back to you. \$\endgroup\$
    – Snailer
    Commented Oct 21, 2011 at 2:16

2 Answers 2

2
\$\begingroup\$

You don't really need to know stuff about quaternions for this. Consider the following:

Vector3f xAxis = sphere.worldToLocal(Vector3f.UNIT_X, null);
Quaternion quaternion = new Quaternion();
sphere.rotate(quaternion.fromAngleAxis(yRot, yAxis));

This will rotate your sphere about the x-axis for the given angle. You need to use worldToLocal because as you rotate your sphere around arbitrary axes, its local axes get rotated too.

As for why the y and x axis needed to be "swapped", you're not swapping anything, just think about it. When you're moving your mouse along the y-axis, you're rotating your sphere about the x-axis and vice versa. This is exactly what your code is saying.

\$\endgroup\$
3
  • \$\begingroup\$ RigidBodyControl doesn't have a rotate() method, just set rotation. However, this could still work.. still not at my computer, but I'll try this out too. \$\endgroup\$
    – Snailer
    Commented Oct 21, 2011 at 16:34
  • \$\begingroup\$ Since you used setPhysicsRotation(getPhysicsRotation().mult, you don't need worldToLocal. Notice that you don't read the xAxis and yAxis variables in your code at all. \$\endgroup\$
    – Zoltán
    Commented Oct 24, 2011 at 9:52
  • \$\begingroup\$ lol, yeah.. I was just excited to get it working :p \$\endgroup\$
    – Snailer
    Commented Oct 24, 2011 at 21:50
0
\$\begingroup\$

Have you considered an arcball implementation? They are relatively straightforward and produce reasonably intuitive means of manipulating objects in 3D space. Essentially, you project the mouse coordinates from the current and previous frame onto an imaginary sphere that surrounds your object (in this case, it is a sphere, so there's that) and then compute the shortest arc quaternion between the two points.

You can then convert that quaternion to a matrix to apply it. Do note that APIs choose slightly different conventions for quaternion representations and your math may need to be adjusted to account for that (I don't know what convention jMonkeyEngine employs).

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .