Loading texture

I loaded a 3ds model , then loaded a texture file. The strange thing is that there are two people in the viewer.  the one in the back has texture, the one in the front doesn't.  how do I load them?

the screen shot is attached.

here's the code:


    protected void simpleInitGame() {
        if (modelToLoad == null) {
            modelToLoad = TestModel.class.getClassLoader().getResource(
                    "jmetest/data/model/mymodel.3ds");
        }
        try {
            MaxToJme C1 = new MaxToJme();
            ByteArrayOutputStream BO = new ByteArrayOutputStream();
            C1.convert(new BufferedInputStream(modelToLoad.openStream()), BO);
            Node r1 = (Node)BinaryImporter.getInstance().load(new ByteArrayInputStream(BO.toByteArray()));
            //Node r = new Node("parent stuff");
            //r.attachChild(C1.get(new BufferedInputStream(modelToLoad.openStream()), BO));
            //r.setLocalScale(.1f);
            r1.setLocalScale(.1f);
            if (r1.getChild(0).getControllers().size() != 0)
                r1.getChild(0).getController(0).setSpeed(20);
           
            Quaternion temp = new Quaternion();
            temp.fromAngleAxis(FastMath.PI / 2, new Vector3f(-1, 0, 0));
            rootNode.setLocalRotation(temp);
            r1.setLocalTranslation(new Vector3f(10,0,0));
            //rootNode.attachChild(r);
            rootNode.attachChild(r1);
            URL tex=TestModel.class.getClassLoader().getResource("jmetest/data/model/mytexture.jpg");
           
             TextureState ts=display.getRenderer().createTextureState();
             ts.setTexture(TextureManager.loadTexture(tex,Texture.MinificationFilter.Trilinear,
                       Texture.MagnificationFilter.Bilinear));
             ts.setEnabled(true);
            r1.setRenderState(ts);
        } catch (IOException e) {
            logger.log(Level.SEVERE, "Failed to load Max file", e);
        }
    }



thanks

I used this code to load model and applied the textures, but the model still shows up like before with two people, the one in the front has no texture, the one in the back seems to have texture. weird.

Sounds like it could possibly be your model file then?  Or something is very wrong with the loader!

Use this to import models


import com.jme.util.LoggingSystem;
import com.jme.util.export.Savable;
import com.jme.util.export.binary.BinaryExporter;
import com.jme.util.export.binary.BinaryImporter;
import com.jmex.model.XMLparser.Converters.AseToJme;
import com.jmex.model.XMLparser.Converters.FormatConverter;
import com.jmex.model.XMLparser.Converters.MaxToJme;
import com.jmex.model.XMLparser.Converters.Md2ToJme;
import com.jmex.model.XMLparser.Converters.Md3ToJme;
import com.jmex.model.XMLparser.Converters.MilkToJme;
import com.jmex.model.XMLparser.Converters.ObjToJme;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;

public static Node loadModel(String file) {

   Node model = null;
   FormatConverter formatConverter;
   ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
   String format = file.substring(file.lastIndexOf(".") + 1, file.length());
   String binary = file.substring(0, file.lastIndexOf(".") + 1) + "jbin";
   URL url = getModel(binary);

   // verify the presence of the jbin model
   if(url == null) {

      url = getModel(file);

      // evaluate all compatable model formats
      if(format.equalsIgnoreCase("3ds")) {
         formatConverter = new MaxToJme();

      } else if(format.equalsIgnoreCase("md2")) {
         formatConverter = new Md2ToJme();

      } else if(format.equalsIgnoreCase("md3")) {
         formatConverter = new Md3ToJme();

      } else if(format.equalsIgnoreCase("ms3d")) {
         formatConverter = new MilkToJme();

      } else if(format.equalsIgnoreCase("ase")) {
         formatConverter = new AseToJme();

      } else if(format.equalsIgnoreCase("obj")) {
         formatConverter = new ObjToJme();

      } else {
         LoggingSystem.getLogger().log(Level.WARNING, "Problem loading model: Unrecognised file type");

         return model;
      }

      try {
         // load in model
         formatConverter.setProperty("mtllib", url);
         formatConverter.convert(url.openStream(), byteArrayOutputStream);

         model = (Node) BinaryImporter.getInstance().load(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));

         // output model in jbin format
         BinaryExporter.getInstance().save((Savable) model, new File(MODELS + System.getProperty("file.separator") + binary));

      } catch(IOException e) {
         LoggingSystem.getLogger().log(Level.WARNING, "Problem loading model: " + e.getMessage());
      }

   } else {
      try {
         // load model in jbin format
         model = (Node) BinaryImporter.getInstance().load(url.openStream());

      } catch(IOException e) {
         LoggingSystem.getLogger().log(Level.WARNING, "Problem loading model: " + e.getMessage());
      }
   }

   return model;
}



Then just import the texture, put it into a texture state, and apply it to the model.

When I went to try this, some of the imports are not found. I downloaded the cvs just this morning, am I missing something?



import com.jme.util.LoggingSystem; <-cannot find symbol LoggingSystem



Then these say package doesn't exist.

import com.jmex.model.XMLparser.Converters.AseToJme;

import com.jmex.model.XMLparser.Converters.FormatConverter;

import com.jmex.model.XMLparser.Converters.MaxToJme;

import com.jmex.model.XMLparser.Converters.Md2ToJme;

import com.jmex.model.XMLparser.Converters.Md3ToJme;

import com.jmex.model.XMLparser.Converters.MilkToJme;

import com.jmex.model.XMLparser.Converters.ObjToJme;



But these are found:

import com.jme.util.export.Savable;

import com.jme.util.export.binary.BinaryExporter;

import com.jme.util.export.binary.BinaryImporter;

import java.io.ByteArrayOutputStream;

import java.io.ByteArrayInputStream;

import java.io.File;

import java.io.IOException;

import java.net.URL;

import java.util.logging.Level;

Perhaps the checkout did complete normally?  Are you checking out the project in an IDE?  Check out the getting starting page on the wiki for detailed instructions on how to check out the source code using eclipse.  Rechecking out the project should fix the problem.

Anubis said:

Perhaps the checkout did complete normally?  Are you checking out the project in an IDE?  Check out the getting starting page on the wiki for detailed instructions on how to check out the source code using eclipse.  Rechecking out the project should fix the problem.


Actually, I did already think of this and have done the checkout multiple times. I have jME set up in Netbeans, followed the instructions on getting started and it builds fine. The only problems I had while setting it up were some errors while generating the javadocs. All the tests and such compile and run just fine. I guess I should probably document the errors and submit under a new thread.
I got my textures/materials to load by exporting  files to .obj format, loading them in Milkshape and exporting to .ms3d from there. Then I modified HelloModelLoading.java to use MilkToJme() and ResourceLocatorTool.addResourceLocator() instead of converter.setProperty("mtllib",model)

Next is to get some animation working. It doesn't appear that 3dsmax is exporting the animation data though :(

After trying many different variations of file formats and converters I have finally come to the conclusion that the best solution for exporting from 3dsMax is to use Enders MD5 Reader 2. It was the only method I tried that successfully imported bones, mesh, texture, AND animation so they would all play nice together. Here's how I did it…


import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import md5reader.MD5AnimReader;
import md5reader.MD5MeshReader;
import model.Model;
import model.SkeletalModelInstance;
import model.animation.Animation;
import model.animation.AnimationAnimator;
import model.animation.AnimationController;
import com.jme.app.SimpleGame;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.scene.Spatial;
import com.jme.scene.state.MaterialState;
import com.jme.scene.state.TextureState;
import com.jme.util.TextureManager;

//based on org.md5reader2.test.FishTest.java that comes with md5reader2 by Ender
//tested with models created in 3dsmax and exported with MD5 Exporter v0.1 by BeRSeRKeR
//names of variables and such have been changed to make it more readable for me
//make sure all md5 and texture files are in your classpath <--very important!!

public class MyMD5Loader extends SimpleGame {

//    fileName will later be appended with .md5mesh or .md5anim as appropriate, easier to change this way
    private static final String fileName = "PATH/NAME_OF_YOUR_FILES_HERE"; //WITHOUT THE .MD5MESH OR .MD5ANIM
    private Model md5Mesh;
    private Animation md5Anim;
    private AnimationController animController;
    private SkeletalModelInstance modelInstance;

    public static void main(String[] args) throws IOException {
        final MyMD5Loader app = new MyMD5Loader();
        app.setDialogBehaviour(SimpleGame.FIRSTRUN_OR_NOCONFIGFILE_SHOW_PROPS_DIALOG);
        app.start();
    }

    public MyMD5Loader() throws IOException {
        md5Mesh = loadModel(fileName + ".md5mesh");
        md5Anim = loadAnimation(fileName + ".md5anim");
    }

    protected void simpleInitGame() {
        lightState.get(0).setAmbient(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));

        modelInstance = new SkeletalModelInstance(md5Mesh);
        animController = modelInstance.addAnimationController();
        AnimationAnimator anim = animController.addAnimation(this.md5Anim);
        anim.setInterpolationThreshold(0f);
       
       
        anim.setCycleType(AnimationAnimator.RT_WRAP);//use RT_CLAMP to animate only once
        animController.update(0f);

//        adjust model rotation so it initializes facing towards camera
        Quaternion rotation = new Quaternion();
        rotation.fromAngleAxis(FastMath.PI * 3 / 2, new Vector3f(1, 0, 0));
        modelInstance.setLocalRotation(rotation);
        modelInstance.setModelBound(new BoundingBox());

        modelInstance.updateModelBound();

        cam.setLocation(new Vector3f(0.0f, 15.0f, 75.0f));
        cam.update();
       
//        to change the textures from the ones in the .md5mesh file...
//        print a list showing indexing of meshes attached to the model instance
//        the meshes are named after the texture they use
        for(int i=0;i<modelInstance.getQuantity();i++){
            System.out.println("getChild("+i+") name = "+modelInstance.getChild(i));
        }
//        create a pointer to one of the mesh nodes
        Spatial triMeshNode = modelInstance.getChild(0);

//        create a texture state and apply it to triMeshNode
        Texture texture = TextureManager.loadTexture(MyMD5Loader.class.getClassLoader().
                getResource("FILE_NAME_OF_YOUR_TEXTURE"),   //I used .tga, but I'm sure others are fine
                Texture.MM_LINEAR_LINEAR,Texture.FM_LINEAR);
        TextureState textureState = display.getRenderer().createTextureState();
        textureState.setEnabled(true);
        textureState.setTexture(texture);

        triMeshNode.setRenderState(textureState);
        System.out.println("meshNode = " + triMeshNode);
       
//        if you'd like to play with materials this is how
//        create a meterial state and apply it to triMeshNode
        MaterialState materialState = display.getRenderer().createMaterialState();
        materialState.setEnabled(true);
//        examples of thigs you can change here...
//        materialState.setAmbient(new ColorRGBA(0.0f, 0.0f, 0.0f, 0.1f));
//        materialState.setSpecular(new ColorRGBA(1.0f, 1.0f, 0.0f, 1.0f));
//        materialState.setShininess(128);
       
        triMeshNode.setRenderState(materialState);

//        attach entire model to rootNode
        rootNode.detachAllChildren();
        rootNode.attachChild(modelInstance);

    }

    private Model loadModel(String path) throws IOException {
        InputStream inputStream = getClass().getResourceAsStream("/" + path);

        if (inputStream == null) {
            throw new FileNotFoundException("Cannot find " + path);
        }
        MD5MeshReader reader = new MD5MeshReader();
//        System.out.println(getClass().getClassLoader());
        reader.setProperty(MD5MeshReader.CLASSLOADER, getClass().getClassLoader());
        return reader.readModel(inputStream);
    }

    private Animation loadAnimation(String path) throws IOException {
        InputStream inputStream = getClass().getResourceAsStream("/" + path);

        if (inputStream == null) {
            throw new FileNotFoundException("Cannot find " + path);
        }

        MD5AnimReader animReader = new MD5AnimReader();
        Animation animation = animReader.readAnimation(inputStream);
        return animation;
    }
}

Have you tried md5importer and/or mesh.xml importer? It would be useful if you pointed out the issues of those importers if you tried them as they are actively developed, whilst MD2Reader2 is not…

I was under the impression that md5reader2 and md5importer had been merged. If this is not the case I could certainly take a look at it. As for the mesh.xml, (you're talking about OgreLoader I assume) I skipped that because I haven't taken the time to set up jME2 yet. It sounds great though.