How to calculate the height of a Model

I'm loading a model from a MD2 file and trying to calculate the Model height to place it over the ground …

I'm getting the triangles from the child meshes … but something is going wrong with the result …

any other easy way to do it ?



look ath the code !


public class NodeUtil {

   public static float getHeight(Node node) {

      float top = 0;
      float bottom = 0;

      Vector3f[] foo = new Vector3f[3];
      Stack<Node> toInspect = new Stack<Node>();
      toInspect.push(node);

      while (!toInspect.isEmpty()) {
         Node current = (Node) toInspect.pop();
         Iterator iterator = current.getChildren().iterator();

         while (iterator.hasNext()) {
            Spatial element = (Spatial) iterator.next();

            if (element instanceof Node) {
               toInspect.push((Node) element);
            } else {
               if (element instanceof TriMesh) {
                  TriMesh mesh = (TriMesh) element;

                  for (int i = 0; i < mesh.getTotalTriangles(); i++) {
                     mesh.getTriangle(i, foo);
                     LoggingSystem.getLogger().info("foo[0].y=" + foo[0].y);

                     if (foo[0].y > top)
                        top = foo[0].y;
                     if (foo[1].y > top)
                        top = foo[1].y;
                     if (foo[2].y > top)
                        top = foo[2].y;

                     if (foo[0].y < bottom)
                        bottom = foo[0].y;
                     if (foo[1].y < bottom)
                        bottom = foo[1].y;
                     if (foo[2].y < bottom)
                        bottom = foo[2].y;
                  }
               }
            } // if node

         }
      }
      
      float height = top - bottom;
      LoggingSystem.getLogger().info("height = " + height);
      return height;
   }

}



and the character still is floating ...  :D


here is the code that I use at the update() method

   @Override
   protected void update(float interpolation) {

      // update the time to get the framerate
      timer.update();
      interpolation = timer.getTimePerFrame();
      // update the keyboard input (move the player around)
      input.update(interpolation);
      // update the chase camera to handle the player moving around.
      chaser.update(interpolation);
      // if escape was pressed, we exit
      if (KeyBindingManager.getKeyBindingManager().isValidCommand("exit")) {
         finished = true;
      }

      // We don't want the chase camera to go below the world, so always keep
      // it 2 units above the level.
      if (cam.getLocation().y < (page.getHeight(cam.getLocation()) + 2)) {
         cam.getLocation().y = page.getHeight(cam.getLocation()) + 2;
         cam.update();
      }

      // player.getLocalTranslation().y = page.getHeight(player
      // .getLocalTranslation().x, player.getLocalTranslation().z)
      // + (player.getHeight() / 2);

      float characterMinHeight = page.getHeight(player.getLocalTranslation())
            + (player.getHeight() / 2) + DISTANCE_FROM_THE_GROUND;

      if (!Float.isInfinite(characterMinHeight)
            && !Float.isNaN(characterMinHeight)) {
         player.getLocalTranslation().y = characterMinHeight;
      }

      // get the normal of the terrain at our current location. We then apply
      // it to the up vector
      // of the player.
      page.getSurfaceNormal(player.getLocalTranslation(), normal);
      if (normal != null) {
         player.rotateUpTo(normal);
      }

      // Because we are changing the scene (moving the skybox and player) we
      // need to update
      // the graph.
      scene.updateGeometricState(interpolation, true);
   }

1 Like

An easy way would be taking the height of the world bound. The accuracy of this depends on the kind of model bound you are using, of course.

good idea !

I have a class Player that loads the model from an MD2 file, after getting an WorldBound = null

I took a look and found that my method of model loading is not setting the boundingbox to the model

even after this change I still get null worldbound …



I think something is wrong at my loadmodelcode …


   private Node loadModel(DisplaySystem display) {
      Md2ToJme converter = new Md2ToJme();
      ByteArrayOutputStream BO = new ByteArrayOutputStream();

      URL textu = Player.class.getClassLoader().getResource(
            "media/models/alita/alita2.jpg");
      URL model = Player.class.getClassLoader().getResource(
            "media/models/alita/tris.md2");
      Node modelMD2 = null;

      try {
         converter.convert(model.openStream(), BO);
         modelMD2 = (Node) BinaryImporter.getInstance().load(
               new ByteArrayInputStream(BO.toByteArray()));
         modelMD2.setLocalScale(.3f);

         modelMD2.setModelBound(new BoundingBox());
         modelMD2.updateModelBound();

      } catch (IOException e) {
         LoggingSystem.getLogger().warning( " ---- ERROR : " + e.getMessage());
      }

      TextureState ts = display.getRenderer().createTextureState();
      ts.setEnabled(true);
      ts.setTexture(TextureManager.loadTexture(textu,
            Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR));
      modelMD2.setRenderState(ts);
      
      System.out.println("model.getWorldBound()=" + modelMD2.getWorldBound());

      return modelMD2;
   }



the system.out shows null world bound ... :(

there are two bounds at each location of the scenegraph…  A local (model) one that encompasses just that node or leaf on the graph and a "world" one that encompasses that node and any nodes or leafs below it.  The world one will not exist until it is generated via an updateWorldBound call.

Hey ! thanks



the character was getting sick of floating hehehehe

now its over tied to the ground …  :smiley: