Jump to content

Using translation matrices with Java 3D

- - - - -

  • Please log in to reply
No replies to this topic

#1
ThemePark

ThemePark

    Programmer

  • Members
  • PipPipPipPip
  • 124 posts
I just started learning Java 3D and I'm taking baby steps here. However, the first thing I want to try out, confuses me still, even though I have tried understanding it many times before.

I'm talking about translation matrices. Rotating and translating objects in your 3D program just escapes me. I get that it has to do with 4x4 matrices, but that's all. Fortunately Java 3D has much more of this wrapped into simple methods that I can understand. So I can easily make one such matrices. But combining them and moving the origin is beyond me.

I use a combination of the Java 3D tutorial and this:
Combining Rotation and Translation in Java 3d — Developer.com

to do what I want. Chapter 1 of the Java 3D tutorial shows you how to spin a colour cube around the Y axis, and how to move the camera so that you look at the cube from above.

I have copied the code from ColourCube and made my own Cube that takes as arguments an x, y and z variable that decides where to place the cube. Also, I have changed the vertices from going from -1 to 1, to going from 0 to 1, since I want a unit cube.

What I want to do is to place a cube at 1.5, 1.5, 1.5 with its vertices going from 1 to 2. I want to spin that cube around the 1.5, y, 1.5 axis, i.e. a translation. And I want that spin to be valid for other cubes I will add later so that they all spin around that point. And finally I want to move the camera so I look at the cube from above.

This is the code I have:
import javax.media.j3d.*;

/**
 * Simple color-per-vertex cube with a different color for each face
 */
public class Cube extends Shape3D {
    private static final float[] verts = {
    // front face
	1.0f, 0.0f, 1.0f,
	1.0f, 1.0f, 1.0f,
	0.0f, 1.0f, 1.0f,
	0.0f, 0.0f, 1.0f,
    // back face
	0.0f, 0.0f, 0.0f,
	0.0f, 1.0f, 0.0f,
	1.0f, 1.0f, 0.0f,
	1.0f, 0.0f, 0.0f,
    // right face
	1.0f, 0.0f, 0.0f,
	1.0f, 1.0f, 0.0f,
	1.0f, 1.0f, 1.0f,
	1.0f, 0.0f, 1.0f,
    // left face
	0.0f, 0.0f, 1.0f,
	0.0f, 1.0f, 1.0f,
	0.0f, 1.0f, 0.0f,
	0.0f, 0.0f, 0.0f,
    // top face
	1.0f, 1.0f, 1.0f,
	1.0f, 1.0f, 0.0f,
	0.0f, 1.0f, 0.0f,
	0.0f, 1.0f, 1.0f,
    // bottom face
	0.0f, 0.0f, 1.0f,
	0.0f, 0.0f, 0.0f,
	1.0f, 0.0f, 0.0f,
	1.0f, 0.0f, 1.0f,
    };

    private static final float[] colors = {
    // front face (red)
	1.0f, 0.0f, 0.0f,
	1.0f, 0.0f, 0.0f,
	1.0f, 0.0f, 0.0f,
	1.0f, 0.0f, 0.0f,
    // back face (green)
	0.0f, 1.0f, 0.0f,
	0.0f, 1.0f, 0.0f,
	0.0f, 1.0f, 0.0f,
	0.0f, 1.0f, 0.0f,
    // right face (blue)
	0.0f, 0.0f, 1.0f,
	0.0f, 0.0f, 1.0f,
	0.0f, 0.0f, 1.0f,
	0.0f, 0.0f, 1.0f,
    // left face (yellow)
	1.0f, 1.0f, 0.0f,
	1.0f, 1.0f, 0.0f,
	1.0f, 1.0f, 0.0f,
	1.0f, 1.0f, 0.0f,
    // top face (magenta)
	1.0f, 0.0f, 1.0f,
	1.0f, 0.0f, 1.0f,
	1.0f, 0.0f, 1.0f,
	1.0f, 0.0f, 1.0f,
    // bottom face (cyan)
	0.0f, 1.0f, 1.0f,
	0.0f, 1.0f, 1.0f,
	0.0f, 1.0f, 1.0f,
	0.0f, 1.0f, 1.0f,
    };

    double scale;

    public Cube(float x, float y, float z) {
    	this(x, y, z, 0.4f);
    }

    public Cube(float x, float y, float z, double scale) {
    	QuadArray cube = new QuadArray(24, QuadArray.COORDINATES | 
    			QuadArray.COLOR_3);

    	float scaledVerts[] = new float[verts.length];
    	for (int i = 0; i < verts.length; i += 3) {
    		scaledVerts[i] = x * (float)scale + verts[i] * (float)scale;
    		scaledVerts[i + 1] = y * (float)scale + verts[i + 1] * (float)scale;
    		scaledVerts[i + 2] = z * (float)scale + verts[i + 2] * (float)scale;
    	}

    	cube.setCoordinates(0, scaledVerts);
    	cube.setColors(0, colors);

    	this.setGeometry(cube);

    	this.scale = scale;
    }
}

import java.applet.Applet;

import java.awt.BorderLayout;
import java.awt.FlowLayout;

import javax.media.j3d.*;
import javax.vecmath.Vector3f;

import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.universe.SimpleUniverse;

public class Test extends Applet {
	public Test() {
		Canvas3D canvas = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
		
		BranchGroup scene = createSceneGraph();
		scene.compile();

		SimpleUniverse universe = new SimpleUniverse(canvas);
		universe.getViewingPlatform().setNominalViewingTransform();
		universe.addBranchGraph(scene);

		setLayout(new BorderLayout());
		add("Center", canvas);
	}
	
	public BranchGroup createSceneGraph() {
		Alpha rotationAlpha = new Alpha(-1, 4000);
		BoundingSphere bounds = new BoundingSphere();

		TransformGroup objSpin = new TransformGroup();
		objSpin.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		RotationInterpolator rotator =
		new RotationInterpolator(rotationAlpha, objSpin);
		rotator.setSchedulingBounds(bounds);
		
        Transform3D objTranslate = new Transform3D();
        objTranslate.setTranslation(new Vector3f(0.0f, 0.0f, 0.0f));
        TransformGroup transformGroup = new TransformGroup();
        transformGroup.setTransform(objTranslate);

		Transform3D rotate = new Transform3D();
		Transform3D tempRotate = new Transform3D();
		rotate.rotX(Math.PI/4.0d);
		tempRotate.rotY(Math.PI/4.0d);
		rotate.mul(tempRotate);
		TransformGroup objRotate = new TransformGroup(rotate);

		BranchGroup objRoot = new BranchGroup();

		objSpin.addChild(rotator);
        objSpin.addChild(new ColorCube());
		objRotate.addChild(objSpin);
        transformGroup.addChild(objRotate);
		objRoot.addChild(transformGroup);
		
		return objRoot;
	}
}

import com.sun.j3d.utils.applet.MainFrame;

public class Simulation {
	public Simulation() {
		new MainFrame(new Test(), 256, 256);
	}
	
	public static void main(String[] args) {
		new Simulation();
	}
}

I am very unsure of the order of which to add those matrices to each other, i.e. who is the parent of whom, and just in general how to translate the Y-axis to another point.

Another, although minor, thing is that I have to use BorderLayout where I would prefer to use FlowLayout. If I use that however, nothing shows in the apple window. Can anybody tell me why?

Update:
Well, it seems that I can't delete my own posts, so I will just write the solution instead.

As it turns out, it was just a stupid mistake of me. Whenever I created a new Cube, the coordinates would usually cause the cube to not be centered at the origin. Because of this, any matrix used afterwards would be relative to the origin as they always are instead of, as I thought, relative to the center of the cube. To solve this, I simply need to build a translation matrix to put the center of the cube back to being the origin, then use a rotation matrix, and then finally a translation matrix to move the cube back to where it was before.

Edited by ThemePark, 17 September 2009 - 08:55 AM.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users