Multiple bugs in Milkshape Loader?

The milkshape loader doens’t update normals at all. As an example, I have a box rotating around the axis. Even though my lights stay in the same place, it -looks- like my light is moving around my box because one side is allways staying lit.



Another bug (probably intentional) is that the boundingbox of an animating model doesn’t update correctly. So as my box is rotating around the axis in a big circle, my boundingBox stays where my box originally was.



I wrote my own Milkshape3D loader with animation support for Java3d a month ago for .ms3d format (not ASCII format). It seems to give me better FPS than jME’s for complex models. I’m trying to port it to figure out if the better FPS are due to Java3D or my loader. I hope it’s just the loader, because I really love the setup of jME and hope to continue it as a main project.

The milkshape loader doens't update normals at all. As an example, I have a box rotating around the axis. Even though my lights stay in the same place, it -looks- like my light is moving around my box because one side is allways staying lit.


Um, normals don't need to be updated as a model rotates/translates. Are you sure you didn't attach a light to the rotating box?

Another bug (probably intentional) is that the boundingbox of an animating model doesn't update correctly. So as my box is rotating around the axis in a big circle, my boundingBox stays where my box originally was.


Not a bug, you have to tell the animating controller to update bounding boxes.

( (DeformationJointController) model.getAnimationController()).
        setUpdateModelBounds(true);



for example

I wrote my own Milkshape3D loader with animation support for Java3d a month ago for .ms3d format (not ASCII format). It seems to give me better FPS than jME's for complex models. I'm trying to port it to figure out if the better FPS are due to Java3D or my loader. I hope it's just the loader, because I really love the setup of jME and hope to continue it as a main project.


FPS wouldn't be any different across different loaders. Once they are loaded it's just a tri-mesh. So, I doubt it's the loader.

Very sure about normals needing to be updated, try the following code and you’ll see the problem.



public class AGame extends SimpleGame{

Model i;

public static void main(String[] args) {

new AGame().start();

}

protected void simpleInitGame() {

lightState.detachAll();

DirectionalLight DL=new DirectionalLight();

DL.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));

DL.setAmbient(new ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f));

DL.setSpecular(new ColorRGBA(0,0,0,1));

DL.setDirection(new Vector3f(0, 0, -1));

DL.setEnabled(true);



lightState.attach(DL);

Model i=new MilkshapeASCIIModel(“guy”);

i.load(“images/boxaxis.txt”);

rootNode.attachChild(i);

}

}



===With the following .txt milkshape file====

// MilkShape 3D ASCII



Frames: 9

Frame: 1



Meshes: 1

“Box04” 0 0

20

0 2.500000 7.521546 1.618909 0.000000 0.000000 0

0 2.500000 -7.476170 1.880695 0.000000 1.000000 0

0 17.500000 7.521546 1.618909 1.000000 0.000000 0

0 17.500000 -7.476170 1.880695 1.000000 1.000000 0

0 17.500000 7.521546 1.618909 0.000000 0.000000 0

0 17.500000 -7.476170 1.880695 0.000000 1.000000 0

0 17.500000 7.464826 -1.630596 1.000000 0.000000 0

0 17.500000 -7.532890 -1.368810 1.000000 1.000000 0

0 17.500000 7.464826 -1.630596 0.000000 0.000000 0

0 17.500000 -7.532890 -1.368810 0.000000 1.000000 0

0 2.500000 7.464826 -1.630596 1.000000 0.000000 0

0 2.500000 -7.532890 -1.368810 1.000000 1.000000 0

0 2.500000 7.464826 -1.630596 0.000000 0.000000 0

0 2.500000 -7.532890 -1.368810 0.000000 1.000000 0

0 2.500000 7.521546 1.618909 1.000000 0.000000 0

0 2.500000 -7.476170 1.880695 1.000000 1.000000 0

0 2.500000 7.521546 1.618909 0.000000 1.000000 0

0 17.500000 7.521546 1.618909 1.000000 1.000000 0

0 2.500000 -7.476170 1.880695 0.000000 0.000000 0

0 17.500000 -7.476170 1.880695 1.000000 0.000000 0

6

0.000000 0.017452 0.999848

1.000000 0.000000 0.000000

0.000000 -0.017452 -0.999848

-1.000000 0.000000 0.000000

0.000000 0.999848 -0.017452

0.000000 -0.999848 0.017452

12

0 0 1 2 0 0 0 1

0 1 3 2 0 0 0 1

0 4 5 6 1 1 1 2

0 5 7 6 1 1 1 2

0 8 9 10 2 2 2 1

0 9 11 10 2 2 2 1

0 12 13 14 3 3 3 2

0 13 15 14 3 3 3 2

0 12 16 6 4 4 4 3

0 16 17 6 4 4 4 3

0 18 13 19 5 5 5 3

0 13 7 19 5 5 5 3



Materials: 1

“Red”

0.200000 0.200000 0.200000 1.000000

1.000000 0.000000 0.000000 1.000000

1.000000 1.000000 1.000000 1.000000

0.000000 0.000000 0.000000 1.000000

109.000000

1.000000

“”

“”



Bones: 1

“joint1”

“”

21 -0.500000 0.000000 0.500000 0.000000 0.000000 0.000000

9

1.000000 0.000000 0.000000 0.000000

2.000000 0.000000 0.000000 0.000000

3.000000 0.000000 0.000000 0.000000

4.000000 0.000000 0.000000 0.000000

5.000000 0.000000 0.000000 0.000000

6.000000 0.000000 0.000000 0.000000

7.000000 0.000000 0.000000 0.000000

8.000000 0.000000 0.000000 0.000000

9.000000 0.000000 0.000000 0.000000

9

1.000000 -0.017453 0.000000 0.000000

2.000000 -0.017453 0.785398 0.000000

3.000000 -0.017453 1.570796 0.000000

4.000000 3.124139 0.785399 -3.141593

5.000000 3.124139 0.000001 -3.141593

6.000000 3.124139 -0.785397 -3.141593

7.000000 -0.017453 -1.570795 0.000000

8.000000 -0.017453 -0.785399 -0.000000

9.000000 -0.017453 -0.000001 0.000000

my boxaxis.txt file is a 3D box rotating around the axis. As it rotates, you should be able to see all the sides, but only one side remains visible

Normals are only set once, unless the geometry vertices change. This is how OpenGL works…



I just altered TestMilkshapeASCII to rotate the model and not animate, it works fine.


/*
 * Copyright (c) 2003-2004, jMonkeyEngine - Mojo Monkey Coding
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the Mojo Monkey Coding, jME, jMonkey Engine, nor the
 * names of its contributors may be used to endorse or promote products derived
 * from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */
package jmetest.renderer.loader;

import java.net.URL;

import com.jme.animation.DeformationJointController;
import com.jme.app.SimpleGame;
import com.jme.light.DirectionalLight;
import com.jme.light.SpotLight;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Controller;
import com.jme.scene.model.Model;
import com.jme.scene.model.msascii.MilkshapeASCIIModel;

/**
 * <code>TestBackwardAction</code>
 * @author Mark Powell
 * @version
 */
public class TestMilkshapeASCII extends SimpleGame {
  private Model model;
 
  private Quaternion rotQuat = new Quaternion();
  private float angle = 0;
  private Vector3f axis = new Vector3f(0, 1, 0);

  public static void main(String[] args) {
    TestMilkshapeASCII app = new TestMilkshapeASCII();
    app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG);
    app.start();
  }
 
  protected void simpleUpdate() {
      if (timer.getTimePerFrame() < 1) {
          angle = angle + (timer.getTimePerFrame() * 25);
          if (angle > 360) {
            angle = 0;
          }
        }

        rotQuat.fromAngleAxis(angle * FastMath.DEG_TO_RAD, axis);
        model.setLocalRotation(rotQuat);
  }

  /**
   * set up the scene
   * @see com.jme.app.AbstractGame#initGame()
   */
  protected void simpleInitGame() {
    display.setTitle("Joint Animation");
    cam.setLocation(new Vector3f(0.0f, 0.0f, 200.0f));
    cam.update();
    URL modelURL = null;
    model = new MilkshapeASCIIModel("Milkshape Model");
    modelURL = TestMilkshapeASCII.class.getClassLoader().getResource(
        "jmetest/data/model/msascii/run.txt");
    model.load(modelURL, "jmetest/data/model/msascii/");
    model.getAnimationController().setSpeed(10.0f);
    model.getAnimationController().setRepeatType(Controller.RT_CYCLE);
    ( (DeformationJointController) model.getAnimationController()).
        setUpdateModelBounds(true);
    model.getAnimationController().setActive(false);
    rootNode.attachChild(model);
    SpotLight am = new SpotLight();
    am.setDiffuse(new ColorRGBA(0.0f, 1.0f, 0.0f, 1.0f));
    am.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
    am.setDirection(new Vector3f(0, 0, 0));
    am.setLocation(new Vector3f(25, 10, 0));
    am.setAngle(15);

    SpotLight am2 = new SpotLight();
    am2.setDiffuse(new ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f));
    am2.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
    am2.setDirection(new Vector3f(0, 0, 0));
    am2.setLocation(new Vector3f( -25, 10, 0));
    am2.setAngle(15);

    DirectionalLight dr = new DirectionalLight();
    dr.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
    dr.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
    dr.setDirection(new Vector3f(0, 0, -150));

    lightState.detachAll();
    lightState.attach(am);
    lightState.attach(dr);
    lightState.attach(am2);
    am.setEnabled(true);
    am2.setEnabled(true);
    dr.setEnabled(true);
  }
}

Then how do I explain the behavior of my boxaxis.txt? When it animates with jME it looks like a 2D plane, when it’s really a 3D box? Try my code and it’ll show up really big.

Ok, I just took the milkshape file from your post, saved it and plugged it into the milkshape test I posted and it worked fine. The box is red (as that’s its material setting). But it’s not a cube: it’s more like a pizza box. It’s definately 3 dimensional though just not uniform. And looking at:



0 2.500000 7.521546 1.618909 0.000000 0.000000 0

0 2.500000 -7.476170 1.880695 0.000000 1.000000 0

0 17.500000 7.521546 1.618909 1.000000 0.000000 0

0 17.500000 -7.476170 1.880695 1.000000 1.000000 0

0 17.500000 7.521546 1.618909 0.000000 0.000000 0

0 17.500000 -7.476170 1.880695 0.000000 1.000000 0

0 17.500000 7.464826 -1.630596 1.000000 0.000000 0

0 17.500000 -7.532890 -1.368810 1.000000 1.000000 0

0 17.500000 7.464826 -1.630596 0.000000 0.000000 0

0 17.500000 -7.532890 -1.368810 0.000000 1.000000 0

0 2.500000 7.464826 -1.630596 1.000000 0.000000 0

0 2.500000 -7.532890 -1.368810 1.000000 1.000000 0

0 2.500000 7.464826 -1.630596 0.000000 0.000000 0

0 2.500000 -7.532890 -1.368810 0.000000 1.000000 0

0 2.500000 7.521546 1.618909 1.000000 0.000000 0

0 2.500000 -7.476170 1.880695 1.000000 1.000000 0

0 2.500000 7.521546 1.618909 0.000000 1.000000 0

0 17.500000 7.521546 1.618909 1.000000 1.000000 0

0 2.500000 -7.476170 1.880695 0.000000 0.000000 0

0 17.500000 -7.476170 1.880695 1.000000 0.000000 0



it’s obvious it’s not supposed to be a full box. The Z axis is either 0 or 1, so it has a depth of 1 unit, which the x and y have a depth of about 14.

Ya it’s more of a pizza box than a cube. The bug is inside how the loader handles animations I believe. Try the following code (it’s extreamly short):



public class AGame extends SimpleGame{

Model i;

public static void main(String[] args) {

new AGame().start();

}

protected void simpleInitGame() {

lightState.detachAll();

DirectionalLight DL=new DirectionalLight();

DL.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));

DL.setAmbient(new ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f));

DL.setSpecular(new ColorRGBA(0,0,0,1));

DL.setDirection(new Vector3f(0, 0, -1));

DL.setEnabled(true);



lightState.attach(DL);

Model i=new MilkshapeASCIIModel(“guy”);

i.load(“images/boxaxis.txt”);

rootNode.attachChild(i);

}

}

ok, when I said:


Normals are only set once, unless the geometry vertices change.


That meant I thought you were rotating the geometry... not that you had an animation that animates rotation. So you *are* changing the geometry vertices. That's where the communication problem occured.

Right, normals are not updated to reflect milkshape animations. It's not a bug, I just never needed it, so I never got around to it. It'll go on the to do list.

Coolio