Skip to main content

A newbie question about ViewPlatformBehavior

No replies
Joined: 2011-11-20

I'm trying to create a TBS in which the keyboard is used to manipulate the ViewPlatform. The idea is to have the view platform up in the air looking down at an angle on a wide landscape. Hitting the arrow keys moves the view platform but preserves the angled view. To give you a better idea, I am trying to replicate this: (just watch the first few seconds)

So here is how I designed it:

1. the landscape runs along the XY plane, with the Z axis pointing towards the sky.

2. a KeyBehavior class (extending ViewPlatformBehavior) controls the view platform.

3. in KeyBehavior's constructor, the view platform's TransformGroup (TG) is rotated by a certain angle to give it that angled view.

4. Moving the arrow keys should modify the X and Y coordinates while not changing the rotation or the Z coordinate; this preserves the angled view.

The problem is, moving the arrow keys changes the Z coordinate too due the the rotation; pressing the W key, for example, moves forward but raises the elevation as well, which is undesirable. I can't understand why this should happen. If anyone can suggest a solution, I would appreciate it very much.


edit: couldn't upload the file so I just copy and pasted:

package graphics;

import java.awt.AWTEvent;

import java.awt.AWTEvent.*;

import java.awt.event.*;

import java.util.ArrayList;

import java.util.Enumeration;


import javax.vecmath.*;

import com.sun.j3d.utils.universe.*;

import com.sun.j3d.utils.behaviors.vp.*;


* Creates a KeyBehavior object, which responds to the key presses as follows: <br>

* <br>

* WASD keys - moves the viewer's position and the point the viewer is looking at.

* The speed at which tbe viewpoint moves is proportional to the Z coordinate i.e.

* level of zoom. The viewpoint is moved in a way such that the angle of elevation of

* the viewpoint remains constant. <br>

* <br>

* Middle mouse wheel - zooms in and out. Zooming increases the Z coordinate as well as

* modifying the Y coordinate to maintain a constant angle of elevation. Zoom speed is

* proportional to the square of the current Z coordinate.


public class KeyBehavior extends ViewPlatformBehavior


private TransformGroup viewTG;

private WakeupOr wakeupOr;

private ArrayList<Integer> keyPressedList = new ArrayList<Integer>();

private static final double ANGLE_OF_ELEVATION = -Math.PI / 6;

private static final double INIT_POSN_Z = 15;

private static final double MOVE_STEP = 0.2;

private static final double ALT_MODIFIER = 5;

private static final int MOVE_RATE_DURING_REPEAT_PAUSE = 24;

private static final Vector3d LEFT = new Vector3d(-MOVE_STEP, 0, 0);

private static final Vector3d RIGHT = new Vector3d(MOVE_STEP, 0, 0);

private static final Vector3d UP = new Vector3d(0, MOVE_STEP, 0);

private static final Vector3d DOWN = new Vector3d(0, -MOVE_STEP, 0);

private static final double ZOOM_SPEED_MULTIPLIER = 8;

private static final double ZOOM_IN = -MOVE_STEP * ZOOM_SPEED_MULTIPLIER;

private static final double ZOOM_OUT = MOVE_STEP * ZOOM_SPEED_MULTIPLIER;

private static final double ZOOM_MAX = 200;

private static final double ZOOM_MIN = 3;

private static final Vector3d ALT_LEFT = new Vector3d(-MOVE_STEP * ALT_MODIFIER, 0, 0);

private static final Vector3d ALT_RIGHT = new Vector3d(MOVE_STEP * ALT_MODIFIER, 0, 0);

private static final Vector3d ALT_UP = new Vector3d(0, MOVE_STEP * ALT_MODIFIER, 0);

private static final Vector3d ALT_DOWN = new Vector3d(0, -MOVE_STEP * ALT_MODIFIER, 0);

private final int forwardKey = KeyEvent.VK_W;

private final int backKey = KeyEvent.VK_S;

private final int leftKey = KeyEvent.VK_A;

private final int rightKey = KeyEvent.VK_D;

private static Point3d lookAt = new Point3d(0, 0, 0.1);

private static final Vector3d normal = new Vector3d(0, 0, 1);

private Vector3d move = new Vector3d();

private Vector3d positionVec = new Vector3d();

private Transform3D t3d = new Transform3D();

private Transform3D move3d = new Transform3D();

private double zoom;

public KeyBehavior(TransformGroup viewTG)


double initY = -INIT_POSN_Z / Math.tan(ANGLE_OF_ELEVATION);

this.viewTG = viewTG;


t3d.setTranslation(new Vector3d(0, 0, INIT_POSN_Z));





WakeupCriterion[] wakeupCriterion = new WakeupCriterion[3];

wakeupCriterion[0] = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED);

wakeupCriterion[1] = new WakeupOnAWTEvent(KeyEvent.KEY_RELEASED);

wakeupCriterion[2] = new WakeupOnElapsedTime(MOVE_RATE_DURING_REPEAT_PAUSE);

wakeupOr = new WakeupOr(wakeupCriterion);


public void initialize()




public void processStimulus(Enumeration criteria)


int keyCode = -1;

int keyCodeIndex;

WakeupCriterion wakeup;

AWTEvent[] event;

while (criteria.hasMoreElements()) {

wakeup = (WakeupCriterion) criteria.nextElement();

if (wakeup instanceof WakeupOnAWTEvent) {

event = ((WakeupOnAWTEvent) wakeup).getAWTEvent();

for (int i = 0; i < event.length; i++) {

if(event[i] instanceof KeyEvent) {

keyCode = ((KeyEvent) event[i]).getKeyCode();

keyCodeIndex = keyPressedList.indexOf(keyCode);

switch(event[i].getID()) {

case KeyEvent.KEY_PRESSED:

if(keyCodeIndex == -1) {





case KeyEvent.KEY_RELEASED:

if(keyCodeIndex != -1) {







} else if(wakeup instanceof WakeupOnElapsedTime) {

if(!keyPressedList.isEmpty()) {







private void processKeyEvents()


move.set(0, 0, 0);

for(Integer keyCode : keyPressedList) {

switch(keyCode) {

case forwardKey:



case backKey:



case leftKey:



case rightKey:





move.scale(getZ() / INIT_POSN_Z);



private void moveTG(Vector3d move)


double zoom = getZ();

if(zoom + move.z > ZOOM_MAX) {

move.z = 200 - zoom;

} else if (zoom + move.z < ZOOM_MIN) {

move.z = 5 - zoom;








public void handleZoomEvent(MouseWheelEvent zoomEvent)


zoom = zoomEvent.getWheelRotation() == -1 ? ZOOM_IN : ZOOM_OUT;

zoom *= Math.pow(getZ() / INIT_POSN_Z, 1);

move.set(new Vector3d(0, 0, zoom));

//move.add(new Vector3d(0, zoom * Math.tan(ANGLE_OF_ELEVATION), 0));



private Vector3d getPositionVec()




return positionVec;


private Point3d getPositionPoint()


positionVec = getPositionVec();

return new Point3d(positionVec.x, positionVec.y, positionVec.z);


private double getZ()


return getPositionVec().getZ();