Skip to main content

keep camera moving along the floor regardless of where it is pointing at

No replies
adamtdisplay
Offline
Joined: 2011-02-02

The problem is i want 2 navigation functions like most games.

Keyboard for movement and i want the mouse/cursor to alter the lookAtPoint, however i believe the mouse is rotating the entire scene rather than just the lookAtPoint, so as a result when i go to navigate the camera position using the keyboard, i of course end up moving off the land and following the path i am looking at, which invariably is outer space.

In essence, i need the function of a game but for some reason am having problems. Bleow is the full code:

import javax.media.j3d.Node;
import paulscode.sound.SoundSystem;
import paulscode.sound.SoundSystemConfig;
import paulscode.sound.SoundSystemException;
import paulscode.sound.libraries.LibraryLWJGLOpenAL;
// (or import LibraryJOAL instead, to eliminate LWJGL overhead)
import paulscode.sound.libraries.LibraryJavaSound;
import paulscode.sound.codecs.CodecWav;
import paulscode.sound.codecs.CodecJOgg; // if you want to use .ogg files

import com.sun.j3d.utils.behaviors.keyboard.KeyNavigatorBehavior;
import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import com.sun.j3d.utils.geometry.ColorCube;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Robot;
import javax.media.j3d.Group;
import javax.media.j3d.GraphicsConfigTemplate3D;
import javax.media.j3d.Shape3D;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
//import javax.swing.Timer;
import java.awt.AWTException;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.LineArray;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3d;

import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.Material;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3f;

import com.sun.j3d.utils.universe.SimpleUniverse;
import java.util.ArrayList;
import java.util.Arrays;
import javax.media.j3d.PolygonAttributes;
import javax.media.j3d.QuadArray;
import javax.swing.Box;

// calculates the up vector and the view plane normal for a camera based on its current position and the
// transformation of two default up vector and VPN reference points.
public final class disPLAY7 extends JFrame implements Runnable
{

//creates the cube and places it at the position of the camera
Shape3D floor()
{
objRoot.setCapability( BranchGroup.ALLOW_CHILDREN_READ );
objRoot.setCapability( BranchGroup.ALLOW_CHILDREN_WRITE );
objRoot.setCapability( BranchGroup.ALLOW_CHILDREN_EXTEND );
// Create a Transformgroup to scale all objects so they
// appear in the scene.
TransformGroup floor = new TransformGroup();
Transform3D t3d = new Transform3D();

t3d.set(new Vector3d(1, -5, 1));
//t3d.set(new Vector3d(cameraPos));
t3d.setScale(40);
floor.setTransform(t3d);
objRoot.addChild(floor);

// Create the transform group node and initialize it to the
// identity. Enable the TRANSFORM_WRITE capability so that
// our behavior code can modify it at runtime. Add it to the
// root of the subgraph.
TransformGroup objTrans = new TransformGroup();
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
floor.addChild(objTrans);
// Create a simple shape leaf node, add it to the scene graph.
objTrans.addChild(new ColorCube());
return new Shape3D();
}

//creates the cube and places it at the position of the camera
Shape3D objScale()
{
objRoot.setCapability( BranchGroup.ALLOW_CHILDREN_READ );
objRoot.setCapability( BranchGroup.ALLOW_CHILDREN_WRITE );
objRoot.setCapability( BranchGroup.ALLOW_CHILDREN_EXTEND );
// Create a Transformgroup to scale all objects so they
// appear in the scene.
TransformGroup objScale = new TransformGroup();
Transform3D t3d = new Transform3D();
// t3d.set(new Vector3d(-3, 1, -5));
t3d.set(new Vector3d(cameraPos));
t3d.setScale(0.1);
objScale.setTransform(t3d);
objRoot.addChild(objScale);

// Create the transform group node and initialize it to the
// identity. Enable the TRANSFORM_WRITE capability so that
// our behavior code can modify it at runtime. Add it to the
// root of the subgraph.
TransformGroup objTrans = new TransformGroup();
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
objScale.addChild(objTrans);
// Create a simple shape leaf node, add it to the scene graph.
objTrans.addChild(new ColorCube());
return new Shape3D();
}

//creates the land
Shape3D createLand()
{
LineArray landGeom = new LineArray(44, GeometryArray.COORDINATES
| GeometryArray.COLOR_3);
float l = -50.0f;
for( int c = 0; c < 44; c += 4 )
{
landGeom.setCoordinate(c + 0, new Point3f(-50.0f, 0.0f, l));
landGeom.setCoordinate(c + 1, new Point3f(50.0f, 0.0f, l));
landGeom.setCoordinate(c + 2, new Point3f(l, 0.0f, -50.0f));
landGeom.setCoordinate(c + 3, new Point3f(l, 0.0f, 50.0f));
l += 10.0f;
}
Color3f c = new Color3f(0.1f, 0.8f, 0.1f);
for (int i = 0; i < 44; i++)
landGeom.setColor(i, c);
return new Shape3D(landGeom);
}
//creates a cube at the position of the camera (maybe?)
BranchGroup getCube()
{
System.err.println( "getCube() was just called, nextCubePos = " + nextCubePos );
BranchGroup cubeRoot = null;

cubeRoot = new BranchGroup();
TransformGroup objScale = new TransformGroup();
Transform3D t3d = new Transform3D();
t3d.set( new Vector3d( nextCubePos ) );
t3d.setScale(0.1);
objScale.setTransform(t3d);
cubeRoot.addChild(objScale);
TransformGroup objTrans = new TransformGroup();
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
objScale.addChild(objTrans);
objTrans.addChild(new ColorCube());

return cubeRoot;
}
public BranchGroup createSceneGraph( SimpleUniverse universe )
{
// Create the root of the branch graph
// BranchGroup objRoot = new BranchGroup();
TransformGroup vpTrans = null;
Vector3f translate = new Vector3f();
Transform3D T3D = new Transform3D();

//TransformGroup TG = null;

objRoot.addChild(createLand());
objRoot.addChild(objScale());
vpTrans = universe.getViewingPlatform().getViewPlatformTransform();
translate.set(0.0f, 0.3f, 0.0f);
T3D.setTranslation(translate);
vpTrans.setTransform(T3D);

// navigate the camera with the mouse
// MouseRotate myMouseRotate = new MouseRotate(vpTrans);
// myMouseRotate.setSchedulingBounds(new BoundingSphere(new Point3d(), 1000.0));
// objRoot.addChild(myMouseRotate);

KeyNavigatorBehavior keyNavBeh = new KeyNavigatorBehavior(vpTrans);
keyNavBeh
.setSchedulingBounds(new BoundingSphere(new Point3d(), 1000.0));
objRoot.addChild(keyNavBeh);
// Let Java 3D perform optimizations on this scene graph.
objRoot.compile();
return objRoot;
} // end of CreateSceneGraph method of KeyNavigatorApp
public disPLAY7()
{

try
{
SoundSystemConfig.addLibrary( LibraryLWJGLOpenAL.class ); // or use LibraryJOAL here
SoundSystemConfig.addLibrary( LibraryJavaSound.class );
SoundSystemConfig.setCodec( "wav", CodecWav.class );
SoundSystemConfig.setCodec( "ogg", CodecJOgg.class ); // if you want to use .ogg files
}
catch( SoundSystemException e )
{
System.err.println( "error linking with the SoundSystem plug-ins" );
}
//initialize sound system:
soundSystem = new SoundSystem();
//place & play a sound:
soundSystem.quickPlay( false, "strike.wav", true, 30,0,-50, SoundSystemConfig.ATTENUATION_ROLLOFF, 1f );

canvas = initializeCanvas();
universe = new SimpleUniverse( canvas );
BranchGroup scene = createSceneGraph(universe);
universe.addBranchGraph(scene);
// Create the content for the virtual universe.
worldRoot = createWorldObjects();

universe.addBranchGraph( worldRoot );

lookAtPoint = new Point3d( 0.0, 0.0, -1.0 );
upPoint = new Point3d( 0.0, 1.0, 0.0 );

this.getContentPane().setLayout(
new BoxLayout( this.getContentPane(), BoxLayout.Y_AXIS ) );
this.getContentPane().add( canvas );
canvas.addMouseListener
(
new MouseAdapter()
{

/**
* The mouseClicked on this mouse listener is where the work for
* calculating the up vector and the view plane normal.
*/
public void mouseClicked( MouseEvent event )
{
if( event.getButton() == MouseEvent.BUTTON3 )
{
// if right-click, end the application
alive = false;
return;
}
synchronized( threadSync ) // synchronizes the two threads
{
// Move the camera.
TransformGroup viewPlatformTG =
universe.getViewingPlatform().getViewPlatformTransform();
Transform3D cameraT3D = new Transform3D();
Vector3d cameraPos = new Vector3d();
viewPlatformTG.getTransform( cameraT3D );
cameraT3D.get( cameraPos );
System.err.println( "location vector = " + cameraPos );
soundSystem.setListenerPosition( (float)cameraPos.x,(float)cameraPos.y,(float)cameraPos.z);
// Calculate the "up" vector.
Point3d newUpPoint = new Point3d();
cameraT3D.transform( upPoint, newUpPoint );
Vector3d up = new Vector3d();
up.x = newUpPoint.x - cameraPos.x;
up.y = newUpPoint.y - cameraPos.y;
up.z = newUpPoint.z - cameraPos.z;
up.normalize();
System.err.println( "up vector = " + up );

//don't allow player to walk off the edge of the world
if (cameraPos.x < -FLOOR_SIZE/2)
cameraPos.x = -FLOOR_SIZE/2;
else if (cameraPos.x > FLOOR_SIZE/2)
cameraPos.x = FLOOR_SIZE/2;

if (cameraPos.z < -FLOOR_SIZE/2)
cameraPos.z = -FLOOR_SIZE/2;
else if (cameraPos.z > FLOOR_SIZE/2)
cameraPos.z = FLOOR_SIZE/2;

// Calculate the "vpn" or direction the camera is pointing.

Point3d newLookAtPoint = new Point3d();
cameraT3D.transform( lookAtPoint, newLookAtPoint );
Vector3d vpn = new Vector3d();
vpn.x = newLookAtPoint.x - cameraPos.x;
vpn.y = newLookAtPoint.y - cameraPos.y;
vpn.z = newLookAtPoint.z - cameraPos.z;
vpn.normalize();
System.err.println( "viewing vector = " + vpn );
soundSystem.setListenerOrientation( (float)vpn.x, (float)vpn.y, (float)vpn.z, (float)up.x, (float)up.y, (float)up.z);
nextCubePos = new Vector3d();
double cubePosOffset = 1.0d;
nextCubePos.x = cameraPos.x + ( vpn.x * cubePosOffset );
nextCubePos.y = cameraPos.y + ( vpn.y * cubePosOffset );
nextCubePos.z = cameraPos.z + ( vpn.z * cubePosOffset );

}
}
}
);
this.setVisible( true );
this.setSize( new Dimension( 300, 375 ) );
new Thread( this ).start(); // starts up the main loop thread ( see method run() )
}
/**
* Set the position of the camera.
*/

private void setCameraPosition( float x, float y, float z )
{
synchronized( threadSync ) // synchronizes the two threads
{
Transform3D vt = new Transform3D();
Point3d eye = new Point3d( x, y , z );
Point3d center = new Point3d( 0, 0, 0 );
Vector3d up = new Vector3d( 0.0, 1.0, 0.0 );
vt.lookAt( eye, center, up );
vt.invert( );
vt.setTranslation( new Vector3d( eye.x, eye.y, eye.z ) );
universe.getViewer().getViewingPlatform( ).
getViewPlatformTransform( ).setTransform( vt );
cameraPos = new Vector3d( x, y, z );
nextCubePos = new Vector3d( x, y, z );
}
soundSystem.setListenerPosition( x, y, z );
}
/**
* Initialize a Canvas3D with default graphics configuration for user's
* system.
*
* @return a <code>Canvas3D</code> value
*/
private Canvas3D initializeCanvas()
{
GraphicsConfigTemplate3D tmpl = new GraphicsConfigTemplate3D( );
GraphicsEnvironment env =
GraphicsEnvironment.getLocalGraphicsEnvironment( );
GraphicsDevice device = env.getDefaultScreenDevice( );
GraphicsConfiguration config = device.getBestConfiguration( tmpl );
Canvas3D canvas3D = new Canvas3D( config );
return canvas3D;
}
private BranchGroup createWorldObjects()
{
BranchGroup root = new BranchGroup();
root.setCapability( BranchGroup.ALLOW_DETACH );
root.setCapability( Group.ALLOW_CHILDREN_EXTEND );
root.setCapability( Group.ALLOW_CHILDREN_READ );
root.setCapability( Group.ALLOW_CHILDREN_WRITE );
root.addChild( createLand() );
return root;
}
/**
* Main method for application.
*/
public static void main( String[] args )
{
new disPLAY7();
}
// ATTRIBUTES
//
/** A Simple 3D virtual world. */
private SimpleUniverse universe;
/** Component to paint contents of virtual world. */
private Canvas3D canvas;
/** Branch group for adding world objects. */
private BranchGroup worldRoot;
/** Points used to calculate the VPN. */
private Point3d lookAtPoint;
private Point3d upPoint;
SoundSystem soundSystem = null; // initialize SoundSystem later
Vector3d cameraPos = new Vector3d();
Vector3d nextCubePos = new Vector3d();
BranchGroup objRoot = new BranchGroup();
/** Used to prevent both threads from trying to access the same resources simultaneously */
final Object threadSync = new Object();
boolean alive = true;

//checkerfloor
private final static int FLOOR_SIZE = 100;
// colors for axis and text
private final static Color3f medRed = new Color3f(0.8f, 0.4f, 0.3f);
private final static Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
// single instance variable, to be able to add to scene graph
private BranchGroup floorBG;

/**
* The main loop, controls the application
*/
@Override
public void run()
{
//creates a robot to automatically click the mouse over the screen when the program is launched
Robot robot = null;
try
{
robot = new Robot();
}
catch( AWTException e )
{
e.printStackTrace();
alive = false; // can't work without the robot, so prevent the main loop from starting
}
int robotEvent = 0; // (can be removed when the "robot" stuff below is removed)

long currentTime = System.currentTimeMillis(); // current time; used for timed events
long lastRobotEventTime = currentTime; // milliseconds since the last "robot" mouse event
long lastCubeEventTime = currentTime; // milliseconds since the last cube was drawn

while( alive ) // to end the loop, simply set "alive = false" from anywhere
{
currentTime = System.currentTimeMillis(); // update the time
if( robotEvent == 0 ) // the first robot event is a mouseMove
{
if( currentTime - lastRobotEventTime >= 5000 ) // wait 5 seconds before this event
{
// robot.mouseMove( 250, 250 );
lastRobotEventTime = currentTime; // reset the robot event timer
robotEvent++; // increment the robot event counter
}
}
else if( robotEvent <= 20 ) // the next 20 robot events are mousePress, mouseRelease
{
if( currentTime - lastRobotEventTime >= 1000 ) // wait 1 second between robot events
{
robot.mousePress( InputEvent.BUTTON1_MASK );
robot.mouseRelease( InputEvent.BUTTON1_MASK );
lastRobotEventTime = currentTime; // reset the robot event timer
robotEvent++; // increment the robot event counter
}
}
else // the last robot event is to shut down the application
{
alive = false; // tells the main loop to stop
}

//timed cube generation events
if( currentTime - lastCubeEventTime >= 1000 ) // wait 5 seconds between events
{
synchronized( threadSync ) // synchronizes the two threads
{
BranchGroup newCube = getCube(); // create a new cube
objRoot.addChild( newCube ); // add the cube to the scene
}

lastCubeEventTime = currentTime; // reset the cube event timer
}
try{Thread.sleep(10);} // Sleep a tiny bit to give the CPU a break
catch( InterruptedException ie ){} // don't care
} // end of the main loop; once it is done, shut down.
soundSystem.cleanup();
System.exit( 0 );
}

}