flickering object when moving both:object AND View

Hello,

Here a small link to my testversion described later: http://www.kingsware.de/j3d/test.zip

I try to make a 3d-Space-Shooter. I’m not sure of changing to Xith3D, but by now I use Java3D 1.3.1!

So I load 2 .obj files: first the Terrain then the ship. When pressing the Arrow keys the ship moves and the view follows. This is executed in a seperated Thread with a infinite while loop that is executed every 40ms ( sleep(40) ). I’ve read games should be single-threaded! perhaps the problem lies there??? I thought of one thread per moving object. The view and the ship Transform is executed in ONE Thread and are set at the same time!
Why does it flicker?

Hi again,

ONLY the ship is flickering NOT the Terrain which is moving, too, when the view moves. The ship stops flickering, if I disable the motion of the view!!!

Greetings,
Juan

Ick, ditch your multiple threads right away, your problem could very well be some sort of race condition (rendering while you’ve called matrix.identity() perhaps?) if you’re setting transforms in one and rendering is going on in another. One thread for all objects, you only need more for networking (and maybe sound).

Have your key listener set state variables to be read by your main thread. This main thread should be triggered by J3D, either via an overridden Canvas’ .preRender or by a behaviour with .wakeOnElapsedFrames(0)

Unless you’re actually suffering from z-fighting, which is totally separate, but unless you describe the flickering its difficult to guess :stuck_out_tongue:

it’s indeed a very strange flickering, it’s like the plane “wants” to be at 2 different places at the same time. Is it possible you’re changing the transform matrix at 2 different places?

send the source, it’ll maybe give us a hint.

I had some problems like this when I first started doing java3d, it’s important to use behaviours to update your geometry unless you are using imediate mode rendering. what I’ve ended up doing is I have a behaviour set to go off every frame for each moving object, which checks it’s data word counterpart for position and updates it, this makes sure the update code and the renderer are in sync, otherwise you can be doing updates whilst java3d is rendering, and that can causes visual stutters/tearing.

HTH

Endolf

Hi again,
To MisterX: The view is following the ship and it looks like Java3d is rendering the transform of the ship first and in the next frame the view follows. How can I change this? perhaps my code makes it more clear???

To Endolf: You mean I should execute every Objecttransform in a seperate Behaviour? Please specifiy (perhaps with a little code strip :stuck_out_tongue: ) how I should code the transform shown in my code below!!!

Here is the code of my GameTimer Thread. I’ve already coded a single-threaded version of my “game”, but the problem is still there:


//KeyEvents und so
import java.awt.event.*;
//Thread und so
import java.lang.*;
//Java3d Core
import javax.media.j3d.*;
import javax.vecmath.*;


public class GameTimer extends Thread {
      
      //Horizontal und Vertical Speed!
      private float hSpeed = 5.0f;
      private float vSpeed = 5.0f;
      
      //Position
      private float x = 0.0f;
      private float y = 0.0f;
      private float z = 0.0f;
      Vector3f position = new Vector3f(0.0f,0.0f,0.0f);
      Transform3D posTrans = new Transform3D();;
      //Die TransformGroup die verändert werden soll!
      private TransformGroup targetTG;
      
      
      //ViewPlatformposition
      private float vpX = 0.0f;
      private float vpY = 0.0f;
      private float vpZ = 150.0f;
      Vector3f vpPosition = new Vector3f(0.0f,0.0f,150.0f);
      Transform3D vpPosTrans = new Transform3D();
      //Die TransformGroup die verändert werden soll!
      private TransformGroup vpTrans;
      
      
      //Beschleunigungsmultiplikatoren für smoothed-motion!
      private float multiUp        = 0.0f;
      private float multiDown  = 0.0f;
      private float multiLeft  = 0.0f;
      private float multiRight = 0.0f;
      
      
      //Keypressed booleans
      private boolean escape_isPressed        = false;
      private boolean upArrow_isPressed        = false;
      private boolean downArrow_isPressed  = false;
      private boolean leftArrow_isPressed  = false;
      private boolean rightArrow_isPressed = false;
      
      //Constructor erhält die Transformgroup, die verändert werden soll
      public GameTimer(TransformGroup targetTG, TransformGroup vpTrans) {
            this.targetTG = targetTG;
            this.vpTrans  = vpTrans;
            vpPosTrans.set(vpPosition);
            posTrans.set(position);
      }
      
      //Gibt zurück, ob der Keypressedstatus auf TRUE oder FALSE gesetzt ist
      public boolean getKeyIsPressed(int keyCode) {
            switch(keyCode) { 
                  case KeyEvent.VK_ESCAPE:
                        return escape_isPressed;
                  case KeyEvent.VK_UP:
                        return upArrow_isPressed;
                  case KeyEvent.VK_DOWN:
                        return downArrow_isPressed;
                  case KeyEvent.VK_LEFT:
                        return leftArrow_isPressed;
                  case KeyEvent.VK_RIGHT:
                        return upArrow_isPressed;
                  default:
                        return false;
            }
      }
      
            //Setzt einen Keypressedstatus auf TRUE oder FALSE
      public void setKeyIsPressed(int keyCode, boolean is_pressed) {
            switch(keyCode) { 
                  case KeyEvent.VK_ESCAPE:
                        escape_isPressed = is_pressed;
                        break;
                  case KeyEvent.VK_UP:
                        upArrow_isPressed = is_pressed;
                        break;
                  case KeyEvent.VK_DOWN:
                        downArrow_isPressed = is_pressed;
                        break;
                  case KeyEvent.VK_LEFT:
                        leftArrow_isPressed = is_pressed;
                        break;
                  case KeyEvent.VK_RIGHT:
                        rightArrow_isPressed = is_pressed;
                        break;
                  default:
                        break;
            }
      }
      
      //setze den Horizontal Speed
      public void setHorizontalSpeed(float speed) {
            hSpeed = speed;
      }
      
      //setze den Vertical Speed
      public void setVerticalSpeed(float speed) {
            vSpeed = speed;
      }

      //bewege, weil Key gedrückt
      private float[] turn(float multi, float speed) {
            if(multi <= 1.0f) {
                  multi += 0.1f;
            }
            //gib die Änderung zurück
            System.out.println(multi);
            float[] f = { (multi*speed), multi };
            return f;
      }

      //bewegung Abremsen, weil Taste released
      private float[] brake(float multi, float speed) {
            //Damit er nicht endlos teilt Grenze auf -0.05f;
            if(multi > 0.05f) {
                  multi /= 1.2f;
                  //gib die Änderung zurück

                  float[] f = { (multi*speed), multi };
                  return f;
            }
            else { 
                  float[] f = {0,0};
                  return f; 
            }
      }

      //BEWEGE DAS SCHIFF UND DEN VIEW
      private void processPositionTransform() {
            //Die Bewegungen an Java3d weitergeben!
            vpTrans.setTransform(vpPosTrans);
            //Der Ziel-TransformGroup die Position einspeisen ;)
            targetTG.setTransform(posTrans);
            
            /*Bewegung des Schiffs*/
            //Bewege Dich nach Links
            if(leftArrow_isPressed) {
                  float[] f = turn(multiLeft, hSpeed);
                  x -= f[0];
                  multiLeft = f[1];
                  //brakevorgang von rechts beenden
                  multiRight = 0.0f;
            }
            else {
                  float[] f = brake(multiLeft, hSpeed);
                  x -= f[0];
                  multiLeft = f[1];
            }
            
            //Bewege Dich nach Rechts
            if(rightArrow_isPressed) {
                  float[] f = turn(multiRight, hSpeed);
                  x += f[0];
                  multiRight = f[1];
                  //brakevorgang von links beenden
                  multiLeft = 0.0f;
            }
            else {
                  float[] f = brake(multiRight, hSpeed);
                  x += f[0];
                  multiRight = f[1];
            }
            
            //Bewege Dich nach oben
            if(upArrow_isPressed) {
                  float[] f = turn(multiUp,vSpeed);
                  y += f[0];
                  multiUp = f[1];
                  //brakevorgang von unten beenden
                  multiDown = 0.0f;
            }
            else {
                  float[] f = brake(multiUp, vSpeed);
                  y += f[0];
                  multiUp = f[1];
            }
            
            //Bewege Dich nach unten
            if(downArrow_isPressed) {
                  float[] f = turn(multiDown, vSpeed);
                  y -= f[0];
                  multiDown = f[1];
                  //brakevorgang von oben beenden
                  multiUp = 0.0f;
            }
            else {
                  float[] f = brake(multiDown, vSpeed);
                  y -= f[0];
                  multiDown = f[1];
            }
          
            //Bewege Dich nach vorne
            //KOMMT NOCH
            //Bewege Dich nach hinten
            //KOMMT NOCH
            
            //Position in einen Vector umwandeln
            position.x = x;
            position.y = y;
            position.z = z;
            
            //Transform3D Objekt initialisieren
            posTrans = new Transform3D();
            
            //Positionsvector an das Transform3Dobjekt übergeben
            posTrans.set(position);            
            
            /*Bewegung des Schiffs ENDE */
            
            /*Bewegung der ViewPlatform */
           
            float difX = vpX - x;
            if((difX > 0.05f) || (difX < -0.05f)) {
                  vpX -= (difX)/3.0f;
            }
            
            float difY = vpY - y;
            if((difY > 0.05f) || (difY < -0.05f)) {
                  vpY -= (difY)/3.0f;
            }
            
            //vpY -= ((multiDown*vSpeed)/2.0f);
            
            vpPosition.x = vpX;
            vpPosition.y = vpY;
            vpPosition.z = vpZ;
            
            vpPosTrans = new Transform3D();
            vpPosTrans.set(vpPosition);
            
            
            /*Bewegung der ViewPlatform ENDE */
                  
            
            
            
      }
      
      private void processRotationTransform() {}//KOMMT NOCH
      
      //Thread Main method
      public void run() {
            while(!escape_isPressed) {
                  //Anweisungen
                  //Beweg Dich
                  processPositionTransform();
                  //Dreh Dich
                  processRotationTransform();
            
            //Versuche 1/25tel Sek zu pennen!
            try {
                this.sleep(40);
            } 
            catch (InterruptedException e){}
              //repaint();
        }
      }
}

Thank you very much for answering!!!
Greetings Juan!

Oh Pardon,

the comments are in german ::)! If something isn’t clear, feel free to ask anything!

Greetings,
Juan

Hi
Instead og calling the class GameThread, call it ObjectUpdater, and don’t extend thread. Remove the run method and create one called update() that just calls

   processPositionTransform(); 
   processRotationTransform(); 

create a bahavior and create the appropriate wake up conditions and then in it’s processStimulus method call update on your object updater (and re initialise the behavior.

Also, I hate to see it when people do import .*, unless you really do need every class in that package you should be more specific, sorry, couldn’t help myself :slight_smile:

I have knocked up the changed class and the new behavior, just add it to your scenegraph and set appropriate scheduling bounds and it will do it, I do suggest that you use my classes as referance, rather than just using them, that way you will learn what it’s doing. I’ve net even compiled them so there might be some errors in there, but the principle is sound (it’s what I do close enough).

Cheers

Endolf

GameUpdater.java
GameUpdaterBehavior.java

Hi endolf,

Thank you very much!!! Of course in the end-version of the game there won’t be any “import .*;”, but in test versions I use it, because its faster ;)!

I take it as a compliment, that your only complaint about my code, aims at the imports :P!!!

I’ll try it this (your) way and will post if it works!

Greetings,
Juan

Hi
I’ve been known to do it in prototyping too, but I try not too these days, it certainly wasn’t a critisim, well, maybe, but a constructive one :), if you can’t get it working then i’m not sure whats going on, as it should work fine :), if it doesn’t then the first thing to check is the shceduling bounds :), just put some debug int he initise and processStimulus methods of the behavior, the second should get fired every frame

HTH

Endolf

THANK YOU ENDOLF!

It really works ;)! I’ve thought about that for days!!! You’ve helped me very much!!!

I changed the wakeupcriterion in wakeupontime, because the animation has to depend on time not on machinespeed. Now I can start coding the transform on the z axis and the Mouse-aiming ;)!

Another question: Do you think Java3D is that much slower than Xith3D, Jogl or LWJGL? Is it a dream, realizing a fast AND pretty game with Java3D??? Because API’S like JOGL, LWJGL and so on, aren’t that good documented, yet! Xith3D e.g. doesn’t even support lights, yet. This should not decrease the performance of David Yazel and Co, but are this very young API’S alternatives???

Thank you very much for your help I’ll put you to the credits if you’d like to!?! The list is very small yet :frowning: (only me)!

Greets,
Juan

new link: http://www.kingsware.de/j3d/gameupdater.zip

NOW IT WORKS!

Hi
The Java3D v.s. JOGL/LWJGL/Xith3D is old, Xith needs alot of work yet before it becomes developed enough to use, but I am keeping my eye on it, writting to raw gl (jogl/lwjgl) will require vast amounts more work than using java3d, java3d does work, and is (mostly) bug free, so if it has teh features you need, then why not us it. Java3d’s performance looks slow at the start, but once you get a more complicated scene gl will slow down alot faster than java3d. You have to look at what you are trying to do, is it simple, or hard. The more time you spend worying about gl stuff, the less time you can spend consentrating on game play. On the other hand jav3d doesn’t support some of the newer features, but unless you are good at gl already, they won’t worry you for a while.
Good advice would be to make sure your rendering technology and your game/gameplay technology are seperated enough that if you later want to change your rendering tech, you don’t have to rewrite your whole game.

HTH

Endolf

Hi
On the wakeup creteri thing, use wakeup on frames(1), and measure the time between frames, then adjust the movement by that rate, that way the faster your graphics run the smoother your updates will be, and your pure movement rate isn’t dependant on machine speed. eg, say you want to move at 1m/s, thather than updateing once a second and moving a meter, updates once a frame, then devide your speed buy 1/time since last update, and move that amount, that way you will still end up moving 1 meter in a second, but will do a fraction of it every frame update, so you won’t get a horrid jerk every second.

Endolf

Hi endolf,

Thank you again! You’re right again! But how do I get the time between two frames. I’ve heard I need a hires timer. Can I use a standard timer like this?!?:


processStimulus(Enumeration criteria) {

  long time = java.util.Date.getTime();
  timediff = time - old_time;

  updater.update(timediff);

  old_time = time;
  wakeupOn(wakeUpCrit);
}

in updater I would then make something like this:


public update(long millis) {
  processPositionTransform(millis);
  processRotationTransform(millis);
}

Two ways, System.currentMillis() will get the current time in milliseconds, so as long as you save this at the end of a frame redner, it will be available on the next one to check the time. but better as your in java3d land would be J3DTimer, which is higher resolution (System.currentMillis on some operating systems can only manage 50 milli second intevels). Same priciple, get the time, render the scene, update based off new time, repeat.

HTH

Endolf

Hi endolf,

I tried what you’ve said. But it is stuttering. I can imagine two possible reasons:

  1. The J3DTimer resolution isn’t high enough. So it is stuttering, when the Framerate isn’t stable and the Framerate is never stable!!!

  2. The Time between the start of processStimulus, where newTime is set and the rendering isn’t mentioned, cause it’s unknown!!!

Here is the code of my Behavior class(in the updater class I do something like this: position.z += speedInMeterPerSecond/fps; ):


import javax.media.j3d.Behavior;
import javax.media.j3d.WakeupOnElapsedFrames;
import com.sun.j3d.utils.timer.J3DTimer;
import java.util.Enumeration;

public class GameUpdaterBehavior extends Behavior {

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

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

  public void processStimulus(Enumeration criteria) {
        newTime = (float)J3DTimer.getValue();
        timeDiff = newTime - oldTime;
        
        fps = 1000000000/timeDiff;
        System.out.println("fps: " + fps);
        
    updater.update(fps);
    //fürs nächste mal!
        oldTime = newTime;
    wakeupOn(wakeupCondition);
  }
}

I tried something like this, too. I thought perhaps I have to add the past time after updating to oldTime in order to stop stuttering, but it didn’t help.

oldTime = newTime + ((float)J3DTimer.getValue() - newTime);

But this could not have been a solution to the problem. What is going wrong there??? I changed this in order to get smoother moving when the machine is faster than 25 FPS and use less CPU power, when the machine is slower than 25 FPS, but it’s only flickering and my framerate is at about 59-70 FPS!!!

Greets,
Juan

Hi
Why are you using floats for the time?, you will never get a fraction of a millisecond returned from getValue method, use the longs, thats what they are there for :), also you need to call updater.update(timeDiff) not fps.

I have converted it to floats, cause when I divide 1000000000/newTime and newTime is a long the result is a long, too. When I use it as long, it’s stuttering even more, cause the fps are e.g 60 not 60.1232143423423f!!!

Greets
Juan