Skip to main content

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

Please note these java.net forums are being decommissioned and use the new and improved forums at https://community.oracle.com/community/java.
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 );
}

}