DiscreteLodNode not working as I expect

Hello,



it seams to me there is a problem with DiscreteLodNode in it's current implementation. The world vectors don't get updated unless selectLevelOfDetail is called. I looked at the code. To me it seams to be a little hacky and incomplete.

Given updateGeometricState is called on a parent node, it calls updateGeometricState one their children which calls updateWorldData. Given DiscreteLodNode is on of these children, it overwrites the method (for performance reasons) but does not call updateWorldVectors but instead updateWorldBound() which is called by updateGeometricState anyway a little later.

The only way to update the world vectors is a call to selectLevelOfDetail on every DiscreteLodNode after it is attached to the scene, which to me seems a bit unlucky. Could be a bug, I think there should be a call to updateWorldVectors() instead.



Have a look at the updateWorldData method of DiscreteLodNode:


   public void updateWorldData (float time) {
      lastUpdate = time;

      updateWorldBound();
   }



Another problem seems to be the selectLevelOfDetail method.
It computes the instance variables modelCenter and worldCenter. modelCenter is never set to anything. modelCenter is always (0,0,0). Instead worldBound.getCenter() should be used imho.
Also the worldBound, worldTranslation and worldScale are possibly not set up correct (relevant for the children to draw correctly), so the whole class seems to need a rewrite.

I would suggest something like:


public class DiscreteLodNode extends SwitchNode implements Savable {
   private static final long serialVersionUID = 1L;

        private static Vector3f tmpVs=new Vector3f();

   private SwitchModel model;

   public DiscreteLodNode() {}
   
   public DiscreteLodNode(String name, SwitchModel model) {
      super(name);
      this.model = model;
   }

   public void updateWorldData (float time) {
      updateWorldVectors();
   }

   public void selectLevelOfDetail (Camera camera) {
      if(model == null || worldBound == null) {
         return;
      }
      
      // compute world squared distance intervals
      float worldSqrScale = tmpVs.set(worldScale).multLocal(worldScale).length();
      model.set(tmpVs.set(worldBound.getCenter()).subtractLocal(camera.getLocation()));
      model.set(new Float(worldSqrScale));
      setActiveChild(model.getSwitchChild());
   }

   public void draw (Renderer r) {
      if(model == null || worldBound == null) {
         return;
      }
      selectLevelOfDetail(r.getCamera());
      super.draw(r);
   }

   public void write(JMEExporter e) throws IOException {
      super.write(e);
      OutputCapsule capsule = e.getCapsule(this);
      capsule.write(model, "model", null);
   }

   public void read(JMEImporter e) throws IOException {
      super.read(e);
      InputCapsule capsule = e.getCapsule(this);
      model = (SwitchModel)capsule.readSavable("model", null);
   }
}




That way the world vectors and world bound get updated which is not as costly as processing the whole geometric state of every child to swich.

Possibly the following could also be added to the updateWorldData method.


      // updateGeometricState is only called on the first child and only if it
      // is active due to performance reasons. That way the the nearest
      // child could still be animated.
      if (getActiveChild() == 0 && getQuantity() > 0) {
         Spatial child = null;
         try {
            child = children.get(0);
         } catch (IndexOutOfBoundsException e) {
            // a child was removed in updateGeometricState (note: this may
            // skip one child)
         }
         if (child != null) {
            child.updateGeometricState(time, false);
         }
      }



The updateGeometricState calls are omitted for every child which is not the first and active for performance reasons, and so we cant do animations for farer objects what is unlikely desired anyway.
But that's possibly not a good idea.

What do you think, is this a bug?

I don't know, why there are no replys. What is my mistake?



Ok, I just checked CVS, and the file has changed. In revision 1.11 the overwritten updateWorldData was removed. I have worked with revision 1.10 which is part of 1_0. Okay.



Ok, this answers my first question:

  1. Shouldn't there be a call to updateWorldVectors() instead of updateWorldBound() in the updateWorldData method of DiscreteLodNode?

    -> Yes. Node's implementation is used. The wrong performance tuning vanished in 1.11, okay.



    But my second question is still there:
  2. Shouldn't worldBound.getCenter() should be used instead of the (0,0,0) modelCenter? modelCenter never changes. Is it intended to always be (0,0,0)?