Browse Source

J3O incompatibility issues fixed
* When loading models with SimpleTextured/WireColor/SolidColor materials
* When loading Unshaded material with spelling error "SeperateTexCoord" instead of "SeparateTexCoord"
* Also fixed issue with loading animated models

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7729 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

sha..rd 14 years ago
parent
commit
951d9fe23a

+ 44 - 0
engine/build.xml

@@ -5,6 +5,50 @@
     <import file="nbproject/build-impl.xml"/>
     <!-- <import file="nbproject/profiler-build-impl.xml"/> -->
 
+    <target depends="init" if="have.sources" name="-javadoc-build">
+        <mkdir dir="${dist.javadoc.dir}"/>
+        <javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
+            <classpath>
+                <path path="${javac.classpath}"/>
+            </classpath>
+            <fileset dir="${src.core.dir}" excludes="${excludes}" includes="${includes}">
+                <filename name="**/*.java"/>
+            </fileset>
+            <fileset dir="${src.terrain.dir}" excludes="${excludes}" includes="${includes}">
+                <filename name="**/doc-files/**"/>
+            </fileset>
+            <fileset dir="${src.networking.dir}" excludes="${excludes}" includes="${includes}">
+                <filename name="**/doc-files/**"/>
+            </fileset>
+            <fileset dir="${src.desktop-fx.dir}" excludes="${excludes}" includes="${includes}">
+                <filename name="**/doc-files/**"/>
+            </fileset>
+            <fileset dir="${src.jbullet.dir}" excludes="${excludes}" includes="${includes}">
+                <filename name="**/doc-files/**"/>
+            </fileset>
+            <fileset dir="${src.niftygui.dir}" excludes="${excludes}" includes="${includes}">
+                <filename name="**/doc-files/**"/>
+            </fileset>
+            <fileset dir="${src.tools.dir}" excludes="${excludes}" includes="${includes}">
+                <filename name="**/doc-files/**"/>
+            </fileset>
+            <fileset dir="${src.xml.dir}" excludes="${excludes}" includes="${includes}">
+                <filename name="**/doc-files/**"/>
+            </fileset>
+            <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+                <include name="**/*.java"/>
+            </fileset>
+        </javadoc>
+        <copy todir="${dist.javadoc.dir}">
+            <fileset dir="${src.core.dir}" excludes="${excludes}" includes="${includes}">
+                <filename name="**/doc-files/**"/>
+            </fileset>
+            <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+                <include name="**/doc-files/**"/>
+            </fileset>
+        </copy>
+    </target>
+
     <target name="-post-compile" depends="-compile-bullet, -compile-android">
     </target>
     

+ 114 - 114
engine/nbproject/project.properties

@@ -1,114 +1,114 @@
-annotation.processing.enabled=false
-annotation.processing.enabled.in.editor=false
-annotation.processing.run.all.processors=true
-ant.customtasks.libs=JWSAntTasks
-application.homepage=http://www.jmonkeyengine.com/
-application.title=jMonkeyEngine 3.0
-application.vendor=jMonkeyEngine
-build.classes.dir=${build.dir}/classes
-build.classes.excludes=**/*.java,**/*.form
-# This directory is removed when the project is cleaned:
-build.dir=build
-build.generated.dir=${build.dir}/generated
-build.generated.sources.dir=${build.dir}/generated-sources
-# Only compile against the classpath explicitly listed here:
-build.sysclasspath=ignore
-build.test.classes.dir=${build.dir}/test/classes
-build.test.results.dir=${build.dir}/test/results
-# Uncomment to specify the preferred debugger connection transport:
-#debug.transport=dt_socket
-debug.classpath=\
-    ${run.classpath}
-debug.test.classpath=\
-    ${run.test.classpath}
-# This directory is removed when the project is cleaned:
-dist.dir=dist
-dist.jar=${dist.dir}/jMonkeyEngine3.jar
-dist.javadoc.dir=${dist.dir}/javadoc
-endorsed.classpath=
-excludes=
-file.reference.src-test-data=src/test-data
-includes=**
-jar.archive.disabled=${jnlp.enabled}
-jar.compress=true
-jar.index=${jnlp.enabled}
-javac.classpath=\
-    ${libs.jogg.classpath}:\
-    ${libs.jbullet.classpath}:\
-    ${libs.bullet.classpath}:\
-    ${libs.lwjgl.classpath}:\
-    ${libs.jheora.classpath}:\
-    ${libs.niftygui1.3.classpath}:\
-    ${libs.jme3-test-data.classpath}:\
-    ${libs.noise.classpath}
-# Space-separated list of extra javac options
-javac.compilerargs=
-javac.deprecation=false
-javac.processorpath=\
-    ${javac.classpath}
-javac.source=1.5
-javac.target=1.5
-javac.test.classpath=\
-    ${javac.classpath}:\
-    ${build.classes.dir}:\
-    ${libs.junit_4.classpath}
-javadoc.additionalparam=
-javadoc.author=false
-javadoc.encoding=${source.encoding}
-javadoc.noindex=false
-javadoc.nonavbar=false
-javadoc.notree=false
-javadoc.private=false
-javadoc.splitindex=true
-javadoc.use=true
-javadoc.version=false
-javadoc.windowtitle=jMonkeyEngine3
-jaxbwiz.endorsed.dirs="${netbeans.home}/../ide12/modules/ext/jaxb/api"
-jnlp.applet.class=jme3test.awt.AppHarness
-jnlp.applet.height=300
-jnlp.applet.width=300
-jnlp.codebase.type=user
-jnlp.codebase.user=http://jmonkeyengine.com/javawebstart/
-jnlp.descriptor=application
-jnlp.enabled=false
-jnlp.icon=/Users/normenhansen/Pictures/jme/icons/jme-logo48.png
-jnlp.mixed.code=default
-jnlp.offline-allowed=true
-jnlp.signed=true
-jnlp.signing=generated
-jnlp.signing.alias=
-jnlp.signing.keystore=
-main.class=jme3test.TestChooser
-manifest.file=MANIFEST.MF
-meta.inf.dir=${src.dir}/META-INF
-mkdist.disabled=false
-platform.active=default_platform
-run.classpath=\
-    ${javac.classpath}:\
-    ${build.classes.dir}
-run.jvmargs=-Xms40m -Xmx40m -XX:MaxDirectMemorySize=256M
-run.test.classpath=\
-    ${javac.test.classpath}:\
-    ${build.test.classes.dir}
-source.encoding=UTF-8
-src.blender.dir=src/blender
-src.core-data.dir=src/core-data
-src.core-plugins.dir=src/core-plugins
-src.core.dir=src/core
-src.desktop-fx.dir=src/desktop-fx
-src.desktop.dir=src/desktop
-src.games.dir=src/games
-src.jbullet.dir=src/jbullet
-src.jheora.dir=src/jheora
-src.jogg.dir=src/jogg
-src.lwjgl-oal.dir=src/lwjgl-oal
-src.lwjgl-ogl.dir=src/lwjgl-ogl
-src.networking.dir=src\\networking
-src.niftygui.dir=src/niftygui
-src.ogre.dir=src/ogre
-src.pack.dir=src/pack
-src.terrain.dir=src/terrain
-src.test.dir=src/test
-src.tools.dir=src/tools
-src.xml.dir=src/xml
-test.test.dir=test
+annotation.processing.enabled=false
+annotation.processing.enabled.in.editor=false
+annotation.processing.run.all.processors=true
+ant.customtasks.libs=JWSAntTasks
+application.homepage=http://www.jmonkeyengine.com/
+application.title=jMonkeyEngine 3.0
+application.vendor=jMonkeyEngine
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+build.generated.sources.dir=${build.dir}/generated-sources
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+# Uncomment to specify the preferred debugger connection transport:
+#debug.transport=dt_socket
+debug.classpath=\
+    ${run.classpath}
+debug.test.classpath=\
+    ${run.test.classpath}
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.jar=${dist.dir}/jMonkeyEngine3.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+endorsed.classpath=
+excludes=
+file.reference.src-test-data=src/test-data
+includes=**
+jar.archive.disabled=${jnlp.enabled}
+jar.compress=true
+jar.index=${jnlp.enabled}
+javac.classpath=\
+    ${libs.jogg.classpath}:\
+    ${libs.jbullet.classpath}:\
+    ${libs.bullet.classpath}:\
+    ${libs.lwjgl.classpath}:\
+    ${libs.jheora.classpath}:\
+    ${libs.niftygui1.3.classpath}:\
+    ${libs.jme3-test-data.classpath}:\
+    ${libs.noise.classpath}
+# Space-separated list of extra javac options
+javac.compilerargs=
+javac.deprecation=false
+javac.processorpath=\
+    ${javac.classpath}
+javac.source=1.5
+javac.target=1.5
+javac.test.classpath=\
+    ${javac.classpath}:\
+    ${build.classes.dir}:\
+    ${libs.junit_4.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.encoding=${source.encoding}
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+javadoc.splitindex=true
+javadoc.use=true
+javadoc.version=false
+javadoc.windowtitle=jMonkeyEngine3
+jaxbwiz.endorsed.dirs="${netbeans.home}/../ide12/modules/ext/jaxb/api"
+jnlp.applet.class=jme3test.awt.AppHarness
+jnlp.applet.height=300
+jnlp.applet.width=300
+jnlp.codebase.type=user
+jnlp.codebase.user=http://jmonkeyengine.com/javawebstart/
+jnlp.descriptor=application
+jnlp.enabled=false
+jnlp.icon=/Users/normenhansen/Pictures/jme/icons/jme-logo48.png
+jnlp.mixed.code=default
+jnlp.offline-allowed=true
+jnlp.signed=true
+jnlp.signing=generated
+jnlp.signing.alias=
+jnlp.signing.keystore=
+main.class=jme3test.export.TestOgreConvert
+manifest.file=MANIFEST.MF
+meta.inf.dir=${src.dir}/META-INF
+mkdist.disabled=false
+platform.active=default_platform
+run.classpath=\
+    ${javac.classpath}:\
+    ${build.classes.dir}
+run.jvmargs=-Xms30m -Xmx30m -XX:MaxDirectMemorySize=256M 
+run.test.classpath=\
+    ${javac.test.classpath}:\
+    ${build.test.classes.dir}
+source.encoding=UTF-8
+src.blender.dir=src/blender
+src.core-data.dir=src/core-data
+src.core-plugins.dir=src/core-plugins
+src.core.dir=src/core
+src.desktop-fx.dir=src/desktop-fx
+src.desktop.dir=src/desktop
+src.games.dir=src/games
+src.jbullet.dir=src/jbullet
+src.jheora.dir=src/jheora
+src.jogg.dir=src/jogg
+src.lwjgl-oal.dir=src/lwjgl-oal
+src.lwjgl-ogl.dir=src/lwjgl-ogl
+src.networking.dir=src\\networking
+src.niftygui.dir=src/niftygui
+src.ogre.dir=src/ogre
+src.pack.dir=src/pack
+src.terrain.dir=src/terrain
+src.test.dir=src/test
+src.tools.dir=src/tools
+src.xml.dir=src/xml
+test.test.dir=test

+ 4 - 4
engine/src/core-data/Common/MatDefs/Light/Lighting.j3md

@@ -38,16 +38,16 @@ MaterialDef Phong Lighting {
         Boolean UseVertexColor
 
         // Ambient color
-        Color Ambient
+        Color Ambient : MaterialAmbient
 
         // Diffuse color
-        Color Diffuse : Color
+        Color Diffuse : MaterialDiffuse
 
         // Specular color
-        Color Specular
+        Color Specular : MaterialSpecular
 
         // Specular power/shininess
-        Float Shininess
+        Float Shininess : MaterialShininess
 
         // Diffuse map
         Texture2D DiffuseMap

+ 1 - 1
engine/src/core-data/Common/MatDefs/Misc/Unshaded.frag

@@ -14,7 +14,7 @@ uniform vec4 m_Color;
 
 #ifdef HAS_LIGHTMAP
     uniform sampler2D m_LightMap;
-    #ifdef SEPERATE_TEXCOORD
+    #ifdef SEPARATE_TEXCOORD
         varying vec2 texCoord2;
     #endif
 #endif

+ 6 - 0
engine/src/core/com/jme3/app/AppTask.java

@@ -60,6 +60,12 @@ public class AppTask<V> implements Future<V> {
     private final ReentrantLock stateLock = new ReentrantLock();
     private final Condition finishedCondition = stateLock.newCondition();
 
+    /**
+     * Create an <code>AppTask</code> that will execute the given 
+     * {@link Callable}.
+     * 
+     * @param callable The callable to be executed
+     */
     public AppTask(Callable<V> callable) {
         this.callable = callable;
     }

+ 109 - 16
engine/src/core/com/jme3/app/Application.java

@@ -37,7 +37,6 @@ import com.jme3.input.JoyInput;
 import com.jme3.input.KeyInput;
 import com.jme3.input.MouseInput;
 import com.jme3.input.TouchInput;
-import com.jme3.system.*;
 import com.jme3.math.Vector3f;
 import com.jme3.renderer.Camera;
 import com.jme3.renderer.Renderer;
@@ -47,6 +46,9 @@ import com.jme3.audio.Listener;
 import com.jme3.input.InputManager;
 import com.jme3.renderer.RenderManager;
 import com.jme3.renderer.ViewPort;
+import com.jme3.system.AppSettings;
+import com.jme3.system.JmeCanvasContext;
+import com.jme3.system.JmeContext;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.concurrent.Callable;
@@ -54,6 +56,10 @@ import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.Future;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import com.jme3.system.JmeContext.Type;
+import com.jme3.system.JmeSystem;
+import com.jme3.system.SystemListener;
+import com.jme3.system.Timer;
 
 /**
  * The <code>Application</code> class represents an instance of a
@@ -103,14 +109,36 @@ public class Application implements SystemListener {
     public Application(){
     }
 
+    /**
+     * Returns true if pause on lost focus is enabled, false otherwise.
+     * 
+     * @return true if pause on lost focus is enabled
+     * 
+     * @see #setPauseOnLostFocus(boolean) 
+     */
     public boolean isPauseOnLostFocus() {
         return pauseOnFocus;
     }
 
+    /**
+     * Enable or disable pause on lost focus.
+     * <p>
+     * By default, pause on lost focus is enabled.
+     * If enabled, the application will stop updating 
+     * when it loses focus or becomes inactive (e.g. alt-tab). 
+     * For online or real-time applications, this might not be preferable,
+     * so this feature should be set to disabled. For other applications,
+     * it is best to keep it on so that CPU usage is not used when
+     * not necessary. 
+     * 
+     * @param pauseOnLostFocus True to enable pause on lost focus, false
+     * otherwise.
+     */
     public void setPauseOnLostFocus(boolean pauseOnLostFocus) {
         this.pauseOnFocus = pauseOnLostFocus;
     }
 
+    @Deprecated
     public void setAssetManager(AssetManager assetManager){
         if (this.assetManager != null)
             throw new IllegalStateException("Can only set asset manager"
@@ -243,78 +271,80 @@ public class Application implements SystemListener {
     }
 
     /**
-     * @return The asset manager for this application.
+     * @return The {@link AssetManager asset manager} for this application.
      */
     public AssetManager getAssetManager(){
         return assetManager;
     }
 
     /**
-     * @return the input manager.
+     * @return the {@link InputManager input manager}.
      */
     public InputManager getInputManager(){
         return inputManager;
     }
 
     /**
-     * @return the app state manager
+     * @return the {@link AppStateManager app state manager}
      */
     public AppStateManager getStateManager() {
         return stateManager;
     }
 
     /**
-     * @return the render manager
+     * @return the {@link RenderManager render manager}
      */
     public RenderManager getRenderManager() {
         return renderManager;
     }
 
     /**
-     * @return The renderer for the application, or null if was not started yet.
+     * @return The {@link Renderer renderer} for the application
      */
     public Renderer getRenderer(){
         return renderer;
     }
 
     /**
-     * @return The audio renderer for the application, or null if was not started yet.
+     * @return The {@link AudioRenderer audio renderer} for the application
      */
     public AudioRenderer getAudioRenderer() {
         return audioRenderer;
     }
 
     /**
-     * @return The listener object for audio
+     * @return The {@link Listener listener} object for audio
      */
     public Listener getListener() {
         return listener;
     }
 
     /**
-     * @return The display context for the application, or null if was not
-     * started yet.
+     * @return The {@link JmeContext display context} for the application
      */
     public JmeContext getContext(){
         return context;
     }
 
     /**
-     * @return The camera for the application, or null if was not started yet.
+     * @return The {@link Camera camera} for the application
      */
     public Camera getCamera(){
         return cam;
     }
 
     /**
-     * Starts the application as a display.
+     * Starts the application in {@link Type#Display display} mode.
+     * 
+     * @see #start(com.jme3.system.JmeContext.Type) 
      */
     public void start(){
         start(JmeContext.Type.Display);
     }
 
     /**
-     * Starts the application. Creating a rendering context and executing
+     * Starts the application. 
+     * Creating a rendering context and executing
      * the main loop in a separate thread.
      */
     public void start(JmeContext.Type contextType){
@@ -333,6 +363,21 @@ public class Application implements SystemListener {
         context.create(false);
     }
 
+    /**
+     * Initializes the application's canvas for use.
+     * <p>
+     * After calling this method, cast the {@link #getContext() context} to 
+     * {@link JmeCanvasContext},
+     * then acquire the canvas with {@link JmeCanvasContext#getCanvas() }
+     * and attach it to an AWT/Swing Frame.
+     * The rendering thread will start when the canvas becomes visible on
+     * screen, however if you wish to start the context immediately you
+     * may call {@link #startCanvas() } to force the rendering thread
+     * to start. 
+     * 
+     * @see JmeCanvasContext
+     * @see Type#Canvas
+     */
     public void createCanvas(){
         if (context != null && context.isCreated()){
             logger.warning("createCanvas() called when application already created!");
@@ -348,30 +393,66 @@ public class Application implements SystemListener {
         context.setSystemListener(this);
     }
 
+    /**
+     * Starts the rendering thread after createCanvas() has been called.
+     * <p>
+     * Same as calling startCanvas(false)
+     * 
+     * @see #startCanvas(boolean) 
+     */
     public void startCanvas(){
         startCanvas(false);
     }
 
+    /**
+     * Starts the rendering thread after createCanvas() has been called.
+     * <p>
+     * Calling this method is optional, the canvas will start automatically
+     * when it becomes visible.
+     * 
+     * @param waitFor If true, the current thread will block until the 
+     * rendering thread is running
+     */
     public void startCanvas(boolean waitFor){
         context.create(waitFor);
     }
 
+    /**
+     * Internal use only. 
+     */
     public void reshape(int w, int h){
         renderManager.notifyReshape(w, h);
     }
 
+    /**
+     * Restarts the context, applying any changed settings.
+     * <p>
+     * Changes to the {@link AppSettings} of this Application are not 
+     * applied immediately; calling this method forces the context
+     * to restart, applying the new settings.
+     */
     public void restart(){
         context.setSettings(settings);
         context.restart();
     }
 
+    /**
+     * 
+     * Requests the context to close, shutting down the main loop
+     * and making necessary cleanup operations.
+     * 
+     * Same as calling stop(false)
+     * 
+     * @see #stop(boolean) 
+     */
     public void stop(){
         stop(false);
     }
 
     /**
-     * Requests the display to close, shutting down the main loop
-     * and making neccessary cleanup operations.
+     * Requests the context to close, shutting down the main loop
+     * and making necessary cleanup operations. 
+     * After the application has stopped, it cannot be used anymore.
      */
     public void stop(boolean waitFor){
         logger.log(Level.FINE, "Closing application: {0}", getClass().getName());
@@ -381,7 +462,7 @@ public class Application implements SystemListener {
     /**
      * Do not call manually.
      * Callback from ContextListener.
-     *
+     * <p>
      * Initializes the <code>Application</code>, by creating a display and
      * default camera. If display settings are not specified, a default
      * 640x480 display is created. Default values are used for the camera;
@@ -409,12 +490,18 @@ public class Application implements SystemListener {
         // user code here..
     }
 
+    /**
+     * Internal use only.
+     */
     public void handleError(String errMsg, Throwable t){
         logger.log(Level.SEVERE, errMsg, t);
         // user should add additional code to handle the error.
         stop(); // stop the application
     }
 
+    /**
+     * Internal use only.
+     */
     public void gainFocus(){
         if (pauseOnFocus){
             paused = false;
@@ -424,6 +511,9 @@ public class Application implements SystemListener {
         }
     }
 
+    /**
+     * Internal use only.
+     */
     public void loseFocus(){
         if (pauseOnFocus){
             paused = true;
@@ -431,6 +521,9 @@ public class Application implements SystemListener {
         }
     }
 
+    /**
+     * Internal use only.
+     */
     public void requestClose(boolean esc){
         context.destroy(false);
     }

+ 39 - 4
engine/src/core/com/jme3/material/Material.java

@@ -56,7 +56,6 @@ import com.jme3.renderer.Renderer;
 import com.jme3.renderer.queue.RenderQueue.Bucket;
 import com.jme3.renderer.queue.RenderQueue.ShadowMode;
 import com.jme3.scene.Geometry;
-import com.jme3.scene.Spatial;
 import com.jme3.shader.Shader;
 import com.jme3.shader.Uniform;
 import com.jme3.shader.VarType;
@@ -1009,13 +1008,42 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
 
     public void read(JmeImporter im) throws IOException {
         InputCapsule ic = im.getCapsule(this);
-        String defName = ic.readString("material_def", null);
-        def = (MaterialDef) im.getAssetManager().loadAsset(new AssetKey(defName));
+        
         additionalState = (RenderState) ic.readSavable("render_state", null);
         transparent = ic.readBoolean("is_transparent", false);
 
+        // Load the material def
+        String defName = ic.readString("material_def", null);
         HashMap<String, MatParam> params = (HashMap<String, MatParam>) ic.readStringSavableMap("parameters", null);
-//        paramValues.putAll(params);
+        
+        boolean enableVcolor = false;
+        boolean separateTexCoord = false;
+        
+        if (im.getFormatVersion() == 0){
+            // Enable compatibility with old models
+            if (defName.equalsIgnoreCase("Common/MatDefs/Misc/VertexColor.j3md")){
+                // Using VertexColor, switch to Unshaded and set VertexColor=true
+                enableVcolor = true;
+                defName = "Common/MatDefs/Misc/Unshaded.j3md";
+            }else if (defName.equalsIgnoreCase("Common/MatDefs/Misc/SimpleTextured.j3md")
+                   || defName.equalsIgnoreCase("Common/MatDefs/Misc/SolidColor.j3md")){
+                // Using SimpleTextured/SolidColor, just switch to Unshaded
+                defName = "Common/MatDefs/Misc/Unshaded.j3md";
+            }else if (defName.equalsIgnoreCase("Common/MatDefs/Misc/WireColor.j3md")){
+                // Using WireColor, set wireframe renderstate = true and use Unshaded
+                additionalState.setWireframe(true);
+                defName = "Common/MatDefs/Misc/Unshaded.j3md";
+            }else if (defName.equalsIgnoreCase("Common/MatDefs/Misc/Unshaded.j3md")){
+                // Uses unshaded, ensure that the proper param is set
+                MatParam value = params.get("SeperateTexCoord");
+                if (value != null && ((Boolean)value.getValue()) == true){
+                    params.remove("SeperateTexCoord");
+                    separateTexCoord = true;
+                }
+            }
+        }
+        
+        def = (MaterialDef) im.getAssetManager().loadAsset(new AssetKey(defName));
         paramValues = new ListMap<String, MatParam>();
 
         // load the textures and update nextTexUnit
@@ -1037,5 +1065,12 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
             param.setName(checkSetParam(param.getVarType(), param.getName()));
             paramValues.put(param.getName(), param);
         }
+        
+        if (enableVcolor){
+            setBoolean("VertexColor", true);
+        }
+        if (separateTexCoord){
+            setBoolean("SeparateTexCoord", true);
+        } 
     }
 }

+ 6 - 1
engine/src/core/com/jme3/scene/Node.java

@@ -592,7 +592,10 @@ public class Node extends Spatial implements Savable {
 
     @Override
     public void read(JmeImporter e) throws IOException {
-        super.read(e);
+        // XXX: Load children before loading itself!!
+        // This prevents empty children list if controls query
+        // it in Control.setSpatial().
+        
         children = e.getCapsule(this).readSavableArrayList("children", null);
 
         // go through children and set parent to this node
@@ -602,6 +605,8 @@ public class Node extends Spatial implements Savable {
                 child.parent = this;
             }
         }
+        
+        super.read(e);
     }
 
     @Override

+ 194 - 0
engine/src/core/com/jme3/scene/shape/StripBox.java

@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2009-2010 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// $Id: Box.java 4131 2009-03-19 20:15:28Z blaine.dev $
+package com.jme3.scene.shape;
+
+import com.jme3.math.Vector3f;
+import com.jme3.scene.VertexBuffer.Type;
+import com.jme3.util.BufferUtils;
+import java.nio.FloatBuffer;
+
+/**
+ * A box with solid (filled) faces.
+ * 
+ * @author Mark Powell
+ * @version $Revision: 4131 $, $Date: 2009-03-19 16:15:28 -0400 (Thu, 19 Mar 2009) $
+ */
+public class StripBox extends AbstractBox {
+    
+    private static final short[] GEOMETRY_INDICES_DATA = 
+    { 1, 0, 4,
+      5, 
+      7, 
+      0, 
+      3, 
+      1, 
+      2, 
+      4, 
+      6, 
+      7, 
+      2, 
+      3 };
+    
+    private static final float[] GEOMETRY_TEXTURE_DATA = {
+        1, 0,
+        0, 0,
+        0, 1,
+        1, 1,
+        
+        1, 0,
+        0, 0,
+        1, 1,
+        0, 1
+    };
+    
+    /**
+     * Creates a new box.
+     * <p>
+     * The box has a center of 0,0,0 and extends in the out from the center by
+     * the given amount in <em>each</em> direction. So, for example, a box
+     * with extent of 0.5 would be the unit cube.
+     *
+     * @param name the name of the box.
+     * @param x the size of the box along the x axis, in both directions.
+     * @param y the size of the box along the y axis, in both directions.
+     * @param z the size of the box along the z axis, in both directions.
+     */
+    public StripBox(float x, float y, float z) {
+        super();
+        updateGeometry(Vector3f.ZERO, x, y, z);
+    }
+
+    /**
+     * Creates a new box.
+     * <p>
+     * The box has the given center and extends in the out from the center by
+     * the given amount in <em>each</em> direction. So, for example, a box
+     * with extent of 0.5 would be the unit cube.
+     * 
+     * @param name the name of the box.
+     * @param center the center of the box.
+     * @param x the size of the box along the x axis, in both directions.
+     * @param y the size of the box along the y axis, in both directions.
+     * @param z the size of the box along the z axis, in both directions.
+     */
+    public StripBox(Vector3f center, float x, float y, float z) {
+        super();
+        updateGeometry(center, x, y, z);
+    }
+
+    /**
+     * Constructor instantiates a new <code>Box</code> object.
+     * <p>
+     * The minimum and maximum point are provided, these two points define the
+     * shape and size of the box but not it’s orientation or position. You should
+     * use the {@link #setLocalTranslation()} and {@link #setLocalRotation()}
+     * methods to define those properties.
+     * 
+     * @param name the name of the box.
+     * @param min the minimum point that defines the box.
+     * @param max the maximum point that defines the box.
+     */
+    public StripBox(Vector3f min, Vector3f max) {
+        super();
+        updateGeometry(min, max);
+    }
+
+    /**
+     * Empty constructor for serialization only. Do not use.
+     */
+    public StripBox(){
+        super();
+    }
+
+    /**
+     * Creates a clone of this box.
+     * <p>
+     * The cloned box will have ‘_clone’ appended to it’s name, but all other
+     * properties will be the same as this box.
+     */
+    @Override
+    public StripBox clone() {
+        return new StripBox(center.clone(), xExtent, yExtent, zExtent);
+    }
+
+    protected void duUpdateGeometryIndices() {
+        if (getBuffer(Type.Index) == null){
+            setBuffer(Type.Index, 3, BufferUtils.createShortBuffer(GEOMETRY_INDICES_DATA));
+        }
+    }
+
+    protected void duUpdateGeometryNormals() {
+        if (getBuffer(Type.Normal) == null){
+            float[] normals = new float[8 * 3];
+            
+            Vector3f[] vert = computeVertices();
+            Vector3f norm = new Vector3f();
+            
+            for (int i = 0; i < 8; i++) {
+                norm.set(vert[i]).normalizeLocal();
+                
+                normals[i * 3 + 0] = norm.x;
+                normals[i * 3 + 1] = norm.x;
+                normals[i * 3 + 2] = norm.x;
+            }
+            
+            setBuffer(Type.Normal, 3, BufferUtils.createFloatBuffer(normals));
+        }
+    }
+
+    protected void duUpdateGeometryTextures() {
+        if (getBuffer(Type.TexCoord) == null){
+            setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(GEOMETRY_TEXTURE_DATA));
+        }
+    }
+
+    protected void duUpdateGeometryVertices() {
+        FloatBuffer fpb = BufferUtils.createVector3Buffer(8 * 3);
+        Vector3f[] v = computeVertices();
+        fpb.put(new float[] {
+                v[0].x, v[0].y, v[0].z, 
+                v[1].x, v[1].y, v[1].z, 
+                v[2].x, v[2].y, v[2].z, 
+                v[3].x, v[3].y, v[3].z,
+                v[4].x, v[4].y, v[4].z, 
+                v[5].x, v[5].y, v[5].z, 
+                v[6].x, v[6].y, v[6].z, 
+                v[7].x, v[7].y, v[7].z, 
+        });
+        setBuffer(Type.Position, 3, fpb);
+        setMode(Mode.TriangleStrip);
+        updateBound();
+    }
+
+}

+ 57 - 23
engine/src/core/com/jme3/util/BufferUtils.java

@@ -56,16 +56,10 @@ import java.util.WeakHashMap;
  */
 public final class BufferUtils {
 
-    ////  -- TEMP DATA OBJECTS --  ////
-//    private static final Vector2f _tempVec2 = new Vector2f();
-//    private static final Vector3f _tempVec3 = new Vector3f();
-//    private static final ColorRGBA _tempColor = new ColorRGBA();
-    ////  -- TRACKER HASH --  ////
     private static final Map<Buffer, Object> trackingHash = Collections.synchronizedMap(new WeakHashMap<Buffer, Object>());
     private static final Object ref = new Object();
-    private static final boolean trackDirectMemory = false;
+    private static final boolean trackDirectMemory = true;
 
-    ////  -- GENERIC CLONE -- ////
     /**
      * Creates a clone of the given buffer. The clone's capacity is
      * equal to the given buffer's limit.
@@ -88,8 +82,58 @@ public final class BufferUtils {
             throw new UnsupportedOperationException();
         }
     }
+    
+    private static void onBufferAllocated(Buffer buffer){
+        /*
+        StackTraceElement[] stackTrace = new Throwable().getStackTrace();
+        int initialIndex = 0;
+        
+        for (int i = 0; i < stackTrace.length; i++){
+            if (!stackTrace[i].getClassName().equals(BufferUtils.class.getName())){
+                initialIndex = i;
+                break;
+            }
+        }
+        
+        int allocated = buffer.capacity();
+        int size = 0;
+    
+        if (buffer instanceof FloatBuffer){
+            size = 4;
+        }else if (buffer instanceof ShortBuffer){
+            size = 2;
+        }else if (buffer instanceof ByteBuffer){
+            size = 1;
+        }else if (buffer instanceof IntBuffer){
+            size = 4;
+        }else if (buffer instanceof DoubleBuffer){
+            size = 8;
+        }
+        
+        allocated *= size;
+        
+        for (int i = initialIndex; i < stackTrace.length; i++){
+            StackTraceElement element = stackTrace[i];
+            if (element.getClassName().startsWith("java")){
+                break;
+            }
+            
+            try {
+                Class clazz = Class.forName(element.getClassName());
+                if (i == initialIndex){
+                    System.out.println(clazz.getSimpleName()+"."+element.getMethodName()+"():" + element.getLineNumber() + " allocated " + allocated);
+                }else{
+                    System.out.println(" at " + clazz.getSimpleName()+"."+element.getMethodName()+"()");
+                }
+            } catch (ClassNotFoundException ex) {
+            }
+        }*/
+        
+        if (trackDirectMemory){
+            trackingHash.put(buffer, ref);
+        }
+    }
 
-    ////  -- VECTOR3F METHODS -- ////
     /**
      * Generate a new FloatBuffer using the given array of Vector3f objects.
      * The FloatBuffer will be 3 * data.length long and contain the vector data
@@ -658,9 +702,7 @@ public final class BufferUtils {
     public static DoubleBuffer createDoubleBuffer(int size) {
         DoubleBuffer buf = ByteBuffer.allocateDirect(8 * size).order(ByteOrder.nativeOrder()).asDoubleBuffer();
         buf.clear();
-        if (trackDirectMemory) {
-            trackingHash.put(buf, ref);
-        }
+        onBufferAllocated(buf);
         return buf;
     }
 
@@ -723,9 +765,7 @@ public final class BufferUtils {
     public static FloatBuffer createFloatBuffer(int size) {
         FloatBuffer buf = ByteBuffer.allocateDirect(4 * size).order(ByteOrder.nativeOrder()).asFloatBuffer();
         buf.clear();
-        if (trackDirectMemory) {
-            trackingHash.put(buf, ref);
-        }
+        onBufferAllocated(buf);
         return buf;
     }
 
@@ -787,9 +827,7 @@ public final class BufferUtils {
     public static IntBuffer createIntBuffer(int size) {
         IntBuffer buf = ByteBuffer.allocateDirect(4 * size).order(ByteOrder.nativeOrder()).asIntBuffer();
         buf.clear();
-        if (trackDirectMemory) {
-            trackingHash.put(buf, ref);
-        }
+        onBufferAllocated(buf);
         return buf;
     }
 
@@ -852,9 +890,7 @@ public final class BufferUtils {
     public static ByteBuffer createByteBuffer(int size) {
         ByteBuffer buf = ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder());
         buf.clear();
-        if (trackDirectMemory) {
-            trackingHash.put(buf, ref);
-        }
+        onBufferAllocated(buf);
         return buf;
     }
 
@@ -932,9 +968,7 @@ public final class BufferUtils {
     public static ShortBuffer createShortBuffer(int size) {
         ShortBuffer buf = ByteBuffer.allocateDirect(2 * size).order(ByteOrder.nativeOrder()).asShortBuffer();
         buf.clear();
-        if (trackDirectMemory) {
-            trackingHash.put(buf, ref);
-        }
+        onBufferAllocated(buf);
         return buf;
     }
 

+ 49 - 13
engine/src/test/jme3test/audio/TestDoppler.java

@@ -32,8 +32,15 @@
 
 package jme3test.audio;
 
+import com.jme3.asset.plugins.FileLocator;
 import com.jme3.audio.AudioNode;
+import com.jme3.audio.Environment;
+import com.jme3.audio.LowPassFilter;
+import com.jme3.math.FastMath;
+import com.jme3.math.Quaternion;
 import com.jme3.math.Vector3f;
+import org.lwjgl.openal.AL10;
+import org.lwjgl.openal.AL11;
 
 /**
  * Test Doppler Effect
@@ -42,8 +49,15 @@ public class TestDoppler extends AudioApp {
 
     private AudioNode ufo;
 
-    private float location = 0;
-    private float rate = 1;
+    private float x = 20, z = 0;
+    
+    private float rate     = -0.05f;
+    private float xDist    = 20;
+    private float zDist    = 5;
+    
+    private float angle    = FastMath.TWO_PI;
+    
+    private LowPassFilter filter = new LowPassFilter(1, 1);
 
     public static void main(String[] args){
         TestDoppler test = new TestDoppler();
@@ -52,28 +66,50 @@ public class TestDoppler extends AudioApp {
 
     @Override
     public void initAudioApp(){
-        ufo  = new AudioNode(audioRenderer, assetManager, "Sound/Effects/Beep.ogg", false);
+        assetManager.registerLocator("C:\\", FileLocator.class);
+        
+        Quaternion q = new Quaternion();
+        q.lookAt(new Vector3f(0, 0, -1f), Vector3f.UNIT_Y);
+        listener.setRotation(q);
+        
+        audioRenderer.setEnvironment(Environment.Dungeon);
+        AL10.alDistanceModel(AL11.AL_EXPONENT_DISTANCE);
+        
+        ufo  = new AudioNode(audioRenderer, assetManager, "test.ogg", false);
         ufo.setPositional(true);
         ufo.setLooping(true);
+        ufo.setReverbEnabled(true);
+        ufo.setRefDistance(100000000);
+        ufo.setMaxDistance(100000000);
         audioRenderer.playSource(ufo);
     }
 
     @Override
     public void updateAudioApp(float tpf){
-        // move the location variable left and right
-        if (location > 10){
-            location = 10;
+        //float x  = (float) (Math.cos(angle) * xDist);
+        float dx = (float)  Math.sin(angle) * xDist; 
+        
+        //float z  = (float) (Math.sin(angle) * zDist);
+        float dz = (float)(-Math.cos(angle) * zDist);
+        
+        x += dx * tpf * 0.05f;
+        z += dz * tpf * 0.05f;
+        
+        angle += tpf * rate;
+        
+        if (angle > FastMath.TWO_PI){
+            angle = FastMath.TWO_PI;
             rate = -rate;
-            ufo.setVelocity(new Vector3f(rate*10, 0, 0));
-        }else if (location < -10){
-            location = -10;
+        }else if (angle < -0){
+            angle = -0;
             rate = -rate;
-            ufo.setVelocity(new Vector3f(rate*10, 0, 0));
-        }else{
-            location += rate * tpf * 10;
         }
-        ufo.setLocalTranslation(location, 0, 2);
+        
+        ufo.setVelocity(new Vector3f(dx, 0, dz));
+        ufo.setLocalTranslation(x, 0, z);
         ufo.updateGeometricState();
+        
+        System.out.println("LOC: " + (int)x +", " + (int)z + ", VEL: " + (int)dx + ", " + (int)dz);
     }
 
 }

+ 1 - 2
engine/src/test/jme3test/awt/TestCanvas.java

@@ -36,7 +36,6 @@ import com.jme3.app.Application;
 import com.jme3.app.SimpleApplication;
 import com.jme3.system.AppSettings;
 import com.jme3.system.JmeCanvasContext;
-import com.jme3.system.JmeSystem;
 import com.jme3.util.JmeFormatter;
 import java.awt.Canvas;
 import java.awt.event.ActionEvent;
@@ -60,7 +59,7 @@ public class TestCanvas {
     private static Canvas canvas;
     private static Application app;
     private static JFrame frame;
-    private static final String appClass = "jme3test.model.shape.TestBox";
+    private static final String appClass = "jme3test.post.TestMultiplesFilters";
 
     private static void createFrame(){
         frame = new JFrame("Test");

+ 0 - 1
engine/src/test/jme3test/export/TestOgreConvert.java

@@ -75,7 +75,6 @@ public class TestOgreConvert extends SimpleApplication {
             AnimControl control = ogreModelReloaded.getControl(AnimControl.class);
             AnimChannel chan = control.createChannel();
             chan.setAnim("Walk");
-//            fis.close();
 
             rootNode.attachChild(ogreModelReloaded);
         } catch (IOException ex){

+ 14 - 13
engine/src/test/jme3test/stress/TestLodStress.java

@@ -33,7 +33,6 @@
 package jme3test.stress;
 
 import com.jme3.app.SimpleApplication;
-import com.jme3.input.KeyInput;
 import com.jme3.light.DirectionalLight;
 import com.jme3.material.Material;
 import com.jme3.math.Quaternion;
@@ -41,32 +40,34 @@ import com.jme3.math.Vector3f;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Node;
 import com.jme3.scene.control.LodControl;
+import com.jme3.scene.shape.Sphere;
 
 public class TestLodStress extends SimpleApplication {
 
-    private boolean lod = false;
-
     public static void main(String[] args){
         TestLodStress app = new TestLodStress();
+        app.setShowSettings(false);
+        app.setPauseOnLostFocus(false);
         app.start();
     }
 
     public void simpleInitApp() {
-//        inputManager.registerKeyBinding("USELOD", KeyInput.KEY_L);
-
         DirectionalLight dl = new DirectionalLight();
         dl.setDirection(new Vector3f(-1,-1,-1).normalizeLocal());
         rootNode.addLight(dl);
 
-        Node teapotNode = (Node) assetManager.loadModel("Models/Teapot/Teapot.mesh.xml");
-        Geometry teapot = (Geometry) teapotNode.getChild(0);
+//        Node teapotNode = (Node) assetManager.loadModel("Models/Teapot/Teapot.mesh.xml");
+//        Geometry teapot = (Geometry) teapotNode.getChild(0);
+        
+        Sphere sph = new Sphere(16, 16, 4);
+        Geometry teapot = new Geometry("teapot", sph);
 
         Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
         mat.setFloat("Shininess", 16f);
-        mat.setBoolean("VertexLighting", true);
+//        mat.setBoolean("VertexLighting", true);
         teapot.setMaterial(mat);
-
-        // show normals as material
+        
+       // show normals as material
         //Material mat = new Material(assetManager, "Common/MatDefs/Misc/ShowNormals.j3md");
 
         for (int y = -10; y < 10; y++){
@@ -77,9 +78,9 @@ public class TestLodStress extends SimpleApplication {
                 clonePot.setLocalTranslation(x * .5f, 0, y * .5f);
                 clonePot.setLocalScale(.15f);
                 
-                LodControl control = new LodControl();
-                clonePot.addControl(control);
-                rootNode.attachChild(clonePot);
+//                LodControl control = new LodControl();
+//                clonePot.addControl(control);
+//                rootNode.attachChild(clonePot);
             }
         }
 

+ 77 - 2
engine/src/tools/jme3tools/converters/ImageToAwt.java

@@ -46,11 +46,12 @@ import java.awt.image.Raster;
 import java.awt.image.WritableRaster;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
-import java.util.HashMap;
+import java.util.EnumMap;
 
 public class ImageToAwt {
 
-    private static final HashMap<Format, DecodeParams> params = new HashMap<Format, DecodeParams>();
+    private static final EnumMap<Format, DecodeParams> params
+            = new EnumMap<Format, DecodeParams>(Format.class);
 
     private static class DecodeParams {
 
@@ -294,6 +295,80 @@ public class ImageToAwt {
         image.setData(BufferUtils.createByteBuffer(total));
     }
 
+    /**
+     * Convert the image from the given format to the output format.
+     * It is assumed that both images have buffers with the appropriate
+     * number of elements and that both have the same dimensions.
+     *
+     * @param input
+     * @param output
+     */
+    public static void convert(Image input, Image output){
+        DecodeParams inParams  = params.get(input.getFormat());
+        DecodeParams outParams = params.get(output.getFormat());
+
+        if (inParams == null || outParams == null)
+            throw new UnsupportedOperationException();
+
+        int width  = input.getWidth();
+        int height = input.getHeight();
+
+        if (width != output.getWidth() || height != output.getHeight())
+            throw new IllegalArgumentException();
+
+        ByteBuffer inData = input.getData(0);
+
+        boolean inAlpha = false;
+        boolean inLum = false;
+        boolean inRGB = false;
+        if (inParams.am != 0) {
+            inAlpha = true;
+        }
+
+        if (inParams.rm != 0 && inParams.gm == 0 && inParams.bm == 0) {
+            inLum = true;
+        } else if (inParams.rm != 0 && inParams.gm != 0 && inParams.bm != 0) {
+            inRGB = true;
+        }
+
+        int expansionA = 8 - Integer.bitCount(inParams.am);
+        int expansionR = 8 - Integer.bitCount(inParams.rm);
+        int expansionG = 8 - Integer.bitCount(inParams.gm);
+        int expansionB = 8 - Integer.bitCount(inParams.bm);
+
+        int inputPixel;
+        for (int y = 0; y < height; y++){
+            for (int x = 0; x < width; x++){
+                int i = Ix(x, y, width) * inParams.bpp;
+                inputPixel = (readPixel(inData, i, inParams.bpp) & inParams.im) >> inParams.is;
+                
+                int a = (inputPixel & inParams.am) >> inParams.as;
+                int r = (inputPixel & inParams.rm) >> inParams.rs;
+                int g = (inputPixel & inParams.gm) >> inParams.gs;
+                int b = (inputPixel & inParams.bm) >> inParams.bs;
+
+                r = r & 0xff;
+                g = g & 0xff;
+                b = b & 0xff;
+                a = a & 0xff;
+
+                a = a << expansionA;
+                r = r << expansionR;
+                g = g << expansionG;
+                b = b << expansionB;
+
+                if (inLum)
+                    b = g = r;
+
+                if (!inAlpha)
+                    a = 0xff;
+
+//                int argb = (a << 24) | (r << 16) | (g << 8) | b;
+//                out.setRGB(x, y, argb);
+            }
+        }
+    }
+
     public static BufferedImage convert(Image image, boolean do16bit, boolean fullalpha, int mipLevel){
         Format format = image.getFormat();
         DecodeParams p = params.get(image.getFormat());