Need help removing last mistakes of my basic game

Hi,

I’ve asked several questions in different threads in this forums and I got many answers and suggestions, that have helped to make what you can see in this examples:

  1. Only ship moves and rotates: http://www.kingsware.de/j3d/gameRot2.zip (use mouse for rotation, strg for Fwd-movement and the Arrowkeys for Sliding up/left/right/down)
  2. The ship rotates and moves and the view follows: http://www.kingsware.de/j3d/gamerot3.zip (use mouse for rotation, strg for Fwd-movement and the Arrowkeys for Sliding up/left/right/down)

In the first example you can see, that my ship rotates correctly around his local x- and y-axis and moves relatively to the rotation!!! So this problem is solved!!!
In the second example you can see that the View seems to follow the ship correctly, because the ship is everytime at the same point in the window and even the Perspective to the ship doesn’t change. But although I didn’t change the Movement & rotation code of my Ship (processShipTransform), both ship and view don’t rotate and move correctly!

Problems:

  1. There is a rotation around the z-axis when you try to rotate up and down. This problem exists only when you had rotated to the left or to the right (around the x-axis) first. So only at a “x-rotation != 0” the ship and view rotates around the z-axis to!
  2. Movement and rotation is stuttering, when using wakeupOnElapsedFrames and the movement and rotation depends on passed time between frames(e.g. MeterPerSecond/FramesPerSecond).
    2.1 Movement/Rotation without using the timebased movement does NOT flicker(e.g. MeterPerSecond/CONSTANTFRAMERATE).
    2.2 When using WakeupOnElapsedTime(40) this problem does not exist, but updaterate wouldn’t depend on machinespeed anymore!
  3. The View follows the ship directly. I’d like to have smoothed camera movement. The View should accelerate a littlebit slower than the ship (rotation & movement)

In the next Entry I show you most of the code used in the 2. example! Only difference in the 1. example is that there is an empty Transform3D returned by “processViewTransform”!

It would be nice if anyone could help me with this small mistakes (perhaps reply a little codecorrection ;))!

Thanks to all of you (especially endolf)!

Don’t have a too deep look at my bad English, please! I’m not only learning Java3d at all ;)!

Greets,
Juan

Code in GameUpdater class:


private Transform3D processShipTransform(float fps) {
  //The change of position! x1, x2... is set in another method
  positionChange.x = x1 + x2;
  positionChange.y = y1 + y2;
  positionChange.z = z;

  /* The rotation! rY = -(e.getY()-(height/2)) and rX = ((e.getX()-(width/2)) (form the MouseEvent) */
  xAngle += (rY/(100.0f*fps)); // * yFactor;
  yAngle += -(rX/(100.0f*fps)); // * xFactor;
  
  //Rotation
  rotX3d.rotX(xAngle);
  rotY3d.rotY(yAngle);
  rotZ3d.rotZ(0.0f);
  rotXY3d.mul(rotX3d, rotY3d);
  rotXYZ3d.mul(rotXY3d, rotZ3d);
  
  
  //Die rotation an vpShipTrans3d weitergeben
  vpShipTrans3d = new Transform3D(rotXYZ3d);
  
  //Füge die Rotation in die Bewegung ein!!!
  rotXYZ3d.transform(positionChange);
  
  newPosition.x = oldPosition.x + positionChange.x;
  newPosition.y = oldPosition.y + positionChange.y;
  newPosition.z = oldPosition.z + positionChange.z;
  
  oldPosition.x = newPosition.x;
  oldPosition.y = newPosition.y;
  oldPosition.z = newPosition.z;

  rotXYZ3d.setTranslation(newPosition);
  
  return rotXYZ3d;
}/*Motion of the Ship END */ 


 //Move the view
 private Transform3D processViewTransform(float fps) { 
  //Rotation
  vpXAngle += (rY/(100.0f*fps)); 
  vpYAngle += -(rX/(100.0f*fps));
  
  
  vpRotX3d.rotX(vpXAngle);
  vpRotY3d.rotY(vpYAngle);
  vpRotZ3d.rotZ(0.0f);
  vpRotXY3d.mul(vpRotX3d, vpRotY3d);
  vpRotXYZ3d.mul(vpRotXY3d, vpRotZ3d);
  
  vpLocalPosition.x = vpSTARTX; //0.0f;
  vpLocalPosition.y = vpSTARTY; //50.0f;
  vpLocalPosition.z = vpSTARTZ; //130.0f;
  
  vpShipTrans3d.transform(vpLocalPosition);
  
  vpNewPosition.x = newPosition.x + vpLocalPosition.x; 
  vpNewPosition.y = newPosition.y + vpLocalPosition.y; 
  vpNewPosition.z = newPosition.z + vpLocalPosition.z; 
  
  vpRotXYZ3d.setTranslation(vpNewPosition);
  
  return vpRotXYZ3d;

 }//END processViewTransform


 public void update(float fps) {
   //Move & rotate the Ship
   trans3D = processShipTransform(fps);
   //Move & rotate the View (follow the ship)
   vpTrans3D = processViewTransform(fps);

   //Update the Transformgroups of the View and the Ship!
   vpTrans.setTransform(vpTrans3D);
   //Der Ziel-TransformGroup die Position einspeisen ;) 
   targetTG.setTransform(trans3D);
 }

End of Code in GameUpdater class

Code of GameUpdateBehavior class:



public class GameUpdaterBehavior extends Behavior  {

  private GameUpdater updater;
  private WakeupOnElapsedFrames wakeupCondition = new WakeupOnElapsedFrames(0);
  
  private long oldTime  = 0;
  private long newTime  = 0;
  private long timeDiff = 0;
  private float fps       = 0.0f;
  
  public GameUpdaterBehavior(GameUpdater updater) {
    this.updater = updater;
  }

  public void initialize() {
    oldTime = J3DTimer.getValue();
    newTime = J3DTimer.getValue();
    wakeupOn(wakeupCondition);
  }

  public void processStimulus(Enumeration criteria) {
    newTime = J3DTimer.getValue();
    timeDiff = newTime - oldTime;
    oldTime = newTime;
    fps = 1000000000.0f/timeDiff;
        
    updater.update(fps);

    //for the next time:      
    wakeupOn(wakeupCondition);
  }
}

End of Code in GameUpdaterBehavior

Code in MainClass:


      public MainClass() {
            //initiallisiere ein Canvas3D-Objekt und füge es in den MainFrame ein
            setLayout(new BorderLayout());
            
            GraphicsConfigTemplate3D template = new GraphicsConfigTemplate3D();
               cfg = GraphicsEnvironment.getLocalGraphicsEnvironment().
             getDefaultScreenDevice().getBestConfiguration(template);
                  canvas3d = new Canvas3D(cfg)
            
            add("Center", canvas3d);
            
            canvas3d.addKeyListener(new KeyListener() {
                  public void keyReleased(KeyEvent e) {
                        key_Rel(e);
                  }
                  
                  public void keyPressed(KeyEvent e) {
                        key_Pres(e);
                  }
                  
                  public void keyTyped(KeyEvent e) {
                        
                  }
            });
            canvas3d.addMouseMotionListener(new MouseMotionListener() {
                  public void mouseDragged(MouseEvent e) {
                        
                  }
                  
                  public void mouseMoved(MouseEvent e) {
                        mouse_Mov(e);
                  }
            });
            canvas3d.requestFocusInWindow();
            initGame();
      }
      
      public void initGame() {
            //Appearanceobjekt für die Scene
            PolygonAttributes polyAttr = new PolygonAttributes();
          polyAttr.setCullFace(PolygonAttributes.CULL_NONE);
          Appearance objAppear = new Appearance();
            objAppear.setPolygonAttributes(polyAttr);
            
            //die Scenegraphs erstellen
            ShipInit initShip = new ShipInit(ShipInit.iSHIP_TYPE_A, new Vector3f(0.0f, 10.0f, 0.0f));
            SceneInit initScene = new SceneInit();
            
            //ACHTUNG STRING FILENAME MUSS NOCH DURCH KONSTANTE WIE BEI SHIPINIT ERSETZT WERDEN!!!
            BranchGroup scene      =      initScene.load("./models/Level/level1.obj", new Vector3f(0.0f, -80.0f, 0.0f), objAppear);
            BranchGroup ship      =      initShip.initShipSceneGraph();
            
            //VirtualUniverse initiallisieren und canvas3d hinzufügen
            UniverseBuilder universe = new UniverseBuilder(canvas3d);
            
            //starte das Behaviorobjekt
            //updater = new GameUpdater(initShip.shipTG, initShip.shipRotTG, universe.vpTrans);
            updater = new GameUpdater(initShip.shipTG, initShip.shipRotTG, universe.vpTrans);
            updaterBehavior = new GameUpdaterBehavior(updater);
            
            updaterBehavior.setSchedulingBounds(new BoundingSphere(new Point3d(0.0d,0.0d,0.0d), 400.0d));
            
            initShip.shipTG.addChild(updaterBehavior);
            
            scene.compile();
            ship.compile();
            
            //SceneGraph zum universum hinzufügen
            universe.addBranchGraph(scene);
            universe.addBranchGraph(ship);
      }
      
      public void key_Rel(KeyEvent e) {
            int keyCode = e.getKeyCode();
            updater.setKeyIsPressed(keyCode, false);
      }
      
      public void key_Pres(KeyEvent e) {
            int keyCode = e.getKeyCode();
            updater.setKeyIsPressed(keyCode, true);
      }
      
      public void mouse_Mov(MouseEvent e) {
            updater.setMouseMoved((e.getX()-(width/2)), -(e.getY()-(height/2)));
      }

End of Code in MainClass

Code in ShipInit:


      //SceneGraph
      public BranchGroup load(int shipType, Vector3f position) { //, Appearance objAppear) {
        //Den Schifftyp auswählen
            switch(shipType) {
                  case iSHIP_TYPE_A: filename = sShip_Type_A;
                        break;
                  default:
                        break;
            }
            
            //Den root des Graphen erstellen
            BranchGroup objRoot = new BranchGroup();
            
            //Die Transformgroup für die Position des Objektes
            TransformGroup objPosition = new TransformGroup();
        
        //Position einstellen
        Transform3D t3dPosition = new Transform3D();
        t3dPosition.set(position);
        //das transform3d objekt der transformgroup hinzufügen
        objPosition.setTransform(t3dPosition);
        //die transformgroup dem root hinzufügen
        objRoot.addChild(objPosition);
            
            int flags = ObjectFile.LOAD_ALL;
            
            ObjectFile f = new ObjectFile();
            Scene s = null;
            try {
                  s = f.load(filename);
            }
            catch(FileNotFoundException e) {
                  System.err.println(e);
                  System.exit(1);
            }
            catch(ParsingErrorException e) {
                  System.err.println(e);
                  System.exit(1);
            }
            catch(IncorrectFormatException e) {
                  System.err.println(e);
                  System.exit(1);
            }
            
            //das Objekt der transformgroup zufügen      
            objPosition.addChild(s.getSceneGroup());
            
            return objRoot;
      }
      
      //Schiff initialisieren
      public BranchGroup initShipSceneGraph() {
            //Root initialisieren
            BranchGroup shipRoot = new BranchGroup();
            
            //TransformGroup für initialisieren
            shipTG = new TransformGroup();
            shipTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
            shipTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
            //shipRotTG has no use will be removed later!!!
            shipRotTG = new TransformGroup();
            shipRotTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
            shipRotTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
            
            //Den ShipSceneGraph erstellen
            shipRoot.addChild(shipTG);
            shipTG.addChild(shipRotTG);
            shipRotTG.addChild(load(shipType, position));
            
            return shipRoot;
      }

End of Code in ShipInit

Code in UniverseBuilder:


      public UniverseBuilder(Canvas3D c) {
            this.myCanvas3D = c;
            
            //Etablier ein virtual universe mit einer einzelnen hi-res Locale
            myUniverse = new VirtualUniverse();
            myLocale = new Locale(myUniverse);
            
            //Erstell ein PhysicalBody und ein PhysicalEnvironment Objekt
            PhysicalBody myBody = new PhysicalBody();
            PhysicalEnvironment myEnvironment = new PhysicalEnvironment();
            
            //Erstelle einen View und füge canvas3d physicalbody und physicalenvironment hinzu
            myView = new View();
            myView.addCanvas3D(c);
            myView.setPhysicalBody(myBody);
            myView.setPhysicalEnvironment(myEnvironment);
            
            //Erstelle einen Branchgroup knoten für die view platform
            BranchGroup vpRoot = new BranchGroup();
            
            //Erstelle ein ViewPlatform Objekt und sein Transformgroup objekt und füg es in den root des untergraphen.Füg den View zur ViewPlatform
            Transform3D t = new Transform3D();
            t.set(new Vector3f(0.0f, 0.0f, 150.0f)); //setzt die viewPlatform auf 0,0,2
            myViewingP = new ViewingPlatform();
            vp = new ViewPlatform();
            myViewingP.setViewPlatform(vp);
            
            vpTrans = new TransformGroup();
            
            //vpTrans mit Referenz auf die viewPlatform-Transformgroup initialisieren
            vpTrans = myViewingP.getViewPlatformTransform();
            vpTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
            vpTrans.setTransform(t);
            
            
            vpRoot.addChild(myViewingP);
            
            myView.attachViewPlatform(vp);
            myView.setBackClipDistance(500);
            
            BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 5000.0d);
            
            //PlatformGeometry myPlatformGeometry = new PlatformGeometry();
            
            // Set up the ambient light
            Color3f ambientColor = new Color3f(0.1f, 0.1f, 0.1f);
            AmbientLight ambientLightNode = new AmbientLight(ambientColor);
            ambientLightNode.setInfluencingBounds(bounds);
            vpRoot.addChild(ambientLightNode);
            
            // Set up the directional lights
            Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
            Vector3f light1Direction  = new Vector3f(1.0f, 1.0f, 1.0f);
            Color3f light2Color = new Color3f(1.0f, 1.0f, 1.0f);
            Vector3f light2Direction  = new Vector3f(-1.0f, -1.0f, -1.0f);
      
            DirectionalLight light1
                = new DirectionalLight(light1Color, light1Direction);
            light1.setInfluencingBounds(bounds);
            vpRoot.addChild(light1);
      
            DirectionalLight light2
                = new DirectionalLight(light2Color, light2Direction);
            light2.setInfluencingBounds(bounds);
            vpRoot.addChild(light2);
            
            //Füg den Branch Grapgh zum universe, via dem Locale zu. Der scene Graph ist jetzt live
            
            myLocale.addBranchGraph(vpRoot);
      }
      
      public void addBranchGraph(BranchGroup bg) {
            myLocale.addBranchGraph(bg);
      }

End of code in UniverseBuilder

Has no One an idea???