Search code examples
javaopenglgraphicsjava-3d

How to rotate an object in Java 3D?


I have a Cone I drew in Java 3D with the following code:

Cone cone = new Cone(2f, 3f);

Transform3D t3d = new Transform3D();
TransformGroup coneTransform = new TransformGroup(t3d);
coneTransform.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

t3d.setTranslation(new Vector3f(0f,0f,0f);
coneTransform.setTransform(t3d);
coneTransform.addChild(cone);

this.addChild(coneTransform);

Suppose I have the cone sitting at point (1,1,1) and I want the tip of the cone to point down an imaginary line running through (0,0,0) and (1,1,1)... how can I do this?

Here's an example of what I've been trying:

Transform3D t3d = new Transform3D();  

Vector3f direction = new Vector3f(1,2,1);    

final double angleX = direction.angle(new Vector3f(1,0,0));
final double angleY = direction.angle(new Vector3f(0,1,0));
final double angleZ = direction.angle(new Vector3f(0,0,1));

t3d.rotX(angleX);
t3d.rotY(angleY);
t3d.rotZ(angleZ);

t3d.setTranslation(direction);

coneTransform.setTransform(t3d);

Thanks in advance for all help!


Solution

  • I finally figured out what I wanted to do by using Quaternions, which I learned about here: http://www.cs.uic.edu/~jbell/Courses/Eng591_F1999/outline_2.html Here's my solution.

    Creating the cone:

     private void attachCone(float size) {
            Cone cone = new Cone(size, size* 2);
    
            // The group for rotation
            arrowheadRotationGroup = new TransformGroup();
            arrowheadRotationGroup.
                 setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
            arrowheadRotationGroup.addChild(cone);
    
            // The group for positioning the cone
            arrowheadPositionGroup = new TransformGroup();
            arrowheadPositionGroup. 
                  setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
            arrowheadPositionGroup.addChild(arrowheadRotationGroup);
    
            super.addChild(arrowheadPositionGroup);
        }
    

    Now, when I want to rotate the cone to point in a certain direction specified as the vector from the point (0,0,0) to (direction.x, direction.y, direction.z), I use:

    private final Vector3f yAxis = new Vector3f(0f, 1f, 0f);
    private Vector3f direction; 
    
    private void rotateCone() {
            // Get the normalized axis perpendicular to the direction 
            Vector3f axis = new Vector3f();
            axis.cross(yAxis, direction);
            axis.normalize();
    
            // When the intended direction is a point on the yAxis, rotate on x
            if (Float.isNaN(axis.x) && Float.isNaN(axis.y) && Float.isNaN(axis.z)) 
            {
                axis.x = 1f;
                axis.y = 0f;
                axis.z = 0f;
            }
            // Compute the quaternion transformations
            final float angleX = yAxis.angle(direction);
            final float a = axis.x * (float) Math.sin(angleX / 2f);
            final float b = axis.y * (float) Math.sin(angleX / 2f);
            final float c = axis.z * (float) Math.sin(angleX / 2f);
            final float d = (float) Math.cos(angleX / 2f);
    
            Transform3D t3d = new Transform3D();
            Quat4f quat = new Quat4f(a, b, c, d);
            t3d.set(quat);
            arrowheadRotationGroup.setTransform(t3d);
    
            Transform3D translateToTarget = new Transform3D();
            translateToTarget.setTranslation(this.direction);
            arrowheadPositionGroup.setTransform(translateToTarget);
        }