Selaa lähdekoodia

Merge branch 'master' into PBRisComing

# Conflicts:
#	jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java
Nehon 9 vuotta sitten
vanhempi
commit
c7d264fe8e
100 muutettua tiedostoa jossa 1408 lisäystä ja 2475 poistoa
  1. 0 136
      jme3-android/src/main/java/com/jme3/asset/AndroidImageInfo.java
  2. 0 533
      jme3-android/src/main/java/com/jme3/audio/android/AndroidMediaPlayerAudioRenderer.java
  3. 5 0
      jme3-android/src/main/java/com/jme3/renderer/android/AndroidGL.java
  4. 0 591
      jme3-android/src/main/java/com/jme3/renderer/android/TextureUtil.java
  5. 0 23
      jme3-android/src/main/java/com/jme3/texture/plugins/AndroidImageLoader.java
  6. 1 1
      jme3-android/src/main/java/jme3test/android/SimpleTexturedTest.java
  7. 33 1
      jme3-bullet-native/build.gradle
  8. 0 44
      jme3-core/src/main/java/com/jme3/animation/BoneAnimation.java
  9. 0 42
      jme3-core/src/main/java/com/jme3/animation/SpatialAnimation.java
  10. 2 1
      jme3-core/src/main/java/com/jme3/app/SimpleApplication.java
  11. 0 36
      jme3-core/src/main/java/com/jme3/asset/TextureKey.java
  12. 104 0
      jme3-core/src/main/java/com/jme3/audio/AudioListenerState.java
  13. 38 6
      jme3-core/src/main/java/com/jme3/audio/AudioNode.java
  14. 3 3
      jme3-core/src/main/java/com/jme3/audio/Listener.java
  15. 5 4
      jme3-core/src/main/java/com/jme3/audio/openal/ALAudioRenderer.java
  16. 2 1
      jme3-core/src/main/java/com/jme3/cinematic/MotionPath.java
  17. 0 76
      jme3-core/src/main/java/com/jme3/effect/ParticleComparator.java
  18. 3 2
      jme3-core/src/main/java/com/jme3/effect/ParticleMesh.java
  19. 3 3
      jme3-core/src/main/java/com/jme3/export/SavableClassUtil.java
  20. 5 18
      jme3-core/src/main/java/com/jme3/material/Material.java
  21. 249 195
      jme3-core/src/main/java/com/jme3/material/RenderState.java
  22. 2 2
      jme3-core/src/main/java/com/jme3/material/Technique.java
  23. 2 3
      jme3-core/src/main/java/com/jme3/material/TechniqueDef.java
  24. 34 9
      jme3-core/src/main/java/com/jme3/material/logic/StaticPassLightingLogic.java
  25. 6 6
      jme3-core/src/main/java/com/jme3/renderer/Camera.java
  26. 8 25
      jme3-core/src/main/java/com/jme3/renderer/Limits.java
  27. 11 15
      jme3-core/src/main/java/com/jme3/renderer/RenderContext.java
  28. 31 27
      jme3-core/src/main/java/com/jme3/renderer/RenderManager.java
  29. 23 1
      jme3-core/src/main/java/com/jme3/renderer/Renderer.java
  30. 144 136
      jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java
  31. 5 0
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java
  32. 5 0
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java
  33. 68 11
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java
  34. 9 11
      jme3-core/src/main/java/com/jme3/scene/Mesh.java
  35. 1 2
      jme3-core/src/main/java/com/jme3/scene/VertexBuffer.java
  36. 0 8
      jme3-core/src/main/java/com/jme3/scene/debug/WireBox.java
  37. 1 6
      jme3-core/src/main/java/com/jme3/shadow/AbstractShadowRenderer.java
  38. 1 6
      jme3-core/src/main/java/com/jme3/shadow/PssmShadowRenderer.java
  39. 17 3
      jme3-core/src/main/java/com/jme3/system/NullRenderer.java
  40. 1 1
      jme3-core/src/main/java/com/jme3/texture/image/LastTextureState.java
  41. 1 1
      jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.j3md
  42. 2 2
      jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.j3md
  43. 1 2
      jme3-core/src/main/resources/com/jme3/asset/General.cfg
  44. 34 23
      jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java
  45. 1 2
      jme3-core/src/plugins/java/com/jme3/scene/plugins/MTLLoader.java
  46. 171 0
      jme3-core/src/test/java/com/jme3/material/MaterialTest.java
  47. 15 0
      jme3-core/src/test/java/com/jme3/material/plugins/J3MLoaderTest.java
  48. 6 0
      jme3-core/src/test/resources/no-default-technique.j3md
  49. 8 0
      jme3-core/src/test/resources/no-shader-specified.j3md
  50. 0 1
      jme3-core/src/tools/java/jme3tools/optimize/TextureAtlas.java
  51. 0 359
      jme3-desktop/src/main/java/com/jme3/system/Natives.java
  52. 2 1
      jme3-examples/src/main/java/jme3test/animation/TestCameraMotionPath.java
  53. 2 1
      jme3-examples/src/main/java/jme3test/animation/TestCinematic.java
  54. 2 1
      jme3-examples/src/main/java/jme3test/animation/TestMotionPath.java
  55. 1 1
      jme3-examples/src/main/java/jme3test/app/TestAppStateLifeCycle.java
  56. 1 1
      jme3-examples/src/main/java/jme3test/app/TestBareBonesApp.java
  57. 1 1
      jme3-examples/src/main/java/jme3test/app/TestReleaseDirectMemory.java
  58. 1 1
      jme3-examples/src/main/java/jme3test/audio/TestAmbient.java
  59. 37 47
      jme3-examples/src/main/java/jme3test/audio/TestDoppler.java
  60. 1 1
      jme3-examples/src/main/java/jme3test/awt/TestAwtPanels.java
  61. 1 1
      jme3-examples/src/main/java/jme3test/awt/TestSafeCanvas.java
  62. 2 2
      jme3-examples/src/main/java/jme3test/batching/TestBatchNode.java
  63. 1 1
      jme3-examples/src/main/java/jme3test/batching/TestBatchNodeCluster.java
  64. 1 1
      jme3-examples/src/main/java/jme3test/batching/TestBatchNodeTower.java
  65. 1 1
      jme3-examples/src/main/java/jme3test/bullet/TestAttachDriver.java
  66. 2 2
      jme3-examples/src/main/java/jme3test/bullet/TestBrickTower.java
  67. 2 2
      jme3-examples/src/main/java/jme3test/bullet/TestBrickWall.java
  68. 1 1
      jme3-examples/src/main/java/jme3test/bullet/TestCcd.java
  69. 1 1
      jme3-examples/src/main/java/jme3test/bullet/TestCollisionGroups.java
  70. 1 1
      jme3-examples/src/main/java/jme3test/bullet/TestGhostObject.java
  71. 1 1
      jme3-examples/src/main/java/jme3test/bullet/TestRagdollCharacter.java
  72. 1 1
      jme3-examples/src/main/java/jme3test/bullet/TestWalkingChar.java
  73. 4 2
      jme3-examples/src/main/java/jme3test/collision/TestMousePick.java
  74. 2 2
      jme3-examples/src/main/java/jme3test/effect/TestSoftParticles.java
  75. 9 4
      jme3-examples/src/main/java/jme3test/games/CubeField.java
  76. 1 1
      jme3-examples/src/main/java/jme3test/helloworld/HelloAssets.java
  77. 1 1
      jme3-examples/src/main/java/jme3test/helloworld/HelloInput.java
  78. 2 1
      jme3-examples/src/main/java/jme3test/light/TestDirectionalLightShadow.java
  79. 2 1
      jme3-examples/src/main/java/jme3test/light/TestPssmShadow.java
  80. 1 1
      jme3-examples/src/main/java/jme3test/light/TestShadow.java
  81. 1 1
      jme3-examples/src/main/java/jme3test/light/TestShadowsPerf.java
  82. 1 1
      jme3-examples/src/main/java/jme3test/light/TestSpotLight.java
  83. 1 1
      jme3-examples/src/main/java/jme3test/light/TestSpotLightShadows.java
  84. 2 1
      jme3-examples/src/main/java/jme3test/model/shape/TestBillboard.java
  85. 0 1
      jme3-examples/src/main/java/jme3test/model/shape/TestBox.java
  86. 1 1
      jme3-examples/src/main/java/jme3test/niftygui/TestNiftyGui.java
  87. 1 1
      jme3-examples/src/main/java/jme3test/niftygui/TestNiftyToMesh.java
  88. 2 1
      jme3-examples/src/main/java/jme3test/post/TestBloom.java
  89. 2 1
      jme3-examples/src/main/java/jme3test/post/TestCrossHatch.java
  90. 2 1
      jme3-examples/src/main/java/jme3test/post/TestPosterization.java
  91. 1 1
      jme3-examples/src/main/java/jme3test/post/TestRenderToMemory.java
  92. 2 2
      jme3-examples/src/main/java/jme3test/post/TestRenderToTexture.java
  93. 110 0
      jme3-examples/src/main/java/jme3test/renderer/TestBlendEquations.java
  94. 116 0
      jme3-examples/src/main/java/jme3test/texture/TestAnisotropicFilter.java
  95. 1 1
      jme3-examples/src/main/java/jme3test/water/TestPostWater.java
  96. 5 0
      jme3-ios/src/main/java/com/jme3/renderer/ios/IosGL.java
  97. 1 0
      jme3-ios/src/main/java/com/jme3/renderer/ios/JmeIosGLES.java
  98. 5 0
      jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java
  99. 4 0
      jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java
  100. 4 0
      jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java

+ 0 - 136
jme3-android/src/main/java/com/jme3/asset/AndroidImageInfo.java

@@ -1,136 +0,0 @@
-package com.jme3.asset;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
-import com.jme3.math.ColorRGBA;
-import com.jme3.texture.Image;
-import com.jme3.texture.Image.Format;
-import com.jme3.texture.image.ImageRaster;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
-  * <code>AndroidImageInfo</code> is set in a jME3 image via the {@link Image#setEfficentData(java.lang.Object) }
-  * method to retrieve a {@link Bitmap} when it is needed by the renderer. 
-  * User code may extend <code>AndroidImageInfo</code> and provide their own implementation of the 
-  * {@link AndroidImageInfo#loadBitmap()} method to acquire a bitmap by their own means.
-  *
-  * @author Kirill Vainer
-  */
-@Deprecated
-public class AndroidImageInfo extends ImageRaster {
-    
-    private static final Logger logger = Logger.getLogger(AndroidImageInfo.class.getName());
-    
-    protected AssetInfo assetInfo;
-    protected Bitmap bitmap;
-    protected Format format;
-
-    public AndroidImageInfo(AssetInfo assetInfo) {
-        this.assetInfo = assetInfo;
-    }
-    
-    public Bitmap getBitmap(){
-        if (bitmap == null || bitmap.isRecycled()){
-            try {
-                loadBitmap();
-            } catch (IOException ex) {
-                // If called first inside AssetManager, the error will propagate
-                // correctly. Assuming that if the first calls succeeds
-                // then subsequent calls will as well.
-                throw new AssetLoadException("Failed to load image " + assetInfo.getKey(), ex);
-            }
-        }
-        return bitmap;
-    }
-    
-    public void notifyBitmapUploaded() {
-        // Default function is to recycle the bitmap.
-        if (bitmap != null && !bitmap.isRecycled()) {
-            bitmap.recycle();
-            bitmap = null;
-            logger.log(Level.FINE, "Bitmap was deleted. ");
-        }
-    }
-    
-    public Format getFormat(){
-        return format;
-    }
-    
-    @Override
-    public int getWidth() {
-        return getBitmap().getWidth();
-    }
-
-    @Override
-    public int getHeight() {
-        return getBitmap().getHeight();
-    }
-    
-    @Override
-    public void setPixel(int x, int y, ColorRGBA color) {
-        getBitmap().setPixel(x, y, color.asIntARGB());
-    }
-
-    @Override
-    public ColorRGBA getPixel(int x, int y, ColorRGBA store) {
-        if (store == null) {
-            store = new ColorRGBA();
-        }
-        store.fromIntARGB(getBitmap().getPixel(x, y));
-        return store;
-    }
-    
-    /**
-     * Loads the bitmap directly from the asset info, possibly updating
-     * or creating the image object.
-     */
-    protected void loadBitmap() throws IOException{
-        InputStream in = null;
-        try {
-            in = assetInfo.openStream();
-            bitmap = BitmapFactory.decodeStream(in);
-            if (bitmap == null) {
-                throw new IOException("Failed to load image: " + assetInfo.getKey().getName());
-            }
-        } finally {
-            if (in != null) {
-                in.close();
-            }
-        }
-
-        switch (bitmap.getConfig()) {
-            case ALPHA_8:
-                format = Image.Format.Alpha8;
-                break;
-            case ARGB_8888:
-                format = Image.Format.RGBA8;
-                break;
-            case RGB_565:
-                format = Image.Format.RGB565;
-                break;
-            default:
-                // This should still work as long
-                // as renderer doesn't check format
-                // but just loads bitmap directly.
-                format = null;
-        }
-
-        TextureKey texKey = (TextureKey) assetInfo.getKey();
-        if (texKey.isFlipY()) {
-            // Flip the image, then delete the old one.
-            Matrix flipMat = new Matrix();
-            flipMat.preScale(1.0f, -1.0f);
-            Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), flipMat, false);
-            bitmap.recycle();
-            bitmap = newBitmap;
-
-            if (bitmap == null) {
-                throw new IOException("Failed to flip image: " + texKey);
-            }
-        }  
-    }
-}

+ 0 - 533
jme3-android/src/main/java/com/jme3/audio/android/AndroidMediaPlayerAudioRenderer.java

@@ -1,533 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.
- */
-package com.jme3.audio.android;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.res.AssetFileDescriptor;
-import android.content.res.AssetManager;
-import android.media.AudioManager;
-import android.media.MediaPlayer;
-import android.media.SoundPool;
-import com.jme3.asset.AssetKey;
-import com.jme3.audio.*;
-import com.jme3.audio.AudioSource.Status;
-import com.jme3.audio.openal.ALAudioRenderer;
-import com.jme3.math.FastMath;
-import com.jme3.math.Vector3f;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * This class is the android implementation for {@link AudioRenderer}
- *
- * @author larynx
- * @author plan_rich
- * 
- * @deprecated No longer supported due to too many limitations. 
- * Please use the generic {@link ALAudioRenderer} instead.
- */
-@Deprecated
-public class AndroidMediaPlayerAudioRenderer implements AudioRenderer,
-        SoundPool.OnLoadCompleteListener, MediaPlayer.OnCompletionListener {
-
-    private static final Logger logger = Logger.getLogger(AndroidMediaPlayerAudioRenderer.class.getName());
-    private final static int MAX_NUM_CHANNELS = 16;
-    private final HashMap<AudioSource, MediaPlayer> musicPlaying = new HashMap<AudioSource, MediaPlayer>();
-    private SoundPool soundPool = null;
-    private final Vector3f listenerPosition = new Vector3f();
-    // For temp use
-    private final Vector3f distanceVector = new Vector3f();
-    private final AssetManager assetManager;
-    private HashMap<Integer, AudioSource> soundpoolStillLoading = new HashMap<Integer, AudioSource>();
-    private Listener listener;
-    private boolean audioDisabled = false;
-    private final AudioManager manager;
-
-    public AndroidMediaPlayerAudioRenderer(Activity context) {
-        manager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-        context.setVolumeControlStream(AudioManager.STREAM_MUSIC);
-        assetManager = context.getAssets();
-    }
-
-    @Override
-    public void initialize() {
-        soundPool = new SoundPool(MAX_NUM_CHANNELS, AudioManager.STREAM_MUSIC,
-                0);
-        soundPool.setOnLoadCompleteListener(this);
-    }
-
-    @Override
-    public void updateSourceParam(AudioSource src, AudioParam param) {
-        if (audioDisabled) {
-            return;
-        }
-
-        if (src.getChannel() < 0) {
-            return;
-        }
-
-        switch (param) {
-            case Position:
-                if (!src.isPositional()) {
-                    return;
-                }
-
-                Vector3f pos = src.getPosition();
-                break;
-            case Velocity:
-                if (!src.isPositional()) {
-                    return;
-                }
-
-                Vector3f vel = src.getVelocity();
-                break;
-            case MaxDistance:
-                if (!src.isPositional()) {
-                    return;
-                }
-                break;
-            case RefDistance:
-                if (!src.isPositional()) {
-                    return;
-                }
-                break;
-            case ReverbFilter:
-                if (!src.isPositional() || !src.isReverbEnabled()) {
-                    return;
-                }
-                break;
-            case ReverbEnabled:
-                if (!src.isPositional()) {
-                    return;
-                }
-
-                if (src.isReverbEnabled()) {
-                    updateSourceParam(src, AudioParam.ReverbFilter);
-                }
-                break;
-            case IsPositional:
-                break;
-            case Direction:
-                if (!src.isDirectional()) {
-                    return;
-                }
-
-                Vector3f dir = src.getDirection();
-                break;
-            case InnerAngle:
-                if (!src.isDirectional()) {
-                    return;
-                }
-                break;
-            case OuterAngle:
-                if (!src.isDirectional()) {
-                    return;
-                }
-                break;
-            case IsDirectional:
-                if (src.isDirectional()) {
-                    updateSourceParam(src, AudioParam.Direction);
-                    updateSourceParam(src, AudioParam.InnerAngle);
-                    updateSourceParam(src, AudioParam.OuterAngle);
-                } else {
-                }
-                break;
-            case DryFilter:
-                if (src.getDryFilter() != null) {
-                    Filter f = src.getDryFilter();
-                    if (f.isUpdateNeeded()) {
-                        // updateFilter(f);
-                    }
-                }
-                break;
-            case Looping:
-                if (src.isLooping()) {
-                }
-                break;
-            case Volume:
-                MediaPlayer mp = musicPlaying.get(src);
-                if (mp != null) {
-                    mp.setVolume(src.getVolume(), src.getVolume());
-                } else {
-                    soundPool.setVolume(src.getChannel(), src.getVolume(),
-                            src.getVolume());
-                }
-
-                break;
-            case Pitch:
-
-                break;
-        }
-
-    }
-
-    @Override
-    public void updateListenerParam(Listener listener, ListenerParam param) {
-        if (audioDisabled) {
-            return;
-        }
-
-        switch (param) {
-            case Position:
-                listenerPosition.set(listener.getLocation());
-                break;
-            case Rotation:
-                Vector3f dir = listener.getDirection();
-                Vector3f up = listener.getUp();
-
-                break;
-            case Velocity:
-                Vector3f vel = listener.getVelocity();
-
-                break;
-            case Volume:
-                // alListenerf(AL_GAIN, listener.getVolume());
-                break;
-        }
-
-    }
-
-    @Override
-    public void update(float tpf) {
-        float distance;
-        float volume;
-
-        // Loop over all mediaplayers
-        for (AudioSource src : musicPlaying.keySet()) {
-
-            MediaPlayer mp = musicPlaying.get(src);
-
-            // Calc the distance to the listener
-            distanceVector.set(listenerPosition);
-            distanceVector.subtractLocal(src.getPosition());
-            distance = FastMath.abs(distanceVector.length());
-
-            if (distance < src.getRefDistance()) {
-                distance = src.getRefDistance();
-            }
-            if (distance > src.getMaxDistance()) {
-                distance = src.getMaxDistance();
-            }
-            volume = src.getRefDistance() / distance;
-
-            AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
-
-            if (FastMath.abs(audioData.getCurrentVolume() - volume) > FastMath.FLT_EPSILON) {
-                // Left / Right channel get the same volume by now, only
-                // positional
-                mp.setVolume(volume, volume);
-
-                audioData.setCurrentVolume(volume);
-            }
-
-        }
-    }
-
-    public void setListener(Listener listener) {
-        if (audioDisabled) {
-            return;
-        }
-
-        if (this.listener != null) {
-            // previous listener no longer associated with current
-            // renderer
-            this.listener.setRenderer(null);
-        }
-
-        this.listener = listener;
-        this.listener.setRenderer(this);
-
-    }
-
-    @Override
-    public void cleanup() {
-        // Cleanup sound pool
-        if (soundPool != null) {
-            soundPool.release();
-            soundPool = null;
-        }
-
-        // Cleanup media player
-        for (AudioSource src : musicPlaying.keySet()) {
-            MediaPlayer mp = musicPlaying.get(src);
-            {
-                mp.stop();
-                mp.release();
-                src.setStatus(Status.Stopped);
-            }
-        }
-        musicPlaying.clear();
-    }
-
-    @Override
-    public void onCompletion(MediaPlayer mp) {
-        if (mp.isPlaying()) {
-            mp.seekTo(0);
-            mp.stop();
-        }
-            // XXX: This has bad performance -> maybe change overall structure of
-            // mediaplayer in this audiorenderer?
-            for (AudioSource src : musicPlaying.keySet()) {
-                if (musicPlaying.get(src) == mp) {
-                    src.setStatus(Status.Stopped);
-                    break;
-                }
-            }
-
-    }
-
-    /**
-     * Plays using the {@link SoundPool} of Android. Due to hard limitation of
-     * the SoundPool: After playing more instances of the sound you only have
-     * the channel of the last played instance.
-     *
-     * It is not possible to get information about the state of the soundpool of
-     * a specific streamid, so removing is not possilbe -&gt; noone knows when
-     * sound finished.
-     */
-    public void playSourceInstance(AudioSource src) {
-        if (audioDisabled) {
-            return;
-        }
-
-        AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
-
-        if (!(audioData.getAssetKey() instanceof AudioKey)) {
-            throw new IllegalArgumentException("Asset is not a AudioKey");
-        }
-
-        AudioKey assetKey = (AudioKey) audioData.getAssetKey();
-
-        try {
-
-            if (audioData.getId() < 0) { // found something to load
-                int soundId = soundPool.load(
-                        assetManager.openFd(assetKey.getName()), 1);
-                audioData.setId(soundId);
-            }
-
-            int channel = soundPool.play(audioData.getId(), 1f, 1f, 1, 0, 1f);
-
-            if (channel == 0) {
-                soundpoolStillLoading.put(audioData.getId(), src);
-            } else {
-                if (src.getStatus() != Status.Stopped) {
-                    soundPool.stop(channel);
-                    src.setStatus(Status.Stopped);
-                }
-                src.setChannel(channel); // receive a channel at the last
-                setSourceParams(src);
-                // playing at least
-
-
-            }
-        } catch (IOException e) {
-            logger.log(Level.SEVERE,
-                    "Failed to load sound " + assetKey.getName(), e);
-            audioData.setId(-1);
-        }
-    }
-
-    @Override
-    public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
-        AudioSource src = soundpoolStillLoading.remove(sampleId);
-
-        if (src == null) {
-            logger.warning("Something went terribly wrong! onLoadComplete"
-                    + " had sampleId which was not in the HashMap of loading items");
-            return;
-        }
-
-        AudioData audioData = src.getAudioData();
-
-        // load was successfull
-        if (status == 0) {
-            int channelIndex;
-            channelIndex = soundPool.play(audioData.getId(), 1f, 1f, 1, 0, 1f);
-            src.setChannel(channelIndex);
-            setSourceParams(src);
-        }
-    }
-
-    public void playSource(AudioSource src) {
-        if (audioDisabled) {
-            return;
-        }
-
-        AndroidAudioData audioData = (AndroidAudioData) src.getAudioData();
-
-        MediaPlayer mp = musicPlaying.get(src);
-        if (mp == null) {
-            mp = new MediaPlayer();
-            mp.setOnCompletionListener(this);
-            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
-        }
-
-        try {
-            if (src.getStatus() == Status.Stopped) {
-                mp.reset();
-                AssetKey<?> key = audioData.getAssetKey();
-
-                AssetFileDescriptor afd = assetManager.openFd(key.getName()); // assetKey.getName()
-                mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(),
-                        afd.getLength());
-                mp.prepare();
-                setSourceParams(src, mp);
-                src.setChannel(0);
-                src.setStatus(Status.Playing);
-                musicPlaying.put(src, mp);
-                mp.start();
-            } else {
-                mp.start();
-            }
-        } catch (IllegalStateException e) {
-            e.printStackTrace();
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-
-    private void setSourceParams(AudioSource src, MediaPlayer mp) {
-        mp.setLooping(src.isLooping());
-        mp.setVolume(src.getVolume(), src.getVolume());
-        //src.getDryFilter();
-    }
-
-    private void setSourceParams(AudioSource src) {
-        soundPool.setLoop(src.getChannel(), src.isLooping() ? -1 : 0);
-        soundPool.setVolume(src.getChannel(), src.getVolume(), src.getVolume());
-    }
-
-    /**
-     * Pause the current playing sounds. Both from the {@link SoundPool} and the
-     * active {@link MediaPlayer}s
-     */
-    public void pauseAll() {
-        if (soundPool != null) {
-            soundPool.autoPause();
-            for (MediaPlayer mp : musicPlaying.values()) {
-                if(mp.isPlaying()){
-                    mp.pause();
-                }
-            }
-        }
-    }
-
-    /**
-     * Resume all paused sounds.
-     */
-    public void resumeAll() {
-        if (soundPool != null) {
-            soundPool.autoResume();
-            for (MediaPlayer mp : musicPlaying.values()) {
-                mp.start(); //no resume -> api says call start to resume
-            }
-        }
-    }
-
-    public void pauseSource(AudioSource src) {
-        if (audioDisabled) {
-            return;
-        }
-
-        MediaPlayer mp = musicPlaying.get(src);
-        if (mp != null) {
-            mp.pause();
-            src.setStatus(Status.Paused);
-        } else {
-            int channel = src.getChannel();
-            if (channel != -1) {
-                soundPool.pause(channel); // is not very likley to make
-            }											// something useful :)
-        }
-    }
-
-    public void stopSource(AudioSource src) {
-        if (audioDisabled) {
-            return;
-        }
-
-        // can be stream or buffer -> so try to get mediaplayer
-        // if there is non try to stop soundpool
-        MediaPlayer mp = musicPlaying.get(src);
-        if (mp != null) {
-            mp.stop();
-            mp.reset();
-            src.setStatus(Status.Stopped);
-        } else {
-            int channel = src.getChannel();
-            if (channel != -1) {
-                soundPool.pause(channel); // is not very likley to make
-                // something useful :)
-            }
-        }
-
-    }
-
-    @Override
-    public void deleteAudioData(AudioData ad) {
-
-        for (AudioSource src : musicPlaying.keySet()) {
-            if (src.getAudioData() == ad) {
-                MediaPlayer mp = musicPlaying.remove(src);
-                mp.stop();
-                mp.release();
-                src.setStatus(Status.Stopped);
-                src.setChannel(-1);
-                ad.setId(-1);
-                break;
-            }
-        }
-
-        if (ad.getId() > 0) {
-            soundPool.unload(ad.getId());
-            ad.setId(-1);
-        }
-    }
-
-    @Override
-    public void setEnvironment(Environment env) {
-        // not yet supported
-    }
-
-    @Override
-    public void deleteFilter(Filter filter) {
-    }
-
-    @Override
-    public float getSourcePlaybackTime(AudioSource src) {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-}

+ 5 - 0
jme3-android/src/main/java/com/jme3/renderer/android/AndroidGL.java

@@ -523,4 +523,9 @@ public class AndroidGL implements GL, GLExt, GLFbo {
     public Object glFenceSync(int condition, int flags) {
         throw new UnsupportedOperationException("OpenGL ES 2 does not support sync fences");
     }
+
+    @Override
+    public void glBlendEquationSeparate(int colorMode, int alphaMode) {
+        GLES20.glBlendEquationSeparate(colorMode, alphaMode);
+    }
 }

+ 0 - 591
jme3-android/src/main/java/com/jme3/renderer/android/TextureUtil.java

@@ -1,591 +0,0 @@
-/*
- * Copyright (c) 2009-2015 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.
- */
-package com.jme3.renderer.android;
-
-import android.graphics.Bitmap;
-import android.opengl.ETC1;
-import android.opengl.ETC1Util.ETC1Texture;
-import android.opengl.GLES20;
-import android.opengl.GLUtils;
-import com.jme3.asset.AndroidImageInfo;
-import com.jme3.renderer.RendererException;
-import com.jme3.texture.Image;
-import com.jme3.texture.Image.Format;
-import com.jme3.util.BufferUtils;
-import java.nio.ByteBuffer;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * @deprecated Should not be used anymore. Use {@link GLRenderer} instead.
- */
-@Deprecated
-public class TextureUtil {
-
-    private static final Logger logger = Logger.getLogger(TextureUtil.class.getName());
-    //TODO Make this configurable through appSettings
-    public static boolean ENABLE_COMPRESSION = true;
-    private static boolean NPOT = false;
-    private static boolean ETC1support = false;
-    private static boolean DXT1 = false;
-    private static boolean DEPTH24_STENCIL8 = false;
-    private static boolean DEPTH_TEXTURE = false;
-    private static boolean RGBA8 = false;
-    
-    // Same constant used by both GL_ARM_rgba8 and GL_OES_rgb8_rgba8.
-    private static final int GL_RGBA8 = 0x8058;
-    
-    private static final int GL_DXT1 = 0x83F0;
-    private static final int GL_DXT1A = 0x83F1;
-    
-    private static final int GL_DEPTH_STENCIL_OES = 0x84F9;
-    private static final int GL_UNSIGNED_INT_24_8_OES = 0x84FA;
-    private static final int GL_DEPTH24_STENCIL8_OES = 0x88F0;
-
-    public static void loadTextureFeatures(String extensionString) {
-        ETC1support = extensionString.contains("GL_OES_compressed_ETC1_RGB8_texture");
-        DEPTH24_STENCIL8 = extensionString.contains("GL_OES_packed_depth_stencil");
-        NPOT = extensionString.contains("GL_IMG_texture_npot") 
-                || extensionString.contains("GL_OES_texture_npot") 
-                || extensionString.contains("GL_NV_texture_npot_2D_mipmap");
-        
-        DXT1 = extensionString.contains("GL_EXT_texture_compression_dxt1");
-        DEPTH_TEXTURE = extensionString.contains("GL_OES_depth_texture");
-        
-        RGBA8 = extensionString.contains("GL_ARM_rgba8") ||
-                extensionString.contains("GL_OES_rgb8_rgba8");
-        
-        logger.log(Level.FINE, "Supports ETC1? {0}", ETC1support);
-        logger.log(Level.FINE, "Supports DEPTH24_STENCIL8? {0}", DEPTH24_STENCIL8);
-        logger.log(Level.FINE, "Supports NPOT? {0}", NPOT);
-        logger.log(Level.FINE, "Supports DXT1? {0}", DXT1);
-        logger.log(Level.FINE, "Supports DEPTH_TEXTURE? {0}", DEPTH_TEXTURE);
-        logger.log(Level.FINE, "Supports RGBA8? {0}", RGBA8);
-    }
-
-    private static void buildMipmap(Bitmap bitmap, boolean compress) {
-        int level = 0;
-        int height = bitmap.getHeight();
-        int width = bitmap.getWidth();
-
-        logger.log(Level.FINEST, " - Generating mipmaps for bitmap using SOFTWARE");
-
-        GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
-
-        while (height >= 1 || width >= 1) {
-            //First of all, generate the texture from our bitmap and set it to the according level
-            if (compress) {
-                logger.log(Level.FINEST, " - Uploading LOD level {0} ({1}x{2}) with compression.", new Object[]{level, width, height});
-                uploadBitmapAsCompressed(GLES20.GL_TEXTURE_2D, level, bitmap, false, 0, 0);
-            } else {
-                logger.log(Level.FINEST, " - Uploading LOD level {0} ({1}x{2}) directly.", new Object[]{level, width, height});
-                GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, level, bitmap, 0);
-            }
-
-            if (height == 1 || width == 1) {
-                break;
-            }
-
-            //Increase the mipmap level
-            height /= 2;
-            width /= 2;
-            Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap, width, height, true);
-
-            // Recycle any bitmaps created as a result of scaling the bitmap.
-            // Do not recycle the original image (mipmap level 0)
-            if (level != 0) {
-                bitmap.recycle();
-            }
-
-            bitmap = bitmap2;
-
-            level++;
-        }
-    }
-
-    private static void uploadBitmapAsCompressed(int target, int level, Bitmap bitmap, boolean subTexture, int x, int y) {
-        if (bitmap.hasAlpha()) {
-            logger.log(Level.FINEST, " - Uploading bitmap directly. Cannot compress as alpha present.");
-            if (subTexture) {
-                GLUtils.texSubImage2D(target, level, x, y, bitmap);
-                RendererUtil.checkGLError();
-            } else {
-                GLUtils.texImage2D(target, level, bitmap, 0);
-                RendererUtil.checkGLError();
-            }
-        } else {
-            // Convert to RGB565
-            int bytesPerPixel = 2;
-            Bitmap rgb565 = bitmap.copy(Bitmap.Config.RGB_565, true);
-
-            // Put texture data into ByteBuffer
-            ByteBuffer inputImage = BufferUtils.createByteBuffer(bitmap.getRowBytes() * bitmap.getHeight());
-            rgb565.copyPixelsToBuffer(inputImage);
-            inputImage.position(0);
-
-            // Delete the copied RGB565 image
-            rgb565.recycle();
-
-            // Encode the image into the output bytebuffer
-            int encodedImageSize = ETC1.getEncodedDataSize(bitmap.getWidth(), bitmap.getHeight());
-            ByteBuffer compressedImage = BufferUtils.createByteBuffer(encodedImageSize);
-            ETC1.encodeImage(inputImage, bitmap.getWidth(),
-                    bitmap.getHeight(),
-                    bytesPerPixel,
-                    bytesPerPixel * bitmap.getWidth(),
-                    compressedImage);
-
-            // Delete the input image buffer
-            BufferUtils.destroyDirectBuffer(inputImage);
-
-            // Create an ETC1Texture from the compressed image data
-            ETC1Texture etc1tex = new ETC1Texture(bitmap.getWidth(), bitmap.getHeight(), compressedImage);
-
-            // Upload the ETC1Texture
-            if (bytesPerPixel == 2) {
-                int oldSize = (bitmap.getRowBytes() * bitmap.getHeight());
-                int newSize = compressedImage.capacity();
-                logger.log(Level.FINEST, " - Uploading compressed image to GL, oldSize = {0}, newSize = {1}, ratio = {2}", new Object[]{oldSize, newSize, (float) oldSize / newSize});
-                if (subTexture) {
-                    GLES20.glCompressedTexSubImage2D(target,
-                            level,
-                            x, y,
-                            bitmap.getWidth(),
-                            bitmap.getHeight(),
-                            ETC1.ETC1_RGB8_OES,
-                            etc1tex.getData().capacity(),
-                            etc1tex.getData());
-                    
-                    RendererUtil.checkGLError();
-                } else {
-                    GLES20.glCompressedTexImage2D(target,
-                            level,
-                            ETC1.ETC1_RGB8_OES,
-                            bitmap.getWidth(),
-                            bitmap.getHeight(),
-                            0,
-                            etc1tex.getData().capacity(),
-                            etc1tex.getData());
-                    
-                    RendererUtil.checkGLError();
-                }
-
-//                ETC1Util.loadTexture(target, level, 0, GLES20.GL_RGB,
-//                        GLES20.GL_UNSIGNED_SHORT_5_6_5, etc1Texture);
-//            } else if (bytesPerPixel == 3) {
-//                ETC1Util.loadTexture(target, level, 0, GLES20.GL_RGB,
-//                        GLES20.GL_UNSIGNED_BYTE, etc1Texture);
-            }
-
-            BufferUtils.destroyDirectBuffer(compressedImage);
-        }
-    }
-
-    /**
-     * <code>uploadTextureBitmap</code> uploads a native android bitmap
-     */
-    public static void uploadTextureBitmap(final int target, Bitmap bitmap, boolean needMips) {
-        uploadTextureBitmap(target, bitmap, needMips, false, 0, 0);
-    }
-
-    /**
-     * <code>uploadTextureBitmap</code> uploads a native android bitmap
-     */
-    public static void uploadTextureBitmap(final int target, Bitmap bitmap, boolean needMips, boolean subTexture, int x, int y) {
-        boolean recycleBitmap = false;
-        //TODO, maybe this should raise an exception when NPOT is not supported
-
-        boolean willCompress = ENABLE_COMPRESSION && ETC1support && !bitmap.hasAlpha();
-        if (needMips && willCompress) {
-            // Image is compressed and mipmaps are desired, generate them
-            // using software.
-            buildMipmap(bitmap, willCompress);
-        } else {
-            if (willCompress) {
-                // Image is compressed but mipmaps are not desired, upload directly.
-                logger.log(Level.FINEST, " - Uploading compressed bitmap. Mipmaps are not generated.");
-                uploadBitmapAsCompressed(target, 0, bitmap, subTexture, x, y);
-
-            } else {
-                // Image is not compressed, mipmaps may or may not be desired.
-                logger.log(Level.FINEST, " - Uploading bitmap directly.{0}",
-                        (needMips
-                        ? " Mipmaps will be generated in HARDWARE"
-                        : " Mipmaps are not generated."));
-                if (subTexture) {
-                    System.err.println("x : " + x + " y :" + y + " , " + bitmap.getWidth() + "/" + bitmap.getHeight());
-                    GLUtils.texSubImage2D(target, 0, x, y, bitmap);
-                    RendererUtil.checkGLError();
-                } else {
-                    GLUtils.texImage2D(target, 0, bitmap, 0);
-                    RendererUtil.checkGLError();
-                }
-
-                if (needMips) {
-                    // No pregenerated mips available,
-                    // generate from base level if required
-                    GLES20.glGenerateMipmap(target);
-                    RendererUtil.checkGLError();
-                }
-            }
-        }
-
-        if (recycleBitmap) {
-            bitmap.recycle();
-        }
-    }
-
-    public static void uploadTextureAny(Image img, int target, int index, boolean needMips) {
-        if (img.getEfficentData() instanceof AndroidImageInfo) {
-            logger.log(Level.FINEST, " === Uploading image {0}. Using BITMAP PATH === ", img);
-            // If image was loaded from asset manager, use fast path
-            AndroidImageInfo imageInfo = (AndroidImageInfo) img.getEfficentData();
-            uploadTextureBitmap(target, imageInfo.getBitmap(), needMips);
-        } else {
-            logger.log(Level.FINEST, " === Uploading image {0}. Using BUFFER PATH === ", img);
-            boolean wantGeneratedMips = needMips && !img.hasMipmaps();
-            if (wantGeneratedMips && img.getFormat().isCompressed()) {
-                logger.log(Level.WARNING, "Generating mipmaps is only"
-                        + " supported for Bitmap based or non-compressed images!");
-            }
-
-            // Upload using slower path
-            logger.log(Level.FINEST, " - Uploading bitmap directly.{0}",
-                    (wantGeneratedMips
-                    ? " Mipmaps will be generated in HARDWARE"
-                    : " Mipmaps are not generated."));
-            
-            uploadTexture(img, target, index);
-
-            // Image was uploaded using slower path, since it is not compressed,
-            // then compress it
-            if (wantGeneratedMips) {
-                // No pregenerated mips available,
-                // generate from base level if required
-                GLES20.glGenerateMipmap(target);
-            }
-        }
-    }
-
-    private static void unsupportedFormat(Format fmt) {
-        throw new UnsupportedOperationException("The image format '" + fmt + "' is unsupported by the video hardware.");
-    }
-
-    public static AndroidGLImageFormat getImageFormat(Format fmt, boolean forRenderBuffer)
-            throws UnsupportedOperationException {
-        AndroidGLImageFormat imageFormat = new AndroidGLImageFormat();
-        switch (fmt) {
-            case Depth32:
-            case Depth32F:
-                throw new UnsupportedOperationException("The image format '"
-                        + fmt + "' is not supported by OpenGL ES 2.0 specification.");
-            case Alpha8:
-                imageFormat.format = GLES20.GL_ALPHA;
-                imageFormat.dataType = GLES20.GL_UNSIGNED_BYTE;
-                if (RGBA8) {
-                    imageFormat.renderBufferStorageFormat = GL_RGBA8;
-                } else {
-                    // Highest precision alpha supported by vanilla OGLES2
-                    imageFormat.renderBufferStorageFormat = GLES20.GL_RGBA4;
-                }
-                break;
-            case Luminance8:
-                imageFormat.format = GLES20.GL_LUMINANCE;
-                imageFormat.dataType = GLES20.GL_UNSIGNED_BYTE;
-                if (RGBA8) {
-                    imageFormat.renderBufferStorageFormat = GL_RGBA8;
-                } else {
-                    // Highest precision luminance supported by vanilla OGLES2
-                    imageFormat.renderBufferStorageFormat = GLES20.GL_RGB565;
-                }
-                break;
-            case Luminance8Alpha8:
-                imageFormat.format = GLES20.GL_LUMINANCE_ALPHA;
-                imageFormat.dataType = GLES20.GL_UNSIGNED_BYTE;
-                if (RGBA8) {
-                    imageFormat.renderBufferStorageFormat = GL_RGBA8;
-                } else {
-                    imageFormat.renderBufferStorageFormat = GLES20.GL_RGBA4;
-                }
-                break;
-            case RGB565:
-                imageFormat.format = GLES20.GL_RGB;
-                imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT_5_6_5;
-                imageFormat.renderBufferStorageFormat = GLES20.GL_RGB565;
-                break;
-            case RGB5A1:
-                imageFormat.format = GLES20.GL_RGBA;
-                imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT_5_5_5_1;
-                imageFormat.renderBufferStorageFormat = GLES20.GL_RGB5_A1;
-                break;
-            case RGB8:
-                imageFormat.format = GLES20.GL_RGB;
-                imageFormat.dataType = GLES20.GL_UNSIGNED_BYTE;
-                if (RGBA8) {
-                    imageFormat.renderBufferStorageFormat = GL_RGBA8;
-                } else {
-                    // Fallback: Use RGB565 if RGBA8 is not available.
-                    imageFormat.renderBufferStorageFormat = GLES20.GL_RGB565;
-                }
-                break;
-            case BGR8:
-                imageFormat.format = GLES20.GL_RGB;
-                imageFormat.dataType = GLES20.GL_UNSIGNED_BYTE;
-                if (RGBA8) {
-                    imageFormat.renderBufferStorageFormat = GL_RGBA8;
-                } else {
-                    imageFormat.renderBufferStorageFormat = GLES20.GL_RGB565;
-                }
-                break;
-            case RGBA8:
-                imageFormat.format = GLES20.GL_RGBA;
-                imageFormat.dataType = GLES20.GL_UNSIGNED_BYTE;
-                if (RGBA8) {
-                    imageFormat.renderBufferStorageFormat = GL_RGBA8;
-                } else {
-                    imageFormat.renderBufferStorageFormat = GLES20.GL_RGBA4;
-                }
-                break;
-            case Depth:
-            case Depth16:
-                if (!DEPTH_TEXTURE && !forRenderBuffer) {
-                    unsupportedFormat(fmt);
-                }
-                imageFormat.format = GLES20.GL_DEPTH_COMPONENT;
-                imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT;
-                imageFormat.renderBufferStorageFormat = GLES20.GL_DEPTH_COMPONENT16;
-                break;
-            case Depth24:
-            case Depth24Stencil8:
-                if (!DEPTH_TEXTURE) {
-                    unsupportedFormat(fmt);
-                }
-                if (DEPTH24_STENCIL8) {
-                    // NEW: True Depth24 + Stencil8 format.
-                    imageFormat.format = GL_DEPTH_STENCIL_OES;
-                    imageFormat.dataType = GL_UNSIGNED_INT_24_8_OES;
-                    imageFormat.renderBufferStorageFormat = GL_DEPTH24_STENCIL8_OES;
-                } else {
-                    // Vanilla OGLES2, only Depth16 available.
-                    imageFormat.format = GLES20.GL_DEPTH_COMPONENT;
-                    imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT;
-                    imageFormat.renderBufferStorageFormat = GLES20.GL_DEPTH_COMPONENT16;
-                }
-                break;
-            case DXT1:
-                if (!DXT1) {
-                    unsupportedFormat(fmt);
-                }
-                imageFormat.format = GL_DXT1;
-                imageFormat.dataType = GLES20.GL_UNSIGNED_BYTE;
-                imageFormat.compress = true;
-                break;
-            case DXT1A:
-                if (!DXT1) {
-                    unsupportedFormat(fmt);
-                }
-                imageFormat.format = GL_DXT1A;
-                imageFormat.dataType = GLES20.GL_UNSIGNED_BYTE;
-                imageFormat.compress = true;
-                break;
-            default:
-                throw new UnsupportedOperationException("Unrecognized format: " + fmt);
-        }
-        return imageFormat;
-    }
-
-    public static class AndroidGLImageFormat {
-
-        boolean compress = false;
-        int format = -1;
-        int renderBufferStorageFormat = -1;
-        int dataType = -1;
-    }
-
-    private static void uploadTexture(Image img,
-            int target,
-            int index) {
-
-        if (img.getEfficentData() instanceof AndroidImageInfo) {
-            throw new RendererException("This image uses efficient data. "
-                    + "Use uploadTextureBitmap instead.");
-        }
-
-        // Otherwise upload image directly.
-        // Prefer to only use power of 2 textures here to avoid errors.
-        Image.Format fmt = img.getFormat();
-        ByteBuffer data;
-        if (index >= 0 || img.getData() != null && img.getData().size() > 0) {
-            data = img.getData(index);
-        } else {
-            data = null;
-        }
-
-        int width = img.getWidth();
-        int height = img.getHeight();
-
-        if (!NPOT && img.isNPOT()) {
-            // Check if texture is POT
-            throw new RendererException("Non-power-of-2 textures "
-                    + "are not supported by the video hardware "
-                    + "and no scaling path available for image: " + img);
-        }
-        AndroidGLImageFormat imageFormat = getImageFormat(fmt, false);
-
-        if (data != null) {
-            GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
-        }
-
-        int[] mipSizes = img.getMipMapSizes();
-        int pos = 0;
-        if (mipSizes == null) {
-            if (data != null) {
-                mipSizes = new int[]{data.capacity()};
-            } else {
-                mipSizes = new int[]{width * height * fmt.getBitsPerPixel() / 8};
-            }
-        }
-
-        for (int i = 0; i < mipSizes.length; i++) {
-            int mipWidth = Math.max(1, width >> i);
-            int mipHeight = Math.max(1, height >> i);
-
-            if (data != null) {
-                data.position(pos);
-                data.limit(pos + mipSizes[i]);
-            }
-
-            if (imageFormat.compress && data != null) {
-                GLES20.glCompressedTexImage2D(target,
-                        i,
-                        imageFormat.format,
-                        mipWidth,
-                        mipHeight,
-                        0,
-                        data.remaining(),
-                        data);
-            } else {
-                GLES20.glTexImage2D(target,
-                        i,
-                        imageFormat.format,
-                        mipWidth,
-                        mipHeight,
-                        0,
-                        imageFormat.format,
-                        imageFormat.dataType,
-                        data);
-            }
-
-            pos += mipSizes[i];
-        }
-    }
-
-    /**
-     * Update the texture currently bound to target at with data from the given
-     * Image at position x and y. The parameter index is used as the zoffset in
-     * case a 3d texture or texture 2d array is being updated.
-     *
-     * @param image Image with the source data (this data will be put into the
-     * texture)
-     * @param target the target texture
-     * @param index the mipmap level to update
-     * @param x the x position where to put the image in the texture
-     * @param y the y position where to put the image in the texture
-     */
-    public static void uploadSubTexture(
-            Image img,
-            int target,
-            int index,
-            int x,
-            int y) {
-        if (img.getEfficentData() instanceof AndroidImageInfo) {
-            AndroidImageInfo imageInfo = (AndroidImageInfo) img.getEfficentData();
-            uploadTextureBitmap(target, imageInfo.getBitmap(), true, true, x, y);
-            return;
-        }
-
-        // Otherwise upload image directly.
-        // Prefer to only use power of 2 textures here to avoid errors.
-        Image.Format fmt = img.getFormat();
-        ByteBuffer data;
-        if (index >= 0 || img.getData() != null && img.getData().size() > 0) {
-            data = img.getData(index);
-        } else {
-            data = null;
-        }
-
-        int width = img.getWidth();
-        int height = img.getHeight();
-
-        if (!NPOT && img.isNPOT()) {
-            // Check if texture is POT
-            throw new RendererException("Non-power-of-2 textures "
-                    + "are not supported by the video hardware "
-                    + "and no scaling path available for image: " + img);
-        }
-        AndroidGLImageFormat imageFormat = getImageFormat(fmt, false);
-
-        if (data != null) {
-            GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
-        }
-
-        int[] mipSizes = img.getMipMapSizes();
-        int pos = 0;
-        if (mipSizes == null) {
-            if (data != null) {
-                mipSizes = new int[]{data.capacity()};
-            } else {
-                mipSizes = new int[]{width * height * fmt.getBitsPerPixel() / 8};
-            }
-        }
-
-        for (int i = 0; i < mipSizes.length; i++) {
-            int mipWidth = Math.max(1, width >> i);
-            int mipHeight = Math.max(1, height >> i);
-
-            if (data != null) {
-                data.position(pos);
-                data.limit(pos + mipSizes[i]);
-            }
-
-            if (imageFormat.compress && data != null) {
-                GLES20.glCompressedTexSubImage2D(target, i, x, y, mipWidth, mipHeight, imageFormat.format, data.remaining(), data);
-                RendererUtil.checkGLError();
-            } else {
-                GLES20.glTexSubImage2D(target, i, x, y, mipWidth, mipHeight, imageFormat.format, imageFormat.dataType, data);
-                RendererUtil.checkGLError();
-            }
-
-            pos += mipSizes[i];
-        }
-    }
-}

+ 0 - 23
jme3-android/src/main/java/com/jme3/texture/plugins/AndroidImageLoader.java

@@ -1,23 +0,0 @@
-package com.jme3.texture.plugins;
-
-import android.graphics.Bitmap;
-import com.jme3.asset.AndroidImageInfo;
-import com.jme3.asset.AssetInfo;
-import com.jme3.asset.AssetLoader;
-import com.jme3.texture.Image;
-import com.jme3.texture.image.ColorSpace;
-import java.io.IOException;
-
-@Deprecated
-public class AndroidImageLoader implements AssetLoader {
-
-    public Object load(AssetInfo info) throws IOException {
-        AndroidImageInfo imageInfo = new AndroidImageInfo(info);
-        Bitmap bitmap = imageInfo.getBitmap();
-        
-        Image image = new Image(imageInfo.getFormat(), bitmap.getWidth(), bitmap.getHeight(), null, ColorSpace.sRGB);
-        
-        image.setEfficentData(imageInfo);
-        return image;
-    }
-}

+ 1 - 1
jme3-android/src/main/java/jme3test/android/SimpleTexturedTest.java

@@ -46,7 +46,7 @@ public class SimpleTexturedTest extends SimpleApplication {
 
 
 		shapeSphere = new Sphere(16, 16, .5f);
-		shapeBox = new Box(Vector3f.ZERO, 0.3f, 0.3f, 0.3f);
+            shapeBox = new Box(0.3f, 0.3f, 0.3f);
 
 
 	//	ModelConverter.optimize(geom);

+ 33 - 1
jme3-bullet-native/build.gradle

@@ -34,7 +34,14 @@ libraries {
 //                linker.args "-static-libstdc++"
             } else if (targetPlatform.operatingSystem.name == "windows") {
                 if (toolChain in Gcc) {
-                    cppCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include/win32"
+                    if (toolChain.name.startsWith('mingw')) {
+                        cppCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include/linux"
+                    } else {
+                        cppCompiler.args '-I', "${org.gradle.internal.jvm.Jvm.current().javaHome}/include/win32"
+                    }
+                    cppCompiler.args "-fpermissive"
+                    cppCompiler.args "-static"
+                    linker.args "-static"
                 }
                 else if (toolChain in VisualCpp) {
                     cppCompiler.args "/I${org.gradle.internal.jvm.Jvm.current().javaHome}\\include\\win32"
@@ -76,6 +83,31 @@ sourceSets {
 
 // Set of target platforms, will be available based on build system
 model {
+
+    toolChains {
+        gcc(Gcc)
+        mingw_x86(Gcc) {
+            eachPlatform() {
+                cCompiler.executable "i686-w64-mingw32-gcc"
+                cppCompiler.executable "i686-w64-mingw32-g++"
+                linker.executable "i686-w64-mingw32-g++"
+                assembler.executable "i686-w64-mingw32-g++"
+                staticLibArchiver.executable "i686-w64-mingw32-gcc-ar"
+            }
+            target("windows_x86")
+        }
+        mingw_x86_64(Gcc) {
+            eachPlatform() {
+                cCompiler.executable "x86_64-w64-mingw32-gcc"
+                cppCompiler.executable "x86_64-w64-mingw32-g++"
+                linker.executable "x86_64-w64-mingw32-g++"
+                assembler.executable "x86_64-w64-mingw32-g++"
+                staticLibArchiver.executable "x86_64-w64-mingw32-gcc-ar"
+            }
+            target("windows_x86_64")
+        }
+    }
+
     platforms{
 //    osx_universal { // TODO: universal binary doesn't work?
 //        architecture 'x86_64'

+ 0 - 44
jme3-core/src/main/java/com/jme3/animation/BoneAnimation.java

@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.
- */
-package com.jme3.animation;
-
-/**
- * @deprecated use Animation instead with tracks of selected type (ie. BoneTrack, SpatialTrack, MeshTrack)
- */
-@Deprecated
-public final class BoneAnimation extends Animation {
-
-    @Deprecated
-    public BoneAnimation(String name, float length) {
-        super(name, length);
-    }
-}

+ 0 - 42
jme3-core/src/main/java/com/jme3/animation/SpatialAnimation.java

@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.
- */
-package com.jme3.animation;
-
-/**
- * @deprecated use Animation instead with tracks of selected type (ie. BoneTrack, SpatialTrack, MeshTrack)
- */
-@Deprecated
-public class SpatialAnimation extends Animation {
-    public SpatialAnimation(String name, float length) {
-        super(name, length);
-    }
-}

+ 2 - 1
jme3-core/src/main/java/com/jme3/app/SimpleApplication.java

@@ -32,6 +32,7 @@
 package com.jme3.app;
 
 import com.jme3.app.state.AppState;
+import com.jme3.audio.AudioListenerState;
 import com.jme3.font.BitmapFont;
 import com.jme3.font.BitmapText;
 import com.jme3.input.FlyByCamera;
@@ -96,7 +97,7 @@ public abstract class SimpleApplication extends LegacyApplication {
     }
 
     public SimpleApplication() {
-        this( new StatsAppState(), new FlyCamAppState(), new DebugKeysAppState() );
+        this(new StatsAppState(), new FlyCamAppState(), new AudioListenerState(), new DebugKeysAppState());
     }
 
     public SimpleApplication( AppState... initialStates ) {

+ 0 - 36
jme3-core/src/main/java/com/jme3/asset/TextureKey.java

@@ -123,24 +123,6 @@ public class TextureKey extends AssetKey<Texture> {
         this.anisotropy = anisotropy;
     }
 
-    /**
-     * @deprecated Use {@link #setTextureTypeHint(com.jme3.texture.Texture.Type) }
-     * instead.
-     */
-    @Deprecated
-    public boolean isAsCube() {
-        return textureTypeHint == Type.CubeMap;
-    }
-
-    /**
-     * @deprecated Use {@link #setTextureTypeHint(com.jme3.texture.Texture.Type) }
-     * instead.
-     */
-    @Deprecated
-    public void setAsCube(boolean asCube) {
-        textureTypeHint = asCube ? Type.CubeMap : Type.TwoDimensional;
-    }
-
     public boolean isGenerateMips() {
         return generateMips;
     }
@@ -149,24 +131,6 @@ public class TextureKey extends AssetKey<Texture> {
         this.generateMips = generateMips;
     }
 
-    /**
-     * @deprecated Use {@link #setTextureTypeHint(com.jme3.texture.Texture.Type) }
-     * instead.
-     */
-    @Deprecated
-    public boolean isAsTexture3D() {
-        return textureTypeHint == Type.ThreeDimensional;
-    }
-
-    /**
-     * @deprecated Use {@link #setTextureTypeHint(com.jme3.texture.Texture.Type) }
-     * instead.
-     */
-    @Deprecated
-    public void setAsTexture3D(boolean asTexture3D) {
-        textureTypeHint = asTexture3D ? Type.ThreeDimensional : Type.TwoDimensional;
-    }
-
     /**
      * The type of texture expected to be returned.
      * 

+ 104 - 0
jme3-core/src/main/java/com/jme3/audio/AudioListenerState.java

@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2009-2016 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.
+ */
+package com.jme3.audio;
+
+import com.jme3.app.Application;
+import com.jme3.app.state.BaseAppState;
+import com.jme3.math.Quaternion;
+import com.jme3.math.Vector3f;
+import com.jme3.renderer.Camera;
+import com.jme3.renderer.RenderManager;
+
+/**
+ * <code>AudioListenerState</code> updates the audio listener's position,
+ * orientation, and velocity from a {@link Camera}.
+ *
+ * @author Kirill Vainer
+ */
+public class AudioListenerState extends BaseAppState {
+
+    private Listener listener;
+    private Camera camera;
+    private float lastTpf;
+
+    public AudioListenerState() {
+    }
+
+    @Override
+    protected void initialize(Application app) {
+        this.camera = app.getCamera();
+        this.listener = app.getListener();
+    }
+
+    @Override
+    protected void cleanup(Application app) {
+    }
+
+    @Override
+    public void update(float tpf) {
+        lastTpf = tpf;
+    }
+
+    @Override
+    public void render(RenderManager rm) {
+        if (!isEnabled()) {
+            return;
+        }
+
+        Vector3f lastLocation = listener.getLocation();
+        Vector3f currentLocation = camera.getLocation();
+        Vector3f velocity = listener.getVelocity();
+
+        if (!lastLocation.equals(currentLocation)) {
+            velocity.set(currentLocation).subtractLocal(lastLocation);
+            velocity.multLocal(1f / lastTpf);
+            listener.setLocation(currentLocation);
+            listener.setVelocity(velocity);
+        } else if (!velocity.equals(Vector3f.ZERO)) {
+            listener.setVelocity(Vector3f.ZERO);
+        }
+
+        Quaternion lastRotation = listener.getRotation();
+        Quaternion currentRotation = camera.getRotation();
+        if (!lastRotation.equals(currentRotation)) {
+            listener.setRotation(currentRotation);
+        }
+    }
+
+    @Override
+    protected void onEnable() {
+    }
+
+    @Override
+    protected void onDisable() {
+    }
+}

+ 38 - 6
jme3-core/src/main/java/com/jme3/audio/AudioNode.java

@@ -78,6 +78,7 @@ public class AudioNode extends Node implements AudioSource {
     protected transient AudioData data = null;
     protected transient volatile AudioSource.Status status = AudioSource.Status.Stopped;
     protected transient volatile int channel = -1;
+    protected Vector3f previousWorldTranslation = Vector3f.NAN;
     protected Vector3f velocity = new Vector3f();
     protected boolean reverbEnabled = false;
     protected float maxDistance = 200; // 200 meters
@@ -88,6 +89,8 @@ public class AudioNode extends Node implements AudioSource {
     protected float innerAngle = 360;
     protected float outerAngle = 360;
     protected boolean positional = true;
+    protected boolean velocityFromTranslation = false;
+    protected float lastTpf;
 
     /**
      * <code>Status</code> indicates the current status of the audio node.
@@ -702,17 +705,44 @@ public class AudioNode extends Node implements AudioSource {
         }
     }
 
+    public boolean isVelocityFromTranslation() {
+        return velocityFromTranslation;
+    }
+
+    public void setVelocityFromTranslation(boolean velocityFromTranslation) {
+        this.velocityFromTranslation = velocityFromTranslation;
+    }
+
     @Override
-    public void updateGeometricState(){
-        boolean updatePos = false;
-        if ((refreshFlags & RF_TRANSFORM) != 0){
-            updatePos = true;
-        }
+    public void updateLogicalState(float tpf) {
+        super.updateLogicalState(tpf);
+        lastTpf = tpf;
+    }
 
+    @Override
+    public void updateGeometricState() {
         super.updateGeometricState();
 
-        if (updatePos && channel >= 0)
+        if (channel < 0) {
+            return;
+        }
+
+        Vector3f currentWorldTranslation = worldTransform.getTranslation();
+
+        if (Float.isNaN(previousWorldTranslation.x)
+                || !previousWorldTranslation.equals(currentWorldTranslation)) {
+
             getRenderer().updateSourceParam(this, AudioParam.Position);
+
+            if (velocityFromTranslation) {
+                velocity.set(currentWorldTranslation).subtractLocal(previousWorldTranslation);
+                velocity.multLocal(1f / lastTpf);
+
+                getRenderer().updateSourceParam(this, AudioParam.Velocity);
+            }
+
+            previousWorldTranslation.set(currentWorldTranslation);
+        }
     }
 
     @Override
@@ -772,6 +802,7 @@ public class AudioNode extends Node implements AudioSource {
         oc.write(outerAngle, "outer_angle", 360);
 
         oc.write(positional, "positional", false);
+        oc.write(velocityFromTranslation, "velocity_from_translation", false);
     }
 
     @Override
@@ -806,6 +837,7 @@ public class AudioNode extends Node implements AudioSource {
         outerAngle = ic.readFloat("outer_angle", 360);
 
         positional = ic.readBoolean("positional", false);
+        velocityFromTranslation = ic.readBoolean("velocity_from_translation", false);
 
         if (audioKey != null) {
             try {

+ 3 - 3
jme3-core/src/main/java/com/jme3/audio/Listener.java

@@ -36,9 +36,9 @@ import com.jme3.math.Vector3f;
 
 public class Listener {
 
-    private Vector3f location;
-    private Vector3f velocity;
-    private Quaternion rotation;
+    private final Vector3f location;
+    private final Vector3f velocity;
+    private final Quaternion rotation;
     private float volume = 1;
     private AudioRenderer renderer;
 

+ 5 - 4
jme3-core/src/main/java/com/jme3/audio/openal/ALAudioRenderer.java

@@ -904,11 +904,12 @@ public class ALAudioRenderer implements AudioRenderer, Runnable {
                     } else {
                         // Buffer finished playing.
                         if (src.isLooping()) {
-                            throw new AssertionError("Unexpected state: " + 
-                                                     "A looping sound has stopped playing");
-                        } else {
-                            reclaimChannel = true;
+                            // When a device is disconnected, all sources
+                            // will enter the "stopped" state.
+                            logger.warning("A looping sound has stopped playing");
                         }
+
+                        reclaimChannel = true;
                     }
                     
                     if (reclaimChannel) {

+ 2 - 1
jme3-core/src/main/java/com/jme3/cinematic/MotionPath.java

@@ -121,7 +121,8 @@ public class MotionPath implements Savable {
             Material m = assetManager.loadMaterial("Common/Materials/RedColor.j3m");
             for (Iterator<Vector3f> it = spline.getControlPoints().iterator(); it.hasNext();) {
                 Vector3f cp = it.next();
-                Geometry geo = new Geometry("box", new Box(cp, 0.3f, 0.3f, 0.3f));
+                Geometry geo = new Geometry("box", new Box(0.3f, 0.3f, 0.3f));
+                geo.setLocalTranslation(cp);
                 geo.setMaterial(m);
                 debugNode.attachChild(geo);
 

+ 0 - 76
jme3-core/src/main/java/com/jme3/effect/ParticleComparator.java

@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.
- */
-package com.jme3.effect;
-
-import com.jme3.renderer.Camera;
-import java.util.Comparator;
-
-@Deprecated
-class ParticleComparator implements Comparator<Particle> {
-
-    private Camera cam;
-
-    public void setCamera(Camera cam){
-        this.cam = cam;
-    }
-
-    public int compare(Particle p1, Particle p2) {
-        return 0; // unused
-        /*
-        if (p1.life <= 0 || p2.life <= 0)
-            return 0;
-
-//        if (p1.life <= 0)
-//            return 1;
-//        else if (p2.life <= 0)
-//            return -1;
-
-        float d1 = p1.distToCam, d2 = p2.distToCam;
-
-        if (d1 == -1){
-            d1 = cam.distanceToNearPlane(p1.position);
-            p1.distToCam = d1;
-        }
-        if (d2 == -1){
-            d2 = cam.distanceToNearPlane(p2.position);
-            p2.distToCam = d2;
-        }
-
-        if (d1 < d2)
-            return 1;
-        else if (d1 > d2)
-            return -1;
-        else
-            return 0;
-        */
-    }
-}

+ 3 - 2
jme3-core/src/main/java/com/jme3/effect/ParticleMesh.java

@@ -50,8 +50,9 @@ public abstract class ParticleMesh extends Mesh {
     public enum Type {
         /**
          * The particle mesh is composed of points. Each particle is a point.
-         * This can be used in conjuction with {@link RenderState#setPointSprite(boolean) point sprites}
-         * to render particles the usual way.
+         * Note that point based particles do not support certain features such
+         * as {@link ParticleEmitter#setRotateSpeed(float) rotation}, and
+         * {@link ParticleEmitter#setFacingVelocity(boolean) velocity following}.
          */
         Point,
         

+ 3 - 3
jme3-core/src/main/java/com/jme3/export/SavableClassUtil.java

@@ -54,10 +54,10 @@ import java.util.logging.Logger;
  */
 public class SavableClassUtil {
 
-    private final static HashMap<String, String> classRemappings = new HashMap<String, String>();
+    private final static HashMap<String, String> CLASS_REMAPPINGS = new HashMap<>();
     
     private static void addRemapping(String oldClass, Class<? extends Savable> newClass){
-        classRemappings.put(oldClass, newClass.getName());
+        CLASS_REMAPPINGS.put(oldClass, newClass.getName());
     }
     
     static {
@@ -74,7 +74,7 @@ public class SavableClassUtil {
     }
     
     private static String remapClass(String className) throws ClassNotFoundException {
-        String result = classRemappings.get(className);
+        String result = CLASS_REMAPPINGS.get(className);
         if (result == null) {
             return className;
         } else {

+ 5 - 18
jme3-core/src/main/java/com/jme3/material/Material.java

@@ -75,18 +75,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
     // Version #2: Fixed issue with RenderState.apply*** flags not getting exported
     public static final int SAVABLE_VERSION = 2;
     private static final Logger logger = Logger.getLogger(Material.class.getName());
-    private static final RenderState additiveLight = new RenderState();
-    private static final RenderState depthOnly = new RenderState();
 
-    static {
-        depthOnly.setDepthTest(true);
-        depthOnly.setDepthWrite(true);
-        depthOnly.setFaceCullMode(RenderState.FaceCullMode.Back);
-        depthOnly.setColorWrite(false);
-
-        additiveLight.setBlendMode(RenderState.BlendMode.AlphaAdditive);
-        additiveLight.setDepthWrite(false);
-    }
     private AssetKey key;
     private String name;
     private MaterialDef def;
@@ -98,7 +87,6 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
     private boolean transparent = false;
     private boolean receivesShadows = false;
     private int sortingId = -1;
-    private transient ColorRGBA ambientLightColor = new ColorRGBA(0, 0, 0, 1);
 
     public Material(MaterialDef def) {
         if (def == null) {
@@ -742,9 +730,11 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
                 lastTech = techDef;
             }
             if (tech == null) {
-                throw new UnsupportedOperationException("No default technique on material '" + def.getName() + "'\n"
-                        + " is supported by the video hardware. The caps "
-                        + lastTech.getRequiredCaps() + " are required.");
+                throw new UnsupportedOperationException(
+                        String.format("No technique '%s' on material "
+                                + "'%s' is supported by the video hardware. "
+                                + "The capabilities %s are required.",
+                                name, def.getName(), lastTech.getRequiredCaps()));
             }
         } else if (technique == tech) {
             // attempting to switch to an already
@@ -1101,14 +1091,11 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
             // Try to guess values of "apply" render state based on defaults
             // if value != default then set apply to true
             additionalState.applyPolyOffset = additionalState.offsetEnabled;
-            additionalState.applyAlphaFallOff = additionalState.alphaTest;
-            additionalState.applyAlphaTest = additionalState.alphaTest;
             additionalState.applyBlendMode = additionalState.blendMode != BlendMode.Off;
             additionalState.applyColorWrite = !additionalState.colorWrite;
             additionalState.applyCullMode = additionalState.cullMode != FaceCullMode.Back;
             additionalState.applyDepthTest = !additionalState.depthTest;
             additionalState.applyDepthWrite = !additionalState.depthWrite;
-            additionalState.applyPointSprite = additionalState.pointSprite;
             additionalState.applyStencilTest = additionalState.stencilTest;
             additionalState.applyWireFrame = additionalState.wireframe;
         }

+ 249 - 195
jme3-core/src/main/java/com/jme3/material/RenderState.java

@@ -75,12 +75,11 @@ public class RenderState implements Cloneable, Savable {
 
     /**
      * <code>TestFunction</code> specifies the testing function for stencil test
-     * function and alpha test function.
+     * function.
      *
-     * <p>The functions work similarly as described except that for stencil
-     * test function, the reference value given in the stencil command is
-     * the input value while the reference is the value already in the stencil
-     * buffer.
+     * <p>
+     * The reference value given in the stencil command is the input value while
+     * the reference is the value already in the stencil buffer.
      */
     public enum TestFunction {
 
@@ -118,7 +117,94 @@ public class RenderState implements Cloneable, Savable {
         /**
          * The test always passes
          */
-        Always,}
+        Always
+    }
+
+    /**
+     * <code>BlendEquation</code> specifies the blending equation to combine
+     * pixels.
+     */
+    public enum BlendEquation {
+        /**
+         * Sets the blend equation so that the source and destination data are
+         * added. (Default) Clamps to [0,1] Useful for things like antialiasing
+         * and transparency.
+         */
+        Add,
+        /**
+         * Sets the blend equation so that the source and destination data are
+         * subtracted (Src - Dest). Clamps to [0,1] Falls back to Add if
+         * supportsSubtract is false.
+         */
+        Subtract,
+        /**
+         * Same as Subtract, but the order is reversed (Dst - Src). Clamps to
+         * [0,1] Falls back to Add if supportsSubtract is false.
+         */
+        ReverseSubtract,
+        /**
+         * Sets the blend equation so that each component of the result color is
+         * the minimum of the corresponding components of the source and
+         * destination colors. This and Max are useful for applications that
+         * analyze image data (image thresholding against a constant color, for
+         * example). Falls back to Add if supportsMinMax is false.
+         */
+        Min,
+        /**
+         * Sets the blend equation so that each component of the result color is
+         * the maximum of the corresponding components of the source and
+         * destination colors. This and Min are useful for applications that
+         * analyze image data (image thresholding against a constant color, for
+         * example). Falls back to Add if supportsMinMax is false.
+         */
+        Max
+    }
+    
+    /**
+     * <code>BlendEquationAlpha</code> specifies the blending equation to
+     * combine pixels for the alpha component.
+     */
+    public enum BlendEquationAlpha {
+        /**
+         * Sets the blend equation to be the same as the one defined by
+         * {@link #blendEquation}.
+         *
+         */
+        InheritColor,
+        /**
+         * Sets the blend equation so that the source and destination data are
+         * added. (Default) Clamps to [0,1] Useful for things like antialiasing
+         * and transparency.
+         */
+        Add,
+        /**
+         * Sets the blend equation so that the source and destination data are
+         * subtracted (Src - Dest). Clamps to [0,1] Falls back to Add if
+         * supportsSubtract is false.
+         */
+        Subtract,
+        /**
+         * Same as Subtract, but the order is reversed (Dst - Src). Clamps to
+         * [0,1] Falls back to Add if supportsSubtract is false.
+         */
+        ReverseSubtract,
+        /**
+         * Sets the blend equation so that the result alpha is the minimum of
+         * the source alpha and destination alpha. This and Max are useful for
+         * applications that analyze image data (image thresholding against a
+         * constant color, for example). Falls back to Add if supportsMinMax is
+         * false.
+         */
+        Min,
+        /**
+         * sSets the blend equation so that the result alpha is the maximum of
+         * the source alpha and destination alpha. This and Min are useful for
+         * applications that analyze image data (image thresholding against a
+         * constant color, for example). Falls back to Add if supportsMinMax is
+         * false.
+         */
+        Max
+    }
 
     /**
      * <code>BlendMode</code> specifies the blending operation to use.
@@ -276,19 +362,16 @@ public class RenderState implements Cloneable, Savable {
     }
 
     static {
-        ADDITIONAL.applyPointSprite = false;
         ADDITIONAL.applyWireFrame = false;
         ADDITIONAL.applyCullMode = false;
         ADDITIONAL.applyDepthWrite = false;
         ADDITIONAL.applyDepthTest = false;
         ADDITIONAL.applyColorWrite = false;
+        ADDITIONAL.applyBlendEquation = false;
+        ADDITIONAL.applyBlendEquationAlpha = false;
         ADDITIONAL.applyBlendMode = false;
-        ADDITIONAL.applyAlphaTest = false;
-        ADDITIONAL.applyAlphaFallOff = false;
         ADDITIONAL.applyPolyOffset = false;
     }
-    boolean pointSprite = false;
-    boolean applyPointSprite = true;
     boolean wireframe = false;
     boolean applyWireFrame = true;
     FaceCullMode cullMode = FaceCullMode.Back;
@@ -299,12 +382,12 @@ public class RenderState implements Cloneable, Savable {
     boolean applyDepthTest = true;
     boolean colorWrite = true;
     boolean applyColorWrite = true;
+    BlendEquation blendEquation = BlendEquation.Add;
+    boolean applyBlendEquation = true;
+    BlendEquationAlpha blendEquationAlpha = BlendEquationAlpha.InheritColor;
+    boolean applyBlendEquationAlpha = true;
     BlendMode blendMode = BlendMode.Off;
     boolean applyBlendMode = true;
-    boolean alphaTest = false;
-    boolean applyAlphaTest = true;
-    float alphaFallOff = 0;
-    boolean applyAlphaFallOff = true;
     float offsetFactor = 0;
     float offsetUnits = 0;
     boolean offsetEnabled = false;
@@ -315,10 +398,7 @@ public class RenderState implements Cloneable, Savable {
     boolean applyLineWidth = false;
     TestFunction depthFunc = TestFunction.LessOrEqual;
     //by default depth func will be applied anyway if depth test is applied
-    boolean applyDepthFunc = false;    
-    //by default alpha func will be applied anyway if alpha test is applied
-    TestFunction alphaFunc = TestFunction.Greater;    
-    boolean applyAlphaFunc = false;
+    boolean applyDepthFunc = false;
     StencilOperation frontStencilStencilFailOperation = StencilOperation.Keep;
     StencilOperation frontStencilDepthFailOperation = StencilOperation.Keep;
     StencilOperation frontStencilDepthPassOperation = StencilOperation.Keep;
@@ -331,15 +411,13 @@ public class RenderState implements Cloneable, Savable {
 
     public void write(JmeExporter ex) throws IOException {
         OutputCapsule oc = ex.getCapsule(this);
-        oc.write(pointSprite, "pointSprite", false);
+        oc.write(true, "pointSprite", false);
         oc.write(wireframe, "wireframe", false);
         oc.write(cullMode, "cullMode", FaceCullMode.Back);
         oc.write(depthWrite, "depthWrite", true);
         oc.write(depthTest, "depthTest", true);
         oc.write(colorWrite, "colorWrite", true);
         oc.write(blendMode, "blendMode", BlendMode.Off);
-        oc.write(alphaTest, "alphaTest", false);
-        oc.write(alphaFallOff, "alphaFallOff", 0);
         oc.write(offsetEnabled, "offsetEnabled", false);
         oc.write(offsetFactor, "offsetFactor", 0);
         oc.write(offsetUnits, "offsetUnits", 0);
@@ -352,38 +430,34 @@ public class RenderState implements Cloneable, Savable {
         oc.write(backStencilDepthPassOperation, "backStencilDepthPassOperation", StencilOperation.Keep);
         oc.write(frontStencilFunction, "frontStencilFunction", TestFunction.Always);
         oc.write(backStencilFunction, "backStencilFunction", TestFunction.Always);
+        oc.write(blendEquation, "blendEquation", BlendEquation.Add);
+        oc.write(blendEquationAlpha, "blendEquationAlpha", BlendEquationAlpha.InheritColor);
         oc.write(depthFunc, "depthFunc", TestFunction.LessOrEqual);
-        oc.write(alphaFunc, "alphaFunc", TestFunction.Greater);
         oc.write(lineWidth, "lineWidth", 1);
 
         // Only "additional render state" has them set to false by default
-        oc.write(applyPointSprite, "applyPointSprite", true);
         oc.write(applyWireFrame, "applyWireFrame", true);
         oc.write(applyCullMode, "applyCullMode", true);
         oc.write(applyDepthWrite, "applyDepthWrite", true);
         oc.write(applyDepthTest, "applyDepthTest", true);
         oc.write(applyColorWrite, "applyColorWrite", true);
+        oc.write(applyBlendEquation, "applyBlendEquation", true);
+        oc.write(applyBlendEquationAlpha, "applyBlendEquationAlpha", true);
         oc.write(applyBlendMode, "applyBlendMode", true);
-        oc.write(applyAlphaTest, "applyAlphaTest", true);
-        oc.write(applyAlphaFallOff, "applyAlphaFallOff", true);
         oc.write(applyPolyOffset, "applyPolyOffset", true);
         oc.write(applyDepthFunc, "applyDepthFunc", true);
-        oc.write(applyAlphaFunc, "applyAlphaFunc", false);
         oc.write(applyLineWidth, "applyLineWidth", true);
 
     }
 
     public void read(JmeImporter im) throws IOException {
         InputCapsule ic = im.getCapsule(this);
-        pointSprite = ic.readBoolean("pointSprite", false);
         wireframe = ic.readBoolean("wireframe", false);
         cullMode = ic.readEnum("cullMode", FaceCullMode.class, FaceCullMode.Back);
         depthWrite = ic.readBoolean("depthWrite", true);
         depthTest = ic.readBoolean("depthTest", true);
         colorWrite = ic.readBoolean("colorWrite", true);
         blendMode = ic.readEnum("blendMode", BlendMode.class, BlendMode.Off);
-        alphaTest = ic.readBoolean("alphaTest", false);
-        alphaFallOff = ic.readFloat("alphaFallOff", 0);
         offsetEnabled = ic.readBoolean("offsetEnabled", false);
         offsetFactor = ic.readFloat("offsetFactor", 0);
         offsetUnits = ic.readFloat("offsetUnits", 0);
@@ -396,23 +470,22 @@ public class RenderState implements Cloneable, Savable {
         backStencilDepthPassOperation = ic.readEnum("backStencilDepthPassOperation", StencilOperation.class, StencilOperation.Keep);
         frontStencilFunction = ic.readEnum("frontStencilFunction", TestFunction.class, TestFunction.Always);
         backStencilFunction = ic.readEnum("backStencilFunction", TestFunction.class, TestFunction.Always);
+        blendEquation = ic.readEnum("blendEquation", BlendEquation.class, BlendEquation.Add);
+        blendEquationAlpha = ic.readEnum("blendEquationAlpha", BlendEquationAlpha.class, BlendEquationAlpha.InheritColor);
         depthFunc = ic.readEnum("depthFunc", TestFunction.class, TestFunction.LessOrEqual);
-        alphaFunc = ic.readEnum("alphaFunc", TestFunction.class, TestFunction.Greater);
         lineWidth = ic.readFloat("lineWidth", 1);
 
 
-        applyPointSprite = ic.readBoolean("applyPointSprite", true);
         applyWireFrame = ic.readBoolean("applyWireFrame", true);
         applyCullMode = ic.readBoolean("applyCullMode", true);
         applyDepthWrite = ic.readBoolean("applyDepthWrite", true);
         applyDepthTest = ic.readBoolean("applyDepthTest", true);
         applyColorWrite = ic.readBoolean("applyColorWrite", true);
+        applyBlendEquation = ic.readBoolean("applyBlendEquation", true);
+        applyBlendEquationAlpha = ic.readBoolean("applyBlendEquationAlpha", true);
         applyBlendMode = ic.readBoolean("applyBlendMode", true);
-        applyAlphaTest = ic.readBoolean("applyAlphaTest", true);
-        applyAlphaFallOff = ic.readBoolean("applyAlphaFallOff", true);
         applyPolyOffset = ic.readBoolean("applyPolyOffset", true);
         applyDepthFunc = ic.readBoolean("applyDepthFunc", true);
-        applyAlphaFunc = ic.readBoolean("applyAlphaFunc", false);
         applyLineWidth = ic.readBoolean("applyLineWidth", true);
 
         
@@ -433,8 +506,8 @@ public class RenderState implements Cloneable, Savable {
     }
 
     /**
-     * returns true if the given renderState is equall to this one
-     * @param o the renderState to compate to
+     * returns true if the given renderState is equal to this one
+     * @param o the renderState to compare to
      * @return true if the renderStates are equal
      */
     @Override
@@ -446,9 +519,6 @@ public class RenderState implements Cloneable, Savable {
             return false;
         }
         RenderState rs = (RenderState) o;
-        if (pointSprite != rs.pointSprite) {
-            return false;
-        }
 
         if (wireframe != rs.wireframe) {
             return false;
@@ -475,23 +545,19 @@ public class RenderState implements Cloneable, Savable {
             return false;
         }
 
-        if (blendMode != rs.blendMode) {
+        if (blendEquation != rs.blendEquation) {
             return false;
         }
 
-        if (alphaTest != rs.alphaTest) {
+        if (blendEquationAlpha != rs.blendEquationAlpha) {
             return false;
         }
-        if (alphaTest) {
-            if (alphaFunc != rs.alphaFunc) {
-                return false;
-            }
-        }
 
-        if (alphaFallOff != rs.alphaFallOff) {
+        if (blendMode != rs.blendMode) {
             return false;
         }
 
+
         if (offsetEnabled != rs.offsetEnabled) {
             return false;
         }
@@ -544,70 +610,30 @@ public class RenderState implements Cloneable, Savable {
     }
 
     /**
-     * Enables point sprite mode.
-     *
-     * <p>When point sprite is enabled, any meshes
-     * with the type of {@link Mode#Points} will be rendered as 2D quads
-     * with texturing enabled. Fragment shaders can write to the
-     * <code>gl_PointCoord</code> variable to manipulate the texture coordinate
-     * for each pixel. The size of the 2D quad can be controlled by writing
-     * to the <code>gl_PointSize</code> variable in the vertex shader.
-     *
-     * @param pointSprite Enables Point Sprite mode.
+     * @deprecated Does nothing. Point sprite is already enabled by default for
+     * all supported platforms. jME3 does not support rendering conventional
+     * point clouds.
      */
+    @Deprecated
     public void setPointSprite(boolean pointSprite) {
-        applyPointSprite = true;
-        this.pointSprite = pointSprite;
-        cachedHashCode = -1;
     }
 
     /**
-     * Sets the alpha fall off value for alpha testing.
-     *
-     * <p>If the pixel's alpha value is greater than the
-     * <code>alphaFallOff</code> then the pixel will be rendered, otherwise
-     * the pixel will be discarded.
-     * 
-     * Note : Alpha test is deprecated since opengl 3.0 and does not exists in
-     * openglES 2.0.
-     * The prefered way is to use the alphaDiscardThreshold on the material
-     * Or have a shader that discards the pixel when its alpha value meets the
-     * discarding condition.
-     *
-     * @param alphaFallOff The alpha of all rendered pixels must be higher
-     * than this value to be rendered. This value should be between 0 and 1.
-     *
-     * @see RenderState#setAlphaTest(boolean)
+     * @deprecated Does nothing. To use alpha test, set the
+     * <code>AlphaDiscardThreshold</code> material parameter.
+     * @param alphaFallOff does nothing
      */
+    @Deprecated
     public void setAlphaFallOff(float alphaFallOff) {
-        applyAlphaFallOff = true;
-        this.alphaFallOff = alphaFallOff;
-        cachedHashCode = -1;
     }
 
     /**
-     * Enable alpha testing.
-     *
-     * <p>When alpha testing is enabled, all input pixels' alpha are compared
-     * to the {@link RenderState#setAlphaFallOff(float) constant alpha falloff}.
-     * If the input alpha is greater than the falloff, the pixel will be rendered,
-     * otherwise it will be discarded.
-     *
-     * @param alphaTest Set to true to enable alpha testing.
-     * 
-     * Note : Alpha test is deprecated since opengl 3.0 and does not exists in
-     * openglES 2.0.
-     * The prefered way is to use the alphaDiscardThreshold on the material
-     * Or have a shader that discards the pixel when its alpha value meets the
-     * discarding condition.
-     * 
-     *
-     * @see RenderState#setAlphaFallOff(float)
+     * @deprecated Does nothing. To use alpha test, set the
+     * <code>AlphaDiscardThreshold</code> material parameter.
+     * @param alphaTest does nothing
      */
+    @Deprecated
     public void setAlphaTest(boolean alphaTest) {
-        applyAlphaTest = true;
-        this.alphaTest = alphaTest;
-        cachedHashCode = -1;
     }
 
     /**
@@ -663,6 +689,61 @@ public class RenderState implements Cloneable, Savable {
         cachedHashCode = -1;
     }
 
+    /**
+     * Set the blending equation.
+     * <p>
+     * When blending is enabled, (<code>blendMode</code> is not
+     * {@link BlendMode#Off}) the input pixel will be blended with the pixel
+     * already in the color buffer. The blending equation is determined by the
+     * {@link BlendEquation}. For example, the mode {@link BlendMode#Additive}
+     * and {@link BlendEquation#Add} will add the input pixel's color to the
+     * color already in the color buffer:
+     * <br/>
+     * <code>Result = Source Color + Destination Color</code>
+     * <br/>
+     * However, the mode {@link BlendMode#Additive}
+     * and {@link BlendEquation#Subtract} will subtract the input pixel's color to the
+     * color already in the color buffer:
+     * <br/>
+     * <code>Result = Source Color - Destination Color</code>
+     *
+     * @param blendEquation The blend equation to use. 
+     */
+    public void setBlendEquation(BlendEquation blendEquation) {
+        applyBlendEquation = true;
+        this.blendEquation = blendEquation;
+        cachedHashCode = -1;
+    }
+    
+    /**
+     * Set the blending equation for the alpha component.
+     * <p>
+     * When blending is enabled, (<code>blendMode</code> is not
+     * {@link BlendMode#Off}) the input pixel will be blended with the pixel
+     * already in the color buffer. The blending equation is determined by the
+     * {@link BlendEquation} and can be overrode for the alpha component using
+     * the {@link BlendEquationAlpha} . For example, the mode
+     * {@link BlendMode#Additive} and {@link BlendEquationAlpha#Add} will add
+     * the input pixel's alpha to the alpha component already in the color
+     * buffer:
+     * <br/>
+     * <code>Result = Source Alpha + Destination Alpha</code>
+     * <br/>
+     * However, the mode {@link BlendMode#Additive} and
+     * {@link BlendEquationAlpha#Subtract} will subtract the input pixel's alpha
+     * to the alpha component already in the color buffer:
+     * <br/>
+     * <code>Result = Source Alpha - Destination Alpha</code>
+     *
+     * @param blendEquationAlpha The blend equation to use for the alpha
+     *                           component.
+     */
+    public void setBlendEquationAlpha(BlendEquationAlpha blendEquationAlpha) {
+        applyBlendEquationAlpha = true;
+        this.blendEquationAlpha = blendEquationAlpha;
+        cachedHashCode = -1;
+    }
+
     /**
      * Enable depth testing.
      *
@@ -796,24 +877,10 @@ public class RenderState implements Cloneable, Savable {
     }
 
     /**
-     * Sets the alpha comparision function to the given TestFunction
-     * default is Greater (GL_GREATER)
-     * 
-     * Note : Alpha test is deprecated since opengl 3.0 and does not exists in
-     * openglES 2.0.
-     * The prefered way is to use the alphaDiscardThreshold on the material
-     * Or have a shader taht discards the pixel when its alpha value meets the
-     * discarding condition.
-     * 
-     * @see TestFunction
-     * @see RenderState#setAlphaTest(boolean) 
-     * @see RenderState#setAlphaFallOff(float) 
-     * @param alphaFunc the alpha comparision function
+     * @deprecated
      */
-    public void setAlphaFunc(TestFunction alphaFunc) {        
-        applyAlphaFunc = true;
-        this.alphaFunc = alphaFunc;
-        cachedHashCode = -1;
+    @Deprecated
+    public void setAlphaFunc(TestFunction alphaFunc) {
     }
 
     /**
@@ -991,6 +1058,24 @@ public class RenderState implements Cloneable, Savable {
         return backStencilFunction;
     }
 
+    /**
+     * Retrieve the blend equation.
+     *
+     * @return the blend equation.
+     */
+    public BlendEquation getBlendEquation() {
+        return blendEquation;
+    }
+    
+    /**
+     * Retrieve the blend equation used for the alpha component.
+     *
+     * @return the blend equation for the alpha component.
+     */
+    public BlendEquationAlpha getBlendEquationAlpha() {
+        return blendEquationAlpha;
+    }
+
     /**
      * Retrieve the blend mode.
      *
@@ -1001,25 +1086,22 @@ public class RenderState implements Cloneable, Savable {
     }
 
     /**
-     * Check if point sprite mode is enabled
-     *
-     * @return True if point sprite mode is enabled.
-     *
-     * @see RenderState#setPointSprite(boolean)
+     * @return true
+     * @deprecated Always returns true since point sprite is always enabled.
+     * @see #setPointSprite(boolean)
      */
+    @Deprecated
     public boolean isPointSprite() {
-        return pointSprite;
+        return true;
     }
 
     /**
-     * Check if alpha test is enabled.
-     *
-     * @return True if alpha test is enabled.
-     *
-     * @see RenderState#setAlphaTest(boolean)
+     * @deprecated To use alpha test, set the <code>AlphaDiscardThreshold</code>
+     * material parameter.
+     * @return false
      */
     public boolean isAlphaTest() {
-        return alphaTest;
+        return false;
     }
 
     /**
@@ -1111,14 +1193,12 @@ public class RenderState implements Cloneable, Savable {
     }
 
     /**
-     * Retrieve the alpha falloff value.
-     *
-     * @return the alpha falloff value.
-     *
-     * @see RenderState#setAlphaFallOff(float)
+     * @return 0
+     * @deprecated
      */
+    @Deprecated
     public float getAlphaFallOff() {
-        return alphaFallOff;
+        return 0f;
     }
 
     /**
@@ -1133,14 +1213,12 @@ public class RenderState implements Cloneable, Savable {
     }
 
     /**
-     * Retrieve the alpha comparison function
-     *
-     * @return the alpha comparison function
-     *
-     * @see RenderState#setAlphaFunc(com.jme3.material.RenderState.TestFunction)
+     * @return {@link TestFunction#Greater}.
+     * @deprecated
      */
+    @Deprecated
     public TestFunction getAlphaFunc() {
-        return alphaFunc;
+        return TestFunction.Greater;
     }
 
     /**
@@ -1153,16 +1231,17 @@ public class RenderState implements Cloneable, Savable {
     }
 
 
-    public boolean isApplyAlphaFallOff() {
-        return applyAlphaFallOff;
+
+    public boolean isApplyBlendMode() {
+        return applyBlendMode;
     }
 
-    public boolean isApplyAlphaTest() {
-        return applyAlphaTest;
+    public boolean isApplyBlendEquation() {
+        return applyBlendEquation;
     }
 
-    public boolean isApplyBlendMode() {
-        return applyBlendMode;
+    public boolean isApplyBlendEquationAlpha() {
+        return applyBlendEquationAlpha;
     }
 
     public boolean isApplyColorWrite() {
@@ -1181,9 +1260,6 @@ public class RenderState implements Cloneable, Savable {
         return applyDepthWrite;
     }
 
-    public boolean isApplyPointSprite() {
-        return applyPointSprite;
-    }
 
     public boolean isApplyPolyOffset() {
         return applyPolyOffset;
@@ -1197,9 +1273,6 @@ public class RenderState implements Cloneable, Savable {
         return applyDepthFunc;
     }
 
-    public boolean isApplyAlphaFunc() {
-        return applyAlphaFunc;
-    }
 
     public boolean isApplyLineWidth() {
         return applyLineWidth;
@@ -1211,7 +1284,6 @@ public class RenderState implements Cloneable, Savable {
     public int contentHashCode() {
         if (cachedHashCode == -1){
             int hash = 7;
-            hash = 79 * hash + (this.pointSprite ? 1 : 0);
             hash = 79 * hash + (this.wireframe ? 1 : 0);
             hash = 79 * hash + (this.cullMode != null ? this.cullMode.hashCode() : 0);
             hash = 79 * hash + (this.depthWrite ? 1 : 0);
@@ -1219,9 +1291,8 @@ public class RenderState implements Cloneable, Savable {
             hash = 79 * hash + (this.depthFunc != null ? this.depthFunc.hashCode() : 0);
             hash = 79 * hash + (this.colorWrite ? 1 : 0);
             hash = 79 * hash + (this.blendMode != null ? this.blendMode.hashCode() : 0);
-            hash = 79 * hash + (this.alphaTest ? 1 : 0);
-            hash = 79 * hash + (this.alphaFunc != null ? this.alphaFunc.hashCode() : 0);
-            hash = 79 * hash + Float.floatToIntBits(this.alphaFallOff);
+            hash = 79 * hash + (this.blendEquation != null ? this.blendEquation.hashCode() : 0);
+            hash = 79 * hash + (this.blendEquationAlpha != null ? this.blendEquationAlpha.hashCode() : 0);
             hash = 79 * hash + Float.floatToIntBits(this.offsetFactor);
             hash = 79 * hash + Float.floatToIntBits(this.offsetUnits);
             hash = 79 * hash + (this.offsetEnabled ? 1 : 0);
@@ -1266,11 +1337,6 @@ public class RenderState implements Cloneable, Savable {
             return this;
         }
 
-        if (additionalState.applyPointSprite) {
-            state.pointSprite = additionalState.pointSprite;
-        } else {
-            state.pointSprite = pointSprite;
-        }
         if (additionalState.applyWireFrame) {
             state.wireframe = additionalState.wireframe;
         } else {
@@ -1302,27 +1368,22 @@ public class RenderState implements Cloneable, Savable {
         } else {
             state.colorWrite = colorWrite;
         }
-        if (additionalState.applyBlendMode) {
-            state.blendMode = additionalState.blendMode;
+        if (additionalState.applyBlendEquation) {
+            state.blendEquation = additionalState.blendEquation;
         } else {
-            state.blendMode = blendMode;
+            state.blendEquation = blendEquation;
         }
-        if (additionalState.applyAlphaTest) {
-            state.alphaTest = additionalState.alphaTest;
+        if (additionalState.applyBlendEquationAlpha) {
+            state.blendEquationAlpha = additionalState.blendEquationAlpha;
         } else {
-            state.alphaTest = alphaTest;
-        }
-        if (additionalState.applyAlphaFunc) {
-            state.alphaFunc = additionalState.alphaFunc;
+            state.blendEquationAlpha = blendEquationAlpha;
+        }        
+        if (additionalState.applyBlendMode) {
+            state.blendMode = additionalState.blendMode;
         } else {
-            state.alphaFunc = alphaFunc;
+            state.blendMode = blendMode;
         }
 
-        if (additionalState.applyAlphaFallOff) {
-            state.alphaFallOff = additionalState.alphaFallOff;
-        } else {
-            state.alphaFallOff = alphaFallOff;
-        }
         if (additionalState.applyPolyOffset) {
             state.offsetEnabled = additionalState.offsetEnabled;
             state.offsetFactor = additionalState.offsetFactor;
@@ -1367,16 +1428,14 @@ public class RenderState implements Cloneable, Savable {
         state.cachedHashCode = -1;
         return state;
     }
-     public void set(RenderState state) {
-        pointSprite = state.pointSprite;
+
+    public void set(RenderState state) {
         wireframe = state.wireframe;
         cullMode = state.cullMode;
         depthWrite = state.depthWrite;
         depthTest = state.depthTest;
         colorWrite = state.colorWrite;
         blendMode = state.blendMode;
-        alphaTest = state.alphaTest;
-        alphaFallOff = state.alphaFallOff;
         offsetEnabled = state.offsetEnabled;
         offsetFactor = state.offsetFactor;
         offsetUnits = state.offsetUnits;
@@ -1389,30 +1448,27 @@ public class RenderState implements Cloneable, Savable {
         backStencilDepthPassOperation = state.backStencilDepthPassOperation;
         frontStencilFunction = state.frontStencilFunction;
         backStencilFunction = state.backStencilFunction;
+        blendEquationAlpha = state.blendEquationAlpha;
+        blendEquation = state.blendEquation;
         depthFunc = state.depthFunc;
-        alphaFunc = state.alphaFunc;
         lineWidth = state.lineWidth;
 
-        applyPointSprite = true;
         applyWireFrame =  true;
         applyCullMode =  true;
         applyDepthWrite =  true;
         applyDepthTest =  true;
         applyColorWrite = true;
-        applyBlendMode =  true;
-        applyAlphaTest =  true;
-        applyAlphaFallOff =  true;
+        applyBlendEquation =  true;
+        applyBlendEquationAlpha =  true;
+        applyBlendMode = true;
         applyPolyOffset =  true;
-        applyDepthFunc =  true;
-        applyAlphaFunc =  false;
+        applyDepthFunc = true;
         applyLineWidth = true;
     }
 
     @Override
     public String toString() {
         return "RenderState[\n"
-                + "pointSprite=" + pointSprite
-                + "\napplyPointSprite=" + applyPointSprite
                 + "\nwireframe=" + wireframe
                 + "\napplyWireFrame=" + applyWireFrame
                 + "\ncullMode=" + cullMode
@@ -1424,13 +1480,11 @@ public class RenderState implements Cloneable, Savable {
                 + "\napplyDepthTest=" + applyDepthTest
                 + "\ncolorWrite=" + colorWrite
                 + "\napplyColorWrite=" + applyColorWrite
+                + "\nblendEquation=" + blendEquation
+                + "\napplyBlendEquation=" + applyBlendEquation
+                + "\napplyBlendEquationAlpha=" + applyBlendEquationAlpha
                 + "\nblendMode=" + blendMode
                 + "\napplyBlendMode=" + applyBlendMode
-                + "\nalphaTest=" + alphaTest
-                + "\nalphaFunc=" + alphaFunc
-                + "\napplyAlphaTest=" + applyAlphaTest
-                + "\nalphaFallOff=" + alphaFallOff
-                + "\napplyAlphaFallOff=" + applyAlphaFallOff
                 + "\noffsetEnabled=" + offsetEnabled
                 + "\napplyPolyOffset=" + applyPolyOffset
                 + "\noffsetFactor=" + offsetFactor

+ 2 - 2
jme3-core/src/main/java/com/jme3/material/Technique.java

@@ -183,8 +183,8 @@ public final class Technique {
      * @return nothing.
      *
      * @deprecated Preset defines are precompiled into
-       * {@link TechniqueDef#getShaderPrologue()}, whereas
-     * dynamic defines are available via {@link #getParamDefines()}.
+     * {@link TechniqueDef#getShaderPrologue()}, whereas dynamic defines are
+     * available via {@link #getParamDefines()}.
      */
     @Deprecated
     public DefineList getAllDefines() {

+ 2 - 3
jme3-core/src/main/java/com/jme3/material/TechniqueDef.java

@@ -155,13 +155,12 @@ public class TechniqueDef implements Savable {
      * <p>
      * Used internally by the J3M/J3MD loader.
      *
-     * @param name The name of the technique, should be set to <code>null</code>
-     * for default techniques.
+     * @param name The name of the technique
      */
     public TechniqueDef(String name, int sortId){
         this();
         this.sortId = sortId;
-        this.name = name == null ? TechniqueDef.DEFAULT_TECHNIQUE_NAME : name;
+        this.name = name;
     }
 
     /**

+ 34 - 9
jme3-core/src/main/java/com/jme3/material/logic/StaticPassLightingLogic.java

@@ -34,12 +34,12 @@ package com.jme3.material.logic;
 import com.jme3.asset.AssetManager;
 import com.jme3.light.DirectionalLight;
 import com.jme3.light.Light;
-import com.jme3.light.Light.Type;
 import com.jme3.light.LightList;
 import com.jme3.light.PointLight;
 import com.jme3.light.SpotLight;
 import com.jme3.material.TechniqueDef;
 import com.jme3.math.ColorRGBA;
+import com.jme3.math.Matrix4f;
 import com.jme3.math.Vector3f;
 import com.jme3.renderer.Caps;
 import com.jme3.renderer.RenderManager;
@@ -72,6 +72,8 @@ public final class StaticPassLightingLogic extends DefaultTechniqueDefLogic {
     private final ArrayList<SpotLight> tempSpotLights = new ArrayList<SpotLight>();
 
     private final ColorRGBA ambientLightColor = new ColorRGBA(0, 0, 0, 1);
+    private final Vector3f tempPosition = new Vector3f();
+    private final Vector3f tempDirection = new Vector3f();
 
     public StaticPassLightingLogic(TechniqueDef techniqueDef) {
         super(techniqueDef);
@@ -113,43 +115,66 @@ public final class StaticPassLightingLogic extends DefaultTechniqueDefLogic {
         return techniqueDef.getShader(assetManager, rendererCaps, defines);
     }
 
-    private void updateLightListUniforms(Shader shader, LightList lights) {
+    private void transformDirection(Matrix4f viewMatrix, Vector3f direction) {
+        viewMatrix.multNormal(direction, direction);
+    }
+
+    private void transformPosition(Matrix4f viewMatrix, Vector3f location) {
+        viewMatrix.mult(location, location);
+    }
+
+    private void updateLightListUniforms(Matrix4f viewMatrix, Shader shader, LightList lights) {
         Uniform ambientColor = shader.getUniform("g_AmbientLightColor");
         ambientColor.setValue(VarType.Vector4, getAmbientColor(lights, true, ambientLightColor));
 
         Uniform lightData = shader.getUniform("g_LightData");
 
+        int totalSize = tempDirLights.size() * 2
+                + tempPointLights.size() * 2
+                + tempSpotLights.size() * 3;
+        lightData.setVector4Length(totalSize);
+
         int index = 0;
         for (DirectionalLight light : tempDirLights) {
             ColorRGBA color = light.getColor();
-            Vector3f dir = light.getDirection();
+            tempDirection.set(light.getDirection());
+            transformDirection(viewMatrix, tempDirection);
             lightData.setVector4InArray(color.r, color.g, color.b, 1f, index++);
-            lightData.setVector4InArray(dir.x, dir.y, dir.z, 1f, index++);
+            lightData.setVector4InArray(tempDirection.x, tempDirection.y, tempDirection.z, 1f, index++);
         }
 
         for (PointLight light : tempPointLights) {
             ColorRGBA color = light.getColor();
-            Vector3f pos = light.getPosition();
+            tempPosition.set(light.getPosition());
+            float invRadius = light.getInvRadius();
+            transformPosition(viewMatrix, tempPosition);
             lightData.setVector4InArray(color.r, color.g, color.b, 1f, index++);
-            lightData.setVector4InArray(pos.x, pos.y, pos.z, 1f, index++);
+            lightData.setVector4InArray(tempPosition.x, tempPosition.y, tempPosition.z, invRadius, index++);
         }
 
         for (SpotLight light : tempSpotLights) {
             ColorRGBA color = light.getColor();
             Vector3f pos = light.getPosition();
             Vector3f dir = light.getDirection();
+
+            tempPosition.set(light.getPosition());
+            tempDirection.set(light.getDirection());
+            transformPosition(viewMatrix, tempPosition);
+            transformDirection(viewMatrix, tempDirection);
+
             float invRange = light.getInvSpotRange();
             float spotAngleCos = light.getPackedAngleCos();
             lightData.setVector4InArray(color.r, color.g, color.b, 1f, index++);
-            lightData.setVector4InArray(pos.x, pos.y, pos.z, invRange, index++);
-            lightData.setVector4InArray(dir.x, dir.y, dir.z, spotAngleCos, index++);
+            lightData.setVector4InArray(tempPosition.x, tempPosition.y, tempPosition.z, invRange, index++);
+            lightData.setVector4InArray(tempDirection.x, tempDirection.y, tempDirection.z, spotAngleCos, index++);
         }
     }
 
     @Override
     public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) {
         Renderer renderer = renderManager.getRenderer();
-        updateLightListUniforms(shader, lights);
+        Matrix4f viewMatrix = renderManager.getCurrentCamera().getViewMatrix();
+        updateLightListUniforms(viewMatrix, shader, lights);
         renderer.setShader(shader);
         renderMeshFromGeometry(renderer, geometry);
     }

+ 6 - 6
jme3-core/src/main/java/com/jme3/renderer/Camera.java

@@ -1005,12 +1005,12 @@ public class Camera implements Savable, Cloneable {
      *
      * NOTE: This method is used internally for culling, for public usage,
      * the plane state of the bounding volume must be saved and restored, e.g:
-     * <code>BoundingVolume bv;<br/>
-     * Camera c;<br/>
-     * int planeState = bv.getPlaneState();<br/>
-     * bv.setPlaneState(0);<br/>
-     * c.contains(bv);<br/>
-     * bv.setPlaneState(plateState);<br/>
+     * <code>BoundingVolume bv;<br>
+     * Camera c;<br>
+     * int planeState = bv.getPlaneState();<br>
+     * bv.setPlaneState(0);<br>
+     * c.contains(bv);<br>
+     * bv.setPlaneState(plateState);<br>
      * </code>
      *
      * @param bound the bound to check for culling

+ 8 - 25
jme3-core/src/main/java/com/jme3/renderer/Limits.java

@@ -32,51 +32,34 @@
 package com.jme3.renderer;
 
 /**
- * <code>Limits</code> allows querying the limits of certain features in 
+ * <code>Limits</code> allows querying the limits of certain features in
  * {@link Renderer}.
  * <p>
  * For example, maximum texture sizes or number of samples.
- * 
+ *
  * @author Kirill Vainer
  */
 public enum Limits {
     /**
-     * Maximum number of vertex texture units, or number of textures
-     * that can be used in the vertex shader.
+     * Maximum number of vertex texture units, or number of textures that can be
+     * used in the vertex shader.
      */
     VertexTextureUnits,
-    
     /**
-     * Maximum number of fragment texture units, or number of textures
-     * that can be used in the fragment shader.
+     * Maximum number of fragment texture units, or number of textures that can
+     * be used in the fragment shader.
      */
     FragmentTextureUnits,
-    
-    FragmentUniforms,
-    
+    FragmentUniformVectors,
+    VertexUniformVectors,
     VertexAttributes,
-    
     FrameBufferSamples,
-    
     FrameBufferAttachments,
-    
     FrameBufferMrtAttachments,
-    
     RenderBufferSize,
-    
     TextureSize,
-    
     CubemapSize,
-    
-    VertexCount,
-    
-    TriangleCount,
-    
     ColorTextureSamples,
-    
     DepthTextureSamples,
-
-    VertexUniformVectors,
-    
     TextureAnisotropy,
 }

+ 11 - 15
jme3-core/src/main/java/com/jme3/renderer/RenderContext.java

@@ -55,16 +55,6 @@ public class RenderContext {
      */
     public boolean depthTestEnabled = false;
 
-    /**
-     * @see RenderState#setAlphaFallOff(float) 
-     */
-    public float alphaTestFallOff = 0f;
-
-    /**
-     * @see RenderState#setAlphaTest(boolean) 
-     */
-    public boolean alphaTestEnabled = false;
-
     /**
      * @see RenderState#setDepthWrite(boolean) 
      */
@@ -111,14 +101,19 @@ public class RenderContext {
     public RenderState.BlendMode blendMode = RenderState.BlendMode.Off;
 
     /**
-     * @see RenderState#setWireframe(boolean) 
+     * @see RenderState#setBlendEquation(com.jme3.material.RenderState.BlendEquation) 
      */
-    public boolean wireframe = false;
+    public RenderState.BlendEquation blendEquation = RenderState.BlendEquation.Add;
+    
+    /**
+     * @see RenderState#setBlendEquationAlpha(com.jme3.material.RenderState.BlendEquationAlpha) 
+     */
+    public RenderState.BlendEquationAlpha blendEquationAlpha = RenderState.BlendEquationAlpha.InheritColor;
 
     /**
-     * @see RenderState#setPointSprite(boolean) 
+     * @see RenderState#setWireframe(boolean) 
      */
-    public boolean pointSprite = false;
+    public boolean wireframe = false;
 
     /**
      * @see Renderer#setShader(com.jme3.shader.Shader) 
@@ -261,7 +256,6 @@ public class RenderContext {
     public void reset(){
         cullMode = RenderState.FaceCullMode.Off;
         depthTestEnabled = false;
-        alphaTestFallOff = 0f;
         depthWriteEnabled = false;
         colorWriteEnabled = false;
         clipRectEnabled = false;
@@ -270,6 +264,8 @@ public class RenderContext {
         polyOffsetUnits = 0;
         pointSize = 1;
         blendMode = RenderState.BlendMode.Off;
+        blendEquation = RenderState.BlendEquation.Add;
+        blendEquationAlpha = RenderState.BlendEquationAlpha.InheritColor;
         wireframe = false;
         boundShaderProgram = 0;
         boundShader = null;

+ 31 - 27
jme3-core/src/main/java/com/jme3/renderer/RenderManager.java

@@ -74,20 +74,19 @@ import java.util.logging.Logger;
 public class RenderManager {
 
     private static final Logger logger = Logger.getLogger(RenderManager.class.getName());
-    private Renderer renderer;
-    private UniformBindingManager uniformBindingManager = new UniformBindingManager();
-    private ArrayList<ViewPort> preViewPorts = new ArrayList<ViewPort>();
-    private ArrayList<ViewPort> viewPorts = new ArrayList<ViewPort>();
-    private ArrayList<ViewPort> postViewPorts = new ArrayList<ViewPort>();
+    private final Renderer renderer;
+    private final UniformBindingManager uniformBindingManager = new UniformBindingManager();
+    private final ArrayList<ViewPort> preViewPorts = new ArrayList<>();
+    private final ArrayList<ViewPort> viewPorts = new ArrayList<>();
+    private final ArrayList<ViewPort> postViewPorts = new ArrayList<>();
     private Camera prevCam = null;
     private Material forcedMaterial = null;
     private String forcedTechnique = null;
     private RenderState forcedRenderState = null;
     private final List<MatParamOverride> forcedOverrides = new ArrayList<>();
     private int viewX, viewY, viewWidth, viewHeight;
-    private Matrix4f orthoMatrix = new Matrix4f();
-    private LightList filteredLightList = new LightList(null);
-    private String tmpTech;
+    private final Matrix4f orthoMatrix = new Matrix4f();
+    private final LightList filteredLightList = new LightList(null);
     private boolean handleTranlucentBucket = true;
     private AppProfiler prof;
     private LightFilter lightFilter = new DefaultLightFilter();
@@ -552,49 +551,54 @@ public class RenderManager {
      * for rendering the material, and the material's own render state is ignored.
      * Otherwise, the material's render state is used as intended.
      * 
-     * @param g The geometry to render
-     * 
+     * @param geom The geometry to render
+       * 
      * @see Technique
      * @see RenderState
      * @see Material#selectTechnique(java.lang.String, com.jme3.renderer.RenderManager) 
      * @see Material#render(com.jme3.scene.Geometry, com.jme3.renderer.RenderManager) 
      */
-    public void renderGeometry(Geometry g) {
-        if (g.isIgnoreTransform()) {
+    public void renderGeometry(Geometry geom) {
+        if (geom.isIgnoreTransform()) {
             setWorldMatrix(Matrix4f.IDENTITY);
         } else {
-            setWorldMatrix(g.getWorldMatrix());
+            setWorldMatrix(geom.getWorldMatrix());
         }
         
         // Perform light filtering if we have a light filter.
-        LightList lightList = g.getWorldLightList();
+        LightList lightList = geom.getWorldLightList();
         
         if (lightFilter != null) {
             filteredLightList.clear();
-            lightFilter.filterLights(g, filteredLightList);
+            lightFilter.filterLights(geom, filteredLightList);
             lightList = filteredLightList;
         }
-        
+
+        Material material = geom.getMaterial();
 
         //if forcedTechnique we try to force it for render,
         //if it does not exists in the mat def, we check for forcedMaterial and render the geom if not null
         //else the geom is not rendered
         if (forcedTechnique != null) {
-            MaterialDef matDef = g.getMaterial().getMaterialDef();
+            MaterialDef matDef = material.getMaterialDef();
             if (matDef.getTechniqueDefs(forcedTechnique) != null) {
-                tmpTech = g.getMaterial().getActiveTechnique() != null
-                        ? g.getMaterial().getActiveTechnique().getDef().getName()
+
+                Technique activeTechnique = material.getActiveTechnique();
+
+                String previousTechniqueName = activeTechnique != null
+                        ? activeTechnique.getDef().getName()
                         : TechniqueDef.DEFAULT_TECHNIQUE_NAME;
-                g.getMaterial().selectTechnique(forcedTechnique, this);
+
+                geom.getMaterial().selectTechnique(forcedTechnique, this);
                 //saving forcedRenderState for future calls
                 RenderState tmpRs = forcedRenderState;
-                if (g.getMaterial().getActiveTechnique().getDef().getForcedRenderState() != null) {
+                if (geom.getMaterial().getActiveTechnique().getDef().getForcedRenderState() != null) {
                     //forcing forced technique renderState
-                    forcedRenderState = g.getMaterial().getActiveTechnique().getDef().getForcedRenderState();
+                    forcedRenderState = geom.getMaterial().getActiveTechnique().getDef().getForcedRenderState();
                 }
                 // use geometry's material
-                g.getMaterial().render(g, lightList, this);
-                g.getMaterial().selectTechnique(tmpTech, this);
+                material.render(geom, lightList, this);
+                material.selectTechnique(previousTechniqueName, this);
 
                 //restoring forcedRenderState
                 forcedRenderState = tmpRs;
@@ -603,13 +607,13 @@ public class RenderManager {
                 //If forcedTechnique does not exists, and forcedMaterial is not set, the geom MUST NOT be rendered
             } else if (forcedMaterial != null) {
                 // use forced material
-                forcedMaterial.render(g, lightList, this);
+                forcedMaterial.render(geom, lightList, this);
             }
         } else if (forcedMaterial != null) {
             // use forced material
-            forcedMaterial.render(g, lightList, this);
+            forcedMaterial.render(geom, lightList, this);
         } else {
-            g.getMaterial().render(g, lightList, this);
+            material.render(geom, lightList, this);
         }
     }
 

+ 23 - 1
jme3-core/src/main/java/com/jme3/renderer/Renderer.java

@@ -43,6 +43,7 @@ import com.jme3.texture.Image;
 import com.jme3.texture.Texture;
 import com.jme3.util.NativeObject;
 import java.nio.ByteBuffer;
+import java.util.EnumMap;
 import java.util.EnumSet;
 
 /**
@@ -66,6 +67,13 @@ public interface Renderer {
      */
     public EnumSet<Caps> getCaps();
 
+    /**
+     * Get the limits of the renderer.
+     *
+     * @return The limits of the renderer.
+     */
+    public EnumMap<Limits, Integer> getLimits();
+
     /**
      * The statistics allow tracking of how data
      * per frame, such as number of objects rendered, number of triangles, etc.
@@ -302,7 +310,21 @@ public interface Renderer {
      * @see NativeObject#deleteObject(java.lang.Object) 
      */
     public void cleanup();
-    
+
+    /**
+     * Set the default anisotropic filter level for textures.
+     *
+     * If the
+     * {@link Texture#setAnisotropicFilter(int) texture anisotropic filter} is
+     * set to 0, then the default level is used. Otherwise if the texture level
+     * is 1 or greater, then the texture's value overrides the default value.
+     *
+     * @param level The default anisotropic filter level to use. Default: 1.
+     *
+     * @throws IllegalArgumentException If level is less than 1.
+     */
+    public void setDefaultAnisotropicFilter(int level);
+
     /**
      * Sets the alpha to coverage state.
      * <p>

+ 144 - 136
jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java

@@ -45,142 +45,149 @@ import java.nio.ShortBuffer;
  */
 public interface GL {
 
-	public static final int GL_ALPHA = 0x1906;
-	public static final int GL_ALWAYS = 0x207;
-	public static final int GL_ARRAY_BUFFER = 0x8892;
-	public static final int GL_BACK = 0x405;
-	public static final int GL_BLEND = 0xBE2;
-	public static final int GL_BYTE = 0x1400;
-	public static final int GL_CLAMP_TO_EDGE = 0x812F;
-	public static final int GL_COLOR_BUFFER_BIT = 0x4000;
-	public static final int GL_COMPILE_STATUS = 0x8B81;
-	public static final int GL_CULL_FACE = 0xB44;
-	public static final int GL_DECR = 0x1E03;
-	public static final int GL_DECR_WRAP = 0x8508;
-	public static final int GL_DEPTH_BUFFER_BIT = 0x100;
-	public static final int GL_DEPTH_COMPONENT = 0x1902;
-	public static final int GL_DEPTH_COMPONENT16 = 0x81A5;
-	public static final int GL_DEPTH_TEST = 0xB71;
-	public static final int GL_DOUBLE = 0x140A;
-	public static final int GL_DST_COLOR = 0x306;
-	public static final int GL_DYNAMIC_DRAW = 0x88E8;
-	public static final int GL_ELEMENT_ARRAY_BUFFER = 0x8893;
-	public static final int GL_EQUAL = 0x202;
-	public static final int GL_EXTENSIONS = 0x1F03;
-	public static final int GL_FALSE = 0x0;
-	public static final int GL_FLOAT = 0x1406;
-	public static final int GL_FRAGMENT_SHADER = 0x8B30;
-	public static final int GL_FRONT = 0x404;
-	public static final int GL_FRONT_AND_BACK = 0x408;
-	public static final int GL_GEQUAL = 0x206;
-	public static final int GL_GREATER = 0x204;
-        public static final int GL_GREEN = 0x1904;
-	public static final int GL_INCR = 0x1E02;
-	public static final int GL_INCR_WRAP = 0x8507;
-	public static final int GL_INFO_LOG_LENGTH = 0x8B84;
-	public static final int GL_INT = 0x1404;
-        public static final int GL_INVALID_ENUM = 0x500;
-        public static final int GL_INVALID_VALUE = 0x501;
-        public static final int GL_INVALID_OPERATION = 0x502;
-	public static final int GL_INVERT = 0x150A;
-	public static final int GL_KEEP = 0x1E00;
-	public static final int GL_LEQUAL = 0x203;
-	public static final int GL_LESS = 0x201;
-	public static final int GL_LINEAR = 0x2601;
-	public static final int GL_LINEAR_MIPMAP_LINEAR = 0x2703;
-	public static final int GL_LINEAR_MIPMAP_NEAREST = 0x2701;
-	public static final int GL_LINES = 0x1;
-	public static final int GL_LINE_LOOP = 0x2;
-	public static final int GL_LINE_STRIP = 0x3;
-	public static final int GL_LINK_STATUS = 0x8B82;
-	public static final int GL_LUMINANCE = 0x1909;
-	public static final int GL_LUMINANCE_ALPHA = 0x190A;
-	public static final int GL_MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C;
-	public static final int GL_MAX_TEXTURE_IMAGE_UNITS = 0x8872;
-	public static final int GL_MAX_TEXTURE_SIZE = 0xD33;
-	public static final int GL_MAX_VERTEX_ATTRIBS = 0x8869;
-	public static final int GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C;
-	public static final int GL_MAX_VERTEX_UNIFORM_COMPONENTS  = 0x8B4A;
-	public static final int GL_MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB;
-	public static final int GL_MIRRORED_REPEAT = 0x8370;
-	public static final int GL_NEAREST = 0x2600;
-	public static final int GL_NEAREST_MIPMAP_LINEAR = 0x2702;
-	public static final int GL_NEAREST_MIPMAP_NEAREST = 0x2700;
-	public static final int GL_NEVER = 0x200;
-        public static final int GL_NO_ERROR = 0x0;
-	public static final int GL_NONE = 0x0;
-	public static final int GL_NOTEQUAL = 0x205;
-	public static final int GL_ONE = 0x1;
-	public static final int GL_ONE_MINUS_DST_COLOR = 0x307;
-	public static final int GL_ONE_MINUS_SRC_ALPHA = 0x303;
-	public static final int GL_ONE_MINUS_SRC_COLOR = 0x301;
-        public static final int GL_OUT_OF_MEMORY = 0x505;
-	public static final int GL_POINTS = 0x0;
-	public static final int GL_POLYGON_OFFSET_FILL = 0x8037;
-        public static final int GL_RED = 0x1903;
-        public static final int GL_RENDERER = 0x1F01;
-	public static final int GL_REPEAT = 0x2901;
-	public static final int GL_REPLACE = 0x1E01;
-	public static final int GL_RGB = 0x1907;
-        public static final int GL_RGB565 = 0x8D62;
-        public static final int GL_RGB5_A1 = 0x8057;
-	public static final int GL_RGBA = 0x1908;
-        public static final int GL_RGBA4 = 0x8056;
-	public static final int GL_SCISSOR_TEST = 0xC11;
-	public static final int GL_SHADING_LANGUAGE_VERSION = 0x8B8C;
-	public static final int GL_SHORT = 0x1402;
-	public static final int GL_SRC_ALPHA = 0x302;
-	public static final int GL_SRC_COLOR = 0x300;
-	public static final int GL_STATIC_DRAW = 0x88E4;
-	public static final int GL_STENCIL_BUFFER_BIT = 0x400;
-	public static final int GL_STENCIL_TEST = 0xB90;
-	public static final int GL_STREAM_DRAW = 0x88E0;
-        public static final int GL_STREAM_READ = 0x88E1;
-	public static final int GL_TEXTURE = 0x1702;
-	public static final int GL_TEXTURE0 = 0x84C0;
-        public static final int GL_TEXTURE1 = 0x84C1;
-        public static final int GL_TEXTURE2 = 0x84C2;
-        public static final int GL_TEXTURE3 = 0x84C3;
-        public static final int GL_TEXTURE4 = 0x84C4;
-        public static final int GL_TEXTURE5 = 0x84C5;
-        public static final int GL_TEXTURE6 = 0x84C6;
-        public static final int GL_TEXTURE7 = 0x84C7;
-        public static final int GL_TEXTURE8 = 0x84C8;
-        public static final int GL_TEXTURE9 = 0x84C9;
-        public static final int GL_TEXTURE10 = 0x84CA;
-        public static final int GL_TEXTURE11 = 0x84CB;
-        public static final int GL_TEXTURE12 = 0x84CC;
-        public static final int GL_TEXTURE13 = 0x84CD;
-        public static final int GL_TEXTURE14 = 0x84CE;
-        public static final int GL_TEXTURE15 = 0x84CF;
-	public static final int GL_TEXTURE_2D = 0xDE1;
-	public static final int GL_TEXTURE_CUBE_MAP = 0x8513;
-	public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;
-        public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;
-        public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;
-        public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;
-        public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;
-        public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A;
-        public static final int GL_TEXTURE_BASE_LEVEL = 0x813C;
-	public static final int GL_TEXTURE_MAG_FILTER = 0x2800;
-	public static final int GL_TEXTURE_MAX_LEVEL = 0x813D;
-	public static final int GL_TEXTURE_MIN_FILTER = 0x2801;
-	public static final int GL_TEXTURE_WRAP_S = 0x2802;
-	public static final int GL_TEXTURE_WRAP_T = 0x2803;
-	public static final int GL_TRIANGLES = 0x4;
-	public static final int GL_TRIANGLE_FAN = 0x6;
-	public static final int GL_TRIANGLE_STRIP = 0x5;
-	public static final int GL_TRUE = 0x1;
-	public static final int GL_UNPACK_ALIGNMENT = 0xCF5;
-	public static final int GL_UNSIGNED_BYTE = 0x1401;
-	public static final int GL_UNSIGNED_INT = 0x1405;
-	public static final int GL_UNSIGNED_SHORT = 0x1403;
-        public static final int GL_UNSIGNED_SHORT_5_6_5 = 0x8363;
-	public static final int GL_UNSIGNED_SHORT_5_5_5_1 = 0x8034;
-        public static final int GL_VENDOR = 0x1F00;
-	public static final int GL_VERSION = 0x1F02;
-	public static final int GL_VERTEX_SHADER = 0x8B31;
-	public static final int GL_ZERO = 0x0;
+    public static final int GL_ALPHA = 0x1906;
+    public static final int GL_ALWAYS = 0x207;
+    public static final int GL_ARRAY_BUFFER = 0x8892;
+    public static final int GL_BACK = 0x405;
+    public static final int GL_BLEND = 0xBE2;
+    public static final int GL_BYTE = 0x1400;
+    public static final int GL_CLAMP_TO_EDGE = 0x812F;
+    public static final int GL_COLOR_BUFFER_BIT = 0x4000;
+    public static final int GL_COMPILE_STATUS = 0x8B81;
+    public static final int GL_CULL_FACE = 0xB44;
+    public static final int GL_DECR = 0x1E03;
+    public static final int GL_DECR_WRAP = 0x8508;
+    public static final int GL_DEPTH_BUFFER_BIT = 0x100;
+    public static final int GL_DEPTH_COMPONENT = 0x1902;
+    public static final int GL_DEPTH_COMPONENT16 = 0x81A5;
+    public static final int GL_DEPTH_TEST = 0xB71;
+    public static final int GL_DOUBLE = 0x140A;
+    public static final int GL_DST_COLOR = 0x306;
+    public static final int GL_DYNAMIC_DRAW = 0x88E8;
+    public static final int GL_ELEMENT_ARRAY_BUFFER = 0x8893;
+    public static final int GL_EQUAL = 0x202;
+    public static final int GL_EXTENSIONS = 0x1F03;
+    public static final int GL_FALSE = 0x0;
+    public static final int GL_FLOAT = 0x1406;
+    public static final int GL_FRAGMENT_SHADER = 0x8B30;
+    public static final int GL_FRONT = 0x404;
+    public static final int GL_FUNC_ADD = 0x8006;
+    public static final int GL_FUNC_SUBTRACT = 0x800A;
+    public static final int GL_FUNC_REVERSE_SUBTRACT = 0x800B;
+    public static final int GL_FRONT_AND_BACK = 0x408;
+    public static final int GL_GEQUAL = 0x206;
+    public static final int GL_GREATER = 0x204;
+    public static final int GL_GREEN = 0x1904;
+    public static final int GL_INCR = 0x1E02;
+    public static final int GL_INCR_WRAP = 0x8507;
+    public static final int GL_INFO_LOG_LENGTH = 0x8B84;
+    public static final int GL_INT = 0x1404;
+    public static final int GL_INVALID_ENUM = 0x500;
+    public static final int GL_INVALID_VALUE = 0x501;
+    public static final int GL_INVALID_OPERATION = 0x502;
+    public static final int GL_INVERT = 0x150A;
+    public static final int GL_KEEP = 0x1E00;
+    public static final int GL_LEQUAL = 0x203;
+    public static final int GL_LESS = 0x201;
+    public static final int GL_LINEAR = 0x2601;
+    public static final int GL_LINEAR_MIPMAP_LINEAR = 0x2703;
+    public static final int GL_LINEAR_MIPMAP_NEAREST = 0x2701;
+    public static final int GL_LINES = 0x1;
+    public static final int GL_LINE_LOOP = 0x2;
+    public static final int GL_LINE_STRIP = 0x3;
+    public static final int GL_LINK_STATUS = 0x8B82;
+    public static final int GL_LUMINANCE = 0x1909;
+    public static final int GL_LUMINANCE_ALPHA = 0x190A;
+    public static final int GL_MAX = 0x8008;
+    public static final int GL_MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C;
+    public static final int GL_MAX_FRAGMENT_UNIFORM_COMPONENTS = 0x8B49;
+    public static final int GL_MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD;
+    public static final int GL_MAX_TEXTURE_IMAGE_UNITS = 0x8872;
+    public static final int GL_MAX_TEXTURE_SIZE = 0xD33;
+    public static final int GL_MAX_VERTEX_ATTRIBS = 0x8869;
+    public static final int GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C;
+    public static final int GL_MAX_VERTEX_UNIFORM_COMPONENTS = 0x8B4A;
+    public static final int GL_MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB;
+    public static final int GL_MIRRORED_REPEAT = 0x8370;
+    public static final int GL_MIN = 0x8007;
+    public static final int GL_NEAREST = 0x2600;
+    public static final int GL_NEAREST_MIPMAP_LINEAR = 0x2702;
+    public static final int GL_NEAREST_MIPMAP_NEAREST = 0x2700;
+    public static final int GL_NEVER = 0x200;
+    public static final int GL_NO_ERROR = 0x0;
+    public static final int GL_NONE = 0x0;
+    public static final int GL_NOTEQUAL = 0x205;
+    public static final int GL_ONE = 0x1;
+    public static final int GL_ONE_MINUS_DST_COLOR = 0x307;
+    public static final int GL_ONE_MINUS_SRC_ALPHA = 0x303;
+    public static final int GL_ONE_MINUS_SRC_COLOR = 0x301;
+    public static final int GL_OUT_OF_MEMORY = 0x505;
+    public static final int GL_POINTS = 0x0;
+    public static final int GL_POLYGON_OFFSET_FILL = 0x8037;
+    public static final int GL_RED = 0x1903;
+    public static final int GL_RENDERER = 0x1F01;
+    public static final int GL_REPEAT = 0x2901;
+    public static final int GL_REPLACE = 0x1E01;
+    public static final int GL_RGB = 0x1907;
+    public static final int GL_RGB565 = 0x8D62;
+    public static final int GL_RGB5_A1 = 0x8057;
+    public static final int GL_RGBA = 0x1908;
+    public static final int GL_RGBA4 = 0x8056;
+    public static final int GL_SCISSOR_TEST = 0xC11;
+    public static final int GL_SHADING_LANGUAGE_VERSION = 0x8B8C;
+    public static final int GL_SHORT = 0x1402;
+    public static final int GL_SRC_ALPHA = 0x302;
+    public static final int GL_SRC_COLOR = 0x300;
+    public static final int GL_STATIC_DRAW = 0x88E4;
+    public static final int GL_STENCIL_BUFFER_BIT = 0x400;
+    public static final int GL_STENCIL_TEST = 0xB90;
+    public static final int GL_STREAM_DRAW = 0x88E0;
+    public static final int GL_STREAM_READ = 0x88E1;
+    public static final int GL_TEXTURE = 0x1702;
+    public static final int GL_TEXTURE0 = 0x84C0;
+    public static final int GL_TEXTURE1 = 0x84C1;
+    public static final int GL_TEXTURE2 = 0x84C2;
+    public static final int GL_TEXTURE3 = 0x84C3;
+    public static final int GL_TEXTURE4 = 0x84C4;
+    public static final int GL_TEXTURE5 = 0x84C5;
+    public static final int GL_TEXTURE6 = 0x84C6;
+    public static final int GL_TEXTURE7 = 0x84C7;
+    public static final int GL_TEXTURE8 = 0x84C8;
+    public static final int GL_TEXTURE9 = 0x84C9;
+    public static final int GL_TEXTURE10 = 0x84CA;
+    public static final int GL_TEXTURE11 = 0x84CB;
+    public static final int GL_TEXTURE12 = 0x84CC;
+    public static final int GL_TEXTURE13 = 0x84CD;
+    public static final int GL_TEXTURE14 = 0x84CE;
+    public static final int GL_TEXTURE15 = 0x84CF;
+    public static final int GL_TEXTURE_2D = 0xDE1;
+    public static final int GL_TEXTURE_CUBE_MAP = 0x8513;
+    public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;
+    public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;
+    public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;
+    public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;
+    public static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;
+    public static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A;
+    public static final int GL_TEXTURE_BASE_LEVEL = 0x813C;
+    public static final int GL_TEXTURE_MAG_FILTER = 0x2800;
+    public static final int GL_TEXTURE_MAX_LEVEL = 0x813D;
+    public static final int GL_TEXTURE_MIN_FILTER = 0x2801;
+    public static final int GL_TEXTURE_WRAP_S = 0x2802;
+    public static final int GL_TEXTURE_WRAP_T = 0x2803;
+    public static final int GL_TRIANGLES = 0x4;
+    public static final int GL_TRIANGLE_FAN = 0x6;
+    public static final int GL_TRIANGLE_STRIP = 0x5;
+    public static final int GL_TRUE = 0x1;
+    public static final int GL_UNPACK_ALIGNMENT = 0xCF5;
+    public static final int GL_UNSIGNED_BYTE = 0x1401;
+    public static final int GL_UNSIGNED_INT = 0x1405;
+    public static final int GL_UNSIGNED_SHORT = 0x1403;
+    public static final int GL_UNSIGNED_SHORT_5_6_5 = 0x8363;
+    public static final int GL_UNSIGNED_SHORT_5_5_5_1 = 0x8034;
+    public static final int GL_VENDOR = 0x1F00;
+    public static final int GL_VERSION = 0x1F02;
+    public static final int GL_VERTEX_SHADER = 0x8B31;
+    public static final int GL_ZERO = 0x0;
 
         public void resetStats();
         
@@ -188,6 +195,7 @@ public interface GL {
 	public void glAttachShader(int program, int shader);
 	public void glBindBuffer(int target, int buffer);
 	public void glBindTexture(int target, int texture);
+	public void glBlendEquationSeparate(int colorMode, int alphaMode);
 	public void glBlendFunc(int sfactor, int dfactor);
         public void glBufferData(int target, long data_size, int usage);
 	public void glBufferData(int target, FloatBuffer data, int usage);

+ 5 - 0
jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java

@@ -100,4 +100,9 @@ public class GLDebugDesktop extends GLDebugES implements GL2, GL3, GL4 {
         gl3.glFramebufferTextureLayer(param1, param2, param3, param4, param5);
         checkError();
     }
+
+    public void glBlendEquationSeparate(int colorMode, int alphaMode) {
+        gl.glBlendEquationSeparate(colorMode, alphaMode);
+        checkError();
+    }
 }

+ 5 - 0
jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java

@@ -560,4 +560,9 @@ public class GLDebugES extends GLDebug implements GL, GLFbo, GLExt {
         checkError();
         return sync;
     }
+
+    public void glBlendEquationSeparate(int colorMode, int alphaMode) {
+        gl.glBlendEquationSeparate(colorMode, alphaMode);
+        checkError();
+    }
 }

+ 68 - 11
jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java

@@ -90,6 +90,7 @@ public final class GLRenderer implements Renderer {
     private final Statistics statistics = new Statistics();
     private int vpX, vpY, vpW, vpH;
     private int clipX, clipY, clipW, clipH;
+    private int defaultAnisotropicFilter = 1;
     private boolean linearizeSrgbImages;
     private HashSet<String> extensions;
 
@@ -252,18 +253,14 @@ public final class GLRenderer implements Renderer {
 
         limits.put(Limits.FragmentTextureUnits, getInteger(GL.GL_MAX_TEXTURE_IMAGE_UNITS));
 
-//        gl.glGetInteger(GL.GL_MAX_VERTEX_UNIFORM_COMPONENTS, intBuf16);
-//        vertexUniforms = intBuf16.get(0);
-//        logger.log(Level.FINER, "Vertex Uniforms: {0}", vertexUniforms);
-//
-//        gl.glGetInteger(GL.GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, intBuf16);
-//        fragUniforms = intBuf16.get(0);
-//        logger.log(Level.FINER, "Fragment Uniforms: {0}", fragUniforms);
         if (caps.contains(Caps.OpenGLES20)) {
+            limits.put(Limits.FragmentUniformVectors, getInteger(GL.GL_MAX_FRAGMENT_UNIFORM_VECTORS));
             limits.put(Limits.VertexUniformVectors, getInteger(GL.GL_MAX_VERTEX_UNIFORM_VECTORS));
         } else {
+            limits.put(Limits.FragmentUniformVectors, getInteger(GL.GL_MAX_FRAGMENT_UNIFORM_COMPONENTS) / 4);
             limits.put(Limits.VertexUniformVectors, getInteger(GL.GL_MAX_VERTEX_UNIFORM_COMPONENTS) / 4);
         }
+
         limits.put(Limits.VertexAttributes, getInteger(GL.GL_MAX_VERTEX_ATTRIBS));
         limits.put(Limits.TextureSize, getInteger(GL.GL_MAX_TEXTURE_SIZE));
         limits.put(Limits.CubemapSize, getInteger(GL.GL_MAX_CUBE_MAP_TEXTURE_SIZE));
@@ -533,7 +530,6 @@ public final class GLRenderer implements Renderer {
             gl2.glEnable(GL2.GL_VERTEX_PROGRAM_POINT_SIZE);
             if (!caps.contains(Caps.CoreProfile)) {
                 gl2.glEnable(GL2.GL_POINT_SPRITE);
-                context.pointSprite = true;
             }
         }
     }
@@ -605,6 +601,14 @@ public final class GLRenderer implements Renderer {
         }
     }
 
+    @Override
+    public void setDefaultAnisotropicFilter(int level) {
+        if (level < 1) {
+            throw new IllegalArgumentException("level cannot be less than 1");
+        }
+        this.defaultAnisotropicFilter = level;
+    }
+
     public void setAlphaToCoverage(boolean value) {
         if (caps.contains(Caps.Multisample)) {
             if (value) {
@@ -746,6 +750,19 @@ public final class GLRenderer implements Renderer {
                         throw new UnsupportedOperationException("Unrecognized blend mode: "
                                 + state.getBlendMode());
                 }
+                
+                if (state.getBlendEquation() != context.blendEquation || state.getBlendEquationAlpha() != context.blendEquationAlpha) {
+                    int colorMode = convertBlendEquation(state.getBlendEquation());
+                    int alphaMode;
+                    if (state.getBlendEquationAlpha() == RenderState.BlendEquationAlpha.InheritColor) {
+                        alphaMode = colorMode;
+                    } else {
+                        alphaMode = convertBlendEquationAlpha(state.getBlendEquationAlpha());
+                    }
+                    gl.glBlendEquationSeparate(colorMode, alphaMode);
+                    context.blendEquation = state.getBlendEquation();
+                    context.blendEquationAlpha = state.getBlendEquationAlpha();
+                }
             }
 
             context.blendMode = state.getBlendMode();
@@ -796,6 +813,41 @@ public final class GLRenderer implements Renderer {
         }
     }
 
+    private int convertBlendEquation(RenderState.BlendEquation blendEquation) {
+        switch (blendEquation) {
+            case Add:
+                return GL2.GL_FUNC_ADD;
+            case Subtract:
+                return GL2.GL_FUNC_SUBTRACT;
+            case ReverseSubtract:
+                return GL2.GL_FUNC_REVERSE_SUBTRACT;
+            case Min:
+                return GL2.GL_MIN;
+            case Max:
+                return GL2.GL_MAX;
+            default:
+                throw new UnsupportedOperationException("Unrecognized blend operation: " + blendEquation);
+        }
+    }
+    
+    private int convertBlendEquationAlpha(RenderState.BlendEquationAlpha blendEquationAlpha) {
+        //Note: InheritColor mode should already be handled, that is why it does not belong the the switch case.
+        switch (blendEquationAlpha) {
+            case Add:
+                return GL2.GL_FUNC_ADD;
+            case Subtract:
+                return GL2.GL_FUNC_SUBTRACT;
+            case ReverseSubtract:
+                return GL2.GL_FUNC_REVERSE_SUBTRACT;
+            case Min:
+                return GL2.GL_MIN;
+            case Max:
+                return GL2.GL_MAX;
+            default:
+                throw new UnsupportedOperationException("Unrecognized alpha blend operation: " + blendEquationAlpha);
+        }
+    }
+
     private int convertStencilOperation(StencilOperation stencilOp) {
         switch (stencilOp) {
             case Keep:
@@ -1883,13 +1935,18 @@ public final class GLRenderer implements Renderer {
             gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, convertMinFilter(tex.getMinFilter(), haveMips));
             curState.minFilter = tex.getMinFilter();
         }
+
+        int desiredAnisoFilter = tex.getAnisotropicFilter() == 0
+                ? defaultAnisotropicFilter
+                : tex.getAnisotropicFilter();
+
         if (caps.contains(Caps.TextureFilterAnisotropic)
-                && curState.anisoFilter != tex.getAnisotropicFilter()) {
+                && curState.anisoFilter != desiredAnisoFilter) {
             bindTextureAndUnit(target, image, unit);
             gl.glTexParameterf(target,
                     GLExt.GL_TEXTURE_MAX_ANISOTROPY_EXT,
-                    tex.getAnisotropicFilter());
-            curState.anisoFilter = tex.getAnisotropicFilter();
+                    desiredAnisoFilter);
+            curState.anisoFilter = desiredAnisoFilter;
         }
 
         switch (tex.getType()) {

+ 9 - 11
jme3-core/src/main/java/com/jme3/scene/Mesh.java

@@ -589,28 +589,26 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
     }
 
     /**
-     * Returns the size of points for point meshes
+     * @deprecated Always returns <code>1.0</code> since point size is
+     * determined in the vertex shader.
      *
-     * @return the size of points
+     * @return <code>1.0</code>
      *
      * @see #setPointSize(float)
      */
+    @Deprecated
     public float getPointSize() {
-        return pointSize;
+        return 1.0f;
     }
 
     /**
-     * Set the size of points for meshes of mode {@link Mode#Points}.
-     * The point size is specified as on-screen pixels, the default
-     * value is 1.0. The point size
-     * does nothing if {@link RenderState#setPointSprite(boolean) point sprite}
-     * render state is enabled, in that case, the vertex shader must specify the
-     * point size by writing to <code>gl_PointSize</code>.
+     * @deprecated Does nothing, since the size of {@link Mode#Points points} is
+     * determined via the vertex shader's <code>gl_PointSize</code> output.
      *
-     * @param pointSize The size of points
+     * @param pointSize ignored
      */
+    @Deprecated
     public void setPointSize(float pointSize) {
-        this.pointSize = pointSize;
     }
 
     /**

+ 1 - 2
jme3-core/src/main/java/com/jme3/scene/VertexBuffer.java

@@ -108,8 +108,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
          * Do not use.
          */
         @Deprecated
-        MiscAttrib,
-
+        Reserved0,
         /**
          * Specifies the index buffer, must contain integer data
          * (ubyte, ushort, or uint).

+ 0 - 8
jme3-core/src/main/java/com/jme3/scene/debug/WireBox.java

@@ -101,14 +101,6 @@ public class WireBox extends Mesh {
         );
         updateBound();
     }
-
-    /**
-     * Old method retained for compatibility: use makeGeometry instead.
-     */
-    @Deprecated
-    public void fromBoundingBox(BoundingBox bbox) {
-        updatePositions(bbox.getXExtent(), bbox.getYExtent(), bbox.getZExtent());
-    }
     
     /**
      * Create a geometry suitable for visualizing the specified bounding box.

+ 1 - 6
jme3-core/src/main/java/com/jme3/shadow/AbstractShadowRenderer.java

@@ -330,12 +330,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor, Savable
     public void initialize(RenderManager rm, ViewPort vp) {
         renderManager = rm;
         viewPort = vp;
-        //checking for caps to chosse the appropriate post material technique
-        if (renderManager.getRenderer().getCaps().contains(Caps.GLSL150)) {
-            postTechniqueName = "PostShadow15";
-        } else {
-            postTechniqueName = "PostShadow";
-        }
+        postTechniqueName = "PostShadow";
         if(zFarOverride>0 && frustumCam == null){
             initFrustumCam();
         }

+ 1 - 6
jme3-core/src/main/java/com/jme3/shadow/PssmShadowRenderer.java

@@ -355,12 +355,7 @@ public class PssmShadowRenderer implements SceneProcessor {
     public void initialize(RenderManager rm, ViewPort vp) {
         renderManager = rm;
         viewPort = vp;
-        //checking for caps to chosse the appropriate post material technique
-        if (renderManager.getRenderer().getCaps().contains(Caps.GLSL150)) {
-            postTechniqueName = "PostShadow15";
-        } else {
-            postTechniqueName = "PostShadow";
-        }
+        postTechniqueName = "PostShadow";
     }
 
     public boolean isInitialized() {

+ 17 - 3
jme3-core/src/main/java/com/jme3/system/NullRenderer.java

@@ -39,6 +39,7 @@ import com.jme3.material.RenderState;
 import com.jme3.math.ColorRGBA;
 import com.jme3.math.Matrix4f;
 import com.jme3.renderer.Caps;
+import com.jme3.renderer.Limits;
 import com.jme3.renderer.Renderer;
 import com.jme3.renderer.Statistics;
 import com.jme3.scene.Mesh;
@@ -48,15 +49,25 @@ import com.jme3.shader.Shader.ShaderSource;
 import com.jme3.texture.FrameBuffer;
 import com.jme3.texture.Image;
 import com.jme3.texture.Texture;
+import java.util.EnumMap;
 
 public class NullRenderer implements Renderer {
 
-    private static final EnumSet<Caps> caps = EnumSet.allOf(Caps.class);
-    private static final Statistics stats = new Statistics();
+    private final EnumSet<Caps> caps = EnumSet.allOf(Caps.class);
+    private final EnumMap<Limits, Integer> limits = new EnumMap<>(Limits.class);
+    private final Statistics stats = new Statistics();
 
     public void initialize() {
+        for (Limits limit : Limits.values()) {
+            limits.put(limit, Integer.MAX_VALUE);
+        }
     }
-    
+
+    @Override
+    public EnumMap<Limits, Integer> getLimits() {
+        return limits;
+    }
+
     public EnumSet<Caps> getCaps() {
         return caps;
     }
@@ -164,4 +175,7 @@ public class NullRenderer implements Renderer {
     public void readFrameBufferWithFormat(FrameBuffer fb, ByteBuffer byteBuf, Image.Format format) {        
     }
 
+    @Override
+    public void setDefaultAnisotropicFilter(int level) {
+    }
 }

+ 1 - 1
jme3-core/src/main/java/com/jme3/texture/image/LastTextureState.java

@@ -58,7 +58,7 @@ public final class LastTextureState {
         rWrap = null;
         magFilter = null;
         minFilter = null;
-        anisoFilter = 0;
+        anisoFilter = 1;
         
         // The default in OpenGL is OFF, so we avoid setting this per texture
         // if its not used.

+ 1 - 1
jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.j3md

@@ -218,7 +218,7 @@ MaterialDef Phong Lighting {
     }
 
 
-    Technique PostShadow15{
+    Technique PostShadow {
         VertexShader GLSL150:   Common/MatDefs/Shadow/PostShadow.vert
         FragmentShader GLSL150: Common/MatDefs/Shadow/PostShadow.frag
 

+ 2 - 2
jme3-core/src/main/resources/Common/MatDefs/Misc/Unshaded.j3md

@@ -148,7 +148,7 @@ MaterialDef Unshaded {
     }
 
 
-    Technique PostShadow15{
+    Technique PostShadow {
         VertexShader GLSL150:   Common/MatDefs/Shadow/PostShadow.vert
         FragmentShader GLSL150: Common/MatDefs/Shadow/PostShadow.frag
 
@@ -181,7 +181,7 @@ MaterialDef Unshaded {
         }
     }
 
-    Technique PostShadow{
+    Technique PostShadow {
         VertexShader GLSL100:   Common/MatDefs/Shadow/PostShadow.vert
         FragmentShader GLSL100: Common/MatDefs/Shadow/PostShadow.frag
 

+ 1 - 2
jme3-core/src/main/resources/com/jme3/asset/General.cfg

@@ -22,5 +22,4 @@ LOADER com.jme3.scene.plugins.ogre.MaterialLoader : material
 LOADER com.jme3.scene.plugins.ogre.SceneLoader : scene
 LOADER com.jme3.scene.plugins.blender.BlenderModelLoader : blend
 LOADER com.jme3.shader.plugins.GLSLLoader : vert, frag, geom, tsctrl, tseval, glsl, glsllib
-LOADER com.jme3.scene.plugins.fbx.SceneLoader : fbx
-LOADER com.jme3.scene.plugins.fbx.SceneWithAnimationLoader : fba
+LOADER com.jme3.scene.plugins.fbx.FbxLoader : fbx

+ 34 - 23
jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java

@@ -34,6 +34,7 @@ package com.jme3.material.plugins;
 import com.jme3.material.logic.*;
 import com.jme3.asset.*;
 import com.jme3.material.*;
+import com.jme3.material.RenderState.BlendEquation;
 import com.jme3.material.RenderState.BlendMode;
 import com.jme3.material.RenderState.FaceCullMode;
 import com.jme3.material.TechniqueDef.LightMode;
@@ -77,14 +78,14 @@ public class J3MLoader implements AssetLoader {
     private RenderState renderState;
     private ArrayList<String> presetDefines = new ArrayList<String>();
 
-    private EnumMap<Shader.ShaderType, String> shaderLanguage;
-    private EnumMap<Shader.ShaderType, String> shaderName;
+    private EnumMap<Shader.ShaderType, String> shaderLanguages;
+    private EnumMap<Shader.ShaderType, String> shaderNames;
 
     private static final String whitespacePattern = "\\p{javaWhitespace}+";
 
     public J3MLoader() {
-        shaderLanguage = new EnumMap<Shader.ShaderType, String>(Shader.ShaderType.class);
-        shaderName = new EnumMap<Shader.ShaderType, String>(Shader.ShaderType.class);
+        shaderLanguages = new EnumMap<>(Shader.ShaderType.class);
+        shaderNames = new EnumMap<>(Shader.ShaderType.class);
     }
 
 
@@ -107,8 +108,8 @@ public class J3MLoader implements AssetLoader {
     }
 
     private void readShaderDefinition(Shader.ShaderType shaderType, String name, String language) {
-        shaderName.put(shaderType, name);
-        shaderLanguage.put(shaderType, language);
+        shaderNames.put(shaderType, name);
+        shaderLanguages.put(shaderType, language);
     }
 
     // LightMode <MODE>
@@ -119,9 +120,6 @@ public class J3MLoader implements AssetLoader {
         }
 
         LightMode lm = LightMode.valueOf(split[1]);
-        if (lm == LightMode.FixedPipeline) {
-            throw new UnsupportedOperationException("OpenGL1 is not supported");
-        }
         technique.setLightMode(lm);
     }
     
@@ -461,9 +459,12 @@ public class J3MLoader implements AssetLoader {
             renderState.setDepthTest(parseBoolean(split[1]));
         }else if (split[0].equals("Blend")){
             renderState.setBlendMode(BlendMode.valueOf(split[1]));
+        }else if (split[0].equals("BlendEquation")){
+            renderState.setBlendEquation(BlendEquation.valueOf(split[1]));
+        }else if (split[0].equals("BlendEquationAlpha")){
+            renderState.setBlendEquationAlpha(RenderState.BlendEquationAlpha.valueOf(split[1]));
         }else if (split[0].equals("AlphaTestFalloff")){
-            renderState.setAlphaTest(true);
-            renderState.setAlphaFallOff(Float.parseFloat(split[1]));
+            // Ignore for backwards compatbility
         }else if (split[0].equals("PolyOffset")){
             float factor = Float.parseFloat(split[1]);
             float units = Float.parseFloat(split[2]);
@@ -471,7 +472,7 @@ public class J3MLoader implements AssetLoader {
         }else if (split[0].equals("ColorWrite")){
             renderState.setColorWrite(parseBoolean(split[1]));
         }else if (split[0].equals("PointSprite")){
-            renderState.setPointSprite(parseBoolean(split[1]));
+            // Ignore for backwards compatbility
         }else if (split[0].equals("DepthFunc")){
             renderState.setDepthFunc(RenderState.TestFunction.valueOf(split[1]));
         }else if (split[0].equals("AlphaFunc")){
@@ -606,18 +607,19 @@ public class J3MLoader implements AssetLoader {
     private void readTechnique(Statement techStat) throws IOException{
         isUseNodes = false;
         String[] split = techStat.getLine().split(whitespacePattern);
-        
+
+        String name;
         if (split.length == 1) {
-            String techniqueUniqueName = materialDef.getAssetName() + "@Default";
-            technique = new TechniqueDef(null, techniqueUniqueName.hashCode());
+            name = TechniqueDef.DEFAULT_TECHNIQUE_NAME;
         } else if (split.length == 2) {
-            String techName = split[1];
-            String techniqueUniqueName = materialDef.getAssetName() + "@" + techName;
-            technique = new TechniqueDef(techName, techniqueUniqueName.hashCode());
+            name = split[1];
         } else {
             throw new IOException("Technique statement syntax incorrect");
         }
 
+        String techniqueUniqueName = materialDef.getAssetName() + "@" + name;
+        technique = new TechniqueDef(name, techniqueUniqueName.hashCode());
+
         for (Statement statement : techStat.getContents()){
             readTechniqueStatement(statement);
         }
@@ -633,8 +635,17 @@ public class J3MLoader implements AssetLoader {
             technique.setShaderFile(technique.hashCode() + "", technique.hashCode() + "", "GLSL100", "GLSL100");
         }
 
-        if (shaderName.containsKey(Shader.ShaderType.Vertex) && shaderName.containsKey(Shader.ShaderType.Fragment)) {
-            technique.setShaderFile(shaderName, shaderLanguage);
+        if (shaderNames.containsKey(Shader.ShaderType.Vertex) && shaderNames.containsKey(Shader.ShaderType.Fragment)) {
+            technique.setShaderFile(shaderNames, shaderLanguages);
+        } else {
+            technique = null;
+            shaderLanguages.clear();
+            shaderNames.clear();
+            presetDefines.clear();
+            logger.log(Level.WARNING, "Fixed function technique was ignored");
+            logger.log(Level.WARNING, "Fixed function technique ''{0}'' was ignored for material {1}",
+                    new Object[]{name, key});
+            return;
         }
         
         technique.setShaderPrologue(createShaderPrologue(presetDefines));
@@ -658,8 +669,8 @@ public class J3MLoader implements AssetLoader {
 
         materialDef.addTechniqueDef(technique);
         technique = null;
-        shaderLanguage.clear();
-        shaderName.clear();
+        shaderLanguages.clear();
+        shaderNames.clear();
         presetDefines.clear();
     }
 
@@ -781,7 +792,7 @@ public class J3MLoader implements AssetLoader {
 
     protected void initNodesLoader() {
         if (!isUseNodes) {
-            isUseNodes = shaderName.get(Shader.ShaderType.Vertex) == null && shaderName.get(Shader.ShaderType.Fragment) == null;
+            isUseNodes = shaderNames.get(Shader.ShaderType.Vertex) == null && shaderNames.get(Shader.ShaderType.Fragment) == null;
             if (isUseNodes) {
                 if (nodesLoaderDelegate == null) {
                     nodesLoaderDelegate = new ShaderNodeLoaderDelegate();

+ 1 - 2
jme3-core/src/plugins/java/com/jme3/scene/plugins/MTLLoader.java

@@ -149,8 +149,7 @@ public class MTLLoader implements AssetLoader {
         if (transparent){
             material.setTransparent(true);
             material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
-            material.getAdditionalRenderState().setAlphaTest(true);
-            material.getAdditionalRenderState().setAlphaFallOff(0.01f);
+            material.setFloat("AlphaDiscardThreshold", 0.01f);
         }
         
         matList.put(matName, material);

+ 171 - 0
jme3-core/src/test/java/com/jme3/material/MaterialTest.java

@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2009-2016 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.
+ */
+package com.jme3.material;
+
+import com.jme3.asset.AssetManager;
+import com.jme3.light.LightList;
+import com.jme3.renderer.Caps;
+import com.jme3.renderer.RenderManager;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.shape.Box;
+import com.jme3.system.NullRenderer;
+import com.jme3.system.TestUtil;
+import java.util.Arrays;
+import java.util.EnumSet;
+import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class MaterialTest {
+
+    private Material material;
+    private final Geometry geometry = new Geometry("Geometry", new Box(1, 1, 1));
+    private final EnumSet<Caps> myCaps = EnumSet.noneOf(Caps.class);
+    private final RenderManager renderManager = new RenderManager(new NullRenderer() {
+        @Override
+        public EnumSet<Caps> getCaps() {
+            return MaterialTest.this.myCaps;
+        }
+    });
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testSelectNonExistentTechnique() {
+        material("Common/MatDefs/Gui/Gui.j3md");
+        material.selectTechnique("Doesn't Exist", renderManager);
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testSelectDefaultTechnique_NoCaps() {
+        material("Common/MatDefs/Gui/Gui.j3md");
+        material.selectTechnique("Default", renderManager);
+    }
+
+    @Test
+    public void testSelectDefaultTechnique_GLSL100Cap() {
+        supportGlsl(100);
+        material("Common/MatDefs/Gui/Gui.j3md");
+
+        material.selectTechnique("Default", renderManager);
+
+        checkRequiredCaps(Caps.GLSL100);
+    }
+
+    @Test
+    public void testSelectDefaultTechnique_GLSL150Cap() {
+        supportGlsl(150);
+        material("Common/MatDefs/Gui/Gui.j3md");
+
+        material.selectTechnique("Default", renderManager);
+
+        checkRequiredCaps(Caps.GLSL150);
+    }
+
+    @Test
+    public void testSelectDefaultTechnique_GLSL120Cap_MultipleLangs() {
+        supportGlsl(120);
+        material("Common/MatDefs/Misc/Particle.j3md");
+
+        material.selectTechnique("Default", renderManager);
+
+        checkRequiredCaps(Caps.GLSL100, Caps.GLSL120);
+    }
+
+    @Test
+    public void testSelectDefaultTechnique_GLSL100Cap_MultipleLangs() {
+        supportGlsl(100);
+        material("Common/MatDefs/Misc/Particle.j3md");
+
+        material.selectTechnique("Default", renderManager);
+
+        checkRequiredCaps(Caps.GLSL100);
+    }
+
+    @Test
+    public void testSelectNamedTechnique_GLSL150Cap() {
+        supportGlsl(150);
+        material("Common/MatDefs/Light/Lighting.j3md");
+
+        material.selectTechnique("PostShadow", renderManager);
+
+        checkRequiredCaps(Caps.GLSL150);
+    }
+
+    @Test
+    public void testSelectNamedTechnique_GLSL100Cap() {
+        supportGlsl(100);
+        material("Common/MatDefs/Light/Lighting.j3md");
+
+        material.selectTechnique("PostShadow", renderManager);
+
+        checkRequiredCaps(Caps.GLSL100);
+    }
+
+    private void checkRequiredCaps(Caps... caps) {
+        EnumSet<Caps> expected = EnumSet.noneOf(Caps.class);
+        expected.addAll(Arrays.asList(caps));
+
+        Technique tech = material.getActiveTechnique();
+
+        assertEquals(expected, tech.getDef().getRequiredCaps());
+    }
+
+    private void supportGlsl(int version) {
+        switch (version) {
+            case 150:
+                myCaps.add(Caps.GLSL150);
+            case 140:
+                myCaps.add(Caps.GLSL140);
+            case 130:
+                myCaps.add(Caps.GLSL130);
+            case 120:
+                myCaps.add(Caps.GLSL120);
+            case 110:
+                myCaps.add(Caps.GLSL110);
+            case 100:
+                myCaps.add(Caps.GLSL100);
+                break;
+        }
+    }
+
+    private void caps(Caps... caps) {
+        myCaps.addAll(Arrays.asList(caps));
+    }
+
+    private void material(String path) {
+        AssetManager assetManager = TestUtil.createAssetManager();
+        material = new Material(assetManager, path);
+        geometry.setMaterial(material);
+    }
+
+}

+ 15 - 0
jme3-core/src/test/java/com/jme3/material/plugins/J3MLoaderTest.java

@@ -55,6 +55,21 @@ public class J3MLoaderTest {
         j3MLoader = new J3MLoader();
     }
 
+    @Test
+    public void noDefaultTechnique_shouldBeSupported() throws IOException {
+        when(assetInfo.openStream()).thenReturn(J3MLoader.class.getResourceAsStream("/no-default-technique.j3md"));
+        MaterialDef def = (MaterialDef) j3MLoader.load(assetInfo);
+        assertEquals(1, def.getTechniqueDefs("Test").size());
+    }
+
+    @Test
+    public void fixedPipelineTechnique_shouldBeIgnored() throws IOException {
+        when(assetInfo.openStream()).thenReturn(J3MLoader.class.getResourceAsStream("/no-shader-specified.j3md"));
+        MaterialDef def = (MaterialDef) j3MLoader.load(assetInfo);
+        assertEquals(null, def.getTechniqueDefs("A"));
+        assertEquals(1, def.getTechniqueDefs("B").size());
+    }
+
     @Test
     public void multipleSameNamedTechniques_shouldBeSupported() throws IOException {
         when(assetInfo.openStream()).thenReturn(J3MLoader.class.getResourceAsStream("/same-name-technique.j3md"));

+ 6 - 0
jme3-core/src/test/resources/no-default-technique.j3md

@@ -0,0 +1,6 @@
+MaterialDef Test Material {
+    Technique Test {
+        VertexShader GLSL100 : test.vert
+        FragmentShader GLSL100 : test.frag
+    }
+}

+ 8 - 0
jme3-core/src/test/resources/no-shader-specified.j3md

@@ -0,0 +1,8 @@
+MaterialDef Test Material {
+    Technique A {
+    }
+    Technique B {
+        VertexShader GLSL100 : test.vert
+        FragmentShader GLSL100 : test.frag
+    }
+}

+ 0 - 1
jme3-core/src/tools/java/jme3tools/optimize/TextureAtlas.java

@@ -504,7 +504,6 @@ public class TextureAtlas {
         geom.setMesh(mesh);
 
         Material mat = new Material(mgr, "Common/MatDefs/Light/Lighting.j3md");
-        mat.getAdditionalRenderState().setAlphaTest(true);
         Texture diffuseMap = atlas.getAtlasTexture("DiffuseMap");
         Texture normalMap = atlas.getAtlasTexture("NormalMap");
         Texture specularMap = atlas.getAtlasTexture("SpecularMap");

+ 0 - 359
jme3-desktop/src/main/java/com/jme3/system/Natives.java

@@ -1,359 +0,0 @@
-/*
- * Copyright (c) 2009-2012 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.
- */
-package com.jme3.system;
-
-import java.io.*;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Helper class for extracting the natives (dll, so) from the jars.
- * This class should only be used internally.
- * 
- * @deprecated Use {@link NativeLibraryLoader} instead.
- */
-@Deprecated
-public final class Natives {
-
-    private static final Logger logger = Logger.getLogger(Natives.class.getName());
-    private static final byte[] buf = new byte[1024 * 100];
-    private static File extractionDirOverride = null;
-    private static File extractionDir = null;
-
-    public static void setExtractionDir(String name) {
-        extractionDirOverride = new File(name).getAbsoluteFile();
-    }
-
-    public static File getExtractionDir() {
-        if (extractionDirOverride != null) {
-            return extractionDirOverride;
-        }
-        if (extractionDir == null) {
-            File workingFolder = new File("").getAbsoluteFile();
-            if (!workingFolder.canWrite()) {
-                setStorageExtractionDir();
-            } else {
-                try {
-                    File file = new File(workingFolder.getAbsolutePath() + File.separator + ".jmetestwrite");
-                    file.createNewFile();
-                    file.delete();
-                    extractionDir = workingFolder;
-                } catch (Exception e) {
-                    setStorageExtractionDir();
-                }
-            }
-        }
-        return extractionDir;
-    }
-
-    private static void setStorageExtractionDir() {
-        logger.log(Level.WARNING, "Working directory is not writable. Using home directory instead.");
-        extractionDir = new File(JmeSystem.getStorageFolder(),
-                "natives_" + Integer.toHexString(computeNativesHash()));
-        if (!extractionDir.exists()) {
-            extractionDir.mkdir();
-        }
-    }
-
-    private static int computeNativesHash() {
-        URLConnection conn = null;
-        try {
-            String classpath = System.getProperty("java.class.path");
-            URL url = Thread.currentThread().getContextClassLoader().getResource("com/jme3/system/Natives.class");
-
-            StringBuilder sb = new StringBuilder(url.toString());
-            if (sb.indexOf("jar:") == 0) {
-                sb.delete(0, 4);
-                sb.delete(sb.indexOf("!"), sb.length());
-                sb.delete(sb.lastIndexOf("/") + 1, sb.length());
-            }
-            try {
-                url = new URL(sb.toString());
-            } catch (MalformedURLException ex) {
-                throw new UnsupportedOperationException(ex);
-            }
-
-            conn = url.openConnection();
-            int hash = classpath.hashCode() ^ (int) conn.getLastModified();
-            return hash;
-        } catch (IOException ex) {
-            throw new UnsupportedOperationException(ex);
-        } finally {
-            if (conn != null) {
-                try {
-                    conn.getInputStream().close();
-                    conn.getOutputStream().close();
-                } catch (IOException ex) { }
-            }
-        }
-    }
-
-    public static void extractNativeLib(String sysName, String name) throws IOException {
-        extractNativeLib(sysName, name, false, true);
-    }
-
-    public static void extractNativeLib(String sysName, String name, boolean load) throws IOException {
-        extractNativeLib(sysName, name, load, true);
-    }
-
-    public static void extractNativeLib(String sysName, String name, boolean load, boolean warning) throws IOException {
-        String fullname;
-        String path;
-        //XXX: hack to allow specifying the extension via supplying an extension in the name (e.g. "blah.dylib")
-        //     this is needed on osx where the openal.dylib always needs to be extracted as dylib
-        //     and never as jnilib, even if that is the platform JNI lib suffix (OpenAL is no JNI library)
-        if(!name.contains(".")){
-            // automatic name mapping
-            fullname = System.mapLibraryName(name);
-            path = "native/" + sysName + "/" + fullname;
-            //XXX: Hack to extract jnilib to dylib on OSX Java 1.7+
-            //     This assumes all jni libs for osx are stored as "jnilib" in the jar file.
-            //     It will be extracted with the name required for the platform.
-            //     At a later stage this should probably inverted so that dylib is the default name.
-            if(sysName.equals("macosx")){
-                path = path.replaceAll("dylib","jnilib");
-            }
-        } else{
-            fullname = name;
-            path = "native/" + sysName + "/" + fullname;
-        }
-
-        URL url = Thread.currentThread().getContextClassLoader().getResource(path);
-
-        // Also check for binaries that are not packed in folders by jme team, e.g. maven artifacts
-        if(url == null){
-            path = fullname;
-            if(sysName.equals("macosx") && !name.contains(".")){
-                path = path.replaceAll("dylib","jnilib");
-            }
-            url = Thread.currentThread().getContextClassLoader().getResource(path);
-        }
-        
-        if(url == null){
-            if (!warning) {
-                logger.log(Level.WARNING, "Cannot locate native library in classpath: {0}/{1}",
-                        new String[]{sysName, fullname});
-            }
-            // Still try loading the library without a filename, maybe it is
-            // accessible otherwise
-            try{
-                System.loadLibrary(name);
-            } catch(UnsatisfiedLinkError e){
-                if (!warning) {
-                    logger.log(Level.WARNING, "Cannot load native library: {0}/{1}",
-                            new String[]{sysName, fullname});
-                }
-            }
-            return;
-        }
-
-        URLConnection conn = url.openConnection();
-        InputStream in = conn.getInputStream();
-        File targetFile = new File(getExtractionDir(), fullname);
-        OutputStream out = null;
-        try {
-            if (targetFile.exists()) {
-                // OK, compare last modified date of this file to 
-                // file in jar
-                long targetLastModified = targetFile.lastModified();
-                long sourceLastModified = conn.getLastModified();
-
-                // Allow ~1 second range for OSes that only support low precision
-                if (targetLastModified + 1000 > sourceLastModified) {
-                    logger.log(Level.FINE, "Not copying library {0}. Latest already extracted.", fullname);
-                    return;
-                }
-            }
-
-            out = new FileOutputStream(targetFile);
-            int len;
-            while ((len = in.read(buf)) > 0) {
-                out.write(buf, 0, len);
-            }
-            in.close();
-            in = null;
-            out.close();
-            out = null;
-
-            // NOTE: On OSes that support "Date Created" property, 
-            // this will cause the last modified date to be lower than
-            // date created which makes no sense
-            targetFile.setLastModified(conn.getLastModified());
-        } catch (FileNotFoundException ex) {
-            if (ex.getMessage().contains("used by another process")) {
-                return;
-            }
-
-            throw ex;
-        } finally {
-            if (load) {
-                System.load(targetFile.getAbsolutePath());
-            }
-            if(in != null){
-                in.close();
-            }
-            if(out != null){
-                out.close();
-            }
-        }
-        logger.log(Level.FINE, "Copied {0} to {1}", new Object[]{fullname, targetFile});
-    }
-
-    protected static boolean isUsingNativeBullet() {
-        try {
-            Class clazz = Class.forName("com.jme3.bullet.util.NativeMeshUtil");
-            return clazz != null;
-        } catch (ClassNotFoundException ex) {
-            return false;
-        }
-    }
-
-    public static void extractNativeLibs(Platform platform, AppSettings settings) throws IOException {
-        if (true) {
-            throw new UnsupportedEncodingException("Now, why would you EVER want to do that?");
-        }
-        
-        String renderer = settings.getRenderer();
-        String audioRenderer = settings.getAudioRenderer();
-        boolean needLWJGL = false;
-        boolean needOAL = false;
-        boolean needJInput = false;
-        boolean needNativeBullet = isUsingNativeBullet();
-        
-        if (renderer != null) {
-            if (renderer.startsWith("LWJGL")) {
-                needLWJGL = true;
-            }
-        }
-        if (audioRenderer != null) {
-            if (audioRenderer.equals("LWJGL")) {
-                needLWJGL = true;
-                needOAL = true;
-            }
-        }
-        needJInput = settings.useJoysticks();
-
-        String libraryPath = getExtractionDir().toString();
-        if (needLWJGL) {
-            logger.log(Level.INFO, "Extraction Directory: {0}", getExtractionDir().toString());
-
-            // LWJGL supports this feature where
-            // it can load libraries from this path.
-            System.setProperty("org.lwjgl.librarypath", libraryPath);
-        }
-        if (needJInput) {
-            // AND Luckily enough JInput supports the same feature.
-            System.setProperty("net.java.games.input.librarypath", libraryPath);
-        }
-
-        switch (platform) {
-            case Windows64:
-                if (needLWJGL) {
-                    extractNativeLib("windows", "lwjgl64");
-                }
-                if (needOAL) {
-                    extractNativeLib("windows", "OpenAL64", true, false);
-                }
-                if (needJInput) {
-                    extractNativeLib("windows", "jinput-dx8_64");
-                    extractNativeLib("windows", "jinput-raw_64");
-                }
-                if (needNativeBullet) {
-                    extractNativeLib("windows", "bulletjme64", true, false);
-                }
-                break;
-            case Windows32:
-                if (needLWJGL) {
-                    extractNativeLib("windows", "lwjgl");
-                }
-                if (needOAL) {
-                    extractNativeLib("windows", "OpenAL32", true, false);
-                }
-                if (needJInput) {
-                    extractNativeLib("windows", "jinput-dx8");
-                    extractNativeLib("windows", "jinput-raw");
-                }
-                if (needNativeBullet) {
-                    extractNativeLib("windows", "bulletjme", true, false);
-                }
-                break;
-            case Linux64:
-                if (needLWJGL) {
-                    extractNativeLib("linux", "lwjgl64");
-                }
-                if (needJInput) {
-                    extractNativeLib("linux", "jinput-linux64");
-                }
-                if (needOAL) {
-                    extractNativeLib("linux", "openal64");
-                }
-                if (needNativeBullet) {
-                    extractNativeLib("linux", "bulletjme64", true, false);
-                }
-                break;
-            case Linux32:
-                if (needLWJGL) {
-                    extractNativeLib("linux", "lwjgl");
-                }
-                if (needJInput) {
-                    extractNativeLib("linux", "jinput-linux");
-                }
-                if (needOAL) {
-                    extractNativeLib("linux", "openal");
-                }
-                if (needNativeBullet) {
-                    extractNativeLib("linux", "bulletjme", true, false);
-                }
-                break;
-            case MacOSX_PPC32:
-            case MacOSX32:
-            case MacOSX_PPC64:
-            case MacOSX64:
-                if (needLWJGL) {
-                    extractNativeLib("macosx", "lwjgl");
-                }
-                if (needOAL){
-                    extractNativeLib("macosx", "openal.dylib");
-                }
-                if (needJInput) {
-                    extractNativeLib("macosx", "jinput-osx");
-                }
-                if (needNativeBullet) {
-                    extractNativeLib("macosx", "bulletjme", true, false);
-                }
-                break;
-        }
-    }
-}

+ 2 - 1
jme3-examples/src/main/java/jme3test/animation/TestCameraMotionPath.java

@@ -139,7 +139,8 @@ public class TestCameraMotionPath extends SimpleApplication {
 
 
         rootNode.attachChild(teapot);
-        Geometry soil = new Geometry("soil", new Box(new Vector3f(0, -1.0f, 0), 50, 1, 50));
+        Geometry soil = new Geometry("soil", new Box(50, 1, 50));
+        soil.setLocalTranslation(0, -1, 0);
         soil.setMaterial(matSoil);
         rootNode.attachChild(soil);
         DirectionalLight light = new DirectionalLight();

+ 2 - 1
jme3-examples/src/main/java/jme3test/animation/TestCinematic.java

@@ -222,7 +222,8 @@ public class TestCinematic extends SimpleApplication {
         matSoil.setColor("Diffuse", ColorRGBA.Green);
         matSoil.setColor("Specular", ColorRGBA.Black);
 
-        Geometry soil = new Geometry("soil", new Box(new Vector3f(0, -6.0f, 0), 50, 1, 50));
+        Geometry soil = new Geometry("soil", new Box(50, 1, 50));
+        soil.setLocalTranslation(0, -6, 0);
         soil.setMaterial(matSoil);
         soil.setShadowMode(ShadowMode.Receive);
         rootNode.attachChild(soil);

+ 2 - 1
jme3-examples/src/main/java/jme3test/animation/TestMotionPath.java

@@ -136,7 +136,8 @@ public class TestMotionPath extends SimpleApplication {
 
 
         rootNode.attachChild(teapot);
-        Geometry soil = new Geometry("soil", new Box(new Vector3f(0, -1.0f, 0), 50, 1, 50));
+        Geometry soil = new Geometry("soil", new Box(50, 1, 50));
+        soil.setLocalTranslation(0, -1, 0);
         soil.setMaterial(matSoil);
 
         rootNode.attachChild(soil);

+ 1 - 1
jme3-examples/src/main/java/jme3test/app/TestAppStateLifeCycle.java

@@ -57,7 +57,7 @@ public class TestAppStateLifeCycle extends SimpleApplication {
 
     @Override
     public void simpleInitApp() {
-        Box b = new Box(Vector3f.ZERO, 1, 1, 1);
+        Box b = new Box(1, 1, 1);
         Geometry geom = new Geometry("Box", b);
         Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         mat.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg"));

+ 1 - 1
jme3-examples/src/main/java/jme3test/app/TestBareBonesApp.java

@@ -56,7 +56,7 @@ public class TestBareBonesApp extends LegacyApplication {
         System.out.println("Initialize");
 
         // create a box
-        boxGeom = new Geometry("Box", new Box(Vector3f.ZERO, 2, 2, 2));
+        boxGeom = new Geometry("Box", new Box(2, 2, 2));
 
         // load some default material
         boxGeom.setMaterial(assetManager.loadMaterial("Interface/Logo/Logo.j3m"));

+ 1 - 1
jme3-examples/src/main/java/jme3test/app/TestReleaseDirectMemory.java

@@ -50,7 +50,7 @@ public class TestReleaseDirectMemory extends SimpleApplication {
 
     @Override
     public void simpleInitApp() {
-        Box b = new Box(Vector3f.ZERO, 1, 1, 1);
+        Box b = new Box(1, 1, 1);
         Geometry geom = new Geometry("Box", b);
         Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         mat.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg"));

+ 1 - 1
jme3-examples/src/main/java/jme3test/audio/TestAmbient.java

@@ -69,7 +69,7 @@ public class TestAmbient extends SimpleApplication {
     nature.play();
     
     // just a blue box to mark the spot
-    Box box1 = new Box(Vector3f.ZERO, .5f, .5f, .5f);
+    Box box1 = new Box(.5f, .5f, .5f);
     Geometry player = new Geometry("Player", box1);
     Material mat1 = new Material(assetManager,
             "Common/MatDefs/Misc/Unshaded.j3md");

+ 37 - 47
jme3-examples/src/main/java/jme3test/audio/TestDoppler.java

@@ -33,72 +33,62 @@
 package jme3test.audio;
 
 import com.jme3.app.SimpleApplication;
+import com.jme3.audio.AudioData;
 import com.jme3.audio.AudioNode;
-import com.jme3.audio.Environment;
 import com.jme3.math.FastMath;
 import com.jme3.math.Vector3f;
-import org.lwjgl.openal.AL10;
-import org.lwjgl.openal.AL11;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.shape.Sphere;
+import com.jme3.scene.shape.Torus;
 
 /**
  * Test Doppler Effect
  */
 public class TestDoppler extends SimpleApplication {
 
-    private AudioNode ufo;
+    private float pos = -5;
+    private float vel = 5;
+    private AudioNode ufoNode;
 
-    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;
-    
     public static void main(String[] args){
         TestDoppler test = new TestDoppler();
         test.start();
     }
 
     @Override
-    public void simpleInitApp(){
-        audioRenderer.setEnvironment(Environment.Dungeon);
-        AL10.alDistanceModel(AL11.AL_EXPONENT_DISTANCE);
-        
-        ufo  = new AudioNode(assetManager, "Sound/Effects/Beep.ogg", false);
-        ufo.setPositional(true);
-        ufo.setLooping(true);
-        ufo.setReverbEnabled(true);
-        ufo.setRefDistance(100000000);
-        ufo.setMaxDistance(100000000);
-        ufo.play();
+    public void simpleInitApp() {
+        flyCam.setMoveSpeed(10);
+
+        Torus torus = new Torus(10, 6, 1, 3);
+        Geometry g = new Geometry("Torus Geom", torus);
+        g.rotate(-FastMath.HALF_PI, 0, 0);
+        g.center();
+
+        g.setMaterial(assetManager.loadMaterial("Common/Materials/RedColor.j3m"));
+//        rootNode.attachChild(g);
+
+        ufoNode = new AudioNode(assetManager, "Sound/Effects/Beep.ogg", AudioData.DataType.Buffer);
+        ufoNode.setLooping(true);
+        ufoNode.setPitch(0.5f);
+        ufoNode.setRefDistance(1);
+        ufoNode.setMaxDistance(100000000);
+        ufoNode.setVelocityFromTranslation(true);
+        ufoNode.play();
+
+        Geometry ball = new Geometry("Beeper", new Sphere(10, 10, 0.1f));
+        ball.setMaterial(assetManager.loadMaterial("Common/Materials/RedColor.j3m"));
+        ufoNode.attachChild(ball);
+
+        rootNode.attachChild(ufoNode);
     }
 
+
     @Override
-    public void simpleUpdate(float tpf){
-        //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;
-        }else if (angle < -0){
-            angle = -0;
-            rate = -rate;
+    public void simpleUpdate(float tpf) {
+        pos += tpf * vel;
+        if (pos < -10 || pos > 10) {
+            vel *= -1;
         }
-        
-        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);
+        ufoNode.setLocalTranslation(new Vector3f(pos, 0, 0));
     }
-
 }

+ 1 - 1
jme3-examples/src/main/java/jme3test/awt/TestAwtPanels.java

@@ -90,7 +90,7 @@ public class TestAwtPanels extends SimpleApplication {
     public void simpleInitApp() {
         flyCam.setDragToRotate(true);
         
-        Box b = new Box(Vector3f.ZERO, 1, 1, 1);
+        Box b = new Box(1, 1, 1);
         Geometry geom = new Geometry("Box", b);
         Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         mat.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg"));

+ 1 - 1
jme3-examples/src/main/java/jme3test/awt/TestSafeCanvas.java

@@ -59,7 +59,7 @@ public class TestSafeCanvas extends SimpleApplication {
     public void simpleInitApp() {
         flyCam.setDragToRotate(true);
 
-        Box b = new Box(Vector3f.ZERO, 1, 1, 1);
+        Box b = new Box(1, 1, 1);
         Geometry geom = new Geometry("Box", b);
         Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         mat.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg"));

+ 2 - 2
jme3-examples/src/main/java/jme3test/batching/TestBatchNode.java

@@ -82,7 +82,7 @@ public class TestBatchNode extends SimpleApplication {
          * A cube with a color "bleeding" through transparent texture. Uses
          * Texture from jme3-test-data library!
          */
-        Box boxshape4 = new Box(Vector3f.ZERO, 1f, 1f, 1f);
+        Box boxshape4 = new Box(1f, 1f, 1f);
         cube = new Geometry("cube1", boxshape4);
         Material mat = assetManager.loadMaterial("Textures/Terrain/Pond/Pond.j3m");
         cube.setMaterial(mat);
@@ -93,7 +93,7 @@ public class TestBatchNode extends SimpleApplication {
          * A cube with a color "bleeding" through transparent texture. Uses
          * Texture from jme3-test-data library!
          */
-        Box box = new Box(Vector3f.ZERO, 1f, 1f, 1f);
+        Box box = new Box(1f, 1f, 1f);
         cube2 = new Geometry("cube2", box);
         cube2.setMaterial(mat);
 

+ 1 - 1
jme3-examples/src/main/java/jme3test/batching/TestBatchNodeCluster.java

@@ -166,7 +166,7 @@ public class TestBatchNodeCluster extends SimpleApplication {
     public void randomGenerator() {
         for (int i = startAt; i < maxCubes - 1; i++) {
             randomize();
-            Geometry box = new Geometry("Box" + i, new Box(Vector3f.ZERO, 1, 1, 1));
+            Geometry box = new Geometry("Box" + i, new Box(1, 1, 1));
             box.setLocalTranslation(new Vector3f(xPosition.get(xPosition.size() - 1),
                     yPosition.get(yPosition.size() - 1),
                     zPosition.get(zPosition.size() - 1)));

+ 1 - 1
jme3-examples/src/main/java/jme3test/batching/TestBatchNodeTower.java

@@ -193,7 +193,7 @@ public class TestBatchNodeTower extends SimpleApplication {
     }
 
     public void initFloor() {
-        Box floorBox = new Box(Vector3f.ZERO, 10f, 0.1f, 5f);
+        Box floorBox = new Box(10f, 0.1f, 5f);
         floorBox.scaleTextureCoordinates(new Vector2f(3, 6));
 
         Geometry floor = new Geometry("floor", floorBox);

+ 1 - 1
jme3-examples/src/main/java/jme3test/bullet/TestAttachDriver.java

@@ -112,7 +112,7 @@ public class TestAttachDriver extends SimpleApplication implements ActionListene
         tex.setMinFilter(Texture.MinFilter.Trilinear);
         mat.setTexture("ColorMap", tex);
 
-        Box floor = new Box(Vector3f.ZERO, 100, 1f, 100);
+        Box floor = new Box(100, 1f, 100);
         Geometry floorGeom = new Geometry("Floor", floor);
         floorGeom.setMaterial(mat);
         floorGeom.setLocalTranslation(new Vector3f(0f, -3, 0f));

+ 2 - 2
jme3-examples/src/main/java/jme3test/bullet/TestBrickTower.java

@@ -126,7 +126,7 @@ public class TestBrickTower extends SimpleApplication {
         bullet.setTextureMode(TextureMode.Projected);
         bulletCollisionShape = new SphereCollisionShape(0.4f);
 
-        brick = new Box(Vector3f.ZERO, brickWidth, brickHeight, brickDepth);
+        brick = new Box(brickWidth, brickHeight, brickDepth);
         brick.scaleTextureCoordinates(new Vector2f(1f, .5f));
         //bulletAppState.getPhysicsSpace().enableDebug(assetManager);
         initMaterial();
@@ -204,7 +204,7 @@ public class TestBrickTower extends SimpleApplication {
     }
 
     public void initFloor() {
-        Box floorBox = new Box(Vector3f.ZERO, 10f, 0.1f, 5f);
+        Box floorBox = new Box(10f, 0.1f, 5f);
         floorBox.scaleTextureCoordinates(new Vector2f(3, 6));
 
         Geometry floor = new Geometry("floor", floorBox);

+ 2 - 2
jme3-examples/src/main/java/jme3test/bullet/TestBrickWall.java

@@ -90,7 +90,7 @@ public class TestBrickWall extends SimpleApplication {
         bullet = new Sphere(32, 32, 0.4f, true, false);
         bullet.setTextureMode(TextureMode.Projected);
         bulletCollisionShape = new SphereCollisionShape(0.4f);
-        brick = new Box(Vector3f.ZERO, bLength, bHeight, bWidth);
+        brick = new Box(bLength, bHeight, bWidth);
         brick.scaleTextureCoordinates(new Vector2f(1f, .5f));
 
         initMaterial();
@@ -151,7 +151,7 @@ public class TestBrickWall extends SimpleApplication {
     }
 
     public void initFloor() {
-        Box floorBox = new Box(Vector3f.ZERO, 10f, 0.1f, 5f);
+        Box floorBox = new Box(10f, 0.1f, 5f);
         floorBox.scaleTextureCoordinates(new Vector2f(3, 6));
 
         Geometry floor = new Geometry("floor", floorBox);

+ 1 - 1
jme3-examples/src/main/java/jme3test/bullet/TestCcd.java

@@ -98,7 +98,7 @@ public class TestCcd extends SimpleApplication implements ActionListener {
         Node node2 = new Node();
         node2.setName("mesh");
         node2.setLocalTranslation(new Vector3f(2.5f, 0, 0f));
-        node2.addControl(new RigidBodyControl(new MeshCollisionShape(new Box(Vector3f.ZERO, 4, 4, 0.1f)), 0));
+        node2.addControl(new RigidBodyControl(new MeshCollisionShape(new Box(4, 4, 0.1f)), 0));
         rootNode.attachChild(node2);
         getPhysicsSpace().add(node2);
 

+ 1 - 1
jme3-examples/src/main/java/jme3test/bullet/TestCollisionGroups.java

@@ -85,7 +85,7 @@ public class TestCollisionGroups extends SimpleApplication {
         getPhysicsSpace().add(node2);
 
         // the floor, does not move (mass=0)
-        Node node3 = PhysicsTestHelper.createPhysicsTestNode(assetManager, new MeshCollisionShape(new Box(Vector3f.ZERO, 100f, 0.2f, 100f)), 0);
+        Node node3 = PhysicsTestHelper.createPhysicsTestNode(assetManager, new MeshCollisionShape(new Box(100f, 0.2f, 100f)), 0);
         node3.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(0f, -6, 0f));
         rootNode.attachChild(node3);
         getPhysicsSpace().add(node3);

+ 1 - 1
jme3-examples/src/main/java/jme3test/bullet/TestGhostObject.java

@@ -65,7 +65,7 @@ public class TestGhostObject extends SimpleApplication {
         bulletAppState.setDebugEnabled(true);
 
         // Mesh to be shared across several boxes.
-        Box boxGeom = new Box(Vector3f.ZERO, 1f, 1f, 1f);
+        Box boxGeom = new Box(1f, 1f, 1f);
         // CollisionShape to be shared across several boxes.
         CollisionShape shape = new BoxCollisionShape(new Vector3f(1, 1, 1));
 

+ 1 - 1
jme3-examples/src/main/java/jme3test/bullet/TestRagdollCharacter.java

@@ -139,7 +139,7 @@ public class TestRagdollCharacter extends SimpleApplication implements AnimEvent
     }
 
     public void initWall(float bLength, float bWidth, float bHeight) {
-        Box brick = new Box(Vector3f.ZERO, bLength, bHeight, bWidth);
+        Box brick = new Box(bLength, bHeight, bWidth);
         brick.scaleTextureCoordinates(new Vector2f(1f, .5f));
         Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         TextureKey key = new TextureKey("Textures/Terrain/BrickWall/BrickWall.jpg");

+ 1 - 1
jme3-examples/src/main/java/jme3test/bullet/TestWalkingChar.java

@@ -171,7 +171,7 @@ public class TestWalkingChar extends SimpleApplication implements ActionListener
         float zOff = -40;
         float startpt = bLength / 4 - xOff;
         float height = 6.1f;
-        brick = new Box(Vector3f.ZERO, bLength, bHeight, bWidth);
+        brick = new Box(bLength, bHeight, bWidth);
         brick.scaleTextureCoordinates(new Vector2f(1f, .5f));
         for (int j = 0; j < 15; j++) {
             for (int i = 0; i < 4; i++) {

+ 4 - 2
jme3-examples/src/main/java/jme3test/collision/TestMousePick.java

@@ -107,8 +107,9 @@ public class TestMousePick extends SimpleApplication {
  
     /** A cube object for target practice */
     protected Geometry makeCube(String name, float x, float y, float z) {
-        Box box = new Box(new Vector3f(x, y, z), 1, 1, 1);
+        Box box = new Box(1, 1, 1);
         Geometry cube = new Geometry(name, box);
+        cube.setLocalTranslation(x, y, z);
         Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         mat1.setColor("Color", ColorRGBA.randomColor());
         cube.setMaterial(mat1);
@@ -117,8 +118,9 @@ public class TestMousePick extends SimpleApplication {
 
     /** A floor to show that the "shot" can go through several objects. */
     protected Geometry makeFloor() {
-        Box box = new Box(new Vector3f(0, -4, -5), 15, .2f, 15);
+        Box box = new Box(15, .2f, 15);
         Geometry floor = new Geometry("the Floor", box);
+        floor.setLocalTranslation(0, -4, -5);
         Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         mat1.setColor("Color", ColorRGBA.Gray);
         floor.setMaterial(mat1);

+ 2 - 2
jme3-examples/src/main/java/jme3test/effect/TestSoftParticles.java

@@ -76,7 +76,7 @@ public class TestSoftParticles extends SimpleApplication {
 
 
         // -------- floor
-        Box b = new Box(Vector3f.ZERO, 10, 0.1f, 10);
+        Box b = new Box(10, 0.1f, 10);
         Geometry geom = new Geometry("Box", b);
         Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         mat.setColor("Color", ColorRGBA.Gray);
@@ -84,7 +84,7 @@ public class TestSoftParticles extends SimpleApplication {
         geom.setMaterial(mat);
         rootNode.attachChild(geom);
 
-        Box b2 = new Box(Vector3f.ZERO, 1, 1, 1);
+        Box b2 = new Box(1, 1, 1);
         Geometry geom2 = new Geometry("Box", b2);
         Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         mat2.setColor("Color", ColorRGBA.DarkGray);

+ 9 - 4
jme3-examples/src/main/java/jme3test/games/CubeField.java

@@ -197,9 +197,9 @@ public class CubeField extends SimpleApplication implements AnalogListener {
     private Geometry createFirstCube() {
         Vector3f loc = player.getLocalTranslation();
         loc.addLocal(4, 0, 0);
-        Box b = new Box(loc, 1, 1, 1);
-
+        Box b = new Box(1, 1, 1);
         Geometry geom = new Geometry("Box", b);
+        geom.setLocalTranslation(loc);
         Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         mat.setColor("Color", ColorRGBA.Blue);
         geom.setMaterial(mat);
@@ -216,10 +216,15 @@ public class CubeField extends SimpleApplication implements AnalogListener {
         playerMesh.setMaterial(playerMaterial);
         playerMesh.setName("player");
 
-        Box floor = new Box(Vector3f.ZERO.add(playerMesh.getLocalTranslation().getX(),
-                playerMesh.getLocalTranslation().getY() - 1, 0), 100, 0, 100);
+        Box floor = new Box(100, 0, 100);
+        
         Geometry floorMesh = new Geometry("Box", floor);
 
+        Vector3f translation = Vector3f.ZERO.add(playerMesh.getLocalTranslation().getX(),
+                playerMesh.getLocalTranslation().getY() - 1, 0);
+
+        floorMesh.setLocalTranslation(translation);
+
         floorMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         floorMaterial.setColor("Color", ColorRGBA.LightGray);
         floorMesh.setMaterial(floorMaterial);

+ 1 - 1
jme3-examples/src/main/java/jme3test/helloworld/HelloAssets.java

@@ -60,7 +60,7 @@ public class HelloAssets extends SimpleApplication {
         rootNode.attachChild(teapot);
 
         /** Create a wall (Box with material and texture from test-data) */
-        Box box = new Box(Vector3f.ZERO, 2.5f,2.5f,1.0f);
+        Box box = new Box(2.5f, 2.5f, 1.0f);
         Spatial wall = new Geometry("Box", box );
         Material mat_brick = new Material( assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         mat_brick.setTexture("ColorMap", assetManager.loadTexture("Textures/Terrain/BrickWall/BrickWall.jpg"));

+ 1 - 1
jme3-examples/src/main/java/jme3test/helloworld/HelloInput.java

@@ -57,7 +57,7 @@ public class HelloInput extends SimpleApplication {
 
   @Override
   public void simpleInitApp() {
-    Box b = new Box(Vector3f.ZERO, 1, 1, 1);
+      Box b = new Box(1, 1, 1);
     player = new Geometry("Player", b);
     Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
     mat.setColor("Color", ColorRGBA.Blue);

+ 2 - 1
jme3-examples/src/main/java/jme3test/light/TestDirectionalLightShadow.java

@@ -127,9 +127,10 @@ public class TestDirectionalLightShadow extends SimpleApplication implements Act
             t.setLocalTranslation(FastMath.nextRandomFloat() * 200f, FastMath.nextRandomFloat() * 30f + 20, 30f * (i + 2f));
         }
 
-        Box b = new Box(new Vector3f(0, 10, 550), 1000, 2, 1000);
+        Box b = new Box(1000, 2, 1000);
         b.scaleTextureCoordinates(new Vector2f(10, 10));
         ground = new Geometry("soil", b);
+        ground.setLocalTranslation(0, 10, 550);
         matGroundU = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         matGroundU.setColor("Color", ColorRGBA.Green);
 

+ 2 - 1
jme3-examples/src/main/java/jme3test/light/TestPssmShadow.java

@@ -113,9 +113,10 @@ public class TestPssmShadow extends SimpleApplication implements ActionListener
             t.setLocalTranslation(FastMath.nextRandomFloat() * 200f, FastMath.nextRandomFloat() * 30f + 20, 30f * (i + 2f));
         }
 
-        Box b = new Box(new Vector3f(0, 10, 550), 1000, 2, 1000);
+        Box b = new Box(1000, 2, 1000);
         b.scaleTextureCoordinates(new Vector2f(10, 10));
         ground = new Geometry("soil", b);
+        ground.setLocalTranslation(0, 10, 550);
         matGroundU = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         matGroundU.setColor("Color", ColorRGBA.Green);
 

+ 1 - 1
jme3-examples/src/main/java/jme3test/light/TestShadow.java

@@ -76,7 +76,7 @@ public class TestShadow extends SimpleApplication {
 
         Material mat = assetManager.loadMaterial("Common/Materials/WhiteColor.j3m");
         rootNode.setShadowMode(ShadowMode.Off);
-        Box floor = new Box(Vector3f.ZERO, 3, 0.1f, 3);
+        Box floor = new Box(3, 0.1f, 3);
         Geometry floorGeom = new Geometry("Floor", floor);
         floorGeom.setMaterial(mat);
         floorGeom.setLocalTranslation(0,-0.2f,0);

+ 1 - 1
jme3-examples/src/main/java/jme3test/light/TestShadowsPerf.java

@@ -83,7 +83,7 @@ public class TestShadowsPerf extends SimpleApplication {
 
         mat = assetManager.loadMaterial("Textures/Terrain/Pond/Pond.j3m");
 
-        Box b = new Box(Vector3f.ZERO, 800, 1, 700);
+        Box b = new Box(800, 1, 700);
         b.scaleTextureCoordinates(new Vector2f(50, 50));
         Geometry ground = new Geometry("ground", b);
         ground.setMaterial(mat);

+ 1 - 1
jme3-examples/src/main/java/jme3test/light/TestSpotLight.java

@@ -100,7 +100,7 @@ public class TestSpotLight extends SimpleApplication {
       //  mat.setBoolean("VertexLighting", true);
         
         
-        Box floor = new Box(Vector3f.ZERO, 50, 1f, 50);
+        Box floor = new Box(50, 1f, 50);
         TangentBinormalGenerator.generate(floor);
         floor.scaleTextureCoordinates(new Vector2f(5, 5));
         Geometry floorGeom = new Geometry("Floor", floor);

+ 1 - 1
jme3-examples/src/main/java/jme3test/light/TestSpotLightShadows.java

@@ -148,7 +148,7 @@ public class TestSpotLightShadows extends SimpleApplication {
         //  mat.setBoolean("VertexLighting", true);
 
 
-        Box floor = new Box(Vector3f.ZERO, 50, 1f, 50);
+        Box floor = new Box(50, 1f, 50);
         TangentBinormalGenerator.generate(floor);
         floor.scaleTextureCoordinates(new Vector2f(5, 5));
         Geometry floorGeom = new Geometry("Floor", floor);

+ 2 - 1
jme3-examples/src/main/java/jme3test/model/shape/TestBillboard.java

@@ -64,8 +64,9 @@ public class TestBillboard extends SimpleApplication {
         g3.setMaterial(mat2);
         g3.setLocalTranslation(.5f, .5f, .01f);
 
-        Box b = new Box(new Vector3f(0, 0, 3), .25f, .5f, .25f);
+        Box b = new Box(.25f, .5f, .25f);
         Geometry g2 = new Geometry("Box", b);
+        g2.setLocalTranslation(0, 0, 3);
         g2.setMaterial(mat);
 
         Node bb = new Node("billboard");

+ 0 - 1
jme3-examples/src/main/java/jme3test/model/shape/TestBox.java

@@ -34,7 +34,6 @@ package jme3test.model.shape;
 
 import com.jme3.app.SimpleApplication;
 import com.jme3.material.Material;
-import com.jme3.math.Vector3f;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.shape.Box;
 

+ 1 - 1
jme3-examples/src/main/java/jme3test/niftygui/TestNiftyGui.java

@@ -54,7 +54,7 @@ public class TestNiftyGui extends SimpleApplication implements ScreenController
 
     @Override
     public void simpleInitApp() {
-        Box b = new Box(Vector3f.ZERO, 1, 1, 1);
+        Box b = new Box(1, 1, 1);
         Geometry geom = new Geometry("Box", b);
         Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         mat.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg"));

+ 1 - 1
jme3-examples/src/main/java/jme3test/niftygui/TestNiftyToMesh.java

@@ -79,7 +79,7 @@ public class TestNiftyToMesh extends SimpleApplication{
         niftyView.setClearFlags(true, true, true);
         niftyView.setOutputFrameBuffer(fb);
 
-        Box b = new Box(Vector3f.ZERO, 1, 1, 1);
+        Box b = new Box(1, 1, 1);
         Geometry geom = new Geometry("Box", b);
         Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         mat.setTexture("ColorMap", tex);

+ 2 - 1
jme3-examples/src/main/java/jme3test/post/TestBloom.java

@@ -102,7 +102,8 @@ public class TestBloom extends SimpleApplication {
 
   
 
-        Geometry soil=new Geometry("soil", new Box(new Vector3f(0, -13, 550), 800, 10, 700));
+        Geometry soil = new Geometry("soil", new Box(800, 10, 700));
+        soil.setLocalTranslation(0, -13, 550);
         soil.setMaterial(matSoil);
         soil.setShadowMode(ShadowMode.CastAndReceive);
         rootNode.attachChild(soil);

+ 2 - 1
jme3-examples/src/main/java/jme3test/post/TestCrossHatch.java

@@ -102,7 +102,8 @@ public class TestCrossHatch extends SimpleApplication {
 
   
 
-        Geometry soil=new Geometry("soil", new Box(new Vector3f(0, -13, 550), 800, 10, 700));
+        Geometry soil = new Geometry("soil", new Box(800, 10, 700));
+        soil.setLocalTranslation(0, -13, 550);
         soil.setMaterial(matSoil);
         soil.setShadowMode(ShadowMode.CastAndReceive);
         rootNode.attachChild(soil);

+ 2 - 1
jme3-examples/src/main/java/jme3test/post/TestPosterization.java

@@ -102,7 +102,8 @@ public class TestPosterization extends SimpleApplication {
 
   
 
-        Geometry soil=new Geometry("soil", new Box(new Vector3f(0, -13, 550), 800, 10, 700));
+        Geometry soil = new Geometry("soil", new Box(800, 10, 700));
+        soil.setLocalTranslation(0, -13, 550);
         soil.setMaterial(matSoil);
         soil.setShadowMode(ShadowMode.CastAndReceive);
         rootNode.attachChild(soil);

+ 1 - 1
jme3-examples/src/main/java/jme3test/post/TestRenderToMemory.java

@@ -202,7 +202,7 @@ public class TestRenderToMemory extends SimpleApplication implements SceneProces
         offView.setOutputFrameBuffer(offBuffer);
 
         // setup framebuffer's scene
-        Box boxMesh = new Box(Vector3f.ZERO, 1,1,1);
+        Box boxMesh = new Box(1, 1, 1);
         Material material = assetManager.loadMaterial("Interface/Logo/Logo.j3m");
         offBox = new Geometry("box", boxMesh);
         offBox.setMaterial(material);

+ 2 - 2
jme3-examples/src/main/java/jme3test/post/TestRenderToTexture.java

@@ -93,7 +93,7 @@ public class TestRenderToTexture extends SimpleApplication implements ActionList
         offView.setOutputFrameBuffer(offBuffer);
 
         // setup framebuffer's scene
-        Box boxMesh = new Box(Vector3f.ZERO, 1,1,1);
+        Box boxMesh = new Box(1, 1, 1);
         Material material = assetManager.loadMaterial("Interface/Logo/Logo.j3m");
         offBox = new Geometry("box", boxMesh);
         offBox.setMaterial(material);
@@ -110,7 +110,7 @@ public class TestRenderToTexture extends SimpleApplication implements ActionList
         cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);
 
         //setup main scene
-        Geometry quad = new Geometry("box", new Box(Vector3f.ZERO, 1,1,1));
+        Geometry quad = new Geometry("box", new Box(1, 1, 1));
 
         Texture offTex = setupOffscreenView();
 

+ 110 - 0
jme3-examples/src/main/java/jme3test/renderer/TestBlendEquations.java

@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2009-2016 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.
+ */
+package jme3test.renderer;
+
+import com.jme3.app.SimpleApplication;
+import com.jme3.light.DirectionalLight;
+import com.jme3.material.Material;
+import com.jme3.material.RenderState;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.Vector3f;
+import com.jme3.renderer.queue.RenderQueue;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.shape.Quad;
+
+public class TestBlendEquations extends SimpleApplication {
+
+    public static void main(String[] args) {
+        TestBlendEquations app = new TestBlendEquations();
+        app.start();
+    }
+
+    public void simpleInitApp() {
+        Geometry teaGeom = (Geometry) assetManager.loadModel("Models/Teapot/Teapot.obj");
+        teaGeom.scale(6);
+        teaGeom.getMaterial().getAdditionalRenderState().setBlendEquation(RenderState.BlendEquation.Add);
+        teaGeom.move(0, -2f, 0);
+
+        DirectionalLight dl = new DirectionalLight();
+        dl.setColor(ColorRGBA.Red);
+        dl.setDirection(Vector3f.UNIT_XYZ.negate());
+
+        rootNode.addLight(dl);
+        rootNode.attachChild(teaGeom);
+
+        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+        mat.setColor("Color", new ColorRGBA(0.5f, 0f, 1f, 0.3f));
+        mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Color);
+        mat.getAdditionalRenderState().setBlendEquation(RenderState.BlendEquation.Subtract);
+
+        Geometry geo = new Geometry("BottomLeft", new Quad(guiViewPort.getCamera().getWidth() / 2, guiViewPort.getCamera().getHeight() / 2));
+        geo.setMaterial(mat);
+        geo.setQueueBucket(RenderQueue.Bucket.Gui);
+        geo.setLocalTranslation(0, 0, 1);
+
+        guiNode.attachChild(geo);
+
+        Material m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+        m.getAdditionalRenderState().setBlendEquation(RenderState.BlendEquation.ReverseSubtract);
+        m.setColor("Color", new ColorRGBA(0.0f, 1f, 1.f, 1f));
+        m.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.AlphaAdditive);
+
+        geo = new Geometry("BottomRight", new Quad(guiViewPort.getCamera().getWidth() / 2, guiViewPort.getCamera().getHeight() / 2));
+        geo.setMaterial(m);
+        geo.setQueueBucket(RenderQueue.Bucket.Gui);
+        geo.setLocalTranslation(guiViewPort.getCamera().getWidth() / 2, 0, 1);
+        
+        guiNode.attachChild(geo);
+        
+        m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+        m.getAdditionalRenderState().setBlendEquation(RenderState.BlendEquation.Min);
+        m.setColor("Color", new ColorRGBA(0.3f, 0f, 0.1f, 0.3f));
+        m.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Additive);
+
+        geo = new Geometry("TopRight", new Quad(guiViewPort.getCamera().getWidth() / 2, guiViewPort.getCamera().getHeight() / 2));
+        geo.setMaterial(m);
+        geo.setQueueBucket(RenderQueue.Bucket.Gui);
+        geo.setLocalTranslation(guiViewPort.getCamera().getWidth() / 2, guiViewPort.getCamera().getHeight() / 2, 1);
+
+        guiNode.attachChild(geo);
+
+        geo = new Geometry("OverTeaPot", new Quad(guiViewPort.getCamera().getWidth() / 2, guiViewPort.getCamera().getHeight() / 2));
+        geo.setMaterial(mat);
+        geo.setQueueBucket(RenderQueue.Bucket.Transparent);
+        geo.setLocalTranslation(0, -100, 5);
+
+        rootNode.attachChild(geo);
+
+    }
+
+
+}

+ 116 - 0
jme3-examples/src/main/java/jme3test/texture/TestAnisotropicFilter.java

@@ -0,0 +1,116 @@
+package jme3test.texture;
+
+import com.jme3.app.SimpleApplication;
+import com.jme3.app.state.ScreenshotAppState;
+import com.jme3.asset.AssetManager;
+import com.jme3.input.KeyInput;
+import com.jme3.input.controls.ActionListener;
+import com.jme3.input.controls.KeyTrigger;
+import com.jme3.material.Material;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.FastMath;
+import com.jme3.math.Quaternion;
+import com.jme3.math.Vector2f;
+import com.jme3.math.Vector3f;
+import com.jme3.renderer.Limits;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.shape.Quad;
+import com.jme3.texture.Image;
+import com.jme3.texture.Image.Format;
+import com.jme3.texture.Texture;
+import com.jme3.texture.Texture2D;
+import com.jme3.texture.image.ColorSpace;
+import com.jme3.texture.image.ImageRaster;
+import com.jme3.util.BufferUtils;
+
+public class TestAnisotropicFilter extends SimpleApplication implements ActionListener {
+
+    private int globalAniso = 1;
+    private int maxAniso = 1;
+
+    @Override
+    public void simpleInitApp() {
+        maxAniso = renderer.getLimits().get(Limits.TextureAnisotropy);
+
+        flyCam.setDragToRotate(true);
+        flyCam.setMoveSpeed(100);
+        cam.setLocation(new Vector3f(197.02617f, 4.6769195f, -194.89545f));
+        cam.setRotation(new Quaternion(0.07921988f, 0.8992258f, -0.18292196f, 0.38943136f));
+        Quad q = new Quad(1000, 1000);
+        q.scaleTextureCoordinates(new Vector2f(1000, 1000));
+        Geometry geom = new Geometry("quad", q);
+        geom.rotate(-FastMath.HALF_PI, 0, 0);
+        geom.setMaterial(createCheckerBoardMaterial(assetManager));
+        rootNode.attachChild(geom);
+
+        inputManager.addMapping("higher", new KeyTrigger(KeyInput.KEY_1));
+        inputManager.addMapping("lower", new KeyTrigger(KeyInput.KEY_2));
+        inputManager.addListener(this, "higher");
+        inputManager.addListener(this, "lower");
+    }
+    
+    private static Material createCheckerBoardMaterial(AssetManager assetManager) {
+        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+        Texture tex = createCheckerBoardTexture(); // assetManager.loadTexture("Textures/Terrain/BrickWall/BrickWall.dds");
+        tex.setMagFilter(Texture.MagFilter.Bilinear);
+        tex.setMinFilter(Texture.MinFilter.Trilinear);
+        tex.setWrap(Texture.WrapMode.Repeat);
+        mat.setTexture("ColorMap", tex);
+        return mat;
+    }
+    
+    private static Texture2D createCheckerBoardTexture() {
+        Image image = new Image(Format.RGBA8, 1024, 1024, BufferUtils.createByteBuffer(1024 * 1024 * 4), ColorSpace.sRGB);
+        
+        ImageRaster raster = ImageRaster.create(image);
+        for (int y = 0; y < 1024; y++) {
+            for (int x = 0; x < 1024; x++) {
+                if (y < 512) {
+                    if (x < 512) {
+                        raster.setPixel(x, y, ColorRGBA.Black);
+                    } else {
+                        raster.setPixel(x, y, ColorRGBA.White);
+                    }
+                } else {
+                    if (x < 512) {
+                        raster.setPixel(x, y, ColorRGBA.White);
+                    } else {
+                        raster.setPixel(x, y, ColorRGBA.Black);
+                    }
+                }
+            }
+        }
+
+        return new Texture2D(image);
+    }
+
+    @Override
+    public void onAction(String name, boolean isPressed, float tpf) {
+        if (isPressed) {
+            return;
+        }
+        switch (name) {
+            case "higher":
+                globalAniso++;
+                if (globalAniso > 32) {
+                    globalAniso = 32;
+                }
+                renderer.setDefaultAnisotropicFilter(globalAniso);
+                System.out.format("Global Aniso: %d / %d\r\n", globalAniso, maxAniso);
+                break;
+            case "lower":
+                globalAniso--;
+                if (globalAniso < 1) {
+                    globalAniso = 1;
+                }
+                renderer.setDefaultAnisotropicFilter(globalAniso);
+                System.out.format("Global Aniso: %d / %d\r\n", globalAniso, maxAniso);
+                break;
+        }
+    }
+
+    public static void main(String[] args) {
+        TestAnisotropicFilter app = new TestAnisotropicFilter();
+        app.start();
+    }
+}

+ 1 - 1
jme3-examples/src/main/java/jme3test/water/TestPostWater.java

@@ -194,7 +194,7 @@ public class TestPostWater extends SimpleApplication {
 
     private void createBox() {
         //creating a transluscent box
-        box = new Geometry("box", new Box(new Vector3f(0, 0, 0), 50, 50, 50));
+        box = new Geometry("box", new Box(50, 50, 50));
         Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         mat.setColor("Color", new ColorRGBA(1.0f, 0, 0, 0.3f));
         mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);

+ 5 - 0
jme3-ios/src/main/java/com/jme3/renderer/ios/IosGL.java

@@ -78,6 +78,11 @@ public class IosGL implements GL, GLExt, GLFbo {
         checkLimit(buffer);
         return buffer.limit() / elementSize;
     }
+
+    @Override
+    public void glBlendEquationSeparate(int colorMode, int alphaMode) {
+        JmeIosGLES.glBlendEquationSeparate(colorMode, alphaMode);
+    }
     
     private int toArray(IntBuffer buffer) {
         int remain = buffer.remaining();

+ 1 - 0
jme3-ios/src/main/java/com/jme3/renderer/ios/JmeIosGLES.java

@@ -142,6 +142,7 @@ public class JmeIosGLES {
 	public static native void glBindRenderbuffer(int target, int renderbuffer);
 	public static native void glBindTexture(int target, int texture);
 //	public static native void glBindVertexArray // TODO: Investigate this 
+    public static native void glBlendEquationSeparate(int colorMode, int alphaMode);
 	public static native void glBlendFunc(int sfactor, int dfactor);
 	public static native void glBufferData(int target, int size, Buffer data, int usage);
 	public static native void glBufferData2(int target, int size, byte[] data, int offset, int usage);

+ 5 - 0
jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java

@@ -78,6 +78,11 @@ public class JoglGL implements GL, GL2, GL3, GL4 {
         GLContext.getCurrentGL().glBindTexture(param1, param2);
     }
 
+    @Override
+    public void glBlendEquationSeparate(int colorMode, int alphaMode){
+        GLContext.getCurrentGL().glBlendEquationSeparate(colorMode, alphaMode);
+    }
+
     @Override
 	public void glBlendFunc(int param1, int param2) {
         GLContext.getCurrentGL().glBlendFunc(param1, param2);

+ 4 - 0
jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java

@@ -50,6 +50,10 @@ public final class LwjglGL implements GL, GL2, GL3, GL4 {
         GL11.glBindTexture(param1, param2);
     }
 
+    public void glBlendEquationSeparate(int colorMode, int alphaMode){
+        GL20.glBlendEquationSeparate(colorMode,alphaMode);
+    }
+
     public void glBlendFunc(int param1, int param2) {
         GL11.glBlendFunc(param1, param2);
     }

+ 4 - 0
jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java

@@ -79,6 +79,10 @@ public class LwjglGL implements GL, GL2, GL3, GL4 {
         GL11.glBindTexture(param1, param2);
     }
 
+    public void glBlendEquationSeparate(int colorMode, int alphaMode){
+        GL20.glBlendEquationSeparate(colorMode,alphaMode);
+    }
+
     public void glBlendFunc(int param1, int param2) {
         GL11.glBlendFunc(param1, param2);
     }

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä