FPS370 - Changes from Alpha8 to Alpha9
Dynamic HUD

The changes problem with transparency was purely external to Java3D. I created the transparent GIF (with PaintShopPro) by color instead of by selection area and it displayed correctly.

The main changes to update the texture dynamically were mostly to the loading and drawing of the HUD texture. In these changes we create an offscreen image to draw into. We then create the Texture using the BY_REFERENCE flag, so changes to our copy of the image are shared with the actual texture.

// create the hud offscreen image
imgHud = new BufferedImage(imgHudBack.getWidth(this),imgHudBack.getHeight(this),
                           BufferedImage.TYPE_4BYTE_ABGR);
drawHudImage();


TextureLoader loader = new TextureLoader(imgHud,TextureLoader.BY_REFERENCE);
textureHud = (Texture2D) loader.getTexture();
icHud = (ImageComponent2D) textureHud.getImage(0);

appHud.setTexture(textureHud); // set the texture
hudUpdater = new HudUpdater(this);
        

We retrieve a reference to the ImageComponent2D with the call to textureHud.getImage(0).

We also created a new class called HudUpdater which Java3D will call when changes are allowed to the texture. We tell Java3D that the texture needs updating when changes have occured. It then calls the HudUpdater class when we can safely make changes to the HUD.

class HudUpdater implements ImageComponent2D.Updater
  {
    private Fps370Panel parent;
    public HudUpdater(Fps370Panel parentInit)
    {
      parent = parentInit;
    }
    public void updateData(ImageComponent2D icUpdate, int x, int y, int width, int height)
    {
      parent.drawHudImage();      
    }
  }

When we want to make a change to the HUD (typically every time through the tick method) we simply call.

  public void updateHud()
  {
    icHud.updateData(hudUpdater,0,0,imgHudBack.getWidth(this),imgHudBack.getHeight(this));
  }

For best performance we should only call this when there is an actual change to the HUD, but for this simple demo calling it everytime does not hurt performance. By calling the imageComponent's updateData, Java3D will then make a callback to our hudUpdater object. Java3D will do this at a time (and on a thread) that will not cause a problem with the rendering of the scene. Changes in another thread besides Java3D could have odd graphical effects if the information changed in the middle of rendering. All we do in the HudUpdater is re-render the HUD image (imgHud). Java3D will automatically use that same image during the next render loop. Remember this image was declared BY_REFERENCE. Meaning a change in one location will change the other. They both share the same image. If it were not BY_REFERENCE, Java3D would have to make a copy of the image everytime there was a change. By sharing the reference performance should increase.

Problems during development:

While developing this feature I spent a lot of time on the following exception.

Exception occurred during Behavior execution: javax.media.j3d.CapabilityNotSetException: ImageComponent2D: no capability to set image at javax.media.j3d.ImageComponent2D.updateData(Unknown Source) at fps370.Fps370Panel.updateHud(Fps370Panel.java:482) at fps370.Fps370Panel.tick(Fps370Panel.java:863) at fps370.Fps370Ticker.processStimulus(Fps370Ticker.java:38) at javax.media.j3d.BehaviorScheduler.doWork(Unknown Source) at javax.media.j3d.J3dThread.run(Unknown Source)

I tried a lot of different setCapability calls on the shapeHud to no avail. I finally came back and read the exception closely. What this is saying is that the ImageComponent2D is the one complaining about the capability not being set. Once I noticed that I went directly to the documentation for ImageComponent2D and found the proper flag.

      icHud.setCapability(ImageComponent.ALLOW_IMAGE_WRITE);

Once I added that call everything worked great.

 

CPSC370 - Games Development
Chapman University
Instructor: W. Wood Harter
(c) copyright 2006 - W. Wood Harter - All Rights Reserved
Screen shots on banner (c) copyright their resprective owners