Hi all,
I seem to be getting closer to getting a working demo of a cameralook. I pulled some code from another post which was doing something similar and added it into a modified version of MouseInteraction.java which I am basing the demo onhttp://www.java-gaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=xith3d;action=display;num=1077631615.
The code more or less does what I am asking except it has two bugs still which I can’t figure out.
-
It seems to reset the camera perspective when you move to a different kind of camera movement. I tried updating the “trans” values with the new location but this didn’t work for me.
-
If you look carefully I think I am getting gimbel lock (I think this is what it is called) which is causing some problems on the rotations around 90degrees.
The code below has a main method and can be run without modification. Anyone have any suggestions for how to fix these two problems? I think this would be a valuable demo for the xith3d project since it seems other people have both A) had similar problems B) are interested in some demo code which addresses this.
import java.awt.*;
import java.awt.event.*;
import javax.vecmath.*;
// Xith3D
import com.xith3d.scenegraph.*;
import com.xith3d.test.*;
// use Jogl
import com.xith3d.loaders.texture.TextureLoader;
import com.xith3d.render.*;
import com.xith3d.render.jogl.*;
public class MouseInteraction
{
// current rotation
private float rotX = 0;
private float rotY = 0;
private float rotZ = 0;
// temporary rotation (used while dragging)
private float rotXTmp = 0;
private float rotYTmp = 0;
private float rotZTmp = 0;
// rotation part of our scenegraph
private TransformGroup objRotate;
private Transform3D rotate;
// current translation
private float transX = 0;
private float transY = 0;
private float transZ = 0;
// temporary translation (used while dragging)
private float transXTmp = 0;
private float transYTmp = 0;
private float transZTmp = 0;
// translation part of our scenegraph
private TransformGroup objTranslate;
private Transform3D translate;
View view = null;
VirtualUniverse universe = null;
// saves the cursor position when user starts to drag
private int startDragX;
private int startDragY;
// schedule actions
private boolean isRotationScheduled = false;
private boolean isTranslationScheduled = false;
BranchGroup scene = null;
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;
}
}
}
}
public static void main(String[] args)
{
new MouseInteraction();
}
public MouseInteraction()
{
universe = new VirtualUniverse();
view = new View();
universe.addView(view);
Locale locale = new Locale();
universe.addLocale(locale);
scene = new BranchGroup();
locale.addBranchGraph(scene);
translate = new Transform3D();
objTranslate = new TransformGroup(translate);
scene.addChild(objTranslate);
rotate = new Transform3D();
objRotate = new TransformGroup(rotate);
objTranslate.addChild(objRotate);
// create Cube & plane
Geometry g = Cube.createCubeViaTriangles(0, 0, 0, 1, true);
Shape3D cube = new Shape3D(g, new Appearance());
objRotate.addChild(cube);
addPlane();
scene.compile();
RenderPeer rp = new RenderPeerImpl();
CanvasPeer cp = rp.makeCanvas(null, 640, 480, 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);
// modify our view so we can see the cube
view.addCanvas3D(canvas);
transX = 0;
transY = 0;
transZ = 10;
view.getTransform().lookAt(new Vector3f( transXTmp, transYTmp, transZ), // location of eye
new Vector3f( 0, 0, 0), // center of view
new Vector3f( 0, 1, 0)); // vector pointing up
while(true)
{
view.renderOnce();
if(isRotationScheduled)
{
performRotation();
isRotationScheduled = false;
}
if(isTranslationScheduled)
{
performTranslation();
isTranslationScheduled = false;
}
}
}
private void keyTyped(KeyEvent e)
{
switch(e.getKeyChar())
{
case 27: System.exit(0); break;
}
}
public void addPlane(){
Appearance groundApp = new Appearance();
groundApp.setPolygonAttributes(
new PolygonAttributes(
PolygonAttributes.POLYGON_FILL,
PolygonAttributes.CULL_NONE,
0));
float k = 2f;
float w = 2f;
float x1 = -2f;
float x2 = 2f;
float y = 0f;
float z1 = -w;
float z2 = w;
float tsx = k * 1f;
float tsy = k * 1f;
Shape3D shape = new Shape3D();
Geometry geom =
TestUtils.createQuad(
new Point3f(x1, z1, y),
new Point3f(x1, z2, y),
new Point3f(x2, z2, y),
new Point3f(x2, z1, y),
tsx,
tsy);
shape.setAppearance(groundApp);
shape.setGeometry(geom);
objRotate.addChild(shape);
}
public void mouseDragged(MouseEvent e)
{
switch(e.getModifiers())
{
case MouseEvent.BUTTON1_MASK: leftDrag(e); break;
case MouseEvent.BUTTON2_MASK: middleDrag(e); break;
case MouseEvent.BUTTON3_MASK: rightDrag(e); break;
}
}
private void mousePressed(MouseEvent e)
{
startDragX = e.getX();
startDragY = e.getY();
}
private void mouseReleased(MouseEvent e)
{ rotX = rotXTmp;
rotY = rotYTmp;
rotZ = rotZTmp;
transX = transXTmp;
transY = transYTmp;
transZ = transZTmp;
}
private void leftDrag(MouseEvent e)
{
rotXTmp = rotY + (e.getY() - startDragY)/100f;
rotYTmp = rotX + (e.getX() - startDragX)/100f;
isRotationScheduled = true;
}
private void middleDrag(MouseEvent e)
{ transZTmp = (transZ + (e.getY() - startDragY)/100f);
isTranslationScheduled = true;
}
private void rightDrag(MouseEvent e)
{
transXTmp = -(transX + (e.getX() - startDragX)/100f);
transYTmp = -(transY - (e.getY() - startDragY)/100f);
isTranslationScheduled = true;
}
private void performRotation()
{ float cos = (float)Math.cos(rotXTmp);
float x = cos*(float)Math.cos(rotYTmp) * transZTmp;
float y = (float)Math.sin(rotXTmp) * transZTmp;
float z = cos*(float)Math.sin(rotYTmp) * transZTmp;
view.getTransform().lookAt(new Vector3f(x,y,z), // location of eye
new Vector3f( 0, 0, 0), // center of view
new Vector3f( 0, 1, 0)); // vector pointing up
}
private void performTranslation()
{ view.getTransform().setTranslation(new Vector3f(transXTmp, transYTmp, transZTmp));
}
}
P.S. Don: One of the only problems with thre rotation the way you suggested is it doesn’t maintain a camera perspective based on the origin.
Thanks,
Rob Leclerc