Ok, here goes:

So here are the pieces you need:
        1) Some sort of Canvas3D, or some other component from which
you are going to receive key strokes.
        2) A class that extends the KeyAdapter class
        3) Some sort of command processor.
        4) A behavior for moving the viewPlatform around.

#1 I think is self explanatory, somewhere in your Java3D code you have
something like:
        Canvas3D canvas = new...

Now instanitiate your KeyAdapter class with:
        KeyAdapterClass canvasKeyAdapter =
                new KeyAdapterClass(commandProcessor);
where commandProcessor is a reference to your command processor class, I'll
get to that.

Now add your KA to your canvas with:
canvas.addKeyListener(canvasKeyAdapter);


So read the KeyAdapter java documents, but mine is attached to this email in the file canvasKeyAdapter.java. You basically want to ovveride the KeyPressed and KeyReleased and KeyTyped methods.

Ok, so my canvasKeyAdapter parses key events and then calls some command in
the command processor.  Like, 'up' key pressed, call
commandProcessor.moveForward();   The commandProcessor has a reference to
the behavior responsible for actually moving the view platform around, I'll
get to that.  See attached file   navCommandProcessor.java for
how I implemented the command processor.  You can safely ignore what
you don't need, as mine handles mouse and tracker input.


Ok, lastly you need a behavior to move the view platform around. This class is instantiated with a reference to the TransformGroup that controlls the view Platform. Get this with TransformGroup vpTransGroup = viewingPlatform.getViewPlatformTransform();

Then call your view platform behaviors constructor with a reference to this
object.  My vpb is also attached to this email in the file
viewPlatformBehavior.java.

Add the vpb to the scene graph.

Its not all that complicated.  You can, at the expense of modularity,
obviate the need for the command processor by just having the KeyAdapter
methods call commands in the viewPlatformBehavior.:

Sam










At 02:14 PM 6/21/2003 -0700, you wrote:
It would be very nice if you'd like to give me more
info and some samples since I still cannot get any
idea just from what you talked about.

Thank you very much!
-H.M


--- Sam Halperin <[EMAIL PROTECTED]> wrote: > One way of going is to scrap the canned keyNavigator > behavior > altogether. Trap keystrokes from the canvas with a > keyListener, then use a > custom behavior to transform the transformGroup > associated with the > viewPlatform. > Email me if you want some code samples or more > detailed info.

> Sam
>
> At 01:55 PM 6/21/2003 -0700, you wrote:
> >Dear all,
> >
> >I am wondering how I can implement smooth walk
> through
> >in a 3D architectural model which is stored in VRML
> or
> >X3D format and displayed using Xj3D.
> >
> >Currently I am using KeyNavigatorBehavior, but I
> >cannot control the distance of translation at each
> key
> >press(ex. up/down arrow key), also the angle of
> >rotation at each key press(ex. left/right arrow
> key)
> >
> >I know how to do such transformation in OpenGL, but
> >dont' know how to do in Java3D, everything seems
> >predefined, do I need to override some methods? and
> >how?
> >
> >any hints?
> >
> >Thanks!
> >
> >-H.M
> >
> >__________________________________
> >Do you Yahoo!?
> >SBC Yahoo! DSL - Now only $29.95 per month!
> >http://sbc.yahoo.com
> >
>
>===========================================================================
> >To unsubscribe, send email to [EMAIL PROTECTED]
> and include in the body
> >of the message "signoff JAVA3D-INTEREST".  For
> general help, send email to
> >[EMAIL PROTECTED] and include in the body of
> the message "help".
>
>
===========================================================================
> To unsubscribe, send email to [EMAIL PROTECTED]
> and include in the body
> of the message "signoff JAVA3D-INTEREST".  For
> general help, send email to
> [EMAIL PROTECTED] and include in the body of the
> message "help".


__________________________________ Do you Yahoo!? SBC Yahoo! DSL - Now only $29.95 per month! http://sbc.yahoo.com

===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff JAVA3D-INTEREST".  For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".
package bpv;

import java.awt.event.*;

/**
 * The command interpreter for the main 3d canvas.  Parses keystrokes
 * and sends them to the navCommandProcessor.
 * @see bpv.navCommandProcessor
 */

public class canvasKeyAdapter extends KeyAdapter{

        // The ncp implements the various movement and look commands that
        // are called by the KeyAdapter.
        private navCommandProcessor ncp;

        /* booleans for dealing with multiple key presses.*/
        private boolean shiftKeyPressedOnce = false;
        private boolean ctrlKeyPressedOnce = true;

        /* boolean for dealing with 'slide' (ctrl) modifier
         * A little weird since shift is sent to the ncp, but
         * alt is handled here. So be it.
         */
        private boolean slide = false;

        /**
         * Construct a canvasKeyAdapter with a reference to the navCommandProcessor.
         * @see bpv.navCommandProcessor
         */
        public canvasKeyAdapter(navCommandProcessor ncp) {
                this.ncp = ncp;
        }


        /**
         * Interpret keyPressed events generated by the main 3d canvas.
         * @param e A key event.
         */
        public void keyPressed(KeyEvent e) {
        if ( (e.getKeyCode() == java.awt.event.KeyEvent.VK_SHIFT) &&
                                (shiftKeyPressedOnce == false) ) {
                        ncp.setFastSpeed();
                        shiftKeyPressedOnce = true;
                }
                else if ( (e.getKeyCode() == java.awt.event.KeyEvent.VK_CONTROL) &&
                                ctrlKeyPressedOnce==false) {
                        slide = true;
                        ctrlKeyPressedOnce = true;
                }

                else if ( (e.getKeyCode() == java.awt.event.KeyEvent.VK_DOWN)) {
                        ncp.moveBack();
                }
                else if ( (e.getKeyCode() == java.awt.event.KeyEvent.VK_LEFT)) {
                        if(slide)
                                ncp.slideL();
                        else
                                ncp.changeDirectionL();
                }
                else if ( (e.getKeyCode() == java.awt.event.KeyEvent.VK_UP)) {
                        ncp.moveForward();
                }
                else if ( (e.getKeyCode() == java.awt.event.KeyEvent.VK_RIGHT)) {
                        if (slide)
                                ncp.slideR();
                        else
                                ncp.changeDirectionR();
                }
                else if(e.getKeyChar() == 'a' || e.getKeyChar() == 'A'){
                        ncp.lookUp();
                        }
                else if(e.getKeyChar() == 'z' || e.getKeyChar() == 'Z'){
                        ncp.lookDn();
                }

    }


        /**
         * Interpret keyReleased events from the main 3d canvas.
         * @param e A KeyEvent.
         */
        public void keyReleased(KeyEvent e) {
                if (e.getKeyCode() == java.awt.event.KeyEvent.VK_SHIFT) {
                        shiftKeyPressedOnce = false;
                        ncp.setRegularSpeed();
                }
                else if (e.getKeyCode() == java.awt.event.KeyEvent.VK_CONTROL) {
                        ctrlKeyPressedOnce = false;
                        slide = false;
                }
        }

        /**
         * Interpret keyTyped events from the main 3d canvas.
         * @param e A keyTyped event.
         */
        public void keyTyped(KeyEvent e) {
        }

}
package bpv;
import bpv.trackers.TrackerInterface;

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

/**
 * The navCommandProcessor processes commands such as mouse movements
 * and keystrokes received from the main 3d canvas display.  Here
 * the perspective object is updated and passed on to the collision
 * detection and terrain following routines.
 */

public class navCommandProcessor{
        /** The last known good perspective.  Changed into a Transform3D object
         * by the 'calculate' method in the perspective class.
         * @see bpv.perspective#calcTransform
         */
        private perspective last;

        /** The target perspective which is generated by calling the various
         * move to and look at commands in the navCommandProcessor.  Becomes
         * the last perspective when the target is modified by the collision
         * detection and terrain following routines and finally written to
         * the viewPlatform of the scene graph.
         */

        private perspective target;

        /**
         * An instance of the collision detection and terrain following engine.
         */
        private collisionAndTerrainDetection ctd;

        /**
         * A reference to the viewPlatformBehavior that does the actual writing
         * to the view platform
         */
        private viewPlatformBehavior vpb;

        /**
         * boolean for movement mode, true = normal movement speed, false
         * = regular movement speed.
         */
        private boolean fast = false;

        /**
         * boolean for look at mode, either mouse/kbd driven or tracker driven.
         */
        private boolean tracking = false;


        /** The move vector added or subtracted to form the target perspective.
         * Selected with call to setFastSpeed(), effecting the 'fast' boolean.
         */
        private Vector3f moveFastV = new Vector3f(0,0,.13f);

        /** The move vector added or subtracted to form the target perspective.
         * Selected with call to setRegularSpeed(), effecting the 'fast' boolean.
         */

        private Vector3f moveV = new Vector3f(0,0,.035f);

        /** The slide vector added or subtracted to form the target perspective.
         * Selected with a call to setFastSpeed().
         */
        private Vector3f slideFastV = new Vector3f(.13f, 0, 0);

        /** The slide vector added or subtracted to form the target perspective.
         * Selected with a call to setRegularSpeed().
         */
        private Vector3f slideV = new Vector3f(.035f, 0, 0);


        /**
         * Change direction regular speed increment.  Added or subtracted to the
         * perspective.direction.angle value.  Change in direction in walk
         * mode occurs about the y axis, while look at mode changes the
         * perspective.direction.lookatAA value about the X axis.
         */
        private float rotIncrement = .017f;

        /**
         * Change direction fast speed increment.  Added or subtracted to the
         * perspective.direction.angle value.  Change in direction in walk
         * mode occurs about the y axis, while look at mode changes the
         * perspective.direction.lookatAA value about the X axis.
         */

        private float fastRotIncrement = .04f;

        /**
         * The delta position represents the amount to add to the perspectives
         * position field.  It is calculated by the perspectives deltaLocation
         * method.
         * I don't know if this is any more efficient, but instead of creating
         * a new Vector3f for each delta position we just modify this existing
         * vector.
         */
        private Vector3f deltaLocationV = new Vector3f();

        /**
         * The tracker.  Null if not tracking.
         */
        private TrackerInterface tracker;

        /** The thread that calls the trackers getReading method and writes
         * it to the ncp's lookTracking method.
         */
        trackerThread tThread;

        /** Construct a navCommandProcessor with references to the collision
         * and terrain detection routines, a beginning perspective, and
         * a reference to the viewPlatform behavior.
         * @param ctd A reference to the collision and Terrain Detection routines.
         * @param initPerspective The initialisation viewpoint of the world.
         * @param vpb  A behavior which does the actual writing to the view
         * platform.
         */
        public navCommandProcessor(collisionAndTerrainDetection ctd,
                        perspective initPerspective, viewPlatformBehavior vpb) {
                //set the start position
                last = initPerspective;
                target = new perspective();
                this.ctd = ctd;
                this.vpb = vpb;
         }

        /**
         * Moves the view Platform forward by the current selected increment.
         * Bounces the new position off of the collision detection and terrain
         * following routine, then writes the perspective to the view platform.
         * @see bpv.navCommandProcessor#setFastSpeed
         * @see bpv.navCommandProcessor#setRegularSpeed
         */
        public void moveForward() {
                // check for move fast or slow and calculate the change in location
                if(fast) {
                        deltaLocationV =
                                last.deltaLocation(moveFastV, last.direction.angle);
                } else {
                        deltaLocationV =
                                last.deltaLocation(moveV, last.direction.angle);
                }
                // add the change in location to the location at the last position

                target.position.set(last.position);
                target.position.sub(deltaLocationV);


                //run collision detection and terrain following
                target =  ctd.collideDetect(target,last);

                // write the new perspective to the view platform.  The ...withCalc
                // converts the perspective into a valid affine transform3D.
                vpb.setTransformWithCalc(target);

                // update the 'last' position now that the target position has been
                // written to the view platform

                last.replaceWith(target);


        }

        /**
         * Moves the view Platform back by the current selected increment.
         * Bounces the new position off of the collision detection and terrain
         * following routine, then writes the perspective to the view platform.
         * @see bpv.navCommandProcessor#setFastSpeed
         * @see bpv.navCommandProcessor#setRegularSpeed
         */
        public void moveBack() {
                // check for move fast or slow and calculate the change in location
                if(fast) {
                        deltaLocationV =
                                last.deltaLocation(moveFastV, last.direction.angle);
                } else {
                        deltaLocationV =
                                last.deltaLocation(moveV, last.direction.angle);
                }
                // subtract the change in location to the location at the last position

                target.position.set(last.position);
                target.position.add(deltaLocationV);

                //run collision detection and terrain following
                target =  ctd.collideDetect(target,last);

                // write the new perspective to the view platform.  The ...withCalc
                // converts a perspective to a valid affine Transform3D
                vpb.setTransformWithCalc(target);

                // update the 'last' position now that the target position has been
                // written to the view platform

                last.replaceWith(target);


        }

        /**
         * Slides the view Platform left by the current selected increment.
         * Bounces the new position off of the collision detection and terrain
         * following routine, then writes the perspective to the view platform.
         * @see bpv.navCommandProcessor#setFastSpeed
         * @see bpv.navCommandProcessor#setRegularSpeed
         */

        public void slideL() {
                // check for move fast or slow and calculate the change in location
                if(fast) {
                        deltaLocationV =
                                last.deltaLocation(slideFastV, last.direction.angle);
                } else {
                        deltaLocationV =
                                last.deltaLocation(slideV, last.direction.angle);
                }
                // subtract the change in location to the location at the last position

                target.position.set(last.position);
                target.position.sub(deltaLocationV);

                //run collision detection and terrain following
                target =  ctd.collideDetect(target,last);

                // write the new perspective to the view platform.  The ...withCalc
                // converts a perspective to a valid affine Transform3D
                vpb.setTransformWithCalc(target);

                // update the 'last' position now that the target position has been
                // written to the view platform

                last.replaceWith(target);


        }

        /**
         * Slides the view Platform right by the current selected increment.
         * Bounces the new position off of the collision detection and terrain
         * following routine, then writes the perspective to the view platform.
         * @see bpv.navCommandProcessor#setFastSpeed
         * @see bpv.navCommandProcessor#setRegularSpeed
         */

        public void slideR() {
                // check for move fast or slow and calculate the change in location
                if(fast) {
                        deltaLocationV =
                                last.deltaLocation(slideFastV, last.direction.angle);
                } else {
                        deltaLocationV =
                                last.deltaLocation(slideV, last.direction.angle);
                }

                // add the change in location to the location at the last position
                target.position.set(last.position);
                target.position.add(deltaLocationV);


                //run collision detection and terrain following
                target =  ctd.collideDetect(target,last);

                // write the new perspective to the view platform.  The ...withCalc
                // converts a perspective to a valid affine Transform3D
                vpb.setTransformWithCalc(target);

                // update the 'last' position now that the target position has been
                // written to the view platform

                last.replaceWith(target);


        }

        /**
         * Rotate the view platform right.  This operation changes the
         * direction of the current perspective object, effecting the
         * move direction that is used to calculate the various move
         * and slide commands.
         * @see bpv.navCommandProcessor#setFastSpeed
         * @see bpv.navCommandProcessor#setRegularSpeed
         */
        public void changeDirectionR() {
                if(fast) {
                        target.direction.angle -= fastRotIncrement;
                } else {
                        target.direction.angle -= rotIncrement;
                }
                vpb.setTransformWithCalc(target);

                last.replaceWith(target);
        }


        public void changeDirectionR(float increment) {
                target.direction.angle-=increment;
                vpb.setTransformWithCalc(target);
                last.replaceWith(target);
        }



        /**
         * Rotate the view platform left.  This operation changes the
         * direction of the current perspective object, effecting the
         * move direction that is used to calculate the various move
         * and slide commands.
         * @see bpv.navCommandProcessor#setFastSpeed
         * @see bpv.navCommandProcessor#setRegularSpeed
         */
        public void changeDirectionL() {
                if(fast) {
                        target.direction.angle += fastRotIncrement;
                } else {
                        target.direction.angle += rotIncrement;
                }
                vpb.setTransformWithCalc(target);

                last.replaceWith(target);

        }

        public void changeDirectionL(float increment) {
                target.direction.angle+=increment;
                vpb.setTransformWithCalc(target);
                last.replaceWith(target);
        }

        /**
         * Rotate the view platform up.  This operation changes the lookAt
         * direction in the current perspective.  Since all modes are 'walk'
         * modes, this does not affect the movement direction.  Example, look
         * up at the ceiling, walk forward along the ground while still looking
         * up at the ceiling.  Rather than look up at the ceiling, move forward
         * along the look direction and fly towards the ceiling.
         * @see bpv.navCommandProcessor#setFastSpeed
         * @see bpv.navCommandProcessor#setRegularSpeed
         */

        public void lookUp() {
                if (fast) {
                        target.lookAtAA.angle +=fastRotIncrement;
                }
                else {
                        target.lookAtAA.angle += rotIncrement;
                }
                vpb.setTransformWithCalc(target);
                last.replaceWith(target);
        }

        public void lookUp(float increment) {
                target.lookAtAA.angle += increment;
                vpb.setTransformWithCalc(target);
                last.replaceWith(target);
        }



        /**
         * Rotate the view platform down.  This operation changes the lookAt
         * direction in the current perspective.  Since all modes are 'walk'
         * modes, this does not affect the movement direction.  Example, look
         * down at the floor, walk forward along the ground while still looking
         * down at the floor.  Rather than look down at the floor, move forward
         * along the look direction and fly down towards the floor.
         * @see bpv.navCommandProcessor#setFastSpeed
         * @see bpv.navCommandProcessor#setRegularSpeed
         */

        public void lookDn() {
                if (fast) {
                        target.lookAtAA.angle -=fastRotIncrement;
                }
                else {
                        target.lookAtAA.angle -= rotIncrement;
                }
                vpb.setTransformWithCalc(target);
                last.replaceWith(target);
        }


        public void lookDn(float increment) {
                target.lookAtAA.angle -= increment;
                vpb.setTransformWithCalc(target);
                last.replaceWith(target);
        }
        /**
         * Increase the various navigation increments to a larger value.
         */
        public void setFastSpeed() {
                fast = true;
        }

        /**
         * Decrease the various navigation increments to their regular value.
         */
        public void setRegularSpeed() {
                fast = false;
        }

        /** Set the amount the viewPlatform is transformed via the
         * various movement commands when fast speed is enabled.
         * @param increment The amount to move the platform with the movement
         * commands.
         */
        public void setFastSpeedMoveIncrement(float increment) {
                moveFastV = new Vector3f(0,0,increment);
                slideFastV = new Vector3f(3f, 0, increment);
        }

        /** Set the amount the viewPlatform is transformed via the
         * various movement commands when regular speed is enabled.
         * @param increment The amount to move the platform with the movement
         * commands.
         */
        public void setRegularSpeedMoveIncrement(float increment) {
                moveV = new Vector3f(0,0,increment);
                slideV = new Vector3f(0,0,increment);
        }


        /**
         * Set the amount the view platform is transformed viea
         * the various rotation commands when fast speed is enabled.
         * @param increment The amount to rotate the platform when using
         * the rotation commands.
         */

        public void setFastRotationIncrement(float increment) {
                fastRotIncrement = increment;
        }

        /**
         * Set the amount the view platform is transformed viea
         * the various rotation commands when regular speed is enabled.
         * @param increment The amount to rotate the platform when using
         * the rotation commands.
         */

        public void setRegularRotationIncrement(float increment) {
                rotIncrement = increment;
        }




        /**
         * Used to affect the look at direction when using a (head)tracker.
         * Does not affect the movement direction enabling the user to, for
         * example, look left and move forward while looking left.
         * @param quaternion The quaternion representation of the trackers
         * orientation data.
         */

        int foo =0;
        public void lookTracking(Quat4f quaternion) {
                System.out.println("commandProcessor.lookTracking... : " + quaternion +
                                " " + foo);
                foo++;
        }


        /**
         * Give the NCP a reference to the current TrackerInterface object.
         */
        public void setTracker(TrackerInterface tracker) {
                this.tracker=tracker;
        }

        /**
         * Enable tracking in the perspective objects.  Affects the way
         * the perspective object calculates the view platform transform.
         * @see bpv.perspective#setTracking
         */
        public void tracking(boolean enable) {
                if(enable) {
                        target.setTracking(enable);
                        last.setTracking(enable);
                        tThread = new trackerThread(this,tracker);
                        tThread.start();
                }else {
                        tThread.destroy();
                        tThread=null;
                }

        }

}


package bpv;
import javax.media.j3d.*;
import java.util.Enumeration;

/**
 * The behavior that does the actual writing of a transform to the
 * view platform transform group
 * */

public class viewPlatformBehavior extends Behavior {
        private TransformGroup viewPlatform;

        /**
         * Requires a reference to the main view platform
         * of the scene graph
         * @param viewPlatfrom The TransformGroup which is the parent
         * of the users view perspective.
         */

        public viewPlatformBehavior(TransformGroup viewPlatform) {
                this.viewPlatform = viewPlatform;
        }

        /**
         * Set the view platform to the Transform3D equivalent of a perspective
         * object.
         * @param p A perspective object
         * @see bpv.perspective
         */
        public void setTransformWithCalc(perspective p) {
                viewPlatform.setTransform(p.calcTransform());
        }

        /**
         * Set the view platform to a Transform3D
         * @param p A valid affine Transform3D
         */

        public void setTransform(Transform3D p) {
                viewPlatform.setTransform(p);
        }


        /**
         * I quote from the spec because I am not really sure how this works:
         * Initialize this behavior. Classes that extend Behavior must provide their
         * own initialize method.  NOTE: Applications should not call this method.
         * It is called by the Java 3D behavior scheduler.
         */

        public void initialize() {
                this.wakeupOn(new WakeupOnBehaviorPost(null,1));
        }

        /**
         * This is probably wrong, but since we are using the above methods
         * to activate the behavior, this method can be empty, but must be there
         * to fulfill the interface.  Also called by behavior scheduler, not by the
         * application.
         */
        public void processStimulus(Enumeration criteria) {
        }



}

Reply via email to