rotation question

Hi, I have what is probably a simple question and I’m learning Xith3D to use to create a game so expect many more!

I’m wondering how I can use the rotate function to rotate around the Z axis at specified X and Y coords. Instead of always rotating around (0,0). Sorry if this is in the docs somewhere I must have missed it, thanks!

Ok, I have another question already, its along the same lines so I’ll post it here as well:

I have my event listener set up already, and I’m wondering how I can get the X and Y coords of where the user clicks. I got the mouse coords using e.getX() and e.getY() however that doesn’t help me I need the X,Y coords on my game map. Thanks again.

To rotate around a particular axis, this is one way.

hero.getTransform().setRotation(new AxisAngle4f(new Vector3f(0, 0, 1), 3.14f))

It sounds to me like you have two transform3d nodes (one for rotation and one for translation) and that you have their positions in the scenegraph mixed up.

To convert mouse coords to world coords, you might need to consider that the (0,0) is at the top left of the canvas for the mouse and (0,0,0) is at the center. You can always do a hack conversion like this “(e.getX() - canvas.getWidth()/2)/3;” till you can figure out the trig to get the correct values of depth

[quote]To rotate around a particular axis, this is one way.

hero.getTransform().setRotation(new AxisAngle4f(new Vector3f(0, 0, 1), 3.14f))

It sounds to me like you have two transform3d nodes (one for rotation and one for translation) and that you have their positions in the scenegraph mixed up.

To convert mouse coords to world coords, you might need to consider that the (0,0) is at the top left of the canvas for the mouse and (0,0,0) is at the center. You can always do a hack conversion like this “(e.getX() - canvas.getWidth()/2)/3;” till you can figure out the trig to get the correct values of depth
[/quote]
Thank you for the reply, however I still can’t seem to get it working the way I want. What is the “hero” in that line of code?

Your saying the best way to get the X,Y coords in world is to convert from mouse coords using math? I’ll play with that idea some more and see if I can figure something out.

Here is my code so you get a better idea of what I’m trying to do, I want to rotate around viewX and viewY and it will only rotate around 0,0. If you notice any other problems, please comment. Thanks!


import javax.vecmath.*;
import java.awt.*;
import java.awt.event.*;

// Xith3D
import com.xith3d.scenegraph.*;
import com.xith3d.test.*;

// use Jogl
import com.xith3d.render.*;
import com.xith3d.render.jogl.*;
import com.xith3d.loaders.texture.*; // new

public class Xith implements KeyListener
{
      //Data to be determined later
      private int SCREEN_WIDTH = 1024;
      private int SCREEN_HEIGHT = 768;
      private int MAP_WIDTH = 10;
      private int MAP_HEIGHT = 10;
      private int STARTING_TILE_X = 5;
      private int STARTING_TILE_Y = 5;
      
      //Universe
      private VirtualUniverse universe;
      private View view;
      private BranchGroup scene;

      //VIEW
      private boolean isViewChangeScheduled = true;
      //Rotation
      private TransformGroup objRotate;
      private Transform3D rotate;
      private boolean isRotationScheduled = true;
      private float rotX = 0;
      private float rotY = 0;
      private float rotZ = 0;
      //Zoom/Translation
      private TransformGroup objTranslate;
      private Transform3D translate;
      
      private float camX = 0;
      private float camY = 0;
      private float camZ = 10f;
      
      private float viewX = STARTING_TILE_X;
      private float viewY = STARTING_TILE_Y;
      
      private static final float PI = 3.141592654f; 
      
    /**
     * Our own EventListener.
     */
    class EventListener implements AWTEventListener
    {
        public void eventDispatched(AWTEvent event)
        {
            if(event instanceof MouseEvent)
            {
                MouseEvent e = (MouseEvent) event;
                switch(e.getID())
                {
                    case MouseEvent.MOUSE_PRESSED: mousePressed(e); break;
                    case MouseEvent.MOUSE_RELEASED: mouseReleased(e); break;
                    case MouseEvent.MOUSE_DRAGGED: mouseDragged(e); break;
                }
            }
            else if(event instanceof KeyEvent)
            {
                KeyEvent e = (KeyEvent) event;
                switch(e.getID())
                {
                    case KeyEvent.KEY_TYPED: keyTyped(e); break;
                }
            }
        }
    }

      /**
       * Starts the application.
       */
      public static void main(String[] args)
      {
            new Xith();
      }

      public Xith()
      {
            // Texture and TextureLoader
            Texture2D textureGrass = null;
            TextureLoader tl = new TextureLoader();

            // specifying the paths for textures
            // there can be more than one path
            tl.registerPath("./");

            // load the texture, if the texture isn't there the
            // program immediatley exits and prints an error
            textureGrass = (Texture2D) tl.getMinMapTexture("textures/grass.png");

            // create the virtual universe and view
            createUniverse();

            // let objects along this path translate
            translate = new Transform3D();
            objTranslate = new TransformGroup(translate);
            scene.addChild(objTranslate);

            // let objects along this path rotate
            rotate = new Transform3D();
            objRotate = new TransformGroup(rotate);
            objTranslate.addChild(objRotate);
                        
            // create Cube
            Geometry terrain = createMap();
            Geometry wall = createWall();
            Appearance a = new Appearance();
            a.setTexture(textureGrass);
            Shape3D sh = new Shape3D(terrain, a);
            objRotate.addChild(sh);
            Shape3D sh2 = new Shape3D(wall, a);
            objRotate.addChild(sh2);

            // turn the scene into a render friendly format
            scene.compile();

            // create a canvas for our graphics
            RenderPeer rp = new RenderPeerImpl();
            CanvasPeer cp = rp.makeCanvas(null, SCREEN_WIDTH, SCREEN_HEIGHT, 32, false);
            Canvas3D canvas = new Canvas3D();
            canvas.set3DPeer(cp);

        Toolkit.getDefaultToolkit().addAWTEventListener(
                new EventListener(),   AWTEvent.KEY_EVENT_MASK
                                     | AWTEvent.MOUSE_EVENT_MASK
                                     | AWTEvent.MOUSE_MOTION_EVENT_MASK);

            //Add keylistener
            cp.getComponent().addKeyListener(this);

            // modify our view so we can see the cube
            view.addCanvas3D(canvas);
            view.startView();

            // main rendering loop
            while (true)
            {
                  view.renderOnce();

                  if (isViewChangeScheduled )
                        handleView();
                  if (isRotationScheduled )
                        handleRotation();
            }
      }

      private void createUniverse()
      {
            universe = new VirtualUniverse();

            // add a view to the universe
            view = new View();
            universe.addView(view);

            // add a locale
            Locale locale = new Locale();
            universe.addLocale(locale);

            // create a BranchGroup
            scene = new BranchGroup();
            locale.addBranchGraph(scene);
      }

      private void handleView()
      {            
            float distance = camZ;
            camY = viewY;
            //float z = camZ - (camZ * (float)(Math.sin(rotX)));
            camX = viewX;
            
            view.getTransform().lookAt(
                        new Vector3f(camX, camY, camZ),            // location of eye 
                        new Vector3f(viewX, viewY, 0),             // center of view
                        new Vector3f(0, 1, 0));                        // vector pointing up
            //translate.setTranslation(new Vector3f(transX, transY, transZ));
            isViewChangeScheduled = false;
            //objTranslate.setTransform(translate);
      }

      private void handleRotation()
      {      
            rotate.rotXYZ(rotX, rotY, rotZ);
            isRotationScheduled = false;
            objRotate.setTransform( rotate );      
      }
      
      public Geometry createMap()
      {
            Point3f[] coords = new Point3f[] { 
                        new Point3f(0, 0, 0), 
                        new Point3f(MAP_WIDTH, 0, 0), 
                        new Point3f(MAP_WIDTH, MAP_HEIGHT, 0), 
                        new Point3f(0, MAP_HEIGHT, 0)};
            TexCoord2f[] texCoords = new TexCoord2f[] {
                        new TexCoord2f(0f, 0f),
                        new TexCoord2f(MAP_WIDTH, 0f),
                        new TexCoord2f(MAP_WIDTH, MAP_HEIGHT),
                        new TexCoord2f(0f, MAP_HEIGHT) };
            
            QuadArray g = new QuadArray(coords.length, GeometryArray.COORDINATES | GeometryArray.TEXTURE_COORDINATE_2);
            g.setCoordinates(0, coords);
            g.setTextureCoordinates( 0, 0, texCoords );

            return g;
      }

      public Geometry createWall()
      {
            Point3f[] coords = new Point3f[] { 
                        new Point3f(5, 5, 0), 
                        new Point3f(6, 5, 0), 
                        new Point3f(6, 5, 3), 
                        new Point3f(5, 5, 3)};
            TexCoord2f[] texCoords = new TexCoord2f[] {
                        new TexCoord2f(0f, 0f),
                        new TexCoord2f(1f, 0f),
                        new TexCoord2f(1f, 1f),
                        new TexCoord2f(0f, 1f) };
            
            QuadArray g = new QuadArray(coords.length, GeometryArray.COORDINATES | GeometryArray.TEXTURE_COORDINATE_2);
            g.setCoordinates(0, coords);
            g.setTextureCoordinates( 0, 0, texCoords );

            return g;
      }
      
      public void keyPressed(KeyEvent e)
      {
            switch (e.getKeyCode())
            {
                  case KeyEvent.VK_INSERT :
                        changeTilt(-0.1f);
                        break;
                  case KeyEvent.VK_HOME :
                        changeTilt(0.1f);
                        break;
                  case KeyEvent.VK_END :
                        changeRotation(+0.2f);
                        break;
                  case KeyEvent.VK_DELETE :
                        changeRotation(-0.2f);
                        break;
                  case KeyEvent.VK_UP :
                        changeViewY(+0.1f);
                        break;
                  case KeyEvent.VK_DOWN :
                        changeViewY(-0.1f);
                        break;
                  case KeyEvent.VK_RIGHT :
                        changeViewX(0.1f);
                        break;
                  case KeyEvent.VK_LEFT :
                        changeViewX(-0.1f);
                        break;
                  case KeyEvent.VK_PAGE_UP :
                        changeZoom(-0.1f);
                        break;
                  case KeyEvent.VK_PAGE_DOWN :
                        changeZoom(0.1f);
                        break;
            }
      }

    public void mouseDragged(MouseEvent e)
    {}

    private void mousePressed(MouseEvent e)
    {
          //viewX=-1*(e.getX() - canvas.getWidth()/2)/3;
          //viewY=-1*(e.getY() - canvas.getHeight()/2)/3;
 
        isViewChangeScheduled=true;
    }

    private void mouseReleased(MouseEvent e)
    {}
      
      private void changeViewX( float change )
      {
            changeView( change, 0 );
      }
      
      private void changeViewY( float change )
      {
            changeView( 0, change );
      }

      private void changeView( float xChange, float yChange )
      {
            viewX += xChange;
            viewY += yChange;            
            isViewChangeScheduled = true;
      }

      private void changeZoom( float change )
      {
            camZ += change;
            isViewChangeScheduled = true;
      }
      
      private void changeTilt( float change )
      {
            rotX += change;
            isRotationScheduled = true;
      }
      
      private void changeRotation( float change )
      {
            rotZ += change;
            isRotationScheduled = true;
      }

      public void keyTyped(KeyEvent e)
      {}

      public void keyReleased(KeyEvent e)
      {}
}

You should make a Transform3D for the position
and another Transform3D where you put the rotation,
then you should write:


Transform3D position = new Transform3D();   // create new Transform3D
Transform3D rotation = new Transform3D();   // create new Transform3D
rotation.rotY(45);   // rotate Y 45 degrees
rotation.setTranslation(new Vector3f(100, 100, 100));   // rotation axis
position.mul(rotation);   // combining the both


This works for me, and the “new Vector3f(100, 100, 100)” is the position where you want your object to rotate around.

If you want your object to rotate around itself:


Transform3D position = new Transform3D();   // create new Transform3D
position.setTranslation(new Vector3f(100, 100, 100));
Transform3D rotation = new Transform3D();   // create new Transform3D
rotation.rotY(45);   // rotate Y 45 degrees
position.mul(rotation);   // combining the both


Where “new Vector3f(100, 100, 100)” is just the position of your object.

Good luck!

Alonzo

Also, to get a mouse look, you can do like this:


Transform3D position = new Transform3D();
Transform3D rotationX = new Transform3D();
Transform3D rotationY = new Transform3D();
rotationX.rotX(45);  // x angle
rotationY.mul(rotationX);
rotationY.rotY(45);  // y angle
position.setTranslation(new Vector3f(10, 10, 10));  // the position
position.mul(rotationY); 


(It will look much better)

Good luck!

Alonzo

Hi,

How can I get my camera to rotate around a point - say Vector3f(200f,0.0,10.0f ) around the Y Axis.
using View.getTransform() and still looking at that point
and maintaining the same distance from the point.
I’ve been trying to figure this out and I just can’t seem to get it.

I have tried:
Vector3f v = new Vector3f();
Object.getTransform().get(v);
Transform3D position = new Transform3D();
position.setTranslation(v);
Transform3D rotation = new Transform3D();
rotation.rotY(angle); position.mul(rotation);

        camView.setTransform(position);

please help

Maybe you could try the lookAt function


view.getTransform().lookAt(      new Vector3f(0, 120.0f, 1.0f), //Camera location
                                                      new Vector3f(0, 0, 0), //COV
                                                      new Vector3f(0, 1, 0)); //Up Vector

Dunno if this thread is still “alive” but there is a neat function i made for doing that.
It rotates about a Node but you can easily extract the relevant parts of it to suit your needs.

`
public BrachGroup rootBG; // <-- The root of your scenegraph…

/**
 * Rotates the camera about the selected node.
 * 
 * If <code>node</code> is null then rotation will be performed about the VirtualWorld origo.
 * Direction of the rotation is taken from <code>x</code> and <code>y</code>.
 * 
 * @param camera
 * @param node
 * @param x
 * @param y
 */
public void rotateCameraAboutNode(View camera, Node node, float x, float y) {
	Transform3D rotationLocation = new Transform3D();
	Transform3D cameraLocation = new Transform3D();
	Transform3D traslateLocation = new Transform3D();
	Matrix3f rotation1 = new Matrix3f();
	Matrix3f rotation2 = new Matrix3f();
	
	// Determine camera location
	camera.getTransform(cameraLocation);

	// Determine rotation point (node or vworld)
	if (node == null) {
		// for rotating about origo this works
		rootBG.getLocalToVworld(rotationLocation); // <-- rootBG is your scenegraph root

		// rotate
		rotation1.setIdentity();
		rotation2.rotX(y / 100.0f);
		rotation1.mul(rotation2);
		rotation2.rotY(x / 100.0f);
		rotation1.mul(rotation2);
		rotationLocation.setRotation(rotation1);
		rotationLocation.mul(cameraLocation);
		// set new camera transform
		cameraLocation.set(rotationLocation);
	} else {
		// for rotating about something else than origo we need slight
		// modifications to rotation code
		rootBG.getLocalToVworld(rotationLocation);
		node.getLocalToVworld(traslateLocation);

		// translate to rotation point
		rotationLocation.mul(traslateLocation);
		// rotate
		rotation1.setIdentity();
		rotation2.rotX(y / 100.0f);
		rotation1.mul(rotation2);
		rotation2.rotY(x / 100.0f);
		rotation1.mul(rotation2);
		rotation1.normalize();
		rotationLocation.setRotation(rotation1);
		// translate away from rotation point
		traslateLocation.invert();
		rotationLocation.mul(traslateLocation);
		rotationLocation.mul(cameraLocation);
		// set new camera transform
		cameraLocation.set(rotationLocation);
	}


	// In Java3D the transform sometimes got non-congruent but that hasnt happened in Xith3D.. Is it normalized in the xith core ???
	// the transform gets non-congruent so often that we might as well
	// normalize it every time
	// cameraLocation.normalize(); 

	try {
		camera.setTransform(cameraLocation);
	} catch (Exception e) {
		e.printStackTrace();
	}
}

`

Note that this rotation will be applied as if the [b]x[/b] and [b]y[/b] parameters were in the node’s coordinate space.
I guess it would require a quaternion rotation to get it work right in all cases, but that is something that is still beyond my comprehension…