Sophie

Sophie

distrib > Mageia > 7 > i586 > media > core-release-src > by-pkgid > e0641a2f323fd8962bef688c59f29736 > files > 3

java3ds-fileloader-1.2-6.mga7.src.rpm

diff -Nru src/com/microcrowd/loader/java3d/max3ds/CannotChopException.java src-gil/com/microcrowd/loader/java3d/max3ds/CannotChopException.java
--- src/com/microcrowd/loader/java3d/max3ds/CannotChopException.java	2005-10-02 00:01:38.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/CannotChopException.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,43 +1,40 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-package com.microcrowd.loader.java3d.max3ds;
-
-/**
- * Exception thrown by chunks to indicate that the
- * chopper cannot appropriately chop(parse) it.
- * This Exception won't return null for getCause()
- */
-public class CannotChopException extends Exception
-{
-
-	private static final long serialVersionUID = 3304855835929328996L;
-
-	public CannotChopException(Throwable cause)
-    {
-        this("", cause);
-    }
-
-    public CannotChopException(String message, Throwable cause)
-    {
-        super(message, cause);
-    }
-
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+package com.microcrowd.loader.java3d.max3ds;
+
+/**
+ * Exception thrown by chunks to indicate that the
+ * chopper cannot appropriately chop(parse) it.
+ * This Exception won't return null for getCause()
+ */
+public class CannotChopException extends Exception
+{
+    public CannotChopException(Throwable cause)
+    {
+        this("", cause);
+    }
+
+    public CannotChopException(String message, Throwable cause)
+    {
+        super(message, cause);
+    }
+
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/ChunkChopper.java src-gil/com/microcrowd/loader/java3d/max3ds/ChunkChopper.java
--- src/com/microcrowd/loader/java3d/max3ds/ChunkChopper.java	2005-10-02 05:40:51.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/ChunkChopper.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,693 +1,635 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@realvue.com
- */
-
-package com.microcrowd.loader.java3d.max3ds;
-
-import java.awt.Image;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.channels.Channels;
-import java.nio.channels.FileChannel;
-import java.nio.channels.ReadableByteChannel;
-import java.util.HashMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.media.j3d.Behavior;
-import javax.media.j3d.BranchGroup;
-import javax.media.j3d.Light;
-import javax.media.j3d.Texture;
-import javax.media.j3d.TransformGroup;
-import javax.vecmath.Point3f;
-import javax.vecmath.Vector3f;
-
-import com.microcrowd.loader.java3d.max3ds.chunks.Chunk;
-import com.microcrowd.loader.java3d.max3ds.data.KeyFramer;
-import com.sun.j3d.loaders.SceneBase;
-import com.sun.j3d.utils.image.TextureLoader;
-
-/**
- * A singleton flyweight factory responsible for chopping the 
- * data up and sending it to the corresponding 
- * chunks(which are flyweights ala the flyweight pattern)
- * for processing.
- * This will sequentially read a 3ds file, load or
- * skip chunks and subchunks and initialize the data
- * for the chunks.  
- * <p>
- * Retrieved data may be stored as state in the ChunkChopper
- * via {@link #pushData} for use by other chunks.
- * <p> 
- * Features not supported; unknown chunks are skipped.
- * This class is inherently not thread safe.
- */
-public class ChunkChopper
-{
-    private Logger logger = Logger.getLogger(ChunkChopper.class.getName());
-
-    private final BranchGroup    sceneGroup;
-    private final SceneBase      base;
-    private final HashMap        dataMap;
-    private ByteBuffer     chunkBuffer;
-    private Integer        chunkID;
-
-    private TransformGroup currentGroup;
-    private String         currentObjectName;
-    //private final ChunkTester chunkTester = new ChunkTester();
-    private final Chunk mainChunk = new Chunk("MainChunk");
-    private final ChunkMap chunkMap = new ChunkMap(mainChunk);
-
-    private KeyFramer keyFramer = new KeyFramer();
-
-	private final TextureImageLoader imageLoader;
-
-    /** This should be turned on by Loader3DS to view debugging information. */
-    public static boolean debug ;
-
-    /** Current chunk for which debugging info is viewed if debug == true */
-    public static Chunk debugChunk;
-
-
-
-    /**
-     * Initializes the chopper.
-     * @param loader the loader which loads texture images.
-     * @param loade2 
-     */
-    public ChunkChopper(TextureImageLoader imageLoader)
-    {
-        this.sceneGroup = new BranchGroup();
-        this.base = new SceneBase();
-        this.dataMap = new HashMap();
-        base.setSceneGroup(sceneGroup);
-        this.imageLoader = imageLoader;
-    }
-
-    /**
-     * Loads the scene in the file
-     * @param fileIn to load memory mapped scene from.
-     */
-    public synchronized SceneBase loadSceneBase(File fileIn)
-    {
-        chunkBuffer = getMemoryMappedBuffer(fileIn, (int)fileIn.length());
-        return loadSceneBase(chunkBuffer);
-    }
-
-    /**
-     * Loads the scene with the provided inputStream.
-     * @param inputStream the stream from which the scene will be loaded.
-     * @param modelSize the size of the data in the inputStream
-     */
-    public synchronized SceneBase loadSceneBase(InputStream inputStream, int modelSize)
-    {
-        chunkBuffer = getDirectByteBuffer(inputStream, modelSize);
-        return loadSceneBase(chunkBuffer);
-    }
-
-    /**
-     * This sequentially parses the chunks out of the input stream and
-     * constructs the 3D entities represented within.
-     * A Chunk is a little endian data structure consists of a 
-     * 6 byte header followed by subchunks and or data.  
-     * The first short int(little endian) represent the id 
-     * of the chunk.  The next int represent the total 
-     * length of the chunk(total of data, subchunks and chunk header).
-     * <p> 
-     * The first chunk is the main chunk (id=4D4D) and its length
-     * is always the length of the file. It only contains sub chunks.
-     * Other chunks may contain data, subchunks or both.  If the format
-     * of a chunk is unknown skipped.
-     * <p>
-     * Subclasses of chunk will all automagically load the subchunks.  
-     * It is the programmers responsibility to ensure that the data 
-     * preceeding the subchunks is loaded or skipped as 
-     * required and that something useful is done with the data.  If data from the
-     * subchunks is needed in order to initialize components then that code should be
-     * placed in {@link Chunk#initialize}.  Otherwise the data may be dealt with in
-     * {@link Chunk#loadData}.  Also, if a chunk has data preceeding its subchunks
-     * it communicates how many bytes long that data is by returning it from loadData.
-     * <p>
-     * This chopper reads a file in order from beginning to end
-     * @param inputStream the stream with the data to be parsed.
-     * @param modelName name of the model file for display purposes.
-     */
-    public synchronized SceneBase loadSceneBase(ByteBuffer chunkBuffer)
-    {
-        int mainChunkID     = chunkBuffer.getShort();
-        long mainChunkLength = chunkBuffer.getInt();
-
-        long begin = System.currentTimeMillis();     
-        logger.finest("\n\n\n STARTING SUBCUNKS " + (mainChunkLength - 61));
-        try 
-        {
-            loadSubChunks(mainChunk, 0);
-        }
-        catch(CannotChopException e){
-            e.printStackTrace();
-        }
-        logger.finest("FINISHED WITH THE SUBCHUNKS");
-        return base;
-    }
-
-    /**
-     * loads a memory mapped byte buffer from the channel
-     * @param inputStream the file channel to load the data from
-     * @return a direct byte buffer containing all the data of the channel at position 0 
-     */
-    public ByteBuffer getMemoryMappedBuffer(File fileIn, int channelSize)
-    {
-        ByteBuffer chunkBuffer = null;
-        FileChannel channel = null;
-        FileInputStream stream = null;
-        try 
-        {
-            stream = new FileInputStream(fileIn);
-            channel = stream.getChannel();
-            chunkBuffer = ByteBuffer.allocateDirect(channelSize);
-            chunkBuffer.order(ByteOrder.LITTLE_ENDIAN);
-            while(chunkBuffer.hasRemaining())
-            {
-                channel.read(chunkBuffer);
-            }
-            chunkBuffer.position(0);
-        }
-        catch (Exception e) {
-            e.printStackTrace();
-        }
-        finally
-        {
-        	try
-        	{
-        		if(channel != null)
-        		    channel.close();
-        		if(stream != null)
-        			stream.close();
-        	}
-        	catch(Exception e){}
-        }
-        return chunkBuffer;
-    }
-
-    /**
-     * Allocates and loads a byte buffer from the channel
-     * @param inputStream the file channel to load the data from
-     * @return a direct byte buffer containing all the data of the channel at position 0 
-     */
-    public ByteBuffer getDirectByteBuffer(InputStream inputStream, int channelSize)
-    {
-        ByteBuffer chunkBuffer = null;
-        try 
-        {
-            ReadableByteChannel channel = Channels.newChannel(inputStream);
-            chunkBuffer = ByteBuffer.allocateDirect(channelSize);
-            chunkBuffer.order(ByteOrder.LITTLE_ENDIAN);
-            while(chunkBuffer.hasRemaining())
-            {
-                channel.read(chunkBuffer);
-            }
-            channel.close();
-
-            chunkBuffer.position(0);
-        }
-        catch (Exception e) {
-            e.printStackTrace();
-        }
-        return chunkBuffer;
-    }
-
-
-    /**
-     * The base class Chunk takes care of loading subchunks for
-     * all chunks types.  It occurs as follows:
-     * <ol>
-     *     <li>The chunk id (short) is read
-     *     <li>The chunk length(int) is read
-     *     <li>A subchunk is looked up from the map of publish 
-     *         subchunk types of the current chunk.
-     *     <li>If it isn't found during the lookup it is skipped.
-     *     <li>Otherwise it is requested to {@link #pushData} 
-     *     <li>The return value, if there is one, is used to determine 
-     *         where its next subchunk is. A return value of 0 signifies
-     *         that the next subchunk is nigh.
-     *     <li>The chunk's subchunks are then loaded.
-     *     <li>The chunks initialize method is called.
-     * </ol>
-     */
-    protected void loadSubChunks(Chunk parentChunk, int level) throws CannotChopException
-    {
-        level++;
-        while(chunkBuffer.hasRemaining())//hasRemaining() evaluates limit - position.
-        {
-            chunkID         = new Integer(chunkBuffer.getShort());
-            Chunk chunk     = parentChunk.getSubChunk(chunkID);
-
-            int currentChunkLength     = chunkBuffer.getInt() - 6;  //length includes this 6 byte header.
-            int finishedPosition       = chunkBuffer.position() + currentChunkLength;
-            int previousLimit          = chunkBuffer.limit();
-            chunkBuffer.limit(chunkBuffer.position() + currentChunkLength);
-
-            if(currentChunkLength < 0)
-            {
-                debug(parentChunk, level, chunkID, currentChunkLength, chunkBuffer.position(), chunkBuffer.limit());
-                System.err.println("Chunk length is negative... which is real bad. Loading cancelled.");
-                return;
-            }
-            if(debug) {
-                debug(parentChunk, level, chunkID, currentChunkLength, chunkBuffer.position(), chunkBuffer.limit());
-            }
-            if(chunk != null && currentChunkLength != 0) {
-                try {
-                    chunk.loadData(this);
-                }
-                catch(BufferUnderflowException e){
-                    chunkBuffer.position(finishedPosition);
-                    chunkBuffer.limit(previousLimit);
-                    throw new CannotChopException(" tried to read too much data from the buffer. Trying to recover.", e);
-                }
-                try {
-                    if(chunkBuffer.hasRemaining()) {
-                        loadSubChunks(chunk, level);
-                    }
-                    chunk.initialize(this);
-                }
-                catch(CannotChopException e){
-                    logger.log(Level.SEVERE, chunk.toString() + "Trying to continue");
-                }
-            } 
-
-            chunkBuffer.position(finishedPosition);
-            chunkBuffer.limit(previousLimit);
-        }
-    }
-
-    /**
-     * Gets the key framer chunk
-     * These should be their own objects instead of chunks.
-     */
-    public KeyFramer getKeyFramer()
-    {
-        return keyFramer;
-    }
-
-    /**
-     * Adds a group to the choppers scene group
-     * and sets the current name and group.
-     * @param the name of the object to add which
-     * will also be the current name of the object
-     * the chopper is working with.
-     * @param group the current group that the chopper
-     * will be adding things too.
-     */
-    public void addObject(String name, TransformGroup group)
-    {
-        sceneGroup.addChild(group);
-        currentGroup = group;
-        currentObjectName = name;
-        base.addNamedObject(name, group);
-    }
-
-
-
-    /**
-     * Gets the name of the current object
-     * the chopper is working with.  The value returned
-     * from this generally is either set by a NamedObjectChunk 
-     * and is the name of the name of the last object added
-     * or is the name set by setObjectName.
-     * @return the name of the current object being 
-     * constructed.
-     */
-    public String getObjectName()
-    {
-        return currentObjectName;
-    }
-
-
-    /**
-     * Sets the name of the current object.
-     * The name of the current object can also be set
-     * with {@link #addObject}
-     * @param name the name that the current object should be set to.
-     */
-    public void setObjectName(String name)
-    {
-        currentObjectName = name;
-    }
-
-    /**
-     * Gets the group for the current object 
-     * the chopper is working with.  The value returned
-     * from this generally gets set by a NamedObjectChunk 
-     * and is the name of the last object added.
-     * @return the group for the current object being 
-     * constructed.
-     */
-    public TransformGroup getGroup()
-    {
-        return currentGroup;
-    }
-
-    /**
-     * Used to store data that may later be used
-     * by another chunk.
-     * @param key the look up key.
-     * @param data the data to store.
-     */
-    public void pushData(Object key, Object data)
-    {
-        dataMap.put(key, data);
-    }
-
-    /**
-     * Gets a datum that had been retrieved and stored
-     * via {@link #pushData} earlier and removes it.
-     * @param key the key used to store the datum earlier.
-     */
-    public Object popData(Object key)
-    {
-        Object retVal = dataMap.remove(key);
-        return retVal;
-    }
-
-    /**
-     * Sets a named object in the loader.
-     * @param key the key name of the object
-     * @param value the named Object.
-     */
-    public void setNamedObject(String key, Object value)
-    {
-        base.addNamedObject(key, value);
-    }
-
-    /**
-     * Returns true if there have been lights loaded.
-     * @return true if there are lights.
-     */
-    public boolean hasLights()
-    {
-        return (base.getLightNodes() != null && base.getLightNodes().length > 0);
-    }
-
-    /**
-     * Adds a behavior to the scene base.
-     * @param behavior the behavior to add to the scene base.
-     */
-    public void addBehaviorNode(Behavior behavior)
-    {
-        base.addBehaviorNode(behavior);
-    }
-
-
-    /**
-     * Adds a light to the scene base.
-     * @param light the light to add to the scene base.
-     */
-    public void addLightNode(Light light)
-    {
-        base.addLightNode(light);
-    }
-
-
-    /**
-     * Adds a camera transform to the scene base.
-     * @param viewGroup the transform group to add as a view.
-     */
-    public void addViewGroup(TransformGroup viewGroup)
-    {
-        base.addViewGroup(viewGroup);
-    }
-
-    /**
-     * Sets a named Object in the loader.
-     * @param key the key used as the name for which the object will be returned
-     */
-    public Object getNamedObject(String key)
-    {
-        if(key == null)
-            return null;
-        return base.getNamedObjects().get(key);
-    }
-
-    /**
-     * Gets and cast the named object for the
-     * key provided.  Its an error if its not
-     * a transform group.
-     */
-    public TransformGroup getNamedTransformGroup(String key)
-    {
-        Object object = getNamedObject(key);
-        if(object instanceof TransformGroup)
-        {
-            return (TransformGroup)object;
-        }
-        else if (object != null)
-        {
-            logger.log(Level.INFO, "Retrieving " + key + " which is a named object but not useable because "+
-                               " its not a transform group. Its a " + object.getClass().getName());
-        }
-        return null;
-    }
-
-
-    /**
-     * Gets a long from the chunk Buffer
-     */
-    public long getLong()
-    {
-        return chunkBuffer.getLong();
-    }
-
-    /**
-     * Reads a short and returns it as a signed
-     * int.
-     */
-    public int getShort()
-    {
-        return chunkBuffer.getShort();
-    }
-
-    /**
-     * Reads a short and returns it as an unsigned
-     * int.
-     */
-    public int getUnsignedShort()
-    {
-        return chunkBuffer.getShort()&0xFFFF;
-    }
-
-    /**
-     * reads a float from the chunkBuffer.
-     */
-    public float getFloat()
-    {
-        return chunkBuffer.getFloat();
-    }
-
-    /**
-     * Reads 3 floats x,z,y from the chunkbuffer.
-     * Since 3ds has z as up and y as pointing in whereas
-     * java3d has z as pointing forward and y as pointing up;
-     * this returns new Vector3f(x,-z,y)
-     *
-     */
-    public Vector3f getVector()
-    {
-        return new Vector3f(getPoint());
-    }
-    /**
-     * Reads 3 floats x,z,y from the chunkbuffer.
-     * Since 3ds has z as up and y as pointing in whereas
-     * java3d has z as pointing forward and y as pointing up;
-     * this returns new Point3f(x,-z,y)
-     */
-    public Point3f getPoint()
-    {
-        float x = chunkBuffer.getFloat();
-        float z = -chunkBuffer.getFloat();
-        float y = chunkBuffer.getFloat();
-        return new Point3f(x,y,z);
-    }
-
-    /**
-     * Reads an int and returns it 
-     * @return the int read
-     */
-    public int getInt()
-    {
-        return chunkBuffer.getInt();
-    }
-
-    /**
-     * Reads an int and returns it 
-     * unsigned, any ints greater than MAX_INT
-     * will break.
-     */
-    public int getUnsignedInt()
-    {
-        return chunkBuffer.getInt()&0xFFFFFFFF;
-    }
-
-    /**
-     * Reads a byte, unsigns it, returns the corresponding int.
-     * @return the unsigned int corresponding to the read byte.
-     */
-    public int getUnsignedByte()
-    {
-        return chunkBuffer.get()&0xFF;
-    }
-
-    /**
-     * Reads a number of bytes corresponding to the
-     * number of bytes left in the current chunk and returns an array
-     * containing them.
-     * @return an array containing all the bytes for the current chunk. 
-     */
-    public byte[] getChunkBytes()
-    {
-        byte[] retVal = new byte[chunkBuffer.limit() - chunkBuffer.position()];
-        get(retVal);
-        return retVal;
-    }
-
-    /**
-     * Fills bytes with data from the chunk buffer.
-     * @param bytes the array to fill with data.
-     */
-    public void get(byte[] bytes)
-    {
-        chunkBuffer.get(bytes);
-    }
-
-
-
-    /**
-     * This reads bytes until it gets 0x00 and returns
-     * the corresponding string.
-     */
-    public String getString()
-    {
-        StringBuffer stringBuffer = new StringBuffer();
-        char charIn = (char)chunkBuffer.get();
-        while(charIn != 0x00) 
-        {
-            stringBuffer.append(charIn);
-            charIn = (char)chunkBuffer.get();
-        }
-        return stringBuffer.toString();
-    }
-
-    /**
-     * Gets the id of the current chunk.
-     * @return id of the current chunk as read
-     * from the chunkBuffer.  It will be a signed <code>short</code>.
-     */
-    public Integer getID()
-    {
-        return chunkID;
-    }
-
-    /**
-     * Loads the image to server as a texture.
-     * @param textureImageName name of the image that 
-     * is going to be set to be the texture.
-     */
-    public Texture createTexture(String textureImageName)
-    {
-        Image image = imageLoader.getTextureImage(textureImageName);
-        if(image == null)
-        {
-            System.err.println("Cannot load texture image " + textureImageName +
-                               ". Make sure it is in the directory with the model file. " +
-                               "If its a bmp make sure JAI is installed.");
-            return null;
-        }
-        try 
-        {
-            TextureLoader textureLoader = new TextureLoader(image, null);
-            return textureLoader.getTexture(); 
-        }
-        catch(Exception e){
-            e.printStackTrace();
-        }
-        return null;
-    }
-
-    /**
-     * prints some handy information... the chunk hierarchy.
-     */
-    protected void debug(Chunk parentChunk, int level, Integer chunkID, long chunkLength, int position, long limit)
-    {
-        try {
-       for(int i=0; i<level; i++)
-       {
-           System.out.print("  ");
-       }
-       Object child = parentChunk.getSubChunk(chunkID);
-       int id = ((short)chunkID.intValue()) & 0xFFFF;
-       System.out.println(parentChunk + " is " +
-                         (child==null?"skipping":"LOADING")+
-                         ": [id=" + Integer.toHexString(id) + 
-                         ", object= <" + parentChunk.getSubChunk(chunkID) +
-                         ">, chunkLength=" + chunkLength + 
-                         ", position=" + position + 
-                         " limit=" + limit + "]");
-        }
-        catch(Exception e){
-            //We're debugging.. its ok
-            e.printStackTrace();
-        }
-    }
-
-    /**
-     * Prints an exception and exits.
-     */
-    private void exceptAndExit(Throwable exception)
-    {
-        logger.log(Level.SEVERE, "\nThe chunk for loadData method read too much or not enough data from the stream." +
-                            " It needs be skipped or adjusted to read more or less data.");
-        exception.printStackTrace();
-        System.exit(3);
-    }
-
-    /**
-     * Convert the integer to an unsigned number.
-     * @param i the integer to convert.
-     */
-    private static String byteString(int i) 
-    {
-        final char[] digits = {
-	    '0' , '1' , '2' , '3' , '4' , '5' ,
-	    '6' , '7' , '8' , '9' , 'a' , 'b' ,
-	    'c' , 'd' , 'e' , 'f' };
-
-        char[] buf = new char[2];
-        buf[1] = digits[i & 0xF];
-        i >>>= 4;
-        buf[0] = digits[i & 0xF];
-
-        return "0x" + new String(buf).toUpperCase();
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@realvue.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds;
+
+import java.awt.Image;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.HashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.media.j3d.Behavior;
+import javax.media.j3d.BranchGroup;
+import javax.media.j3d.Light;
+import javax.media.j3d.Texture;
+import javax.media.j3d.TransformGroup;
+import javax.vecmath.Point3f;
+import javax.vecmath.Vector3f;
+import com.microcrowd.loader.java3d.max3ds.chunks.Chunk;
+import com.microcrowd.loader.java3d.max3ds.data.KeyFramer;
+import com.sun.j3d.loaders.SceneBase;
+import com.sun.j3d.utils.image.TextureLoader;
+
+/**
+ * A singleton flyweight factory responsible for chopping the 
+ * data up and sending it to the corresponding 
+ * chunks(which are flyweights ala the flyweight pattern)
+ * for processing.
+ * This will sequentially read a 3ds file, load or
+ * skip chunks and subchunks and initialize the data
+ * for the chunks.  
+ * <p>
+ * Retrieved data may be stored as state in the ChunkChopper
+ * via {@link #pushData} for use by other chunks.
+ * <p> 
+ * Features not supported; unknown chunks are skipped.
+ */
+public class ChunkChopper
+{
+    private Logger logger = Logger.getLogger(ChunkChopper.class.getName());
+
+    private Loader3DS      loader;
+    private BranchGroup    sceneGroup;
+    private SceneBase      base;
+    private HashMap        dataMap;
+    private ByteBuffer     chunkBuffer;
+    private Integer        chunkID;
+
+    private TransformGroup currentGroup;
+    private String         currentObjectName;
+    private ChunkTester chunkTester = new ChunkTester();
+    private Chunk mainChunk = new Chunk("MainChunk");
+    private ChunkMap chunkMap = new ChunkMap(mainChunk);
+
+    private KeyFramer keyFramer = new KeyFramer();
+
+    /** This should be turned on by Loader3DS to view debugging information. */
+    public static boolean debug;
+
+    /** Current chunk for which debugging info is viewed if debug == true */
+    public static Chunk debugChunk;
+
+    /**
+     * private singleton constructor.
+     */
+    public ChunkChopper(){}
+
+    /**
+     * This sequentially parses the chunks out of the input stream and
+     * constructs the 3D entities represented within.
+     * A Chunk is a little endian data structure consists of a 
+     * 6 byte header followed by subchunks and or data.  
+     * The first short int(little endian) represent the id 
+     * of the chunk.  The next int represent the total 
+     * length of the chunk(total of data, subchunks and chunk header).
+     * <p> 
+     * The first chunk is the main chunk (id=4D4D) and its length
+     * is always the length of the file. It only contains sub chunks.
+     * Other chunks may contain data, subchunks or both.  If the format
+     * of a chunk is unknown skipped.
+     * <p>
+     * Subclasses of chunk will all automagically load the subchunks.  
+     * It is the programmers responsibility to ensure that the data 
+     * preceeding the subchunks is loaded or skipped as 
+     * required and that something useful is done with the data.  If data from the
+     * subchunks is needed in order to initialize components then that code should be
+     * placed in {@link Chunk#initialize}.  Otherwise the data may be dealt with in
+     * {@link Chunk#loadData}.  Also, if a chunk has data preceeding its subchunks
+     * it communicates how many bytes long that data is by returning it from loadData.
+     * <p>
+     * This chopper reads a file in order from beginning to end
+     * @param inputStream the stream with the data to be parsed.
+     * @param loader the loader that will be configured from the data.
+     * @param modelName name of the model file for display purposes.
+     * @param modelSize size in bytes of the file to read.
+     */
+    public synchronized SceneBase loadSceneBase(InputStream inputStream, Loader3DS loader, int modelSize)
+    {
+        this.loader = loader;
+        this.sceneGroup = new BranchGroup();
+        this.base = new SceneBase();
+        this.dataMap = new HashMap();
+        base.setSceneGroup(sceneGroup);
+
+        //FileChannel channel = null; 
+        ReadableByteChannel channel = null; 
+        try {
+            channel = Channels.newChannel(inputStream);
+            chunkBuffer = getByteBuffer(channel, modelSize);
+            //chunkBuffer = getDirectByteBuffer(channel, modelSize);
+
+            int mainChunkID     = chunkBuffer.getShort();
+            long mainChunkLength = chunkBuffer.getInt();
+
+            long begin = System.currentTimeMillis();     
+            logger.finest("\n\n\n STARTING SUBCUNKS " + (mainChunkLength - 61));
+            try {
+                loadSubChunks(mainChunk, 0);
+            }
+            catch(CannotChopException e){
+                
+            }
+            logger.finest("FINISHED WITH THE SUBCHUNKS");
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+        }
+        finally
+        {
+            try {
+                if(channel != null) {
+                    channel.close();
+                }
+            } catch (Exception e){
+                //Just closing file.. don't care.
+            }
+        }
+        return base;
+    }
+
+    /**
+     * Allocates and loads a byte buffer from the channel
+     * @param channel the file channel to load the data from
+     * @return a direct byte buffer containing all the data of the channel at position 0 
+     */
+    public ByteBuffer getByteBuffer(ReadableByteChannel channel, int channelSize) throws IOException
+    {
+        ByteBuffer chunkBuffer = ByteBuffer.allocate(channelSize);
+        chunkBuffer.order(ByteOrder.LITTLE_ENDIAN);
+        channel.read(chunkBuffer);
+        chunkBuffer.position(0);
+        return chunkBuffer;
+    }
+
+
+    /**
+     * The base class Chunk takes care of loading subchunks for
+     * all chunks types.  It occurs as follows:
+     * <ol>
+     *     <li>The chunk id (short) is read
+     *     <li>The chunk length(int) is read
+     *     <li>A subchunk is looked up from the map of publish 
+     *         subchunk types of the current chunk.
+     *     <li>If it isn't found during the lookup it is skipped.
+     *     <li>Otherwise it is requested to {@link #pushData} 
+     *     <li>The return value, if there is one, is used to determine 
+     *         where its next subchunk is. A return value of 0 signifies
+     *         that the next subchunk is nigh.
+     *     <li>The chunk's subchunks are then loaded.
+     *     <li>The chunks initialize method is called.
+     * </ol>
+     */
+    protected void loadSubChunks(Chunk parentChunk, int level) throws CannotChopException
+    {
+        level++;
+        while(chunkBuffer.hasRemaining())//hasRemaining() evaluates limit - position.
+        {
+            chunkID         = new Integer(chunkBuffer.getShort());
+            Chunk chunk     = parentChunk.getSubChunk(chunkID);
+
+            int currentChunkLength     = chunkBuffer.getInt() - 6;  //length includes this 6 byte header.
+            int finishedPosition       = chunkBuffer.position() + currentChunkLength;
+            int previousLimit          = chunkBuffer.limit();
+            chunkBuffer.limit(chunkBuffer.position() + currentChunkLength);
+
+            if(debug) {
+                debug(parentChunk, level, chunkID, currentChunkLength, chunkBuffer.position(), chunkBuffer.limit());
+            }
+            if(chunk != null && currentChunkLength != 0) {
+                try {
+                    chunk.loadData(this);
+                }
+                catch(BufferUnderflowException e){
+                    chunkBuffer.position(finishedPosition);
+                    chunkBuffer.limit(previousLimit);
+                    throw new CannotChopException(" tried to read too much data from the buffer. Trying to recover.", e);
+                }
+                try {
+                    if(chunkBuffer.hasRemaining()) {
+                        loadSubChunks(chunk, level);
+                    }
+                    chunk.initialize(this);
+                }
+                catch(CannotChopException e){
+                    logger.log(Level.SEVERE, chunk.toString() + "Trying to continue");
+                }
+            } 
+
+            chunkBuffer.position(finishedPosition);
+            chunkBuffer.limit(previousLimit);
+        }
+    }
+
+    /**
+     * Gets the key framer chunk
+     * These should be their own objects instead of chunks.
+     */
+    public KeyFramer getKeyFramer()
+    {
+        return keyFramer;
+    }
+
+    /**
+     * Adds a group to the choppers scene group
+     * and sets the current name and group.
+     * @param the name of the object to add which
+     * will also be the current name of the object
+     * the chopper is working with.
+     * @param group the current group that the chopper
+     * will be adding things too.
+     */
+    public void addObject(String name, TransformGroup group)
+    {
+        sceneGroup.addChild(group);
+        currentGroup = group;
+        currentObjectName = name;
+        base.addNamedObject(name, group);
+    }
+
+
+
+    /**
+     * Gets the name of the current object
+     * the chopper is working with.  The value returned
+     * from this generally is either set by a NamedObjectChunk 
+     * and is the name of the name of the last object added
+     * or is the name set by setObjectName.
+     * @return the name of the current object being 
+     * constructed.
+     */
+    public String getObjectName()
+    {
+        return currentObjectName;
+    }
+
+
+    /**
+     * Sets the name of the current object.
+     * The name of the current object can also be set
+     * with {@link #addObject}
+     * @param name the name that the current object should be set to.
+     */
+    public void setObjectName(String name)
+    {
+        currentObjectName = name;
+    }
+
+    /**
+     * Gets the group for the current object 
+     * the chopper is working with.  The value returned
+     * from this generally gets set by a NamedObjectChunk 
+     * and is the name of the last object added.
+     * @return the group for the current object being 
+     * constructed.
+     */
+    public TransformGroup getGroup()
+    {
+        return currentGroup;
+    }
+
+    /**
+     * Used to store data that may later be used
+     * by another chunk.
+     * @param key the look up key.
+     * @param data the data to store.
+     */
+    public void pushData(Object key, Object data)
+    {
+        dataMap.put(key, data);
+    }
+
+    /**
+     * Gets a datum that had been retrieved and stored
+     * via {@link #pushData} earlier and removes it.
+     * @param key the key used to store the datum earlier.
+     */
+    public Object popData(Object key)
+    {
+        Object retVal = dataMap.remove(key);
+        return retVal;
+    }
+
+    /**
+     * Sets a named object in the loader.
+     * @param key the key name of the object
+     * @param value the named Object.
+     */
+    public void setNamedObject(String key, Object value)
+    {
+        base.addNamedObject(key, value);
+    }
+
+    /**
+     * Returns true if there have been lights loaded.
+     * @return true if there are lights.
+     */
+    public boolean hasLights()
+    {
+        return (base.getLightNodes() != null && base.getLightNodes().length > 0);
+    }
+
+    /**
+     * Adds a behavior to the scene base.
+     * @param behavior the behavior to add to the scene base.
+     */
+    public void addBehaviorNode(Behavior behavior)
+    {
+        base.addBehaviorNode(behavior);
+    }
+
+
+    /**
+     * Adds a light to the scene base.
+     * @param light the light to add to the scene base.
+     */
+    public void addLightNode(Light light)
+    {
+        base.addLightNode(light);
+    }
+
+
+    /**
+     * Adds a camera transform to the scene base.
+     * @param viewGroup the transform group to add as a view.
+     */
+    public void addViewGroup(TransformGroup viewGroup)
+    {
+        base.addViewGroup(viewGroup);
+    }
+
+    /**
+     * Sets a named Object in the loader.
+     * @param key the key used as the name for which the object will be returned
+     */
+    public Object getNamedObject(String key)
+    {
+        if(key == null)
+            return null;
+        return base.getNamedObjects().get(key);
+    }
+
+    /**
+     * Gets and cast the named object for the
+     * key provided.  Its an error if its not
+     * a transform group.
+     */
+    public TransformGroup getNamedTransformGroup(String key)
+    {
+        Object object = getNamedObject(key);
+        if(object instanceof TransformGroup)
+        {
+            return (TransformGroup)object;
+        }
+        else if (object != null)
+        {
+            logger.log(Level.INFO, "Retrieving " + key + " which is a named object but not useable because "+
+                               " its not a transform group. Its a " + object.getClass().getName());
+        }
+        return null;
+    }
+
+
+    /**
+     * Gets a long from the chunk Buffer
+     */
+    public long getLong()
+    {
+        return chunkBuffer.getLong();
+    }
+
+    /**
+     * Reads a short and returns it as a signed
+     * int.
+     */
+    public int getShort()
+    {
+        return chunkBuffer.getShort();
+    }
+
+    /**
+     * Reads a short and returns it as an unsigned
+     * int.
+     */
+    public int getUnsignedShort()
+    {
+        return chunkBuffer.getShort()&0xFFFF;
+    }
+
+    /**
+     * reads a float from the chunkBuffer.
+     */
+    public float getFloat()
+    {
+        return chunkBuffer.getFloat();
+    }
+
+    /**
+     * Reads 3 floats x,z,y from the chunkbuffer.
+     * Since 3ds has z as up and y as pointing in whereas
+     * java3d has z as pointing forward and y as pointing up;
+     * this returns new Vector3f(x,-z,y)
+     *
+     */
+    public Vector3f getVector()
+    {
+        return new Vector3f(getPoint());
+    }
+    /**
+     * Reads 3 floats x,z,y from the chunkbuffer.
+     * Since 3ds has z as up and y as pointing in whereas
+     * java3d has z as pointing forward and y as pointing up;
+     * this returns new Point3f(x,-z,y)
+     */
+    public Point3f getPoint()
+    {
+        float x = chunkBuffer.getFloat();
+        float z = -chunkBuffer.getFloat();
+        float y = chunkBuffer.getFloat();
+        return new Point3f(x,y,z);
+    }
+
+    /**
+     * Reads an int and returns it 
+     * @return the int read
+     */
+    public int getInt()
+    {
+        return chunkBuffer.getInt();
+    }
+
+    /**
+     * Reads an int and returns it 
+     * unsigned, any ints greater than MAX_INT
+     * will break.
+     */
+    public int getUnsignedInt()
+    {
+        return chunkBuffer.getInt()&0xFFFFFFFF;
+    }
+
+    /**
+     * Reads a byte, unsigns it, returns the corresponding int.
+     * @return the unsigned int corresponding to the read byte.
+     */
+    public int getUnsignedByte()
+    {
+        return chunkBuffer.get()&0xFF;
+    }
+
+    /**
+     * Reads a number of bytes corresponding to the
+     * number of bytes left in the current chunk and returns an array
+     * containing them.
+     * @return an array containing all the bytes for the current chunk. 
+     */
+    public byte[] getChunkBytes()
+    {
+        byte[] retVal = new byte[chunkBuffer.limit() - chunkBuffer.position()];
+        get(retVal);
+        return retVal;
+    }
+
+    /**
+     * Fills bytes with data from the chunk buffer.
+     * @param bytes the array to fill with data.
+     */
+    public void get(byte[] bytes)
+    {
+        chunkBuffer.get(bytes);
+    }
+
+
+    /**
+     * Sets the data map used to store values
+     * that chunks may need to retrieve later.
+     * @param dataMap the hashmap that will be used to store
+     * and retrieve values for use by chunks.
+     */
+    public void setDataMap(HashMap dataMap)
+    {
+        this.dataMap = dataMap;
+    }
+
+
+    /**
+     * This reads bytes until it gets 0x00 and returns
+     * the corresponding string.
+     */
+    public String getString()
+    {
+        StringBuffer stringBuffer = new StringBuffer();
+        char charIn = (char)chunkBuffer.get();
+        while(charIn != 0x00) 
+        {
+            stringBuffer.append(charIn);
+            charIn = (char)chunkBuffer.get();
+        }
+        return stringBuffer.toString();
+    }
+
+    /**
+     * Gets the id of the current chunk.
+     * @return id of the current chunk as read
+     * from the chunkBuffer.  It will be a signed <code>short</code>.
+     */
+    public Integer getID()
+    {
+        return chunkID;
+    }
+
+    /**
+     * Loads the image to server as a texture.
+     * @param textureImageName name of the image that 
+     * is going to be set to be the texture.
+     */
+    public Texture createTexture(String textureImageName)
+    {
+        Image image = loader.getTextureImage(textureImageName);
+        if(image == null)
+        {
+            System.err.println("Cannot load texture image " + textureImageName +
+                               ". Make sure it is in the directory with the model file. " +
+                               "If its a bmp make sure JAI is installed.");
+            return null;
+        }
+        try 
+        {
+            TextureLoader textureLoader = new TextureLoader(image, null);
+            return textureLoader.getTexture(); 
+        }
+        catch(Exception e){
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * prints some handy information... the chunk hierarchy.
+     */
+    protected void debug(Chunk parentChunk, int level, Integer chunkID, long chunkLength, int position, long limit)
+    {
+        try {
+       for(int i=0; i<level; i++)
+       {
+           System.out.print("  ");
+       }
+       Object child = parentChunk.getSubChunk(chunkID);
+       int id = ((short)chunkID.intValue()) & 0xFFFF;
+       System.out.println(parentChunk + " is " +
+                         (child==null?"skipping":"LOADING")+
+                         ": [id=" + Integer.toHexString(id) + 
+                         ", object= <" + parentChunk.getSubChunk(chunkID) +
+                         ">, chunkLength=" + chunkLength + 
+                         ", position=" + position + 
+                         " limit=" + limit + "]");
+        }
+        catch(Exception e){
+            //We're debugging.. its ok
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Prints an exception and exits.
+     */
+    private void exceptAndExit(Throwable exception)
+    {
+        logger.log(Level.SEVERE, "\nThe chunk for loadData method read too much or not enough data from the stream." +
+                            " It needs be skipped or adjusted to read more or less data.");
+        exception.printStackTrace();
+        System.exit(3);
+    }
+
+    /**
+     * Convert the integer to an unsigned number.
+     * @param i the integer to convert.
+     */
+    private static String byteString(int i) 
+    {
+        final char[] digits = {
+	    '0' , '1' , '2' , '3' , '4' , '5' ,
+	    '6' , '7' , '8' , '9' , 'a' , 'b' ,
+	    'c' , 'd' , 'e' , 'f' };
+
+        char[] buf = new char[2];
+        buf[1] = digits[i & 0xF];
+        i >>>= 4;
+        buf[0] = digits[i & 0xF];
+
+        return "0x" + new String(buf).toUpperCase();
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/ChunkMap.java src-gil/com/microcrowd/loader/java3d/max3ds/ChunkMap.java
--- src/com/microcrowd/loader/java3d/max3ds/ChunkMap.java	2005-07-25 19:37:32.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/ChunkMap.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,444 +1,444 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds;
-
-import java.util.HashMap;
-import com.microcrowd.loader.java3d.max3ds.chunks.AxisChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.BooleanChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.BoundingBoxChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.CameraChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.Chunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.ColorChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.FacesDescriptionChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.FacesMaterialChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.FloatChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.FramesChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.FramesDescriptionChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.GlobalColorChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.HierarchyInfoChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.KeyFramerInfoChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.LightChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.MaterialChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.NamedObjectChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.PercentageChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.PivotChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.PositionChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.RotationChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.ScaleChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.SmoothingChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.SpotLightChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.StringChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.TextureChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.Vertex2ListChunk;
-import com.microcrowd.loader.java3d.max3ds.chunks.Vertex3ListChunk;
-
-
-/**
- * A Hashmap with the chunk names as values with keys
- * being the chunk id.
- */
-public class ChunkMap extends HashMap
-{
-    private Chunk mainChunk;
-
-    /** Constant designating a chunk as a frames chunk*/
-    public static final Integer FRAMES_CHUNK = new Integer((short)0x0B008);
-    /** Constant designating a chunk as a mesh info chunk*/
-    //public static final Integer AMBIENT_LIGHT_INFO = new Integer((short)0x0B001);
-    public static final Integer MESH_INFO = new Integer((short)0x0B002);
-    //public static final Integer CAMERA_INFO = new Integer((short)0x0B003);
-    //public static final Integer CAMERA_TARGET_INFO = new Integer((short)0x0B004);
-    //public static final Integer OMNI_LIGHT_INFO = new Integer((short)0x0B005);
-    //public static final Integer SPOT_LIGHT_TARGET_INFO = new Integer((short)0x0B006);
-    public static final Integer SPOT_LIGHT_INFO = new Integer((short)0x0B007);
-    /** Key for the name and flags chunk */
-    public static final Integer NAME_AND_FLAGS = new Integer((short)0xB010);
-    /** Key for the pivot chunk */
-    public static final Integer PIVOT = new Integer((short)0xB013);
-    /** Indicates a position track chunk **/
-    public static final Integer POSITION = new Integer((short)0xB020);
-    /** Indicates a scale track chunk */
-    public static final Integer SCALE_TRACK= new Integer((short)0xB022);
-    /** Indicates a rotation track chunk */
-    public static final Integer ROTATION= new Integer((short)0xB021);
-    public static final Integer BOUNDING_BOX    = new Integer((short)0x0B014);
-    /** Indicates a hierarchy info chunk **/
-    public static final Integer HIERARCHY_INFO= new Integer((short)0xB030);
-    /** Signifies that the light is off **/
-    //public static final Integer LIGHT_OFF = new Integer((short)0x4620);
-    /** Signifies that the light is attenuated **/
-    public static final Integer ATTENUATED = new Integer((short)0x4625);
-    public static final Integer RANGE_START = new Integer((short)0x4659);
-    public static final Integer RANGE_END = new Integer((short)0x465A);
-    public static final Integer MULTIPLIER = new Integer((short)0x465B);
-    public static final Integer SPOTLIGHT = new Integer((short)0x4610);
-    public static final Integer COLOR     = new Integer((short)0x0010);
-    public static final Integer VERSION = new Integer((short)0x2);
-    public static final Integer EDITOR = new Integer((short)0x3D3D);
-    public static final Integer KEYFRAMER = new Integer((short)0xB000);
-    /** These are the chunk ids for colors */
-    public static final Integer MATERIAL_NAME = new Integer((short)0xA000);
-    /** ID of the chunk that will be used to represent the ambient color. **/
-    public static final Integer AMBIENT_COLOR = new Integer((short)0xA010);
-    /** ID of the chunk that will be used to represent the diffuse color. **/
-    public static final Integer DIFFUSE_COLOR = new Integer((short)0xA020);
-    /** ID of the chunk that will be used to represent the specular color. **/
-    public static final Integer SPECULAR_COLOR = new Integer((short)0xA030);
-    /** ID of the chunk that will be used to represent the shinines. **/
-    public static final Integer SHININESS = new Integer((short)0xA040);
-    //public static final Integer SHININESS = new Integer((short)0xA041);
-    /** ID of the chunk that will be used to represent the transparency. **/
-    public static final Integer TRANSPARENCY = new Integer((short)0xA050);
-    /** ID of the chunk that will be used to represent the two sided. **/
-    public static final Integer TWO_SIDED = new Integer((short)0xA081);
-    /** ID of the chunk that will be used to represent the texture. **/
-    public static final Integer TEXTURE = new Integer((short)0xA200);
-    /** ID of the chunk that will be used to represent the self illumination. **/
-    /** Represent a mesh object for shapes. */
-    public static final Integer MESH = new Integer((short)0x4100);
-    /** Represent a camera for viewing */
-    public static final Integer CAMERA = new Integer((short)0x4700);
-    /** Represent a light */
-    public static final Integer LIGHT = new Integer((short)0x4600);
-    /** Signifies that the light is off **/
-    //public static final Integer LIGHT_OFF      = new Integer((short)0x4620);
-    //public static final Integer RAYTRACE       = new Integer((short)0x4627);
-    //public static final Integer SHADOWED       = new Integer((short)0x4630);
-    //public static final Integer SHADOW_MAP     = new Integer((short)0x4641);
-    //public static final Integer SHOW_CONE      = new Integer((short)0x4650);
-    //public static final Integer RECTANGULAR    = new Integer((short)0x4651);
-    //public static final Integer OVERSHOOT      = new Integer((short)0x4652);
-    //public static final Integer SPOT_MAP       = new Integer((short)0x4653);
-    //public static final Integer SPOT_ROLL      = new Integer((short)0x4656);
-    //public static final Integer RAY_TRACE_BIAS = new Integer((short)0x4658);
-    /** the id of a texture name chunk.*/
-    public static final Integer TEXTURE_NAME = new Integer((short)0xA300);
-    public static final int TEXTURE_TILING = 0xA351;
-    public static final int TEXBLUR = 0xA353;
-    /** The vertex list from which vertices of a face array will be used. */
-    public static final Integer VERTEX_LIST = new Integer((short)0x4110);
-    /** reference coordinates into the vertex list which represent texture coordinates. */
-    public static final Integer TEXTURE_COORDINATES = new Integer((short)0x4140);
-    /** Local coordinate system of the mesh. */
-    public static final Integer COORDINATE_AXES = new Integer((short)0x4160);
-    /** reference coordinates into the vertex list which represent shape vertex coordinates. */
-    public static final Integer FACES_DESCRIPTION = new Integer((short)0x4120);
-    public static final Integer MATERIAL = new Integer((short)0xAFFF);
-    public static final Integer SCALE = new Integer((short)0x100);
-    public static final Integer NAMED_OBJECT = new Integer((short)0x4000);
-    /**  Key mapping faces material chunk as a child of this chunk */
-    public static final Integer FACES_MATERIAL = new Integer((short)0x4130);
-    /**  Key mapping smoothing chunk as a child of this chunk */
-    public static final Integer SMOOTH = new Integer((short)0x4150);
-
-    /**
-     * singleton constructor.
-     */
-    public ChunkMap(Chunk mainChunk)
-    {
-        this.mainChunk = mainChunk;
-        initializeDataMap();
-    }
-
-    public Chunk get(Integer chunkID)
-    {
-        return (Chunk)super.get(chunkID);
-    }
-
-    /**
-     * looks up the chunk corresponding to chunkID
-     * in the chopper's cache. If its not there
-     * look it up from the parent chunk provided.
-     * @param chunkID the id of the chunk to lookup
-     * @return the chunk for chunkID
-    public synchronized Chunk getChunk(Chunk parentChunk, Integer chunkID)
-    {
-        Chunk chunk = (Chunk)get(chunkID);
-        if(chunk == null && parentChunk != null)
-        {
-            chunk = (Chunk)(parentChunk.getChunkMap().get(chunkID)); //look up chunk from its parent.
-            put(chunkID, chunk);
-        }
-        return chunk;
-    }
-     */
-
-    /**
-     * Called when debugging is turned on. The keys are cast to short so that
-     * they are improperly signed since java will be reading improperly signed
-     * ids out of the file.
-     */
-    private void initializeDataMap()
-    {
-        Chunk keyFramerChunk         = new Chunk("KeyFramerChunk");
-        Chunk editorChunk            = new Chunk("EditorChunk");
-        Chunk triangularMeshChunk    = new Chunk("TriangularMeshChunk");
-
-        Chunk facesDescriptionChunk  = new FacesDescriptionChunk();
-        Chunk framesDescriptionChunk = new FramesDescriptionChunk();
-        Chunk textureChunk           = new TextureChunk();
-        Chunk lightChunk             = new LightChunk();
-        Chunk namedObjectChunk       = new NamedObjectChunk();
-        Chunk materialChunk          = new MaterialChunk();
-        Chunk keyFramerInfoChunk     = new KeyFramerInfoChunk();
-        Chunk spotLightChunk         = new SpotLightChunk();
-        Chunk floatChunk             = new FloatChunk();
-        Chunk framesChunk            = new FramesChunk();
-        Chunk pivotChunk             = new PivotChunk();
-        Chunk positionChunk          = new PositionChunk();
-        Chunk rotationChunk          = new RotationChunk();
-        Chunk scaleChunk             = new ScaleChunk();
-        Chunk hierarchyInfoChunk     = new HierarchyInfoChunk();
-        Chunk boundingBoxChunk       = new BoundingBoxChunk();
-        Chunk stringChunk            = new StringChunk();
-        Chunk globalColorChunk       = new GlobalColorChunk();
-        Chunk booleanChunk           = new BooleanChunk();
-        Chunk percentageChunk        = new PercentageChunk();
-        Chunk cameraChunk            = new CameraChunk();
-        Chunk colorChunk             = new ColorChunk();
-        Chunk vertex3ListChunk       = new Vertex3ListChunk();
-        Chunk vertex2ListChunk       = new Vertex2ListChunk();
-        Chunk axisChunk              = new AxisChunk();
-        Chunk facesMaterialChunk     = new FacesMaterialChunk();
-        Chunk smoothingChunk         = new SmoothingChunk();
-
-
-        //mainChunk.addSubChunk(VERSION, stringChunk);
-        mainChunk.addSubChunk(EDITOR, editorChunk);
-        mainChunk.addSubChunk(KEYFRAMER, keyFramerChunk);
-
-        editorChunk.addSubChunk(MATERIAL, materialChunk);
-        editorChunk.addSubChunk(SCALE, floatChunk);
-        editorChunk.addSubChunk(NAMED_OBJECT, namedObjectChunk);
-
-        keyFramerChunk.addSubChunk(FRAMES_CHUNK, framesChunk);
-        keyFramerChunk.addSubChunk(MESH_INFO, keyFramerInfoChunk);
-        //keyFramerChunk.addSubChunk(AMBIENT_LIGHT_INFO, keyFramerInfoChunk);
-        //keyFramerChunk.addSubChunk(CAMERA_INFO, keyFramerInfoChunk);
-        //keyFramerChunk.addSubChunk(CAMERA_TARGET_INFO, keyFramerInfoChunk);
-        //keyFramerChunk.addSubChunk(OMNI_LIGHT_INFO, keyFramerInfoChunk);
-        //keyFramerChunk.addSubChunk(SPOT_LIGHT_TARGET_INFO, keyFramerInfoChunk);
-        //keyFramerChunk.addSubChunk(SPOT_LIGHT_INFO, keyFramerInfoChunk);
-
-        keyFramerInfoChunk.addSubChunk(NAME_AND_FLAGS, framesDescriptionChunk);
-        keyFramerInfoChunk.addSubChunk(PIVOT, pivotChunk);
-        keyFramerInfoChunk.addSubChunk(POSITION, positionChunk);
-        keyFramerInfoChunk.addSubChunk(ROTATION, rotationChunk);
-        keyFramerInfoChunk.addSubChunk(SCALE_TRACK, scaleChunk);
-        keyFramerInfoChunk.addSubChunk(HIERARCHY_INFO, hierarchyInfoChunk);
-        keyFramerInfoChunk.addSubChunk(BOUNDING_BOX, boundingBoxChunk);
-
-        //spotLightChunk.addSubChunk(LIGHT_OFF, booleanChunk);
-        //spotLightChunk.addSubChunk(RAYTRACE, booleanChunk);
-        //spotLightChunk.addSubChunk(SHADOWED, booleanChunk);
-        //spotLightChunk.addSubChunk(SHOW_CONE, booleanChunk);
-        //spotLightChunk.addSubChunk(RECTANGULAR, booleanChunk);
-        //spotLightChunk.addSubChunk(SHADOW_MAP, booleanChunk);
-        //spotLightChunk.addSubChunk(OVERSHOOT, booleanChunk);
-        //spotLightChunk.addSubChunk(SPOT_MAP, booleanChunk);
-        //spotLightChunk.addSubChunk(SPOT_ROLL, booleanChunk);
-        //spotLightChunk.addSubChunk(RAY_TRACE_BIAS, booleanChunk);
-
-        materialChunk.addSubChunk(MATERIAL_NAME, stringChunk);
-
-        materialChunk.addSubChunk(AMBIENT_COLOR, globalColorChunk);
-        materialChunk.addSubChunk(DIFFUSE_COLOR, globalColorChunk);
-        materialChunk.addSubChunk(SPECULAR_COLOR, globalColorChunk);
-        materialChunk.addSubChunk(TEXTURE, textureChunk);
-
-        materialChunk.addSubChunk(TWO_SIDED, booleanChunk);
-
-        materialChunk.addSubChunk(SHININESS, percentageChunk);
-        materialChunk.addSubChunk(TRANSPARENCY, percentageChunk);
-
-        namedObjectChunk.addSubChunk(MESH, triangularMeshChunk);
-        namedObjectChunk.addSubChunk(CAMERA, cameraChunk);
-        namedObjectChunk.addSubChunk(LIGHT, lightChunk);
-
-        lightChunk.addSubChunk(RANGE_START, floatChunk);
-        lightChunk.addSubChunk(COLOR, colorChunk);
-        lightChunk.addSubChunk(RANGE_END, floatChunk);
-        lightChunk.addSubChunk(MULTIPLIER, floatChunk);
-        lightChunk.addSubChunk(SPOTLIGHT, spotLightChunk);
-
-
-        textureChunk.addSubChunk(TEXTURE_NAME, stringChunk);
-
-        triangularMeshChunk.addSubChunk(VERTEX_LIST, vertex3ListChunk);
-        triangularMeshChunk.addSubChunk(TEXTURE_COORDINATES, vertex2ListChunk);
-        triangularMeshChunk.addSubChunk(FACES_DESCRIPTION, facesDescriptionChunk);
-        triangularMeshChunk.addSubChunk(COORDINATE_AXES, axisChunk);
-
-        facesDescriptionChunk.addSubChunk(FACES_MATERIAL, facesMaterialChunk);
-        facesDescriptionChunk.addSubChunk(SMOOTH, smoothingChunk);
-
-        /*
-           put(new Integer((short)0x0010), "Rgb (float)");
-           put(new Integer((short)0x0011), "Rgb (byte)");
-           put(new Integer((short)0x0012), "Rgb (byte) gamma corrected");
-           put(new Integer((short)0x0013), "Rgb (float) gamma corrected");
-           put(new Integer((short)0x0030), "percent (int)");
-           put(new Integer((short)0x0031), "percent (float)");
-           put(new Integer((short)0x0002), "3DS-Version");
-           put(new Integer((short)0x3D3D), "3D editor chunk");
-           put(new Integer((short)0x0100), "One unit");
-           put(new Integer((short)0x1100), "Background bitmap");
-           put(new Integer((short)0x1101), "Use background bitmap");
-           put(new Integer((short)0x1200), "Background color");
-           put(new Integer((short)0x1201), "Use background color");
-           put(new Integer((short)0x1300), "Gradient colors");
-           put(new Integer((short)0x1301), "Use gradient");
-           put(new Integer((short)0x1400), "Shadow map bias");
-           put(new Integer((short)0x1420), "Shadow map size");
-           put(new Integer((short)0x1450), "Shadow map sample range");
-           put(new Integer((short)0x1460), "Raytrace bias");
-           put(new Integer((short)0x1470), "Raytrace on");
-           put(new Integer((short)0x2100), "Ambient color");
-           put(new Integer((short)0x2200), "Fog");
-           put(new Integer((short)0x2210), "fog background");
-           put(new Integer((short)0x2201), "Use fog");
-           put(new Integer((short)0x2210), "Fog background");
-           put(new Integer((short)0x2300), "Distance queue");
-           put(new Integer((short)0x2310), "Dim background");
-           put(new Integer((short)0x2301), "Use distance queue");
-           put(new Integer((short)0x2302), "Layered fog options");
-           put(new Integer((short)0x2303), "Use layered fog");
-           put(new Integer((short)0x3D3E), "Mesh version");
-           put(new Integer((short)0x4000), "Object block");
-           put(new Integer((short)0x4010), "Object hidden");
-           put(new Integer((short)0x4012), "Object doesn't cast");
-           put(new Integer((short)0x4013), "Matte object");
-           put(new Integer((short)0x4015), "External process on");
-           put(new Integer((short)0x4017), "Object doesn't receive shadows");
-           put(new Integer((short)0x4100), "Triangular mesh");
-           put(new Integer((short)0x4110), "Vertices list");
-           put(new Integer((short)0x4120), "Faces description");
-           put(new Integer((short)0x4130), "Faces material list");
-           put(new Integer((short)0x4140), "Mapping coordinates list");
-           put(new Integer((short)0x4150), "Smoothing group list");
-           put(new Integer((short)0x4160), "Local coordinate system");
-           put(new Integer((short)0x4165), "Object color in editor");
-           put(new Integer((short)0x4181), "External process name");
-           put(new Integer((short)0x4182), "External process parameters");
-           put(new Integer((short)0x4600), "Light");
-           put(new Integer((short)0x4610), "Spotlight");
-           put(new Integer((short)0x4627), "Spot raytrace");
-           put(new Integer((short)0x4630), "Light shadowed");
-           put(new Integer((short)0x4641), "Spot shadow map");
-           put(new Integer((short)0x4650), "Spot show cone");
-           put(new Integer((short)0x4651), "Spot is rectangular");
-           put(new Integer((short)0x4652), "Spot overshoot");
-           put(new Integer((short)0x4653), "Spot map");
-           put(new Integer((short)0x4656), "Spot roll");
-           put(new Integer((short)0x4658), "Spot ray trace bias");
-           put(new Integer((short)0x4620), "Light off");
-           put(new Integer((short)0x4625), "Attenuation on");
-           put(new Integer((short)0x4659), "Range start");
-           put(new Integer((short)0x465A), "Range end");
-           put(new Integer((short)0x465B), "Multiplier");
-           put(new Integer((short)0x4700), "Camera");
-           put(new Integer((short)0x7001), "Window settings");
-           put(new Integer((short)0x7011), "Window description #2 ...");
-           put(new Integer((short)0x7012), "Window description #1 ...");
-           put(new Integer((short)0x7020), "Mesh windows ...");
-           put(new Integer((short)0xAFFF), "Material block");
-           put(new Integer((short)0xA000), "Material name");
-           put(new Integer((short)0xA010), "Ambient color");
-           put(new Integer((short)0xA020), "Diffuse color");
-           put(new Integer((short)0xA030), "Specular color");
-           put(new Integer((short)0xA040), "Shininess percent");
-           put(new Integer((short)0xA041), "Shininess strength percent");
-           put(new Integer((short)0xA050), "Transparency percent");
-           put(new Integer((short)0xA052), "Transparency falloff percent");
-           put(new Integer((short)0xA053), "Reflection blur percent");
-           put(new Integer((short)0xA081), "2 sided");
-           put(new Integer((short)0xA083), "Add trans");
-           put(new Integer((short)0xA084), "Self illum");
-           put(new Integer((short)0xA085), "Wire frame on");
-           put(new Integer((short)0xA087), "Wire thickness");
-           put(new Integer((short)0xA088), "Face map");
-           put(new Integer((short)0xA08A), "In tranc");
-           put(new Integer((short)0xA08C), "Soften");
-           put(new Integer((short)0xA08E), "Wire in units");
-           put(new Integer((short)0xA100), "Render type");
-           put(new Integer((short)0xA240), "Transparency falloff percent present");
-           put(new Integer((short)0xA250), "Reflection blur percent present");
-           put(new Integer((short)0xA252), "Bump map present (true percent)");
-           put(new Integer((short)0xA200), "Texture map 1");
-           put(new Integer((short)0xA33A), "Texture map 2");
-           put(new Integer((short)0xA210), "Opacity map");
-           put(new Integer((short)0xA230), "Bump map");
-           put(new Integer((short)0xA33C), "Shininess map");
-           put(new Integer((short)0xA204), "Specular map");
-           put(new Integer((short)0xA33D), "Self illum. map");
-           put(new Integer((short)0xA220), "Reflection map");
-           put(new Integer((short)0xA33E), "Mask for texture map 1");
-           put(new Integer((short)0xA340), "Mask for texture map 2");
-           put(new Integer((short)0xA342), "Mask for opacity map");
-           put(new Integer((short)0xA344), "Mask for bump map");
-           put(new Integer((short)0xA346), "Mask for shininess map");
-           put(new Integer((short)0xA348), "Mask for specular map");
-           put(new Integer((short)0xA34A), "Mask for self illum. map");
-           put(new Integer((short)0xA34C), "Mask for reflection map");
-           put(new Integer((short)0xA300), "Mapping filename");
-           put(new Integer((short)0xA351), "Mapping parameters");
-           put(new Integer((short)0xA353), "Blur percent");
-           put(new Integer((short)0xA354), "V scale");
-           put(new Integer((short)0xA356), "U scale");
-           put(new Integer((short)0xA358), "U offset");
-           put(new Integer((short)0xA35A), "V offset");
-           put(new Integer((short)0xA35C), "Rotation angle");
-           put(new Integer((short)0xA360), "RGB Luma/Alpha tint 1");
-           put(new Integer((short)0xA362), "RGB Luma/Alpha tint 2");
-           put(new Integer((short)0xA364), "RGB tint R");
-           put(new Integer((short)0xA366), "RGB tint G");
-           put(new Integer((short)0xA368), "RGB tint B");
-           put(new Integer((short)0xB000), "Key Framer");
-           put(new Integer((short)0xB001), "Ambient light information block");
-           put(new Integer((short)0xB002), "Mesh information block");
-           put(new Integer((short)0xB003), "Camera information block");
-           put(new Integer((short)0xB004), "Camera target information block");
-           put(new Integer((short)0xB005), "Omni light information block");
-           put(new Integer((short)0xB006), "Spot light target information block");
-           put(new Integer((short)0xB007), "Spot light information block");
-           put(new Integer((short)0xB008), "Frames (Start and End)");
-           put(new Integer((short)0xB009), "Current Frame");
-           put(new Integer((short)0xB00A), "Animation revision, filename and length");
-           put(new Integer((short)0xB010), "Object name, parameters and hierarchy father");
-           put(new Integer((short)0xB013), "Object pivot point");
-           put(new Integer((short)0xB014), "Bounding Box");
-           put(new Integer((short)0xB015), "Object morph angle");
-           put(new Integer((short)0xB020), "Position track");
-           put(new Integer((short)0xB021), "Rotation track");
-           put(new Integer((short)0xB022), "Scale track");
-           put(new Integer((short)0xB023), "FOV track");
-           put(new Integer((short)0xB024), "Roll track");
-           put(new Integer((short)0xB025), "Color track");
-           put(new Integer((short)0xB026), "Morph track");
-           put(new Integer((short)0xB027), "Hotspot track");
-           put(new Integer((short)0xB028), "Falloff track");
-           put(new Integer((short)0xB029), "Hide track");
-           put(new Integer((short)0xB030), "Hierarchy position");
-        */
-    }
-
-    }
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds;
+
+import java.util.HashMap;
+import com.microcrowd.loader.java3d.max3ds.chunks.AxisChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.BooleanChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.BoundingBoxChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.CameraChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.Chunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.ColorChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.FacesDescriptionChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.FacesMaterialChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.FloatChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.FramesChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.FramesDescriptionChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.GlobalColorChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.HierarchyInfoChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.KeyFramerInfoChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.LightChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.MaterialChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.NamedObjectChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.PercentageChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.PivotChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.PositionChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.RotationChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.ScaleChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.SmoothingChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.SpotLightChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.StringChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.TextureChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.Vertex2ListChunk;
+import com.microcrowd.loader.java3d.max3ds.chunks.Vertex3ListChunk;
+
+
+/**
+ * A Hashmap with the chunk names as values with keys
+ * being the chunk id.
+ */
+public class ChunkMap extends HashMap
+{
+    private Chunk mainChunk;
+
+    /** Constant designating a chunk as a frames chunk*/
+    public static final Integer FRAMES_CHUNK = new Integer((short)0x0B008);
+    /** Constant designating a chunk as a mesh info chunk*/
+    //public static final Integer AMBIENT_LIGHT_INFO = new Integer((short)0x0B001);
+    public static final Integer MESH_INFO = new Integer((short)0x0B002);
+    //public static final Integer CAMERA_INFO = new Integer((short)0x0B003);
+    //public static final Integer CAMERA_TARGET_INFO = new Integer((short)0x0B004);
+    //public static final Integer OMNI_LIGHT_INFO = new Integer((short)0x0B005);
+    //public static final Integer SPOT_LIGHT_TARGET_INFO = new Integer((short)0x0B006);
+    public static final Integer SPOT_LIGHT_INFO = new Integer((short)0x0B007);
+    /** Key for the name and flags chunk */
+    public static final Integer NAME_AND_FLAGS = new Integer((short)0xB010);
+    /** Key for the pivot chunk */
+    public static final Integer PIVOT = new Integer((short)0xB013);
+    /** Indicates a position track chunk **/
+    public static final Integer POSITION = new Integer((short)0xB020);
+    /** Indicates a scale track chunk */
+    public static final Integer SCALE_TRACK= new Integer((short)0xB022);
+    /** Indicates a rotation track chunk */
+    public static final Integer ROTATION= new Integer((short)0xB021);
+    public static final Integer BOUNDING_BOX    = new Integer((short)0x0B014);
+    /** Indicates a hierarchy info chunk **/
+    public static final Integer HIERARCHY_INFO= new Integer((short)0xB030);
+    /** Signifies that the light is off **/
+    //public static final Integer LIGHT_OFF = new Integer((short)0x4620);
+    /** Signifies that the light is attenuated **/
+    public static final Integer ATTENUATED = new Integer((short)0x4625);
+    public static final Integer RANGE_START = new Integer((short)0x4659);
+    public static final Integer RANGE_END = new Integer((short)0x465A);
+    public static final Integer MULTIPLIER = new Integer((short)0x465B);
+    public static final Integer SPOTLIGHT = new Integer((short)0x4610);
+    public static final Integer COLOR     = new Integer((short)0x0010);
+    public static final Integer VERSION = new Integer((short)0x2);
+    public static final Integer EDITOR = new Integer((short)0x3D3D);
+    public static final Integer KEYFRAMER = new Integer((short)0xB000);
+    /** These are the chunk ids for colors */
+    public static final Integer MATERIAL_NAME = new Integer((short)0xA000);
+    /** ID of the chunk that will be used to represent the ambient color. **/
+    public static final Integer AMBIENT_COLOR = new Integer((short)0xA010);
+    /** ID of the chunk that will be used to represent the diffuse color. **/
+    public static final Integer DIFFUSE_COLOR = new Integer((short)0xA020);
+    /** ID of the chunk that will be used to represent the specular color. **/
+    public static final Integer SPECULAR_COLOR = new Integer((short)0xA030);
+    /** ID of the chunk that will be used to represent the shinines. **/
+    public static final Integer SHININESS = new Integer((short)0xA040);
+    //public static final Integer SHININESS = new Integer((short)0xA041);
+    /** ID of the chunk that will be used to represent the transparency. **/
+    public static final Integer TRANSPARENCY = new Integer((short)0xA050);
+    /** ID of the chunk that will be used to represent the two sided. **/
+    public static final Integer TWO_SIDED = new Integer((short)0xA081);
+    /** ID of the chunk that will be used to represent the texture. **/
+    public static final Integer TEXTURE = new Integer((short)0xA200);
+    /** ID of the chunk that will be used to represent the self illumination. **/
+    /** Represent a mesh object for shapes. */
+    public static final Integer MESH = new Integer((short)0x4100);
+    /** Represent a camera for viewing */
+    public static final Integer CAMERA = new Integer((short)0x4700);
+    /** Represent a light */
+    public static final Integer LIGHT = new Integer((short)0x4600);
+    /** Signifies that the light is off **/
+    //public static final Integer LIGHT_OFF      = new Integer((short)0x4620);
+    //public static final Integer RAYTRACE       = new Integer((short)0x4627);
+    //public static final Integer SHADOWED       = new Integer((short)0x4630);
+    //public static final Integer SHADOW_MAP     = new Integer((short)0x4641);
+    //public static final Integer SHOW_CONE      = new Integer((short)0x4650);
+    //public static final Integer RECTANGULAR    = new Integer((short)0x4651);
+    //public static final Integer OVERSHOOT      = new Integer((short)0x4652);
+    //public static final Integer SPOT_MAP       = new Integer((short)0x4653);
+    //public static final Integer SPOT_ROLL      = new Integer((short)0x4656);
+    //public static final Integer RAY_TRACE_BIAS = new Integer((short)0x4658);
+    /** the id of a texture name chunk.*/
+    public static final Integer TEXTURE_NAME = new Integer((short)0xA300);
+    public static final int TEXTURE_TILING = 0xA351;
+    public static final int TEXBLUR = 0xA353;
+    /** The vertex list from which vertices of a face array will be used. */
+    public static final Integer VERTEX_LIST = new Integer((short)0x4110);
+    /** reference coordinates into the vertex list which represent texture coordinates. */
+    public static final Integer TEXTURE_COORDINATES = new Integer((short)0x4140);
+    /** Local coordinate system of the mesh. */
+    public static final Integer COORDINATE_AXES = new Integer((short)0x4160);
+    /** reference coordinates into the vertex list which represent shape vertex coordinates. */
+    public static final Integer FACES_DESCRIPTION = new Integer((short)0x4120);
+    public static final Integer MATERIAL = new Integer((short)0xAFFF);
+    public static final Integer SCALE = new Integer((short)0x100);
+    public static final Integer NAMED_OBJECT = new Integer((short)0x4000);
+    /**  Key mapping faces material chunk as a child of this chunk */
+    public static final Integer FACES_MATERIAL = new Integer((short)0x4130);
+    /**  Key mapping smoothing chunk as a child of this chunk */
+    public static final Integer SMOOTH = new Integer((short)0x4150);
+
+    /**
+     * singleton constructor.
+     */
+    public ChunkMap(Chunk mainChunk)
+    {
+        this.mainChunk = mainChunk;
+        initializeDataMap();
+    }
+
+    public Chunk get(Integer chunkID)
+    {
+        return (Chunk)super.get(chunkID);
+    }
+
+    /**
+     * looks up the chunk corresponding to chunkID
+     * in the chopper's cache. If its not there
+     * look it up from the parent chunk provided.
+     * @param chunkID the id of the chunk to lookup
+     * @return the chunk for chunkID
+    public synchronized Chunk getChunk(Chunk parentChunk, Integer chunkID)
+    {
+        Chunk chunk = (Chunk)get(chunkID);
+        if(chunk == null && parentChunk != null)
+        {
+            chunk = (Chunk)(parentChunk.getChunkMap().get(chunkID)); //look up chunk from its parent.
+            put(chunkID, chunk);
+        }
+        return chunk;
+    }
+     */
+
+    /**
+     * Called when debugging is turned on. The keys are cast to short so that
+     * they are improperly signed since java will be reading improperly signed
+     * ids out of the file.
+     */
+    private void initializeDataMap()
+    {
+        Chunk keyFramerChunk         = new Chunk("KeyFramerChunk");
+        Chunk editorChunk            = new Chunk("EditorChunk");
+        Chunk triangularMeshChunk    = new Chunk("TriangularMeshChunk");
+
+        Chunk facesDescriptionChunk  = new FacesDescriptionChunk();
+        Chunk framesDescriptionChunk = new FramesDescriptionChunk();
+        Chunk textureChunk           = new TextureChunk();
+        Chunk lightChunk             = new LightChunk();
+        Chunk namedObjectChunk       = new NamedObjectChunk();
+        Chunk materialChunk          = new MaterialChunk();
+        Chunk keyFramerInfoChunk     = new KeyFramerInfoChunk();
+        Chunk spotLightChunk         = new SpotLightChunk();
+        Chunk floatChunk             = new FloatChunk();
+        Chunk framesChunk            = new FramesChunk();
+        Chunk pivotChunk             = new PivotChunk();
+        Chunk positionChunk          = new PositionChunk();
+        Chunk rotationChunk          = new RotationChunk();
+        Chunk scaleChunk             = new ScaleChunk();
+        Chunk hierarchyInfoChunk     = new HierarchyInfoChunk();
+        Chunk boundingBoxChunk       = new BoundingBoxChunk();
+        Chunk stringChunk            = new StringChunk();
+        Chunk globalColorChunk       = new GlobalColorChunk();
+        Chunk booleanChunk           = new BooleanChunk();
+        Chunk percentageChunk        = new PercentageChunk();
+        Chunk cameraChunk            = new CameraChunk();
+        Chunk colorChunk             = new ColorChunk();
+        Chunk vertex3ListChunk       = new Vertex3ListChunk();
+        Chunk vertex2ListChunk       = new Vertex2ListChunk();
+        Chunk axisChunk              = new AxisChunk();
+        Chunk facesMaterialChunk     = new FacesMaterialChunk();
+        Chunk smoothingChunk         = new SmoothingChunk();
+
+
+        //mainChunk.addSubChunk(VERSION, stringChunk);
+        mainChunk.addSubChunk(EDITOR, editorChunk);
+        mainChunk.addSubChunk(KEYFRAMER, keyFramerChunk);
+
+        editorChunk.addSubChunk(MATERIAL, materialChunk);
+        editorChunk.addSubChunk(SCALE, floatChunk);
+        editorChunk.addSubChunk(NAMED_OBJECT, namedObjectChunk);
+
+        keyFramerChunk.addSubChunk(FRAMES_CHUNK, framesChunk);
+        keyFramerChunk.addSubChunk(MESH_INFO, keyFramerInfoChunk);
+        //keyFramerChunk.addSubChunk(AMBIENT_LIGHT_INFO, keyFramerInfoChunk);
+        //keyFramerChunk.addSubChunk(CAMERA_INFO, keyFramerInfoChunk);
+        //keyFramerChunk.addSubChunk(CAMERA_TARGET_INFO, keyFramerInfoChunk);
+        //keyFramerChunk.addSubChunk(OMNI_LIGHT_INFO, keyFramerInfoChunk);
+        //keyFramerChunk.addSubChunk(SPOT_LIGHT_TARGET_INFO, keyFramerInfoChunk);
+        //keyFramerChunk.addSubChunk(SPOT_LIGHT_INFO, keyFramerInfoChunk);
+
+        keyFramerInfoChunk.addSubChunk(NAME_AND_FLAGS, framesDescriptionChunk);
+        keyFramerInfoChunk.addSubChunk(PIVOT, pivotChunk);
+        keyFramerInfoChunk.addSubChunk(POSITION, positionChunk);
+        keyFramerInfoChunk.addSubChunk(ROTATION, rotationChunk);
+        keyFramerInfoChunk.addSubChunk(SCALE_TRACK, scaleChunk);
+        keyFramerInfoChunk.addSubChunk(HIERARCHY_INFO, hierarchyInfoChunk);
+        keyFramerInfoChunk.addSubChunk(BOUNDING_BOX, boundingBoxChunk);
+
+        //spotLightChunk.addSubChunk(LIGHT_OFF, booleanChunk);
+        //spotLightChunk.addSubChunk(RAYTRACE, booleanChunk);
+        //spotLightChunk.addSubChunk(SHADOWED, booleanChunk);
+        //spotLightChunk.addSubChunk(SHOW_CONE, booleanChunk);
+        //spotLightChunk.addSubChunk(RECTANGULAR, booleanChunk);
+        //spotLightChunk.addSubChunk(SHADOW_MAP, booleanChunk);
+        //spotLightChunk.addSubChunk(OVERSHOOT, booleanChunk);
+        //spotLightChunk.addSubChunk(SPOT_MAP, booleanChunk);
+        //spotLightChunk.addSubChunk(SPOT_ROLL, booleanChunk);
+        //spotLightChunk.addSubChunk(RAY_TRACE_BIAS, booleanChunk);
+
+        materialChunk.addSubChunk(MATERIAL_NAME, stringChunk);
+
+        materialChunk.addSubChunk(AMBIENT_COLOR, globalColorChunk);
+        materialChunk.addSubChunk(DIFFUSE_COLOR, globalColorChunk);
+        materialChunk.addSubChunk(SPECULAR_COLOR, globalColorChunk);
+        materialChunk.addSubChunk(TEXTURE, textureChunk);
+
+        materialChunk.addSubChunk(TWO_SIDED, booleanChunk);
+
+        materialChunk.addSubChunk(SHININESS, percentageChunk);
+        materialChunk.addSubChunk(TRANSPARENCY, percentageChunk);
+
+        namedObjectChunk.addSubChunk(MESH, triangularMeshChunk);
+        namedObjectChunk.addSubChunk(CAMERA, cameraChunk);
+        namedObjectChunk.addSubChunk(LIGHT, lightChunk);
+
+        lightChunk.addSubChunk(RANGE_START, floatChunk);
+        lightChunk.addSubChunk(COLOR, colorChunk);
+        lightChunk.addSubChunk(RANGE_END, floatChunk);
+        lightChunk.addSubChunk(MULTIPLIER, floatChunk);
+        lightChunk.addSubChunk(SPOTLIGHT, spotLightChunk);
+
+
+        textureChunk.addSubChunk(TEXTURE_NAME, stringChunk);
+
+        triangularMeshChunk.addSubChunk(VERTEX_LIST, vertex3ListChunk);
+        triangularMeshChunk.addSubChunk(TEXTURE_COORDINATES, vertex2ListChunk);
+        triangularMeshChunk.addSubChunk(FACES_DESCRIPTION, facesDescriptionChunk);
+        triangularMeshChunk.addSubChunk(COORDINATE_AXES, axisChunk);
+
+        facesDescriptionChunk.addSubChunk(FACES_MATERIAL, facesMaterialChunk);
+        facesDescriptionChunk.addSubChunk(SMOOTH, smoothingChunk);
+
+        /*
+           put(new Integer((short)0x0010), "Rgb (float)");
+           put(new Integer((short)0x0011), "Rgb (byte)");
+           put(new Integer((short)0x0012), "Rgb (byte) gamma corrected");
+           put(new Integer((short)0x0013), "Rgb (float) gamma corrected");
+           put(new Integer((short)0x0030), "percent (int)");
+           put(new Integer((short)0x0031), "percent (float)");
+           put(new Integer((short)0x0002), "3DS-Version");
+           put(new Integer((short)0x3D3D), "3D editor chunk");
+           put(new Integer((short)0x0100), "One unit");
+           put(new Integer((short)0x1100), "Background bitmap");
+           put(new Integer((short)0x1101), "Use background bitmap");
+           put(new Integer((short)0x1200), "Background color");
+           put(new Integer((short)0x1201), "Use background color");
+           put(new Integer((short)0x1300), "Gradient colors");
+           put(new Integer((short)0x1301), "Use gradient");
+           put(new Integer((short)0x1400), "Shadow map bias");
+           put(new Integer((short)0x1420), "Shadow map size");
+           put(new Integer((short)0x1450), "Shadow map sample range");
+           put(new Integer((short)0x1460), "Raytrace bias");
+           put(new Integer((short)0x1470), "Raytrace on");
+           put(new Integer((short)0x2100), "Ambient color");
+           put(new Integer((short)0x2200), "Fog");
+           put(new Integer((short)0x2210), "fog background");
+           put(new Integer((short)0x2201), "Use fog");
+           put(new Integer((short)0x2210), "Fog background");
+           put(new Integer((short)0x2300), "Distance queue");
+           put(new Integer((short)0x2310), "Dim background");
+           put(new Integer((short)0x2301), "Use distance queue");
+           put(new Integer((short)0x2302), "Layered fog options");
+           put(new Integer((short)0x2303), "Use layered fog");
+           put(new Integer((short)0x3D3E), "Mesh version");
+           put(new Integer((short)0x4000), "Object block");
+           put(new Integer((short)0x4010), "Object hidden");
+           put(new Integer((short)0x4012), "Object doesn't cast");
+           put(new Integer((short)0x4013), "Matte object");
+           put(new Integer((short)0x4015), "External process on");
+           put(new Integer((short)0x4017), "Object doesn't receive shadows");
+           put(new Integer((short)0x4100), "Triangular mesh");
+           put(new Integer((short)0x4110), "Vertices list");
+           put(new Integer((short)0x4120), "Faces description");
+           put(new Integer((short)0x4130), "Faces material list");
+           put(new Integer((short)0x4140), "Mapping coordinates list");
+           put(new Integer((short)0x4150), "Smoothing group list");
+           put(new Integer((short)0x4160), "Local coordinate system");
+           put(new Integer((short)0x4165), "Object color in editor");
+           put(new Integer((short)0x4181), "External process name");
+           put(new Integer((short)0x4182), "External process parameters");
+           put(new Integer((short)0x4600), "Light");
+           put(new Integer((short)0x4610), "Spotlight");
+           put(new Integer((short)0x4627), "Spot raytrace");
+           put(new Integer((short)0x4630), "Light shadowed");
+           put(new Integer((short)0x4641), "Spot shadow map");
+           put(new Integer((short)0x4650), "Spot show cone");
+           put(new Integer((short)0x4651), "Spot is rectangular");
+           put(new Integer((short)0x4652), "Spot overshoot");
+           put(new Integer((short)0x4653), "Spot map");
+           put(new Integer((short)0x4656), "Spot roll");
+           put(new Integer((short)0x4658), "Spot ray trace bias");
+           put(new Integer((short)0x4620), "Light off");
+           put(new Integer((short)0x4625), "Attenuation on");
+           put(new Integer((short)0x4659), "Range start");
+           put(new Integer((short)0x465A), "Range end");
+           put(new Integer((short)0x465B), "Multiplier");
+           put(new Integer((short)0x4700), "Camera");
+           put(new Integer((short)0x7001), "Window settings");
+           put(new Integer((short)0x7011), "Window description #2 ...");
+           put(new Integer((short)0x7012), "Window description #1 ...");
+           put(new Integer((short)0x7020), "Mesh windows ...");
+           put(new Integer((short)0xAFFF), "Material block");
+           put(new Integer((short)0xA000), "Material name");
+           put(new Integer((short)0xA010), "Ambient color");
+           put(new Integer((short)0xA020), "Diffuse color");
+           put(new Integer((short)0xA030), "Specular color");
+           put(new Integer((short)0xA040), "Shininess percent");
+           put(new Integer((short)0xA041), "Shininess strength percent");
+           put(new Integer((short)0xA050), "Transparency percent");
+           put(new Integer((short)0xA052), "Transparency falloff percent");
+           put(new Integer((short)0xA053), "Reflection blur percent");
+           put(new Integer((short)0xA081), "2 sided");
+           put(new Integer((short)0xA083), "Add trans");
+           put(new Integer((short)0xA084), "Self illum");
+           put(new Integer((short)0xA085), "Wire frame on");
+           put(new Integer((short)0xA087), "Wire thickness");
+           put(new Integer((short)0xA088), "Face map");
+           put(new Integer((short)0xA08A), "In tranc");
+           put(new Integer((short)0xA08C), "Soften");
+           put(new Integer((short)0xA08E), "Wire in units");
+           put(new Integer((short)0xA100), "Render type");
+           put(new Integer((short)0xA240), "Transparency falloff percent present");
+           put(new Integer((short)0xA250), "Reflection blur percent present");
+           put(new Integer((short)0xA252), "Bump map present (true percent)");
+           put(new Integer((short)0xA200), "Texture map 1");
+           put(new Integer((short)0xA33A), "Texture map 2");
+           put(new Integer((short)0xA210), "Opacity map");
+           put(new Integer((short)0xA230), "Bump map");
+           put(new Integer((short)0xA33C), "Shininess map");
+           put(new Integer((short)0xA204), "Specular map");
+           put(new Integer((short)0xA33D), "Self illum. map");
+           put(new Integer((short)0xA220), "Reflection map");
+           put(new Integer((short)0xA33E), "Mask for texture map 1");
+           put(new Integer((short)0xA340), "Mask for texture map 2");
+           put(new Integer((short)0xA342), "Mask for opacity map");
+           put(new Integer((short)0xA344), "Mask for bump map");
+           put(new Integer((short)0xA346), "Mask for shininess map");
+           put(new Integer((short)0xA348), "Mask for specular map");
+           put(new Integer((short)0xA34A), "Mask for self illum. map");
+           put(new Integer((short)0xA34C), "Mask for reflection map");
+           put(new Integer((short)0xA300), "Mapping filename");
+           put(new Integer((short)0xA351), "Mapping parameters");
+           put(new Integer((short)0xA353), "Blur percent");
+           put(new Integer((short)0xA354), "V scale");
+           put(new Integer((short)0xA356), "U scale");
+           put(new Integer((short)0xA358), "U offset");
+           put(new Integer((short)0xA35A), "V offset");
+           put(new Integer((short)0xA35C), "Rotation angle");
+           put(new Integer((short)0xA360), "RGB Luma/Alpha tint 1");
+           put(new Integer((short)0xA362), "RGB Luma/Alpha tint 2");
+           put(new Integer((short)0xA364), "RGB tint R");
+           put(new Integer((short)0xA366), "RGB tint G");
+           put(new Integer((short)0xA368), "RGB tint B");
+           put(new Integer((short)0xB000), "Key Framer");
+           put(new Integer((short)0xB001), "Ambient light information block");
+           put(new Integer((short)0xB002), "Mesh information block");
+           put(new Integer((short)0xB003), "Camera information block");
+           put(new Integer((short)0xB004), "Camera target information block");
+           put(new Integer((short)0xB005), "Omni light information block");
+           put(new Integer((short)0xB006), "Spot light target information block");
+           put(new Integer((short)0xB007), "Spot light information block");
+           put(new Integer((short)0xB008), "Frames (Start and End)");
+           put(new Integer((short)0xB009), "Current Frame");
+           put(new Integer((short)0xB00A), "Animation revision, filename and length");
+           put(new Integer((short)0xB010), "Object name, parameters and hierarchy father");
+           put(new Integer((short)0xB013), "Object pivot point");
+           put(new Integer((short)0xB014), "Bounding Box");
+           put(new Integer((short)0xB015), "Object morph angle");
+           put(new Integer((short)0xB020), "Position track");
+           put(new Integer((short)0xB021), "Rotation track");
+           put(new Integer((short)0xB022), "Scale track");
+           put(new Integer((short)0xB023), "FOV track");
+           put(new Integer((short)0xB024), "Roll track");
+           put(new Integer((short)0xB025), "Color track");
+           put(new Integer((short)0xB026), "Morph track");
+           put(new Integer((short)0xB027), "Hotspot track");
+           put(new Integer((short)0xB028), "Falloff track");
+           put(new Integer((short)0xB029), "Hide track");
+           put(new Integer((short)0xB030), "Hierarchy position");
+        */
+    }
+
+    }
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/AxisChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/AxisChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/AxisChunk.java	2005-10-02 00:01:38.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/AxisChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,83 +1,83 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import javax.media.j3d.Transform3D;
-import javax.vecmath.Point3f;
-
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * Extracts the local coordinate that will act 
- * as a shape's axis that will be used by the mesh 
- * info chunk.
- */
-public class AxisChunk extends Chunk
-{
-
-    /**
-     * Loads the local coordinate system for the current mesh.
-     *
-     * @param chopper the ChunkChopper containing the state of the parser. 
-     *
-     * The location of the local coordinate system is defined relative to 
-     * positions and rotations at frame 0.  But the orientation is absolutely
-     * defined.
-     *
-     * With either 3x3 or 4x4 rotation, translation, there
-     * is a simple relationship between each matrix and the resulting coordinate
-     * system. The first three columns of the matrix define the direction vector of the
-     * X, Y and Z axii respectively.
-     * If a 4x4 matrix is defined as:
-     * <code>
-     *     | A B C D |
-     * M = | E F G H |
-     *     | I J K L |
-     *     | M N O P |
-     * </code>
-     * Then the direction vector for each axis is as follows:
-     *
-     * <code>
-     * X-axis = [ A E I ]
-     * Y-axis = [ B F J ]
-     * Z-axis = [ C G K ]
-     * </code>
-     *
-     * @return the actual number of bytes read.  
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        Point3f xAxis  = new Point3f();
-        xAxis  = chopper.getPoint();
-        Point3f zAxis  = chopper.getPoint();
-        Point3f yAxis  = chopper.getPoint();
-        Point3f origin = chopper.getPoint();
-
-        Transform3D transform = new Transform3D(new double[]{
-            xAxis.x,  xAxis.y,  xAxis.z, origin.x, 
-            yAxis.x,  yAxis.y,  yAxis.z, origin.y,  
-            -zAxis.x,  -zAxis.y,  -zAxis.z, origin.z,
-            0,0,0,1});
-        String meshName = chopper.getObjectName();
-        chopper.getKeyFramer().setCoordinateSystem(meshName, transform);
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import javax.media.j3d.Transform3D;
+import javax.vecmath.Point3f;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * Extracts the local coordinate that will act 
+ * as a shape's axis that will be used by the mesh 
+ * info chunk.
+ */
+public class AxisChunk extends Chunk
+{
+    private float value;
+
+    /**
+     * Loads the local coordinate system for the current mesh.
+     *
+     * @param chopper the ChunkChopper containing the state of the parser. 
+     *
+     * The location of the local coordinate system is defined relative to 
+     * positions and rotations at frame 0.  But the orientation is absolutely
+     * defined.
+     *
+     * With either 3x3 or 4x4 rotation, translation, there
+     * is a simple relationship between each matrix and the resulting coordinate
+     * system. The first three columns of the matrix define the direction vector of the
+     * X, Y and Z axii respectively.
+     * If a 4x4 matrix is defined as:
+     * <code>
+     *     | A B C D |
+     * M = | E F G H |
+     *     | I J K L |
+     *     | M N O P |
+     * </code>
+     * Then the direction vector for each axis is as follows:
+     *
+     * <code>
+     * X-axis = [ A E I ]
+     * Y-axis = [ B F J ]
+     * Z-axis = [ C G K ]
+     * </code>
+     *
+     * @return the actual number of bytes read.  
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        Point3f xAxis  = new Point3f();
+        xAxis  = chopper.getPoint();
+        Point3f zAxis  = chopper.getPoint();
+        Point3f yAxis  = chopper.getPoint();
+        Point3f origin = chopper.getPoint();
+
+        Transform3D transform = new Transform3D(new double[]{
+            xAxis.x,  xAxis.y,  xAxis.z, origin.x, 
+            yAxis.x,  yAxis.y,  yAxis.z, origin.y,  
+            -zAxis.x,  -zAxis.y,  -zAxis.z, origin.z,
+            0,0,0,1});
+        String meshName = chopper.getObjectName();
+        chopper.getKeyFramer().setCoordinateSystem(meshName, transform);
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/BooleanChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/BooleanChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/BooleanChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/BooleanChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,46 +1,46 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * A boolean chunk is true if it is present otherwise
- * there is no chunk and that represents false. This chunk
- * will set chopper data to Boolean true with a key that is the id of the chunk.
- * These have no subchunks. Only String data.
- */
-public class BooleanChunk extends Chunk
-{
-    /**
-     * If this method is being called then 
-     * a boolean true will be set on the chunk chopper
-     * with a key that is the id of this chunk.
-     *
-     * @param chopper the chopper on which the boolean true data is to be set 
-     * 
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        chopper.pushData(chopper.getID(), new Boolean(true));
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * A boolean chunk is true if it is present otherwise
+ * there is no chunk and that represents false. This chunk
+ * will set chopper data to Boolean true with a key that is the id of the chunk.
+ * These have no subchunks. Only String data.
+ */
+public class BooleanChunk extends Chunk
+{
+    /**
+     * If this method is being called then 
+     * a boolean true will be set on the chunk chopper
+     * with a key that is the id of this chunk.
+     *
+     * @param chopper the chopper on which the boolean true data is to be set 
+     * 
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        chopper.pushData(chopper.getID(), new Boolean(true));
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/BoundingBoxChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/BoundingBoxChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/BoundingBoxChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/BoundingBoxChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,55 +1,55 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import javax.media.j3d.BoundingBox;
-import javax.vecmath.Point3d;
-import javax.vecmath.Point3f;
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * Loads the bounding box for keyframer of mesh. The pivot
- * is relative to it.
- * {@see KeyFramerInfoChunk} for more information about using
- * animations from a 3ds file
- */
-public class BoundingBoxChunk extends Chunk
-{
-    /**
-     * Gets the bounding box and associates it with the current mes.
-     * @param chopper the ChunkChopper containing the state of the parser.  
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        Point3f min = chopper.getPoint();
-        Point3f max = chopper.getPoint();
-        BoundingBox box = new BoundingBox(new Point3d(min), new Point3d(max));
-
-        Point3f center = new Point3f(max.x - min.x, 
-                max.y - min.y, 
-                max.z - min.z);
-
-            //chopper.getKeyFramer().setBoundingBox(box);
-            chopper.getKeyFramer().setPivotCenter(center);
-    }
-
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import javax.media.j3d.BoundingBox;
+import javax.vecmath.Point3d;
+import javax.vecmath.Point3f;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * Loads the bounding box for keyframer of mesh. The pivot
+ * is relative to it.
+ * {@see KeyFramerInfoChunk} for more information about using
+ * animations from a 3ds file
+ */
+public class BoundingBoxChunk extends Chunk
+{
+    /**
+     * Gets the bounding box and associates it with the current mes.
+     * @param chopper the ChunkChopper containing the state of the parser.  
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        Point3f min = chopper.getPoint();
+        Point3f max = chopper.getPoint();
+        BoundingBox box = new BoundingBox(new Point3d(min), new Point3d(max));
+
+        Point3f center = new Point3f(max.x - min.x, 
+                max.y - min.y, 
+                max.z - min.z);
+
+            //chopper.getKeyFramer().setBoundingBox(box);
+            chopper.getKeyFramer().setPivotCenter(center);
+    }
+
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/CameraChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/CameraChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/CameraChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/CameraChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,65 +1,65 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import javax.media.j3d.Transform3D;
-import javax.media.j3d.TransformGroup;
-import javax.vecmath.Point3d;
-import javax.vecmath.Vector3d;
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-/**
- * Loads percentage values from binary data representing them.
- */
-public class CameraChunk extends Chunk
-{
-    /**
-     * Reads the position and target vectors and subtracts them to get 
-     * an axis of rotation. Translate a transform to position and rotate
-     * on the axis of rotation to point at the target.   The angle 
-     * between the z axis and the axis of rotation is the angle used to
-     * rotate.  The translated and rotated vector is stored it the
-     * chopper as a named object since camera chunks are named. 
-     */
-    public void loadData(ChunkChopper chopper) 
-    {
-        Vector3d yVector  = new Vector3d(0,1,0);
-        Point3d position = new Point3d(chopper.getPoint());
-        Point3d target   = new Point3d(chopper.getPoint());
-        float    bank     = chopper.getFloat();
-        float    lens     = chopper.getFloat();
-
-        //This is the vector for the direction
-        //of the camera. Represented as a line 
-        //from target to position.  We'll use it
-        //as an axis when we bank.
-        //Vector3d cameraDirection = new Vector3d();
-        //cameraDirection.sub(target,position);
-        //AxisAngle4f bankAxisAngle = new AxisAngle4f(cameraDirection, bankAngle);
-
-
-        Transform3D transform = new Transform3D();
-        transform.lookAt(position, target, yVector);
-        transform.invert();
-        ((TransformGroup)chopper.getGroup()).setTransform(transform);
-        chopper.addViewGroup(chopper.getGroup());
-    }  
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import javax.media.j3d.Transform3D;
+import javax.media.j3d.TransformGroup;
+import javax.vecmath.Point3d;
+import javax.vecmath.Vector3d;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+/**
+ * Loads percentage values from binary data representing them.
+ */
+public class CameraChunk extends Chunk
+{
+    /**
+     * Reads the position and target vectors and subtracts them to get 
+     * an axis of rotation. Translate a transform to position and rotate
+     * on the axis of rotation to point at the target.   The angle 
+     * between the z axis and the axis of rotation is the angle used to
+     * rotate.  The translated and rotated vector is stored it the
+     * chopper as a named object since camera chunks are named. 
+     */
+    public void loadData(ChunkChopper chopper) 
+    {
+        Vector3d yVector  = new Vector3d(0,1,0);
+        Point3d position = new Point3d(chopper.getPoint());
+        Point3d target   = new Point3d(chopper.getPoint());
+        float    bank     = chopper.getFloat();
+        float    lens     = chopper.getFloat();
+
+        //This is the vector for the direction
+        //of the camera. Represented as a line 
+        //from target to position.  We'll use it
+        //as an axis when we bank.
+        //Vector3d cameraDirection = new Vector3d();
+        //cameraDirection.sub(target,position);
+        //AxisAngle4f bankAxisAngle = new AxisAngle4f(cameraDirection, bankAngle);
+
+
+        Transform3D transform = new Transform3D();
+        transform.lookAt(position, target, yVector);
+        transform.invert();
+        ((TransformGroup)chopper.getGroup()).setTransform(transform);
+        chopper.addViewGroup(chopper.getGroup());
+    }  
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/Chunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/Chunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/Chunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/Chunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,139 +1,139 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import java.util.HashMap;
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * The base class for all chunks. Chunks are  flyweights and should be managed
- * by  {@link ChunkChopper}  Every chunk should know how many bytes of data(or
- * be able figure out)  to read before its subchunks are found. Chunks that only have
- * subchunks need not overrided loadData.
- * Chunks may store data for later use in loadData with {@link pushData}
- * If a chunk needs to initialize components with from subchunks, that data
- * can be retrieved with  {@link ChunkChopper#popData} inside the  {@link
- * #initialize} method.  {@link #loadData} is called at the beginning of the
- * loading process, before any data or subchunks have been loaded(the chunk
- * itself must load its data).
- * <p>
- * During loadData, if the length of data before subchunks is unknown,
- * {@link ChunkChopper#getChunkBytes} may be called and all the data
- * for the chunk(including subchunks) will be read and returned.
- */
-public class Chunk 
-{
-    private HashMap subChunkMap = new HashMap();
-    private String name;
-    private String description;
-
-    /**
-     * default no-arg constructror.
-     */
-    public Chunk(String chunkName)
-    {
-        name = chunkName;
-    }
-
-    /**
-     * default no-arg constructror.
-     */
-    public Chunk()
-    {
-    }
-
-    public void addSubChunk(Integer id, Chunk subChunk)
-    {
-        subChunkMap.put(id, subChunk);
-    }
-
-    public Chunk getSubChunk(Integer id)
-    {
-        return (Chunk)subChunkMap.get(id);
-    }
-
-    /**
-     * This method is called after all the  current chunks subchunks are
-     * loaded. Any data stored by those subchunks may be retrieved via {@link
-     * ChunkChopper#popData}
-     * The default implementation does nothing.
-     *
-     * @param chopper may contain data loaded by subchunks. 
-     */
-    public void initialize(ChunkChopper chopper) 
-    {
-    }
-
-    /**
-     * This is called by the chunk chopper before any of the chunk's 
-     * subchunks  are loaded.  Any data loaded that may need to be 
-     * used later by superchunks should be stored in
-     * the chunk chopper via {@link ChunkChopper#popData}
-     * The default implementation does nothing.
-     * @param chopper may contain data loaded by subchunks. 
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-    }
-
-    /**
-     * Sets  nice human readable name for the chunk.
-     * @param name to use for display of this chunk.
-     */
-    public final void setName(String name)
-    {
-        this.name = name;
-    }
-
-    /**
-     * Gets a human readable name for the chunk.
-     * @return name used to display the chunk.
-     */
-    public final String getName()
-    {
-        return name;
-    }
-
-    public final String getDescription()
-    {
-        return description;
-    }
-
-    public final void setDescription(String desc)
-    {
-        description = desc;
-    }
-
-    /**
-     * Returns the name of this chunk.
-     * If the name is null then it just
-     * returns the unqualified class name.
-     */
-    public String toString()
-    {
-        if (getName() != null)
-            return getName();
-        String className = getClass().getName();
-        return className.substring(className.lastIndexOf('.') + 1, 
-            className.length()); 
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import java.util.HashMap;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * The base class for all chunks. Chunks are  flyweights and should be managed
+ * by  {@link ChunkChopper}  Every chunk should know how many bytes of data(or
+ * be able figure out)  to read before its subchunks are found. Chunks that only have
+ * subchunks need not overrided loadData.
+ * Chunks may store data for later use in loadData with {@link pushData}
+ * If a chunk needs to initialize components with from subchunks, that data
+ * can be retrieved with  {@link ChunkChopper#popData} inside the  {@link
+ * #initialize} method.  {@link #loadData} is called at the beginning of the
+ * loading process, before any data or subchunks have been loaded(the chunk
+ * itself must load its data).
+ * <p>
+ * During loadData, if the length of data before subchunks is unknown,
+ * {@link ChunkChopper#getChunkBytes} may be called and all the data
+ * for the chunk(including subchunks) will be read and returned.
+ */
+public class Chunk 
+{
+    private HashMap subChunkMap = new HashMap();
+    private String name;
+    private String description;
+
+    /**
+     * default no-arg constructror.
+     */
+    public Chunk(String chunkName)
+    {
+        name = chunkName;
+    }
+
+    /**
+     * default no-arg constructror.
+     */
+    public Chunk()
+    {
+    }
+
+    public void addSubChunk(Integer id, Chunk subChunk)
+    {
+        subChunkMap.put(id, subChunk);
+    }
+
+    public Chunk getSubChunk(Integer id)
+    {
+        return (Chunk)subChunkMap.get(id);
+    }
+
+    /**
+     * This method is called after all the  current chunks subchunks are
+     * loaded. Any data stored by those subchunks may be retrieved via {@link
+     * ChunkChopper#popData}
+     * The default implementation does nothing.
+     *
+     * @param chopper may contain data loaded by subchunks. 
+     */
+    public void initialize(ChunkChopper chopper) 
+    {
+    }
+
+    /**
+     * This is called by the chunk chopper before any of the chunk's 
+     * subchunks  are loaded.  Any data loaded that may need to be 
+     * used later by superchunks should be stored in
+     * the chunk chopper via {@link ChunkChopper#popData}
+     * The default implementation does nothing.
+     * @param chopper may contain data loaded by subchunks. 
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+    }
+
+    /**
+     * Sets  nice human readable name for the chunk.
+     * @param name to use for display of this chunk.
+     */
+    public final void setName(String name)
+    {
+        this.name = name;
+    }
+
+    /**
+     * Gets a human readable name for the chunk.
+     * @return name used to display the chunk.
+     */
+    public final String getName()
+    {
+        return name;
+    }
+
+    public final String getDescription()
+    {
+        return description;
+    }
+
+    public final void setDescription(String desc)
+    {
+        description = desc;
+    }
+
+    /**
+     * Returns the name of this chunk.
+     * If the name is null then it just
+     * returns the unqualified class name.
+     */
+    public String toString()
+    {
+        if (getName() != null)
+            return getName();
+        String className = getClass().getName();
+        return className.substring(className.lastIndexOf('.') + 1, 
+            className.length()); 
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/ColorChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/ColorChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/ColorChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/ColorChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,82 +1,82 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import javax.vecmath.Color3f;
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * Loads colors from binary data representing them.
- */
-public class ColorChunk extends Chunk
-{
-    protected int currentColorType;
-
-    private static final int FLOAT_COLOR = 0x10;
-    private static final int BYTE_COLOR = 0x11;
-    private static final int BYTE_COLOR_GAMMA = 0x12;
-    private static final int FLOAT_COLOR_GAMMA = 0x13;
-
-    /**
-     * Based on the color type retrieved
-     * from {@link #getColorType} loads
-     * an rgb or float color and pushes
-     * it onto the chunk chopper.
-     *
-     * @param chopper the chopper that will store the color data.  
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        int colorType = getColorType(chopper);
-        if (colorType == BYTE_COLOR) 
-        {
-            float r = (chopper.getUnsignedByte()) / 255f;
-            float g = (chopper.getUnsignedByte()) / 255f;
-            float b = (chopper.getUnsignedByte()) / 255f;
-            Color3f color = new Color3f(r, g, b);
-            chopper.pushData(chopper.getID(), color);
-        } 
-        else if (colorType == FLOAT_COLOR) 
-        {
-            Color3f color = new Color3f(chopper.getFloat(), chopper.getFloat(), chopper.getFloat());
-            chopper.pushData(chopper.getID(), color);
-        }
-        else 
-        {
-            throw new IllegalArgumentException("Only RGB colors are enabled. ChunkID=" 
-                    + Integer.toHexString((byte)chopper.getID().intValue()) 
-                    + " Color type = " + Integer.toHexString((byte)colorType));
-        }
-    }
-
-    /**
-     * Gets the color type for this chunk.
-     * @param chopper with the information the
-     * chunk may use to determine color type
-     * @return the color type for the chunk retrieved
-     * from the chopper using this chunks id.
-     */
-    protected int getColorType(ChunkChopper chopper)
-    {
-        return chopper.getID().intValue();
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import javax.vecmath.Color3f;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * Loads colors from binary data representing them.
+ */
+public class ColorChunk extends Chunk
+{
+    protected int currentColorType;
+
+    private static final int FLOAT_COLOR = 0x10;
+    private static final int BYTE_COLOR = 0x11;
+    private static final int BYTE_COLOR_GAMMA = 0x12;
+    private static final int FLOAT_COLOR_GAMMA = 0x13;
+
+    /**
+     * Based on the color type retrieved
+     * from {@link #getColorType} loads
+     * an rgb or float color and pushes
+     * it onto the chunk chopper.
+     *
+     * @param chopper the chopper that will store the color data.  
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        int colorType = getColorType(chopper);
+        if (colorType == BYTE_COLOR) 
+        {
+            float r = (chopper.getUnsignedByte()) / 255f;
+            float g = (chopper.getUnsignedByte()) / 255f;
+            float b = (chopper.getUnsignedByte()) / 255f;
+            Color3f color = new Color3f(r, g, b);
+            chopper.pushData(chopper.getID(), color);
+        } 
+        else if (colorType == FLOAT_COLOR) 
+        {
+            Color3f color = new Color3f(chopper.getFloat(), chopper.getFloat(), chopper.getFloat());
+            chopper.pushData(chopper.getID(), color);
+        }
+        else 
+        {
+            throw new IllegalArgumentException("Only RGB colors are enabled. ChunkID=" 
+                    + Integer.toHexString((byte)chopper.getID().intValue()) 
+                    + " Color type = " + Integer.toHexString((byte)colorType));
+        }
+    }
+
+    /**
+     * Gets the color type for this chunk.
+     * @param chopper with the information the
+     * chunk may use to determine color type
+     * @return the color type for the chunk retrieved
+     * from the chopper using this chunks id.
+     */
+    protected int getColorType(ChunkChopper chopper)
+    {
+        return chopper.getID().intValue();
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/FacesDescriptionChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/FacesDescriptionChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/FacesDescriptionChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/FacesDescriptionChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,322 +1,322 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-import javax.media.j3d.Appearance;
-import javax.media.j3d.Geometry;
-import javax.media.j3d.Material;
-import javax.media.j3d.Shape3D;
-import javax.media.j3d.TransformGroup;
-import javax.vecmath.Color3f;
-import javax.vecmath.Point3f;
-import javax.vecmath.TexCoord2f;
-import javax.vecmath.Vector3f;
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-import com.microcrowd.loader.java3d.max3ds.ChunkMap;
-import com.sun.j3d.utils.geometry.GeometryInfo;
-import com.sun.j3d.utils.geometry.NormalGenerator;
-import com.sun.j3d.utils.geometry.Stripifier;
-
-/**
- * This chunk describes all the triangles that make up a mesh.
- * Each triangle is defined in terms of three indexes each of which
- * is a point reference to a vertex in the vertex list loaded
- * by the triangular mesh chunk.
- * After loading the Smoothing chunk the normals for the mesh
- * are generated accordingly.
- */
-public class FacesDescriptionChunk extends Chunk
-{
-    public static final Appearance DEFAULT_APPEARANCE;
-
-    private Point3f[] currentVertices;
-    private TexCoord2f[] textureTriangles;
-    private PointMapper shareMap;
-
-    static {
-        DEFAULT_APPEARANCE= new Appearance();
-        Material defaultMaterial = new Material();
-        defaultMaterial.setAmbientColor(new Color3f(.5f, .5f, .5f));
-        //defaultMaterial.setDiffuseColor(new Color3f(.5f, .5f, .5f));
-        //defaultMaterial.setSpecularColor(new Color3f(.5f, .5f, .5f));
-        DEFAULT_APPEARANCE.setMaterial(defaultMaterial);
-    }
-
-
-
-    /**
-     * Maintains a two way mapping between coordinates
-     * and vertices.  A coordinate to vertex is one to many 
-     * Vertex to coordinate is one to one.
-     * In this class we maintain the definition that a coordinate
-     * is a point in 3D space and a vertex is a coordinate serving
-     * as one of three defining a face.
-     */
-    private class PointMapper extends HashMap
-    {
-        private Set[] coordinateSet;
-        /**
-         * Constructs a PointMapper with a
-         * the number of coordinates initialized to size.
-         * @param size the number of coordinates in the set.
-         */
-        public PointMapper(int size)
-        {
-            coordinateSet = new Set[size];
-        }
-
-        /**
-         * Adds an index for a coordinate to the set of vertices mapped
-         * to that coordinate. All coordinates may have one or more vertices
-         * that use them.  
-         * @param coordinate the coordinate being mapped to the vertexNum 
-         * @param vertexNum the number of the vertex using the coordinate
-         */
-        public void addCoordinate(Point3f coordinate, int vertexNum)
-        {
-            Set sharedCoordinates = (Set)get(coordinate); 
-            if(sharedCoordinates == null)
-            {
-                sharedCoordinates = new HashSet();
-                put(coordinate, sharedCoordinates);
-            }
-            sharedCoordinates.add(new Integer(vertexNum));
-            coordinateSet[vertexNum] = sharedCoordinates;
-        }
-
-        /**
-         * Gets all the coordinates for a particular vertex that
-         * also share that vertex after the smoothing groups have been
-         * accounted for.  Any coordinates that are not both shared
-         * by the vertex and do not share a smoothing group with the coordinate
-         * will not be returned.
-         * @param coordinateNum the number of the coordinate to get the set
-         * of vertices for that share it.
-         * @param smoothGroups the group of coordinates used to filter out the 
-         * non-shared vertices.
-         */
-        public Set getSharedCoordinates(int coordinateNum, int[] smoothGroups)
-        {
-            Set returnSet = new HashSet();
-            Set sharingVertices = coordinateSet[coordinateNum];
-            Iterator vertices = sharingVertices.iterator();
-            int coordinateMask = smoothGroups[coordinateNum];
-            while(vertices.hasNext())
-            {
-                Integer vertex = (Integer)vertices.next();
-                int nextMask = smoothGroups[vertex.intValue()];
-                if((nextMask & coordinateMask) != 0)
-                {
-                    returnSet.add(vertex);
-                }
-            }
-            return returnSet; 
-        }
-    }
-
-    /**
-     * Reads the number of faces from the ChunkChopper.
-     * For each face read three shorts representing
-     * indices of vertices loaded by the TriangularMeshChunk
-     *
-     * @param chopper chopper the has the data  
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        int numFaces = chopper.getUnsignedShort();
-        shareMap = new PointMapper(numFaces*3);
-        Point3f[] coordinates = (Point3f[])chopper.popData(ChunkMap.VERTEX_LIST);
-        TexCoord2f[] texturePoints = (TexCoord2f[])chopper.popData(ChunkMap.TEXTURE_COORDINATES);
-
-        currentVertices = new Point3f[numFaces * 3];
-        chopper.pushData(chopper.getID(), currentVertices);
-        if (texturePoints != null) 
-        {
-            textureTriangles = new TexCoord2f[numFaces * 3];
-        }
-
-        for (int i = 0; i < numFaces; i++) {
-            int vertexIndex = i * 3;
-            int index0 = chopper.getUnsignedShort();
-            int index1 = chopper.getUnsignedShort();
-            int index2 = chopper.getUnsignedShort();
-
-            currentVertices[vertexIndex] = coordinates[index0];
-            currentVertices[vertexIndex + 1] = coordinates[index1];
-            currentVertices[vertexIndex + 2] = coordinates[index2];
-
-            shareMap.addCoordinate(coordinates[index0], vertexIndex);
-            shareMap.addCoordinate(coordinates[index1], vertexIndex+1);
-            shareMap.addCoordinate(coordinates[index2], vertexIndex+2);
-
-
-            if (textureTriangles != null) {
-                textureTriangles[vertexIndex] = texturePoints[index0];
-                textureTriangles[vertexIndex + 1] = texturePoints[index1];
-                textureTriangles[vertexIndex + 2] = texturePoints[index2];
-            }
-
-            //This is a bit masked value that is used to determine which edges are visible... not needed.
-            chopper.getUnsignedShort(); 
-        }
-    }
-
-    /**
-     * Loads a mesh onto the scene graph with the specified data
-     * from subchunks.
-     * If there is no material, this will put a default
-     * material on the shape.
-     */
-    public void initialize(ChunkChopper chopper)
-    {
-        final String materialName = (String)chopper.popData(ChunkMap.FACES_MATERIAL);
-        final int[]  smoothGroups = (int[])chopper.popData(ChunkMap.SMOOTH);
-        Shape3D      shape        = new Shape3D();
-        GeometryInfo geometryInfo = new GeometryInfo(GeometryInfo.TRIANGLE_ARRAY);
-
-        geometryInfo.setCoordinates(currentVertices);
-        TransformGroup transformGroup = (TransformGroup)chopper.getGroup();
-        transformGroup.addChild(shape);
-
-        if (textureTriangles != null) 
-        {
-            geometryInfo.setTextureCoordinateParams(1, 2);
-            geometryInfo.setTextureCoordinates(0, textureTriangles);
-        }
-
-        if(materialName != null)
-        {
-            shape.setAppearance((Appearance)chopper.getNamedObject(materialName));
-        }
-        else
-        {
-            shape.setAppearance(DEFAULT_APPEARANCE);
-        }
-        if(smoothGroups == null)
-        {
-            NormalGenerator normalGenerator = new NormalGenerator();
-            geometryInfo.recomputeIndices();
-            normalGenerator.generateNormals(geometryInfo);
-        }
-        else
-        {
-            Vector3f[] normals = generateNormals(currentVertices);
-            Vector3f[] smoothNormals = smoothNormals(normals, shareMap, smoothGroups);
-            geometryInfo.setNormals(smoothNormals);
-        }
-
-        new Stripifier().stripify(geometryInfo);
-        shape.setGeometry(geometryInfo.getGeometryArray());
-        shape.setCapability(Geometry.ALLOW_INTERSECT);
-        com.sun.j3d.utils.picking.PickTool.setCapabilities(shape, com.sun.j3d.utils.picking.PickTool.INTERSECT_FULL);
-
-        currentVertices=null;
-        textureTriangles=null;
-    }
-
-    /**
-     * Takes all the normals for all the vertices and averages them with
-     * normals with which they share a coordinate and at least one smooth group.
-     * @param currentNormals the normals for each face.
-     * @param sharedPoints the point mapper that will choose which points are 
-     * and which are not shared.
-     * @param smoothGroups the indexed list of group masks loaded by the smooth chunk.
-     * @return normals averaged among the shared vertices in their smoothing groups.
-     */
-    public Vector3f[] smoothNormals(Vector3f[] currentNormals, PointMapper sharedPoints, int[] smoothGroups)
-    {
-        Vector3f[] smoothNormals = new Vector3f[currentNormals.length];
-        for(int i=0; i < currentNormals.length; i++)
-        {
-            Set otherPoints = sharedPoints.getSharedCoordinates(i, smoothGroups);
-            if(otherPoints != null)
-            {
-                Vector3f[] sharedNormals = new Vector3f[otherPoints.size()]; 
-                Iterator pointIterator = otherPoints.iterator();
-                for(int j = 0; j < sharedNormals.length; j++)
-                {
-                    sharedNormals[j] = currentNormals[((Integer)pointIterator.next()).intValue()];
-                }
-                smoothNormals[i] = averageNormals(sharedNormals);
-            }
-            else
-            {
-                smoothNormals[i] = currentNormals[i];
-            }
-        }
-        return smoothNormals;
-    }
-
-    /**
-     * Averages the normals provided in order to provide
-     * smooth, noncreased appearances for meshes.
-     * @param normals the normals that should be averaged
-     * @return a normalized normal that can be used in place
-     * of all the normals provided.
-     */
-    public Vector3f averageNormals(Vector3f[] normals)
-    {
-        Vector3f newNormal = new Vector3f();
-        for(int i=0; i < normals.length; i++)
-        {
-            newNormal.add(normals[i]);
-        }
-        newNormal.normalize();
-        return newNormal;
-    }
-
-    /**
-     * Generates normals for each vertex of each
-     * face that are absolutely normal to the face.
-     * @param point0 The first point of the face
-     * @param point1 The second point of the face
-     * @param point2 The third point of the face
-     * @return the three normals that should be 
-     * used for the triangle represented by the parameters.
-     */
-    private Vector3f[] generateNormals(Point3f points[])
-    {
-        Vector3f[] normals = new Vector3f[points.length];
-        for(int i=0; i < normals.length;)
-        {
-            Vector3f normal    = new Vector3f();
-            Vector3f v1        = new Vector3f();
-            Vector3f v2        = new Vector3f();
-    
-            v1.sub(points[i+1], points[i]);
-            v2.sub(points[i+2], points[i]);
-            normal.cross(v1, v2);
-            normal.normalize();
-
-    
-            normals[i++] = new Vector3f(normal);
-            normals[i++] = new Vector3f(normal);
-            normals[i++] = new Vector3f(normal);
-        }
-
-        return normals;
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import javax.media.j3d.Appearance;
+import javax.media.j3d.Geometry;
+import javax.media.j3d.Material;
+import javax.media.j3d.Shape3D;
+import javax.media.j3d.TransformGroup;
+import javax.vecmath.Color3f;
+import javax.vecmath.Point3f;
+import javax.vecmath.TexCoord2f;
+import javax.vecmath.Vector3f;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+import com.microcrowd.loader.java3d.max3ds.ChunkMap;
+import com.sun.j3d.utils.geometry.GeometryInfo;
+import com.sun.j3d.utils.geometry.NormalGenerator;
+import com.sun.j3d.utils.geometry.Stripifier;
+
+/**
+ * This chunk describes all the triangles that make up a mesh.
+ * Each triangle is defined in terms of three indexes each of which
+ * is a point reference to a vertex in the vertex list loaded
+ * by the triangular mesh chunk.
+ * After loading the Smoothing chunk the normals for the mesh
+ * are generated accordingly.
+ */
+public class FacesDescriptionChunk extends Chunk
+{
+    public static final Appearance DEFAULT_APPEARANCE;
+
+    private Point3f[] currentVertices;
+    private TexCoord2f[] textureTriangles;
+    private PointMapper shareMap;
+
+    static {
+        DEFAULT_APPEARANCE= new Appearance();
+        Material defaultMaterial = new Material();
+        defaultMaterial.setAmbientColor(new Color3f(.5f, .5f, .5f));
+        //defaultMaterial.setDiffuseColor(new Color3f(.5f, .5f, .5f));
+        //defaultMaterial.setSpecularColor(new Color3f(.5f, .5f, .5f));
+        DEFAULT_APPEARANCE.setMaterial(defaultMaterial);
+    }
+
+
+
+    /**
+     * Maintains a two way mapping between coordinates
+     * and vertices.  A coordinate to vertex is one to many 
+     * Vertex to coordinate is one to one.
+     * In this class we maintain the definition that a coordinate
+     * is a point in 3D space and a vertex is a coordinate serving
+     * as one of three defining a face.
+     */
+    private class PointMapper extends HashMap
+    {
+        private Set[] coordinateSet;
+        /**
+         * Constructs a PointMapper with a
+         * the number of coordinates initialized to size.
+         * @param size the number of coordinates in the set.
+         */
+        public PointMapper(int size)
+        {
+            coordinateSet = new Set[size];
+        }
+
+        /**
+         * Adds an index for a coordinate to the set of vertices mapped
+         * to that coordinate. All coordinates may have one or more vertices
+         * that use them.  
+         * @param coordinate the coordinate being mapped to the vertexNum 
+         * @param vertexNum the number of the vertex using the coordinate
+         */
+        public void addCoordinate(Point3f coordinate, int vertexNum)
+        {
+            Set sharedCoordinates = (Set)get(coordinate); 
+            if(sharedCoordinates == null)
+            {
+                sharedCoordinates = new HashSet();
+                put(coordinate, sharedCoordinates);
+            }
+            sharedCoordinates.add(new Integer(vertexNum));
+            coordinateSet[vertexNum] = sharedCoordinates;
+        }
+
+        /**
+         * Gets all the coordinates for a particular vertex that
+         * also share that vertex after the smoothing groups have been
+         * accounted for.  Any coordinates that are not both shared
+         * by the vertex and do not share a smoothing group with the coordinate
+         * will not be returned.
+         * @param coordinateNum the number of the coordinate to get the set
+         * of vertices for that share it.
+         * @param smoothGroups the group of coordinates used to filter out the 
+         * non-shared vertices.
+         */
+        public Set getSharedCoordinates(int coordinateNum, int[] smoothGroups)
+        {
+            Set returnSet = new HashSet();
+            Set sharingVertices = coordinateSet[coordinateNum];
+            Iterator vertices = sharingVertices.iterator();
+            int coordinateMask = smoothGroups[coordinateNum];
+            while(vertices.hasNext())
+            {
+                Integer vertex = (Integer)vertices.next();
+                int nextMask = smoothGroups[vertex.intValue()];
+                if((nextMask & coordinateMask) != 0)
+                {
+                    returnSet.add(vertex);
+                }
+            }
+            return returnSet; 
+        }
+    }
+
+    /**
+     * Reads the number of faces from the ChunkChopper.
+     * For each face read three shorts representing
+     * indices of vertices loaded by the TriangularMeshChunk
+     *
+     * @param chopper chopper the has the data  
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        int numFaces = chopper.getUnsignedShort();
+        shareMap = new PointMapper(numFaces*3);
+        Point3f[] coordinates = (Point3f[])chopper.popData(ChunkMap.VERTEX_LIST);
+        TexCoord2f[] texturePoints = (TexCoord2f[])chopper.popData(ChunkMap.TEXTURE_COORDINATES);
+
+        currentVertices = new Point3f[numFaces * 3];
+        chopper.pushData(chopper.getID(), currentVertices);
+        if (texturePoints != null) 
+        {
+            textureTriangles = new TexCoord2f[numFaces * 3];
+        }
+
+        for (int i = 0; i < numFaces; i++) {
+            int vertexIndex = i * 3;
+            int index0 = chopper.getUnsignedShort();
+            int index1 = chopper.getUnsignedShort();
+            int index2 = chopper.getUnsignedShort();
+
+            currentVertices[vertexIndex] = coordinates[index0];
+            currentVertices[vertexIndex + 1] = coordinates[index1];
+            currentVertices[vertexIndex + 2] = coordinates[index2];
+
+            shareMap.addCoordinate(coordinates[index0], vertexIndex);
+            shareMap.addCoordinate(coordinates[index1], vertexIndex+1);
+            shareMap.addCoordinate(coordinates[index2], vertexIndex+2);
+
+
+            if (textureTriangles != null) {
+                textureTriangles[vertexIndex] = texturePoints[index0];
+                textureTriangles[vertexIndex + 1] = texturePoints[index1];
+                textureTriangles[vertexIndex + 2] = texturePoints[index2];
+            }
+
+            //This is a bit masked value that is used to determine which edges are visible... not needed.
+            chopper.getUnsignedShort(); 
+        }
+    }
+
+    /**
+     * Loads a mesh onto the scene graph with the specified data
+     * from subchunks.
+     * If there is no material, this will put a default
+     * material on the shape.
+     */
+    public void initialize(ChunkChopper chopper)
+    {
+        final String materialName = (String)chopper.popData(ChunkMap.FACES_MATERIAL);
+        final int[]  smoothGroups = (int[])chopper.popData(ChunkMap.SMOOTH);
+        Shape3D      shape        = new Shape3D();
+        GeometryInfo geometryInfo = new GeometryInfo(GeometryInfo.TRIANGLE_ARRAY);
+
+        geometryInfo.setCoordinates(currentVertices);
+        TransformGroup transformGroup = (TransformGroup)chopper.getGroup();
+        transformGroup.addChild(shape);
+
+        if (textureTriangles != null) 
+        {
+            geometryInfo.setTextureCoordinateParams(1, 2);
+            geometryInfo.setTextureCoordinates(0, textureTriangles);
+        }
+
+        if(materialName != null)
+        {
+            shape.setAppearance((Appearance)chopper.getNamedObject(materialName));
+        }
+        else
+        {
+            shape.setAppearance(DEFAULT_APPEARANCE);
+        }
+        if(smoothGroups == null)
+        {
+            NormalGenerator normalGenerator = new NormalGenerator();
+            geometryInfo.recomputeIndices();
+            normalGenerator.generateNormals(geometryInfo);
+        }
+        else
+        {
+            Vector3f[] normals = generateNormals(currentVertices);
+            Vector3f[] smoothNormals = smoothNormals(normals, shareMap, smoothGroups);
+            geometryInfo.setNormals(smoothNormals);
+        }
+
+        new Stripifier().stripify(geometryInfo);
+        shape.setGeometry(geometryInfo.getGeometryArray());
+        shape.setCapability(Geometry.ALLOW_INTERSECT);
+        com.sun.j3d.utils.picking.PickTool.setCapabilities(shape, com.sun.j3d.utils.picking.PickTool.INTERSECT_FULL);
+
+        currentVertices=null;
+        textureTriangles=null;
+    }
+
+    /**
+     * Takes all the normals for all the vertices and averages them with
+     * normals with which they share a coordinate and at least one smooth group.
+     * @param currentNormals the normals for each face.
+     * @param sharedPoints the point mapper that will choose which points are 
+     * and which are not shared.
+     * @param smoothGroups the indexed list of group masks loaded by the smooth chunk.
+     * @return normals averaged among the shared vertices in their smoothing groups.
+     */
+    public Vector3f[] smoothNormals(Vector3f[] currentNormals, PointMapper sharedPoints, int[] smoothGroups)
+    {
+        Vector3f[] smoothNormals = new Vector3f[currentNormals.length];
+        for(int i=0; i < currentNormals.length; i++)
+        {
+            Set otherPoints = sharedPoints.getSharedCoordinates(i, smoothGroups);
+            if(otherPoints != null)
+            {
+                Vector3f[] sharedNormals = new Vector3f[otherPoints.size()]; 
+                Iterator pointIterator = otherPoints.iterator();
+                for(int j = 0; j < sharedNormals.length; j++)
+                {
+                    sharedNormals[j] = currentNormals[((Integer)pointIterator.next()).intValue()];
+                }
+                smoothNormals[i] = averageNormals(sharedNormals);
+            }
+            else
+            {
+                smoothNormals[i] = currentNormals[i];
+            }
+        }
+        return smoothNormals;
+    }
+
+    /**
+     * Averages the normals provided in order to provide
+     * smooth, noncreased appearances for meshes.
+     * @param normals the normals that should be averaged
+     * @return a normalized normal that can be used in place
+     * of all the normals provided.
+     */
+    public Vector3f averageNormals(Vector3f[] normals)
+    {
+        Vector3f newNormal = new Vector3f();
+        for(int i=0; i < normals.length; i++)
+        {
+            newNormal.add(normals[i]);
+        }
+        newNormal.normalize();
+        return newNormal;
+    }
+
+    /**
+     * Generates normals for each vertex of each
+     * face that are absolutely normal to the face.
+     * @param point0 The first point of the face
+     * @param point1 The second point of the face
+     * @param point2 The third point of the face
+     * @return the three normals that should be 
+     * used for the triangle represented by the parameters.
+     */
+    private Vector3f[] generateNormals(Point3f points[])
+    {
+        Vector3f[] normals = new Vector3f[points.length];
+        for(int i=0; i < normals.length;)
+        {
+            Vector3f normal    = new Vector3f();
+            Vector3f v1        = new Vector3f();
+            Vector3f v2        = new Vector3f();
+    
+            v1.sub(points[i+1], points[i]);
+            v2.sub(points[i+2], points[i]);
+            normal.cross(v1, v2);
+            normal.normalize();
+
+    
+            normals[i++] = new Vector3f(normal);
+            normals[i++] = new Vector3f(normal);
+            normals[i++] = new Vector3f(normal);
+        }
+
+        return normals;
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/FacesMaterialChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/FacesMaterialChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/FacesMaterialChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/FacesMaterialChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,59 +1,59 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- *
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * FacesMaterialsChunk contains the materials information 
- * from the 3ds file. It contains information pertaining to
- * which faces of a mesh have materials on them and the
- * texture coordinates for texture mapping.
- * Right now, its just putting the name of the material
- * that needs to be applied to the mesh under construction.
- *
- * @author jdeford
- */
-public class FacesMaterialChunk extends Chunk
-{
-    /**
-     * Loads the texture coordinates for a mesh, 
-     *
-     * @param chopper the ChunkChopper containing the state of the parser.  
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        final String materialName = chopper.getString();
-        int numFaces = chopper.getUnsignedShort();
-        if (numFaces > 0) 
-        {
-            for (int j = 0; j < numFaces; j++) 
-            {
-                int index = j * 3;
-                int position = chopper.getUnsignedShort() * 3;
-            }
-        }
-
-        chopper.pushData(chopper.getID(), materialName);
-    }
-}
-
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ *
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * FacesMaterialsChunk contains the materials information 
+ * from the 3ds file. It contains information pertaining to
+ * which faces of a mesh have materials on them and the
+ * texture coordinates for texture mapping.
+ * Right now, its just putting the name of the material
+ * that needs to be applied to the mesh under construction.
+ *
+ * @author jdeford
+ */
+public class FacesMaterialChunk extends Chunk
+{
+    /**
+     * Loads the texture coordinates for a mesh, 
+     *
+     * @param chopper the ChunkChopper containing the state of the parser.  
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        final String materialName = chopper.getString();
+        int numFaces = chopper.getUnsignedShort();
+        if (numFaces > 0) 
+        {
+            for (int j = 0; j < numFaces; j++) 
+            {
+                int index = j * 3;
+                int position = chopper.getUnsignedShort() * 3;
+            }
+        }
+
+        chopper.pushData(chopper.getID(), materialName);
+    }
+}
+
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/FloatChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/FloatChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/FloatChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/FloatChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,47 +1,47 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * These have no subchunks. Only data.
- * Any objects that have a float chunk
- * as a sub chunk may retrieve the float
- * value from {@link ChunkChopper.popData()}
- * using the current chunk id as an argument.
- */
-public class FloatChunk extends Chunk
-{
-    /**
-     * Loads a Float value into the chopper
-     * for use later when parent chunks are 
-     * initializing
-     *
-     * @param chopper the chopper in which the float
-     * chunk will be stored by the id of this chunk. 
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        chopper.pushData(chopper.getID(), new Float(chopper.getFloat()));
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * These have no subchunks. Only data.
+ * Any objects that have a float chunk
+ * as a sub chunk may retrieve the float
+ * value from {@link ChunkChopper.popData()}
+ * using the current chunk id as an argument.
+ */
+public class FloatChunk extends Chunk
+{
+    /**
+     * Loads a Float value into the chopper
+     * for use later when parent chunks are 
+     * initializing
+     *
+     * @param chopper the chopper in which the float
+     * chunk will be stored by the id of this chunk. 
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        chopper.pushData(chopper.getID(), new Float(chopper.getFloat()));
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/FramesChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/FramesChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/FramesChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/FramesChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,45 +1,45 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * This chunk specifies the beginning and end frames.
- *
- * @author jdeford 
- */
-public class FramesChunk extends Chunk
-{
-    /**
-     * Reads two ints. Start frame and stop frame. 
-     *
-     * @param chopper  the chopper that may be used to store the starting and 
-     * stopping frames.
-     * 
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        long start = chopper.getUnsignedInt();
-        long stop = chopper.getUnsignedInt();
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * This chunk specifies the beginning and end frames.
+ *
+ * @author jdeford 
+ */
+public class FramesChunk extends Chunk
+{
+    /**
+     * Reads two ints. Start frame and stop frame. 
+     *
+     * @param chopper  the chopper that may be used to store the starting and 
+     * stopping frames.
+     * 
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        long start = chopper.getUnsignedInt();
+        long stop = chopper.getUnsignedInt();
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/FramesDescriptionChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/FramesDescriptionChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/FramesDescriptionChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/FramesDescriptionChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,59 +1,59 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-
-import javax.media.j3d.TransformGroup;
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-import com.microcrowd.loader.java3d.max3ds.data.KeyFramer;
-/**
- * This chunk contains the name of the object
- * the frames belong to and the parameters and 
- * hierarchy information for it.
- */
-public class FramesDescriptionChunk extends Chunk
-{
-    /**
-     * reads the name of the object for these frames
-     * and stores it in the chopper.
-     *
-     * @param chopper the chopper used to store the transient data
-     * for this chunk. 
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        KeyFramer keyFramer = chopper.getKeyFramer();
-        String objectName = chopper.getString();
-        chopper.setObjectName(objectName);
-        chopper.getUnsignedShort();
-        chopper.getUnsignedShort();
-        int fatherID = chopper.getShort();
-        TransformGroup transformGroup = chopper.getNamedTransformGroup(objectName);
-        if(transformGroup == null)//its a dummy transformGroup.
-        {
-            transformGroup = new TransformGroup();
-            keyFramer.setDummyObject(transformGroup);
-        }
-
-        keyFramer.addFather(fatherID, transformGroup);
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+
+import javax.media.j3d.TransformGroup;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+import com.microcrowd.loader.java3d.max3ds.data.KeyFramer;
+/**
+ * This chunk contains the name of the object
+ * the frames belong to and the parameters and 
+ * hierarchy information for it.
+ */
+public class FramesDescriptionChunk extends Chunk
+{
+    /**
+     * reads the name of the object for these frames
+     * and stores it in the chopper.
+     *
+     * @param chopper the chopper used to store the transient data
+     * for this chunk. 
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        KeyFramer keyFramer = chopper.getKeyFramer();
+        String objectName = chopper.getString();
+        chopper.setObjectName(objectName);
+        chopper.getUnsignedShort();
+        chopper.getUnsignedShort();
+        int fatherID = chopper.getShort();
+        TransformGroup transformGroup = chopper.getNamedTransformGroup(objectName);
+        if(transformGroup == null)//its a dummy transformGroup.
+        {
+            transformGroup = new TransformGroup();
+            keyFramer.setDummyObject(transformGroup);
+        }
+
+        keyFramer.addFather(fatherID, transformGroup);
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/GlobalColorChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/GlobalColorChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/GlobalColorChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/GlobalColorChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,45 +1,45 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * Loads colors from binary data representing them.
- * Its a global in the manner that it reads its own
- * header information.
- */
-public class GlobalColorChunk extends ColorChunk
-{
-    /**
-     * Gets the color type for this chunk.
-     * @param chopper with the information the
-     * chunk may use to determine color type
-     * @return the color type for the chunk.
-     */
-    protected int getColorType(ChunkChopper chopper)
-    {
-        int type = chopper.getUnsignedShort();
-        int colorLength = chopper.getUnsignedInt();
-        return type;
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * Loads colors from binary data representing them.
+ * Its a global in the manner that it reads its own
+ * header information.
+ */
+public class GlobalColorChunk extends ColorChunk
+{
+    /**
+     * Gets the color type for this chunk.
+     * @param chopper with the information the
+     * chunk may use to determine color type
+     * @return the color type for the chunk.
+     */
+    protected int getColorType(ChunkChopper chopper)
+    {
+        int type = chopper.getUnsignedShort();
+        int colorLength = chopper.getUnsignedInt();
+        return type;
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/HierarchyInfoChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/HierarchyInfoChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/HierarchyInfoChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/HierarchyInfoChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,46 +1,46 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * A HierarchyInfoChunk stores information about 
- * where an object belong in a hierarchy of object that 
- * have animations which may or may not be related.
- * Each object, including dummy objects, have an identifier
- * used to specify them as hierarchical parents of other 
- * objects for the purpose of key framing.
- *
- * @author Josh DeFord 
- */
-public class HierarchyInfoChunk extends Chunk
-{
-    /**
-     * Loads a word of data that describes the parent. 
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        int hierarchyIdentifier = chopper.getShort();
-        chopper.getKeyFramer().setID(hierarchyIdentifier);
-    }
-
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * A HierarchyInfoChunk stores information about 
+ * where an object belong in a hierarchy of object that 
+ * have animations which may or may not be related.
+ * Each object, including dummy objects, have an identifier
+ * used to specify them as hierarchical parents of other 
+ * objects for the purpose of key framing.
+ *
+ * @author Josh DeFord 
+ */
+public class HierarchyInfoChunk extends Chunk
+{
+    /**
+     * Loads a word of data that describes the parent. 
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        int hierarchyIdentifier = chopper.getShort();
+        chopper.getKeyFramer().setID(hierarchyIdentifier);
+    }
+
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/KeyFramerInfoChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/KeyFramerInfoChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/KeyFramerInfoChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/KeyFramerInfoChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,68 +1,68 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import javax.media.j3d.Behavior;
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * A KeyFramerInfoChunk stores information about things
- * that happen to meshes: Position information, rotation
- * information, scale information, pivot information 
- * and frame information.
- * Together with the frames chunk thes are used
- * display animation behaviors.
- *
- * @author Josh DeFord 
- */
-public class KeyFramerInfoChunk extends Chunk
-{
-
-    /**
-     * Retrieves the named object for the current key framer
-     * inserts the rotation, position and pivot transformations for frame 0
-     * and assigns the coordinate system to it.
-     *
-     * The inverse of the local coordinate system converts from 3ds 
-     * semi-absolute coordinates (what is in the file) to local coordinates.
-     *
-     * Then these local coordinates are converted with matrix 
-     * that will instantiate them to absolute coordinates:
-     * Xabs = sx a1 (Xl-Px) + sy a2 (Yl-Py) + sz a3 (Zl-Pz) + Tx
-     * Yabs = sx b1 (Xl-Px) + sy b2 (Yl-Py) + sz b3 (Zl-Pz) + Ty
-     * Zabs = sx c1 (Xl-Px) + sy c2 (Yl-Py) + sz c3 (Zl-Pz) + Tz
-     * Where:
-     * (Xabs,Yabs,Zabs) = absolute coordinate
-     * (Px,Py,Pz) = mesh pivot (constant)
-     * (X1,Y1,Z1) = local coordinates
-     *
-     * @param chopper the ChunkChopper containing the current state of the parser. 
-     */
-    public void initialize(ChunkChopper chopper) 
-    {
-        String meshName = (String)chopper.getObjectName();
-        Behavior frameBehavior = chopper.getKeyFramer().createBehavior(meshName,
-                                                        chopper.getNamedTransformGroup(meshName),
-                                                        chopper.getNamedObject(meshName));
-        if(frameBehavior != null)
-            chopper.addBehaviorNode(frameBehavior);
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import javax.media.j3d.Behavior;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * A KeyFramerInfoChunk stores information about things
+ * that happen to meshes: Position information, rotation
+ * information, scale information, pivot information 
+ * and frame information.
+ * Together with the frames chunk thes are used
+ * display animation behaviors.
+ *
+ * @author Josh DeFord 
+ */
+public class KeyFramerInfoChunk extends Chunk
+{
+
+    /**
+     * Retrieves the named object for the current key framer
+     * inserts the rotation, position and pivot transformations for frame 0
+     * and assigns the coordinate system to it.
+     *
+     * The inverse of the local coordinate system converts from 3ds 
+     * semi-absolute coordinates (what is in the file) to local coordinates.
+     *
+     * Then these local coordinates are converted with matrix 
+     * that will instantiate them to absolute coordinates:
+     * Xabs = sx a1 (Xl-Px) + sy a2 (Yl-Py) + sz a3 (Zl-Pz) + Tx
+     * Yabs = sx b1 (Xl-Px) + sy b2 (Yl-Py) + sz b3 (Zl-Pz) + Ty
+     * Zabs = sx c1 (Xl-Px) + sy c2 (Yl-Py) + sz c3 (Zl-Pz) + Tz
+     * Where:
+     * (Xabs,Yabs,Zabs) = absolute coordinate
+     * (Px,Py,Pz) = mesh pivot (constant)
+     * (X1,Y1,Z1) = local coordinates
+     *
+     * @param chopper the ChunkChopper containing the current state of the parser. 
+     */
+    public void initialize(ChunkChopper chopper) 
+    {
+        String meshName = (String)chopper.getObjectName();
+        Behavior frameBehavior = chopper.getKeyFramer().createBehavior(meshName,
+                                                        chopper.getNamedTransformGroup(meshName),
+                                                        chopper.getNamedObject(meshName));
+        if(frameBehavior != null)
+            chopper.addBehaviorNode(frameBehavior);
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/LightChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/LightChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/LightChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/LightChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,80 +1,80 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import javax.media.j3d.BoundingSphere;
-import javax.media.j3d.PointLight;
-import javax.media.j3d.Transform3D;
-import javax.media.j3d.TransformGroup;
-import javax.vecmath.Color3f;
-import javax.vecmath.Point3d;
-import javax.vecmath.Vector3f;
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-import com.microcrowd.loader.java3d.max3ds.ChunkMap;
-/**
- * Lights to be placed in a scene.
- * Only point lights and target spot lights are supported.
- * All the default parameters are used for lights as well.
- * Only position is specified.
- */
-public class LightChunk extends Chunk
-{
-    private Vector3f currentPosition;
-
-    /**
-     * This is called by the chunk chopper before any of the chunk's 
-     * subchunks  are loaded.  Any data loaded that may need to be 
-     * used later by superchunks should be stored in
-     * the chunk chopper via {@link ChunkChopper#pushData}
-     *
-     * @param chopper used to store the position of the light. 
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        currentPosition = chopper.getVector();
-        TransformGroup group = chopper.getGroup();
-        Transform3D transform = new Transform3D();
-        group.getTransform(transform);
-        transform.setTranslation(currentPosition);
-        group.setTransform(transform);
-        chopper.pushData(chopper.getID(), currentPosition);
-    }
-
-    /**
-     * Gets the data put into the chopper by the subchunks
-     * and creates a light, adding it to the scene as a named object.
-     * @param chopper the ChunkChopper containing sub chunk data.
-     */
-    public void initialize(ChunkChopper chopper)
-    {
-        Color3f color = (Color3f)chopper.popData(ChunkMap.COLOR);
-        PointLight light = (PointLight)chopper.popData(ChunkMap.SPOTLIGHT);
-        if(light == null)
-        {
-            light = new PointLight();
-            chopper.addLightNode(light);
-        }
-
-        light.setColor(color);
-        light.setInfluencingBounds(new BoundingSphere(new Point3d(0,0,0), 3000));
-        chopper.getGroup().addChild(light);
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import javax.media.j3d.BoundingSphere;
+import javax.media.j3d.PointLight;
+import javax.media.j3d.Transform3D;
+import javax.media.j3d.TransformGroup;
+import javax.vecmath.Color3f;
+import javax.vecmath.Point3d;
+import javax.vecmath.Vector3f;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+import com.microcrowd.loader.java3d.max3ds.ChunkMap;
+/**
+ * Lights to be placed in a scene.
+ * Only point lights and target spot lights are supported.
+ * All the default parameters are used for lights as well.
+ * Only position is specified.
+ */
+public class LightChunk extends Chunk
+{
+    private Vector3f currentPosition;
+
+    /**
+     * This is called by the chunk chopper before any of the chunk's 
+     * subchunks  are loaded.  Any data loaded that may need to be 
+     * used later by superchunks should be stored in
+     * the chunk chopper via {@link ChunkChopper#pushData}
+     *
+     * @param chopper used to store the position of the light. 
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        currentPosition = chopper.getVector();
+        TransformGroup group = chopper.getGroup();
+        Transform3D transform = new Transform3D();
+        group.getTransform(transform);
+        transform.setTranslation(currentPosition);
+        group.setTransform(transform);
+        chopper.pushData(chopper.getID(), currentPosition);
+    }
+
+    /**
+     * Gets the data put into the chopper by the subchunks
+     * and creates a light, adding it to the scene as a named object.
+     * @param chopper the ChunkChopper containing sub chunk data.
+     */
+    public void initialize(ChunkChopper chopper)
+    {
+        Color3f color = (Color3f)chopper.popData(ChunkMap.COLOR);
+        PointLight light = (PointLight)chopper.popData(ChunkMap.SPOTLIGHT);
+        if(light == null)
+        {
+            light = new PointLight();
+            chopper.addLightNode(light);
+        }
+
+        light.setColor(color);
+        light.setInfluencingBounds(new BoundingSphere(new Point3d(0,0,0), 3000));
+        chopper.getGroup().addChild(light);
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/MaterialChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/MaterialChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/MaterialChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/MaterialChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,121 +1,121 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import javax.media.j3d.Appearance;
-import javax.media.j3d.Material;
-import javax.media.j3d.PolygonAttributes;
-import javax.media.j3d.Texture;
-import javax.media.j3d.TransparencyAttributes;
-import javax.vecmath.Color3f;
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-import com.microcrowd.loader.java3d.max3ds.ChunkMap;
-
-
-
-/**
- * Loads material chunks with ambient, diffuse and specular colors,
- * shininess, transparency, two sidedness and texture.
- */
-public class MaterialChunk extends Chunk
-{
-
-    //public static final Integer SELF_ILLUMINATED = new Integer((short)0xA084);
-
-
-    /**
-     * This will set the ambient, diffuse and specular
-     * colors as well as the textures, two sidedness
-     * and transparency of the material.
-     *
-     * @param chopper the chopper containing the data
-     * needed to set the attributes.
-     */
-    public void initialize(ChunkChopper chopper)
-    {
-        Appearance appearance = new Appearance();
-        Material material = new Material();
-
-        Color3f ambientColor = (Color3f)chopper.popData(ChunkMap.AMBIENT_COLOR);
-        if (ambientColor != null) {
-            material.setAmbientColor(ambientColor);
-        }
-
-        Color3f color = (Color3f)chopper.popData(ChunkMap.DIFFUSE_COLOR);
-        if (color != null) {
-            material.setDiffuseColor(color);
-        }
-
-        color = (Color3f)chopper.popData(ChunkMap.SPECULAR_COLOR);
-        if (color != null) {
-            material.setSpecularColor(color);
-        }
-
-        Texture texture = (Texture)chopper.popData(ChunkMap.TEXTURE);
-        if(texture != null)
-        {
-            appearance.setTexture(texture);
-        }
-
-        Boolean twoSided = (Boolean)chopper.popData(ChunkMap.TWO_SIDED);
-        if (twoSided != null) //Just being there is equivalent to a boolean true.
-        {
-
-            PolygonAttributes polyAttributes = appearance.getPolygonAttributes(); 
-            if(polyAttributes == null)
-            {
-                polyAttributes = new PolygonAttributes();
-            }
-
-            polyAttributes.setCullFace(PolygonAttributes.CULL_NONE);
-            appearance.setPolygonAttributes(polyAttributes);
-        }
-
-        Float transparency = (Float)chopper.popData(ChunkMap.TRANSPARENCY);
-        if (transparency != null) {
-            if (transparency.floatValue() > 0.01f) {
-
-                TransparencyAttributes transparencyAttributes = new TransparencyAttributes(TransparencyAttributes.FASTEST, transparency.floatValue());
-                appearance.setTransparencyAttributes(transparencyAttributes);
-            }
-        }
-
-        String name = (String)chopper.popData(ChunkMap.MATERIAL_NAME);
-        Float shininess = (Float)chopper.popData(ChunkMap.SHININESS);
-        if (shininess != null) 
-        {
-            float shine = shininess.floatValue() * 1024f;
-            material.setShininess(shine);
-        }
-
-        /*
-           Boolean illuminated = (Boolean)chopper.popData(SELF_ILLUMINATED);
-           if(illuminated != null && illuminated.booleanValue() == true)
-           {
-           material.setEmissiveColor(ambientColor);
-           }
-           */
-
-        appearance.setMaterial(material);
-        chopper.setNamedObject(name, appearance);
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import javax.media.j3d.Appearance;
+import javax.media.j3d.Material;
+import javax.media.j3d.PolygonAttributes;
+import javax.media.j3d.Texture;
+import javax.media.j3d.TransparencyAttributes;
+import javax.vecmath.Color3f;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+import com.microcrowd.loader.java3d.max3ds.ChunkMap;
+
+
+
+/**
+ * Loads material chunks with ambient, diffuse and specular colors,
+ * shininess, transparency, two sidedness and texture.
+ */
+public class MaterialChunk extends Chunk
+{
+
+    //public static final Integer SELF_ILLUMINATED = new Integer((short)0xA084);
+
+
+    /**
+     * This will set the ambient, diffuse and specular
+     * colors as well as the textures, two sidedness
+     * and transparency of the material.
+     *
+     * @param chopper the chopper containing the data
+     * needed to set the attributes.
+     */
+    public void initialize(ChunkChopper chopper)
+    {
+        Appearance appearance = new Appearance();
+        Material material = new Material();
+
+        Color3f ambientColor = (Color3f)chopper.popData(ChunkMap.AMBIENT_COLOR);
+        if (ambientColor != null) {
+            material.setAmbientColor(ambientColor);
+        }
+
+        Color3f color = (Color3f)chopper.popData(ChunkMap.DIFFUSE_COLOR);
+        if (color != null) {
+            material.setDiffuseColor(color);
+        }
+
+        color = (Color3f)chopper.popData(ChunkMap.SPECULAR_COLOR);
+        if (color != null) {
+            material.setSpecularColor(color);
+        }
+
+        Texture texture = (Texture)chopper.popData(ChunkMap.TEXTURE);
+        if(texture != null)
+        {
+            appearance.setTexture(texture);
+        }
+
+        Boolean twoSided = (Boolean)chopper.popData(ChunkMap.TWO_SIDED);
+        if (twoSided != null) //Just being there is equivalent to a boolean true.
+        {
+
+            PolygonAttributes polyAttributes = appearance.getPolygonAttributes(); 
+            if(polyAttributes == null)
+            {
+                polyAttributes = new PolygonAttributes();
+            }
+
+            polyAttributes.setCullFace(PolygonAttributes.CULL_NONE);
+            appearance.setPolygonAttributes(polyAttributes);
+        }
+
+        Float transparency = (Float)chopper.popData(ChunkMap.TRANSPARENCY);
+        if (transparency != null) {
+            if (transparency.floatValue() > 0.01f) {
+
+                TransparencyAttributes transparencyAttributes = new TransparencyAttributes(TransparencyAttributes.FASTEST, transparency.floatValue());
+                appearance.setTransparencyAttributes(transparencyAttributes);
+            }
+        }
+
+        String name = (String)chopper.popData(ChunkMap.MATERIAL_NAME);
+        Float shininess = (Float)chopper.popData(ChunkMap.SHININESS);
+        if (shininess != null) 
+        {
+            float shine = shininess.floatValue() * 1024f;
+            material.setShininess(shine);
+        }
+
+        /*
+           Boolean illuminated = (Boolean)chopper.popData(SELF_ILLUMINATED);
+           if(illuminated != null && illuminated.booleanValue() == true)
+           {
+           material.setEmissiveColor(ambientColor);
+           }
+           */
+
+        appearance.setMaterial(material);
+        chopper.setNamedObject(name, appearance);
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/NamedObjectChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/NamedObjectChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/NamedObjectChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/NamedObjectChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,50 +1,50 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import javax.media.j3d.TransformGroup;
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * Loads information about a named object: Cameras, meshes and lights
- */
-public class NamedObjectChunk extends Chunk
-{
-
-    /**
-     * Adds a TransformGroup the the chopper's branch
-     * group to which meshes will be added.
-     *
-     * @param chopper The chopper containing the state of parsing.  
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        final String name = chopper.getString();
-        TransformGroup transformGroup = new TransformGroup();
-
-        transformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
-        transformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
-        transformGroup.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
-
-        chopper.addObject(name, transformGroup);
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import javax.media.j3d.TransformGroup;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * Loads information about a named object: Cameras, meshes and lights
+ */
+public class NamedObjectChunk extends Chunk
+{
+
+    /**
+     * Adds a TransformGroup the the chopper's branch
+     * group to which meshes will be added.
+     *
+     * @param chopper The chopper containing the state of parsing.  
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        final String name = chopper.getString();
+        TransformGroup transformGroup = new TransformGroup();
+
+        transformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+        transformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+        transformGroup.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
+
+        chopper.addObject(name, transformGroup);
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/PercentageChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/PercentageChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/PercentageChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/PercentageChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,59 +1,59 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * Loads percentage values from binary data representing them.
- */
-public class PercentageChunk extends Chunk
-{
-    /** Represents an int percentage */
-    public static final int INT = 0x30;
-
-    /** Represents a float percentage */
-    public static final int FLOAT = 0x31;
-    private float percentage;
-
-    /**
-     * Gets tye type of percentage, reads it
-     * and sets the value on the chopper using
-     * the id of the current chunk as the key.
-     *
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        int percentageType = chopper.getUnsignedShort();
-        int percentageLength = chopper.getUnsignedInt();
-        if (percentageType == INT) {
-            percentage = (chopper.getUnsignedShort()) / 100f;
-            chopper.pushData(chopper.getID(), new Float(percentage));
-        } else if (percentageType == FLOAT) {
-            percentage = chopper.getFloat() / 100f;
-            chopper.pushData(chopper.getID(), new Float(percentage));
-        } else {
-            throw new IllegalArgumentException("Only float and int percentages are enabled.");
-        }
-
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * Loads percentage values from binary data representing them.
+ */
+public class PercentageChunk extends Chunk
+{
+    /** Represents an int percentage */
+    public static final int INT = 0x30;
+
+    /** Represents a float percentage */
+    public static final int FLOAT = 0x31;
+    private float percentage;
+
+    /**
+     * Gets tye type of percentage, reads it
+     * and sets the value on the chopper using
+     * the id of the current chunk as the key.
+     *
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        int percentageType = chopper.getUnsignedShort();
+        int percentageLength = chopper.getUnsignedInt();
+        if (percentageType == INT) {
+            percentage = (chopper.getUnsignedShort()) / 100f;
+            chopper.pushData(chopper.getID(), new Float(percentage));
+        } else if (percentageType == FLOAT) {
+            percentage = chopper.getFloat() / 100f;
+            chopper.pushData(chopper.getID(), new Float(percentage));
+        } else {
+            throw new IllegalArgumentException("Only float and int percentages are enabled.");
+        }
+
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/PivotChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/PivotChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/PivotChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/PivotChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,45 +1,45 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import javax.vecmath.Point3f;
-import javax.vecmath.Vector3f;
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-/**
- * Loads the pivot for a mesh. 
- * {@see KeyFramerInfoChunk} for more information about using
- * animations from a 3ds file
- */
-public class PivotChunk extends Chunk
-{
-    /**
-     * Gets the pivot and associates it with the current mes.
-     * @param chopper the ChunkChopper containing the state of the parser.  
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        Vector3f pivot = new Vector3f((Point3f)chopper.getPoint());
-
-        chopper.getKeyFramer().setPivot(pivot);
-    }
-
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import javax.vecmath.Point3f;
+import javax.vecmath.Vector3f;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+/**
+ * Loads the pivot for a mesh. 
+ * {@see KeyFramerInfoChunk} for more information about using
+ * animations from a 3ds file
+ */
+public class PivotChunk extends Chunk
+{
+    /**
+     * Gets the pivot and associates it with the current mes.
+     * @param chopper the ChunkChopper containing the state of the parser.  
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        Vector3f pivot = new Vector3f((Point3f)chopper.getPoint());
+
+        chopper.getKeyFramer().setPivot(pivot);
+    }
+
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/PositionChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/PositionChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/PositionChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/PositionChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,63 +1,63 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import java.util.ArrayList;
-import javax.vecmath.Point3f;
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * Loads the position of a mesh as defined in the 3ds file.
- * This position may need to be converted to another coordinate
- * system by KeyFramerInfoChunk.
- *  * {@see KeyFramerInfoChunk} for more information about using
- * animations from a 3ds file
- */
-public class PositionChunk extends Chunk
-{
-    /**
-     * Loads the position for a shape and KeyFramerInfoChunk
-     *
-     * @param chopper the ChunkChopper containing the state of the parser.  
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        int flags = chopper.getUnsignedShort();
-        chopper.getLong();
-        int numKeys = chopper.getUnsignedInt();
-
-        ArrayList pointList = new ArrayList();
-        for(int i =0; i < numKeys; i++)
-        {
-            long keyNumber = chopper.getUnsignedInt();
-            int  accelerationData = chopper.getUnsignedShort(); 
-
-            Point3f position = chopper.getPoint(); 
-            if(i==0)
-            {
-                chopper.getKeyFramer().setPosition(position);
-            }
-            pointList.add(position);
-        }
-        chopper.getKeyFramer().setPositionKeys(pointList);
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import java.util.ArrayList;
+import javax.vecmath.Point3f;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * Loads the position of a mesh as defined in the 3ds file.
+ * This position may need to be converted to another coordinate
+ * system by KeyFramerInfoChunk.
+ *  * {@see KeyFramerInfoChunk} for more information about using
+ * animations from a 3ds file
+ */
+public class PositionChunk extends Chunk
+{
+    /**
+     * Loads the position for a shape and KeyFramerInfoChunk
+     *
+     * @param chopper the ChunkChopper containing the state of the parser.  
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        int flags = chopper.getUnsignedShort();
+        chopper.getLong();
+        int numKeys = chopper.getUnsignedInt();
+
+        ArrayList pointList = new ArrayList();
+        for(int i =0; i < numKeys; i++)
+        {
+            long keyNumber = chopper.getUnsignedInt();
+            int  accelerationData = chopper.getUnsignedShort(); 
+
+            Point3f position = chopper.getPoint(); 
+            if(i==0)
+            {
+                chopper.getKeyFramer().setPosition(position);
+            }
+            pointList.add(position);
+        }
+        chopper.getKeyFramer().setPositionKeys(pointList);
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/RotationChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/RotationChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/RotationChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/RotationChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,129 +1,129 @@
-/*8
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import java.util.ArrayList;
-import java.util.List;
-import javax.vecmath.Quat4f;
-import javax.vecmath.Vector3f;
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * Extracts the rotation information from the 3ds file.
- * Rotations occur about a pivot at a position within
- * a local coordinate system. The rotation information
- * is provided to the KeyFramerInfoChunk which then converts
- * it to a global coordinate system and applies animation
- * information.
- * {@see KeyFramerInfoChunk} for more information about using
- * animations from a 3ds file
- */
-public class RotationChunk extends Chunk
-{
-    /** 
-     *  String that will be used as a data object in the transform that the 
-     *  RotationInterpolator will be a child of so it may be look up later.
-     **/
-    public static String ROTATION_TAG = "ROTATION_INTERPOLATOR";
-
-    /**
-     * Loads the quaternion for a rotation of a shape
-     * and notifies mesh info chunk.
-     *
-     * @param chopper the ChunkChopper containing the state of the parser.  
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        int flags = chopper.getUnsignedShort();
-        chopper.getLong();
-        int numKeys = chopper.getUnsignedInt();
-
-        Quat4f previousQuat = null;
-
-        List quats = new ArrayList();
-        for(int i =0; i < numKeys; i++)
-        {
-            long         frameNumber = chopper.getUnsignedInt();//Part of the track header
-            int   accelerationData = chopper.getUnsignedShort();//Part of the track header
-            getSplineTerms(accelerationData, chopper);//Part of the track header
-
-            float            angle = chopper.getFloat();
-            Vector3f        vector = chopper.getVector(); 
-
-            Quat4f quat = getQuaternion(vector, angle);
-            if(previousQuat != null) {
-                quat.mul(previousQuat, quat);
-            }
-            previousQuat = quat; 
-
-            quats.add(quat); 
-            if(i==0)
-            {
-                chopper.getKeyFramer().setRotation(quat);
-            }
-        }
-        chopper.getKeyFramer().setOrientationKeys(quats);
-    }
-
-    /**
-     * This only reads the spline data and should be part
-     * of the track header when it gets invented.
-     * @param chopper an integer representing the bits that 
-     * determine which of the five possible spline terms are present in the 
-     * data and should be read.
-     * @param chopper what to read the data from
-     * The possible spline values are are 
-     * <ol>
-     * <li> Tension
-     * <li> Continuity
-     * <li> Bias
-     * <li> EaseTo
-     * <li> EaseFrom
-     * </ol>
-     */
-    private void getSplineTerms(final int accelerationData, ChunkChopper chopper)
-    {
-        int bits = accelerationData;
-        for(int i=0; i < 5; i++)
-        {
-            bits = bits >>> i;
-            if((bits & 1) == 1)
-            {
-                chopper.getFloat();
-            }
-        }
-    }
-
-    /**
-     * This converts a 3ds angle and axis to 
-     * a quaternion rotation.  Successive
-     * rotations are relative to the first so each
-     * rotation must be made absolute by multiplying
-     * it with its predecessor
-     */
-    public Quat4f getQuaternion(Vector3f axis, float angle)
-    {
-        float sinA  = (float)(java.lang.Math.sin(angle/2.0f));
-        float cosA  = (float)(java.lang.Math.cos(angle/2.0f));
-        return new Quat4f(axis.x * sinA, axis.y * sinA, axis.z * sinA, cosA);
-    }
-}
+/*8
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.vecmath.Quat4f;
+import javax.vecmath.Vector3f;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * Extracts the rotation information from the 3ds file.
+ * Rotations occur about a pivot at a position within
+ * a local coordinate system. The rotation information
+ * is provided to the KeyFramerInfoChunk which then converts
+ * it to a global coordinate system and applies animation
+ * information.
+ * {@see KeyFramerInfoChunk} for more information about using
+ * animations from a 3ds file
+ */
+public class RotationChunk extends Chunk
+{
+    /** 
+     *  String that will be used as a data object in the transform that the 
+     *  RotationInterpolator will be a child of so it may be look up later.
+     **/
+    public static String ROTATION_TAG = "ROTATION_INTERPOLATOR";
+
+    /**
+     * Loads the quaternion for a rotation of a shape
+     * and notifies mesh info chunk.
+     *
+     * @param chopper the ChunkChopper containing the state of the parser.  
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        int flags = chopper.getUnsignedShort();
+        chopper.getLong();
+        int numKeys = chopper.getUnsignedInt();
+
+        Quat4f previousQuat = null;
+
+        List quats = new ArrayList();
+        for(int i =0; i < numKeys; i++)
+        {
+            long         frameNumber = chopper.getUnsignedInt();//Part of the track header
+            int   accelerationData = chopper.getUnsignedShort();//Part of the track header
+            getSplineTerms(accelerationData, chopper);//Part of the track header
+
+            float            angle = chopper.getFloat();
+            Vector3f        vector = chopper.getVector(); 
+
+            Quat4f quat = getQuaternion(vector, angle);
+            if(previousQuat != null) {
+                quat.mul(previousQuat, quat);
+            }
+            previousQuat = quat; 
+
+            quats.add(quat); 
+            if(i==0)
+            {
+                chopper.getKeyFramer().setRotation(quat);
+            }
+        }
+        chopper.getKeyFramer().setOrientationKeys(quats);
+    }
+
+    /**
+     * This only reads the spline data and should be part
+     * of the track header when it gets invented.
+     * @param chopper an integer representing the bits that 
+     * determine which of the five possible spline terms are present in the 
+     * data and should be read.
+     * @param chopper what to read the data from
+     * The possible spline values are are 
+     * <ol>
+     * <li> Tension
+     * <li> Continuity
+     * <li> Bias
+     * <li> EaseTo
+     * <li> EaseFrom
+     * </ol>
+     */
+    private void getSplineTerms(final int accelerationData, ChunkChopper chopper)
+    {
+        int bits = accelerationData;
+        for(int i=0; i < 5; i++)
+        {
+            bits = bits >>> i;
+            if((bits & 1) == 1)
+            {
+                chopper.getFloat();
+            }
+        }
+    }
+
+    /**
+     * This converts a 3ds angle and axis to 
+     * a quaternion rotation.  Successive
+     * rotations are relative to the first so each
+     * rotation must be made absolute by multiplying
+     * it with its predecessor
+     */
+    public Quat4f getQuaternion(Vector3f axis, float angle)
+    {
+        float sinA  = (float)(java.lang.Math.sin(angle/2.0f));
+        float cosA  = (float)(java.lang.Math.cos(angle/2.0f));
+        return new Quat4f(axis.x * sinA, axis.y * sinA, axis.z * sinA, cosA);
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/ScaleChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/ScaleChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/ScaleChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/ScaleChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,67 +1,67 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import java.util.ArrayList;
-import java.util.List;
-import javax.vecmath.Vector3f;
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * Extracts scale information from the 3ds file which
- * is then used by the mesh info chunk to construct a 
- * animation.
- */
-public class ScaleChunk extends Chunk
-{
-    /**
-     * Loads the scale for a shape
-     * and notifies the KeyFramerInfoChunk
-     *
-     * @param chopper the ChunkChopper containing the state of the parser.  
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        int flags = chopper.getUnsignedShort();
-        chopper.getLong();
-        int numKeys = chopper.getUnsignedInt();
-
-        List scaleKeys = new ArrayList();
-
-        for(int i =0; i < numKeys; i++)
-        {
-            long keyNumber = chopper.getUnsignedInt();
-            int  accelerationData = chopper.getUnsignedShort(); 
-
-            float scaleX = chopper.getFloat();
-            float scaleZ = chopper.getFloat();
-            float scaleY = chopper.getFloat();
-            Vector3f scale = new Vector3f(scaleX, scaleY, scaleZ);
-            if(i==0)
-            {
-                chopper.getKeyFramer().setScale(scale);
-            }
-            scaleKeys.add(scale);
-        }
-        chopper.getKeyFramer().setScaleKeys(scaleKeys);
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.vecmath.Vector3f;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * Extracts scale information from the 3ds file which
+ * is then used by the mesh info chunk to construct a 
+ * animation.
+ */
+public class ScaleChunk extends Chunk
+{
+    /**
+     * Loads the scale for a shape
+     * and notifies the KeyFramerInfoChunk
+     *
+     * @param chopper the ChunkChopper containing the state of the parser.  
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        int flags = chopper.getUnsignedShort();
+        chopper.getLong();
+        int numKeys = chopper.getUnsignedInt();
+
+        List scaleKeys = new ArrayList();
+
+        for(int i =0; i < numKeys; i++)
+        {
+            long keyNumber = chopper.getUnsignedInt();
+            int  accelerationData = chopper.getUnsignedShort(); 
+
+            float scaleX = chopper.getFloat();
+            float scaleZ = chopper.getFloat();
+            float scaleY = chopper.getFloat();
+            Vector3f scale = new Vector3f(scaleX, scaleY, scaleZ);
+            if(i==0)
+            {
+                chopper.getKeyFramer().setScale(scale);
+            }
+            scaleKeys.add(scale);
+        }
+        chopper.getKeyFramer().setScaleKeys(scaleKeys);
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/SmoothingChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/SmoothingChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/SmoothingChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/SmoothingChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,65 +1,65 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import javax.vecmath.Point3f;
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-import com.microcrowd.loader.java3d.max3ds.ChunkMap;
-
-/**
- * This chunk is used to generate normals for a mesh according
- * to the data in the smoothing groups chunk.
- * Vertices that share coordinates will all use the same, averaged
- * normal if they also belong to the same smoothing groups.
- * @author jdeford
- */
-public class SmoothingChunk extends Chunk
-{
-    /**
-     * Loads the vertices smoothing groups for 
-     * a mesh and stores it in chopper
-     *
-     * @param chopper the ChunkChopper containing the state of the parser.  
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        Point3f[] vertices = (Point3f[])chopper.popData(ChunkMap.FACES_DESCRIPTION);
-        int[] smoothGroups = new int[vertices.length];
-        int numFaces = vertices.length/3;
-        for(int i=0; i < numFaces; i++)
-        {
-            int groupMask = chopper.getInt();
-            smoothGroups[i*3]=groupMask;
-            smoothGroups[(i*3)+1]=groupMask;
-            smoothGroups[(i*3)+2]=groupMask;
-
-            java.util.ArrayList list = new java.util.ArrayList();
-            for(int j=0; j < 32; j++)
-            {
-                if(((0x1l << j) & groupMask) > 0)
-                {
-                    list.add(new Integer(j));
-                }
-            }
-        }
-        chopper.pushData(chopper.getID(), smoothGroups);
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import javax.vecmath.Point3f;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+import com.microcrowd.loader.java3d.max3ds.ChunkMap;
+
+/**
+ * This chunk is used to generate normals for a mesh according
+ * to the data in the smoothing groups chunk.
+ * Vertices that share coordinates will all use the same, averaged
+ * normal if they also belong to the same smoothing groups.
+ * @author jdeford
+ */
+public class SmoothingChunk extends Chunk
+{
+    /**
+     * Loads the vertices smoothing groups for 
+     * a mesh and stores it in chopper
+     *
+     * @param chopper the ChunkChopper containing the state of the parser.  
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        Point3f[] vertices = (Point3f[])chopper.popData(ChunkMap.FACES_DESCRIPTION);
+        int[] smoothGroups = new int[vertices.length];
+        int numFaces = vertices.length/3;
+        for(int i=0; i < numFaces; i++)
+        {
+            int groupMask = chopper.getInt();
+            smoothGroups[i*3]=groupMask;
+            smoothGroups[(i*3)+1]=groupMask;
+            smoothGroups[(i*3)+2]=groupMask;
+
+            java.util.ArrayList list = new java.util.ArrayList();
+            for(int j=0; j < 32; j++)
+            {
+                if(((0x1l << j) & groupMask) > 0)
+                {
+                    list.add(new Integer(j));
+                }
+            }
+        }
+        chopper.pushData(chopper.getID(), smoothGroups);
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/SpotLightChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/SpotLightChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/SpotLightChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/SpotLightChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,73 +1,73 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import javax.media.j3d.SpotLight;
-import javax.media.j3d.Transform3D;
-import javax.media.j3d.TransformGroup;
-import javax.vecmath.Point3d;
-import javax.vecmath.Point3f;
-import javax.vecmath.Vector3d;
-import javax.vecmath.Vector3f;
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-import com.microcrowd.loader.java3d.max3ds.ChunkMap;
-
-/**
- * SpotLights to be placed in a scene.
- *
- * All the default parameters other than 
- * position and direction are used and
- * not loaded from the 3ds file.
- */
-public class SpotLightChunk extends Chunk
-{
-
-
-    /**
-     * This is called by the chunk chopper before any of the chunk's 
-     * subchunks  are loaded.  Any data loaded that may need to be 
-     * used later by superchunks should be stored in
-     * the chunk chopper via {@link ChunkChopper#popData}
-     *
-     * @param chopper the ChunkChopper that will have the light placed in it.  
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        Point3f target = chopper.getPoint();
-        float beam = chopper.getFloat();
-        float falloff = chopper.getFloat();
-        SpotLight light = new SpotLight();
-
-        Vector3f direction = new Vector3f(0,0,-1); 
-
-        Vector3f position = (Vector3f)chopper.popData(ChunkMap.LIGHT);
-        TransformGroup group = chopper.getGroup();
-        Transform3D transform = new Transform3D();
-        group.getTransform(transform);
-        transform.lookAt(new Point3d(position), new Point3d(target), new Vector3d(0,1,0));
-        transform.invert();
-        transform.setTranslation(position);
-        group.setTransform(transform);
-
-        chopper.pushData(chopper.getID(), light);
-        chopper.addLightNode(light);
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import javax.media.j3d.SpotLight;
+import javax.media.j3d.Transform3D;
+import javax.media.j3d.TransformGroup;
+import javax.vecmath.Point3d;
+import javax.vecmath.Point3f;
+import javax.vecmath.Vector3d;
+import javax.vecmath.Vector3f;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+import com.microcrowd.loader.java3d.max3ds.ChunkMap;
+
+/**
+ * SpotLights to be placed in a scene.
+ *
+ * All the default parameters other than 
+ * position and direction are used and
+ * not loaded from the 3ds file.
+ */
+public class SpotLightChunk extends Chunk
+{
+
+
+    /**
+     * This is called by the chunk chopper before any of the chunk's 
+     * subchunks  are loaded.  Any data loaded that may need to be 
+     * used later by superchunks should be stored in
+     * the chunk chopper via {@link ChunkChopper#popData}
+     *
+     * @param chopper the ChunkChopper that will have the light placed in it.  
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        Point3f target = chopper.getPoint();
+        float beam = chopper.getFloat();
+        float falloff = chopper.getFloat();
+        SpotLight light = new SpotLight();
+
+        Vector3f direction = new Vector3f(0,0,-1); 
+
+        Vector3f position = (Vector3f)chopper.popData(ChunkMap.LIGHT);
+        TransformGroup group = chopper.getGroup();
+        Transform3D transform = new Transform3D();
+        group.getTransform(transform);
+        transform.lookAt(new Point3d(position), new Point3d(target), new Vector3d(0,1,0));
+        transform.invert();
+        transform.setTranslation(position);
+        group.setTransform(transform);
+
+        chopper.pushData(chopper.getID(), light);
+        chopper.addLightNode(light);
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/StringChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/StringChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/StringChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/StringChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,52 +1,52 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * These have no subchunks. Only String data terminated with a null. For
- * strings with unknown length use {@link ChunkChopper#getString} This can
- * also be used for chunks that have data of a known length beginning with a
- * string with unnessecary(you don't want to use it) data following.
- */
-public class StringChunk extends Chunk
-{
-    /**
-     * Reads in all the data for this chunk and makes a string out of it.
-     * This will set the data in the chopper with a key of this chunks id.
-     *
-     *
-     * @param chopper the chopper that is doing the parsing.  
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        byte[] stringArray = chopper.getChunkBytes();
-
-        String value = new String(stringArray, 0, stringArray.length - 1);
-        if (value.indexOf((char)(0x0000)) > 0) {
-            value = value.substring(0, value.indexOf((char)(0x0000)));
-        }
-
-        chopper.pushData(chopper.getID(), value);
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * These have no subchunks. Only String data terminated with a null. For
+ * strings with unknown length use {@link ChunkChopper#getString} This can
+ * also be used for chunks that have data of a known length beginning with a
+ * string with unnessecary(you don't want to use it) data following.
+ */
+public class StringChunk extends Chunk
+{
+    /**
+     * Reads in all the data for this chunk and makes a string out of it.
+     * This will set the data in the chopper with a key of this chunks id.
+     *
+     *
+     * @param chopper the chopper that is doing the parsing.  
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        byte[] stringArray = chopper.getChunkBytes();
+
+        String value = new String(stringArray, 0, stringArray.length - 1);
+        if (value.indexOf((char)(0x0000)) > 0) {
+            value = value.substring(0, value.indexOf((char)(0x0000)));
+        }
+
+        chopper.pushData(chopper.getID(), value);
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/TextureChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/TextureChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/TextureChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/TextureChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,47 +1,47 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-import com.microcrowd.loader.java3d.max3ds.ChunkMap;
-
-
-/**
- * Loads percentage values from binary data representing them.
- */
-public class TextureChunk extends Chunk
-{
-
-    /**
-     * Gets the current texture image from the chopper
-     * creates a texture with it and sets that texture
-     * on the chopper.
-     *
-     * @param chopper  the parser containing the state of parsing
-     */
-    public void initialize(ChunkChopper chopper)
-    {
-        String textureName = (String)chopper.popData(ChunkMap.TEXTURE_NAME);
-        chopper.pushData(ChunkMap.TEXTURE, chopper.createTexture(textureName));
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+import com.microcrowd.loader.java3d.max3ds.ChunkMap;
+
+
+/**
+ * Loads percentage values from binary data representing them.
+ */
+public class TextureChunk extends Chunk
+{
+
+    /**
+     * Gets the current texture image from the chopper
+     * creates a texture with it and sets that texture
+     * on the chopper.
+     *
+     * @param chopper  the parser containing the state of parsing
+     */
+    public void initialize(ChunkChopper chopper)
+    {
+        String textureName = (String)chopper.popData(ChunkMap.TEXTURE_NAME);
+        chopper.pushData(ChunkMap.TEXTURE, chopper.createTexture(textureName));
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/Vertex2ListChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/Vertex2ListChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/Vertex2ListChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/Vertex2ListChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,55 +1,55 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import javax.vecmath.TexCoord2f;
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * Reads a list of x,y points that will be used
- * later for texture mapping.
- *
- * @author jdeford 
- */
-public class Vertex2ListChunk extends Chunk
-{
-    private static final int POINT_2F_SIZE = 8;
-
-    /**
-     * Reads all the point data from the chopper and stores
-     * teh points in the chopper.
-     *
-     * @param chopper the chopper that will parse and store
-     * the data using this chunks id as the key. 
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        int numVertices = chopper.getUnsignedShort();
-        TexCoord2f[] points = new TexCoord2f[numVertices];
-        for (int i = 0; i < numVertices; i++) {
-            float point0 = chopper.getFloat();
-            float point1 = chopper.getFloat();
-            points[i] = new TexCoord2f(point0, point1);
-        }
-        chopper.pushData(chopper.getID(), points);
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import javax.vecmath.TexCoord2f;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * Reads a list of x,y points that will be used
+ * later for texture mapping.
+ *
+ * @author jdeford 
+ */
+public class Vertex2ListChunk extends Chunk
+{
+    private static final int POINT_2F_SIZE = 8;
+
+    /**
+     * Reads all the point data from the chopper and stores
+     * teh points in the chopper.
+     *
+     * @param chopper the chopper that will parse and store
+     * the data using this chunks id as the key. 
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        int numVertices = chopper.getUnsignedShort();
+        TexCoord2f[] points = new TexCoord2f[numVertices];
+        for (int i = 0; i < numVertices; i++) {
+            float point0 = chopper.getFloat();
+            float point1 = chopper.getFloat();
+            points[i] = new TexCoord2f(point0, point1);
+        }
+        chopper.pushData(chopper.getID(), points);
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/chunks/Vertex3ListChunk.java src-gil/com/microcrowd/loader/java3d/max3ds/chunks/Vertex3ListChunk.java
--- src/com/microcrowd/loader/java3d/max3ds/chunks/Vertex3ListChunk.java	2005-07-25 19:37:33.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/chunks/Vertex3ListChunk.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,54 +1,54 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds.chunks;
-
-import javax.vecmath.Point3f;
-import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
-
-/**
- * Reads and store x,y,z vertex coordinates.
- * The coordinates will be accessed with indexes to construct 
- * the mesh out of triangles.
- * @author  jdeford
- */
-public class Vertex3ListChunk extends Chunk
-{
-    private static final int POINT_3F_SIZE = 12;
-
-    /**
-     * Reads all the point data from the chopper
-     * and stores it using this chunk's id as the key.
-     *
-     * @param chopper the chopper that will read and
-     * store the data. 
-     */
-    public void loadData(ChunkChopper chopper)
-    {
-        int numVertices = chopper.getUnsignedShort();
-        Point3f[] points = new Point3f[numVertices];
-        for (int i = 0; i < numVertices; i++) {
-            points[i] = new Point3f(chopper.getPoint());
-        }
-
-        chopper.pushData(chopper.getID(), points);
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds.chunks;
+
+import javax.vecmath.Point3f;
+import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
+
+/**
+ * Reads and store x,y,z vertex coordinates.
+ * The coordinates will be accessed with indexes to construct 
+ * the mesh out of triangles.
+ * @author  jdeford
+ */
+public class Vertex3ListChunk extends Chunk
+{
+    private static final int POINT_3F_SIZE = 12;
+
+    /**
+     * Reads all the point data from the chopper
+     * and stores it using this chunk's id as the key.
+     *
+     * @param chopper the chopper that will read and
+     * store the data. 
+     */
+    public void loadData(ChunkChopper chopper)
+    {
+        int numVertices = chopper.getUnsignedShort();
+        Point3f[] points = new Point3f[numVertices];
+        for (int i = 0; i < numVertices; i++) {
+            points[i] = new Point3f(chopper.getPoint());
+        }
+
+        chopper.pushData(chopper.getID(), points);
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/ChunkTester.java src-gil/com/microcrowd/loader/java3d/max3ds/ChunkTester.java
--- src/com/microcrowd/loader/java3d/max3ds/ChunkTester.java	2005-07-25 19:37:32.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/ChunkTester.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,31 +1,31 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- *
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com.com
- */
-
-package com.microcrowd.loader.java3d.max3ds;
-
-/**
- * Used to test and create test data for chunks.
- */
-public class ChunkTester
-{
-    
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ *
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds;
+
+/**
+ * Used to test and create test data for chunks.
+ */
+public class ChunkTester
+{
+    
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/data/KeyFramer.java src-gil/com/microcrowd/loader/java3d/max3ds/data/KeyFramer.java
--- src/com/microcrowd/loader/java3d/max3ds/data/KeyFramer.java	2005-07-25 19:41:47.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/data/KeyFramer.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,526 +1,526 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- *
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-package com.microcrowd.loader.java3d.max3ds.data;
-
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import javax.media.j3d.Alpha;
-import javax.media.j3d.Behavior;
-import javax.media.j3d.Group;
-import javax.media.j3d.Node;
-import javax.media.j3d.RotPosPathInterpolator;
-import javax.media.j3d.Transform3D;
-import javax.media.j3d.TransformGroup;
-import javax.media.j3d.TransformInterpolator;
-import javax.vecmath.Matrix4f;
-import javax.vecmath.Point3f;
-import javax.vecmath.Quat4f;
-import javax.vecmath.Vector3d;
-import javax.vecmath.Vector3f;
-
-/**
- * @author Josh DeFord 
- */
-public class KeyFramer
-{
-    private HashMap lastGroupMap = new HashMap();
-    private HashMap fatherMap = new HashMap();
-
-    private Quat4f   rotation;
-    private Point3f  position;
-    private Point3f  pivotCenter;
-    private Vector3f pivot;
-    private Vector3f scale;
-    private HashMap  namedObjectCoordinateSystems = new HashMap();
-
-    private List positionKeys;
-    private List orientationKeys;
-    private List scaleKeys;
-
-    private Integer id;
-    private Group father;
-    private Group dummyObject;
-
-
-    /**
-     * Retrieves the named object for the current key framer
-     * inserts the rotation, position and pivot transformations for frame 0
-     * and assigns the coordinate system to it.
-     *
-     * The inverse of the local coordinate system converts from 3ds 
-     * semi-absolute coordinates (what is in the file) to local coordinates.
-     *
-     * Then these local coordinates are converted with matrix 
-     * that will instantiate them to absolute coordinates:
-     * Xabs = sx a1 (Xl-Px) + sy a2 (Yl-Py) + sz a3 (Zl-Pz) + Tx
-     * Yabs = sx b1 (Xl-Px) + sy b2 (Yl-Py) + sz b3 (Zl-Pz) + Ty
-     * Zabs = sx c1 (Xl-Px) + sy c2 (Yl-Py) + sz c3 (Zl-Pz) + Tz
-     * Where:
-     * (Xabs,Yabs,Zabs) = absolute coordinate
-     * (Px,Py,Pz) = mesh pivot (constant)
-     * (X1,Y1,Z1) = local coordinates
-     *
-     */
-    public Behavior createBehavior(String meshName, Group transformGroup, Object testObject)
-    {
-        Group objectGroup = getObjectByName(meshName, transformGroup, testObject);
-        //System.out.println("mesh " + meshName + " scale " + scale);
-        if(objectGroup == null)
-            return null;
-
-        insertFather(objectGroup, meshName);
-
-        TransformInterpolator behavior = null;
-        Transform3D coordinateSystem  = (Transform3D)namedObjectCoordinateSystems.get(meshName);
-
-        //Gonna put these children back later.
-        Enumeration children = removeChildren(objectGroup);
-
-        Transform3D coordinateTransform = coordinateSystem == null ? new Transform3D() : new Transform3D(coordinateSystem);
-
-        Transform3D targetTransform = new Transform3D();
-        TransformGroup targetGroup = new TransformGroup(targetTransform);
-
-        TransformGroup localCoordinates = hasKeys() ? buildLocalCoordinates(coordinateSystem) : new TransformGroup();
-        TransformGroup lastGroup = (TransformGroup)addGroups(objectGroup, new Group[]
-                {
-                    localCoordinates,
-                    targetGroup,
-                    buildPivotGroup(coordinateTransform, pivot),
-                    buildKeysGroup(),
-                });
-
-        addChildren(children, lastGroup);
-        lastGroupMap.put(objectGroup, lastGroup);
-
-
-        behavior = buildInterpolator(targetGroup, coordinateSystem);
-        if(behavior != null)
-        {
-            behavior.setEnable(false);
-            targetGroup.addChild(behavior);
-
-            behavior.computeTransform(0f, targetTransform);
-            targetGroup.setTransform(targetTransform);
-        }
-        return behavior;
-    }
-
-    private Enumeration removeChildren(Group group)
-    {
-        Enumeration children = group.getAllChildren(); 
-        group.removeAllChildren();
-        return children;
-    }
-
-    private void addChildren(Enumeration children, Group group)
-    {
-        if(group == null)
-            return;
-        while(children.hasMoreElements())
-        {
-            Node node = (Node)(children.nextElement());
-            group.addChild(node);
-        }
-    }
-
-    /**
-     * Looks up the current object.
-     * objectGroup is returned if it is the right one to return
-     * otherwise a new dummy object may be returned.
-     * If it isn't there it gets the dummy object
-     * from the frames description chunk.
-     */
-    private Group getObjectByName(String objectName, Group objectGroup, Object testObject)
-    {
-
-        //This means its a dummy object.  It needs to be created.
-        if(objectGroup == null && testObject == null)
-        {
-            namedObjectCoordinateSystems.put(objectName, new Transform3D());
-            objectGroup = dummyObject;
-        }
-
-        return objectGroup;
-    }
-
-    /**
-     * Locates the father for the object named objectName and inserts 
-     * its transform cluster between the parent and all
-     * the parent's children. This only occurs in a hierarchical
-     * model. like bones and stuff. The fatherGroup, if found,
-     * is removed from whatever parent belonged to on before insertion.
-     */
-    private void insertFather(Group parentGroup, String objectName)
-    {
-        if(father == null)
-            return;
-        Group topGroup = new TransformGroup(); 
-        topGroup.addChild(father);
-        Group bottomGroup = (Group)lastGroupMap.get(father);
-
-        if(topGroup == null)
-            return;
-
-        Group fatherParent = (Group)topGroup.getParent();
-        if(fatherParent != null)
-            fatherParent.removeChild(topGroup);
-        
-        Enumeration originalChildren = removeChildren(parentGroup);
-        parentGroup.addChild(topGroup);
-        addChildren(originalChildren, bottomGroup);
-    }
-
-    /**
-     * Builds a transform group from the zeroth key of the 
-     * position and rotation tracks.
-     * @return transform group with position and rotation information
-     */
-    private TransformGroup buildKeysGroup()
-    {
-        Transform3D positionTransform   = new Transform3D();
-        positionTransform.set(new Vector3f(position));
-
-        Transform3D rotationTransform   = new Transform3D();
-        rotationTransform.set(rotation);
-
-        Transform3D scaleTransform = new Transform3D();
-        scaleTransform.setScale(new Vector3d(scale));
-        TransformGroup scaleGroup = new TransformGroup(scaleTransform);
-
-        Transform3D keyTransform = new Transform3D(positionTransform);
-        keyTransform.mul(scaleTransform);
-        keyTransform.mul(rotationTransform);
-        return new TransformGroup(keyTransform);
-    }
-
-    /**
-     * Builds a pivot group that will allow the objects
-     * to be positioned properly according to their rotations
-     * and positions.
-     * @param coordinateTransform the coordinate system defining the 
-     * location and orientation of the local axis. This is not modified.
-     * @param pivot the pivot defined in the 3ds file loaded by pivot chunk.
-     * This is not changed.
-     */
-    private TransformGroup buildPivotGroup(Transform3D coordinateTransform, Vector3f pivot)
-    {
-            Transform3D pivotTransform = new Transform3D();
-            pivotTransform.mulInverse(coordinateTransform);
-            pivot = new Vector3f(pivot);
-            pivot.negate();
-            translatePivot(pivotTransform, pivot, pivotCenter);
-            return new TransformGroup(pivotTransform);
-    }
-
-    /**
-     * Builds a coordinate group that will allow the objects
-     * to be positioned properly according to their rotations
-     * and positions.
-     * @param coordinateSystem the coordinate system defining the 
-     * location and orientation of the local axis. This is modified 
-     * so it will be useful during the construction
-     * of the animations.
-     */
-    private TransformGroup buildLocalCoordinates(Transform3D coordinateSystem)
-    {
-        Matrix4f coordMatrix = new Matrix4f();
-        Vector3f translation = new Vector3f();
-
-        coordinateSystem.get(translation);
-        coordinateSystem.invert();
-
-        coordinateSystem.get(coordMatrix);
-        coordMatrix.m03 = translation.x;
-        coordMatrix.m13 = translation.y;
-        coordMatrix.m23 = translation.z;
-        coordinateSystem.set(coordMatrix);
-        coordinateSystem.invert();
-        TransformGroup systemGroup = new TransformGroup(coordinateSystem);
-        coordinateSystem.invert();
-        return systemGroup;
-    }
-
-   /**
-     * Hierarchically adds the provided groups in order to parentGroup.
-     * groups[0] is added to parentGroup, groups[1] is added to groups[0] etc.
-     * @return the last group added (groups[groups.length - 1]).
-     */
-    private Group addGroups(Group parentGroup, Group[] groups)
-    {
-        Group nextGroup = parentGroup;
-        for(int i=0; i < groups.length; i++)
-        {
-            nextGroup.addChild(groups[i]);
-            nextGroup = groups[i];
-        }
-        return groups[groups.length - 1];
-    }
-
-    /**
-     * Does a pre rotational translation of the pivot.
-     * @param transform the matrix that will have a translation concatenated to it.
-     * @param vector the vector which will be used to translate the matrix.
-     * @param offset the offset used to offset the pivot. 
-     */
-    private void translatePivot(Transform3D transform, Vector3f vector, Point3f offset)
-    {
-        if(offset != null)
-        {
-            pivot.sub(offset);
-        }
-        Matrix4f matrix = new Matrix4f();
-        transform.get(matrix);
-
-        matrix.m03 += (matrix.m00*vector.x + matrix.m01*vector.y + matrix.m02*vector.z);
-        matrix.m13 += (matrix.m10*vector.x + matrix.m11*vector.y + matrix.m12*vector.z);
-        matrix.m23 += (matrix.m20*vector.x + matrix.m21*vector.y + matrix.m22*vector.z);
-
-        transform.set(matrix);
-    }
-
-
-    /**
-     * Builds a rotation position interpolator for use on this mesh using position and rotation information
-     * adds it to targetGroup.
-     * This does not set the capability bits that need to be set for the animation  
-     * to be used. The capability bits of the targetGroup must be set by the client application.
-     * The alpha object on the Interpolator must also be enabled. 
-     * The Interpolator must also have its scheduling bounds set.
-     * @param pivotGroup transform group which will be operated on by the interpolator.
-     * @param interpolatorAxis the axis that about which rotations will be centered.
-     */
-    //TODO... This needs to use both a rotation interpolator and a position interpolator
-    //in case there are keys with no position information but position information and 
-    //vice versa right now its using RotPosPathInterpolator
-    private TransformInterpolator buildInterpolator(TransformGroup targetGroup, Transform3D axisOfTransform)
-    {
-        makeTwoListsTheSameSize(positionKeys, orientationKeys);
-        int numKeys = positionKeys.size();
-
-        Point3f currentPoint = position; 
-        Quat4f  currentQuat  = rotation; 
-        RotPosPathInterpolator rotator = null; 
-        if(numKeys > 1) 
-        {
-            float[]    knots = new float[numKeys];
-            Point3f[] points = new Point3f[numKeys];
-            Quat4f[]  quats  = new Quat4f[numKeys];
-
-            for(int i=0; i < numKeys; i++) 
-            {
-                //Knots need to be between 0(beginning) and 1(end)
-                knots[i]= (i==0?0:((float)i/((float)(numKeys-1))));
-                if(positionKeys.size() > i)
-                {
-                    Point3f newPoint = (Point3f)positionKeys.get(i);
-                    if(newPoint != null)
-                    {
-                        currentPoint = newPoint;
-                    }
-
-                    Quat4f newQuat = (Quat4f)orientationKeys.get(i);
-                    if(newQuat != null)
-                    {
-                        currentQuat = newQuat;
-                    }
-                }
-
-                points[i] = currentPoint;
-                quats[i] = currentQuat;
-                quats[i].inverse();
-            }
-
-            //This gives a continuous loop at a rate of 30 fps
-            Alpha alpha = new Alpha(-1, (long)(numKeys/.03));
-            alpha.setStartTime(System.currentTimeMillis());
-            alpha.setDuplicateOnCloneTree(true);
-
-            rotator = new RotPosPathInterpolator(alpha, targetGroup, 
-                    axisOfTransform, knots, 
-                    quats, points);
-        }
-        return rotator;
-    }
-
-    public void makeTwoListsTheSameSize(List list1, List list2)
-    {
-        growList(list2.size() - 1, list1);
-        growList(list1.size() - 1, list2);
-    }
-
-    /**
-     * Make sure the list is at least able to
-     * hold a value at index.
-     * @param index an int specifying the initial size
-     * @parame the list that may need to grow
-     */
-    public void growList(int index, List list)
-    {
-        int numNeeded = (index + 1) - list.size();
-        while(numNeeded-- > 0)
-        {
-            list.add(null);
-        }
-    }
-
-    /**
-     * Sets the center of the bounding box that the pivot
-     * should offset.
-     */
-    public void setPivotCenter(Point3f center)
-    {
-        this.pivotCenter = center;
-    }
-
-    /**
-     * Called to set the coordinate system transform for an object named
-     * objectName. 
-     * This is the first t
-     */
-    public void setCoordinateSystem(String objectName, Transform3D coordinateSystem)
-    {
-        namedObjectCoordinateSystems.put(objectName, coordinateSystem);
-    }
-
-    /**
-     * Sets the group that will be used to center rotations.
-     * This is applied to the mesh after all other transforms
-     * have been applied.
-     * @param group the group that will act as the rotation transform.
-     */
-    public void setRotation(Quat4f rotation)
-    {
-        this.rotation = rotation;
-    }
-
-    /**
-     * Sets the pivot that will be used to as a pivot for
-     * these transfomations.
-     * @param group the group that will act as the pivot. 
-     */
-    public void setPivot(Vector3f pivot)
-    {
-        this.pivot = pivot;
-    }
-
-    /**
-     * Sets the scale for x y and z axis for objects. 
-     * This is applied to the mesh before the rotation transform 
-     * has been applied.
-     * @param group the group that will act as the scale 
-     */
-    public void setScale(Vector3f scale)
-    {
-        this.scale = scale;
-    }
-
-    /**
-     * Sets the scale information necessary for animation.s
-     * @param scaleKeys a list of Vector3f, which may contain null elements,
-     * containing a position for some keys.
-     */
-    public void setScaleKeys(List scaleKeys)
-    {
-        this.scaleKeys = scaleKeys;
-    }
-
-    /**
-     * Sets the group that will be used to translate the mesh..
-     * This is applied to the mesh just before the rotation transform 
-     * has been applied.
-     * @param group the group that will act as the position transform.
-     */
-    public void setPosition(Point3f position)
-    {
-        this.position = position;
-    }
-
-    /**
-     * Sets the position information necessary for animation.s
-     * @param positions a list of Point3f, which may contain null elements,
-     * containing a position for some keys.
-     */
-    public void setPositionKeys(List positions)
-    {
-        positionKeys = positions;
-    }
-
-    /**
-     * Sets the orientation information necessary for animation.s
-     * @param positions a list of Quat4f, which may contain null elements,
-     * containing a orientation for some keys.
-     */
-    public void setOrientationKeys(List orientations)
-    {
-        orientationKeys = orientations;
-    }
-
-    /**
-     *
-     */
-    public void setDummyObject(Group object)
-    {
-        dummyObject = object;
-    }
-
-    /**
-     * returns true if position keys and orientation
-     * keys are longer than one element each.
-     */
-    public boolean hasKeys()
-    {
-        return (positionKeys.size() > 1 || orientationKeys.size() > 1);
-    }
-
-    /**
-     */
-    public void addFather(int fatherID, TransformGroup newFather)
-    {
-        if(fatherID < 0)
-        {
-            father = null;
-        }
-        else
-        {
-            father = (TransformGroup)(fatherMap.get(new Integer(fatherID)));
-            //Remove the father's father because the father will
-            //be inserted somewhere later.
-            Group grandFather = (Group)father.getParent();
-            if(grandFather != null)
-            {
-                grandFather.removeChild(father);
-            }
-        }
-        fatherMap.put(id, newFather);
-    }
-
-    /**
-     * Sets the id for these frames.
-     * @param id the id for these frames.
-     */
-    public void setID(int id)
-    {
-        this.id = new Integer(id);
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ *
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+package com.microcrowd.loader.java3d.max3ds.data;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import javax.media.j3d.Alpha;
+import javax.media.j3d.Behavior;
+import javax.media.j3d.Group;
+import javax.media.j3d.Node;
+import javax.media.j3d.RotPosPathInterpolator;
+import javax.media.j3d.Transform3D;
+import javax.media.j3d.TransformGroup;
+import javax.media.j3d.TransformInterpolator;
+import javax.vecmath.Matrix4f;
+import javax.vecmath.Point3f;
+import javax.vecmath.Quat4f;
+import javax.vecmath.Vector3d;
+import javax.vecmath.Vector3f;
+
+/**
+ * @author Josh DeFord 
+ */
+public class KeyFramer
+{
+    private HashMap lastGroupMap = new HashMap();
+    private HashMap fatherMap = new HashMap();
+
+    private Quat4f   rotation;
+    private Point3f  position;
+    private Point3f  pivotCenter;
+    private Vector3f pivot;
+    private Vector3f scale;
+    private HashMap  namedObjectCoordinateSystems = new HashMap();
+
+    private List positionKeys;
+    private List orientationKeys;
+    private List scaleKeys;
+
+    private Integer id;
+    private Group father;
+    private Group dummyObject;
+
+
+    /**
+     * Retrieves the named object for the current key framer
+     * inserts the rotation, position and pivot transformations for frame 0
+     * and assigns the coordinate system to it.
+     *
+     * The inverse of the local coordinate system converts from 3ds 
+     * semi-absolute coordinates (what is in the file) to local coordinates.
+     *
+     * Then these local coordinates are converted with matrix 
+     * that will instantiate them to absolute coordinates:
+     * Xabs = sx a1 (Xl-Px) + sy a2 (Yl-Py) + sz a3 (Zl-Pz) + Tx
+     * Yabs = sx b1 (Xl-Px) + sy b2 (Yl-Py) + sz b3 (Zl-Pz) + Ty
+     * Zabs = sx c1 (Xl-Px) + sy c2 (Yl-Py) + sz c3 (Zl-Pz) + Tz
+     * Where:
+     * (Xabs,Yabs,Zabs) = absolute coordinate
+     * (Px,Py,Pz) = mesh pivot (constant)
+     * (X1,Y1,Z1) = local coordinates
+     *
+     */
+    public Behavior createBehavior(String meshName, Group transformGroup, Object testObject)
+    {
+        Group objectGroup = getObjectByName(meshName, transformGroup, testObject);
+        //System.out.println("mesh " + meshName + " scale " + scale);
+        if(objectGroup == null)
+            return null;
+
+        insertFather(objectGroup, meshName);
+
+        TransformInterpolator behavior = null;
+        Transform3D coordinateSystem  = (Transform3D)namedObjectCoordinateSystems.get(meshName);
+
+        //Gonna put these children back later.
+        Enumeration children = removeChildren(objectGroup);
+
+        Transform3D coordinateTransform = coordinateSystem == null ? new Transform3D() : new Transform3D(coordinateSystem);
+
+        Transform3D targetTransform = new Transform3D();
+        TransformGroup targetGroup = new TransformGroup(targetTransform);
+
+        TransformGroup localCoordinates = hasKeys() ? buildLocalCoordinates(coordinateSystem) : new TransformGroup();
+        TransformGroup lastGroup = (TransformGroup)addGroups(objectGroup, new Group[]
+                {
+                    localCoordinates,
+                    targetGroup,
+                    buildPivotGroup(coordinateTransform, pivot),
+                    buildKeysGroup(),
+                });
+
+        addChildren(children, lastGroup);
+        lastGroupMap.put(objectGroup, lastGroup);
+
+
+        behavior = buildInterpolator(targetGroup, coordinateSystem);
+        if(behavior != null)
+        {
+            behavior.setEnable(false);
+            targetGroup.addChild(behavior);
+
+            behavior.computeTransform(0f, targetTransform);
+            targetGroup.setTransform(targetTransform);
+        }
+        return behavior;
+    }
+
+    private Enumeration removeChildren(Group group)
+    {
+        Enumeration children = group.getAllChildren(); 
+        group.removeAllChildren();
+        return children;
+    }
+
+    private void addChildren(Enumeration children, Group group)
+    {
+        if(group == null)
+            return;
+        while(children.hasMoreElements())
+        {
+            Node node = (Node)(children.nextElement());
+            group.addChild(node);
+        }
+    }
+
+    /**
+     * Looks up the current object.
+     * objectGroup is returned if it is the right one to return
+     * otherwise a new dummy object may be returned.
+     * If it isn't there it gets the dummy object
+     * from the frames description chunk.
+     */
+    private Group getObjectByName(String objectName, Group objectGroup, Object testObject)
+    {
+
+        //This means its a dummy object.  It needs to be created.
+        if(objectGroup == null && testObject == null)
+        {
+            namedObjectCoordinateSystems.put(objectName, new Transform3D());
+            objectGroup = dummyObject;
+        }
+
+        return objectGroup;
+    }
+
+    /**
+     * Locates the father for the object named objectName and inserts 
+     * its transform cluster between the parent and all
+     * the parent's children. This only occurs in a hierarchical
+     * model. like bones and stuff. The fatherGroup, if found,
+     * is removed from whatever parent belonged to on before insertion.
+     */
+    private void insertFather(Group parentGroup, String objectName)
+    {
+        if(father == null)
+            return;
+        Group topGroup = new TransformGroup(); 
+        topGroup.addChild(father);
+        Group bottomGroup = (Group)lastGroupMap.get(father);
+
+        if(topGroup == null)
+            return;
+
+        Group fatherParent = (Group)topGroup.getParent();
+        if(fatherParent != null)
+            fatherParent.removeChild(topGroup);
+        
+        Enumeration originalChildren = removeChildren(parentGroup);
+        parentGroup.addChild(topGroup);
+        addChildren(originalChildren, bottomGroup);
+    }
+
+    /**
+     * Builds a transform group from the zeroth key of the 
+     * position and rotation tracks.
+     * @return transform group with position and rotation information
+     */
+    private TransformGroup buildKeysGroup()
+    {
+        Transform3D positionTransform   = new Transform3D();
+        positionTransform.set(new Vector3f(position));
+
+        Transform3D rotationTransform   = new Transform3D();
+        rotationTransform.set(rotation);
+
+        Transform3D scaleTransform = new Transform3D();
+        scaleTransform.setScale(new Vector3d(scale));
+        TransformGroup scaleGroup = new TransformGroup(scaleTransform);
+
+        Transform3D keyTransform = new Transform3D(positionTransform);
+        keyTransform.mul(scaleTransform);
+        keyTransform.mul(rotationTransform);
+        return new TransformGroup(keyTransform);
+    }
+
+    /**
+     * Builds a pivot group that will allow the objects
+     * to be positioned properly according to their rotations
+     * and positions.
+     * @param coordinateTransform the coordinate system defining the 
+     * location and orientation of the local axis. This is not modified.
+     * @param pivot the pivot defined in the 3ds file loaded by pivot chunk.
+     * This is not changed.
+     */
+    private TransformGroup buildPivotGroup(Transform3D coordinateTransform, Vector3f pivot)
+    {
+            Transform3D pivotTransform = new Transform3D();
+            pivotTransform.mulInverse(coordinateTransform);
+            pivot = new Vector3f(pivot);
+            pivot.negate();
+            translatePivot(pivotTransform, pivot, pivotCenter);
+            return new TransformGroup(pivotTransform);
+    }
+
+    /**
+     * Builds a coordinate group that will allow the objects
+     * to be positioned properly according to their rotations
+     * and positions.
+     * @param coordinateSystem the coordinate system defining the 
+     * location and orientation of the local axis. This is modified 
+     * so it will be useful during the construction
+     * of the animations.
+     */
+    private TransformGroup buildLocalCoordinates(Transform3D coordinateSystem)
+    {
+        Matrix4f coordMatrix = new Matrix4f();
+        Vector3f translation = new Vector3f();
+
+        coordinateSystem.get(translation);
+        coordinateSystem.invert();
+
+        coordinateSystem.get(coordMatrix);
+        coordMatrix.m03 = translation.x;
+        coordMatrix.m13 = translation.y;
+        coordMatrix.m23 = translation.z;
+        coordinateSystem.set(coordMatrix);
+        coordinateSystem.invert();
+        TransformGroup systemGroup = new TransformGroup(coordinateSystem);
+        coordinateSystem.invert();
+        return systemGroup;
+    }
+
+   /**
+     * Hierarchically adds the provided groups in order to parentGroup.
+     * groups[0] is added to parentGroup, groups[1] is added to groups[0] etc.
+     * @return the last group added (groups[groups.length - 1]).
+     */
+    private Group addGroups(Group parentGroup, Group[] groups)
+    {
+        Group nextGroup = parentGroup;
+        for(int i=0; i < groups.length; i++)
+        {
+            nextGroup.addChild(groups[i]);
+            nextGroup = groups[i];
+        }
+        return groups[groups.length - 1];
+    }
+
+    /**
+     * Does a pre rotational translation of the pivot.
+     * @param transform the matrix that will have a translation concatenated to it.
+     * @param vector the vector which will be used to translate the matrix.
+     * @param offset the offset used to offset the pivot. 
+     */
+    private void translatePivot(Transform3D transform, Vector3f vector, Point3f offset)
+    {
+        if(offset != null)
+        {
+            pivot.sub(offset);
+        }
+        Matrix4f matrix = new Matrix4f();
+        transform.get(matrix);
+
+        matrix.m03 += (matrix.m00*vector.x + matrix.m01*vector.y + matrix.m02*vector.z);
+        matrix.m13 += (matrix.m10*vector.x + matrix.m11*vector.y + matrix.m12*vector.z);
+        matrix.m23 += (matrix.m20*vector.x + matrix.m21*vector.y + matrix.m22*vector.z);
+
+        transform.set(matrix);
+    }
+
+
+    /**
+     * Builds a rotation position interpolator for use on this mesh using position and rotation information
+     * adds it to targetGroup.
+     * This does not set the capability bits that need to be set for the animation  
+     * to be used. The capability bits of the targetGroup must be set by the client application.
+     * The alpha object on the Interpolator must also be enabled. 
+     * The Interpolator must also have its scheduling bounds set.
+     * @param pivotGroup transform group which will be operated on by the interpolator.
+     * @param interpolatorAxis the axis that about which rotations will be centered.
+     */
+    //TODO... This needs to use both a rotation interpolator and a position interpolator
+    //in case there are keys with no position information but position information and 
+    //vice versa right now its using RotPosPathInterpolator
+    private TransformInterpolator buildInterpolator(TransformGroup targetGroup, Transform3D axisOfTransform)
+    {
+        makeTwoListsTheSameSize(positionKeys, orientationKeys);
+        int numKeys = positionKeys.size();
+
+        Point3f currentPoint = position; 
+        Quat4f  currentQuat  = rotation; 
+        RotPosPathInterpolator rotator = null; 
+        if(numKeys > 1) 
+        {
+            float[]    knots = new float[numKeys];
+            Point3f[] points = new Point3f[numKeys];
+            Quat4f[]  quats  = new Quat4f[numKeys];
+
+            for(int i=0; i < numKeys; i++) 
+            {
+                //Knots need to be between 0(beginning) and 1(end)
+                knots[i]= (i==0?0:((float)i/((float)(numKeys-1))));
+                if(positionKeys.size() > i)
+                {
+                    Point3f newPoint = (Point3f)positionKeys.get(i);
+                    if(newPoint != null)
+                    {
+                        currentPoint = newPoint;
+                    }
+
+                    Quat4f newQuat = (Quat4f)orientationKeys.get(i);
+                    if(newQuat != null)
+                    {
+                        currentQuat = newQuat;
+                    }
+                }
+
+                points[i] = currentPoint;
+                quats[i] = currentQuat;
+                quats[i].inverse();
+            }
+
+            //This gives a continuous loop at a rate of 30 fps
+            Alpha alpha = new Alpha(-1, (long)(numKeys/.03));
+            alpha.setStartTime(System.currentTimeMillis());
+            alpha.setDuplicateOnCloneTree(true);
+
+            rotator = new RotPosPathInterpolator(alpha, targetGroup, 
+                    axisOfTransform, knots, 
+                    quats, points);
+        }
+        return rotator;
+    }
+
+    public void makeTwoListsTheSameSize(List list1, List list2)
+    {
+        growList(list2.size() - 1, list1);
+        growList(list1.size() - 1, list2);
+    }
+
+    /**
+     * Make sure the list is at least able to
+     * hold a value at index.
+     * @param index an int specifying the initial size
+     * @parame the list that may need to grow
+     */
+    public void growList(int index, List list)
+    {
+        int numNeeded = (index + 1) - list.size();
+        while(numNeeded-- > 0)
+        {
+            list.add(null);
+        }
+    }
+
+    /**
+     * Sets the center of the bounding box that the pivot
+     * should offset.
+     */
+    public void setPivotCenter(Point3f center)
+    {
+        this.pivotCenter = center;
+    }
+
+    /**
+     * Called to set the coordinate system transform for an object named
+     * objectName. 
+     * This is the first t
+     */
+    public void setCoordinateSystem(String objectName, Transform3D coordinateSystem)
+    {
+        namedObjectCoordinateSystems.put(objectName, coordinateSystem);
+    }
+
+    /**
+     * Sets the group that will be used to center rotations.
+     * This is applied to the mesh after all other transforms
+     * have been applied.
+     * @param group the group that will act as the rotation transform.
+     */
+    public void setRotation(Quat4f rotation)
+    {
+        this.rotation = rotation;
+    }
+
+    /**
+     * Sets the pivot that will be used to as a pivot for
+     * these transfomations.
+     * @param group the group that will act as the pivot. 
+     */
+    public void setPivot(Vector3f pivot)
+    {
+        this.pivot = pivot;
+    }
+
+    /**
+     * Sets the scale for x y and z axis for objects. 
+     * This is applied to the mesh before the rotation transform 
+     * has been applied.
+     * @param group the group that will act as the scale 
+     */
+    public void setScale(Vector3f scale)
+    {
+        this.scale = scale;
+    }
+
+    /**
+     * Sets the scale information necessary for animation.s
+     * @param scaleKeys a list of Vector3f, which may contain null elements,
+     * containing a position for some keys.
+     */
+    public void setScaleKeys(List scaleKeys)
+    {
+        this.scaleKeys = scaleKeys;
+    }
+
+    /**
+     * Sets the group that will be used to translate the mesh..
+     * This is applied to the mesh just before the rotation transform 
+     * has been applied.
+     * @param group the group that will act as the position transform.
+     */
+    public void setPosition(Point3f position)
+    {
+        this.position = position;
+    }
+
+    /**
+     * Sets the position information necessary for animation.s
+     * @param positions a list of Point3f, which may contain null elements,
+     * containing a position for some keys.
+     */
+    public void setPositionKeys(List positions)
+    {
+        positionKeys = positions;
+    }
+
+    /**
+     * Sets the orientation information necessary for animation.s
+     * @param positions a list of Quat4f, which may contain null elements,
+     * containing a orientation for some keys.
+     */
+    public void setOrientationKeys(List orientations)
+    {
+        orientationKeys = orientations;
+    }
+
+    /**
+     *
+     */
+    public void setDummyObject(Group object)
+    {
+        dummyObject = object;
+    }
+
+    /**
+     * returns true if position keys and orientation
+     * keys are longer than one element each.
+     */
+    public boolean hasKeys()
+    {
+        return (positionKeys.size() > 1 || orientationKeys.size() > 1);
+    }
+
+    /**
+     */
+    public void addFather(int fatherID, TransformGroup newFather)
+    {
+        if(fatherID < 0)
+        {
+            father = null;
+        }
+        else
+        {
+            father = (TransformGroup)(fatherMap.get(new Integer(fatherID)));
+            //Remove the father's father because the father will
+            //be inserted somewhere later.
+            Group grandFather = (Group)father.getParent();
+            if(grandFather != null)
+            {
+                grandFather.removeChild(father);
+            }
+        }
+        fatherMap.put(id, newFather);
+    }
+
+    /**
+     * Sets the id for these frames.
+     * @param id the id for these frames.
+     */
+    public void setID(int id)
+    {
+        this.id = new Integer(id);
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/DefaultTextureImageLoader.java src-gil/com/microcrowd/loader/java3d/max3ds/DefaultTextureImageLoader.java
--- src/com/microcrowd/loader/java3d/max3ds/DefaultTextureImageLoader.java	2005-10-02 05:40:51.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/DefaultTextureImageLoader.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,120 +1,103 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- *
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@realvue.com
- */
-package com.microcrowd.loader.java3d.max3ds;
-
-import java.awt.Image;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.net.URL;
-import javax.imageio.ImageIO;
-
-/**
- * General purpose implementation of TextureImageLoader.
- * Gets the base path from loader and prepends it to the
- * file name to load an image.
- */
-public class DefaultTextureImageLoader implements TextureImageLoader
-{
-    private final URL baseURL;
-	private final String basePath;
-
-    /**
-     * Constructs an image loader that will resolve image
-     * locations to the base path of the loader provided.
-     * @param url the url from which images should be loaded or null.
-     * @throws NullPointerException if url is null.
-     */
-    public DefaultTextureImageLoader(URL url)
-    {
-    	if(url == null)
-    		throw new NullPointerException("url must not be null");
-    	baseURL = url;
-    	basePath = null;
-    }
-    
-    /**
-     * Constructs an image loader that will resolve image
-     * locations to the base path of the loader provided.
-     * @param url the url from which images should be loaded or null.
-     * @throws NullPointerExceptoin if path is null;
-     */
-    public DefaultTextureImageLoader(String path)
-    {
-    	if(path == null)
-    		throw new NullPointerException("path must not be null");
-    	basePath = path;
-    	baseURL = null;
-    }
-
-
-    /**
-     * Gets the image to be loaded as a texture.
-     * @param imageName the name of the image to load.
-     * @return image to be used.
-     */
-    public Image getTextureImage(String imageName)
-    {
-        File file = null;
-        InputStream in = null;
-        if(baseURL != null)
-        {
-            try 
-            {
-                in = new URL(baseURL + imageName).openStream();
-                return ImageIO.read(in);
-            }
-            catch (FileNotFoundException e)
-            {
-                throw new IllegalArgumentException(" Can't load texture: " + imageName + 
-                        " Make sure it is located in the " +
-                        " same server and directory with the model file."+
-                        " the loader's base path is: " + baseURL);
-            }
-            catch (Exception e)
-            {
-                e.printStackTrace();
-                throw new IllegalArgumentException(" Can't load texture: " + imageName + 
-                        " Make sure it is located in the " +
-                        " same server and directory with the model file."+
-                        " the loader's base path is: " + baseURL);
-            }
-        }
-        else
-        {
-            try 
-            {
-                in = new FileInputStream(new File(basePath + imageName));
-                return ImageIO.read(in);
-            }
-            catch (Exception e)
-            {
-                e.printStackTrace();
-                throw new IllegalArgumentException(" Can't load texture: " + imageName + 
-                        " Make sure it is located in the " +
-                        " same server and directory with the model file."+
-                        " the loader's base path is: " + basePath);
-            }
-        }
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ *
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@realvue.com
+ */
+package com.microcrowd.loader.java3d.max3ds;
+
+import java.awt.Image;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.net.URL;
+import javax.imageio.ImageIO;
+
+/**
+ * General purpose implementation of TextureImageLoader.
+ * Gets the base path from loader and prepends it to the
+ * file name to load an image.
+ */
+public class DefaultTextureImageLoader implements TextureImageLoader
+{
+
+    private Loader3DS loader;
+
+    /**
+     * Constructs an image loader that will resolve image
+     * locations to the base path of the loader provided.
+     * @param the loader that will specify the base path
+     * used to retrieve images.
+     */
+    public DefaultTextureImageLoader(Loader3DS loader)
+    {
+        this.loader = loader;
+    }
+
+
+    /**
+     * Gets the image to be loaded as a texture.
+     * @param imageName the name of the image to load.
+     * @return image to be used.
+     */
+    public Image getTextureImage(String imageName)
+    {
+        File file = null;
+        InputStream in = null;
+        if(loader.fromUrl())
+        {
+            try 
+            {
+                in = new URL(loader.getBaseUrl() + imageName).openStream();
+                return ImageIO.read(in);
+            }
+            catch (FileNotFoundException e)
+            {
+                throw new IllegalArgumentException(" Can't load texture: " + imageName + 
+                        " Make sure it is located in the " +
+                        " same server and directory with the model file."+
+                        " the loader's base path is: " + loader.getBaseUrl());
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+                throw new IllegalArgumentException(" Can't load texture: " + imageName + 
+                        " Make sure it is located in the " +
+                        " same server and directory with the model file."+
+                        " the loader's base path is: " + loader.getBaseUrl());
+            }
+        }
+        else
+        {
+            try 
+            {
+                in = new FileInputStream(new File(loader.getBasePath() + imageName));
+                return ImageIO.read(in);
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+                throw new IllegalArgumentException(" Can't load texture: " + imageName + 
+                        " Make sure it is located in the " +
+                        " same server and directory with the model file."+
+                        " the loader's base path is: " + loader.getBasePath());
+            }
+        }
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/Loader3DS.java src-gil/com/microcrowd/loader/java3d/max3ds/Loader3DS.java
--- src/com/microcrowd/loader/java3d/max3ds/Loader3DS.java	2005-10-02 05:40:51.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/Loader3DS.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,371 +1,317 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds;
-
-import java.awt.Image;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
-
-import javax.media.j3d.BoundingSphere;
-import javax.media.j3d.Group;
-import javax.media.j3d.PointLight;
-import javax.media.j3d.Transform3D;
-import javax.media.j3d.TransformGroup;
-import javax.vecmath.Point3d;
-
-import com.sun.j3d.loaders.LoaderBase;
-import com.sun.j3d.loaders.Scene;
-
-/**
- * Used to load a 3ds studio max file. This will sequentially read a 3ds file,
- * load or skip chunks and subchunks and initialize the data for the chunks.
- * A {@link ChunkChopper} is a flyweight factory responsible for
- * chopping the data up and sending it to the  corresponding chunks(which are
- * flyweights ala the flyweight pattern) for processing.
- * This class is not thread safe as the base class is not either.
- * <p>
- * Features not supported; unknown chunks are skipped.
- * </p>
- */
-public class Loader3DS extends LoaderBase
-{
-    private Scene baseScene;
-
-    private TextureImageLoader textureImageLoader;
-    private boolean fromUrl;
-    private boolean haveSeenLights;
-    private boolean defaultLights;
-    
-	public Loader3DS()
-    {
-        //turnOnDebug();
-    }
-
-    /**
-     * Setting this will initialize a lot of debugging code that has lots of
-     * overhead.
-     */
-    private boolean debugMode;
-
-    /**
-     * This is not supported
-     *
-     * @param reader loads a model from a reader 
-     *
-     * @return nothing, this isn't implemented. 
-     *
-     * @throws FileNotFoundException 
-     * @throws UnsupportedOperationException 
-     */
-    public Scene load(Reader reader)
-    {
-        throw new UnsupportedOperationException("Not supported for 3DS");
-    }
-
-    /**
-     * Loads the model by parsing the file, modelPath and  creating a 3D Scene.
-     *
-     * @param modelPath the path of the 3ds file.
-     *
-     * @return a loaded scene 
-     *
-     * @throws FileNotFoundException if the file can't be located. 
-     */
-    public Scene load(String modelPath)
-    {
-        InputStream fileIn = null;
-        setBasePathFromFilename(modelPath);
-
-        try {
-            File modelFile = getFile(modelPath);
-            return parseChunks(modelFile);
-        } finally {
-            try {
-            	if(fileIn != null)
-                    fileIn.close();
-            } catch (Exception e) {
-                //Don't care about exceptions at this point.
-            }
-        }
-    }
-
-	private void setBaseUrlFromUrl(URL url) throws FileNotFoundException
-    {
-        String u = url.toString();
-        String s;
-        if (u.lastIndexOf('/') == -1) {
-            s = url.getProtocol() + ":";
-        } else {
-            s = u.substring(0, u.lastIndexOf('/') + 1);
-        }
-        try {
-            setBaseUrl(new URL(s));
-        }
-        catch (MalformedURLException e) {
-            throw new FileNotFoundException(e.getMessage());
-        }
-    }
-
-    /*
-     * Takes a file name and sets the base path to the directory
-     * containing that file.
-     */
-    private void setBasePathFromFilename(String fileName)
-    {
-        if (fileName.lastIndexOf(java.io.File.separator) == -1) {
-            // No path given - current directory
-            setBasePath("." + java.io.File.separator);
-        } else {
-            setBasePath(fileName.substring(0, fileName.lastIndexOf(java.io.File.separator)));
-        }
-    }
-
-    /**
-     * Set the path where files associated with this .obj file are
-     * located.
-     * Only needs to be called to set it to a different directory
-     * from that containing the .obj file.
-     */
-    public void setBasePath(String pathName)
-    {
-      String basePath = pathName;
-      if (basePath == null || basePath == "")
-	  basePath = "." + java.io.File.separator;
-      basePath = basePath.replace('/', java.io.File.separatorChar);
-      basePath = basePath.replace('\\', java.io.File.separatorChar);
-      if (!basePath.endsWith(java.io.File.separator))
-	  basePath = basePath + java.io.File.separator;
-      super.setBasePath(basePath);
-    }
-
-    /**
-     * Returns true if this loader is loading files
-     * from a url.
-     */
-    public boolean fromUrl()
-    {
-        return fromUrl;
-    }
-
-    /**
-     * gets an image with the specified name.
-     * This uses a DefaultTextureImageLoader
-     * to load the image if one hasn't been set for
-     * this loader.
-     * @param imageName name of image to load.
-     * @return image corresponding to imageName
-     */
-    public Image getTextureImage(String imageName)
-    {
-        try 
-        {
-            return textureImageLoader.getTextureImage(imageName);
-        } 
-        catch (IllegalArgumentException e)
-        {
-            System.out.println(e.getMessage());
-        }
-        catch (Exception e)
-        {
-            e.printStackTrace();
-        }
-        return null;
-    }
-
-    /**
-     * Sets the TextureImageLoader to be used
-     * when texture images are needed.
-     * @param loader the TextureImageLoader that will be used to load images.
-     */
-    public void setTextureImageLoader(TextureImageLoader loader)
-    {
-        textureImageLoader = loader;
-    }
-
-    /**
-     * Gets a chunk chopper to do all the dirty work.
-     *
-     * @param fileIn the stream containing the model.
-     * @param modelSize size of the model file. 
-     *
-     * @return a java3d scene built from input. 
-     */
-    private Scene parseChunks(File fileIn)
-    {
-        ChunkChopper chopper = new ChunkChopper(textureImageLoader == null ? 
- 		          new DefaultTextureImageLoader(getBasePath()) : textureImageLoader);
-        baseScene = chopper.loadSceneBase(fileIn);
-        checkLighting(chopper);
-        return baseScene;
-    }
-
-	private void checkLighting(ChunkChopper chopper) {
-		haveSeenLights = chopper.hasLights();
-        if(defaultLights)
-            defaultLights();
-	}
-	
-    /**
-     * Gets a chunk chopper to do all the dirty work.
-     *
-     * @param fileIn the stream containing the model.
-     * @param modelSize size of the model file. 
-     * @param loader the TextureImageLoader the chopper will use.
-     *
-     * @return a java3d scene built from input. 
-     */
-    private Scene parseChunks(InputStream stream, int modelSize)
-    {
-        ChunkChopper chopper = new ChunkChopper(textureImageLoader == null ? 
- 		          new DefaultTextureImageLoader(getBaseUrl()) : textureImageLoader);
-        baseScene = chopper.loadSceneBase(stream, modelSize);
-        checkLighting(chopper);
-        return baseScene;
-    }
-
-    /**
-     * Turns on default lights if no lights have been seen 
-     * in the scene yet. harrr!
-     */
-    private void defaultLights()
-    {
-        if(!haveSeenLights && baseScene != null)
-        {
-            addDefaultLights(baseScene.getSceneGroup());
-        }
-    }
-
-    /**
-     * Adds default lights to the scene. Safe to call at 
-     * any time.  If the scene loaded by this loader already
-     * contains lights this will have no effect.
-     */
-    public void addDefaultLights()
-    {
-        defaultLights=true;
-        defaultLights();
-    }
-
-    /**
-     * Adds defaultlights to the group provided 
-     * similar to the ones 3ds max adds when there are none in the scene.
-     * @param group to add the lighting to.
-     */
-    public static void addDefaultLights(Group group)
-    {
-        PointLight light1 = new PointLight();
-        PointLight light2 = new PointLight();
-        light1.setInfluencingBounds(new BoundingSphere(new Point3d(0,0,0), 3000));
-        light2.setInfluencingBounds(new BoundingSphere(new Point3d(0,0,0), 3000));
-
-        Transform3D t1 = new Transform3D(new float[]{1.0f, 0.0f, 0.0f, -900f, 
-            0.0f, 1.0f, 0.0f, 1500f, 
-            0.0f, 0.0f, 1.0f, 1000f, 
-            0.0f, 0.0f, 0.0f, 1.0f});
-        Transform3D t2 = new Transform3D(new float[]{1.0f, 0.0f, 0.0f, 900f, 
-            0.0f, 1.0f, 0.0f, -1500f, 
-            0.0f, 0.0f, 1.0f, -1000f, 
-            0.0f, 0.0f, 0.0f, 1.0f});
-        TransformGroup group1 = new TransformGroup(t1);
-        TransformGroup group2 = new TransformGroup(t2);
-        group1.addChild(light1);
-        group2.addChild(light2);
-        group.addChild(group1);
-        group.addChild(group2);
-    }
-
-    /**
-     * Retrieves a file with a given name. 
-     *
-     * @param fileName name of file to retrieve. 
-     *
-     * @return retrieved file. 
-     */
-    private File getFile(String fileName)
-    {
-        File file = null;
-        try {
-            file = new File(fileName);
-            if (!file.exists()) {
-                throw new IOException(fileName + " doesn't exist");
-            }
-        } catch (IOException ioe) {
-            ioe.printStackTrace();
-        }
-
-        return file;
-    }
-
-    /**
-     * throws UnsupportedOperationException
-     * @param url url of model to be loaded. 
-     * @return a java3d scene represented in url 
-     *
-     * @throws FileNotFoundException if file couldn't be found. 
-     */
-    public Scene load(URL url)
-    {
-        fromUrl = true;
-        InputStream stream = null;
-        try 
-        {
-            URLConnection connection = url.openConnection();
-            stream = connection.getInputStream();
-            if (baseUrl == null) 
-                setBaseUrlFromUrl(url);
-
-            return parseChunks(stream, connection.getContentLength());
-            		
-        } 
-        catch (Exception e)
-        {
-            e.printStackTrace();
-            throw new IllegalArgumentException("Url " + url + " cannot be loaded");
-        }
-        finally
-        {
-        	try
-        	{
-        		if(stream != null)
-        			stream.close();
-        	}
-        	catch(Exception e){}
-        }
-    }
-
-    /**
-     * Turn on debug mode for all 3ds xml.
-     */
-    public void turnOnDebug()
-    {
-        if (!debugMode) {
-            ChunkChopper.debug = true;
-            debugMode = true;
-        }
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds;
+
+import java.awt.Image;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import javax.media.j3d.BoundingSphere;
+import javax.media.j3d.Group;
+import javax.media.j3d.PointLight;
+import javax.media.j3d.Transform3D;
+import javax.media.j3d.TransformGroup;
+import javax.vecmath.Point3d;
+import com.sun.j3d.loaders.LoaderBase;
+import com.sun.j3d.loaders.Scene;
+import com.sun.j3d.loaders.SceneBase;
+
+/**
+ * Used to load a 3ds studio max file. This will sequentially read a 3ds file,
+ * load or skip chunks and subchunks and initialize the data for the chunks.
+ * A {@link ChunkChopper} is a singleton flyweight factory responsible for
+ * chopping the data up and sending it to the  corresponding chunks(which are
+ * flyweights ala the flyweight pattern) for processing.
+ * 
+ * <p>
+ * Features not supported; unknown chunks are skipped.
+ * </p>
+ */
+public class Loader3DS extends LoaderBase
+{
+    private boolean dataMapInitialized;
+
+    private TextureImageLoader textureImageLoader;
+    private boolean fromUrl;
+
+    public Loader3DS()
+    {
+        //turnOnDebug();
+    }
+
+    /**
+     * Setting this will initialize a lot of debugging code that has lots of
+     * overhead.
+     */
+    private boolean debugMode;
+
+    /**
+     * This is not supported
+     *
+     * @param reader loads a model from a reader 
+     *
+     * @return nothing, this isn't implemented. 
+     *
+     * @throws FileNotFoundException 
+     * @throws UnsupportedOperationException 
+     */
+    public Scene load(Reader reader) throws FileNotFoundException
+    {
+        throw new UnsupportedOperationException("Not supported for 3DS");
+    }
+
+    /**
+     * Loads the model by parsing the file, modelPath and  creating a 3D Scene.
+     *
+     * @param modelPath the path of the 3ds file.
+     *
+     * @return a loaded scene 
+     *
+     * @throws FileNotFoundException if the file can't be located. 
+     */
+    public Scene load(String modelPath) throws FileNotFoundException
+    {
+        InputStream fileIn = null;
+        setBasePathFromFilename(modelPath);
+
+        try {
+            File modelFile = getFile(modelPath);
+            fileIn = new FileInputStream(modelFile);
+            return parseChunks(fileIn, (int)modelFile.length());
+        } finally {
+            try {
+                fileIn.close();
+            } catch (Exception e) {
+                e.printStackTrace();
+                //Don't care about exceptions at this point.
+            }
+        }
+    }
+
+    private void setBaseUrlFromUrl(URL url) throws FileNotFoundException
+    {
+        String u = url.toString();
+        String s;
+        if (u.lastIndexOf('/') == -1) {
+            s = url.getProtocol() + ":";
+        } else {
+            s = u.substring(0, u.lastIndexOf('/') + 1);
+        }
+        try {
+            setBaseUrl(new URL(s));
+        }
+        catch (MalformedURLException e) {
+            throw new FileNotFoundException(e.getMessage());
+        }
+    }
+
+    /*
+     * Takes a file name and sets the base path to the directory
+     * containing that file.
+     */
+    private void setBasePathFromFilename(String fileName)
+    {
+        if (fileName.lastIndexOf(java.io.File.separator) == -1) {
+            // No path given - current directory
+            setBasePath("." + java.io.File.separator);
+        } else {
+            setBasePath(fileName.substring(0, fileName.lastIndexOf(java.io.File.separator)));
+        }
+    }
+
+    /**
+     * Set the path where files associated with this .obj file are
+     * located.
+     * Only needs to be called to set it to a different directory
+     * from that containing the .obj file.
+     */
+    public void setBasePath(String pathName)
+    {
+      String basePath = pathName;
+      if (basePath == null || basePath == "")
+	  basePath = "." + java.io.File.separator;
+      basePath = basePath.replace('/', java.io.File.separatorChar);
+      basePath = basePath.replace('\\', java.io.File.separatorChar);
+      if (!basePath.endsWith(java.io.File.separator))
+	  basePath = basePath + java.io.File.separator;
+      super.setBasePath(basePath);
+    }
+
+    /**
+     * Returns true if this loader is loading files
+     * from a url.
+     */
+    public boolean fromUrl()
+    {
+        return fromUrl;
+    }
+
+    /**
+     * gets an image with the specified name.
+     * This uses a DefaultTextureImageLoader
+     * to load the image if one hasn't been set for
+     * this loader.
+     * @param imageName name of image to load.
+     * @return image corresponding to imageName
+     */
+    public Image getTextureImage(String imageName)
+    {
+        try {
+            if(textureImageLoader == null)
+            {
+                textureImageLoader = new DefaultTextureImageLoader(this);
+            }
+            return textureImageLoader.getTextureImage(imageName);
+        } 
+        catch (IllegalArgumentException e)
+        {
+            System.out.println(e.getMessage());
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * Sets the TextureImageLoader to be used
+     * when texture images are needed.
+     * @param loader the TextureImageLoader that will be used to load images.
+     */
+    public void setTextureImageLoader(TextureImageLoader loader)
+    {
+        textureImageLoader = loader;
+    }
+
+    /**
+     * Gets a chunk chopper to do all the dirty work.
+     *
+     * @param inputStream the stream containing the model.
+     * @param modelSize size of the model file. 
+     *
+     * @return a java3d scene built from input. 
+     */
+    protected Scene parseChunks(InputStream inputStream, int modelSize)
+    {
+        ChunkChopper chopper = new ChunkChopper();
+        SceneBase base = chopper.loadSceneBase(inputStream, this, modelSize);
+        if(!chopper.hasLights())
+        {
+            addDefaultLights(base.getSceneGroup());
+            addDefaultLights(chopper.getGroup());
+        }
+        return base;
+    }
+
+    /**
+     * Adds defaultlights to the group provided 
+     * similar to the ones 3ds max adds when there are none in the scene.
+     * @param group to add the lighting to.
+     */
+    public static void addDefaultLights(Group group)
+    {
+        PointLight light1 = new PointLight();
+        PointLight light2 = new PointLight();
+        light1.setInfluencingBounds(new BoundingSphere(new Point3d(0,0,0), 3000));
+        light2.setInfluencingBounds(new BoundingSphere(new Point3d(0,0,0), 3000));
+
+        Transform3D t1 = new Transform3D(new float[]{1.0f, 0.0f, 0.0f, -900f, 
+            0.0f, 1.0f, 0.0f, 1500f, 
+            0.0f, 0.0f, 1.0f, 1000f, 
+            0.0f, 0.0f, 0.0f, 1.0f});
+        Transform3D t2 = new Transform3D(new float[]{1.0f, 0.0f, 0.0f, 900f, 
+            0.0f, 1.0f, 0.0f, -1500f, 
+            0.0f, 0.0f, 1.0f, -1000f, 
+            0.0f, 0.0f, 0.0f, 1.0f});
+        TransformGroup group1 = new TransformGroup(t1);
+        TransformGroup group2 = new TransformGroup(t2);
+        group1.addChild(light1);
+        group2.addChild(light2);
+        group.addChild(group1);
+        group.addChild(group2);
+    }
+
+    /**
+     * Retrieves a file with a given name. 
+     *
+     * @param fileName name of file to retrieve. 
+     *
+     * @return retrieved file. 
+     */
+    private File getFile(String fileName)
+    {
+        File file = null;
+        try {
+            file = new File(fileName);
+            if (!file.exists()) {
+                throw new IOException(fileName + " doesn't exist");
+            }
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+        }
+
+        return file;
+    }
+
+    /**
+     * throws UnsupportedOperationException
+     *
+     * @param url url of model to be loaded. 
+     *
+     * @return a java3d scene represented in url 
+     *
+     * @throws FileNotFoundException if file couldn't be found. 
+     */
+    public Scene load(URL url) throws FileNotFoundException
+    {
+        fromUrl = true;
+        try {
+            URLConnection connection = url.openConnection();
+            if (baseUrl == null) 
+                setBaseUrlFromUrl(url);
+
+            return parseChunks(connection.getInputStream(), connection.getContentLength());
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new IllegalArgumentException("Url " + url + " cannot be loaded");
+
+        }
+    }
+
+    /**
+     * Turn on debug mode for all 3ds xml.
+     */
+    public void turnOnDebug()
+    {
+        if (!debugMode) {
+            ChunkChopper.debug = true;
+            debugMode = true;
+        }
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/Main.java src-gil/com/microcrowd/loader/java3d/max3ds/Main.java
--- src/com/microcrowd/loader/java3d/max3ds/Main.java	2005-10-02 05:40:51.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/Main.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,126 +1,454 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds;
-
-import java.applet.Applet;
-import java.awt.BorderLayout;
-import java.net.URL;
-import java.net.URLDecoder;
-import java.net.MalformedURLException;
-
-import com.sun.j3d.utils.applet.MainFrame;
-
-
-/**
- * Provides an example of loader usage with key navigation.
- * If loaded as an applet expects a 'url' parameter tag which
- * must be specified as a fully qualified url.  If there isn't a 
- * url tag it looks for an applet parameter called filename.
- * If this is run from the command line it will try to load
- * the file passed in at the prompt, unless a command line argument
- * 'url' is the first argument.  Then it will load the url represented
- * as the second command argument.
- */
-public class Main extends Applet
-{
-    private String modelLocation;
-    public static String MODEL_PARAM = "modelName";
-
-    /**
-     * If loaded from the command line a modelFile must be provided.
-     * args are <filename> or url <url>
-     */
-    public static void main(String args[])
-    {
-        Main self = new Main();
-        if(args.length > 0)
-            self.modelLocation = args[0];
-
-        MainFrame mainFrame = new MainFrame(self, 750, 550);
-    }
-
-    /**
-     * Initializes applet. If this is loaded from a command
-     * line the model is loaded from the parameters provided.
-     * If it is loaded from an applet the parameter tag 'model'
-     * is checked for a path to a model. 
-     */
-    public void init()
-    {
-        URL url = getURL();
-        World world = null;
-        if(url != null)
-        {
-            world = new World(this, url);
-        }
-        else
-        {
-            world = new World(this, modelLocation);
-        }
-
-        setLayout(new BorderLayout());
-        add("Center", world);
-    }
-
-    /**
-     * Attempts to retrieve the url in the following ways.
-     * <ul>
-     *   <li>the url of the first argument.
-     *   <li>the url of the applet parameter MODEL_PARAM.
-     *   <li>the decoded relative url of the applet parameter MODEL_PARAM from the applet code base.
-     *   <li>The decoded relative url of the applet parameter from the applet code base.
-     * </ul>
-     * @return url or null.
-     */
-    private URL getURL()
-    {
-        try 
-        {
-            return new URL(modelLocation);
-        }
-        catch(MalformedURLException e){ }
-
-        String modelURL = getParameter(MODEL_PARAM);
-        if(modelURL != null)
-        {
-            String decodedURL = modelURL;
-            try {
-                decodedURL = URLDecoder.decode(modelURL, "UTF-8");
-            }
-            catch(Exception e){
-            }
-
-            try 
-            {
-                return new URL(decodedURL);
-            }
-            catch(MalformedURLException e){ }
-
-            try 
-            {
-                return new URL(getCodeBase(), decodedURL);
-            }
-            catch(Exception e){ }
-        }
-        return null;
-    }
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+
+package com.microcrowd.loader.java3d.max3ds;
+
+import java.applet.Applet;
+import java.awt.BorderLayout;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import javax.media.j3d.Behavior;
+import javax.media.j3d.BoundingSphere;
+import javax.media.j3d.BranchGroup;
+import javax.media.j3d.Canvas3D;
+import javax.media.j3d.GraphicsConfigTemplate3D;
+import javax.media.j3d.Interpolator;
+import javax.media.j3d.Locale;
+import javax.media.j3d.PhysicalBody;
+import javax.media.j3d.PhysicalEnvironment;
+import javax.media.j3d.RotPosPathInterpolator;
+import javax.media.j3d.Transform3D;
+import javax.media.j3d.TransformGroup;
+import javax.media.j3d.TransformInterpolator;
+import javax.media.j3d.View;
+import javax.media.j3d.ViewPlatform;
+import javax.media.j3d.VirtualUniverse;
+import javax.swing.JFileChooser;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.filechooser.FileFilter;
+import javax.vecmath.Point3d;
+import javax.vecmath.Point3f;
+import javax.vecmath.Quat4f;
+import com.sun.j3d.loaders.Scene;
+import com.sun.j3d.utils.applet.MainFrame;
+import com.sun.j3d.utils.behaviors.keyboard.KeyNavigatorBehavior;
+
+
+/**
+ * Provides an example of loader usage with key navigation.
+ * If loaded as an applet expects a 'url' parameter tag which
+ * must be specified as a fully qualified url.  If there isn't a 
+ * url tag it looks for an applet parameter called filename.
+ * If this is run from the command line it will try to load
+ * the file passed in at the prompt, unless a command line argument
+ * 'url' is the first argument.  Then it will load the url represented
+ * as the second command argument.
+ */
+public class Main extends Applet
+{
+    private BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0),3000.0);
+    private Canvas3D canvas;
+    private String modelLocation;
+    private static final String DEFAULT_MODEL = "bounce.3DS";
+    private BranchGroup universeBranch;
+
+    /**
+     * If loaded from the command line a modelFile must be provided.
+     * args are <filename> or url <url>
+     */
+    public static void main(String args[])
+    {
+        Main self = new Main();
+        if(args.length > 0)
+            self.modelLocation = args[0];
+
+        MainFrame mainFrame = new MainFrame(self, 750, 550);
+    }
+
+    /**
+     * Initializes applet. If this is loaded from a command
+     * line the model is loaded from the parameters provided.
+     * If it is loaded from an applet the parameter tag 'model'
+     * is checked for a path to a model. 
+     */
+    public void init()
+    {
+        try 
+        {
+            URL location = null;
+            if(modelLocation == null)
+            {
+                location = findAFile(DEFAULT_MODEL);
+            }
+            else
+            {
+                location = findAFile(modelLocation);
+            } 
+
+            if(location == null)
+                throw new IllegalArgumentException("No model was found when attempting to retrieve " +
+                        (modelLocation == null ? DEFAULT_MODEL : modelLocation));
+
+            GraphicsConfigTemplate3D config = new GraphicsConfigTemplate3D();
+            config.setSceneAntialiasing(GraphicsConfigTemplate3D.PREFERRED);
+            GraphicsDevice gd[] = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
+            canvas = new Canvas3D(gd[0].getBestConfiguration(config));
+
+            setLayout(new BorderLayout());
+            add("Center", canvas);
+
+            JMenuBar menuBar = new JMenuBar();
+            JMenu fileMenu = new JMenu("File");
+            JMenuItem menuItem = new JMenuItem("Open");
+            add(menuBar, "North");
+            menuBar.add(fileMenu);
+            fileMenu.add(menuItem);
+            menuItem.addActionListener(new BrowseListener());
+
+            View view = new View();
+
+            Scene scene = getScene(location);
+            universeBranch = createUniverse(view, scene);
+            view.addCanvas3D(canvas);
+
+            addSceneToBranch(universeBranch, scene);
+        }
+        catch(Exception e){
+            e.printStackTrace();
+            usage(e.getMessage());
+        }
+    }
+
+    /**
+     * Adds the scene to the branch and turns on the scene's 
+     * behaviors.
+     */
+    private void addSceneToBranch(BranchGroup branch, Scene scene)
+    {
+        turnOnBehaviors(scene.getBehaviorNodes());
+        BranchGroup modelGroup = scene.getSceneGroup();
+        modelGroup.compile();
+        branch.addChild(modelGroup);
+    }
+
+    /**
+     * This is called during initialization of the applet, 
+     */
+    public void Main()
+    {
+    }
+
+    /**
+     * load the scene.
+     */
+    public Scene getScene(URL location)
+    {
+        Scene scene = null;
+
+        try 
+        {
+            return new Loader3DS().load(location);
+        }
+        catch(IOException e){
+            e.printStackTrace();
+            usage(e.getMessage());
+        }
+        return null;
+    }
+
+
+    /**
+     * Turns on all the behaviors provided.
+     * @param bahaviors the behaviors to enable.
+     */
+    public void turnOnBehaviors(Behavior[] behaviors)
+    {
+        if(behaviors == null)
+            return;
+        for(int i=0; i < behaviors.length; i++)
+        {
+
+            behaviors[i].setEnable(true);
+            if(behaviors[i] instanceof Interpolator)
+            {
+                ((Interpolator)behaviors[i]).setSchedulingBounds(new BoundingSphere(new Point3d(), 3000));
+            }
+            if(behaviors[i] instanceof TransformInterpolator)
+            {
+                ((TransformInterpolator)behaviors[i]).getTarget().setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+            } 
+        }
+    }
+
+    /**
+     * Adds an interpolator that will be added to 
+     * the view transform so that it may be used to
+     * switched cameras later.
+     * @param target the target that the interpolator will operate on
+     */
+    private void addCameraInterpolator(TransformGroup target)
+    {
+        Interpolator cameraInterpolator = new RotPosPathInterpolator(
+                null, target, new Transform3D(), new float[]{0,1}, 
+                new Quat4f[]{new Quat4f(), new Quat4f()}, new Point3f[]{new Point3f(), new Point3f()});
+        cameraInterpolator.setSchedulingBounds(bounds);
+        target.addChild(cameraInterpolator);
+    }
+    /**
+     * Constructs a scene graph.
+     * <ol>
+     * <li>Creates a branch group
+     * <li>Adds the parent transform group to it.
+     * </ol>
+     */
+    public BranchGroup createSceneGraph() {
+        BranchGroup    root           = new BranchGroup();
+        TransformGroup parentGroup     = new TransformGroup();
+
+        parentGroup.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
+        parentGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+        parentGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+        parentGroup.setCapability(TransformGroup.ALLOW_CHILDREN_READ);
+        parentGroup.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
+        parentGroup.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
+
+        root.addChild(parentGroup);
+
+        return root;
+    } 
+
+    /**
+     * Creates a universe with a locale turns the scene graph.  
+     * Builds a scene branch group and adds it to the locale.  
+     * Builds a view platform that uses the provided view and adds
+     * that to the locale.
+     * @param view the view to use in the view platform
+     * @param scene the scene to grab a camera from as a default view
+     *
+     * @return the root group of the scene branch of the universe. This
+     * is what other groups for display are added to. 
+     */
+    public BranchGroup createUniverse(View view, Scene scene) 
+    {
+        VirtualUniverse universe         = new VirtualUniverse();
+        Locale locale           = new Locale(universe);
+        BranchGroup     sceneBranch = createSceneGraph();
+        BranchGroup viewBranchGroup  = new BranchGroup();
+        sceneBranch.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
+        viewBranchGroup.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
+        ViewPlatform    platform         = new ViewPlatform();
+
+        TransformGroup viewTransformGroup = new TransformGroup();
+        viewTransformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+        viewTransformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+        viewTransformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
+
+        TransformGroup[] viewGroups = scene.getViewGroups();
+        Transform3D viewTransform = new Transform3D();
+        if(viewGroups != null && viewGroups.length > 0)
+        {
+            viewGroups[0].getTransform(viewTransform);
+        }
+
+        addViewKeyBehavior(viewTransformGroup);
+        viewTransformGroup.setTransform(viewTransform);
+
+        addCameraInterpolator(viewTransformGroup);
+        viewTransformGroup.addChild(platform);
+        viewBranchGroup.addChild(viewTransformGroup);
+
+        platform.setViewAttachPolicy(View.RELATIVE_TO_FIELD_OF_VIEW);
+        platform.setActivationRadius(100);
+
+        configureView(platform, view);
+        sceneBranch.setCapability(BranchGroup.ALLOW_DETACH);
+
+        viewBranchGroup.compile();
+        sceneBranch.compile();
+        locale.addBranchGraph(viewBranchGroup);
+        locale.addBranchGraph(sceneBranch);
+        return sceneBranch;
+    }
+
+    /**
+     * Adds a behavior to the view that listens to the canvas.
+     * This allows 1st person navigation.
+     */
+    public void addViewKeyBehavior(TransformGroup viewTransformGroup)
+    {
+        KeyNavigatorBehavior keyBehavior = new KeyNavigatorBehavior(canvas, viewTransformGroup);
+        keyBehavior.setSchedulingBounds(bounds);
+        //keyBehavior.setMovementRate(100.0f);
+        viewTransformGroup.addChild(keyBehavior);
+    }
+
+    /**
+     * Creates a physical environment and physical body and
+     * adds it them the view which is configured to use
+     * a regular screen display for configuration. The view is
+     * attached to the platform.
+     * @param platform the platform which will have the view attached to it.
+     * @param view the view to which the body and environment will be added.
+     * canvas 3d added to it.
+     */
+    protected void configureView(ViewPlatform platform, View view)
+    {
+        PhysicalBody        body        = new PhysicalBody();
+        PhysicalEnvironment environment = new PhysicalEnvironment();
+
+        view.setPhysicalEnvironment(environment);
+        view.setPhysicalBody(body);
+        view.attachViewPlatform(platform);
+        view.setBackClipDistance(1000.0);
+        view.setFrontClipDistance(1.0);
+
+
+    }
+
+    public static void usage()
+    {
+        usage("");
+    }
+
+    public static void usage(String message)
+    {
+        System.out.println(message);
+        System.out.println("This is a sample program for the java3ds loader");
+        System.out.println("usage java -jar Loader3DS <model> where model is the 3ds file");
+        System.out.println("Textures for the file should be in the same directory as the model");
+        System.out.println("If this is being run as an applet a parameter named model (a relative url) may be provided");
+        System.exit(1);
+    }
+
+    /** 
+     * Looks for a file to load.  If one
+     * cannot be found looks for and loads 
+     * the default one.
+     * @param name, or path of the file to find
+     * looks for the following:
+     * <ol>
+     * <li>a file with the path of fileName
+     * <li>a resource in the classpath with fileName
+     * <li>a resource in the classpath corresponding to 
+     * the default file.
+     * <li>a url specified in the applet parameter &quot;model&quot;
+     * </ol>
+     *
+     **/
+    private URL findAFile(String fileName)
+    {
+        URL location = null;
+        if(fileName != null)
+        {
+            try 
+            {
+                File file = new File(fileName);
+                if (file.exists())
+                {
+                    return file.toURL();
+                }
+            }
+            catch(IOException e)
+            {
+                e.printStackTrace();
+                usage(e.getMessage());
+            }
+        }
+
+        if(fileName != null)
+        {
+            location = Main.class.getClassLoader().getResource(fileName);
+        }
+        if(location != null)
+        {
+            return location;
+        }
+
+        String relativeURL = getParameter("model");
+        if(relativeURL != null)
+        {
+            try 
+            {
+                URL codeBase = getCodeBase();
+                return new URL(codeBase.toString() + relativeURL);
+            }
+            catch(MalformedURLException e){
+                e.printStackTrace();
+                usage(e.getMessage());
+            }
+        }
+
+
+        return location;
+    }
+
+    private class BrowseListener implements ActionListener
+    {
+        public void actionPerformed(ActionEvent event)
+        {
+            File file = null;
+            try {
+                JFileChooser chooser = new JFileChooser();
+                Filter3DS filter = new Filter3DS();
+                chooser.setFileFilter(filter);
+                chooser.showDialog(Main.this, "wee");
+                file = chooser.getSelectedFile();
+                if(file == null)
+                    return;
+                Scene scene = getScene(file.toURL());
+                addSceneToBranch(universeBranch, scene);
+            }
+            catch(Exception e){
+                e.printStackTrace();
+                System.out.println("file not loadable " + file);
+            }
+        }
+    }
+
+    private class Filter3DS extends FileFilter
+    {
+        public String getDescription()
+        {
+            return "3DS Files";
+        }
+        public boolean accept(File file)
+        {
+            if (file.isDirectory())
+                return true;
+            String fileName = file.getName();
+            if(fileName.length() < 4)
+                return false;
+            
+            String extension = fileName.substring(fileName.length() - 3, fileName.length());
+            if(extension.equalsIgnoreCase("3ds"))
+                return true;
+            return false;
+        }
+    }
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/package.html src-gil/com/microcrowd/loader/java3d/max3ds/package.html
--- src/com/microcrowd/loader/java3d/max3ds/package.html	2005-07-25 19:27:15.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/package.html	2009-11-27 16:05:45.000000000 +0100
@@ -1,3 +1,3 @@
-<html><body>
-        Contains classes used to load 3d studio max files.
-</body></html>
+<html><body>
+        Contains classes used to load 3d studio max files.
+</body></html>
diff -Nru src/com/microcrowd/loader/java3d/max3ds/TextureImageLoader.java src-gil/com/microcrowd/loader/java3d/max3ds/TextureImageLoader.java
--- src/com/microcrowd/loader/java3d/max3ds/TextureImageLoader.java	2005-10-02 05:40:51.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/TextureImageLoader.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,42 +1,42 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-package com.microcrowd.loader.java3d.max3ds;
-
-import java.awt.Image;
-
-/**
- * Interface specifying a lookup for images to be loaded
- * in textures.  Implementations using this loader may need
- * to use different methods to resolve images.  In these
- * cases a class should be created that implements
- * this interface. For general purpose applications
- * DefaultTextureImageLoader should be used.
- */
-public interface TextureImageLoader
-{
-
-    /**
-     * Gets the image to be loaded as a texture.
-     * @param imageName the name of the image with which it will be
-     * looked up.
-     */
-    public Image getTextureImage(String imageaName);
-}
+/**
+ * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+package com.microcrowd.loader.java3d.max3ds;
+
+import java.awt.Image;
+
+/**
+ * Interface specifying a lookup for images to be loaded
+ * in textures.  Implementations using this loader may need
+ * to use different methods to resolve images.  In these
+ * cases a class should be created that implements
+ * this interface. For general purpose applications
+ * DefaultTextureImageLoader should be used.
+ */
+public interface TextureImageLoader
+{
+
+    /**
+     * Gets the image to be loaded as a texture.
+     * @param imageName the name of the image with which it will be
+     * looked up.
+     */
+    public Image getTextureImage(String imageaName) throws Exception;
+}
diff -Nru src/com/microcrowd/loader/java3d/max3ds/World.java src-gil/com/microcrowd/loader/java3d/max3ds/World.java
--- src/com/microcrowd/loader/java3d/max3ds/World.java	2005-10-02 05:40:51.000000000 +0200
+++ src-gil/com/microcrowd/loader/java3d/max3ds/World.java	1970-01-01 01:00:00.000000000 +0100
@@ -1,414 +0,0 @@
-/**
- * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
- * Microcrowd.com This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of the License,
- * or (at your option) any later version. This library is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU Lesser General Public License for more details. You should have
- * received a copy of the GNU Lesser General Public License along with this
- * library; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA Contact Josh DeFord
- * jdeford@microcrowd.com
- */
-
-package com.microcrowd.loader.java3d.max3ds;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.GraphicsDevice;
-import java.awt.GraphicsEnvironment;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.File;
-import java.net.URL;
-import java.net.URLEncoder;
-
-import javax.media.j3d.Behavior;
-import javax.media.j3d.BoundingSphere;
-import javax.media.j3d.BranchGroup;
-import javax.media.j3d.Canvas3D;
-import javax.media.j3d.GraphicsConfigTemplate3D;
-import javax.media.j3d.Interpolator;
-import javax.media.j3d.Locale;
-import javax.media.j3d.PhysicalBody;
-import javax.media.j3d.PhysicalEnvironment;
-import javax.media.j3d.RotPosPathInterpolator;
-import javax.media.j3d.Transform3D;
-import javax.media.j3d.TransformGroup;
-import javax.media.j3d.TransformInterpolator;
-import javax.media.j3d.View;
-import javax.media.j3d.ViewPlatform;
-import javax.media.j3d.VirtualUniverse;
-import javax.swing.JFileChooser;
-import javax.swing.JMenu;
-import javax.swing.JMenuBar;
-import javax.swing.JMenuItem;
-import javax.swing.JPanel;
-import javax.swing.filechooser.FileFilter;
-import javax.vecmath.Point3d;
-import javax.vecmath.Point3f;
-import javax.vecmath.Quat4f;
-
-import com.sun.j3d.loaders.Scene;
-import com.sun.j3d.utils.behaviors.keyboard.KeyNavigatorBehavior;
-
-/**
- **/
-public class World extends JPanel
-{
-    private BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0),3000.0);
-    private Canvas3D canvas;
-    private static final String DEFAULT_MODEL = "bounce.3DS";
-    private BranchGroup universeBranch;
-    private Component parent;
-	private BranchGroup viewBranchGroup  = new BranchGroup();
-	private TransformGroup viewTransformGroup = new TransformGroup();
-
-    
-//	private Scene scene;
-    
-
-    /**
-     * Constructs a world with a parent for the file dialog.
-     * @param parent the parent component used for dialog boxes.
-     * @param url the url of the model
-     */
-    public World(Component parent, URL url)
-    {
-        this(parent);
-        load(url);
-    }
-
-    /**
-     * Constructs a world that loads the default model.
-     * @param parent
-     */
-    public World(Component parent)
-    {
-        this(parent, (String)null);
-    }
-
-    /**
-     * Constructs a world from the provided filename which should be a 3DS file.
-     * Will look for the file in the classpath for the file first.
-     * @param parent the parent component used for dialog boxes.
-     * @param fileName the name of the file to load.
-     */
-    public World(Component parent, String fileName)
-    {
-        this.parent = parent;
-        try
-        {
-            URL url = null;
-            if (fileName == null)
-            {
-                url = getClass().getClassLoader().getResource(DEFAULT_MODEL);
-                if(url == null)
-                	url = new File(DEFAULT_MODEL).toURL();
-            }
-            else
-            {
-                url = getClass().getClassLoader().getResource(fileName);
-            }
-
-            if(url != null)
-                load(url);
-            else if(fileName != null)
-                load(fileName);
-            else
-                throw new IllegalArgumentException("No model was found when attempting to retrieve "
-                        + (fileName == null ? DEFAULT_MODEL : fileName));
-            	
-        }
-        catch (Exception e)
-        {
-            e.printStackTrace();
-            usage(e.getMessage());
-        }
-    }
-
-    private void load(String fileName)
-    {
-        loadScene(fileName, null);
-    }
-
-    private void load(URL url)
-    {
-        loadScene(null, url);
-    }
-
-    private void loadScene(String fileName, URL url)
-    {
-        GraphicsConfigTemplate3D config = new GraphicsConfigTemplate3D();
-        config.setSceneAntialiasing(GraphicsConfigTemplate3D.PREFERRED);
-        GraphicsDevice gd[] = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
-        canvas = new Canvas3D(gd[0].getBestConfiguration(config));
-
-        setLayout(new BorderLayout());
-        add("Center", canvas);
-
-        JMenuBar menuBar = new JMenuBar();
-        JMenu fileMenu = new JMenu("File");
-        JMenuItem menuItem = new JMenuItem("Open");
-        add(menuBar, "North");
-        menuBar.add(fileMenu);
-        fileMenu.add(menuItem);
-        menuItem.addActionListener(new BrowseListener());
-
-        View view = new View();
-
-        createUniverse(view);
-        view.addCanvas3D(canvas);
-
-        addSceneToUniverse(fileName, url);
-    }
-    
-    public Canvas3D getCanvas()
-    {
-        return canvas;
-    }
-    
-    
-    /**
-     * Adds the scene to the branch and turns on the scene's 
-     * behaviors.
-     */
-    private void addSceneToUniverse(final String path, final URL url)
-    {
-    	if(url == null && path == null)
-    		throw new NullPointerException("url and location can't both be null");
-    	Runnable worker = new Runnable()
-    	{
-    		public void run()
-    		{
-                Loader3DS loader = new Loader3DS();
-                loader.addDefaultLights();
-                Scene scene;
-    			if(url != null)
-    			{
-	                scene = loader.load(url);
-    			}
-    			else
-    			{
-	                scene = loader.load(path);
-    			}
-		        turnOnBehaviors(scene.getBehaviorNodes());
-		        BranchGroup modelGroup = scene.getSceneGroup();
-		        modelGroup.compile();
-
-		        addViews(scene);
-		        universeBranch.addChild(modelGroup);
-    		}
-    	};
-    	new Thread(worker).start();
-    }
-
-
-
-    /**
-     * Turns on all the behaviors provided.
-     * @param bahaviors the behaviors to enable.
-     */
-    public void turnOnBehaviors(Behavior[] behaviors)
-    {
-        if(behaviors == null)
-            return;
-        for(int i=0; i < behaviors.length; i++)
-        {
-
-            behaviors[i].setEnable(true);
-            if(behaviors[i] instanceof Interpolator)
-            {
-                ((Interpolator)behaviors[i]).setSchedulingBounds(new BoundingSphere(new Point3d(), 3000));
-            }
-            if(behaviors[i] instanceof TransformInterpolator)
-            {
-                ((TransformInterpolator)behaviors[i]).getTarget().setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
-            } 
-        }
-    }
-
-    /**
-     * Adds an interpolator that will be added to 
-     * the view transform so that it may be used to
-     * switched cameras later.
-     * @param target the target that the interpolator will operate on
-     */
-    private void addCameraInterpolator(TransformGroup target)
-    {
-        Interpolator cameraInterpolator = new RotPosPathInterpolator(
-                null, target, new Transform3D(), new float[]{0,1}, 
-                new Quat4f[]{new Quat4f(), new Quat4f()}, new Point3f[]{new Point3f(), new Point3f()});
-        cameraInterpolator.setSchedulingBounds(bounds);
-        target.addChild(cameraInterpolator);
-    }
-    /**
-     * Constructs a scene graph.
-     * <ol>
-     * <li>Creates a branch group
-     * <li>Adds the parent transform group to it.
-     * </ol>
-     */
-    public BranchGroup createSceneGraph() {
-        BranchGroup    root           = new BranchGroup();
-        TransformGroup parentGroup     = new TransformGroup();
-
-        parentGroup.setCapability(TransformGroup.ENABLE_PICK_REPORTING);
-        parentGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
-        parentGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
-        parentGroup.setCapability(TransformGroup.ALLOW_CHILDREN_READ);
-        parentGroup.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
-        parentGroup.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
-
-        root.addChild(parentGroup);
-
-        return root;
-    } 
-
-    /**
-     * Creates a universe with a locale turns the scene graph.  
-     * Builds a scene branch group and adds it to the locale.  
-     * Builds a view platform that uses the provided view and adds
-     * that to the locale.
-     * @param view the view to use in the view platform
-     * @param scene the scene to grab a camera from as a default view
-     */
-    public  void createUniverse(View view) 
-    {
-        VirtualUniverse universe         = new VirtualUniverse();
-        Locale locale           = new Locale(universe);
-        universeBranch = createSceneGraph();
-        universeBranch.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
-
-        viewTransformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
-        viewTransformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
-        viewTransformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
-        ViewPlatform viewPlatform = new ViewPlatform();
-
-        addCameraInterpolator(viewTransformGroup);
-        viewTransformGroup.addChild(viewPlatform);
-        
-        viewBranchGroup.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
-        viewBranchGroup.addChild(viewTransformGroup);
-
-        viewPlatform.setViewAttachPolicy(View.RELATIVE_TO_FIELD_OF_VIEW);
-        viewPlatform.setActivationRadius(100);
-
-        addViewKeyBehavior(viewTransformGroup);
-        configureView(viewPlatform, view);
-        universeBranch.setCapability(BranchGroup.ALLOW_DETACH);
-
-        viewBranchGroup.compile();
-        universeBranch.compile();
-        locale.addBranchGraph(viewBranchGroup);
-        locale.addBranchGraph(universeBranch);
-    }
-
-	private void addViews(Scene scene) {
-		TransformGroup[] viewGroups = scene.getViewGroups();
-        Transform3D viewTransform = new Transform3D();
-        if(viewGroups != null && viewGroups.length > 0)
-        {
-            viewGroups[0].getTransform(viewTransform);
-        }
-
-        viewTransformGroup.setTransform(viewTransform);
-	}
-
-    /**
-     * Adds a behavior to the view that listens to the canvas.
-     * This allows 1st person navigation.
-     */
-    public void addViewKeyBehavior(TransformGroup viewTransformGroup)
-    {
-        KeyNavigatorBehavior keyBehavior = new KeyNavigatorBehavior(canvas, viewTransformGroup);
-        keyBehavior.setSchedulingBounds(bounds);
-        //keyBehavior.setMovementRate(100.0f);
-        viewTransformGroup.addChild(keyBehavior);
-        //System.out.println(URLEncoder.encode("http://loader.microcrowd.com/ball.3DS"));
-        
-    }
-
-    /**
-     * Creates a physical environment and physical body and
-     * adds it them the view which is configured to use
-     * a regular screen display for configuration. The view is
-     * attached to the platform.
-     * @param platform the platform which will have the view attached to it.
-     * @param view the view to which the body and environment will be added.
-     * canvas 3d added to it.
-     */
-    protected void configureView(ViewPlatform platform, View view)
-    {
-        PhysicalBody        body        = new PhysicalBody();
-        PhysicalEnvironment environment = new PhysicalEnvironment();
-
-        view.setPhysicalEnvironment(environment);
-        view.setPhysicalBody(body);
-        view.attachViewPlatform(platform);
-        view.setBackClipDistance(1000.0);
-        view.setFrontClipDistance(1.0);
-
-
-    }
-
-    public static void usage()
-    {
-        usage("");
-    }
-
-    public static void usage(String message)
-    {
-        System.out.println(message);
-        System.out.println("This is a sample program for the java3ds loader");
-        System.out.println("usage java -jar Loader3DS <model> where model is the 3ds file");
-        System.out.println("Textures for the file should be in the same directory as the model");
-        System.out.println("If this is being run as an applet a parameter named model (a relative url) may be provided");
-        System.exit(1);
-    }
-
-    private class BrowseListener implements ActionListener
-    {
-		public void actionPerformed(ActionEvent event)
-        {
-            File file = null;
-            try {
-                JFileChooser chooser = new JFileChooser();
-                Filter3DS filter = new Filter3DS();
-                chooser.setFileFilter(filter);
-                chooser.showDialog(parent, "wee");
-                file = chooser.getSelectedFile();
-                if(file == null)
-                    return;
-                addSceneToUniverse(file.getAbsolutePath(), null);
-            }
-            catch(Exception e){
-                e.printStackTrace();
-                System.err.println("file not loadable " + file);
-            }
-        }
-    }
-
-    private class Filter3DS extends FileFilter
-    {
-        public String getDescription()
-        {
-            return "3DS Files";
-        }
-        public boolean accept(File file)
-        {
-            if (file.isDirectory())
-                return true;
-            String fileName = file.getName();
-            if(fileName.length() < 4)
-                return false;
-            
-            String extension = fileName.substring(fileName.length() - 3, fileName.length());
-            if(extension.equalsIgnoreCase("3ds"))
-                return true;
-            return false;
-        }
-    }    
-}
diff -Nru src/com/realvue/sim/ui/loader/java3d/max3ds/Loader3DS.java src-gil/com/realvue/sim/ui/loader/java3d/max3ds/Loader3DS.java
--- src/com/realvue/sim/ui/loader/java3d/max3ds/Loader3DS.java	2005-07-25 19:28:20.000000000 +0200
+++ src-gil/com/realvue/sim/ui/loader/java3d/max3ds/Loader3DS.java	2009-11-27 16:05:45.000000000 +0100
@@ -1,34 +1,34 @@
-/*
- * Microcrowd.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * Contact Josh DeFord jdeford@microcrowd.com
- */
-package com.realvue.sim.ui.loader.java3d.max3ds;
-
-
-/**
- * @author jdeford
- *
- * Fonzie makes the windmill go round.
- */
-public class Loader3DS
-{
-    static
-    {
-        System.err.println("com.realvue.sim.ui.loader.java3d.max3ds.Loader has been replaced by com.microcrowd.loader.java3d.max3ds.Loader3DS. Just change the package and it will work.");
-    }
-}
+/*
+ * Microcrowd.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ * Contact Josh DeFord jdeford@microcrowd.com
+ */
+package com.realvue.sim.ui.loader.java3d.max3ds;
+
+
+/**
+ * @author jdeford
+ *
+ * Fonzie makes the windmill go round.
+ */
+public class Loader3DS
+{
+    static
+    {
+        System.err.println("com.realvue.sim.ui.loader.java3d.max3ds.Loader has been replaced by com.microcrowd.loader.java3d.max3ds.Loader3DS. Just change the package and it will work.");
+    }
+}