Merge branch 'master' into PBRisComing

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

@ -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);
}
}
}
}

@ -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.");
}
}

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

@ -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];
}
}
}

@ -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;
}
}

@ -46,7 +46,7 @@ public class SimpleTexturedTest extends SimpleApplication {
shapeSphere = new Sphere(16, 16, .5f); 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); // ModelConverter.optimize(geom);

@ -34,7 +34,14 @@ libraries {
// linker.args "-static-libstdc++" // linker.args "-static-libstdc++"
} else if (targetPlatform.operatingSystem.name == "windows") { } else if (targetPlatform.operatingSystem.name == "windows") {
if (toolChain in Gcc) { 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) { else if (toolChain in VisualCpp) {
cppCompiler.args "/I${org.gradle.internal.jvm.Jvm.current().javaHome}\\include\\win32" 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 // Set of target platforms, will be available based on build system
model { 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{ platforms{
// osx_universal { // TODO: universal binary doesn't work? // osx_universal { // TODO: universal binary doesn't work?
// architecture 'x86_64' // architecture 'x86_64'

@ -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);
}
}

@ -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);
}
}

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

@ -123,24 +123,6 @@ public class TextureKey extends AssetKey<Texture> {
this.anisotropy = anisotropy; 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() { public boolean isGenerateMips() {
return generateMips; return generateMips;
} }
@ -149,24 +131,6 @@ public class TextureKey extends AssetKey<Texture> {
this.generateMips = generateMips; 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. * The type of texture expected to be returned.
* *

@ -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() {
}
}

@ -78,6 +78,7 @@ public class AudioNode extends Node implements AudioSource {
protected transient AudioData data = null; protected transient AudioData data = null;
protected transient volatile AudioSource.Status status = AudioSource.Status.Stopped; protected transient volatile AudioSource.Status status = AudioSource.Status.Stopped;
protected transient volatile int channel = -1; protected transient volatile int channel = -1;
protected Vector3f previousWorldTranslation = Vector3f.NAN;
protected Vector3f velocity = new Vector3f(); protected Vector3f velocity = new Vector3f();
protected boolean reverbEnabled = false; protected boolean reverbEnabled = false;
protected float maxDistance = 200; // 200 meters protected float maxDistance = 200; // 200 meters
@ -88,6 +89,8 @@ public class AudioNode extends Node implements AudioSource {
protected float innerAngle = 360; protected float innerAngle = 360;
protected float outerAngle = 360; protected float outerAngle = 360;
protected boolean positional = true; protected boolean positional = true;
protected boolean velocityFromTranslation = false;
protected float lastTpf;
/** /**
* <code>Status</code> indicates the current status of the audio node. * <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 @Override
public void updateGeometricState(){ public void updateLogicalState(float tpf) {
boolean updatePos = false; super.updateLogicalState(tpf);
if ((refreshFlags & RF_TRANSFORM) != 0){ lastTpf = tpf;
updatePos = true; }
}
@Override
public void updateGeometricState() {
super.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); 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 @Override
@ -772,6 +802,7 @@ public class AudioNode extends Node implements AudioSource {
oc.write(outerAngle, "outer_angle", 360); oc.write(outerAngle, "outer_angle", 360);
oc.write(positional, "positional", false); oc.write(positional, "positional", false);
oc.write(velocityFromTranslation, "velocity_from_translation", false);
} }
@Override @Override
@ -806,6 +837,7 @@ public class AudioNode extends Node implements AudioSource {
outerAngle = ic.readFloat("outer_angle", 360); outerAngle = ic.readFloat("outer_angle", 360);
positional = ic.readBoolean("positional", false); positional = ic.readBoolean("positional", false);
velocityFromTranslation = ic.readBoolean("velocity_from_translation", false);
if (audioKey != null) { if (audioKey != null) {
try { try {

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

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

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

@ -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;
*/
}
}

@ -50,8 +50,9 @@ public abstract class ParticleMesh extends Mesh {
public enum Type { public enum Type {
/** /**
* The particle mesh is composed of points. Each particle is a point. * 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} * Note that point based particles do not support certain features such
* to render particles the usual way. * as {@link ParticleEmitter#setRotateSpeed(float) rotation}, and
* {@link ParticleEmitter#setFacingVelocity(boolean) velocity following}.
*/ */
Point, Point,

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

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

@ -75,12 +75,11 @@ public class RenderState implements Cloneable, Savable {
/** /**
* <code>TestFunction</code> specifies the testing function for stencil test * <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 * <p>
* test function, the reference value given in the stencil command is * The reference value given in the stencil command is the input value while
* the input value while the reference is the value already in the stencil * the reference is the value already in the stencil buffer.
* buffer.
*/ */
public enum TestFunction { public enum TestFunction {
@ -118,7 +117,94 @@ public class RenderState implements Cloneable, Savable {
/** /**
* The test always passes * 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. * <code>BlendMode</code> specifies the blending operation to use.
@ -276,19 +362,16 @@ public class RenderState implements Cloneable, Savable {
} }
static { static {
ADDITIONAL.applyPointSprite = false;
ADDITIONAL.applyWireFrame = false; ADDITIONAL.applyWireFrame = false;
ADDITIONAL.applyCullMode = false; ADDITIONAL.applyCullMode = false;
ADDITIONAL.applyDepthWrite = false; ADDITIONAL.applyDepthWrite = false;
ADDITIONAL.applyDepthTest = false; ADDITIONAL.applyDepthTest = false;
ADDITIONAL.applyColorWrite = false; ADDITIONAL.applyColorWrite = false;
ADDITIONAL.applyBlendEquation = false;
ADDITIONAL.applyBlendEquationAlpha = false;
ADDITIONAL.applyBlendMode = false; ADDITIONAL.applyBlendMode = false;
ADDITIONAL.applyAlphaTest = false;
ADDITIONAL.applyAlphaFallOff = false;
ADDITIONAL.applyPolyOffset = false; ADDITIONAL.applyPolyOffset = false;
} }
boolean pointSprite = false;
boolean applyPointSprite = true;
boolean wireframe = false; boolean wireframe = false;
boolean applyWireFrame = true; boolean applyWireFrame = true;
FaceCullMode cullMode = FaceCullMode.Back; FaceCullMode cullMode = FaceCullMode.Back;
@ -299,12 +382,12 @@ public class RenderState implements Cloneable, Savable {
boolean applyDepthTest = true; boolean applyDepthTest = true;
boolean colorWrite = true; boolean colorWrite = true;
boolean applyColorWrite = true; boolean applyColorWrite = true;
BlendEquation blendEquation = BlendEquation.Add;
boolean applyBlendEquation = true;
BlendEquationAlpha blendEquationAlpha = BlendEquationAlpha.InheritColor;
boolean applyBlendEquationAlpha = true;
BlendMode blendMode = BlendMode.Off; BlendMode blendMode = BlendMode.Off;
boolean applyBlendMode = true; boolean applyBlendMode = true;
boolean alphaTest = false;
boolean applyAlphaTest = true;
float alphaFallOff = 0;
boolean applyAlphaFallOff = true;
float offsetFactor = 0; float offsetFactor = 0;
float offsetUnits = 0; float offsetUnits = 0;
boolean offsetEnabled = false; boolean offsetEnabled = false;
@ -316,9 +399,6 @@ public class RenderState implements Cloneable, Savable {
TestFunction depthFunc = TestFunction.LessOrEqual; TestFunction depthFunc = TestFunction.LessOrEqual;
//by default depth func will be applied anyway if depth test is applied //by default depth func will be applied anyway if depth test is applied
boolean applyDepthFunc = false; boolean applyDepthFunc = false;
//by default alpha func will be applied anyway if alpha test is applied
TestFunction alphaFunc = TestFunction.Greater;
boolean applyAlphaFunc = false;
StencilOperation frontStencilStencilFailOperation = StencilOperation.Keep; StencilOperation frontStencilStencilFailOperation = StencilOperation.Keep;
StencilOperation frontStencilDepthFailOperation = StencilOperation.Keep; StencilOperation frontStencilDepthFailOperation = StencilOperation.Keep;
StencilOperation frontStencilDepthPassOperation = StencilOperation.Keep; StencilOperation frontStencilDepthPassOperation = StencilOperation.Keep;
@ -331,15 +411,13 @@ public class RenderState implements Cloneable, Savable {
public void write(JmeExporter ex) throws IOException { public void write(JmeExporter ex) throws IOException {
OutputCapsule oc = ex.getCapsule(this); OutputCapsule oc = ex.getCapsule(this);
oc.write(pointSprite, "pointSprite", false); oc.write(true, "pointSprite", false);
oc.write(wireframe, "wireframe", false); oc.write(wireframe, "wireframe", false);
oc.write(cullMode, "cullMode", FaceCullMode.Back); oc.write(cullMode, "cullMode", FaceCullMode.Back);
oc.write(depthWrite, "depthWrite", true); oc.write(depthWrite, "depthWrite", true);
oc.write(depthTest, "depthTest", true); oc.write(depthTest, "depthTest", true);
oc.write(colorWrite, "colorWrite", true); oc.write(colorWrite, "colorWrite", true);
oc.write(blendMode, "blendMode", BlendMode.Off); oc.write(blendMode, "blendMode", BlendMode.Off);
oc.write(alphaTest, "alphaTest", false);
oc.write(alphaFallOff, "alphaFallOff", 0);
oc.write(offsetEnabled, "offsetEnabled", false); oc.write(offsetEnabled, "offsetEnabled", false);
oc.write(offsetFactor, "offsetFactor", 0); oc.write(offsetFactor, "offsetFactor", 0);
oc.write(offsetUnits, "offsetUnits", 0); oc.write(offsetUnits, "offsetUnits", 0);
@ -352,38 +430,34 @@ public class RenderState implements Cloneable, Savable {
oc.write(backStencilDepthPassOperation, "backStencilDepthPassOperation", StencilOperation.Keep); oc.write(backStencilDepthPassOperation, "backStencilDepthPassOperation", StencilOperation.Keep);
oc.write(frontStencilFunction, "frontStencilFunction", TestFunction.Always); oc.write(frontStencilFunction, "frontStencilFunction", TestFunction.Always);
oc.write(backStencilFunction, "backStencilFunction", 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(depthFunc, "depthFunc", TestFunction.LessOrEqual);
oc.write(alphaFunc, "alphaFunc", TestFunction.Greater);
oc.write(lineWidth, "lineWidth", 1); oc.write(lineWidth, "lineWidth", 1);
// Only "additional render state" has them set to false by default // Only "additional render state" has them set to false by default
oc.write(applyPointSprite, "applyPointSprite", true);
oc.write(applyWireFrame, "applyWireFrame", true); oc.write(applyWireFrame, "applyWireFrame", true);
oc.write(applyCullMode, "applyCullMode", true); oc.write(applyCullMode, "applyCullMode", true);
oc.write(applyDepthWrite, "applyDepthWrite", true); oc.write(applyDepthWrite, "applyDepthWrite", true);
oc.write(applyDepthTest, "applyDepthTest", true); oc.write(applyDepthTest, "applyDepthTest", true);
oc.write(applyColorWrite, "applyColorWrite", true); oc.write(applyColorWrite, "applyColorWrite", true);
oc.write(applyBlendEquation, "applyBlendEquation", true);
oc.write(applyBlendEquationAlpha, "applyBlendEquationAlpha", true);
oc.write(applyBlendMode, "applyBlendMode", true); oc.write(applyBlendMode, "applyBlendMode", true);
oc.write(applyAlphaTest, "applyAlphaTest", true);
oc.write(applyAlphaFallOff, "applyAlphaFallOff", true);
oc.write(applyPolyOffset, "applyPolyOffset", true); oc.write(applyPolyOffset, "applyPolyOffset", true);
oc.write(applyDepthFunc, "applyDepthFunc", true); oc.write(applyDepthFunc, "applyDepthFunc", true);
oc.write(applyAlphaFunc, "applyAlphaFunc", false);
oc.write(applyLineWidth, "applyLineWidth", true); oc.write(applyLineWidth, "applyLineWidth", true);
} }
public void read(JmeImporter im) throws IOException { public void read(JmeImporter im) throws IOException {
InputCapsule ic = im.getCapsule(this); InputCapsule ic = im.getCapsule(this);
pointSprite = ic.readBoolean("pointSprite", false);
wireframe = ic.readBoolean("wireframe", false); wireframe = ic.readBoolean("wireframe", false);
cullMode = ic.readEnum("cullMode", FaceCullMode.class, FaceCullMode.Back); cullMode = ic.readEnum("cullMode", FaceCullMode.class, FaceCullMode.Back);
depthWrite = ic.readBoolean("depthWrite", true); depthWrite = ic.readBoolean("depthWrite", true);
depthTest = ic.readBoolean("depthTest", true); depthTest = ic.readBoolean("depthTest", true);
colorWrite = ic.readBoolean("colorWrite", true); colorWrite = ic.readBoolean("colorWrite", true);
blendMode = ic.readEnum("blendMode", BlendMode.class, BlendMode.Off); blendMode = ic.readEnum("blendMode", BlendMode.class, BlendMode.Off);
alphaTest = ic.readBoolean("alphaTest", false);
alphaFallOff = ic.readFloat("alphaFallOff", 0);
offsetEnabled = ic.readBoolean("offsetEnabled", false); offsetEnabled = ic.readBoolean("offsetEnabled", false);
offsetFactor = ic.readFloat("offsetFactor", 0); offsetFactor = ic.readFloat("offsetFactor", 0);
offsetUnits = ic.readFloat("offsetUnits", 0); offsetUnits = ic.readFloat("offsetUnits", 0);
@ -396,23 +470,22 @@ public class RenderState implements Cloneable, Savable {
backStencilDepthPassOperation = ic.readEnum("backStencilDepthPassOperation", StencilOperation.class, StencilOperation.Keep); backStencilDepthPassOperation = ic.readEnum("backStencilDepthPassOperation", StencilOperation.class, StencilOperation.Keep);
frontStencilFunction = ic.readEnum("frontStencilFunction", TestFunction.class, TestFunction.Always); frontStencilFunction = ic.readEnum("frontStencilFunction", TestFunction.class, TestFunction.Always);
backStencilFunction = ic.readEnum("backStencilFunction", 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); depthFunc = ic.readEnum("depthFunc", TestFunction.class, TestFunction.LessOrEqual);
alphaFunc = ic.readEnum("alphaFunc", TestFunction.class, TestFunction.Greater);
lineWidth = ic.readFloat("lineWidth", 1); lineWidth = ic.readFloat("lineWidth", 1);
applyPointSprite = ic.readBoolean("applyPointSprite", true);
applyWireFrame = ic.readBoolean("applyWireFrame", true); applyWireFrame = ic.readBoolean("applyWireFrame", true);
applyCullMode = ic.readBoolean("applyCullMode", true); applyCullMode = ic.readBoolean("applyCullMode", true);
applyDepthWrite = ic.readBoolean("applyDepthWrite", true); applyDepthWrite = ic.readBoolean("applyDepthWrite", true);
applyDepthTest = ic.readBoolean("applyDepthTest", true); applyDepthTest = ic.readBoolean("applyDepthTest", true);
applyColorWrite = ic.readBoolean("applyColorWrite", true); applyColorWrite = ic.readBoolean("applyColorWrite", true);
applyBlendEquation = ic.readBoolean("applyBlendEquation", true);
applyBlendEquationAlpha = ic.readBoolean("applyBlendEquationAlpha", true);
applyBlendMode = ic.readBoolean("applyBlendMode", true); applyBlendMode = ic.readBoolean("applyBlendMode", true);
applyAlphaTest = ic.readBoolean("applyAlphaTest", true);
applyAlphaFallOff = ic.readBoolean("applyAlphaFallOff", true);
applyPolyOffset = ic.readBoolean("applyPolyOffset", true); applyPolyOffset = ic.readBoolean("applyPolyOffset", true);
applyDepthFunc = ic.readBoolean("applyDepthFunc", true); applyDepthFunc = ic.readBoolean("applyDepthFunc", true);
applyAlphaFunc = ic.readBoolean("applyAlphaFunc", false);
applyLineWidth = ic.readBoolean("applyLineWidth", true); 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 * returns true if the given renderState is equal to this one
* @param o the renderState to compate to * @param o the renderState to compare to
* @return true if the renderStates are equal * @return true if the renderStates are equal
*/ */
@Override @Override
@ -446,9 +519,6 @@ public class RenderState implements Cloneable, Savable {
return false; return false;
} }
RenderState rs = (RenderState) o; RenderState rs = (RenderState) o;
if (pointSprite != rs.pointSprite) {
return false;
}
if (wireframe != rs.wireframe) { if (wireframe != rs.wireframe) {
return false; return false;
@ -475,23 +545,19 @@ public class RenderState implements Cloneable, Savable {
return false; return false;
} }
if (blendMode != rs.blendMode) { if (blendEquation != rs.blendEquation) {
return false; return false;
} }
if (alphaTest != rs.alphaTest) { if (blendEquationAlpha != rs.blendEquationAlpha) {
return false; return false;
} }
if (alphaTest) {
if (alphaFunc != rs.alphaFunc) {
return false;
}
}
if (alphaFallOff != rs.alphaFallOff) { if (blendMode != rs.blendMode) {
return false; return false;
} }
if (offsetEnabled != rs.offsetEnabled) { if (offsetEnabled != rs.offsetEnabled) {
return false; return false;
} }
@ -544,70 +610,30 @@ public class RenderState implements Cloneable, Savable {
} }
/** /**
* Enables point sprite mode. * @deprecated Does nothing. Point sprite is already enabled by default for
* * all supported platforms. jME3 does not support rendering conventional
* <p>When point sprite is enabled, any meshes * point clouds.
* 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
public void setPointSprite(boolean pointSprite) { public void setPointSprite(boolean pointSprite) {
applyPointSprite = true;
this.pointSprite = pointSprite;
cachedHashCode = -1;
} }
/** /**
* Sets the alpha fall off value for alpha testing. * @deprecated Does nothing. To use alpha test, set the
* * <code>AlphaDiscardThreshold</code> material parameter.
* <p>If the pixel's alpha value is greater than the * @param alphaFallOff does nothing
* <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
public void setAlphaFallOff(float alphaFallOff) { public void setAlphaFallOff(float alphaFallOff) {
applyAlphaFallOff = true;
this.alphaFallOff = alphaFallOff;
cachedHashCode = -1;
} }
/** /**
* Enable alpha testing. * @deprecated Does nothing. To use alpha test, set the
* * <code>AlphaDiscardThreshold</code> material parameter.
* <p>When alpha testing is enabled, all input pixels' alpha are compared * @param alphaTest does nothing
* 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
public void setAlphaTest(boolean alphaTest) { public void setAlphaTest(boolean alphaTest) {
applyAlphaTest = true;
this.alphaTest = alphaTest;
cachedHashCode = -1;
} }
/** /**
@ -663,6 +689,61 @@ public class RenderState implements Cloneable, Savable {
cachedHashCode = -1; 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. * Enable depth testing.
* *
@ -796,24 +877,10 @@ public class RenderState implements Cloneable, Savable {
} }
/** /**
* Sets the alpha comparision function to the given TestFunction * @deprecated
* 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) { public void setAlphaFunc(TestFunction alphaFunc) {
applyAlphaFunc = true;
this.alphaFunc = alphaFunc;
cachedHashCode = -1;
} }
/** /**
@ -991,6 +1058,24 @@ public class RenderState implements Cloneable, Savable {
return backStencilFunction; 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. * Retrieve the blend mode.
* *
@ -1001,25 +1086,22 @@ public class RenderState implements Cloneable, Savable {
} }
/** /**
* Check if point sprite mode is enabled * @return true
* * @deprecated Always returns true since point sprite is always enabled.
* @return True if point sprite mode is enabled. * @see #setPointSprite(boolean)
*
* @see RenderState#setPointSprite(boolean)
*/ */
@Deprecated
public boolean isPointSprite() { public boolean isPointSprite() {
return pointSprite; return true;
} }
/** /**
* Check if alpha test is enabled. * @deprecated To use alpha test, set the <code>AlphaDiscardThreshold</code>
* * material parameter.
* @return True if alpha test is enabled. * @return false
*
* @see RenderState#setAlphaTest(boolean)
*/ */
public boolean isAlphaTest() { public boolean isAlphaTest() {
return alphaTest; return false;
} }
/** /**
@ -1111,14 +1193,12 @@ public class RenderState implements Cloneable, Savable {
} }
/** /**
* Retrieve the alpha falloff value. * @return 0
* * @deprecated
* @return the alpha falloff value.
*
* @see RenderState#setAlphaFallOff(float)
*/ */
@Deprecated
public float getAlphaFallOff() { public float getAlphaFallOff() {
return alphaFallOff; return 0f;
} }
/** /**
@ -1133,14 +1213,12 @@ public class RenderState implements Cloneable, Savable {
} }
/** /**
* Retrieve the alpha comparison function * @return {@link TestFunction#Greater}.
* * @deprecated
* @return the alpha comparison function
*
* @see RenderState#setAlphaFunc(com.jme3.material.RenderState.TestFunction)
*/ */
@Deprecated
public TestFunction getAlphaFunc() { 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() { public boolean isApplyBlendEquation() {
return applyAlphaTest; return applyBlendEquation;
} }
public boolean isApplyBlendMode() { public boolean isApplyBlendEquationAlpha() {
return applyBlendMode; return applyBlendEquationAlpha;
} }
public boolean isApplyColorWrite() { public boolean isApplyColorWrite() {
@ -1181,9 +1260,6 @@ public class RenderState implements Cloneable, Savable {
return applyDepthWrite; return applyDepthWrite;
} }
public boolean isApplyPointSprite() {
return applyPointSprite;
}
public boolean isApplyPolyOffset() { public boolean isApplyPolyOffset() {
return applyPolyOffset; return applyPolyOffset;
@ -1197,9 +1273,6 @@ public class RenderState implements Cloneable, Savable {
return applyDepthFunc; return applyDepthFunc;
} }
public boolean isApplyAlphaFunc() {
return applyAlphaFunc;
}
public boolean isApplyLineWidth() { public boolean isApplyLineWidth() {
return applyLineWidth; return applyLineWidth;
@ -1211,7 +1284,6 @@ public class RenderState implements Cloneable, Savable {
public int contentHashCode() { public int contentHashCode() {
if (cachedHashCode == -1){ if (cachedHashCode == -1){
int hash = 7; int hash = 7;
hash = 79 * hash + (this.pointSprite ? 1 : 0);
hash = 79 * hash + (this.wireframe ? 1 : 0); hash = 79 * hash + (this.wireframe ? 1 : 0);
hash = 79 * hash + (this.cullMode != null ? this.cullMode.hashCode() : 0); hash = 79 * hash + (this.cullMode != null ? this.cullMode.hashCode() : 0);
hash = 79 * hash + (this.depthWrite ? 1 : 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.depthFunc != null ? this.depthFunc.hashCode() : 0);
hash = 79 * hash + (this.colorWrite ? 1 : 0); hash = 79 * hash + (this.colorWrite ? 1 : 0);
hash = 79 * hash + (this.blendMode != null ? this.blendMode.hashCode() : 0); hash = 79 * hash + (this.blendMode != null ? this.blendMode.hashCode() : 0);
hash = 79 * hash + (this.alphaTest ? 1 : 0); hash = 79 * hash + (this.blendEquation != null ? this.blendEquation.hashCode() : 0);
hash = 79 * hash + (this.alphaFunc != null ? this.alphaFunc.hashCode() : 0); hash = 79 * hash + (this.blendEquationAlpha != null ? this.blendEquationAlpha.hashCode() : 0);
hash = 79 * hash + Float.floatToIntBits(this.alphaFallOff);
hash = 79 * hash + Float.floatToIntBits(this.offsetFactor); hash = 79 * hash + Float.floatToIntBits(this.offsetFactor);
hash = 79 * hash + Float.floatToIntBits(this.offsetUnits); hash = 79 * hash + Float.floatToIntBits(this.offsetUnits);
hash = 79 * hash + (this.offsetEnabled ? 1 : 0); hash = 79 * hash + (this.offsetEnabled ? 1 : 0);
@ -1266,11 +1337,6 @@ public class RenderState implements Cloneable, Savable {
return this; return this;
} }
if (additionalState.applyPointSprite) {
state.pointSprite = additionalState.pointSprite;
} else {
state.pointSprite = pointSprite;
}
if (additionalState.applyWireFrame) { if (additionalState.applyWireFrame) {
state.wireframe = additionalState.wireframe; state.wireframe = additionalState.wireframe;
} else { } else {
@ -1302,27 +1368,22 @@ public class RenderState implements Cloneable, Savable {
} else { } else {
state.colorWrite = colorWrite; state.colorWrite = colorWrite;
} }
if (additionalState.applyBlendMode) { if (additionalState.applyBlendEquation) {
state.blendMode = additionalState.blendMode; state.blendEquation = additionalState.blendEquation;
} else { } else {
state.blendMode = blendMode; state.blendEquation = blendEquation;
} }
if (additionalState.applyAlphaTest) { if (additionalState.applyBlendEquationAlpha) {
state.alphaTest = additionalState.alphaTest; state.blendEquationAlpha = additionalState.blendEquationAlpha;
} else { } else {
state.alphaTest = alphaTest; state.blendEquationAlpha = blendEquationAlpha;
} }
if (additionalState.applyAlphaFunc) { if (additionalState.applyBlendMode) {
state.alphaFunc = additionalState.alphaFunc; state.blendMode = additionalState.blendMode;
} else { } else {
state.alphaFunc = alphaFunc; state.blendMode = blendMode;
} }
if (additionalState.applyAlphaFallOff) {
state.alphaFallOff = additionalState.alphaFallOff;
} else {
state.alphaFallOff = alphaFallOff;
}
if (additionalState.applyPolyOffset) { if (additionalState.applyPolyOffset) {
state.offsetEnabled = additionalState.offsetEnabled; state.offsetEnabled = additionalState.offsetEnabled;
state.offsetFactor = additionalState.offsetFactor; state.offsetFactor = additionalState.offsetFactor;
@ -1367,16 +1428,14 @@ public class RenderState implements Cloneable, Savable {
state.cachedHashCode = -1; state.cachedHashCode = -1;
return state; return state;
} }
public void set(RenderState state) {
pointSprite = state.pointSprite; public void set(RenderState state) {
wireframe = state.wireframe; wireframe = state.wireframe;
cullMode = state.cullMode; cullMode = state.cullMode;
depthWrite = state.depthWrite; depthWrite = state.depthWrite;
depthTest = state.depthTest; depthTest = state.depthTest;
colorWrite = state.colorWrite; colorWrite = state.colorWrite;
blendMode = state.blendMode; blendMode = state.blendMode;
alphaTest = state.alphaTest;
alphaFallOff = state.alphaFallOff;
offsetEnabled = state.offsetEnabled; offsetEnabled = state.offsetEnabled;
offsetFactor = state.offsetFactor; offsetFactor = state.offsetFactor;
offsetUnits = state.offsetUnits; offsetUnits = state.offsetUnits;
@ -1389,30 +1448,27 @@ public class RenderState implements Cloneable, Savable {
backStencilDepthPassOperation = state.backStencilDepthPassOperation; backStencilDepthPassOperation = state.backStencilDepthPassOperation;
frontStencilFunction = state.frontStencilFunction; frontStencilFunction = state.frontStencilFunction;
backStencilFunction = state.backStencilFunction; backStencilFunction = state.backStencilFunction;
blendEquationAlpha = state.blendEquationAlpha;
blendEquation = state.blendEquation;
depthFunc = state.depthFunc; depthFunc = state.depthFunc;
alphaFunc = state.alphaFunc;
lineWidth = state.lineWidth; lineWidth = state.lineWidth;
applyPointSprite = true;
applyWireFrame = true; applyWireFrame = true;
applyCullMode = true; applyCullMode = true;
applyDepthWrite = true; applyDepthWrite = true;
applyDepthTest = true; applyDepthTest = true;
applyColorWrite = true; applyColorWrite = true;
applyBlendMode = true; applyBlendEquation = true;
applyAlphaTest = true; applyBlendEquationAlpha = true;
applyAlphaFallOff = true; applyBlendMode = true;
applyPolyOffset = true; applyPolyOffset = true;
applyDepthFunc = true; applyDepthFunc = true;
applyAlphaFunc = false;
applyLineWidth = true; applyLineWidth = true;
} }
@Override @Override
public String toString() { public String toString() {
return "RenderState[\n" return "RenderState[\n"
+ "pointSprite=" + pointSprite
+ "\napplyPointSprite=" + applyPointSprite
+ "\nwireframe=" + wireframe + "\nwireframe=" + wireframe
+ "\napplyWireFrame=" + applyWireFrame + "\napplyWireFrame=" + applyWireFrame
+ "\ncullMode=" + cullMode + "\ncullMode=" + cullMode
@ -1424,13 +1480,11 @@ public class RenderState implements Cloneable, Savable {
+ "\napplyDepthTest=" + applyDepthTest + "\napplyDepthTest=" + applyDepthTest
+ "\ncolorWrite=" + colorWrite + "\ncolorWrite=" + colorWrite
+ "\napplyColorWrite=" + applyColorWrite + "\napplyColorWrite=" + applyColorWrite
+ "\nblendEquation=" + blendEquation
+ "\napplyBlendEquation=" + applyBlendEquation
+ "\napplyBlendEquationAlpha=" + applyBlendEquationAlpha
+ "\nblendMode=" + blendMode + "\nblendMode=" + blendMode
+ "\napplyBlendMode=" + applyBlendMode + "\napplyBlendMode=" + applyBlendMode
+ "\nalphaTest=" + alphaTest
+ "\nalphaFunc=" + alphaFunc
+ "\napplyAlphaTest=" + applyAlphaTest
+ "\nalphaFallOff=" + alphaFallOff
+ "\napplyAlphaFallOff=" + applyAlphaFallOff
+ "\noffsetEnabled=" + offsetEnabled + "\noffsetEnabled=" + offsetEnabled
+ "\napplyPolyOffset=" + applyPolyOffset + "\napplyPolyOffset=" + applyPolyOffset
+ "\noffsetFactor=" + offsetFactor + "\noffsetFactor=" + offsetFactor

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

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

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

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

@ -41,42 +41,25 @@ package com.jme3.renderer;
*/ */
public enum Limits { public enum Limits {
/** /**
* Maximum number of vertex texture units, or number of textures * Maximum number of vertex texture units, or number of textures that can be
* that can be used in the vertex shader. * used in the vertex shader.
*/ */
VertexTextureUnits, VertexTextureUnits,
/** /**
* Maximum number of fragment texture units, or number of textures * Maximum number of fragment texture units, or number of textures that can
* that can be used in the fragment shader. * be used in the fragment shader.
*/ */
FragmentTextureUnits, FragmentTextureUnits,
FragmentUniformVectors,
FragmentUniforms, VertexUniformVectors,
VertexAttributes, VertexAttributes,
FrameBufferSamples, FrameBufferSamples,
FrameBufferAttachments, FrameBufferAttachments,
FrameBufferMrtAttachments, FrameBufferMrtAttachments,
RenderBufferSize, RenderBufferSize,
TextureSize, TextureSize,
CubemapSize, CubemapSize,
VertexCount,
TriangleCount,
ColorTextureSamples, ColorTextureSamples,
DepthTextureSamples, DepthTextureSamples,
VertexUniformVectors,
TextureAnisotropy, TextureAnisotropy,
} }

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

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

@ -43,6 +43,7 @@ import com.jme3.texture.Image;
import com.jme3.texture.Texture; import com.jme3.texture.Texture;
import com.jme3.util.NativeObject; import com.jme3.util.NativeObject;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.EnumMap;
import java.util.EnumSet; import java.util.EnumSet;
/** /**
@ -66,6 +67,13 @@ public interface Renderer {
*/ */
public EnumSet<Caps> getCaps(); 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 * The statistics allow tracking of how data
* per frame, such as number of objects rendered, number of triangles, etc. * per frame, such as number of objects rendered, number of triangles, etc.
@ -303,6 +311,20 @@ public interface Renderer {
*/ */
public void cleanup(); 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. * Sets the alpha to coverage state.
* <p> * <p>

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

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

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

@ -90,6 +90,7 @@ public final class GLRenderer implements Renderer {
private final Statistics statistics = new Statistics(); private final Statistics statistics = new Statistics();
private int vpX, vpY, vpW, vpH; private int vpX, vpY, vpW, vpH;
private int clipX, clipY, clipW, clipH; private int clipX, clipY, clipW, clipH;
private int defaultAnisotropicFilter = 1;
private boolean linearizeSrgbImages; private boolean linearizeSrgbImages;
private HashSet<String> extensions; 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)); 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)) { 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)); limits.put(Limits.VertexUniformVectors, getInteger(GL.GL_MAX_VERTEX_UNIFORM_VECTORS));
} else { } 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.VertexUniformVectors, getInteger(GL.GL_MAX_VERTEX_UNIFORM_COMPONENTS) / 4);
} }
limits.put(Limits.VertexAttributes, getInteger(GL.GL_MAX_VERTEX_ATTRIBS)); limits.put(Limits.VertexAttributes, getInteger(GL.GL_MAX_VERTEX_ATTRIBS));
limits.put(Limits.TextureSize, getInteger(GL.GL_MAX_TEXTURE_SIZE)); limits.put(Limits.TextureSize, getInteger(GL.GL_MAX_TEXTURE_SIZE));
limits.put(Limits.CubemapSize, getInteger(GL.GL_MAX_CUBE_MAP_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); gl2.glEnable(GL2.GL_VERTEX_PROGRAM_POINT_SIZE);
if (!caps.contains(Caps.CoreProfile)) { if (!caps.contains(Caps.CoreProfile)) {
gl2.glEnable(GL2.GL_POINT_SPRITE); 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) { public void setAlphaToCoverage(boolean value) {
if (caps.contains(Caps.Multisample)) { if (caps.contains(Caps.Multisample)) {
if (value) { if (value) {
@ -746,6 +750,19 @@ public final class GLRenderer implements Renderer {
throw new UnsupportedOperationException("Unrecognized blend mode: " throw new UnsupportedOperationException("Unrecognized blend mode: "
+ state.getBlendMode()); + 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(); 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) { private int convertStencilOperation(StencilOperation stencilOp) {
switch (stencilOp) { switch (stencilOp) {
case Keep: case Keep:
@ -1883,13 +1935,18 @@ public final class GLRenderer implements Renderer {
gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, convertMinFilter(tex.getMinFilter(), haveMips)); gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, convertMinFilter(tex.getMinFilter(), haveMips));
curState.minFilter = tex.getMinFilter(); curState.minFilter = tex.getMinFilter();
} }
int desiredAnisoFilter = tex.getAnisotropicFilter() == 0
? defaultAnisotropicFilter
: tex.getAnisotropicFilter();
if (caps.contains(Caps.TextureFilterAnisotropic) if (caps.contains(Caps.TextureFilterAnisotropic)
&& curState.anisoFilter != tex.getAnisotropicFilter()) { && curState.anisoFilter != desiredAnisoFilter) {
bindTextureAndUnit(target, image, unit); bindTextureAndUnit(target, image, unit);
gl.glTexParameterf(target, gl.glTexParameterf(target,
GLExt.GL_TEXTURE_MAX_ANISOTROPY_EXT, GLExt.GL_TEXTURE_MAX_ANISOTROPY_EXT,
tex.getAnisotropicFilter()); desiredAnisoFilter);
curState.anisoFilter = tex.getAnisotropicFilter(); curState.anisoFilter = desiredAnisoFilter;
} }
switch (tex.getType()) { switch (tex.getType()) {

@ -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) * @see #setPointSize(float)
*/ */
@Deprecated
public float getPointSize() { public float getPointSize() {
return pointSize; return 1.0f;
} }
/** /**
* Set the size of points for meshes of mode {@link Mode#Points}. * @deprecated Does nothing, since the size of {@link Mode#Points points} is
* The point size is specified as on-screen pixels, the default * determined via the vertex shader's <code>gl_PointSize</code> output.
* 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>.
* *
* @param pointSize The size of points * @param pointSize ignored
*/ */
@Deprecated
public void setPointSize(float pointSize) { public void setPointSize(float pointSize) {
this.pointSize = pointSize;
} }
/** /**

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

@ -102,14 +102,6 @@ public class WireBox extends Mesh {
updateBound(); 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. * Create a geometry suitable for visualizing the specified bounding box.
* *

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

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

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

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

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

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

@ -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.ogre.SceneLoader : scene
LOADER com.jme3.scene.plugins.blender.BlenderModelLoader : blend LOADER com.jme3.scene.plugins.blender.BlenderModelLoader : blend
LOADER com.jme3.shader.plugins.GLSLLoader : vert, frag, geom, tsctrl, tseval, glsl, glsllib 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.FbxLoader : fbx
LOADER com.jme3.scene.plugins.fbx.SceneWithAnimationLoader : fba

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

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

@ -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);
}
}

@ -55,6 +55,21 @@ public class J3MLoaderTest {
j3MLoader = new J3MLoader(); 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 @Test
public void multipleSameNamedTechniques_shouldBeSupported() throws IOException { public void multipleSameNamedTechniques_shouldBeSupported() throws IOException {
when(assetInfo.openStream()).thenReturn(J3MLoader.class.getResourceAsStream("/same-name-technique.j3md")); when(assetInfo.openStream()).thenReturn(J3MLoader.class.getResourceAsStream("/same-name-technique.j3md"));

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

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

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

@ -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;
}
}
}

@ -139,7 +139,8 @@ public class TestCameraMotionPath extends SimpleApplication {
rootNode.attachChild(teapot); 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); soil.setMaterial(matSoil);
rootNode.attachChild(soil); rootNode.attachChild(soil);
DirectionalLight light = new DirectionalLight(); DirectionalLight light = new DirectionalLight();

@ -222,7 +222,8 @@ public class TestCinematic extends SimpleApplication {
matSoil.setColor("Diffuse", ColorRGBA.Green); matSoil.setColor("Diffuse", ColorRGBA.Green);
matSoil.setColor("Specular", ColorRGBA.Black); 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.setMaterial(matSoil);
soil.setShadowMode(ShadowMode.Receive); soil.setShadowMode(ShadowMode.Receive);
rootNode.attachChild(soil); rootNode.attachChild(soil);

@ -136,7 +136,8 @@ public class TestMotionPath extends SimpleApplication {
rootNode.attachChild(teapot); 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); soil.setMaterial(matSoil);
rootNode.attachChild(soil); rootNode.attachChild(soil);

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

@ -56,7 +56,7 @@ public class TestBareBonesApp extends LegacyApplication {
System.out.println("Initialize"); System.out.println("Initialize");
// create a box // 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 // load some default material
boxGeom.setMaterial(assetManager.loadMaterial("Interface/Logo/Logo.j3m")); boxGeom.setMaterial(assetManager.loadMaterial("Interface/Logo/Logo.j3m"));

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

@ -69,7 +69,7 @@ public class TestAmbient extends SimpleApplication {
nature.play(); nature.play();
// just a blue box to mark the spot // 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); Geometry player = new Geometry("Player", box1);
Material mat1 = new Material(assetManager, Material mat1 = new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md"); "Common/MatDefs/Misc/Unshaded.j3md");

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

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

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

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

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

@ -193,7 +193,7 @@ public class TestBatchNodeTower extends SimpleApplication {
} }
public void initFloor() { 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)); floorBox.scaleTextureCoordinates(new Vector2f(3, 6));
Geometry floor = new Geometry("floor", floorBox); Geometry floor = new Geometry("floor", floorBox);

@ -112,7 +112,7 @@ public class TestAttachDriver extends SimpleApplication implements ActionListene
tex.setMinFilter(Texture.MinFilter.Trilinear); tex.setMinFilter(Texture.MinFilter.Trilinear);
mat.setTexture("ColorMap", tex); 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); Geometry floorGeom = new Geometry("Floor", floor);
floorGeom.setMaterial(mat); floorGeom.setMaterial(mat);
floorGeom.setLocalTranslation(new Vector3f(0f, -3, 0f)); floorGeom.setLocalTranslation(new Vector3f(0f, -3, 0f));

@ -126,7 +126,7 @@ public class TestBrickTower extends SimpleApplication {
bullet.setTextureMode(TextureMode.Projected); bullet.setTextureMode(TextureMode.Projected);
bulletCollisionShape = new SphereCollisionShape(0.4f); 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)); brick.scaleTextureCoordinates(new Vector2f(1f, .5f));
//bulletAppState.getPhysicsSpace().enableDebug(assetManager); //bulletAppState.getPhysicsSpace().enableDebug(assetManager);
initMaterial(); initMaterial();
@ -204,7 +204,7 @@ public class TestBrickTower extends SimpleApplication {
} }
public void initFloor() { 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)); floorBox.scaleTextureCoordinates(new Vector2f(3, 6));
Geometry floor = new Geometry("floor", floorBox); Geometry floor = new Geometry("floor", floorBox);

@ -90,7 +90,7 @@ public class TestBrickWall extends SimpleApplication {
bullet = new Sphere(32, 32, 0.4f, true, false); bullet = new Sphere(32, 32, 0.4f, true, false);
bullet.setTextureMode(TextureMode.Projected); bullet.setTextureMode(TextureMode.Projected);
bulletCollisionShape = new SphereCollisionShape(0.4f); 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)); brick.scaleTextureCoordinates(new Vector2f(1f, .5f));
initMaterial(); initMaterial();
@ -151,7 +151,7 @@ public class TestBrickWall extends SimpleApplication {
} }
public void initFloor() { 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)); floorBox.scaleTextureCoordinates(new Vector2f(3, 6));
Geometry floor = new Geometry("floor", floorBox); Geometry floor = new Geometry("floor", floorBox);

@ -98,7 +98,7 @@ public class TestCcd extends SimpleApplication implements ActionListener {
Node node2 = new Node(); Node node2 = new Node();
node2.setName("mesh"); node2.setName("mesh");
node2.setLocalTranslation(new Vector3f(2.5f, 0, 0f)); 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); rootNode.attachChild(node2);
getPhysicsSpace().add(node2); getPhysicsSpace().add(node2);

@ -85,7 +85,7 @@ public class TestCollisionGroups extends SimpleApplication {
getPhysicsSpace().add(node2); getPhysicsSpace().add(node2);
// the floor, does not move (mass=0) // 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)); node3.getControl(RigidBodyControl.class).setPhysicsLocation(new Vector3f(0f, -6, 0f));
rootNode.attachChild(node3); rootNode.attachChild(node3);
getPhysicsSpace().add(node3); getPhysicsSpace().add(node3);

@ -65,7 +65,7 @@ public class TestGhostObject extends SimpleApplication {
bulletAppState.setDebugEnabled(true); bulletAppState.setDebugEnabled(true);
// Mesh to be shared across several boxes. // 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 to be shared across several boxes.
CollisionShape shape = new BoxCollisionShape(new Vector3f(1, 1, 1)); CollisionShape shape = new BoxCollisionShape(new Vector3f(1, 1, 1));

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

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

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

@ -76,7 +76,7 @@ public class TestSoftParticles extends SimpleApplication {
// -------- floor // -------- 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); Geometry geom = new Geometry("Box", b);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Gray); mat.setColor("Color", ColorRGBA.Gray);
@ -84,7 +84,7 @@ public class TestSoftParticles extends SimpleApplication {
geom.setMaterial(mat); geom.setMaterial(mat);
rootNode.attachChild(geom); 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); Geometry geom2 = new Geometry("Box", b2);
Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat2.setColor("Color", ColorRGBA.DarkGray); mat2.setColor("Color", ColorRGBA.DarkGray);

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

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

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

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

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

@ -76,7 +76,7 @@ public class TestShadow extends SimpleApplication {
Material mat = assetManager.loadMaterial("Common/Materials/WhiteColor.j3m"); Material mat = assetManager.loadMaterial("Common/Materials/WhiteColor.j3m");
rootNode.setShadowMode(ShadowMode.Off); 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); Geometry floorGeom = new Geometry("Floor", floor);
floorGeom.setMaterial(mat); floorGeom.setMaterial(mat);
floorGeom.setLocalTranslation(0,-0.2f,0); floorGeom.setLocalTranslation(0,-0.2f,0);

@ -83,7 +83,7 @@ public class TestShadowsPerf extends SimpleApplication {
mat = assetManager.loadMaterial("Textures/Terrain/Pond/Pond.j3m"); 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)); b.scaleTextureCoordinates(new Vector2f(50, 50));
Geometry ground = new Geometry("ground", b); Geometry ground = new Geometry("ground", b);
ground.setMaterial(mat); ground.setMaterial(mat);

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

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

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

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

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

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

@ -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.setMaterial(matSoil);
soil.setShadowMode(ShadowMode.CastAndReceive); soil.setShadowMode(ShadowMode.CastAndReceive);
rootNode.attachChild(soil); rootNode.attachChild(soil);

@ -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.setMaterial(matSoil);
soil.setShadowMode(ShadowMode.CastAndReceive); soil.setShadowMode(ShadowMode.CastAndReceive);
rootNode.attachChild(soil); rootNode.attachChild(soil);

@ -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.setMaterial(matSoil);
soil.setShadowMode(ShadowMode.CastAndReceive); soil.setShadowMode(ShadowMode.CastAndReceive);
rootNode.attachChild(soil); rootNode.attachChild(soil);

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

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

@ -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);
}
}

@ -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();
}
}

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

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

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

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

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

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

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save