Model guide, is there one?

Started by .jayderyu, February 21, 2009, 05:59:03 AM

Previous topic - Next topic

.jayderyu

I'm sorry to be a pest. All my projects typicly use Primitive shapes. This is the first time I've tried to use a model. I'm experimenting with a advanced model that I downloaded from the web.

I noticed that the Loader loads an array of Object[]. What I'm wondering is there a guide to this.

Are these Objects attached to each other. Do these objects have ID that corrospond to their editor name?
Will I need to Object[0].add(Object).  how do textures get loaded and applied. Is this automatic or do I have
to go through the Objects.

The model i'm using has 57 materials & textures, 32000 faces and I'm not sure how many parts. I think 50. It's a Obj whatever that editor is from. I'm only using it temporarily until I can get some one to help with some low poly models.

paulscode

You can use the Object3D.add() idea to put everything into one Object3D.  That makes it a little more difficult to change textures later if your Object 3D has different textures for different parts.  Another way to do it is to set all the objects as children of an Object3D.createDummyObj().  Just make sure all the sub-objects have a pivot of (0, 0, 0) when you create them in your modeling program.  In Autodesk 3DS Max, you can do this by selecting each object, clicking the "move" icon, choosing "affect pivot only" in the heirarchy tab, then typing the coordinates (0, 0, 0) into the coordinate fields at the bottom of the screen.  I am sure other modeling programs have a way to do this as well.

If you use the TextureManager to create textures with the same names as those used by your model (do this before loading the model), then you won't need to apply the textures to the objects.

As for object ids, the order of the objects in the array returned by the Loader class is the same order that they exist in the 3DS file.  In Autodesk 3ds Max, I give each object in my model a name I can recognize.  Then I can click on the "select by name" icon and write down a list of all the object names in order.  Then I can use that list to know where each object will show up in the array returned by the Loader class.  I am sure you can do something similar if you use a different modeler such as Blender - just play around with in the menus to find a list of objects in your model.

.jayderyu

Ok I tried the createDummyObj(). added all the bits of the array to it. even built each part though I don't think I need too. added the dummy to th world. and I don't see any form of it.

worrying about the textures later. I just don't see even a grey version of the object.
could I be missing something.

I'm incrementing a zoom out at camera.z -1.0 per cycle just to see if the scale is way out their. after a minute I still don't see anything.



EgonOlsen

Maybe a code snippet that shows your loading and merging part will help...

paulscode

#4
Quote from: .jayderyu on February 21, 2009, 08:25:54 PMOk I tried the createDummyObj(). added all the bits of the array to it.
Sounds like you have this part correct.  You call the dummy-object's addChild() method to add each of the objects in the array as children of the dummy-object.

Quote from: .jayderyu on February 21, 2009, 08:25:54 PMbuilt each part though I don't think I need too.
Yes, you need to build each object in the array returned by the Loader class.

Quote from: .jayderyu on February 21, 2009, 08:25:54 PMadded the dummy to th world.
You do not need to add the dummy object to the world, since there is nothing to see, although it won't hurt anything if you do add it to the world.

Quote from: .jayderyu on February 21, 2009, 08:25:54 PMand I don't see any form of it.
The child Object3Ds (the ones in the array returned by the Loader) must be built and added to the world.  The dummy object is what you will use to move, rotate, and scale the model as a whole, but first all the Object3D parts of the model must be added to the world individually before you will be able to see them.

--EDIT--
Oh, one more thing - this describes the second method I mentioned for loading a 3DS object (the "children of a dummy-object" method).  If instead you were trying to use the other method (using Object3D.mergeObjects()), then you should have seen something when you added the root Object3D to the world.  In that case, a code snippet would be helpful to track down the problem, as Egon mentioned.

I use various versions of the following methods in all of my projects to make loading 3ds models easy.  You will notice that I have an additional step where I rotate the loaded objects.  This is to compensate for the fact that all 3ds files exported by Autodesk 3ds Max are oriented incorrectly when loaded into jPCT.  If you are not using Autodesk 3ds Max, you might not need that part, but at least you might find this code useful to use for reference:
public class EasyLoader
{
    // Load a 3ds file, and return an array of Object3D parts
    public static Object3D[] load3DS( String filename, float scale )
    {
        Object3D[] objs = Loader.load3DS(
            Utils.class.getClassLoader().getResourceAsStream(
                filename ), scale );
        if( objs.length < 1 )
        {
            System.out.println( "Unknown file format: " + filename );
        }
       
        // 3ds files always load wrong, so correct the orientation:
        for( int x = 0; x < objs.length; x++ )
        {
            objs[x].rotateX( (float) Math.PI / 2 );
            objs[x].rotateY( (float) Math.PI );
            objs[x].rotateZ( (float) Math.PI );
            objs[x].rotateMesh();
            objs[x].setRotationMatrix( new Matrix() );
        }
       
        return objs;
    }
   
    // Load a multi-object 3ds file, merge all parts, and return a single Object3D:
    public static Object3D loadMerged3DS( String filename, float scale )
    {
        Object3D newObject = new Object3D(0);
       
        Object3D[] objs = Loader.load3DS(
            Utils.class.getClassLoader().getResourceAsStream(
                filename ), scale );
       
        if( objs.length < 1 )
        {
            System.out.println( "Unknown file format: " + filename );
        }
        for( int x = 0; x < objs.length; x++ )
        {
            Object3D part = objs[x];
            part.setCenter( new SimpleVector( 0, 0, 0 ) );
            newObject = Object3D.mergeObjects( newObject, part );
        }
       
        // 3ds files always load wrong, so correct the orientation:
        newObject.rotateX( (float) Math.PI / 2 );
        newObject.rotateY( (float) Math.PI );
        newObject.rotateZ( (float) Math.PI );
        newObject.rotateMesh();
        newObject.setRotationMatrix( new Matrix() );
       
        return newObject;
    }
   
    // Load an md2 file
    public static Object3D loadMD2( String filename, float scale )
    {
        Object3D newObject = new Object3D(0);
       
        newObject = Loader.loadMD2(
            Utils.class.getClassLoader().getResourceAsStream(
                filename ), scale );
       
        // md2 files always load wrong, so correct the orientation:
        newObject.rotateY( (float) Math.PI / 2 );
        newObject.rotateMesh();
        newObject.setRotationMatrix( new Matrix() );
       
        return newObject;
    }
   
    // create and return a pivot with the array of objects as children:
    public static Object3D assimilate( Object3D[] objs )
    {
        if( objs == null || objs.length < 1 )
            return null;
       
        Object3D pivot = Object3D.createDummyObj();
        pivot.setCenter( new SimpleVector( 0, 0, 0 ) );
        for( int x = 0; x < objs.length; x++ )
        {
            pivot.addChild( objs[x] );
        }
        return pivot;
    }
   
    // add the array of Object3D's to the world:
    public static void addObjects( Object3D[] objs, World world )
    {
        if( world == null || objs == null )
            return;
        for( int x = 0; x < objs.length; x++ )
        {
            world.addObject( objs[x] );
        }
    }

    // remove the array of Object3D's to the world:
    public static void removeObjects( Object3D[] objs, World world )
    {
        if( world == null || objs == null )
            return;
        for( int x = 0; x < objs.length; x++ )
        {
            world.removeObject( objs[x] );
        }
    }
   
    // Build all Object3Ds in the array:
    public static void build( Object3D[] objs )
    {
        if( objs == null || objs.length < 1 )
            return;
        for( int x = 0; x < objs.length; x++ )
            if( objs[x] != null )
                objs[x].build();
    }
}


You would use the EasyLoader class to load a 3ds file like this:
        Object3D[] modelParts = EasyLoader.load3DS( "myModel.3ds" );
        EasyLoader.build( modelParts );
        EasyLoader.addObjects( modelParts, myWorld );
       
        Object3D myModel = EasyLoader.assimilate( modelParts );

Then you could use the varriable "myModel" to manipulate your model (scale, rotate, translate, etc).

When you are ready to remove your model from the world, you would simply call:
        EasyLoader.removeObjects( modelParts, myWorld );

.jayderyu

I thought all children of an object by default were added to the world. Ok I will try that.


  public Object3D loadModel(String file, float scale){
    Object3D base = Object3D.createDummyObj();
    Object3D[] list = Loader.load3DS(getResource(file), scale);
   
    for(int i = 0; i < list.length; i++){
      list[i].build();
      base.addChild(list[i]);
    }
   
    return base;
  }