data = img.getData();
@@ -1881,7 +1838,7 @@ public class OGLESShaderRenderer implements Renderer {
TextureUtil.uploadTexture(img, target, i, 0, tdc);
}
}*/else{
- TextureUtil.uploadTexture(gl, img, target, 0, 0, tdc, true, powerOf2);
+ TextureUtil.uploadTexture(img, target, 0, 0, tdc, true, powerOf2);
if (verboseLogging)
logger.info("GLES20.glTexParameteri(" + target + "GLES11.GL_GENERATE_MIMAP, GLES20.GL_TRUE)");
@@ -2843,11 +2800,18 @@ public class OGLESShaderRenderer implements Renderer {
public void setAlphaToCoverage(boolean value)
{
- // TODO Auto-generated method stub
+ if (value) {
+ GLES20.glEnable(GLES20.GL_SAMPLE_ALPHA_TO_COVERAGE);
+ } else {
+ GLES20.glDisable(GLES20.GL_SAMPLE_ALPHA_TO_COVERAGE);
+ }
}
- public void invalidateState(){
- // TODO invalidateState
+ @Override
+ public void invalidateState()
+ {
+ context.reset();
+ boundShader = null;
+ lastFb = null;
}
-
}
diff --git a/engine/src/android/com/jme3/renderer/android/TextureUtil.java b/engine/src/android/com/jme3/renderer/android/TextureUtil.java
index 08ca07051..f1eea426d 100644
--- a/engine/src/android/com/jme3/renderer/android/TextureUtil.java
+++ b/engine/src/android/com/jme3/renderer/android/TextureUtil.java
@@ -1,6 +1,7 @@
package com.jme3.renderer.android;
import android.graphics.Bitmap;
+import android.opengl.GLES20;
import android.opengl.GLUtils;
import com.jme3.math.FastMath;
import com.jme3.texture.Image;
@@ -36,7 +37,7 @@ public class TextureUtil {
}
}
- private static void buildMipmap(GL10 gl, Bitmap bitmap) {
+ private static void buildMipmap(Bitmap bitmap) {
int level = 0;
int height = bitmap.getHeight();
int width = bitmap.getWidth();
@@ -61,7 +62,7 @@ public class TextureUtil {
}
}
- private static void uploadTextureBitmap(GL10 gl, Bitmap bitmap, boolean generateMips, boolean powerOf2){
+ private static void uploadTextureBitmap(Bitmap bitmap, boolean generateMips, boolean powerOf2){
if (!powerOf2){
int width = bitmap.getWidth();
int height = bitmap.getHeight();
@@ -76,7 +77,7 @@ public class TextureUtil {
}
if (generateMips){
- buildMipmap(gl, bitmap);
+ buildMipmap(bitmap);
}else{
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
@@ -84,18 +85,17 @@ public class TextureUtil {
}
public static void uploadTexture(
- GL10 gl,
Image img,
int target,
int index,
int border,
- boolean tdc,
+ boolean tdc,
boolean generateMips,
boolean powerOf2){
if (img.getEfficentData() instanceof Bitmap){
Bitmap bitmap = (Bitmap) img.getEfficentData();
- uploadTextureBitmap(gl, bitmap, generateMips, powerOf2);
+ uploadTextureBitmap(bitmap, generateMips, powerOf2);
// img.setEfficentData(null);
return;
}
@@ -118,71 +118,71 @@ public class TextureUtil {
switch (fmt){
case Alpha16:
- format = gl.GL_ALPHA;
- dataType = gl.GL_UNSIGNED_BYTE;
+ format = GL10.GL_ALPHA;
+ dataType = GL10.GL_UNSIGNED_BYTE;
break;
case Alpha8:
- format = gl.GL_ALPHA;
- dataType = gl.GL_UNSIGNED_BYTE;
+ format = GL10.GL_ALPHA;
+ dataType = GL10.GL_UNSIGNED_BYTE;
break;
case Luminance8:
- format = gl.GL_LUMINANCE;
- dataType = gl.GL_UNSIGNED_BYTE;
+ format = GL10.GL_LUMINANCE;
+ dataType = GL10.GL_UNSIGNED_BYTE;
break;
case Luminance8Alpha8:
- format = gl.GL_LUMINANCE_ALPHA;
- dataType = gl.GL_UNSIGNED_BYTE;
+ format = GL10.GL_LUMINANCE_ALPHA;
+ dataType = GL10.GL_UNSIGNED_BYTE;
break;
case Luminance16Alpha16:
- format = gl.GL_LUMINANCE_ALPHA;
- dataType = gl.GL_UNSIGNED_BYTE;
+ format = GL10.GL_LUMINANCE_ALPHA;
+ dataType = GL10.GL_UNSIGNED_BYTE;
break;
case Luminance16:
- format = gl.GL_LUMINANCE;
- dataType = gl.GL_UNSIGNED_BYTE;
+ format = GL10.GL_LUMINANCE;
+ dataType = GL10.GL_UNSIGNED_BYTE;
break;
case RGB565:
- format = gl.GL_RGB;
- dataType = gl.GL_UNSIGNED_SHORT_5_6_5;
+ format = GL10.GL_RGB;
+ dataType = GL10.GL_UNSIGNED_SHORT_5_6_5;
break;
case ARGB4444:
- format = gl.GL_RGBA;
- dataType = gl.GL_UNSIGNED_SHORT_4_4_4_4;
+ format = GL10.GL_RGBA;
+ dataType = GL10.GL_UNSIGNED_SHORT_4_4_4_4;
break;
case RGB10:
- format = gl.GL_RGB;
- dataType = gl.GL_UNSIGNED_BYTE;
+ format = GL10.GL_RGB;
+ dataType = GL10.GL_UNSIGNED_BYTE;
break;
case RGB16:
- format = gl.GL_RGB;
- dataType = gl.GL_UNSIGNED_BYTE;
+ format = GL10.GL_RGB;
+ dataType = GL10.GL_UNSIGNED_BYTE;
break;
case RGB5A1:
- format = gl.GL_RGBA;
- dataType = gl.GL_UNSIGNED_SHORT_5_5_5_1;
+ format = GL10.GL_RGBA;
+ dataType = GL10.GL_UNSIGNED_SHORT_5_5_5_1;
break;
case RGB8:
- format = gl.GL_RGB;
- dataType = gl.GL_UNSIGNED_BYTE;
+ format = GL10.GL_RGB;
+ dataType = GL10.GL_UNSIGNED_BYTE;
break;
case BGR8:
- format = gl.GL_RGB;
- dataType = gl.GL_UNSIGNED_BYTE;
+ format = GL10.GL_RGB;
+ dataType = GL10.GL_UNSIGNED_BYTE;
break;
case RGBA16:
- format = gl.GL_RGBA;
- dataType = gl.GL_UNSIGNED_BYTE;
+ format = GL10.GL_RGBA;
+ dataType = GL10.GL_UNSIGNED_BYTE;
break;
case RGBA8:
- format = gl.GL_RGBA;
- dataType = gl.GL_UNSIGNED_BYTE;
+ format = GL10.GL_RGBA;
+ dataType = GL10.GL_UNSIGNED_BYTE;
break;
default:
throw new UnsupportedOperationException("Unrecognized format: "+fmt);
}
if (data != null)
- gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1);
+ GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
int[] mipSizes = img.getMipMapSizes();
int pos = 0;
@@ -197,7 +197,7 @@ public class TextureUtil {
// of more than paletted compressions is added..
if (compress){
data.clear();
- gl.glCompressedTexImage2D(gl.GL_TEXTURE_2D,
+ GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D,
1 - mipSizes.length,
format,
width,
@@ -219,7 +219,7 @@ public class TextureUtil {
}
if (compress && data != null){
- gl.glCompressedTexImage2D(gl.GL_TEXTURE_2D,
+ GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D,
i,
format,
mipWidth,
@@ -228,7 +228,7 @@ public class TextureUtil {
data.remaining(),
data);
}else{
- gl.glTexImage2D(gl.GL_TEXTURE_2D,
+ GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D,
i,
format,
mipWidth,
diff --git a/engine/src/android/com/jme3/system/JmeSystem.java b/engine/src/android/com/jme3/system/JmeSystem.java
index f7e07d6cb..c3fb96c2e 100644
--- a/engine/src/android/com/jme3/system/JmeSystem.java
+++ b/engine/src/android/com/jme3/system/JmeSystem.java
@@ -6,8 +6,8 @@ import com.jme3.asset.AndroidAssetManager;
import com.jme3.asset.AssetManager;
import com.jme3.audio.AudioNode;
import com.jme3.audio.AudioData;
-import com.jme3.audio.AudioRenderer;
import com.jme3.audio.AudioParam;
+import com.jme3.audio.AudioRenderer;
import com.jme3.audio.Environment;
import com.jme3.audio.Listener;
import com.jme3.audio.ListenerParam;
@@ -28,6 +28,7 @@ public class JmeSystem {
private static final Logger logger = Logger.getLogger(JmeSystem.class.getName());
private static boolean initialized = false;
+ private static boolean lowPermissions = false;
private static Resources res;
public static void initialize(AppSettings settings){
@@ -51,7 +52,15 @@ public class JmeSystem {
}
public static String getFullName(){
- return "jMonkey Engine 3 ALPHA 0.50";
+ return "jMonkey Engine 3 ALPHA 0.50 Android";
+ }
+
+ public static void setLowPermissions(boolean lowPerm){
+ lowPermissions = lowPerm;
+ }
+
+ public static boolean isLowPermissions() {
+ return lowPermissions;
}
public static JmeContext newContext(AppSettings settings, Type contextType) {
@@ -71,8 +80,15 @@ public class JmeSystem {
public void initialize() {}
public void update(float tpf) {}
public void cleanup() {}
- public void updateListenerParam(Listener listener, ListenerParam parameter) {}
- public void updateSourceParam(AudioNode node, AudioParam parameter) {}
+ public void updateListenerParam(Listener listener,
+ ListenerParam param) {
+ // TODO Auto-generated method stub
+
+ }
+ public void updateSourceParam(AudioNode src, AudioParam param) {
+ // TODO Auto-generated method stub
+
+ }
};
}
@@ -85,16 +101,16 @@ public class JmeSystem {
}
public static AssetManager newAssetManager(){
- logger.info("newAssetManager()");
- return new AndroidAssetManager(true);
+ logger.info("newAssetManager()");
+ return new AndroidAssetManager(null);
}
public static AssetManager newAssetManager(URL url){
- logger.info("newAssetManager(" + url + ")");
- return new AndroidAssetManager(true);
+ logger.info("newAssetManager(" + url + ")");
+ return new AndroidAssetManager(url);
}
- public static boolean showSettingsDialog(AppSettings settings) {
+ public static boolean showSettingsDialog(AppSettings settings, boolean loadSettings) {
return true;
}
diff --git a/engine/src/android/com/jme3/system/android/AndroidTimer.java b/engine/src/android/com/jme3/system/android/AndroidTimer.java
index ef0b76898..4cabc3330 100644
--- a/engine/src/android/com/jme3/system/android/AndroidTimer.java
+++ b/engine/src/android/com/jme3/system/android/AndroidTimer.java
@@ -35,15 +35,14 @@ package com.jme3.system.android;
import com.jme3.system.Timer;
/**
- * NanoTimer
is a System.nanoTime implementation of Timer
.
- * This is primarily useful for headless applications running on a server.
- *
- * @author Matthew D. Hicks
+ * AndroidTimer
is a System.nanoTime implementation of Timer
.
*/
public class AndroidTimer extends Timer {
- private static final long TIMER_RESOLUTION = 1000L;
- private static final float INVERSE_TIMER_RESOLUTION = 1f/1000L;
+ //private static final long TIMER_RESOLUTION = 1000L;
+ //private static final float INVERSE_TIMER_RESOLUTION = 1f/1000L;
+ private static final long TIMER_RESOLUTION = 1000000000L;
+ private static final float INVERSE_TIMER_RESOLUTION = 1f/1000000000L;
private long startTime;
private long previousTime;
@@ -51,7 +50,8 @@ public class AndroidTimer extends Timer {
private float fps;
public AndroidTimer() {
- startTime = System.currentTimeMillis();
+ //startTime = System.currentTimeMillis();
+ startTime = System.nanoTime();
}
/**
@@ -66,7 +66,8 @@ public class AndroidTimer extends Timer {
}
public long getTime() {
- return System.currentTimeMillis() - startTime;
+ //return System.currentTimeMillis() - startTime;
+ return System.nanoTime() - startTime;
}
public long getResolution() {
@@ -88,7 +89,8 @@ public class AndroidTimer extends Timer {
}
public void reset() {
- startTime = System.currentTimeMillis();
+ //startTime = System.currentTimeMillis();
+ startTime = System.nanoTime();
previousTime = getTime();
}
}
diff --git a/engine/src/android/com/jme3/system/android/OGLESContext.java b/engine/src/android/com/jme3/system/android/OGLESContext.java
index 26ac788e1..353bd56ca 100644
--- a/engine/src/android/com/jme3/system/android/OGLESContext.java
+++ b/engine/src/android/com/jme3/system/android/OGLESContext.java
@@ -39,7 +39,6 @@ import com.jme3.input.JoyInput;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.android.AndroidInput;
-//import com.jme3.renderer.android.OGLESRenderer;
import com.jme3.renderer.android.OGLESShaderRenderer;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeContext;
@@ -51,48 +50,60 @@ import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
-public class OGLESContext implements JmeContext, GLSurfaceView.Renderer {
+public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
+{
private static final Logger logger = Logger.getLogger(OGLESContext.class.getName());
- protected AtomicBoolean created = new AtomicBoolean(false);
- protected AppSettings settings = new AppSettings(true);
+ protected final AtomicBoolean created = new AtomicBoolean(false);
+ protected final AtomicBoolean renderable = new AtomicBoolean(false);
+ protected final AtomicBoolean needClose = new AtomicBoolean(false);
+ protected final Object createdLock = new Object();
+ protected final AppSettings settings = new AppSettings(true);
- /* < OpenGL ES 2.0 * */
- //protected OGLESRenderer renderer;
/* >= OpenGL ES 2.0 (Android 2.2+) */
protected OGLESShaderRenderer renderer;
protected Timer timer;
protected SystemListener listener;
- protected AtomicBoolean needClose = new AtomicBoolean(false);
+
protected boolean wasActive = false;
- protected int frameRate = 0;
protected boolean autoFlush = true;
protected AndroidInput view;
+
+ private long milliStart;
+ private long milliDelta;
+ protected int frameRate = 33;
+ //protected int minFrameDuration = 1000 / frameRate; // Set a max FPS of 33
+ protected int minFrameDuration = 0; // No FPS cap
- public OGLESContext(){
- }
+ public OGLESContext() { }
- public Type getType() {
+ @Override
+ public Type getType()
+ {
return Type.Display;
}
-
- public GLSurfaceView createView(Activity activity){
- view = new AndroidInput(activity);
-
- /*
- * Requesting client version from GLSurfaceView which is extended by
- * AndroidInput.
- * This is required to get OpenGL ES 2.0
- */
-
- logger.info("setEGLContextClientVersion(2)");
- view.setEGLContextClientVersion(2);
- logger.info("setEGLContextClientVersion(2) ... done.");
-
+
+ public GLSurfaceView createView(Activity activity)
+ {
+ return createView(new AndroidInput(activity));
+ }
+
+
+ public GLSurfaceView createView(AndroidInput view)
+ {
+ this.view = view;
+
+ /*
+ * Requesting client version from GLSurfaceView which is extended by
+ * AndroidInput.
+ * This is required to get OpenGL ES 2.0
+ */
+ view.setEGLContextClientVersion(2);
+
//RGB565, Depth16
view.setEGLConfigChooser(5, 6, 5, 0, 16, 0);
view.setFocusableInTouchMode(true);
@@ -104,12 +115,11 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer {
return view;
}
+
- protected void applySettings(AppSettings setting){
- }
-
- protected void initInThread(GL10 gl){
- logger.info("Display created.");
+ protected void initInThread()
+ {
+ logger.info("OGLESContext create");
logger.fine("Running on thread: "+Thread.currentThread().getName());
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@@ -117,175 +127,220 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer {
listener.handleError("Uncaught exception thrown in "+thread.toString(), thrown);
}
});
-
- created.set(true);
-
+
timer = new AndroidTimer();
- renderer = new OGLESShaderRenderer(gl);
- applySettingsToRenderer(renderer, settings);
-
+ renderer = new OGLESShaderRenderer();
+
+ renderer.setUseVA(true);
+ renderer.setVerboseLogging(false);
+
renderer.initialize();
- listener.initialize();
-
- // OGLESShaderRenderer does not support guiView yet
- // forcefully remove all gui nodes
-
- if (listener instanceof com.jme3.app.SimpleApplication) {
- ((com.jme3.app.SimpleApplication) listener).getGuiNode().detachAllChildren();
- }
+ listener.initialize();
+ created.set(true);
+
+ needClose.set(false);
}
/**
* De-initialize in the OpenGL thread.
*/
- protected void deinitInThread(){
+ protected void deinitInThread()
+ {
+ if (renderer != null)
+ renderer.cleanup();
+
listener.destroy();
- if (renderer != null) {
- renderer.cleanup();
- // do android specific cleaning here
-
- logger.info("Display destroyed.");
+
+ // do android specific cleaning here
+ logger.info("Display destroyed.");
+ renderable.set(false);
created.set(false);
renderer = null;
timer = null;
- }
+ }
+
+ protected void applySettingsToRenderer(OGLESShaderRenderer renderer, AppSettings settings)
+ {
+ logger.warning("setSettings.USE_VA: [" + settings.getBoolean("USE_VA") + "]");
+ logger.warning("setSettings.VERBOSE_LOGGING: [" + settings.getBoolean("VERBOSE_LOGGING") + "]");
+ renderer.setUseVA(settings.getBoolean("USE_VA"));
+ renderer.setVerboseLogging(settings.getBoolean("VERBOSE_LOGGING"));
+ }
+
+ protected void applySettings(AppSettings setting)
+ {
+ if (renderer != null)
+ applySettingsToRenderer(renderer, settings);
}
-
- protected void applySettingsToRenderer(OGLESShaderRenderer renderer, AppSettings settings) {
- logger.warning("setSettings.USE_VA: [" + settings.getBoolean("USE_VA") + "]");
- logger.warning("setSettings.VERBOSE_LOGGING: [" + settings.getBoolean("VERBOSE_LOGGING") + "]");
- renderer.setUseVA(settings.getBoolean("USE_VA"));
- renderer.setVerboseLogging(settings.getBoolean("VERBOSE_LOGGING"));
- }
-
- @Override
- public void setSettings(AppSettings settings) {
- this.settings.copyFrom(settings);
-
- // XXX This code should be somewhere else
- if (renderer != null)
- applySettingsToRenderer(renderer, this.settings);
+ @Override
+ public void setSettings(AppSettings settings)
+ {
+ this.settings.copyFrom(settings);
}
+ @Override
public void setSystemListener(SystemListener listener){
this.listener = listener;
}
+ @Override
public AppSettings getSettings() {
return settings;
}
+ @Override
public com.jme3.renderer.Renderer getRenderer() {
return renderer;
}
+ @Override
public MouseInput getMouseInput() {
return view;
}
+ @Override
public KeyInput getKeyInput() {
return view;
}
-
+
+ @Override
public JoyInput getJoyInput() {
return null;
}
-
- public Timer getTimer() {
+
+ @Override
+ public Timer getTimer()
+ {
return timer;
}
- public void setTitle(String title) {
+ @Override
+ public void setTitle(String title)
+ {
}
-
- public boolean isCreated(){
+
+ @Override
+ public boolean isCreated()
+ {
return created.get();
}
-
- public void setAutoFlushFrames(boolean enabled){
+ @Override
+ public void setAutoFlushFrames(boolean enabled)
+ {
this.autoFlush = enabled;
}
// renderer:initialize
- public void onSurfaceCreated(GL10 gl, EGLConfig cfg) {
- logger.info("Using Android");
- initInThread(gl);
+ @Override
+ public void onSurfaceCreated(GL10 gl, EGLConfig cfg)
+ {
+ logger.info("GL Surface created");
+ initInThread();
+ renderable.set(true);
}
// SystemListener:reshape
- public void onSurfaceChanged(GL10 gl, int width, int height) {
+ @Override
+ public void onSurfaceChanged(GL10 gl, int width, int height)
+ {
settings.setResolution(width, height);
listener.reshape(width, height);
}
// SystemListener:update
- public void onDrawFrame(GL10 gl) {
- if (needClose.get()){
- deinitInThread(); // ???
+ @Override
+ public void onDrawFrame(GL10 gl)
+ {
+
+ if (!created.get())
+ throw new IllegalStateException("onDrawFrame without create");
+
+ if (needClose.get())
+ {
+ deinitInThread();
return;
}
-
-// if (wasActive != Display.isActive()){
-// if (!wasActive){
-// listener.gainFocus();
-// wasActive = true;
-// }else{
-// listener.loseFocus();
-// wasActive = false;
-// }
-// }
-
- if (!created.get())
- throw new IllegalStateException();
-
- listener.update();
-
- // swap buffers
- if (frameRate > 0){
-// Display.sync(frameRate);
- // synchronzie to framerate
- }
+ if (renderable.get())
+ {
+ milliStart = System.currentTimeMillis();
+
- if (autoFlush)
- renderer.onFrame();
- }
-
- /**
- * TODO: get these methods to follow the spec
- * @param waitFor
- */
- public void create(boolean waitFor) {
- if (created.get()){
- logger.warning("create() called when display is already created!");
- return;
+
+ listener.update();
+
+
+ if (autoFlush)
+ {
+ renderer.onFrame();
+ }
+
+ milliDelta = System.currentTimeMillis() - milliStart;
+
+ // Enforce a FPS cap
+ if (milliDelta < minFrameDuration)
+ {
+ //logger.log(Level.INFO, "Time per frame {0}", milliDelta);
+ try {
+ Thread.sleep(minFrameDuration - milliDelta);
+ } catch (InterruptedException e) {
+ }
+ }
+
}
+
+
}
-
- public void create(){
- create(false);
+
+ @Override
+ public boolean isRenderable()
+ {
+ return renderable.get();
}
-
- public void restart() {
+
+ @Override
+ public void create(boolean waitFor)
+ {
+ if (waitFor)
+ waitFor(true);
}
-
- public boolean isRenderable() {
- // TODO isRenderable
- return true;
+
+ public void create()
+ {
+ create(false);
}
- /**
- * TODO: get these methods to follow the spec
- * @param waitFor
- */
- public void destroy(boolean waitFor) {
+ @Override
+ public void restart()
+ {
+
+ }
+
+ @Override
+ public void destroy(boolean waitFor)
+ {
needClose.set(true);
+ if (waitFor)
+ waitFor(false);
}
-
- public void destroy(){
+
+ public void destroy()
+ {
destroy(false);
}
+
+ protected void waitFor(boolean createdVal)
+ {
+ synchronized (createdLock){
+ while (created.get() != createdVal){
+ try {
+ createdLock.wait();
+ } catch (InterruptedException ex) {
+ }
+ }
+ }
+ }
}
diff --git a/engine/src/android/com/jme3/texture/plugins/AndroidImageLoader.java b/engine/src/android/com/jme3/texture/plugins/AndroidImageLoader.java
index e28ad5d41..1e7c8b518 100644
--- a/engine/src/android/com/jme3/texture/plugins/AndroidImageLoader.java
+++ b/engine/src/android/com/jme3/texture/plugins/AndroidImageLoader.java
@@ -2,8 +2,11 @@ package com.jme3.texture.plugins;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.Matrix;
+
import com.jme3.asset.AssetInfo;
import com.jme3.asset.AssetLoader;
+import com.jme3.asset.TextureKey;
import com.jme3.texture.Image;
import com.jme3.texture.Image.Format;
import com.jme3.util.BufferUtils;
@@ -11,16 +14,19 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
-public class AndroidImageLoader implements AssetLoader {
+public class AndroidImageLoader implements AssetLoader
+{
- public Object load2(AssetInfo info) throws IOException {
+ public Object load2(AssetInfo info) throws IOException
+ {
ByteBuffer bb = BufferUtils.createByteBuffer(1 * 1 * 2);
bb.put( (byte) 0xff ).put( (byte) 0xff );
bb.clear();
return new Image(Format.RGB5A1, 1, 1, bb);
}
- public Object load(AssetInfo info) throws IOException {
+ public Object load(AssetInfo info) throws IOException
+ {
InputStream in = null;
Bitmap bitmap = null;
try {
@@ -36,59 +42,41 @@ public class AndroidImageLoader implements AssetLoader {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
- int bytesPerPixel = -1;
Format fmt;
switch (bitmap.getConfig()){
case ALPHA_8:
- bytesPerPixel = 1;
fmt = Format.Alpha8;
break;
case ARGB_4444:
- bytesPerPixel = 2;
fmt = Format.ARGB4444;
break;
case ARGB_8888:
- bytesPerPixel = 4;
fmt = Format.RGBA8;
break;
- case RGB_565:
- bytesPerPixel = 2;
+ case RGB_565:
fmt = Format.RGB565;
break;
default:
return null;
}
-// if (width > 128 || height > 128){
-// if (width > height){
-// float aspect = (float) height / width;
-// width = 128;
-// height = (int) (128 * aspect);
-//
-// }else{
-// float aspect = (float) width / height;
-// width = (int) (128 * aspect);
-// height = 128;
-// }
-// bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
-// }
+ if ( ((TextureKey)info.getKey()).isFlipY() )
+ {
+ Bitmap newBitmap = null;
+ Matrix flipMat = new Matrix();
+ flipMat.preScale(1.0f, -1.0f);
+ newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), flipMat, false);
+ bitmap.recycle();
+ bitmap = newBitmap;
-// if ( ((TextureKey)info.getKey()).isFlipY() ){
-// Bitmap newBitmap = null;
-// Matrix flipMat = new Matrix();
-// flipMat.preScale(1.0f, -1.0f);
-// newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), flipMat, false);
-// bitmap.recycle();
-// bitmap = newBitmap;
-//
-// if (bitmap == null){
-// throw new IOException("Failed to load image2: "+info.getKey().getName());
-// }
-// }
+ if (bitmap == null){
+ throw new IOException("Failed to flip image: "+info.getKey().getName());
+ }
+ }
Image image = new Image(fmt, width, height, null);
- image.setEfficentData(bitmap);
+ image.setEfficentData(bitmap);
return image;
}
diff --git a/engine/src/android/com/jme3/util/FastInteger.java b/engine/src/android/com/jme3/util/FastInteger.java
new file mode 100644
index 000000000..49294b4a9
--- /dev/null
+++ b/engine/src/android/com/jme3/util/FastInteger.java
@@ -0,0 +1,359 @@
+package com.jme3.util;
+
+
+/**
+ * The wrapper for the primitive type {@code int}.
+ *
+ * As with the specification, this implementation relies on code laid out in Henry S. Warren, Jr.'s Hacker's
+ * Delight, (Addison Wesley, 2002) as well as The Aggregate's Magic Algorithms.
+ *
+ * @see java.lang.Number
+ * @since 1.1
+ */
+public final class FastInteger {
+
+ /**
+ * Constant for the maximum {@code int} value, 231-1.
+ */
+ public static final int MAX_VALUE = 0x7FFFFFFF;
+
+ /**
+ * Constant for the minimum {@code int} value, -231.
+ */
+ public static final int MIN_VALUE = 0x80000000;
+
+ /**
+ * Constant for the number of bits needed to represent an {@code int} in
+ * two's complement form.
+ *
+ * @since 1.5
+ */
+ public static final int SIZE = 32;
+
+ /*
+ * Progressively smaller decimal order of magnitude that can be represented
+ * by an instance of Integer. Used to help compute the String
+ * representation.
+ */
+ private static final int[] decimalScale = new int[] { 1000000000, 100000000,
+ 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1 };
+
+ /**
+ * Converts the specified integer into its decimal string representation.
+ * The returned string is a concatenation of a minus sign if the number is
+ * negative and characters from '0' to '9'.
+ *
+ * @param value
+ * the integer to convert.
+ * @return the decimal string representation of {@code value}.
+ */
+ public static boolean toCharArray(int value, char[] output) {
+ if (value == 0)
+ {
+ output[0] = '0';
+ output[1] = 0;
+ return true;
+ }
+
+ // Faster algorithm for smaller Integers
+ if (value < 1000 && value > -1000) {
+
+ int positive_value = value < 0 ? -value : value;
+ int first_digit = 0;
+ if (value < 0) {
+ output[0] = '-';
+ first_digit++;
+ }
+ int last_digit = first_digit;
+ int quot = positive_value;
+ do {
+ int res = quot / 10;
+ int digit_value = quot - ((res << 3) + (res << 1));
+ digit_value += '0';
+ output[last_digit++] = (char) digit_value;
+ quot = res;
+ } while (quot != 0);
+
+ int count = last_digit--;
+ do {
+ char tmp = output[last_digit];
+ output[last_digit--] = output[first_digit];
+ output[first_digit++] = tmp;
+ } while (first_digit < last_digit);
+ output[count] = 0;
+ return true;
+ }
+ if (value == MIN_VALUE) {
+ System.arraycopy("-2147483648".toCharArray(), 0, output, 0, 12);
+ output[12] = 0;
+ return true;
+ }
+
+
+ int positive_value = value < 0 ? -value : value;
+ byte first_digit = 0;
+ if (value < 0) {
+ output[0] = '-';
+ first_digit++;
+ }
+ byte last_digit = first_digit;
+ byte count;
+ int number;
+ boolean start = false;
+ for (int i = 0; i < 9; i++) {
+ count = 0;
+ if (positive_value < (number = decimalScale[i])) {
+ if (start) {
+ output[last_digit++] = '0';
+ }
+ continue;
+ }
+
+ if (i > 0) {
+ number = (decimalScale[i] << 3);
+ if (positive_value >= number) {
+ positive_value -= number;
+ count += 8;
+ }
+ number = (decimalScale[i] << 2);
+ if (positive_value >= number) {
+ positive_value -= number;
+ count += 4;
+ }
+ }
+ number = (decimalScale[i] << 1);
+ if (positive_value >= number) {
+ positive_value -= number;
+ count += 2;
+ }
+ if (positive_value >= decimalScale[i]) {
+ positive_value -= decimalScale[i];
+ count++;
+ }
+ if (count > 0 && !start) {
+ start = true;
+ }
+ if (start) {
+ output[last_digit++] = (char) (count + '0');
+ }
+ }
+
+ output[last_digit++] = (char) (positive_value + '0');
+ output[last_digit] = 0;
+ count = last_digit--;
+ return true;
+ }
+
+
+ /**
+ * Determines the highest (leftmost) bit of the specified integer that is 1
+ * and returns the bit mask value for that bit. This is also referred to as
+ * the Most Significant 1 Bit. Returns zero if the specified integer is
+ * zero.
+ *
+ * @param i
+ * the integer to examine.
+ * @return the bit mask indicating the highest 1 bit in {@code i}.
+ * @since 1.5
+ */
+ public static int highestOneBit(int i) {
+ i |= (i >> 1);
+ i |= (i >> 2);
+ i |= (i >> 4);
+ i |= (i >> 8);
+ i |= (i >> 16);
+ return (i & ~(i >>> 1));
+ }
+
+ /**
+ * Determines the lowest (rightmost) bit of the specified integer that is 1
+ * and returns the bit mask value for that bit. This is also referred
+ * to as the Least Significant 1 Bit. Returns zero if the specified integer
+ * is zero.
+ *
+ * @param i
+ * the integer to examine.
+ * @return the bit mask indicating the lowest 1 bit in {@code i}.
+ * @since 1.5
+ */
+ public static int lowestOneBit(int i) {
+ return (i & (-i));
+ }
+
+ /**
+ * Determines the number of leading zeros in the specified integer prior to
+ * the {@link #highestOneBit(int) highest one bit}.
+ *
+ * @param i
+ * the integer to examine.
+ * @return the number of leading zeros in {@code i}.
+ * @since 1.5
+ */
+ public static int numberOfLeadingZeros(int i) {
+ i |= i >> 1;
+ i |= i >> 2;
+ i |= i >> 4;
+ i |= i >> 8;
+ i |= i >> 16;
+ return bitCount(~i);
+ }
+
+ /**
+ * Determines the number of trailing zeros in the specified integer after
+ * the {@link #lowestOneBit(int) lowest one bit}.
+ *
+ * @param i
+ * the integer to examine.
+ * @return the number of trailing zeros in {@code i}.
+ * @since 1.5
+ */
+ public static int numberOfTrailingZeros(int i) {
+ return bitCount((i & -i) - 1);
+ }
+
+ /**
+ * Counts the number of 1 bits in the specified integer; this is also
+ * referred to as population count.
+ *
+ * @param i
+ * the integer to examine.
+ * @return the number of 1 bits in {@code i}.
+ * @since 1.5
+ */
+ public static int bitCount(int i) {
+ i -= ((i >> 1) & 0x55555555);
+ i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
+ i = (((i >> 4) + i) & 0x0F0F0F0F);
+ i += (i >> 8);
+ i += (i >> 16);
+ return (i & 0x0000003F);
+ }
+
+ /**
+ * Rotates the bits of the specified integer to the left by the specified
+ * number of bits.
+ *
+ * @param i
+ * the integer value to rotate left.
+ * @param distance
+ * the number of bits to rotate.
+ * @return the rotated value.
+ * @since 1.5
+ */
+ public static int rotateLeft(int i, int distance) {
+ if (distance == 0) {
+ return i;
+ }
+ /*
+ * According to JLS3, 15.19, the right operand of a shift is always
+ * implicitly masked with 0x1F, which the negation of 'distance' is
+ * taking advantage of.
+ */
+ return ((i << distance) | (i >>> (-distance)));
+ }
+
+ /**
+ * Rotates the bits of the specified integer to the right by the specified
+ * number of bits.
+ *
+ * @param i
+ * the integer value to rotate right.
+ * @param distance
+ * the number of bits to rotate.
+ * @return the rotated value.
+ * @since 1.5
+ */
+ public static int rotateRight(int i, int distance) {
+ if (distance == 0) {
+ return i;
+ }
+ /*
+ * According to JLS3, 15.19, the right operand of a shift is always
+ * implicitly masked with 0x1F, which the negation of 'distance' is
+ * taking advantage of.
+ */
+ return ((i >>> distance) | (i << (-distance)));
+ }
+
+ /**
+ * Reverses the order of the bytes of the specified integer.
+ *
+ * @param i
+ * the integer value for which to reverse the byte order.
+ * @return the reversed value.
+ * @since 1.5
+ */
+ public static int reverseBytes(int i) {
+ int b3 = i >>> 24;
+ int b2 = (i >>> 8) & 0xFF00;
+ int b1 = (i & 0xFF00) << 8;
+ int b0 = i << 24;
+ return (b0 | b1 | b2 | b3);
+ }
+
+ /**
+ * Reverses the order of the bits of the specified integer.
+ *
+ * @param i
+ * the integer value for which to reverse the bit order.
+ * @return the reversed value.
+ * @since 1.5
+ */
+ public static int reverse(int i) {
+ // From Hacker's Delight, 7-1, Figure 7-1
+ i = (i & 0x55555555) << 1 | (i >> 1) & 0x55555555;
+ i = (i & 0x33333333) << 2 | (i >> 2) & 0x33333333;
+ i = (i & 0x0F0F0F0F) << 4 | (i >> 4) & 0x0F0F0F0F;
+ return reverseBytes(i);
+ }
+
+ /**
+ * Returns the value of the {@code signum} function for the specified
+ * integer.
+ *
+ * @param i
+ * the integer value to check.
+ * @return -1 if {@code i} is negative, 1 if {@code i} is positive, 0 if
+ * {@code i} is zero.
+ * @since 1.5
+ */
+ public static int signum(int i) {
+ return (i == 0 ? 0 : (i < 0 ? -1 : 1));
+ }
+
+ /**
+ * Returns a {@code Integer} instance for the specified integer value.
+ *
+ * If it is not necessary to get a new {@code Integer} instance, it is
+ * recommended to use this method instead of the constructor, since it
+ * maintains a cache of instances which may result in better performance.
+ *
+ * @param i
+ * the integer value to store in the instance.
+ * @return a {@code Integer} instance containing {@code i}.
+ * @since 1.5
+ */
+ public static Integer valueOf(int i) {
+ if (i < -128 || i > 127) {
+ return new Integer(i);
+ }
+ return valueOfCache.CACHE [i+128];
+
+ }
+
+ static class valueOfCache {
+ /**
+ *
+ * A cache of instances used by {@link Integer#valueOf(int)} and auto-boxing.
+ */
+ static final Integer[] CACHE = new Integer[256];
+
+ static {
+ for(int i=-128; i<=127; i++) {
+ CACHE[i+128] = new Integer(i);
+ }
+ }
+ }
+}