Move/Spin model

Hey

I am currently makeing something for fun. I have a 3ds max model of a jeep which I load into my program with kevs loader
everything goes fine but i want to move it. I also want to make the wheels spin when the jeep is riding en make them turn
when i make a turn. To do so i have made severl tranformgroups to be able to animate each part seperatly
but the things wont move and when I rotate a wheel its rotating not around the center of itself but around an axis
how can i fix this. This is the code of the jeep class, which includes methods to drive and spin weels:

//standard xith3D imports
import com.xith3d.scenegraph.;
import javax.vecmath.
;

/**

  • Jeep 3ds max model
    **/
    public class Jeep extends Model
    {
    //wheels
    private TransformGroup rlw; private Transform3D rlw3D; private float angleRLW = 0;
    private TransformGroup rrw; private Transform3D frw3D; private float angleFRW = 0;
    private TransformGroup flw; private Transform3D flw3D; private float angleFLW = 0;
    private TransformGroup frw; private Transform3D rrw3D; private float angleRRW = 0;
    //steerings
    private TransformGroup ls;
    private TransformGroup rs;
    //main body
    private TransformGroup main;
/**
 *  Constructor
 **/
public Jeep ()
{
	super ("./models/jeep/jeep.3ds", "./models/jeep/");
	loadComponents ();
}

//loads each component and add it to it's own tranform3d
public void loadComponents ()
{
	rlw = TDSmodel.getNamedTransformGroup("rlw");
	rlw.removeFromParentGroup();
	rrw = TDSmodel.getNamedTransformGroup("rrw");
	rrw.removeFromParentGroup();
	flw = TDSmodel.getNamedTransformGroup("flw");
	flw.removeFromParentGroup();
	frw = TDSmodel.getNamedTransformGroup("frw");
	frw.removeFromParentGroup();

	ls = TDSmodel.getNamedTransformGroup("lsteer");
	ls.removeFromParentGroup();
	rs = TDSmodel.getNamedTransformGroup("rsteer");
	rs.removeFromParentGroup();
	
	main = TDSmodel.getNamedTransformGroup("main");
	main.removeFromParentGroup();
}

//rotates the front right wheel
public void rotateFRW ()
{
	
	angleFRW += 0.1f;
	frw3D = new Transform3D();
	frw3D.setTranslation(new Vector3f(2.0f, -5.0f, 0.0f));
	frw.getTransform(frw3D);				
	
	frw3D.rotX(angleFRW);
	frw.setTransform(frw3D);
	//rlw.getTransform().setTranslation(new Vector3f(2.0f, -5.0f, 0.0f));
}

//rotates the rear rightt wheel
public void rotateRRW ()
{
	
	angleRRW += 0.1f;
	
	rrw3D = new Transform3D();
	rrw.getTransform(rrw3D);				
	rrw3D.rotX(angleRRW);
	rrw.setTransform(rrw3D);
	//rlw.getTransform().setTranslation(new Vector3f(2.0f, -5.0f, 0.0f));
}

//rotates the front left wheel
public void rotateFLW ()
{
	
	angleFLW += 0.1f;
	
	flw3D = new Transform3D();
	flw.getTransform(flw3D);				
	flw3D.rotX(angleFLW);
	flw.setTransform(flw3D);
	//rlw.getTransform().setTranslation(new Vector3f(2.0f, -5.0f, 0.0f));
}

//rotates the rear left wheel
public void rotateRLW ()
{
	
	angleRLW += 0.1f;
	
	rlw3D = new Transform3D();
	rlw.getTransform(rlw3D);				
	rlw3D.rotX(angleRLW);
	rlw.setTransform(rlw3D);
	//rlw.getTransform().setTranslation(new Vector3f(2.0f, -5.0f, 0.0f));
}

public void drive ()
{
	rlw.getTransform().setTranslation(new Vector3f(2.0f, -5.0f, 5.0f));
	rrw.getTransform().setTranslation(new Vector3f(2.0f, -5.0f, 5.0f));
	flw.getTransform().setTranslation(new Vector3f(2.0f, -5.0f, 10.0f));
	frw.getTransform().setTranslation(new Vector3f(2.0f, -5.0f, 10.0f));
}

/**
 * Getters
 **/
 
//return each wheel
public TransformGroup getRearLeftWheel () { return rlw; } 
public TransformGroup getRearRightWheel () { return rrw; } 
public TransformGroup getFrontLeftWheel () { return flw; } 
public TransformGroup getFrontRightWheel () { return frw; } 
//return eacht steer
public TransformGroup getLeftSteer() { return ls; } 
public TransformGroup getRightSteer() { return rs; } 
//return main body
public TransformGroup getMainBody() { return main; } 
//return the whole model
public BranchGroup getModel ()
{
	BranchGroup bg = new BranchGroup();
	bg.addChild(rlw); bg.addChild(flw);	bg.addChild(rrw); bg.addChild(frw);
	bg.addChild(ls); bg.addChild(rs);
	bg.addChild(main);
	return bg;
}

}

In mijn main class I have created a branchgroup and have added echt part serperatly to it
and then added it to the scene but it doesnt work. Here is my mainclass code:

//standard xith3D imports
import com.xith3d.scenegraph.;
import javax.vecmath.
;
// use Jogl
import com.xith3d.render.;
import com.xith3d.render.jogl.
;
// Texture stuff
import com.xith3d.loaders.texture.;
// Model loader
import com.kinostudios.loader3ds.
;
//keylistener
import java.awt.event.*;

/**

  • Class which animates the wheels bij turning and spinning them
    **/
    public class WheelAnimation
    {
    private final int DIST = 20;
private float rotX = 0;
private float rotY = 0;
private float rotZ = 0;

private TransformGroup objRotate;
private Transform3D rotate;

private boolean isRotationScheduled = false;
	
private View view;
private BranchGroup scene;

private Jeep jeep;

public WheelAnimation()
{
	VirtualUniverse vu = new VirtualUniverse();
	
	view = new View();
	vu.addView(view);
	
	Locale locale = new Locale();
	vu.addLocale(locale);

    rotate = new Transform3D();
    rotate.rotXYZ(rotX, rotY, rotZ);
    objRotate = new TransformGroup(rotate);
    objRotate.addChild(createScene());       
	
	scene =  new BranchGroup();
	// let objects along this path rotate
    scene.addChild(objRotate);
	locale.addBranchGraph(scene);

	drawGrid ();

	RenderPeer    rp      = new RenderPeerImpl();
	CanvasPeer    cp      = rp.makeCanvas(null, 1280, 1024, 32, true);
	Canvas3D      canvas  = new Canvas3D();
	//set the render options
	RenderOptions options = new RenderOptions();
	options.setOption(Option.USE_SHADOWS, true);
	options.setOption(Option.USE_LIGHTING, true);
	options.setOption(Option.USE_TEXTURES, true);
	cp.setRenderOptions(options);
	//close app with ESC key
	cp.getComponent().addKeyListener(new KeyAdapter() {
		public void keyPressed(KeyEvent e) {
    		switch(e.getKeyCode()) {
	            case KeyEvent.VK_LEFT : rotY+=0.05; 
	            						isRotationScheduled = true;
	            						break;
		        case KeyEvent.VK_RIGHT: rotY-=0.05;
		        						isRotationScheduled = true;
		        						break;
    		}
		}
		public void keyTyped(KeyEvent e) {	
			switch(e.getKeyChar()) { case 27: System.exit(0); break; }
		}
	});
	
	Color3f ambientColor = new Color3f(1f, 1f, 1f);
	AmbientLight ambientLightNode = new AmbientLight(true, ambientColor);
	scene.addChild(ambientLightNode);

	DirectionalLight light = new DirectionalLight(true,
												  	new Color3f(1f, 1f, 1f), 
												  	new Vector3f(0f, -2f, -3f));
	scene.addChild(light);

	canvas.set3DPeer(cp);

	view.addCanvas3D(canvas);
	view.getTransform().lookAt(new Vector3f(DIST, DIST, DIST), // location of eye
								new Vector3f(0, -10, 0), // center of view
								new Vector3f(0, 1, 0));// which axis is "up"

	scene.compile();
	//keep on rendering
	run();
}

//draws a grid on the scene
public void drawGrid ()
{		
	for (int i = -20; i <= 20; i+=2)
	{	//draw lines // with X-axis
		objRotate.addChild( new Shape3D( 
						 drawLine ( new Point3f[] { 
										new Point3f (i, 0, -20),
										new Point3f (i, 0, 20) }),
	 								new Appearance()));
		//draw lines // with Z-axis
		objRotate.addChild( new Shape3D( 
						 drawLine ( new Point3f[] { 
										new Point3f (-20, 0, i),
										new Point3f (20, 0, i) }),
	 								new Appearance()));
	}
}
	
public Geometry drawLine (Point3f[] coords)
{
	LineArray g = new LineArray(coords.length, GeometryArray.COORDINATES);
	g.setCoordinates(0,coords);
	return g;
}

public void run()
{
	while (true)
	{
		/*jeep.rotateRLW();
		jeep.rotateFLW();
		jeep.rotateRRW();
		jeep.rotateFRW();
		*/
		jeep.drive();
		view.renderOnce();
		if(isRotationScheduled)
        {
        	performRotation();
            isRotationScheduled = false;
        }
        try { Thread.sleep(50); } catch (Exception e) {e.printStackTrace();}
    }
}

public BranchGroup createScene()
{
	BranchGroup root = new BranchGroup();
	//change backgroundcolor
	Background bg = new Background(new Color3f(0.5f,0.5f,0.5f));
	root.addChild(bg);
	//load the axis model
	Axis assen = new Axis ();
	root.addChild(assen.getModel());
	
	//load jeep model
	jeep = new Jeep ();
					
	BranchGroup bg1 = new BranchGroup();
	bg1.addChild(jeep.getRearLeftWheel());
	bg1.addChild(jeep.getFrontLeftWheel());
	bg1.addChild(jeep.getRearRightWheel());
	bg1.addChild(jeep.getFrontRightWheel());
	root.addChild(bg1);
	
	return root;
}

/**
 * This method performs the rotation of the canvas
 */
private void performRotation()
{
    rotate.rotXYZ(rotX, rotY, rotZ);
    objRotate.setTransform(rotate);
}

public static void main(String[] args) { new WheelAnimation(); }

}

Can anyone help? plz thx a lot :slight_smile:

i have been able to track the coordinates of the center of each wheel
cant i rotate a wheel around a custom axis? (formed with that coordinate)

I do not know if the 3ds loader can create individual transform groups relitive to the object’s center (or pivot point).

I do know that the ASE Loader can do this because I added this feature, use it regularly and wrote a tutorial about the topic.

Cheers,

Will.

i first used the ase loader but my 3ds files get soooo large and it doenst support the 3ds materials
thats why i used an external 3ds loader for xith (kevs) to be able to do all this
aint their a way i can move the (0,0,0) around so point (1,2,5) for example becomes the new center?

If you have a point p you can rotate it with a rotation-matrix M around a point q by doing this:


new_p = q.add(M.translate(p.sub(q)));

Is that what you want to do?

is it possible to get the names of the nodes bcz when i use
TDSmodel.getNamedTransformGroup(name);
I have to allready know the name so i cant make a gerenal class which lodes each node seperatly

How did you do the tracking I wonder, without getting the names of the nodes?

i have a wheel and i want to rotate around its own X-aixs (to make it spin, to let you feel the car is riding)
and around its Y-axis when you make a turn te make the wheels turn

the spinning round X en Y isnt at the same time though

i know the names because its just a testing model.
But i would want to make a general class for each model, from which i dont know the names

yep you have to have the appropriate Matrix for that. e.g. you can set rotations around an Axis with AxisAngle and the setting the AxisAngle to the Matrix. Look at javax.vecmath.Matrix3f.

do you have an example? much easier to understand than

Matrix3f m = new Matrix3f();
AxisAngle4f a = new AxisAngle4f(1,0,0,2); // rotate 2 radians around the x-Axis
m.set(a);

but i have for example a wheel at (5,3,2)
if I use that axisAngle wont it rotate around an axis trought that point and (0,0,0)?
I don’t quite understand sorry

Matrix3f.transform(Point) rotates Point around (0|0|0) and with the AxisAngle you specify the direction and the amount (e.g. x-Axis and 2 radians).

to rotate Point around another Point you first have to translate it, so that the other Point is at (0|0|0) then you can transform it with the matrix, and then you can translate it back.

In my experiance what makes it hard is that the actual geometry coordinates are at say 10,10,10 which makes it hard to transform it based on the object’s own pivot point (instead of the object turning by itself, it is transformed relitive to the origin which is not what you want), hence the reason for my work on the ASE loader.

I’m not sure if I am misreading your problem though, it just sounded similar to one I had (and solved).

Will.

i have now made a generic class which loads any model by loading its groups seperatly
i have made a little loader in which u can select which groups u want to see
but i have an other question, i have upgraded to java 1.5 and something in my menu doenst work anymore
i have added some jcheckbox in a option JMenu but i cant click them
they appear when i click the jmenu so it unfolds but when i click the jcheckbox nothing happens bcz the program doesnt call the actionlistener
this was going fine with java 1.4.2, the shadow jcheckbox is autoselected but both cant be clicked and I need to be albe those jcheckboxes
bcz I have added another menu with all names of nodes/parts so i can select which ones i want to view


http://img335.imageshack.us/img335/7840/modelloader0bd.th.jpg


http://img108.imageshack.us/img108/1515/modelloader4qr.th.jpg

the only why i can use the jcheckboxes is by first clicking on them so they are selected and then by pressing space their state changes
and so the actionlistener is called

strange
have you tested, if this also happens in normal application, without the Xith-Canvas below? (maybe this is a heavyweight/lightwight problem)

will try btw i still dont get my wheel to spin dont quite understand, can I add u at icq or maybe send me my code for some help?

wrote a test class with just a jframe
i have adde 2 jcheckboxes (1 selected) to a jmenubar but stille the same problem
i also adde a jpanel with a jcheckbox on and i can click that one no problem :s
anyone has an idea?

//awt and swingcomponents
import java.awt.;
import javax.swing.
;
import java.awt.event.*;

class TestFrame extends JFrame
{
public TestFrame()
{
setTitle(“TestFrame”);
//add menubar to frame
setJMenuBar(createMenuBar());
//add panel with jcheckbox
addPanel();
//start frame maximized
setExtendedState(JFrame.MAXIMIZED_BOTH);
setVisible(true);
}

public void addPanel ()
{
	JPanel test = new JPanel ();
	JCheckBox click = new JCheckBox ("click me");
	test.add(click);
	add(test);
}

//creates the menubar
public JMenuBar createMenuBar ()
{
	JMenuBar mb = new JMenuBar ();

	//create the menu file
	JMenu file = new JMenu ("File");
	
	JMenuItem quit = new JMenuItem ("Quit");
	quit.addActionListener(new ActionListener(){
		public void actionPerformed (ActionEvent ae){ close(); }
	});
	//add menuitems to menu file
	file.add(quit);

	//create the menu options
	JMenu options = new JMenu ("Options");
	//menuitems of het menu
	JCheckBox wire = new JCheckBox ("Wireframe Models");
	wire.addActionListener(new ActionListener(){
		public void actionPerformed (ActionEvent ae){ 

		}
	});
	JCheckBox shadows = new JCheckBox ("Shadows");
	shadows.setSelected(true);
	shadows.addActionListener(new ActionListener(){
		public void actionPerformed (ActionEvent ae){ 

		}
	});
	//add menuitems to menu file
	options.add(wire);
	options.add(shadows);

	//add menus to menubar
	mb.add(file);
	mb.add(options);
	
	return mb;
}

//displays dialog which ask to close
public void close ()
{
	if (JOptionPane.showConfirmDialog(null, "Do you really want to close",
										"Close ModelLoader",
										JOptionPane.YES_NO_OPTION)
			== JOptionPane.YES_OPTION)
		System.exit(0);
}
		
//main method
public static void main(String[] args) { new TestFrame(); }	

}