• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Main repository of MikuMikuStudio


Commit MetaInfo

Revisión20e66b4d9846e2cbb2bca11dd18bcf082de8fbcd (tree)
Tiempo2014-02-17 04:11:46
Autorkobayasi <kobayasi@pscn...>
Commiterkobayasi

Log Message

Add libgdx support.

Cambiar Resumen

Diferencia incremental

--- a/build.sbt
+++ b/build.sbt
@@ -10,7 +10,7 @@ lazy val desktop = project.dependsOn(engine)
1010
1111 lazy val android = project
1212
13-lazy val gdx = project
13+lazy val gdx = project.dependsOn(engine)
1414
1515 lazy val niftygui = project.dependsOn(engine)
1616
--- a/desktop/build.sbt
+++ b/desktop/build.sbt
@@ -10,10 +10,6 @@ unmanagedSourceDirectories in Compile ++= Seq(
1010
1111 libraryDependencies += "org.lwjgl.lwjgl" % "lwjgl" % "2.9.0"
1212
13-libraryDependencies += "net.sf.sociaal" % "j-ogg-oggd" % "3.0.0.20130526"
14-
15-libraryDependencies += "net.sf.sociaal" % "j-ogg-vorbisd" % "3.0.0.20130526"
16-
1713 libraryDependencies += "net.java.jinput" % "jinput" % "2.0.5"
1814
1915 libraryDependencies += "org.bushe" % "eventbus" % "1.4"
--- a/engine/src/desktop/com/jme3/asset/Desktop.cfg
+++ b/desktop/src/main/resources/com/jme3/asset/Desktop.cfg
@@ -1,24 +1,24 @@
1-LOCATOR / com.jme3.asset.plugins.ClasspathLocator
2-
3-LOADER com.jme3.texture.plugins.AWTLoader : jpg, bmp, gif, png, jpeg, sph, spa
4-LOADER com.jme3.audio.plugins.WAVLoader : wav
5-LOADER com.jme3.audio.plugins.OGGLoader : ogg
6-LOADER com.jme3.material.plugins.J3MLoader : j3m
7-LOADER com.jme3.material.plugins.J3MLoader : j3md
8-LOADER com.jme3.font.plugins.BitmapFontLoader : fnt
9-LOADER com.jme3.texture.plugins.DDSLoader : dds
10-LOADER com.jme3.texture.plugins.PFMLoader : pfm
11-LOADER com.jme3.texture.plugins.HDRLoader : hdr
12-LOADER com.jme3.texture.plugins.TGALoader : tga
13-LOADER com.jme3.export.binary.BinaryImporter : j3o
14-LOADER com.jme3.export.binary.BinaryImporter : j3f
15-LOADER com.jme3.scene.plugins.OBJLoader : obj
16-LOADER com.jme3.scene.plugins.MTLLoader : mtl
17-LOADER com.jme3.scene.plugins.ogre.MeshLoader : meshxml, mesh.xml
18-LOADER com.jme3.scene.plugins.ogre.SkeletonLoader : skeletonxml, skeleton.xml
19-LOADER com.jme3.scene.plugins.ogre.MaterialLoader : material
20-LOADER com.jme3.scene.plugins.ogre.SceneLoader : scene
21-LOADER com.jme3.scene.plugins.blender.BlenderModelLoader : blend
22-LOADER com.jme3.shader.plugins.GLSLLoader : vert, frag, glsl, glsllib
23-LOADER projectkyoto.jme3.mmd.PMDLoaderGLSLSkinning2 : pmd
24-LOADER projectkyoto.jme3.mmd.VMDLoader : vmd
1+LOCATOR / com.jme3.asset.plugins.ClasspathLocator
2+
3+LOADER com.jme3.texture.plugins.AWTLoader : jpg, bmp, gif, png, jpeg, sph, spa
4+LOADER com.jme3.audio.plugins.WAVLoader : wav
5+LOADER com.jme3.audio.plugins.OGGLoader : ogg
6+LOADER com.jme3.material.plugins.J3MLoader : j3m
7+LOADER com.jme3.material.plugins.J3MLoader : j3md
8+LOADER com.jme3.font.plugins.BitmapFontLoader : fnt
9+LOADER com.jme3.texture.plugins.DDSLoader : dds
10+LOADER com.jme3.texture.plugins.PFMLoader : pfm
11+LOADER com.jme3.texture.plugins.HDRLoader : hdr
12+LOADER com.jme3.texture.plugins.TGALoader : tga
13+LOADER com.jme3.export.binary.BinaryImporter : j3o
14+LOADER com.jme3.export.binary.BinaryImporter : j3f
15+LOADER com.jme3.scene.plugins.OBJLoader : obj
16+LOADER com.jme3.scene.plugins.MTLLoader : mtl
17+LOADER com.jme3.scene.plugins.ogre.MeshLoader : meshxml, mesh.xml
18+LOADER com.jme3.scene.plugins.ogre.SkeletonLoader : skeletonxml, skeleton.xml
19+LOADER com.jme3.scene.plugins.ogre.MaterialLoader : material
20+LOADER com.jme3.scene.plugins.ogre.SceneLoader : scene
21+LOADER com.jme3.scene.plugins.blender.BlenderModelLoader : blend
22+LOADER com.jme3.shader.plugins.GLSLLoader : vert, frag, glsl, glsllib
23+LOADER projectkyoto.jme3.mmd.PMDLoaderGLSLSkinning2 : pmd
24+LOADER projectkyoto.jme3.mmd.VMDLoader : vmd
--- a/engine/build.sbt
+++ b/engine/build.sbt
@@ -15,6 +15,7 @@ unmanagedSourceDirectories in Compile := Seq(
1515 , baseDirectory.value / "src/desktop-fx"
1616 , baseDirectory.value / "src/games"
1717 // , baseDirectory.value / "src/jheora"
18+ , baseDirectory.value / "src/jogg"
1819 // , baseDirectory.value / "src/lwjgl-oal"
1920 // , baseDirectory.value / "src/lwjgl-ogl"
2021 , baseDirectory.value / "src/mmd"
@@ -45,3 +46,6 @@ libraryDependencies += "xpp3" % "xpp3" % "1.1.4c"
4546
4647 libraryDependencies += "com.jme3" % "noise" % "3.0.0-SNAPSHOT"
4748
49+libraryDependencies += "net.sf.sociaal" % "j-ogg-oggd" % "3.0.0.20130526"
50+
51+libraryDependencies += "net.sf.sociaal" % "j-ogg-vorbisd" % "3.0.0.20130526"
\ No newline at end of file
--- a/engine/src/desktop/com/jme3/system/JmeSystem.java
+++ b/engine/src/desktop/com/jme3/system/JmeSystem.java
@@ -31,6 +31,7 @@
3131 */
3232 package com.jme3.system;
3333
34+import com.jme3.app.Application;
3435 import com.jme3.asset.AssetManager;
3536 import com.jme3.audio.AudioRenderer;
3637
@@ -44,6 +45,7 @@ public class JmeSystem {
4445 private static boolean initialized = false;
4546
4647 private static JmeSystemDelegate delegate;
48+ protected static ThreadLocal<Application> app = new ThreadLocal<Application>();
4749
4850 static {
4951 try {
--- /dev/null
+++ b/gdx/build.sbt
@@ -0,0 +1,7 @@
1+Common.settings
2+
3+name := "mms-gdx"
4+
5+libraryDependencies ++= Seq(
6+ "com.badlogicgames.gdx" % "gdx" % "1.0-SNAPSHOT"
7+)
\ No newline at end of file
--- /dev/null
+++ b/gdx/src/main/java/com/jme3/asset/gdx/GdxAssetManager.java
@@ -0,0 +1,47 @@
1+package com.jme3.asset.gdx;
2+
3+import com.jme3.asset.*;
4+import com.jme3.material.Material;
5+import com.jme3.system.gdx.GdxAudioLoader;
6+import com.jme3.texture.Texture;
7+import com.jme3.texture.plugins.gdx.GdxTGALoader;
8+import com.jme3.texture.plugins.gdx.GdxImageLoader;
9+
10+/**
11+ * Created with IntelliJ IDEA.
12+ * User: kobayasi
13+ * Date: 13/10/08
14+ * Time: 0:56
15+ * To change this template use File | Settings | File Templates.
16+ */
17+public class GdxAssetManager extends DesktopAssetManager {
18+ public GdxAssetManager() {
19+ super(true);
20+ registerLoader(GdxTGALoader.class, "tga");
21+ this.registerLoader(GdxImageLoader.class, "jpg", "bmp", "gif", "png", "jpeg","spa","sph");
22+ this.registerLoader(GdxAudioLoader.class, "wav", "mp3", "ogg");
23+ }
24+
25+ @Override
26+ public <T> T loadAsset(AssetKey<T> key) {
27+ return super.loadAsset(key); //To change body of overridden methods use File | Settings | File Templates.
28+ }
29+
30+ @Override
31+ public Object loadAsset(String name) {
32+ return super.loadAsset(name); //To change body of overridden methods use File | Settings | File Templates.
33+ }
34+
35+ @Override
36+ public Texture loadTexture(TextureKey key) {
37+ return super.loadTexture(key); //To change body of overridden methods use File | Settings | File Templates.
38+ }
39+
40+ @Override
41+ public Material loadMaterial(String name) {
42+ return super.loadMaterial(name); //To change body of overridden methods use File | Settings | File Templates.
43+ }
44+
45+
46+
47+}
--- /dev/null
+++ b/gdx/src/main/java/com/jme3/asset/gdx/MMSFilterInputStream.java
@@ -0,0 +1,109 @@
1+package com.jme3.asset.gdx;
2+
3+import java.io.FilterInputStream;
4+import java.io.IOException;
5+import java.io.InputStream;
6+
7+/**
8+ *
9+ * @author kobayasi
10+ */
11+public class MMSFilterInputStream extends FilterInputStream {
12+
13+ int size;
14+
15+ public MMSFilterInputStream(InputStream in, int size) {
16+ super(in);
17+ this.size = size;
18+ }
19+
20+ @Override
21+ public int available() throws IOException {
22+ return size;
23+ }
24+
25+ @Override
26+ public void close() throws IOException {
27+ super.close();
28+ }
29+
30+ @Override
31+ public synchronized void mark(int i) {
32+ super.mark(i);
33+ }
34+
35+ @Override
36+ public boolean markSupported() {
37+ return true;
38+ }
39+
40+ @Override
41+ public int read() throws IOException {
42+ if (size == 0) {
43+ return -1;
44+ }
45+ int i = super.read();
46+ if (i >= 0) {
47+ size--;
48+ }
49+ return i;
50+ }
51+
52+ @Override
53+ public int read(byte[] bytes) throws IOException {
54+ int i = read(bytes, 0, bytes.length);
55+ return i;
56+ }
57+
58+ @Override
59+ public int read(byte[] bytes, int i, int i1) throws IOException {
60+ if (size == 0) {
61+ return -1;
62+ }
63+ int readSize = 0;
64+ if (i1 > size) {
65+ i1 = size;
66+ }
67+ while(size > 0 && readSize != i1) {
68+ int i2 = super.read(bytes, i+readSize, i1 - readSize);
69+ if (i2 >= 0) {
70+ size = size - i2;
71+ readSize += i2;
72+ } else {
73+ break;
74+ }
75+ }
76+ return readSize;
77+ }
78+
79+ @Override
80+ public synchronized void reset() throws IOException {
81+ super.reset();
82+ }
83+
84+ @Override
85+ public long skip(long n) throws IOException {
86+// long totalBytesSkipped = 0L;
87+// while (totalBytesSkipped < n && size > 0) {
88+// long bytesSkipped = in.skip(n - totalBytesSkipped);
89+// size = size - (int) bytesSkipped;
90+// if (bytesSkipped == 0L) {
91+// int b = read();
92+// if (b < 0) {
93+// break; // we reached EOF
94+// } else {
95+// bytesSkipped = 1; // we read one byte
96+//// size = size - 1;
97+// }
98+// }
99+// totalBytesSkipped += bytesSkipped;
100+// }
101+ for(long i = 0;i<n;i++) {
102+ if (read() < 0) {
103+ return i-1;
104+ }
105+ }
106+ return n;
107+ }
108+}
109+
--- /dev/null
+++ b/gdx/src/main/java/com/jme3/renderer/gdx/GdxRenderer.java
@@ -0,0 +1,3187 @@
1+/*
2+ * Copyright (c) 2009-2010 jMonkeyEngine
3+ * All rights reserved.
4+ *
5+ * Redistribution and use in source and binary forms, with or without
6+ * modification, are permitted provided that the following conditions are
7+ * met:
8+ *
9+ * * Redistributions of source code must retain the above copyright
10+ * notice, this list of conditions and the following disclaimer.
11+ *
12+ * * Redistributions in binary form must reproduce the above copyright
13+ * notice, this list of conditions and the following disclaimer in the
14+ * documentation and/or other materials provided with the distribution.
15+ *
16+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17+ * may be used to endorse or promote products derived from this software
18+ * without specific prior written permission.
19+ *
20+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+ */
32+package com.jme3.renderer.gdx;
33+
34+import com.badlogic.gdx.Gdx;
35+import com.badlogic.gdx.graphics.GL10;
36+import com.badlogic.gdx.graphics.GL20;
37+import com.jme3.light.LightList;
38+import com.jme3.material.RenderState;
39+import com.jme3.math.*;
40+import com.jme3.renderer.*;
41+import com.jme3.scene.Mesh;
42+import com.jme3.scene.Mesh.Mode;
43+import com.jme3.scene.VertexBuffer;
44+import com.jme3.scene.VertexBuffer.Format;
45+import com.jme3.scene.VertexBuffer.Type;
46+import com.jme3.scene.VertexBuffer.Usage;
47+import com.jme3.shader.Attribute;
48+import com.jme3.shader.Shader;
49+import com.jme3.shader.Shader.ShaderSource;
50+import com.jme3.shader.Shader.ShaderType;
51+import com.jme3.shader.Uniform;
52+import com.jme3.texture.FrameBuffer;
53+import com.jme3.texture.FrameBuffer.RenderBuffer;
54+import com.jme3.texture.Image;
55+import com.jme3.texture.Texture;
56+import com.jme3.texture.Texture.WrapAxis;
57+import com.jme3.util.BufferUtils;
58+import com.jme3.util.IntMap;
59+import com.jme3.util.ListMap;
60+import com.jme3.util.NativeObjectManager;
61+import com.jme3.util.SafeArrayList;
62+import java.nio.*;
63+import java.util.EnumSet;
64+import java.util.logging.Level;
65+import java.util.logging.Logger;
66+
67+public final class GdxRenderer implements Renderer {
68+
69+ private static final Logger logger = Logger.getLogger(GdxRenderer.class.getName());
70+ private static final boolean VALIDATE_SHADER = false;
71+ private final ByteBuffer nameBuf = BufferUtils.createByteBuffer(250);
72+ private final StringBuilder stringBuf = new StringBuilder(250);
73+ private final IntBuffer intBuf1 = BufferUtils.createIntBuffer(1);
74+ private final IntBuffer intBuf16 = BufferUtils.createIntBuffer(16);
75+ private final RenderContext context = new RenderContext();
76+ private final NativeObjectManager objManager = new NativeObjectManager();
77+ private final EnumSet<Caps> caps = EnumSet.noneOf(Caps.class);
78+ // current state
79+ private Shader boundShader;
80+ private int initialDrawBuf, initialReadBuf;
81+ private int glslVer;
82+ private int vertexTextureUnits;
83+ private int fragTextureUnits;
84+ private int vertexUniforms;
85+ private int fragUniforms;
86+ private int vertexAttribs;
87+ private int maxFBOSamples;
88+ private int maxFBOAttachs = 1;
89+ private int maxMRTFBOAttachs;
90+ private int maxRBSize;
91+ private int maxTexSize;
92+ private int maxCubeTexSize;
93+ private int maxVertCount;
94+ private int maxTriCount;
95+ private boolean tdc;
96+ private FrameBuffer lastFb = null;
97+ private FrameBuffer mainFbOverride = null;
98+ private final Statistics statistics = new Statistics();
99+ private int vpX, vpY, vpW, vpH;
100+ private int clipX, clipY, clipW, clipH;
101+ //private final GL10 gl;
102+ private boolean powerOf2 = false;
103+ private boolean verboseLogging = false;
104+ private boolean useVBO = true;
105+ public boolean adreno_finish_bug = false;
106+
107+ public GdxRenderer() {
108+ }
109+
110+ public void setUseVA(boolean value) {
111+ logger.log(Level.INFO, "use_VBO [{0}] -> [{1}]", new Object[]{useVBO, !value});
112+ useVBO = !value;
113+ }
114+
115+ public void setVerboseLogging(boolean value) {
116+ logger.log(Level.INFO, "verboseLogging [{0}] -> [{1}]", new Object[]{verboseLogging, value});
117+ verboseLogging = value;
118+ }
119+
120+ protected void updateNameBuffer() {
121+ int len = stringBuf.length();
122+
123+ nameBuf.position(0);
124+ nameBuf.limit(len);
125+ for (int i = 0; i < len; i++) {
126+ nameBuf.put((byte) stringBuf.charAt(i));
127+ }
128+
129+ nameBuf.rewind();
130+ }
131+
132+ public Statistics getStatistics() {
133+ return statistics;
134+ }
135+
136+ public EnumSet<Caps> getCaps() {
137+ return caps;
138+ }
139+
140+ public void initialize() {
141+
142+ logger.info("Vendor: " + Gdx.gl20.glGetString(GL20.GL_VENDOR));
143+ logger.info("Renderer: " + Gdx.gl20.glGetString(GL20.GL_RENDERER));
144+ logger.info("Version: " + Gdx.gl20.glGetString(GL20.GL_VERSION));
145+
146+ String shadingLanguageVersion = Gdx.gl20.glGetString(GL20.GL_SHADING_LANGUAGE_VERSION);
147+ logger.log(Level.INFO, "GLES20.Shading Language Version: {0}", shadingLanguageVersion);
148+
149+ /*
150+ ContextCapabilities ctxCaps = GLContext.getCapabilities();
151+ if (ctxCaps.OpenGL20){
152+ caps.add(Caps.OpenGL20);
153+ }
154+ if (ctxCaps.OpenGL21){
155+ caps.add(Caps.OpenGL21);
156+ }
157+ if (ctxCaps.OpenGL30){
158+ caps.add(Caps.OpenGL30);
159+ }
160+ */
161+ String versionStr = Gdx.gl20.glGetString(GL20.GL_SHADING_LANGUAGE_VERSION);
162+ if (versionStr == null || versionStr.equals("")) {
163+// glslVer = -1;
164+// throw new UnsupportedOperationException("GLSL and OpenGL2 is "
165+// + "required for the OpenGL ES "
166+// + "renderer!");
167+ versionStr = "";
168+ }
169+ logger.info("GLES20.GL_SHADING_LANGUAGE_VERSION = " + versionStr);
170+
171+ // Fix issue in TestRenderToMemory when GL_FRONT is the main
172+ // buffer being used.
173+
174+// initialDrawBuf = GLES20.glGetIntegeri(GLES20.GL_DRAW_BUFFER);
175+// initialReadBuf = GLES20.glGetIntegeri(GLES20.GL_READ_BUFFER);
176+
177+ int spaceIdx = versionStr.lastIndexOf(" ");
178+ if (spaceIdx >= 1) {
179+ versionStr = versionStr.substring(spaceIdx, versionStr.length());
180+ }
181+
182+ float version = 1;
183+ try {
184+ version = Float.parseFloat(versionStr);
185+ } catch (Exception ex) {
186+ }
187+ glslVer = (int) (version * 100);
188+
189+ switch (glslVer) {
190+ default:
191+ if (glslVer < 400) {
192+ break;
193+ }
194+
195+ // so that future OpenGL revisions wont break jme3
196+
197+ // fall through intentional
198+ case 400:
199+ case 330:
200+ case 150:
201+ caps.add(Caps.GLSL150);
202+ case 140:
203+ caps.add(Caps.GLSL140);
204+ case 130:
205+ caps.add(Caps.GLSL130);
206+ case 120:
207+ caps.add(Caps.GLSL120);
208+ case 110:
209+ caps.add(Caps.GLSL110);
210+ case 100:
211+ caps.add(Caps.GLSL100);
212+ break;
213+ }
214+
215+ if (!caps.contains(Caps.GLSL100)) {
216+ logger.info("Force-adding GLSL100 support, since OpenGL is supported.");
217+ caps.add(Caps.GLSL100);
218+ }
219+
220+ Gdx.gl20.glGetIntegerv(GL20.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, intBuf16);
221+ vertexTextureUnits = intBuf16.get(0);
222+ logger.log(Level.INFO, "VTF Units: {0}", vertexTextureUnits);
223+ if (vertexTextureUnits > 0) {
224+ caps.add(Caps.VertexTextureFetch);
225+ }
226+
227+ Gdx.gl20.glGetIntegerv(GL20.GL_MAX_TEXTURE_IMAGE_UNITS, intBuf16);
228+ fragTextureUnits = intBuf16.get(0);
229+ logger.log(Level.INFO, "Texture Units: {0}", fragTextureUnits);
230+ /*
231+ GLES20.glGetIntegerv(GLES20.GL_MAX_VERTEX_UNIFORM_COMPONENTS, intBuf16);
232+ vertexUniforms = intBuf16.get(0);
233+ logger.log(Level.FINER, "Vertex Uniforms: {0}", vertexUniforms);
234+
235+ GLES20.glGetIntegerv(GLES20.GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, intBuf16);
236+ fragUniforms = intBuf16.get(0);
237+ logger.log(Level.FINER, "Fragment Uniforms: {0}", fragUniforms);
238+ */
239+
240+ Gdx.gl20.glGetIntegerv(GL20.GL_MAX_VERTEX_ATTRIBS, intBuf16);
241+ vertexAttribs = intBuf16.get(0);
242+ logger.log(Level.INFO, "Vertex Attributes: {0}", vertexAttribs);
243+
244+ /*
245+ GLES20.glGetIntegerv(GLES20.GL_MAX_VARYING_FLOATS, intBuf16);
246+ int varyingFloats = intBuf16.get(0);
247+ logger.log(Level.FINER, "Varying Floats: {0}", varyingFloats);
248+ */
249+
250+ Gdx.gl20.glGetIntegerv(GL20.GL_SUBPIXEL_BITS, intBuf16);
251+ int subpixelBits = intBuf16.get(0);
252+ logger.log(Level.INFO, "Subpixel Bits: {0}", subpixelBits);
253+ /*
254+ GLES20.glGetIntegerv(GLES20.GL_MAX_ELEMENTS_VERTICES, intBuf16);
255+ maxVertCount = intBuf16.get(0);
256+ logger.log(Level.FINER, "Preferred Batch Vertex Count: {0}", maxVertCount);
257+
258+ GLES20.glGetIntegerv(GLES20.GL_MAX_ELEMENTS_INDICES, intBuf16);
259+ maxTriCount = intBuf16.get(0);
260+ logger.log(Level.FINER, "Preferred Batch Index Count: {0}", maxTriCount);
261+ */
262+ Gdx.gl20.glGetIntegerv(GL20.GL_MAX_TEXTURE_SIZE, intBuf16);
263+ maxTexSize = intBuf16.get(0);
264+ logger.log(Level.INFO, "Maximum Texture Resolution: {0}" + maxTexSize);
265+
266+ Gdx.gl20.glGetIntegerv(GL20.GL_MAX_CUBE_MAP_TEXTURE_SIZE, intBuf16);
267+ maxCubeTexSize = intBuf16.get(0);
268+ logger.log(Level.INFO, "Maximum CubeMap Resolution: {0}", maxCubeTexSize);
269+
270+
271+ /*
272+ if (ctxCaps.GL_ARB_color_buffer_float){
273+ // XXX: Require both 16 and 32 bit float support for FloatColorBuffer.
274+ if (ctxCaps.GL_ARB_half_float_pixel){
275+ caps.add(Caps.FloatColorBuffer);
276+ }
277+ }
278+
279+ if (ctxCaps.GL_ARB_depth_buffer_float){
280+ caps.add(Caps.FloatDepthBuffer);
281+ }
282+
283+ if (ctxCaps.GL_ARB_draw_instanced)
284+ caps.add(Caps.MeshInstancing);
285+
286+ if (ctxCaps.GL_ARB_fragment_program)
287+ caps.add(Caps.ARBprogram);
288+
289+ if (ctxCaps.GL_ARB_texture_buffer_object)
290+ caps.add(Caps.TextureBuffer);
291+
292+ if (ctxCaps.GL_ARB_texture_float){
293+ if (ctxCaps.GL_ARB_half_float_pixel){
294+ caps.add(Caps.FloatTexture);
295+ }
296+ }
297+
298+ if (ctxCaps.GL_ARB_vertex_array_object)
299+ caps.add(Caps.VertexBufferArray);
300+
301+ boolean latc = ctxCaps.GL_EXT_texture_compression_latc;
302+ boolean atdc = ctxCaps.GL_ATI_texture_compression_3dc;
303+ if (latc || atdc){
304+ caps.add(Caps.TextureCompressionLATC);
305+ if (atdc && !latc){
306+ tdc = true;
307+ }
308+ }
309+
310+ if (ctxCaps.GL_EXT_packed_float){
311+ caps.add(Caps.PackedFloatColorBuffer);
312+ if (ctxCaps.GL_ARB_half_float_pixel){
313+ // because textures are usually uploaded as RGB16F
314+ // need half-float pixel
315+ caps.add(Caps.PackedFloatTexture);
316+ }
317+ }
318+
319+ if (ctxCaps.GL_EXT_texture_array)
320+ caps.add(Caps.TextureArray);
321+
322+ if (ctxCaps.GL_EXT_texture_shared_exponent)
323+ caps.add(Caps.SharedExponentTexture);
324+
325+ if (ctxCaps.GL_EXT_framebuffer_object){
326+ caps.add(Caps.FrameBuffer);
327+
328+ glGetInteger(GL_MAX_RENDERBUFFER_SIZE_EXT, intBuf16);
329+ maxRBSize = intBuf16.get(0);
330+ logger.log(Level.FINER, "FBO RB Max Size: {0}", maxRBSize);
331+
332+ glGetInteger(GL_MAX_COLOR_ATTACHMENTS_EXT, intBuf16);
333+ maxFBOAttachs = intBuf16.get(0);
334+ logger.log(Level.FINER, "FBO Max renderbuffers: {0}", maxFBOAttachs);
335+
336+ if (ctxCaps.GL_EXT_framebuffer_multisample){
337+ caps.add(Caps.FrameBufferMultisample);
338+
339+ glGetInteger(GL_MAX_SAMPLES_EXT, intBuf16);
340+ maxFBOSamples = intBuf16.get(0);
341+ logger.log(Level.FINER, "FBO Max Samples: {0}", maxFBOSamples);
342+ }
343+
344+ if (ctxCaps.GL_ARB_draw_buffers){
345+ caps.add(Caps.FrameBufferMRT);
346+ glGetInteger(ARBDrawBuffers.GL_MAX_DRAW_BUFFERS_ARB, intBuf16);
347+ maxMRTFBOAttachs = intBuf16.get(0);
348+ logger.log(Level.FINER, "FBO Max MRT renderbuffers: {0}", maxMRTFBOAttachs);
349+ }
350+ }
351+
352+ if (ctxCaps.GL_ARB_multisample){
353+ glGetInteger(ARBMultisample.GL_SAMPLE_BUFFERS_ARB, intBuf16);
354+ boolean available = intBuf16.get(0) != 0;
355+ glGetInteger(ARBMultisample.GL_SAMPLES_ARB, intBuf16);
356+ int samples = intBuf16.get(0);
357+ logger.log(Level.FINER, "Samples: {0}", samples);
358+ boolean enabled = glIsEnabled(ARBMultisample.GL_MULTISAMPLE_ARB);
359+ if (samples > 0 && available && !enabled){
360+ glEnable(ARBMultisample.GL_MULTISAMPLE_ARB);
361+ }
362+ }
363+ */
364+ Gdx.gl20.glGetIntegerv(GL20.GL_MAX_RENDERBUFFER_SIZE, intBuf16);
365+ maxRBSize = intBuf16.get(0);
366+ logger.log(Level.FINER, "FBO RB Max Size: {0}", maxRBSize);
367+
368+ String extensions = Gdx.gl20.glGetString(GL20.GL_EXTENSIONS);
369+ logger.log(Level.INFO, "GL_EXTENSIONS: {0}", extensions);
370+
371+// GLES20.glGetIntegerv(GLES20.GL_COMPRESSED_TEXTURE_FORMATS, intBuf16);
372+// for (int i = 0; i < intBuf16.limit(); i++) {
373+// logger.log(Level.INFO, "Compressed Texture Formats: {0}", intBuf16.get(i));
374+// }
375+
376+ if (extensions.contains("GL_OES_texture_npot")) {
377+ powerOf2 = true;
378+ }
379+
380+
381+
382+ applyRenderState(RenderState.DEFAULT);
383+// GLES20.glClearDepthf(1.0f);
384+
385+ if (verboseLogging) {
386+ logger.info("GLES20.glDisable(GL10.GL_DITHER)");
387+ }
388+
389+ Gdx.gl20.glDisable(GL20.GL_DITHER);
390+
391+ checkGLError();
392+
393+ if (verboseLogging) {
394+ logger.info("GLES20.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST)");
395+ }
396+
397+ Gdx.gl20.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
398+
399+// checkGLError();
400+
401+ useVBO = true;
402+
403+ // NOTE: SDK_INT is only available since 1.6,
404+ // but for jME3 it doesn't matter since android versions 1.5 and below
405+ // are not supported.
406+ //if (Build.VERSION.SDK_INT >= 9) {
407+ // useVBO = true;
408+ //}
409+ // chekc Adreno200,205,220 bug
410+ if (Gdx.gl20.glGetString(GL20.GL_RENDERER).indexOf("Adreno") >= 0) {
411+ adreno_finish_bug = true;
412+ }
413+ logger.log(Level.INFO, "Caps: {0}", caps);
414+ }
415+
416+ /**
417+ * <code>resetGLObjects</code> should be called when die GLView gets recreated to reset all GPU objects
418+ */
419+ public void resetGLObjects() {
420+ objManager.resetObjects();
421+ statistics.clearMemory();
422+ boundShader = null;
423+ lastFb = null;
424+ context.reset();
425+ }
426+
427+ public void cleanup() {
428+ objManager.deleteAllObjects(this);
429+ statistics.clearMemory();
430+ }
431+
432+ private void checkCap(Caps cap) {
433+ if (!caps.contains(cap)) {
434+ throw new UnsupportedOperationException("Required capability missing: " + cap.name());
435+ }
436+ }
437+
438+ /*********************************************************************\
439+ |* Render State *|
440+ \*********************************************************************/
441+ public void setDepthRange(float start, float end) {
442+
443+ if (verboseLogging) {
444+ logger.log(Level.INFO, "GLES20.glDepthRangef({0}, {1})", new Object[]{start, end});
445+ }
446+ Gdx.gl20.glDepthRangef(start, end);
447+ checkGLError();
448+ }
449+
450+ public void clearBuffers(boolean color, boolean depth, boolean stencil) {
451+ int bits = 0;
452+ if (color) {
453+ bits = GL20.GL_COLOR_BUFFER_BIT;
454+ }
455+ if (depth) {
456+ bits |= GL20.GL_DEPTH_BUFFER_BIT;
457+ if (context.depthWriteEnabled == false) {
458+ Gdx.gl20.glDepthMask(true);
459+ context.depthWriteEnabled = true;
460+ }
461+ }
462+ if (stencil) {
463+ bits |= GL20.GL_STENCIL_BUFFER_BIT;
464+ }
465+ if (bits != 0) {
466+ if (verboseLogging) {
467+ logger.log(Level.INFO, "GLES20.glClear(color={0}, depth={1}, stencil={2})", new Object[]{color, depth, stencil});
468+ }
469+ Gdx.gl20.glClear(bits);
470+ checkGLError();
471+ }
472+ }
473+
474+ public void setBackgroundColor(ColorRGBA color) {
475+ if (verboseLogging) {
476+ logger.log(Level.INFO, "GLES20.glClearColor({0}, {1}, {2}, {3})", new Object[]{color.r, color.g, color.b, color.a});
477+ }
478+ Gdx.gl20.glClearColor(color.r, color.g, color.b, color.a);
479+ checkGLError();
480+ }
481+
482+ public void applyRenderState(RenderState state) {
483+ /*
484+ if (state.isWireframe() && !context.wireframe){
485+ GLES20.glPolygonMode(GLES20.GL_FRONT_AND_BACK, GLES20.GL_LINE);
486+ context.wireframe = true;
487+ }else if (!state.isWireframe() && context.wireframe){
488+ GLES20.glPolygonMode(GLES20.GL_FRONT_AND_BACK, GLES20.GL_FILL);
489+ context.wireframe = false;
490+ }
491+ */
492+ if (state.isDepthTest() && !context.depthTestEnabled) {
493+ if (verboseLogging) {
494+ logger.info("GLES20.glEnable(GLES20.GL_DEPTH_TEST)");
495+ }
496+ Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST);
497+ checkGLError();
498+ if (verboseLogging) {
499+ logger.info("GLES20.glDepthFunc(GL20.LEQUAL)");
500+ }
501+ Gdx.gl20.glDepthFunc(GL20.GL_LEQUAL);
502+ checkGLError();
503+ context.depthTestEnabled = true;
504+ } else if (!state.isDepthTest() && context.depthTestEnabled) {
505+ if (verboseLogging) {
506+ logger.info("GLES20.glDisable(GLES20.GL_DEPTH_TEST)");
507+ }
508+ Gdx.gl20.glDisable(GL20.GL_DEPTH_TEST);
509+ checkGLError();
510+ context.depthTestEnabled = false;
511+ }
512+ if (state.isAlphaTest() && !context.alphaTestEnabled) {
513+// GLES20.glEnable(GLES20.GL_ALPHA_TEST);
514+// GLES20.glAlphaFunc(GLES20.GL_GREATER, state.getAlphaFallOff());
515+ context.alphaTestEnabled = true;
516+ } else if (!state.isAlphaTest() && context.alphaTestEnabled) {
517+// GLES20.glDisable(GLES20.GL_ALPHA_TEST);
518+ context.alphaTestEnabled = false;
519+ }
520+ if (state.isDepthWrite() && !context.depthWriteEnabled) {
521+ if (verboseLogging) {
522+ logger.info("GLES20.glDepthMask(true)");
523+ }
524+ Gdx.gl20.glDepthMask(true);
525+ checkGLError();
526+ context.depthWriteEnabled = true;
527+ } else if (!state.isDepthWrite() && context.depthWriteEnabled) {
528+ if (verboseLogging) {
529+ logger.info("GLES20.glDepthMask(false)");
530+ }
531+ Gdx.gl20.glDepthMask(false);
532+ checkGLError();
533+ context.depthWriteEnabled = false;
534+ }
535+ if (state.isColorWrite() && !context.colorWriteEnabled) {
536+ if (verboseLogging) {
537+ logger.info("GLES20.glColorMask(true, true, true, true)");
538+ }
539+ Gdx.gl20.glColorMask(true, true, true, true);
540+ checkGLError();
541+ context.colorWriteEnabled = true;
542+ } else if (!state.isColorWrite() && context.colorWriteEnabled) {
543+ if (verboseLogging) {
544+ logger.info("GLES20.glColorMask(false, false, false, false)");
545+ }
546+ Gdx.gl20.glColorMask(false, false, false, false);
547+ checkGLError();
548+ context.colorWriteEnabled = false;
549+ }
550+ if (state.isPointSprite() && !context.pointSprite) {
551+// GLES20.glEnable(GLES20.GL_POINT_SPRITE);
552+// GLES20.glTexEnvi(GLES20.GL_POINT_SPRITE, GLES20.GL_COORD_REPLACE, GLES20.GL_TRUE);
553+// GLES20.glEnable(GLES20.GL_VERTEX_PROGRAM_POINT_SIZE);
554+// GLES20.glPointParameterf(GLES20.GL_POINT_SIZE_MIN, 1.0f);
555+ } else if (!state.isPointSprite() && context.pointSprite) {
556+// GLES20.glDisable(GLES20.GL_POINT_SPRITE);
557+ }
558+
559+ if (state.isPolyOffset()) {
560+ if (!context.polyOffsetEnabled) {
561+ if (verboseLogging) {
562+ logger.info("GLES20.glEnable(GLES20.GL_POLYGON_OFFSET_FILL)");
563+ }
564+ Gdx.gl20.glEnable(GL20.GL_POLYGON_OFFSET_FILL);
565+ checkGLError();
566+ if (verboseLogging) {
567+ logger.log(Level.INFO, "GLES20.glPolygonOffset({0}, {1})", new Object[]{state.getPolyOffsetFactor(), state.getPolyOffsetUnits()});
568+ }
569+ Gdx.gl20.glPolygonOffset(state.getPolyOffsetFactor(),
570+ state.getPolyOffsetUnits());
571+ checkGLError();
572+ context.polyOffsetEnabled = true;
573+ context.polyOffsetFactor = state.getPolyOffsetFactor();
574+ context.polyOffsetUnits = state.getPolyOffsetUnits();
575+ } else {
576+ if (state.getPolyOffsetFactor() != context.polyOffsetFactor
577+ || state.getPolyOffsetUnits() != context.polyOffsetUnits) {
578+ if (verboseLogging) {
579+ logger.log(Level.INFO, "GLES20.glPolygonOffset({0}, {1})", new Object[]{state.getPolyOffsetFactor(), state.getPolyOffsetUnits()});
580+ }
581+ Gdx.gl20.glPolygonOffset(state.getPolyOffsetFactor(),
582+ state.getPolyOffsetUnits());
583+ checkGLError();
584+ context.polyOffsetFactor = state.getPolyOffsetFactor();
585+ context.polyOffsetUnits = state.getPolyOffsetUnits();
586+ }
587+ }
588+ } else {
589+ if (context.polyOffsetEnabled) {
590+ if (verboseLogging) {
591+ logger.info("GLES20.glDisable(GLES20.GL_POLYGON_OFFSET_FILL)");
592+ }
593+ Gdx.gl20.glDisable(GL20.GL_POLYGON_OFFSET_FILL);
594+ checkGLError();
595+ context.polyOffsetEnabled = false;
596+ context.polyOffsetFactor = 0;
597+ context.polyOffsetUnits = 0;
598+ }
599+ }
600+ if (state.getFaceCullMode() != context.cullMode) {
601+ if (state.getFaceCullMode() == RenderState.FaceCullMode.Off) {
602+ if (verboseLogging) {
603+ logger.info("GLES20.glDisable(GLES20.GL_CULL_FACE)");
604+ }
605+ Gdx.gl20.glDisable(GL20.GL_CULL_FACE);
606+ } else {
607+ if (verboseLogging) {
608+ logger.info("GLES20.glEnable(GLES20.GL_CULL_FACE)");
609+ }
610+ Gdx.gl20.glEnable(GL20.GL_CULL_FACE);
611+ }
612+
613+ checkGLError();
614+
615+ switch (state.getFaceCullMode()) {
616+ case Off:
617+ break;
618+ case Back:
619+ if (verboseLogging) {
620+ logger.info("GLES20.glCullFace(GLES20.GL_BACK)");
621+ }
622+ Gdx.gl20.glCullFace(GL20.GL_BACK);
623+ break;
624+ case Front:
625+ if (verboseLogging) {
626+ logger.info("GLES20.glCullFace(GLES20.GL_FRONT)");
627+ }
628+ Gdx.gl20.glCullFace(GL20.GL_FRONT);
629+ break;
630+ case FrontAndBack:
631+ if (verboseLogging) {
632+ logger.info("GLES20.glCullFace(GLES20.GL_FRONT_AND_BACK)");
633+ }
634+ Gdx.gl20.glCullFace(GL20.GL_FRONT_AND_BACK);
635+ break;
636+ default:
637+ throw new UnsupportedOperationException("Unrecognized face cull mode: "
638+ + state.getFaceCullMode());
639+ }
640+
641+ checkGLError();
642+
643+ context.cullMode = state.getFaceCullMode();
644+ }
645+
646+ if (state.getBlendMode() != context.blendMode) {
647+ if (state.getBlendMode() == RenderState.BlendMode.Off) {
648+ if (verboseLogging) {
649+ logger.info("GLES20.glDisable(GLES20.GL_BLEND)");
650+ }
651+ Gdx.gl20.glDisable(GL20.GL_BLEND);
652+ } else {
653+ if (verboseLogging) {
654+ logger.info("GLES20.glEnable(GLES20.GL_BLEND)");
655+ }
656+ Gdx.gl20.glEnable(GL20.GL_BLEND);
657+ switch (state.getBlendMode()) {
658+ case Off:
659+ break;
660+ case Additive:
661+ if (verboseLogging) {
662+ logger.info("GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE)");
663+ }
664+ Gdx.gl20.glBlendFunc(GL20.GL_ONE, GL20.GL_ONE);
665+ break;
666+ case AlphaAdditive:
667+ if (verboseLogging) {
668+ logger.info("GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE)");
669+ }
670+ Gdx.gl20.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE);
671+ break;
672+ case Color:
673+ if (verboseLogging) {
674+ logger.info("GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_COLOR)");
675+ }
676+ Gdx.gl20.glBlendFunc(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_COLOR);
677+ break;
678+ case Alpha:
679+ if (verboseLogging) {
680+ logger.info("GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA)");
681+ }
682+ Gdx.gl20.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
683+ break;
684+ case PremultAlpha:
685+ if (verboseLogging) {
686+ logger.info("GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA)");
687+ }
688+ Gdx.gl20.glBlendFunc(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA);
689+ break;
690+ case Modulate:
691+ if (verboseLogging) {
692+ logger.info("GLES20.glBlendFunc(GLES20.GL_DST_COLOR, GLES20.GL_ZERO)");
693+ }
694+ Gdx.gl20.glBlendFunc(GL20.GL_DST_COLOR, GL20.GL_ZERO);
695+ break;
696+ case ModulateX2:
697+ if (verboseLogging) {
698+ logger.info("GLES20.glBlendFunc(GLES20.GL_DST_COLOR, GLES20.GL_SRC_COLOR)");
699+ }
700+ Gdx.gl20.glBlendFunc(GL20.GL_DST_COLOR, GL20.GL_SRC_COLOR);
701+ break;
702+ default:
703+ throw new UnsupportedOperationException("Unrecognized blend mode: "
704+ + state.getBlendMode());
705+ }
706+ }
707+
708+ checkGLError();
709+
710+ context.blendMode = state.getBlendMode();
711+ }
712+ }
713+
714+ /*********************************************************************\
715+ |* Camera and World transforms *|
716+ \*********************************************************************/
717+ public void setViewPort(int x, int y, int w, int h) {
718+ if (x != vpX || vpY != y || vpW != w || vpH != h) {
719+ if (verboseLogging) {
720+ logger.log(Level.INFO, "GLES20.glViewport({0}, {1}, {2}, {3})", new Object[]{x, y, w, h});
721+ }
722+ Gdx.gl20.glViewport(x, y, w, h);
723+ checkGLError();
724+ vpX = x;
725+ vpY = y;
726+ vpW = w;
727+ vpH = h;
728+ }
729+ }
730+
731+ public void setClipRect(int x, int y, int width, int height) {
732+ if (!context.clipRectEnabled) {
733+ if (verboseLogging) {
734+ logger.info("GLES20.glEnable(GLES20.GL_SCISSOR_TEST)");
735+ }
736+ Gdx.gl20.glEnable(GL20.GL_SCISSOR_TEST);
737+ checkGLError();
738+ context.clipRectEnabled = true;
739+ }
740+ if (clipX != x || clipY != y || clipW != width || clipH != height) {
741+ if (verboseLogging) {
742+ logger.log(Level.INFO, "GLES20.glScissor({0}, {1}, {2}, {3})", new Object[]{x, y, width, height});
743+ }
744+ Gdx.gl20.glScissor(x, y, width, height);
745+ clipX = x;
746+ clipY = y;
747+ clipW = width;
748+ clipH = height;
749+ checkGLError();
750+ }
751+ }
752+
753+ public void clearClipRect() {
754+ if (context.clipRectEnabled) {
755+ if (verboseLogging) {
756+ logger.info("GLES20.glDisable(GLES20.GL_SCISSOR_TEST)");
757+ }
758+ Gdx.gl20.glDisable(GL20.GL_SCISSOR_TEST);
759+ checkGLError();
760+ context.clipRectEnabled = false;
761+
762+ clipX = 0;
763+ clipY = 0;
764+ clipW = 0;
765+ clipH = 0;
766+ }
767+ }
768+
769+ public void onFrame() {
770+ objManager.deleteUnused(this);
771+// statistics.clearFrame();
772+ }
773+
774+ public void setWorldMatrix(Matrix4f worldMatrix) {
775+ }
776+
777+ public void setViewProjectionMatrices(Matrix4f viewMatrix, Matrix4f projMatrix) {
778+ }
779+
780+ /*********************************************************************\
781+ |* Shaders *|
782+ \*********************************************************************/
783+ protected void updateUniformLocation(Shader shader, Uniform uniform) {
784+ stringBuf.setLength(0);
785+ stringBuf.append(uniform.getName()).append('\0');
786+ updateNameBuffer();
787+ if (verboseLogging) {
788+ logger.log(Level.INFO, "GLES20.glGetUniformLocation({0}, {1})", new Object[]{shader.getId(), uniform.getName()});
789+ }
790+ int loc = Gdx.gl20.glGetUniformLocation(shader.getId(), uniform.getName());
791+ checkGLError();
792+ if (loc < 0) {
793+ uniform.setLocation(-1);
794+ // uniform is not declared in shader
795+ if (verboseLogging) {
796+ logger.log(Level.WARNING, "Uniform [{0}] is not declared in shader.", uniform.getName());
797+ }
798+ } else {
799+ uniform.setLocation(loc);
800+ }
801+ }
802+
803+ protected void updateUniform(Shader shader, Uniform uniform) {
804+ int shaderId = shader.getId();
805+
806+ assert uniform.getName() != null;
807+ assert shader.getId() > 0;
808+
809+ if (context.boundShaderProgram != shaderId) {
810+ if (verboseLogging) {
811+ logger.log(Level.INFO, "GLES20.glUseProgram({0})", shaderId);
812+ }
813+ Gdx.gl20.glUseProgram(shaderId);
814+ checkGLError();
815+ statistics.onShaderUse(shader, true);
816+ boundShader = shader;
817+ context.boundShaderProgram = shaderId;
818+ } else {
819+ statistics.onShaderUse(shader, false);
820+ }
821+
822+ int loc = uniform.getLocation();
823+ if (loc == -1) {
824+ if (verboseLogging) {
825+ logger.log(Level.WARNING, "no location for uniform [{0}]", uniform.getName());
826+ }
827+ return;
828+ }
829+
830+ if (loc == -2) {
831+ // get uniform location
832+ updateUniformLocation(shader, uniform);
833+ if (uniform.getLocation() == -1) {
834+ // not declared, ignore
835+
836+ if (verboseLogging) {
837+ logger.log(Level.WARNING, "not declared uniform: [{0}]", uniform.getName());
838+ }
839+
840+ uniform.clearUpdateNeeded();
841+ return;
842+ }
843+ loc = uniform.getLocation();
844+ }
845+
846+ if (uniform.getVarType() == null) {
847+ logger.warning("value is not set yet.");
848+ return; // value not set yet..
849+ }
850+
851+ statistics.onUniformSet();
852+
853+ uniform.clearUpdateNeeded();
854+ FloatBuffer fb;
855+ switch (uniform.getVarType()) {
856+ case Float:
857+ if (verboseLogging) {
858+ logger.info("GLES20.glUniform1f set Float. " + uniform.getName());
859+ }
860+ Float f = (Float) uniform.getValue();
861+ Gdx.gl20.glUniform1f(loc, f.floatValue());
862+ break;
863+ case Vector2:
864+ if (verboseLogging) {
865+ logger.info("GLES20.glUniform2f set Vector2. " + uniform.getName());
866+ }
867+ Vector2f v2 = (Vector2f) uniform.getValue();
868+ Gdx.gl20.glUniform2f(loc, v2.getX(), v2.getY());
869+ break;
870+ case Vector3:
871+ if (verboseLogging) {
872+ logger.info("GLES20.glUniform3f set Vector3. " + uniform.getName());
873+ }
874+ Vector3f v3 = (Vector3f) uniform.getValue();
875+ Gdx.gl20.glUniform3f(loc, v3.getX(), v3.getY(), v3.getZ());
876+ break;
877+ case Vector4:
878+ if (verboseLogging) {
879+ logger.info("GLES20.glUniform4f set Vector4." + uniform.getName());
880+ }
881+ Object val = uniform.getValue();
882+ if (val instanceof ColorRGBA) {
883+ ColorRGBA c = (ColorRGBA) val;
884+ Gdx.gl20.glUniform4f(loc, c.r, c.g, c.b, c.a);
885+ } else if (val instanceof Vector4f) {
886+ Vector4f c = (Vector4f) val;
887+ Gdx.gl20.glUniform4f(loc, c.x, c.y, c.z, c.w);
888+ } else {
889+ Quaternion c = (Quaternion) uniform.getValue();
890+ Gdx.gl20.glUniform4f(loc, c.getX(), c.getY(), c.getZ(), c.getW());
891+ }
892+ break;
893+ case Boolean:
894+ if (verboseLogging) {
895+ logger.info("GLES20.glUniform1i set Boolean." + uniform.getName());
896+ }
897+ Boolean b = (Boolean) uniform.getValue();
898+ Gdx.gl20.glUniform1i(loc, b.booleanValue() ? GL20.GL_TRUE : GL20.GL_FALSE);
899+ break;
900+ case Matrix3:
901+ if (verboseLogging) {
902+ logger.info("GLES20.glUniformMatrix3fv set Matrix3." + uniform.getName());
903+ }
904+ fb = (FloatBuffer) uniform.getValue();
905+ assert fb.remaining() == 9;
906+ Gdx.gl20.glUniformMatrix3fv(loc, 1, false, fb);
907+ break;
908+ case Matrix4:
909+ if (verboseLogging) {
910+ logger.info("GLES20.glUniformMatrix4fv set Matrix4." + uniform.getName());
911+ }
912+ fb = (FloatBuffer) uniform.getValue();
913+ assert fb.remaining() == 16;
914+ Gdx.gl20.glUniformMatrix4fv(loc, 1, false, fb);
915+ break;
916+ case FloatArray:
917+ if (verboseLogging) {
918+ logger.info("GLES20.glUniform1fv set FloatArray." + uniform.getName());
919+ }
920+ fb = (FloatBuffer) uniform.getValue();
921+ Gdx.gl20.glUniform1fv(loc, fb.capacity(), fb);
922+ break;
923+ case Vector2Array:
924+ if (verboseLogging) {
925+ logger.info("GLES20.glUniform2fv set Vector2Array." + uniform.getName());
926+ }
927+ fb = (FloatBuffer) uniform.getValue();
928+ Gdx.gl20.glUniform2fv(loc, fb.capacity() / 2, fb);
929+ break;
930+ case Vector3Array:
931+ if (verboseLogging) {
932+ logger.info("GLES20.glUniform3fv set Vector3Array." + uniform.getName());
933+ }
934+ fb = (FloatBuffer) uniform.getValue();
935+ Gdx.gl20.glUniform3fv(loc, fb.capacity() / 3, fb);
936+ break;
937+ case Vector4Array:
938+ if (verboseLogging) {
939+ logger.info("GLES20.glUniform4fv set Vector4Array." + uniform.getName());
940+ }
941+ fb = (FloatBuffer) uniform.getValue();
942+ Gdx.gl20.glUniform4fv(loc, fb.capacity() / 4, fb);
943+ break;
944+ case Matrix4Array:
945+ if (verboseLogging) {
946+ logger.info("GLES20.glUniform4fv set Matrix4Array." + uniform.getName());
947+ }
948+ fb = (FloatBuffer) uniform.getValue();
949+ Gdx.gl20.glUniformMatrix4fv(loc, fb.capacity() / 16, false, fb);
950+ break;
951+ case Int:
952+ if (verboseLogging) {
953+ logger.info("GLES20.glUniform1i set Int." + uniform.getName());
954+ }
955+ Integer i = (Integer) uniform.getValue();
956+ Gdx.gl20.glUniform1i(loc, i.intValue());
957+ break;
958+ default:
959+ throw new UnsupportedOperationException("Unsupported uniform type: " + uniform.getVarType());
960+ }
961+ checkGLError();
962+ }
963+
964+ protected void updateShaderUniforms(Shader shader) {
965+ ListMap<String, Uniform> uniforms = shader.getUniformMap();
966+// for (Uniform uniform : shader.getUniforms()){
967+ for (int i = 0; i < uniforms.size(); i++) {
968+ Uniform uniform = uniforms.getValue(i);
969+ if (uniform.isUpdateNeeded()) {
970+ updateUniform(shader, uniform);
971+ }
972+ }
973+ }
974+
975+ protected void resetUniformLocations(Shader shader) {
976+ ListMap<String, Uniform> uniforms = shader.getUniformMap();
977+// for (Uniform uniform : shader.getUniforms()){
978+ for (int i = 0; i < uniforms.size(); i++) {
979+ Uniform uniform = uniforms.getValue(i);
980+ uniform.reset(); // e.g check location again
981+ }
982+ }
983+
984+ /*
985+ * (Non-javadoc)
986+ * Only used for fixed-function. Ignored.
987+ */
988+ public void setLighting(LightList list) {
989+ }
990+
991+ public int convertShaderType(ShaderType type) {
992+ switch (type) {
993+ case Fragment:
994+ return GL20.GL_FRAGMENT_SHADER;
995+ case Vertex:
996+ return GL20.GL_VERTEX_SHADER;
997+// case Geometry:
998+// return ARBGeometryShader4.GL_GEOMETRY_SHADER_ARB;
999+ default:
1000+ throw new RuntimeException("Unrecognized shader type.");
1001+ }
1002+ }
1003+
1004+ public void updateShaderSourceData(ShaderSource source, String language) {
1005+ int id = source.getId();
1006+ if (id == -1) {
1007+ // create id
1008+ if (verboseLogging) {
1009+ logger.info("GLES20.glCreateShader(" + source.getType() + ")");
1010+ }
1011+ id = Gdx.gl20.glCreateShader(convertShaderType(source.getType()));
1012+ checkGLError();
1013+ if (id <= 0) {
1014+ throw new RendererException("Invalid ID received when trying to create shader.");
1015+ }
1016+
1017+ source.setId(id);
1018+ }
1019+
1020+ // upload shader source
1021+ // merge the defines and source code
1022+ byte[] versionData = new byte[]{};//"#version 140\n".getBytes();
1023+// versionData = "#define INSTANCING 1\n".getBytes();
1024+ byte[] definesCodeData = source.getDefines().getBytes();
1025+ byte[] sourceCodeData = source.getSource().getBytes();
1026+ ByteBuffer codeBuf = BufferUtils.createByteBuffer(versionData.length
1027+ + definesCodeData.length
1028+ + sourceCodeData.length);
1029+ codeBuf.put(versionData);
1030+ codeBuf.put(definesCodeData);
1031+ codeBuf.put(sourceCodeData);
1032+ codeBuf.flip();
1033+
1034+ if (verboseLogging) {
1035+ logger.info("GLES20.glShaderSource(" + id + ")");
1036+ }
1037+ if (source.getType().equals(ShaderType.Vertex)
1038+ && Gdx.gl20.glGetString(GL20.GL_RENDERER).indexOf("PowerVR") >= 0) {
1039+ Gdx.gl20.glShaderSource(
1040+ id,
1041+ source.getDefines()
1042+ + source.getSource());
1043+ } else {
1044+ if (!Gdx.app.getType().equals(com.badlogic.gdx.Application.ApplicationType.Desktop)) {
1045+ Gdx.gl20.glShaderSource(
1046+ id,
1047+ "precision mediump float;\n"
1048+ + source.getDefines()
1049+ + source.getSource());
1050+ } else {
1051+ Gdx.gl20.glShaderSource(
1052+ id,
1053+ source.getDefines()
1054+ + source.getSource());
1055+ }
1056+ }
1057+ checkGLError();
1058+
1059+ if (verboseLogging) {
1060+ logger.info("GLES20.glCompileShader(" + id + ")");
1061+ }
1062+
1063+ Gdx.gl20.glCompileShader(id);
1064+
1065+ checkGLError();
1066+
1067+ if (verboseLogging) {
1068+ logger.info("GLES20.glGetShaderiv(" + id + ", GLES20.GL_COMPILE_STATUS)");
1069+ }
1070+
1071+ Gdx.gl20.glGetShaderiv(id, GL20.GL_COMPILE_STATUS, intBuf1);
1072+
1073+ checkGLError();
1074+
1075+ boolean compiledOK = intBuf1.get(0) == GL20.GL_TRUE;
1076+ String infoLog = null;
1077+
1078+ if (VALIDATE_SHADER || !compiledOK) {
1079+ // even if compile succeeded, check
1080+ // log for warnings
1081+ if (verboseLogging) {
1082+ logger.info("GLES20.glGetShaderiv()");
1083+ }
1084+ Gdx.gl20.glGetShaderiv(id, GL20.GL_INFO_LOG_LENGTH, intBuf1);
1085+ checkGLError();
1086+ if (verboseLogging) {
1087+ logger.info("GLES20.glGetShaderInfoLog(" + id + ")");
1088+ }
1089+ infoLog = Gdx.gl20.glGetShaderInfoLog(id);
1090+ logger.severe("Errooooooooooot(" + id + ")");
1091+ }
1092+
1093+ if (compiledOK) {
1094+ if (infoLog != null) {
1095+ logger.log(Level.INFO, "compile success: " + source.getName() + ", " + infoLog);
1096+ } else {
1097+ logger.log(Level.FINE, "compile success: " + source.getName());
1098+ }
1099+ } else {
1100+ logger.log(Level.WARNING, "Bad compile of:\n{0}{1}",
1101+ new Object[]{source.getDefines(), source.getSource()});
1102+ if (infoLog != null) {
1103+ throw new RendererException("compile error in:" + source + " error:" + infoLog);
1104+ } else {
1105+ throw new RendererException("compile error in:" + source + " error: <not provided>");
1106+ }
1107+ }
1108+
1109+ source.clearUpdateNeeded();
1110+ // only usable if compiled
1111+ source.setUsable(compiledOK);
1112+ if (!compiledOK) {
1113+ // make sure to dispose id cause all program's
1114+ // shaders will be cleared later.
1115+ if (verboseLogging) {
1116+ logger.info("GLES20.glDeleteShader(" + id + ")");
1117+ }
1118+ Gdx.gl20.glDeleteShader(id);
1119+ checkGLError();
1120+ } else {
1121+ // register for cleanup since the ID is usable
1122+ objManager.registerForCleanup(source);
1123+ }
1124+ }
1125+
1126+ public void updateShaderData(Shader shader) {
1127+ int id = shader.getId();
1128+ boolean needRegister = false;
1129+ if (id == -1) {
1130+ // create program
1131+
1132+ if (verboseLogging) {
1133+ logger.info("GLES20.glCreateProgram()");
1134+ }
1135+
1136+ id = Gdx.gl20.glCreateProgram();
1137+
1138+ if (id <= 0) {
1139+ throw new RendererException("Invalid ID received when trying to create shader program.");
1140+ }
1141+
1142+ shader.setId(id);
1143+ needRegister = true;
1144+ }
1145+
1146+ for (ShaderSource source : shader.getSources()) {
1147+ if (source.isUpdateNeeded()) {
1148+ updateShaderSourceData(source, shader.getLanguage());
1149+ // shader has been compiled here
1150+ }
1151+
1152+ if (!source.isUsable()) {
1153+ // it's useless.. just forget about everything..
1154+ shader.setUsable(false);
1155+ shader.clearUpdateNeeded();
1156+ return;
1157+ }
1158+ if (verboseLogging) {
1159+ logger.info("GLES20.glAttachShader(" + id + ", " + source.getId() + ")");
1160+ }
1161+
1162+ Gdx.gl20.glAttachShader(id, source.getId());
1163+ }
1164+
1165+ // link shaders to program
1166+ if (verboseLogging) {
1167+ logger.info("GLES20.glLinkProgram(" + id + ")");
1168+ }
1169+
1170+ Gdx.gl20.glLinkProgram(id);
1171+
1172+
1173+ if (verboseLogging) {
1174+ logger.info("GLES20.glGetProgramiv(" + id + ")");
1175+ }
1176+
1177+ Gdx.gl20.glGetProgramiv(id, GL20.GL_LINK_STATUS, intBuf1);
1178+
1179+ boolean linkOK = intBuf1.get(0) == GL20.GL_TRUE;
1180+ String infoLog = null;
1181+
1182+ if (VALIDATE_SHADER || !linkOK) {
1183+ if (verboseLogging) {
1184+ logger.info("GLES20.glGetProgramiv(" + id + ", GLES20.GL_INFO_LOG_LENGTH, buffer)");
1185+ }
1186+
1187+ Gdx.gl20.glGetProgramiv(id, GL20.GL_INFO_LOG_LENGTH, intBuf1);
1188+
1189+ int length = intBuf1.get(0);
1190+ if (length > 3) {
1191+ // get infos
1192+
1193+ if (verboseLogging) {
1194+ logger.info("GLES20.glGetProgramInfoLog(" + id + ")");
1195+ }
1196+
1197+ infoLog = Gdx.gl20.glGetProgramInfoLog(id);
1198+ }
1199+ }
1200+
1201+ if (linkOK) {
1202+ if (infoLog != null) {
1203+ logger.log(Level.INFO, "shader link success. \n{0}", infoLog);
1204+ } else {
1205+ logger.fine("shader link success");
1206+ }
1207+ } else {
1208+ if (infoLog != null) {
1209+ throw new RendererException("Shader link failure, shader:" + shader + " info:" + infoLog);
1210+ } else {
1211+ throw new RendererException("Shader link failure, shader:" + shader + " info: <not provided>");
1212+ }
1213+ }
1214+
1215+ shader.clearUpdateNeeded();
1216+ if (!linkOK) {
1217+ // failure.. forget about everything
1218+ shader.resetSources();
1219+ shader.setUsable(false);
1220+ deleteShader(shader);
1221+ } else {
1222+ shader.setUsable(true);
1223+ if (needRegister) {
1224+ objManager.registerForCleanup(shader);
1225+ statistics.onNewShader();
1226+ } else {
1227+ // OpenGL spec: uniform locations may change after re-link
1228+ resetUniformLocations(shader);
1229+ }
1230+ }
1231+ }
1232+
1233+ public void setShader(Shader shader) {
1234+ if (verboseLogging) {
1235+ logger.info("setShader(" + shader + ")");
1236+ }
1237+
1238+ if (shader == null) {
1239+ if (context.boundShaderProgram > 0) {
1240+
1241+ if (verboseLogging) {
1242+ logger.info("GLES20.glUseProgram(0)");
1243+ }
1244+
1245+ Gdx.gl20.glUseProgram(0);
1246+
1247+ statistics.onShaderUse(null, true);
1248+ context.boundShaderProgram = 0;
1249+ boundShader = null;
1250+ }
1251+ } else {
1252+ if (shader.isUpdateNeeded()) {
1253+ updateShaderData(shader);
1254+ }
1255+
1256+ // NOTE: might want to check if any of the
1257+ // sources need an update?
1258+
1259+ if (!shader.isUsable()) {
1260+ logger.warning("shader is not usable.");
1261+ return;
1262+ }
1263+
1264+ assert shader.getId() > 0;
1265+
1266+ updateShaderUniforms(shader);
1267+ if (context.boundShaderProgram != shader.getId()) {
1268+ if (VALIDATE_SHADER) {
1269+ // check if shader can be used
1270+ // with current state
1271+ if (verboseLogging) {
1272+ logger.info("GLES20.glValidateProgram(" + shader.getId() + ")");
1273+ }
1274+
1275+ Gdx.gl20.glValidateProgram(shader.getId());
1276+
1277+ if (verboseLogging) {
1278+ logger.info("GLES20.glGetProgramiv(" + shader.getId() + ", GLES20.GL_VALIDATE_STATUS, buffer)");
1279+ }
1280+
1281+ Gdx.gl20.glGetProgramiv(shader.getId(), GL20.GL_VALIDATE_STATUS, intBuf1);
1282+
1283+ boolean validateOK = intBuf1.get(0) == GL20.GL_TRUE;
1284+
1285+ if (validateOK) {
1286+ logger.fine("shader validate success");
1287+ } else {
1288+ logger.warning("shader validate failure");
1289+ }
1290+ }
1291+
1292+ if (verboseLogging) {
1293+ logger.info("GLES20.glUseProgram(" + shader.getId() + ")");
1294+ }
1295+
1296+ Gdx.gl20.glUseProgram(shader.getId());
1297+
1298+ statistics.onShaderUse(shader, true);
1299+ context.boundShaderProgram = shader.getId();
1300+ boundShader = shader;
1301+ } else {
1302+ statistics.onShaderUse(shader, false);
1303+ }
1304+ }
1305+ }
1306+
1307+ public void setShaderWithoutUpdateUniforms(Shader shader) {
1308+ if (verboseLogging) {
1309+ logger.info("setShader(" + shader + ")");
1310+ }
1311+
1312+ if (shader == null) {
1313+ if (context.boundShaderProgram > 0) {
1314+
1315+ if (verboseLogging) {
1316+ logger.info("GLES20.glUseProgram(0)");
1317+ }
1318+
1319+ Gdx.gl20.glUseProgram(0);
1320+
1321+ statistics.onShaderUse(null, true);
1322+ context.boundShaderProgram = 0;
1323+ boundShader = null;
1324+ }
1325+ } else {
1326+ if (shader.isUpdateNeeded()) {
1327+ updateShaderData(shader);
1328+ }
1329+
1330+ // NOTE: might want to check if any of the
1331+ // sources need an update?
1332+
1333+ if (!shader.isUsable()) {
1334+ logger.warning("shader is not usable.");
1335+ return;
1336+ }
1337+
1338+ assert shader.getId() > 0;
1339+
1340+ if (context.boundShaderProgram != shader.getId()) {
1341+ if (VALIDATE_SHADER) {
1342+ // check if shader can be used
1343+ // with current state
1344+ if (verboseLogging) {
1345+ logger.info("GLES20.glValidateProgram(" + shader.getId() + ")");
1346+ }
1347+
1348+ Gdx.gl20.glValidateProgram(shader.getId());
1349+
1350+ if (verboseLogging) {
1351+ logger.info("GLES20.glGetProgramiv(" + shader.getId() + ", GLES20.GL_VALIDATE_STATUS, buffer)");
1352+ }
1353+
1354+ Gdx.gl20.glGetProgramiv(shader.getId(), GL20.GL_VALIDATE_STATUS, intBuf1);
1355+
1356+ boolean validateOK = intBuf1.get(0) == GL20.GL_TRUE;
1357+
1358+ if (validateOK) {
1359+ logger.fine("shader validate success");
1360+ } else {
1361+ logger.warning("shader validate failure");
1362+ }
1363+ }
1364+
1365+ if (verboseLogging) {
1366+ logger.info("GLES20.glUseProgram(" + shader.getId() + ")");
1367+ }
1368+
1369+ Gdx.gl20.glUseProgram(shader.getId());
1370+
1371+ statistics.onShaderUse(shader, true);
1372+ context.boundShaderProgram = shader.getId();
1373+ boundShader = shader;
1374+ } else {
1375+ statistics.onShaderUse(shader, false);
1376+ }
1377+ }
1378+ }
1379+
1380+ public void deleteShaderSource(ShaderSource source) {
1381+ if (source.getId() < 0) {
1382+ logger.warning("Shader source is not uploaded to GPU, cannot delete.");
1383+ return;
1384+ }
1385+ source.setUsable(false);
1386+ source.clearUpdateNeeded();
1387+
1388+ if (verboseLogging) {
1389+ logger.info("GLES20.glDeleteShader(" + source.getId() + ")");
1390+ }
1391+
1392+ Gdx.gl20.glDeleteShader(source.getId());
1393+ source.resetObject();
1394+ }
1395+
1396+ public void deleteShader(Shader shader) {
1397+ if (shader.getId() == -1) {
1398+ logger.warning("Shader is not uploaded to GPU, cannot delete.");
1399+ return;
1400+ }
1401+ for (ShaderSource source : shader.getSources()) {
1402+ if (source.getId() != -1) {
1403+
1404+ if (verboseLogging) {
1405+ logger.info("GLES20.glDetachShader(" + shader.getId() + ", " + source.getId() + ")");
1406+ }
1407+
1408+ Gdx.gl20.glDetachShader(shader.getId(), source.getId());
1409+ // the next part is done by the GLObjectManager automatically
1410+// glDeleteShader(source.getId());
1411+ }
1412+ }
1413+ // kill all references so sources can be collected
1414+ // if needed.
1415+ shader.resetSources();
1416+
1417+ if (verboseLogging) {
1418+ logger.info("GLES20.glDeleteProgram(" + shader.getId() + ")");
1419+ }
1420+
1421+ Gdx.gl20.glDeleteProgram(shader.getId());
1422+
1423+ statistics.onDeleteShader();
1424+ }
1425+
1426+ /*********************************************************************\
1427+ |* Framebuffers *|
1428+ \*********************************************************************/
1429+ public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) {
1430+ copyFrameBuffer(src, dst, true);
1431+ }
1432+
1433+ public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
1434+ logger.warning("copyFrameBuffer is not supported.");
1435+ }
1436+ private void checkFrameBufferStatus(FrameBuffer fb) {
1437+ try {
1438+ checkFrameBufferError();
1439+ } catch (IllegalStateException ex) {
1440+ logger.log(Level.SEVERE, "=== jMonkeyEngine FBO State ===\n{0}", fb);
1441+ printRealFrameBufferInfo(fb);
1442+ throw ex;
1443+ }
1444+ }
1445+
1446+ private void checkFrameBufferError() {
1447+ int status = Gdx.gl20.glCheckFramebufferStatus(GL20.GL_FRAMEBUFFER);
1448+ switch (status) {
1449+ case GL20.GL_FRAMEBUFFER_COMPLETE:
1450+ break;
1451+ case GL20.GL_FRAMEBUFFER_UNSUPPORTED:
1452+ //Choose different formats
1453+ throw new IllegalStateException("Framebuffer object format is "
1454+ + "unsupported by the video hardware.");
1455+ case GL20.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
1456+ throw new IllegalStateException("Framebuffer has erronous attachment.");
1457+ case GL20.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
1458+ throw new IllegalStateException("Framebuffer doesn't have any renderbuffers attached.");
1459+ case GL20.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
1460+ throw new IllegalStateException("Framebuffer attachments must have same dimensions.");
1461+// case GLES20.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
1462+// throw new IllegalStateException("Framebuffer attachments must have same formats.");
1463+// case GLES20.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
1464+// throw new IllegalStateException("Incomplete draw buffer.");
1465+// case GLES20.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
1466+// throw new IllegalStateException("Incomplete read buffer.");
1467+// case GLES20.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
1468+// throw new IllegalStateException("Incomplete multisample buffer.");
1469+ default:
1470+ //Programming error; will fail on all hardware
1471+ throw new IllegalStateException("Some video driver error "
1472+ + "or programming error occured. "
1473+ + "Framebuffer object status is invalid: " + status);
1474+ }
1475+ }
1476+ private void printRealRenderBufferInfo(FrameBuffer fb, RenderBuffer rb, String name) {
1477+ System.out.println("== Renderbuffer " + name + " ==");
1478+ System.out.println("RB ID: " + rb.getId());
1479+ System.out.println("Is proper? " + Gdx.gl20.glIsRenderbuffer(rb.getId()));
1480+
1481+ int attachment = convertAttachmentSlot(rb.getSlot());
1482+
1483+ intBuf16.clear();
1484+ Gdx.gl20.glGetFramebufferAttachmentParameteriv(GL20.GL_FRAMEBUFFER,
1485+ attachment, GL20.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, intBuf16);
1486+ int type = intBuf16.get(0);
1487+
1488+ intBuf16.clear();
1489+ Gdx.gl20.glGetFramebufferAttachmentParameteriv(GL20.GL_FRAMEBUFFER,
1490+ attachment, GL20.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, intBuf16);
1491+ int rbName = intBuf16.get(0);
1492+
1493+ switch (type) {
1494+ case GL20.GL_NONE:
1495+ System.out.println("Type: None");
1496+ break;
1497+ case GL20.GL_TEXTURE:
1498+ System.out.println("Type: Texture");
1499+ break;
1500+ case GL20.GL_RENDERBUFFER:
1501+ System.out.println("Type: Buffer");
1502+ System.out.println("RB ID: " + rbName);
1503+ break;
1504+ }
1505+
1506+
1507+
1508+ }
1509+
1510+ private void printRealFrameBufferInfo(FrameBuffer fb) {
1511+// boolean doubleBuffer = GLES20.glGetBooleanv(GLES20.GL_DOUBLEBUFFER);
1512+ boolean doubleBuffer = false; // FIXME
1513+// String drawBuf = getTargetBufferName(glGetInteger(GL_DRAW_BUFFER));
1514+// String readBuf = getTargetBufferName(glGetInteger(GL_READ_BUFFER));
1515+
1516+ int fbId = fb.getId();
1517+ intBuf16.clear();
1518+// int curDrawBinding = GLES20.glGetIntegerv(GLES20.GL_DRAW_FRAMEBUFFER_BINDING);
1519+// int curReadBinding = glGetInteger(ARBFramebufferObject.GL_READ_FRAMEBUFFER_BINDING);
1520+
1521+ System.out.println("=== OpenGL FBO State ===");
1522+ System.out.println("Context doublebuffered? " + doubleBuffer);
1523+ System.out.println("FBO ID: " + fbId);
1524+ System.out.println("Is proper? " + Gdx.gl20.glIsFramebuffer(fbId));
1525+// System.out.println("Is bound to draw? " + (fbId == curDrawBinding));
1526+// System.out.println("Is bound to read? " + (fbId == curReadBinding));
1527+// System.out.println("Draw buffer: " + drawBuf);
1528+// System.out.println("Read buffer: " + readBuf);
1529+
1530+ if (context.boundFBO != fbId) {
1531+ Gdx.gl20.glBindFramebuffer(GL20.GL_FRAMEBUFFER, fbId);
1532+ context.boundFBO = fbId;
1533+ }
1534+
1535+ if (fb.getDepthBuffer() != null) {
1536+ printRealRenderBufferInfo(fb, fb.getDepthBuffer(), "Depth");
1537+ }
1538+ for (int i = 0; i < fb.getNumColorBuffers(); i++) {
1539+ printRealRenderBufferInfo(fb, fb.getColorBuffer(i), "Color" + i);
1540+ }
1541+ }
1542+
1543+ private void updateRenderBuffer(FrameBuffer fb, RenderBuffer rb) {
1544+ int id = rb.getId();
1545+ if (id == -1) {
1546+ Gdx.gl20.glGenRenderbuffers(1, intBuf1);
1547+// RendererUtil.checkGLError();
1548+
1549+ id = intBuf1.get(0);
1550+ rb.setId(id);
1551+ }
1552+
1553+ if (context.boundRB != id) {
1554+ Gdx.gl20.glBindRenderbuffer(GL20.GL_RENDERBUFFER, id);
1555+// RendererUtil.checkGLError();
1556+
1557+ context.boundRB = id;
1558+ }
1559+
1560+ if (fb.getWidth() > maxRBSize || fb.getHeight() > maxRBSize) {
1561+ throw new RendererException("Resolution " + fb.getWidth()
1562+ + ":" + fb.getHeight() + " is not supported.");
1563+ }
1564+
1565+ TextureUtilGdx.AndroidGLImageFormat imageFormat = TextureUtilGdx.getImageFormat(rb.getFormat());
1566+ if (imageFormat.renderBufferStorageFormat == 0) {
1567+ throw new RendererException("The format '" + rb.getFormat() + "' cannot be used for renderbuffers.");
1568+ }
1569+
1570+// if (fb.getSamples() > 1 && GLContext.getCapabilities().GL_EXT_framebuffer_multisample) {
1571+ if (fb.getSamples() > 1) {
1572+// // FIXME
1573+ throw new RendererException("Multisample FrameBuffer is not supported yet.");
1574+// int samples = fb.getSamples();
1575+// if (maxFBOSamples < samples) {
1576+// samples = maxFBOSamples;
1577+// }
1578+// glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT,
1579+// samples,
1580+// glFmt.internalFormat,
1581+// fb.getWidth(),
1582+// fb.getHeight());
1583+ } else {
1584+ Gdx.gl20.glRenderbufferStorage(GL20.GL_RENDERBUFFER,
1585+ imageFormat.renderBufferStorageFormat,
1586+ fb.getWidth(),
1587+ fb.getHeight());
1588+
1589+// RendererUtil.checkGLError();
1590+ }
1591+ }
1592+ private int convertAttachmentSlot(int attachmentSlot) {
1593+ // can also add support for stencil here
1594+ if (attachmentSlot == -100) {
1595+ return GL20.GL_DEPTH_ATTACHMENT;
1596+ } else if (attachmentSlot == 0) {
1597+ return GL20.GL_COLOR_ATTACHMENT0;
1598+ } else {
1599+ throw new UnsupportedOperationException("Android does not support multiple color attachments to an FBO");
1600+ }
1601+ }
1602+
1603+ public void updateRenderTexture(FrameBuffer fb, RenderBuffer rb) {
1604+ Texture tex = rb.getTexture();
1605+ Image image = tex.getImage();
1606+ if (image.isUpdateNeeded()) {
1607+ updateTexImageData(image, tex.getType(), false);
1608+
1609+ // NOTE: For depth textures, sets nearest/no-mips mode
1610+ // Required to fix "framebuffer unsupported"
1611+ // for old NVIDIA drivers!
1612+ setupTextureParams(tex);
1613+ }
1614+
1615+ Gdx.gl20.glFramebufferTexture2D(GL20.GL_FRAMEBUFFER,
1616+ convertAttachmentSlot(rb.getSlot()),
1617+ convertTextureType(tex.getType()),
1618+ image.getId(),
1619+ 0);
1620+
1621+// RendererUtil.checkGLError();
1622+ }
1623+
1624+ public void updateFrameBufferAttachment(FrameBuffer fb, RenderBuffer rb) {
1625+ boolean needAttach;
1626+ if (rb.getTexture() == null) {
1627+ // if it hasn't been created yet, then attach is required.
1628+ needAttach = rb.getId() == -1;
1629+ updateRenderBuffer(fb, rb);
1630+ } else {
1631+ needAttach = false;
1632+ updateRenderTexture(fb, rb);
1633+ }
1634+ if (needAttach) {
1635+ Gdx.gl20.glFramebufferRenderbuffer(GL20.GL_FRAMEBUFFER,
1636+ convertAttachmentSlot(rb.getSlot()),
1637+ GL20.GL_RENDERBUFFER,
1638+ rb.getId());
1639+
1640+// RendererUtil.checkGLError();
1641+ }
1642+ }
1643+
1644+ public void updateFrameBuffer(FrameBuffer fb) {
1645+ int id = fb.getId();
1646+ if (id == -1) {
1647+ intBuf1.clear();
1648+ // create FBO
1649+ Gdx.gl20.glGenFramebuffers(1, intBuf1);
1650+// RendererUtil.checkGLError();
1651+
1652+ id = intBuf1.get(0);
1653+ fb.setId(id);
1654+ objManager.registerForCleanup(fb);
1655+
1656+ statistics.onNewFrameBuffer();
1657+ }
1658+
1659+ if (context.boundFBO != id) {
1660+ Gdx.gl20.glBindFramebuffer(GL20.GL_FRAMEBUFFER, id);
1661+// RendererUtil.checkGLError();
1662+
1663+ // binding an FBO automatically sets draw buf to GL_COLOR_ATTACHMENT0
1664+ context.boundDrawBuf = 0;
1665+ context.boundFBO = id;
1666+ }
1667+
1668+ RenderBuffer depthBuf = fb.getDepthBuffer();
1669+ if (depthBuf != null) {
1670+ updateFrameBufferAttachment(fb, depthBuf);
1671+ }
1672+
1673+ for (int i = 0; i < fb.getNumColorBuffers(); i++) {
1674+ RenderBuffer colorBuf = fb.getColorBuffer(i);
1675+ updateFrameBufferAttachment(fb, colorBuf);
1676+ }
1677+
1678+ fb.clearUpdateNeeded();
1679+ }
1680+
1681+ public void setMainFrameBufferOverride(FrameBuffer fb){
1682+ mainFbOverride = fb;
1683+ }
1684+
1685+ public void setFrameBuffer(FrameBuffer fb) {
1686+ if (fb == null && mainFbOverride != null) {
1687+ fb = mainFbOverride;
1688+ }
1689+
1690+ if (lastFb == fb) {
1691+ if (fb == null || !fb.isUpdateNeeded()) {
1692+ return;
1693+ }
1694+ }
1695+
1696+ // generate mipmaps for last FB if needed
1697+ if (lastFb != null) {
1698+ for (int i = 0; i < lastFb.getNumColorBuffers(); i++) {
1699+ RenderBuffer rb = lastFb.getColorBuffer(i);
1700+ Texture tex = rb.getTexture();
1701+ if (tex != null
1702+ && tex.getMinFilter().usesMipMapLevels()) {
1703+ setTexture(0, rb.getTexture());
1704+
1705+// int textureType = convertTextureType(tex.getType(), tex.getImage().getMultiSamples(), rb.getFace());
1706+ int textureType = convertTextureType(tex.getType());
1707+ Gdx.gl20.glGenerateMipmap(textureType);
1708+// RendererUtil.checkGLError();
1709+ }
1710+ }
1711+ }
1712+
1713+ if (fb == null) {
1714+ // unbind any fbos
1715+ if (context.boundFBO != 0) {
1716+ Gdx.gl20.glBindFramebuffer(GL20.GL_FRAMEBUFFER, 0);
1717+// RendererUtil.checkGLError();
1718+
1719+ statistics.onFrameBufferUse(null, true);
1720+
1721+ context.boundFBO = 0;
1722+ }
1723+
1724+ /*
1725+ // select back buffer
1726+ if (context.boundDrawBuf != -1) {
1727+ glDrawBuffer(initialDrawBuf);
1728+ context.boundDrawBuf = -1;
1729+ }
1730+ if (context.boundReadBuf != -1) {
1731+ glReadBuffer(initialReadBuf);
1732+ context.boundReadBuf = -1;
1733+ }
1734+ */
1735+
1736+ lastFb = null;
1737+ } else {
1738+ if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null) {
1739+ throw new IllegalArgumentException("The framebuffer: " + fb
1740+ + "\nDoesn't have any color/depth buffers");
1741+ }
1742+
1743+ if (fb.isUpdateNeeded()) {
1744+ updateFrameBuffer(fb);
1745+ }
1746+
1747+ if (context.boundFBO != fb.getId()) {
1748+ Gdx.gl20.glBindFramebuffer(GL20.GL_FRAMEBUFFER, fb.getId());
1749+// RendererUtil.checkGLError();
1750+
1751+ statistics.onFrameBufferUse(fb, true);
1752+
1753+ // update viewport to reflect framebuffer's resolution
1754+ setViewPort(0, 0, fb.getWidth(), fb.getHeight());
1755+
1756+ context.boundFBO = fb.getId();
1757+ } else {
1758+ statistics.onFrameBufferUse(fb, false);
1759+ }
1760+ if (fb.getNumColorBuffers() == 0) {
1761+// // make sure to select NONE as draw buf
1762+// // no color buffer attached. select NONE
1763+ if (context.boundDrawBuf != -2) {
1764+// glDrawBuffer(GL_NONE);
1765+ context.boundDrawBuf = -2;
1766+ }
1767+ if (context.boundReadBuf != -2) {
1768+// glReadBuffer(GL_NONE);
1769+ context.boundReadBuf = -2;
1770+ }
1771+ } else {
1772+ if (fb.getNumColorBuffers() > maxFBOAttachs) {
1773+ throw new RendererException("Framebuffer has more color "
1774+ + "attachments than are supported"
1775+ + " by the video hardware!");
1776+ }
1777+ if (fb.isMultiTarget()) {
1778+ if (fb.getNumColorBuffers() > maxMRTFBOAttachs) {
1779+ throw new RendererException("Framebuffer has more"
1780+ + " multi targets than are supported"
1781+ + " by the video hardware!");
1782+ }
1783+
1784+ if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()) {
1785+ intBuf16.clear();
1786+ for (int i = 0; i < fb.getNumColorBuffers(); i++) {
1787+ intBuf16.put(Gdx.gl20.GL_COLOR_ATTACHMENT0 + i);
1788+ }
1789+
1790+ intBuf16.flip();
1791+// glDrawBuffers(intBuf16);
1792+ context.boundDrawBuf = 100 + fb.getNumColorBuffers();
1793+ }
1794+ } else {
1795+ RenderBuffer rb = fb.getColorBuffer(fb.getTargetIndex());
1796+ // select this draw buffer
1797+ if (context.boundDrawBuf != rb.getSlot()) {
1798+ Gdx.gl20.glActiveTexture(convertAttachmentSlot(rb.getSlot()));
1799+// RendererUtil.checkGLError();
1800+
1801+ context.boundDrawBuf = rb.getSlot();
1802+ }
1803+ }
1804+ }
1805+
1806+ assert fb.getId() >= 0;
1807+ assert context.boundFBO == fb.getId();
1808+
1809+ lastFb = fb;
1810+
1811+ checkFrameBufferStatus(fb);
1812+ }
1813+ }
1814+
1815+ /**
1816+ * Reads the Color Buffer from OpenGL and stores into the ByteBuffer.
1817+ * Make sure to call setViewPort with the appropriate viewport size before
1818+ * calling readFrameBuffer.
1819+ * @param fb FrameBuffer
1820+ * @param byteBuf ByteBuffer to store the Color Buffer from OpenGL
1821+ */
1822+ public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf) {
1823+ if (fb != null) {
1824+ RenderBuffer rb = fb.getColorBuffer();
1825+ if (rb == null) {
1826+ throw new IllegalArgumentException("Specified framebuffer"
1827+ + " does not have a colorbuffer");
1828+ }
1829+
1830+ setFrameBuffer(fb);
1831+ } else {
1832+ setFrameBuffer(null);
1833+ }
1834+
1835+ Gdx.gl20.glReadPixels(vpX, vpY, vpW, vpH, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE, byteBuf);
1836+// RendererUtil.checkGLError();
1837+ }
1838+
1839+ private void deleteRenderBuffer(FrameBuffer fb, RenderBuffer rb) {
1840+ intBuf1.put(0, rb.getId());
1841+ Gdx.gl20.glDeleteRenderbuffers(1, intBuf1);
1842+// RendererUtil.checkGLError();
1843+ }
1844+
1845+ public void deleteFrameBuffer(FrameBuffer fb) {
1846+ if (fb.getId() != -1) {
1847+ if (context.boundFBO == fb.getId()) {
1848+ Gdx.gl20.glBindFramebuffer(GL20.GL_FRAMEBUFFER, 0);
1849+// RendererUtil.checkGLError();
1850+
1851+ context.boundFBO = 0;
1852+ }
1853+
1854+ if (fb.getDepthBuffer() != null) {
1855+ deleteRenderBuffer(fb, fb.getDepthBuffer());
1856+ }
1857+ if (fb.getColorBuffer() != null) {
1858+ deleteRenderBuffer(fb, fb.getColorBuffer());
1859+ }
1860+
1861+ intBuf1.put(0, fb.getId());
1862+ Gdx.gl20.glDeleteFramebuffers(1, intBuf1);
1863+// RendererUtil.checkGLError();
1864+
1865+ fb.resetObject();
1866+
1867+ statistics.onDeleteFrameBuffer();
1868+ }
1869+ }
1870+
1871+ /*********************************************************************\
1872+ |* Textures *|
1873+ \*********************************************************************/
1874+ private int convertTextureType(Texture.Type type) {
1875+ switch (type) {
1876+ case TwoDimensional:
1877+ return GL20.GL_TEXTURE_2D;
1878+ // case TwoDimensionalArray:
1879+ // return EXTTextureArray.GL_TEXTURE_2D_ARRAY_EXT;
1880+// case ThreeDimensional:
1881+ // return GLES20.GL_TEXTURE_3D;
1882+ case CubeMap:
1883+ return GL20.GL_TEXTURE_CUBE_MAP;
1884+ default:
1885+ throw new UnsupportedOperationException("Unknown texture type: " + type);
1886+ }
1887+ }
1888+
1889+ private int convertMagFilter(Texture.MagFilter filter) {
1890+ switch (filter) {
1891+ case Bilinear:
1892+ return GL20.GL_LINEAR;
1893+ case Nearest:
1894+ return GL20.GL_NEAREST;
1895+ default:
1896+ throw new UnsupportedOperationException("Unknown mag filter: " + filter);
1897+ }
1898+ }
1899+
1900+ private int convertMinFilter(Texture.MinFilter filter) {
1901+ switch (filter) {
1902+ case Trilinear:
1903+ return GL20.GL_LINEAR_MIPMAP_LINEAR;
1904+ case BilinearNearestMipMap:
1905+ return GL20.GL_LINEAR_MIPMAP_NEAREST;
1906+ case NearestLinearMipMap:
1907+ return GL20.GL_NEAREST_MIPMAP_LINEAR;
1908+ case NearestNearestMipMap:
1909+ return GL20.GL_NEAREST_MIPMAP_NEAREST;
1910+ case BilinearNoMipMaps:
1911+ return GL20.GL_LINEAR;
1912+ case NearestNoMipMaps:
1913+ return GL20.GL_NEAREST;
1914+ default:
1915+ throw new UnsupportedOperationException("Unknown min filter: " + filter);
1916+ }
1917+ }
1918+
1919+ private int convertWrapMode(Texture.WrapMode mode) {
1920+ switch (mode) {
1921+// case BorderClamp:
1922+// return GLES20.GL_CLAMP_TO_BORDER;
1923+// case Clamp:
1924+// return GLES20.GL_CLAMP;
1925+ case EdgeClamp:
1926+ return GL20.GL_CLAMP_TO_EDGE;
1927+ case Repeat:
1928+ return GL20.GL_REPEAT;
1929+ case MirroredRepeat:
1930+ return GL20.GL_MIRRORED_REPEAT;
1931+ default:
1932+ throw new UnsupportedOperationException("Unknown wrap mode: " + mode);
1933+ }
1934+ }
1935+
1936+ /**
1937+ * <code>setupTextureParams</code> sets the OpenGL context texture parameters
1938+ * @param tex the Texture to set the texture parameters from
1939+ */
1940+ private void setupTextureParams(Texture tex) {
1941+ int target = convertTextureType(tex.getType());
1942+
1943+ // filter things
1944+ int minFilter = convertMinFilter(tex.getMinFilter());
1945+ int magFilter = convertMagFilter(tex.getMagFilter());
1946+
1947+ if (verboseLogging) {
1948+ logger.info("GLES20.glTexParameteri(" + target + ", GLES20.GL_TEXTURE_MIN_FILTER, " + minFilter + ")");
1949+ }
1950+
1951+ Gdx.gl20.glTexParameteri(target, GL20.GL_TEXTURE_MIN_FILTER, minFilter);
1952+
1953+ if (verboseLogging) {
1954+ logger.info("GLES20.glTexParameteri(" + target + ", GLES20.GL_TEXTURE_MAG_FILTER, " + magFilter + ")");
1955+ }
1956+
1957+ Gdx.gl20.glTexParameteri(target, GL20.GL_TEXTURE_MAG_FILTER, magFilter);
1958+
1959+ /*
1960+ if (tex.getAnisotropicFilter() > 1){
1961+
1962+ if (GLContext.getCapabilities().GL_EXT_texture_filter_anisotropic){
1963+ glTexParameterf(target,
1964+ EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT,
1965+ tex.getAnisotropicFilter());
1966+ }
1967+
1968+ }
1969+ */
1970+ // repeat modes
1971+
1972+ switch (tex.getType()) {
1973+ case ThreeDimensional:
1974+ case CubeMap: // cubemaps use 3D coords
1975+ // GL_TEXTURE_WRAP_R is not available in api 8
1976+ //GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_WRAP_R, convertWrapMode(tex.getWrap(WrapAxis.R)));
1977+ case TwoDimensional:
1978+ case TwoDimensionalArray:
1979+
1980+ if (verboseLogging) {
1981+ logger.info("GLES20.glTexParameteri(" + target + ", GLES20.GL_TEXTURE_WRAP_T, " + convertWrapMode(tex.getWrap(WrapAxis.T)));
1982+ }
1983+
1984+ Gdx.gl20.glTexParameteri(target, GL20.GL_TEXTURE_WRAP_T, convertWrapMode(tex.getWrap(WrapAxis.T)));
1985+
1986+ // fall down here is intentional..
1987+// case OneDimensional:
1988+
1989+ if (verboseLogging) {
1990+ logger.info("GLES20.glTexParameteri(" + target + ", GLES20.GL_TEXTURE_WRAP_S, " + convertWrapMode(tex.getWrap(WrapAxis.S)));
1991+ }
1992+
1993+ Gdx.gl20.glTexParameteri(target, GL20.GL_TEXTURE_WRAP_S, convertWrapMode(tex.getWrap(WrapAxis.S)));
1994+ break;
1995+ default:
1996+ throw new UnsupportedOperationException("Unknown texture type: " + tex.getType());
1997+ }
1998+
1999+ // R to Texture compare mode
2000+/*
2001+ if (tex.getShadowCompareMode() != Texture.ShadowCompareMode.Off){
2002+ GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_COMPARE_MODE, GLES20.GL_COMPARE_R_TO_TEXTURE);
2003+ GLES20.glTexParameteri(target, GLES20.GL_DEPTH_TEXTURE_MODE, GLES20.GL_INTENSITY);
2004+ if (tex.getShadowCompareMode() == Texture.ShadowCompareMode.GreaterOrEqual){
2005+ GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_COMPARE_FUNC, GLES20.GL_GEQUAL);
2006+ }else{
2007+ GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_COMPARE_FUNC, GLES20.GL_LEQUAL);
2008+ }
2009+ }
2010+ */
2011+ }
2012+
2013+ /**
2014+ * <code>updateTexImageData</code> activates and binds the texture
2015+ * @param img
2016+ * @param type
2017+ * @param mips
2018+ */
2019+ public void updateTexImageData(Image img, Texture.Type type, boolean mips) {
2020+ int texId = img.getId();
2021+ if (texId == -1) {
2022+ // create texture
2023+ if (verboseLogging) {
2024+ logger.info("GLES20.glGenTexture(1, buffer)");
2025+ }
2026+
2027+ Gdx.gl20.glGenTextures(1, intBuf1);
2028+ texId = intBuf1.get(0);
2029+ img.setId(texId);
2030+ objManager.registerForCleanup(img);
2031+
2032+ statistics.onNewTexture();
2033+ }
2034+
2035+ // bind texture
2036+ int target = convertTextureType(type);
2037+ if (context.boundTextureUnit != 0) {
2038+ if (verboseLogging) {
2039+ logger.info("GLES20.glActiveTexture(GLES20.GL_TEXTURE0)");
2040+ }
2041+
2042+ Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE0);
2043+ context.boundTextureUnit = 0;
2044+ }
2045+ if (context.boundTextures[0] != img) {
2046+
2047+ if (verboseLogging) {
2048+ logger.info("GLES20.glBindTexture(" + target + ", " + texId + ")");
2049+ }
2050+
2051+ Gdx.gl20.glBindTexture(target, texId);
2052+ context.boundTextures[0] = img;
2053+ }
2054+
2055+
2056+ if (target == GL20.GL_TEXTURE_CUBE_MAP) {
2057+ // Upload a cube map / sky box
2058+ // TODO
2059+// @SuppressWarnings("unchecked")
2060+// List<Bitmap> bmps = (List<Bitmap>) img.getEfficentData();
2061+// if (bmps != null) {
2062+// // Native android bitmap
2063+// if (bmps.size() != 6) {
2064+// throw new UnsupportedOperationException("Invalid texture: " + img
2065+// + "Cubemap textures must contain 6 data units.");
2066+// }
2067+// for (int i = 0; i < 6; i++) {
2068+// TextureUtilGdx.uploadTextureBitmap(GL20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, bmps.get(i), false, powerOf2);
2069+// }
2070+// } else {
2071+// // Standard jme3 image data
2072+// List<ByteBuffer> data = img.getData();
2073+// if (data.size() != 6) {
2074+// logger.log(Level.WARNING, "Invalid texture: {0}\n"
2075+// + "Cubemap textures must contain 6 data units.", img);
2076+// return;
2077+// }
2078+// for (int i = 0; i < 6; i++) {
2079+// TextureUtilGdx.uploadTexture(img, GL20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, 0, tdc, false, powerOf2);
2080+// }
2081+// }
2082+ } else {
2083+ // TODO
2084+ TextureUtilGdx.uploadTexture(img, target, 0, 0, tdc, false, powerOf2);
2085+
2086+ if (verboseLogging) {
2087+ logger.info("GLES20.glTexParameteri(" + target + "GLES11.GL_GENERATE_MIMAP, GLES20.GL_TRUE)");
2088+ }
2089+
2090+ if (!img.hasMipmaps() && mips) {
2091+ // No pregenerated mips available,
2092+ // generate from base level if required
2093+ if (verboseLogging) {
2094+ logger.info("GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D)");
2095+ }
2096+ Gdx.gl20.glGenerateMipmap(GL20.GL_TEXTURE_2D);
2097+ }
2098+ }
2099+
2100+ img.clearUpdateNeeded();
2101+ }
2102+ public void setTexture(int unit, Texture tex) {
2103+ Image image = tex.getImage();
2104+ // TODO
2105+ if (image.getData().size() == 0 || image.getFormat() == null) {
2106+ return;
2107+ }
2108+ if (image.isUpdateNeeded()) {
2109+// logger.warning("setTexture: isUpdateNeeded");
2110+// if (image.getEfficentData() instanceof Bitmap) {
2111+// Bitmap bmp = (Bitmap) image.getEfficentData();
2112+// if (bmp != null) {
2113+// // Check if the bitmap got recycled, can happen after wakeup/restart
2114+// if (bmp.isRecycled()) {
2115+// // We need to reload the bitmap
2116+// DesktopAssetManager assetManager;
2117+// try {
2118+// assetManager = (DesktopAssetManager) ((AndroidHarness) JmeSystem.getActivity()).getJmeApplication().getAssetManager();
2119+// } catch (ClassCastException ex) {
2120+// Application app = JmeSystem.getApplication();
2121+// assetManager = (DesktopAssetManager) app.getAssetManager();
2122+// }
2123+// assetManager.deleteFromCache((TextureKey) tex.getKey());
2124+// Texture textureReloaded = assetManager.loadTexture((TextureKey) tex.getKey());
2125+// image.setEfficentData(textureReloaded.getImage().getEfficentData());
2126+// }
2127+// }
2128+// }
2129+ updateTexImageData(image, tex.getType(), tex.getMinFilter().usesMipMapLevels());
2130+ setupTextureParams(tex);
2131+ }
2132+
2133+ int texId = image.getId();
2134+ assert texId != -1;
2135+
2136+ if (texId == -1) {
2137+ logger.warning("error: texture image has -1 id");
2138+ }
2139+
2140+ Image[] textures = context.boundTextures;
2141+
2142+ int type = convertTextureType(tex.getType());
2143+// if (!context.textureIndexList.moveToNew(unit)) {
2144+// if (context.boundTextureUnit != unit){
2145+// glActiveTexture(GL_TEXTURE0 + unit);
2146+// context.boundTextureUnit = unit;
2147+// }
2148+// glEnable(type);
2149+// }
2150+
2151+ if (context.boundTextureUnit != unit) {
2152+ if (verboseLogging) {
2153+ logger.info("GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + " + unit + ")");
2154+ }
2155+ }
2156+ if (textures[unit] != image) {
2157+
2158+ if (verboseLogging) {
2159+ logger.info("GLES20.glBindTexture(" + type + ", " + texId + ")");
2160+ }
2161+
2162+ Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE0 + unit);
2163+ context.boundTextureUnit = unit;
2164+ Gdx.gl20.glBindTexture(type, texId);
2165+ textures[unit] = image;
2166+
2167+ statistics.onTextureUse(tex.getImage(), true);
2168+ } else {
2169+ statistics.onTextureUse(tex.getImage(), false);
2170+ }
2171+
2172+// setupTextureParams(tex);
2173+ }
2174+
2175+ public void clearTextureUnits() {
2176+// IDList textureList = context.textureIndexList;
2177+// Image[] textures = context.boundTextures;
2178+// for (int i = 0; i < textureList.oldLen; i++) {
2179+// int idx = textureList.oldList[i];
2180+// if (context.boundTextureUnit != idx){
2181+// GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + idx);
2182+// context.boundTextureUnit = idx;
2183+// }
2184+// GLES20.glDisable(GLES20.GL_TEXTURE_2D/*convertTextureType(textures[idx].getType())*/);
2185+// textures[idx] = null;
2186+// }
2187+// context.textureIndexList.copyNewToOld();
2188+ }
2189+
2190+ public void deleteImage(Image image) {
2191+ int texId = image.getId();
2192+ if (texId != -1) {
2193+ intBuf1.put(0, texId);
2194+ intBuf1.position(0).limit(1);
2195+
2196+ if (verboseLogging) {
2197+ logger.info("GLES20.glDeleteTexture(1, buffer)");
2198+ }
2199+
2200+ Gdx.gl20.glDeleteTextures(1, intBuf1);
2201+ image.resetObject();
2202+
2203+ statistics.onDeleteTexture();
2204+ }
2205+ }
2206+
2207+ /*********************************************************************\
2208+ |* Vertex Buffers and Attributes *|
2209+ \*********************************************************************/
2210+ private int convertUsage(Usage usage) {
2211+ switch (usage) {
2212+ case Static:
2213+ return GL20.GL_STATIC_DRAW;
2214+ case Dynamic:
2215+ return GL20.GL_DYNAMIC_DRAW;
2216+ case Stream:
2217+ return GL20.GL_STREAM_DRAW;
2218+ default:
2219+ throw new RuntimeException("Unknown usage type.");
2220+ }
2221+ }
2222+
2223+ private int convertFormat(Format format) {
2224+ switch (format) {
2225+ case Byte:
2226+ return GL20.GL_BYTE;
2227+ case UnsignedByte:
2228+ return GL20.GL_UNSIGNED_BYTE;
2229+ case Short:
2230+ return GL20.GL_SHORT;
2231+ case UnsignedShort:
2232+ return GL20.GL_UNSIGNED_SHORT;
2233+ case Int:
2234+ return GL20.GL_INT;
2235+ case UnsignedInt:
2236+ return GL20.GL_UNSIGNED_INT;
2237+ /*
2238+ case Half:
2239+ return NVHalfFloat.GL_HALF_FLOAT_NV;
2240+ // return ARBHalfFloatVertex.GL_HALF_FLOAT;
2241+ */
2242+ case Float:
2243+ return GL20.GL_FLOAT;
2244+// case Double:
2245+// return GLES20.GL_DOUBLE;
2246+ default:
2247+ throw new RuntimeException("Unknown buffer format.");
2248+
2249+ }
2250+ }
2251+
2252+ public void updateBufferData(VertexBuffer vb) {
2253+
2254+ if (verboseLogging) {
2255+ logger.info("updateBufferData(" + vb + ")");
2256+ }
2257+
2258+ int bufId = vb.getId();
2259+ boolean created = false;
2260+ if (bufId == -1) {
2261+ // create buffer
2262+
2263+ if (verboseLogging) {
2264+ logger.info("GLES20.glGenBuffers(" + 1 + ", buffer)");
2265+ }
2266+
2267+ Gdx.gl20.glGenBuffers(1, intBuf1);
2268+ bufId = intBuf1.get(0);
2269+ vb.setId(bufId);
2270+ objManager.registerForCleanup(vb);
2271+
2272+ created = true;
2273+ }
2274+
2275+ // bind buffer
2276+ int target;
2277+ if (vb.getBufferType() == Type.Index) {
2278+ target = GL20.GL_ELEMENT_ARRAY_BUFFER;
2279+
2280+ if (verboseLogging) {
2281+ logger.info("vb.getBufferType() == VertexBuffer.Type.Index");
2282+ }
2283+
2284+ if (context.boundElementArrayVBO != bufId) {
2285+
2286+ if (verboseLogging) {
2287+ logger.info("GLES20.glBindBuffer(" + target + ", " + bufId + ")");
2288+ }
2289+
2290+ Gdx.gl20.glBindBuffer(target, bufId);
2291+ context.boundElementArrayVBO = bufId;
2292+ }
2293+ } else {
2294+ if (verboseLogging) {
2295+ logger.info("vb.getBufferType() != VertexBuffer.Type.Index");
2296+ }
2297+
2298+ target = GL20.GL_ARRAY_BUFFER;
2299+
2300+ if (context.boundArrayVBO != bufId) {
2301+
2302+ if (verboseLogging) {
2303+ logger.info("GLES20.glBindBuffer(" + target + ", " + bufId + ")");
2304+ }
2305+
2306+ Gdx.gl20.glBindBuffer(target, bufId);
2307+ context.boundArrayVBO = bufId;
2308+ }
2309+ }
2310+
2311+ int usage = convertUsage(vb.getUsage());
2312+ vb.getData().clear();
2313+
2314+ if (created || vb.hasDataSizeChanged()) {
2315+ // upload data based on format
2316+ int size = vb.getData().capacity() * vb.getFormat().getComponentSize();
2317+
2318+ switch (vb.getFormat()) {
2319+ case Byte:
2320+ case UnsignedByte:
2321+
2322+ if (verboseLogging) {
2323+ logger.info("GLES20.glBufferData(" + target + ", " + size + ", (data), " + usage + ")");
2324+ }
2325+
2326+ Gdx.gl20.glBufferData(target, size, (ByteBuffer) vb.getData(), usage);
2327+ break;
2328+ // case Half:
2329+ case Short:
2330+ case UnsignedShort:
2331+
2332+ if (verboseLogging) {
2333+ logger.info("GLES20.glBufferData(" + target + ", " + size + ", (data), " + usage + ")");
2334+ }
2335+
2336+ Gdx.gl20.glBufferData(target, size, (ShortBuffer) vb.getData(), usage);
2337+ break;
2338+ case Int:
2339+ case UnsignedInt:
2340+
2341+ if (verboseLogging) {
2342+ logger.info("GLES20.glBufferData(" + target + ", " + size + ", (data), " + usage + ")");
2343+ }
2344+
2345+ Gdx.gl20.glBufferData(target, size, (IntBuffer) vb.getData(), usage);
2346+ break;
2347+ case Float:
2348+ if (verboseLogging) {
2349+ logger.info("GLES20.glBufferData(" + target + ", " + size + ", (data), " + usage + ")");
2350+ }
2351+
2352+ Gdx.gl20.glBufferData(target, size, (FloatBuffer) vb.getData(), usage);
2353+ break;
2354+ case Double:
2355+ if (verboseLogging) {
2356+ logger.info("GLES20.glBufferData(" + target + ", " + size + ", (data), " + usage + ")");
2357+ }
2358+
2359+ Gdx.gl20.glBufferData(target, size, (DoubleBuffer) vb.getData(), usage);
2360+ break;
2361+ default:
2362+ throw new RuntimeException("Unknown buffer format.");
2363+ }
2364+ } else {
2365+ int size = vb.getData().capacity() * vb.getFormat().getComponentSize();
2366+
2367+ switch (vb.getFormat()) {
2368+ case Byte:
2369+ case UnsignedByte:
2370+ if (verboseLogging) {
2371+ logger.info("GLES20.glBufferSubData(" + target + ", 0, " + size + ", (data))");
2372+ }
2373+
2374+ Gdx.gl20.glBufferSubData(target, 0, size, (ByteBuffer) vb.getData());
2375+ break;
2376+ case Short:
2377+ case UnsignedShort:
2378+ if (verboseLogging) {
2379+ logger.info("GLES20.glBufferSubData(" + target + ", 0, " + size + ", (data))");
2380+ }
2381+
2382+ Gdx.gl20.glBufferSubData(target, 0, size, (ShortBuffer) vb.getData());
2383+ break;
2384+ case Int:
2385+ case UnsignedInt:
2386+ if (verboseLogging) {
2387+ logger.info("GLES20.glBufferSubData(" + target + ", 0, " + size + ", (data))");
2388+ }
2389+
2390+ Gdx.gl20.glBufferSubData(target, 0, size, (IntBuffer) vb.getData());
2391+ break;
2392+ case Float:
2393+ if (verboseLogging) {
2394+ logger.info("GLES20.glBufferSubData(" + target + ", 0, " + size + ", (data))");
2395+ }
2396+
2397+ Gdx.gl20.glBufferSubData(target, 0, size, (FloatBuffer) vb.getData());
2398+ break;
2399+ case Double:
2400+ if (verboseLogging) {
2401+ logger.info("GLES20.glBufferSubData(" + target + ", 0, " + size + ", (data))");
2402+ }
2403+
2404+ Gdx.gl20.glBufferSubData(target, 0, size, (DoubleBuffer) vb.getData());
2405+ break;
2406+ default:
2407+ throw new RuntimeException("Unknown buffer format.");
2408+ }
2409+ }
2410+// }else{
2411+// if (created || vb.hasDataSizeChanged()){
2412+// glBufferData(target, vb.getData().capacity() * vb.getFormat().getComponentSize(), usage);
2413+// }
2414+//
2415+// ByteBuffer buf = glMapBuffer(target,
2416+// GL_WRITE_ONLY,
2417+// vb.getMappedData());
2418+//
2419+// if (buf != vb.getMappedData()){
2420+// buf = buf.order(ByteOrder.nativeOrder());
2421+// vb.setMappedData(buf);
2422+// }
2423+//
2424+// buf.clear();
2425+//
2426+// switch (vb.getFormat()){
2427+// case Byte:
2428+// case UnsignedByte:
2429+// buf.put( (ByteBuffer) vb.getData() );
2430+// break;
2431+// case Short:
2432+// case UnsignedShort:
2433+// buf.asShortBuffer().put( (ShortBuffer) vb.getData() );
2434+// break;
2435+// case Int:
2436+// case UnsignedInt:
2437+// buf.asIntBuffer().put( (IntBuffer) vb.getData() );
2438+// break;
2439+// case Float:
2440+// buf.asFloatBuffer().put( (FloatBuffer) vb.getData() );
2441+// break;
2442+// case Double:
2443+// break;
2444+// default:
2445+// throw new RuntimeException("Unknown buffer format.");
2446+// }
2447+//
2448+// glUnmapBuffer(target);
2449+// }
2450+
2451+ vb.clearUpdateNeeded();
2452+ }
2453+
2454+ public void deleteBuffer(VertexBuffer vb) {
2455+ int bufId = vb.getId();
2456+ if (bufId != -1) {
2457+ // delete buffer
2458+ intBuf1.put(0, bufId);
2459+ intBuf1.position(0).limit(1);
2460+ if (verboseLogging) {
2461+ logger.info("GLES20.glDeleteBuffers(1, buffer)");
2462+ }
2463+
2464+ Gdx.gl20.glDeleteBuffers(1, intBuf1);
2465+ vb.resetObject();
2466+ }
2467+ }
2468+
2469+ public void clearVertexAttribs() {
2470+ IDList attribList = context.attribIndexList;
2471+ int oldLen = attribList.oldLen;
2472+ for (int i = 0; i < oldLen; i++) {
2473+ int idx = attribList.oldList[i];
2474+
2475+ if (verboseLogging) {
2476+ logger.info("GLES20.glDisableVertexAttribArray(" + idx + ")");
2477+ }
2478+ if (idx != -1) {
2479+ Gdx.gl20.glDisableVertexAttribArray(idx);
2480+ context.boundAttribs[idx] = null;
2481+ }
2482+ }
2483+ context.attribIndexList.copyNewToOld();
2484+ }
2485+
2486+ public void setVertexAttrib(VertexBuffer vb, VertexBuffer idb) {
2487+ if (verboseLogging) {
2488+ logger.info("setVertexAttrib(" + vb + ", " + idb + ")");
2489+ }
2490+
2491+ if (vb.getBufferType() == Type.Index) {
2492+ throw new IllegalArgumentException("Index buffers not allowed to be set to vertex attrib");
2493+ }
2494+
2495+ if (vb.isUpdateNeeded() && idb == null) {
2496+ updateBufferData(vb);
2497+ }
2498+
2499+ int programId = context.boundShaderProgram;
2500+ if (programId > 0) {
2501+ Attribute attrib = boundShader.getAttribute(vb.getBufferType());
2502+ int loc = attrib.getLocation();
2503+ if (loc == -1) {
2504+
2505+ if (verboseLogging) {
2506+ logger.warning("location is invalid for attrib: [" + vb.getBufferType().name() + "]");
2507+ }
2508+
2509+ return; // not defined
2510+ }
2511+
2512+ if (loc == -2) {
2513+// stringBuf.setLength(0);
2514+// stringBuf.append("in").append(vb.getBufferType().name()).append('\0');
2515+// updateNameBuffer();
2516+
2517+ String attributeName = "in" + vb.getBufferType().name();
2518+
2519+ if (verboseLogging) {
2520+ logger.info("GLES20.glGetAttribLocation(" + programId + ", " + attributeName + ")");
2521+ }
2522+
2523+ loc = Gdx.gl20.glGetAttribLocation(programId, attributeName);
2524+
2525+ // not really the name of it in the shader (inPosition\0) but
2526+ // the internal name of the enum (Position).
2527+ if (loc < 0) {
2528+ attrib.setLocation(-1);
2529+
2530+ if (verboseLogging) {
2531+ logger.warning("attribute is invalid in shader: [" + vb.getBufferType().name() + "]");
2532+ }
2533+
2534+ return; // not available in shader.
2535+ } else {
2536+ attrib.setLocation(loc);
2537+ }
2538+ }
2539+
2540+ VertexBuffer[] attribs = context.boundAttribs;
2541+ if (!context.attribIndexList.moveToNew(loc)) {
2542+ if (verboseLogging) {
2543+ logger.info("GLES20.glEnableVertexAttribArray(" + loc + ")");
2544+ }
2545+
2546+ Gdx.gl20.glEnableVertexAttribArray(loc);
2547+ //System.out.println("Enabled ATTRIB IDX: "+loc);
2548+ }
2549+ if (attribs[loc] != vb) {
2550+ // NOTE: Use id from interleaved buffer if specified
2551+ int bufId = idb != null ? idb.getId() : vb.getId();
2552+ assert bufId != -1;
2553+
2554+ if (bufId == -1) {
2555+ logger.warning("invalid buffer id");
2556+ }
2557+
2558+ if (context.boundArrayVBO != bufId) {
2559+ if (verboseLogging) {
2560+ logger.info("GLES20.glBindBuffer(" + GL20.GL_ARRAY_BUFFER + ", " + bufId + ")");
2561+ }
2562+ Gdx.gl20.glBindBuffer(GL20.GL_ARRAY_BUFFER, bufId);
2563+ context.boundArrayVBO = bufId;
2564+ }
2565+
2566+// vb.getData().clear();
2567+
2568+ if (verboseLogging) {
2569+ logger.info("GLES20.glVertexAttribPointer("
2570+ + "location=" + loc + ", "
2571+ + "numComponents=" + vb.getNumComponents() + ", "
2572+ + "format=" + vb.getFormat() + ", "
2573+ + "isNormalized=" + vb.isNormalized() + ", "
2574+ + "stride=" + vb.getStride() + ", "
2575+ + "data.capacity=" + vb.getData().capacity() + ")");
2576+ }
2577+
2578+ Gdx.gl20.glVertexAttribPointer(loc,
2579+ vb.getNumComponents(),
2580+ convertFormat(vb.getFormat()),
2581+ vb.isNormalized(),
2582+ vb.getStride(),
2583+ vb.getOffset());
2584+
2585+ attribs[loc] = vb;
2586+ }
2587+ } else {
2588+ throw new IllegalStateException("Cannot render mesh without shader bound");
2589+ }
2590+ }
2591+
2592+ public void setVertexAttrib(VertexBuffer vb) {
2593+ setVertexAttrib(vb, null);
2594+ }
2595+
2596+ public void drawTriangleArray(Mode mode, int count, int vertCount) {
2597+ /* if (count > 1){
2598+ ARBDrawInstanced.glDrawArraysInstancedARB(convertElementMode(mode), 0,
2599+ vertCount, count);
2600+ }else{*/
2601+ if (verboseLogging) {
2602+ logger.info("GLES20.glDrawArrays(" + vertCount + ")");
2603+ }
2604+
2605+ Gdx.gl20.glDrawArrays(convertElementMode(mode), 0, vertCount);
2606+ /*
2607+ }*/
2608+ }
2609+
2610+ public void drawTriangleList(VertexBuffer indexBuf, Mesh mesh, int count) {
2611+
2612+ if (verboseLogging) {
2613+ logger.info("drawTriangleList(" + count + ")");
2614+ }
2615+
2616+ if (indexBuf.getBufferType() != Type.Index) {
2617+ throw new IllegalArgumentException("Only index buffers are allowed as triangle lists.");
2618+ }
2619+
2620+ if (indexBuf.isUpdateNeeded()) {
2621+ if (verboseLogging) {
2622+ logger.info("updateBufferData for indexBuf.");
2623+ }
2624+ updateBufferData(indexBuf);
2625+ }
2626+
2627+ int bufId = indexBuf.getId();
2628+ assert bufId != -1;
2629+
2630+ if (bufId == -1) {
2631+ logger.info("invalid buffer id!");
2632+ }
2633+
2634+ if (context.boundElementArrayVBO != bufId) {
2635+ if (verboseLogging) {
2636+ logger.log(Level.INFO, "GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, {0})", bufId);
2637+ }
2638+
2639+ Gdx.gl20.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, bufId);
2640+ context.boundElementArrayVBO = bufId;
2641+ }
2642+
2643+ int vertCount = mesh.getVertexCount();
2644+ boolean useInstancing = count > 1 && caps.contains(Caps.MeshInstancing);
2645+
2646+ Buffer indexData = indexBuf.getData();
2647+
2648+ if (mesh.getMode() == Mode.Hybrid) {
2649+ int[] modeStart = mesh.getModeStart();
2650+ int[] elementLengths = mesh.getElementLengths();
2651+
2652+ int elMode = convertElementMode(Mode.Triangles);
2653+ int fmt = convertFormat(indexBuf.getFormat());
2654+ int elSize = indexBuf.getFormat().getComponentSize();
2655+ int listStart = modeStart[0];
2656+ int stripStart = modeStart[1];
2657+ int fanStart = modeStart[2];
2658+ int curOffset = 0;
2659+ for (int i = 0; i < elementLengths.length; i++) {
2660+ if (i == stripStart) {
2661+ elMode = convertElementMode(Mode.TriangleStrip);
2662+ } else if (i == fanStart) {
2663+ elMode = convertElementMode(Mode.TriangleStrip);
2664+ }
2665+ int elementLength = elementLengths[i];
2666+
2667+ if (useInstancing) {
2668+ //ARBDrawInstanced.
2669+ throw new IllegalArgumentException("instancing is not supported.");
2670+ /*
2671+ GLES20.glDrawElementsInstancedARB(elMode,
2672+ elementLength,
2673+ fmt,
2674+ curOffset,
2675+ count);
2676+ */
2677+ } else {
2678+ indexBuf.getData().position(curOffset);
2679+ if (verboseLogging) {
2680+ logger.log(Level.INFO, "glDrawElements(): {0}, {1}", new Object[]{elementLength, curOffset});
2681+ }
2682+
2683+ Gdx.gl20.glDrawElements(elMode, elementLength, fmt, indexBuf.getData());
2684+ /*
2685+ glDrawRangeElements(elMode,
2686+ 0,
2687+ vertCount,
2688+ elementLength,
2689+ fmt,
2690+ curOffset);
2691+ */
2692+ }
2693+
2694+ curOffset += elementLength * elSize;
2695+ }
2696+ } else {
2697+ if (useInstancing) {
2698+ throw new IllegalArgumentException("instancing is not supported.");
2699+ //ARBDrawInstanced.
2700+/*
2701+ GLES20.glDrawElementsInstancedARB(convertElementMode(mesh.getMode()),
2702+ indexBuf.getData().capacity(),
2703+ convertFormat(indexBuf.getFormat()),
2704+ 0,
2705+ count);
2706+ */
2707+ } else {
2708+ indexData.clear();
2709+
2710+ if (verboseLogging) {
2711+ logger.log(Level.INFO, "glDrawElements(), indexBuf.capacity ({0}), vertCount ({1})", new Object[]{indexBuf.getData().capacity(), vertCount});
2712+ }
2713+
2714+ Gdx.gl20.glDrawElements(
2715+ convertElementMode(mesh.getMode()),
2716+ indexBuf.getData().capacity(),
2717+ convertFormat(indexBuf.getFormat()),
2718+ 0);
2719+ }
2720+ }
2721+ }
2722+
2723+ /*********************************************************************\
2724+ |* Render Calls *|
2725+ \*********************************************************************/
2726+ public int convertElementMode(Mode mode) {
2727+ switch (mode) {
2728+ case Points:
2729+ return GL20.GL_POINTS;
2730+ case Lines:
2731+ return GL20.GL_LINES;
2732+ case LineLoop:
2733+ return GL20.GL_LINE_LOOP;
2734+ case LineStrip:
2735+ return GL20.GL_LINE_STRIP;
2736+ case Triangles:
2737+ return GL20.GL_TRIANGLES;
2738+ case TriangleFan:
2739+ return GL20.GL_TRIANGLE_FAN;
2740+ case TriangleStrip:
2741+ return GL20.GL_TRIANGLE_STRIP;
2742+ default:
2743+ throw new UnsupportedOperationException("Unrecognized mesh mode: " + mode);
2744+ }
2745+ }
2746+
2747+ public void updateVertexArray(Mesh mesh) {
2748+ logger.log(Level.INFO, "updateVertexArray({0})", mesh);
2749+ int id = mesh.getId();
2750+ /*
2751+ if (id == -1){
2752+ IntBuffer temp = intBuf1;
2753+ // ARBVertexArrayObject.glGenVertexArrays(temp);
2754+ GLES20.glGenVertexArrays(temp);
2755+ id = temp.get(0);
2756+ mesh.setId(id);
2757+ }
2758+
2759+ if (context.boundVertexArray != id){
2760+ // ARBVertexArrayObject.glBindVertexArray(id);
2761+ GLES20.glBindVertexArray(id);
2762+ context.boundVertexArray = id;
2763+ }
2764+ */
2765+ VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData);
2766+ if (interleavedData != null && interleavedData.isUpdateNeeded()) {
2767+ updateBufferData(interleavedData);
2768+ }
2769+
2770+ SafeArrayList<VertexBuffer> buffersList = mesh.getBufferList();
2771+ for (int i = 0; i < buffersList.size(); i++) {
2772+ VertexBuffer vb = buffersList.get(i);
2773+
2774+ if (vb.getBufferType() == Type.InterleavedData
2775+ || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers
2776+ || vb.getBufferType() == Type.Index) {
2777+ continue;
2778+ }
2779+
2780+ if (vb.getStride() == 0) {
2781+ // not interleaved
2782+ setVertexAttrib(vb);
2783+ } else {
2784+ // interleaved
2785+ setVertexAttrib(vb, interleavedData);
2786+ }
2787+ }
2788+ }
2789+
2790+ /**
2791+ * renderMeshVertexArray renders a mesh using vertex arrays
2792+ * @param mesh
2793+ * @param lod
2794+ * @param count
2795+ */
2796+ private void renderMeshVertexArray(Mesh mesh, int lod, int count) {
2797+ if (verboseLogging) {
2798+ logger.info("renderMeshVertexArray");
2799+ }
2800+
2801+ // IntMap<VertexBuffer> buffers = mesh.getBuffers();
2802+ IntMap<VertexBuffer> buffers = mesh.getBuffers();
2803+ IntMap.Entry<VertexBuffer> table[] = buffers.getTable();
2804+ for (IntMap.Entry<VertexBuffer> entry : table) {
2805+ if (entry == null) {
2806+ continue;
2807+ }
2808+ VertexBuffer vb = entry.getValue();
2809+
2810+ if (vb.getBufferType() == Type.InterleavedData
2811+ || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers
2812+ || vb.getBufferType() == Type.Index) {
2813+ continue;
2814+ }
2815+
2816+ if (vb.getStride() == 0) {
2817+ // not interleaved
2818+ setVertexAttrib_Array(vb);
2819+ } else {
2820+ // interleaved
2821+ VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData);
2822+ setVertexAttrib_Array(vb, interleavedData);
2823+ }
2824+ }
2825+
2826+ VertexBuffer indices = null;
2827+ if (mesh.getNumLodLevels() > 0) {
2828+ indices = mesh.getLodLevel(lod);
2829+ } else {
2830+ indices = mesh.getBuffer(Type.Index);//buffers.get(Type.Index.ordinal());
2831+ }
2832+ clearVertexAttribs();
2833+// clearTextureUnits();
2834+ if (indices != null) {
2835+ drawTriangleList_Array(indices, mesh, count);
2836+ } else {
2837+ if (verboseLogging) {
2838+ logger.log(Level.INFO, "GLES20.glDrawArrays({0}, {1}, {2})",
2839+ new Object[]{mesh.getMode(), 0, mesh.getVertexCount()});
2840+ }
2841+
2842+ Gdx.gl20.glDrawArrays(convertElementMode(mesh.getMode()), 0, mesh.getVertexCount());
2843+ }
2844+ }
2845+
2846+ private void renderMeshDefault(Mesh mesh, int lod, int count) {
2847+ if (verboseLogging) {
2848+ logger.log(Level.INFO, "renderMeshDefault({0}, {1}, {2})",
2849+ new Object[]{mesh, lod, count});
2850+ }
2851+ VertexBuffer indices = null;
2852+
2853+ VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData);
2854+ if (interleavedData != null && interleavedData.isUpdateNeeded()) {
2855+ updateBufferData(interleavedData);
2856+ }
2857+
2858+ //IntMap<VertexBuffer> buffers = mesh.getBuffers(); ;
2859+ if (mesh.getNumLodLevels() > 0) {
2860+ indices = mesh.getLodLevel(lod);
2861+ } else {
2862+ indices = mesh.getBuffer(Type.Index);// buffers.get(Type.Index.ordinal());
2863+ }
2864+ SafeArrayList<VertexBuffer> buffersList = mesh.getBufferList();
2865+ for (int i = 0; i < buffersList.size(); i++) {
2866+ VertexBuffer vb = buffersList.get(i);
2867+
2868+ if (vb.getBufferType() == Type.InterleavedData
2869+ || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers
2870+ || vb.getBufferType() == Type.Index) {
2871+ continue;
2872+ }
2873+
2874+ if (vb.getStride() == 0) {
2875+ // not interleaved
2876+ setVertexAttrib(vb);
2877+ } else {
2878+ // interleaved
2879+ setVertexAttrib(vb, interleavedData);
2880+ }
2881+ }
2882+ clearVertexAttribs();
2883+// clearTextureUnits();
2884+ if (indices != null) {
2885+ drawTriangleList(indices, mesh, count);
2886+ } else {
2887+// throw new UnsupportedOperationException("Cannot render without index buffer");
2888+ if (verboseLogging) {
2889+ logger.log(Level.INFO, "GLES20.glDrawArrays({0}, 0, {1})",
2890+ new Object[]{convertElementMode(mesh.getMode()), mesh.getVertexCount()});
2891+ }
2892+
2893+ Gdx.gl20.glDrawArrays(convertElementMode(mesh.getMode()), 0, mesh.getVertexCount());
2894+ }
2895+ }
2896+
2897+ public void renderMesh(Mesh mesh, int lod, int count) {
2898+ if (context.pointSize != mesh.getPointSize()) {
2899+
2900+ if (verboseLogging) {
2901+ logger.log(Level.INFO, "GLES10.glPointSize({0})", mesh.getPointSize());
2902+ }
2903+ // TODO
2904+ Gdx.gl10.glPointSize(mesh.getPointSize());
2905+ context.pointSize = mesh.getPointSize();
2906+ }
2907+ if (context.lineWidth != mesh.getLineWidth()) {
2908+
2909+ if (verboseLogging) {
2910+ logger.log(Level.INFO, "GLES20.glLineWidth({0})", mesh.getLineWidth());
2911+ }
2912+
2913+ Gdx.gl20.glLineWidth(mesh.getLineWidth());
2914+ context.lineWidth = mesh.getLineWidth();
2915+ }
2916+
2917+ statistics.onMeshDrawn(mesh, lod);
2918+// if (GLContext.getCapabilities().GL_ARB_vertex_array_object){
2919+// renderMeshVertexArray(mesh, lod, count);
2920+// }else{
2921+
2922+ if (useVBO) {
2923+ if (verboseLogging) {
2924+ logger.info("RENDERING A MESH USING VertexBufferObject");
2925+ }
2926+
2927+ renderMeshDefault(mesh, lod, count);
2928+ } else {
2929+ if (verboseLogging) {
2930+ logger.info("RENDERING A MESH USING VertexArray");
2931+ }
2932+
2933+ renderMeshVertexArray(mesh, lod, count);
2934+ }
2935+
2936+// }
2937+ }
2938+
2939+ private void checkGLError() {
2940+ }
2941+
2942+ private void checkGLError2() {
2943+ int error;
2944+ while ((error = Gdx.gl20.glGetError()) != GL20.GL_NO_ERROR) {
2945+ logger.log(Level.WARNING, "glError {0}", error);
2946+ // throw new RuntimeException("glError " + error);
2947+ }
2948+ }
2949+
2950+ private boolean log(String message) {
2951+ logger.info(message);
2952+ return true;
2953+ }
2954+
2955+ /**
2956+ * drawTriangleList_Array uses Vertex Array
2957+ * @param indexBuf
2958+ * @param mesh
2959+ * @param count
2960+ */
2961+ public void drawTriangleList_Array(VertexBuffer indexBuf, Mesh mesh, int count) {
2962+ if (verboseLogging) {
2963+ logger.log(Level.INFO, "drawTriangleList_Array(Count = {0})", count);
2964+ }
2965+
2966+ if (indexBuf.getBufferType() != Type.Index) {
2967+ throw new IllegalArgumentException("Only index buffers are allowed as triangle lists.");
2968+ }
2969+
2970+ boolean useInstancing = count > 1 && caps.contains(Caps.MeshInstancing);
2971+ if (useInstancing) {
2972+ throw new IllegalArgumentException("Caps.MeshInstancing is not supported.");
2973+ }
2974+
2975+ int vertCount = mesh.getVertexCount();
2976+ Buffer indexData = indexBuf.getData();
2977+ indexData.clear();
2978+
2979+ if (mesh.getMode() == Mode.Hybrid) {
2980+ int[] modeStart = mesh.getModeStart();
2981+ int[] elementLengths = mesh.getElementLengths();
2982+
2983+ int elMode = convertElementMode(Mode.Triangles);
2984+ int fmt = convertFormat(indexBuf.getFormat());
2985+ int elSize = indexBuf.getFormat().getComponentSize();
2986+ int listStart = modeStart[0];
2987+ int stripStart = modeStart[1];
2988+ int fanStart = modeStart[2];
2989+ int curOffset = 0;
2990+ for (int i = 0; i < elementLengths.length; i++) {
2991+ if (i == stripStart) {
2992+ elMode = convertElementMode(Mode.TriangleStrip);
2993+ } else if (i == fanStart) {
2994+ elMode = convertElementMode(Mode.TriangleStrip);
2995+ }
2996+ int elementLength = elementLengths[i];
2997+
2998+ indexBuf.getData().position(curOffset);
2999+ if (verboseLogging) {
3000+ logger.log(Level.INFO, "glDrawElements(): {0}, {1}", new Object[]{elementLength, curOffset});
3001+ }
3002+
3003+ Gdx.gl20.glDrawElements(elMode, elementLength, fmt, indexBuf.getData());
3004+
3005+ curOffset += elementLength * elSize;
3006+ }
3007+ } else {
3008+ if (verboseLogging) {
3009+ logger.log(Level.INFO, "glDrawElements(), indexBuf.capacity ({0}), vertCount ({1})", new Object[]{indexBuf.getData().capacity(), vertCount});
3010+ }
3011+
3012+ Gdx.gl20.glDrawElements(
3013+ convertElementMode(mesh.getMode()),
3014+ indexBuf.getData().capacity(),
3015+ convertFormat(indexBuf.getFormat()),
3016+ indexBuf.getData());
3017+ }
3018+ }
3019+
3020+ /**
3021+ * setVertexAttrib_Array uses Vertex Array
3022+ * @param vb
3023+ * @param idb
3024+ */
3025+ public void setVertexAttrib_Array(VertexBuffer vb, VertexBuffer idb) {
3026+ if (verboseLogging) {
3027+ logger.log(Level.INFO, "setVertexAttrib_Array({0}, {1})", new Object[]{vb, idb});
3028+ }
3029+
3030+ if (vb.getBufferType() == Type.Index) {
3031+ throw new IllegalArgumentException("Index buffers not allowed to be set to vertex attrib");
3032+ }
3033+
3034+ // Get shader
3035+ int programId = context.boundShaderProgram;
3036+ if (programId > 0) {
3037+ VertexBuffer[] attribs = context.boundAttribs;
3038+
3039+ Attribute attrib = boundShader.getAttribute(vb.getBufferType());
3040+ int loc = attrib.getLocation();
3041+ if (loc == -1) {
3042+ //throw new IllegalArgumentException("Location is invalid for attrib: [" + vb.getBufferType().name() + "]");
3043+ if (verboseLogging) {
3044+ logger.log(Level.WARNING, "attribute is invalid in shader: [{0}]", vb.getBufferType().name());
3045+ }
3046+ return;
3047+ } else if (loc == -2) {
3048+ String attributeName = "in" + vb.getBufferType().name();
3049+
3050+ if (verboseLogging) {
3051+ logger.log(Level.INFO, "GLES20.glGetAttribLocation({0}, {1})", new Object[]{programId, attributeName});
3052+ }
3053+
3054+ loc = Gdx.gl20.glGetAttribLocation(programId, attributeName);
3055+ if (loc < 0) {
3056+ attrib.setLocation(-1);
3057+ if (verboseLogging) {
3058+ logger.log(Level.WARNING, "attribute is invalid in shader: [{0}]", vb.getBufferType().name());
3059+ }
3060+ return; // not available in shader.
3061+ } else {
3062+ attrib.setLocation(loc);
3063+ }
3064+
3065+ } // if (loc == -2)
3066+
3067+ if ((attribs[loc] != vb) || vb.isUpdateNeeded()) {
3068+ System.err.println("isUpdateNeeded "+vb.isUpdateNeeded());
3069+ vb.clearUpdateNeeded();
3070+ // NOTE: Use data from interleaved buffer if specified
3071+ VertexBuffer avb = idb != null ? idb : vb;
3072+ avb.getData().clear();
3073+ avb.getData().position(vb.getOffset());
3074+
3075+ if (verboseLogging) {
3076+ logger.log(Level.INFO,
3077+ "GLES20.glVertexAttribPointer("
3078+ + "location={0}, "
3079+ + "numComponents={1}, "
3080+ + "format={2}, "
3081+ + "isNormalized={3}, "
3082+ + "stride={4}, "
3083+ + "data.capacity={5})",
3084+ new Object[]{loc, vb.getNumComponents(),
3085+ vb.getFormat(),
3086+ vb.isNormalized(),
3087+ vb.getStride(),
3088+ avb.getData().capacity()});
3089+ }
3090+
3091+
3092+ // Upload attribute data
3093+
3094+ Gdx.gl20.glVertexAttribPointer(loc,
3095+ vb.getNumComponents(),
3096+ convertFormat(vb.getFormat()),
3097+ vb.isNormalized(),
3098+ vb.getStride(),
3099+ convBuffer(avb.getData()));
3100+ checkGLError();
3101+
3102+ Gdx.gl20.glEnableVertexAttribArray(loc);
3103+
3104+ attribs[loc] = vb;
3105+ } // if (attribs[loc] != vb)
3106+ } else {
3107+ throw new IllegalStateException("Cannot render mesh without shader bound");
3108+ }
3109+ }
3110+ private ByteBuffer convBuffer(Buffer buf) {
3111+ System.err.println("convBuffer");
3112+ if (buf instanceof FloatBuffer) {
3113+ System.err.println("FloatBuffer");
3114+ FloatBuffer fb = (FloatBuffer)buf;
3115+ ByteBuffer bb = BufferUtils.createByteBuffer(buf.capacity() * 4);
3116+ FloatBuffer fb2 = bb.asFloatBuffer();
3117+ fb2.put(fb);
3118+ return bb;
3119+ } else if (buf instanceof ShortBuffer) {
3120+ System.err.println("ShortBuffer");
3121+
3122+ ShortBuffer sb = (ShortBuffer)buf;
3123+ ByteBuffer bb = BufferUtils.createByteBuffer(buf.capacity() * 2);
3124+ ShortBuffer sb2 = bb.asShortBuffer();
3125+ sb2.put(sb);
3126+ return bb;
3127+ } else {
3128+ return (ByteBuffer)buf;
3129+ //throw new RuntimeException("type = "+buf.getClass().getName());
3130+ }
3131+ }
3132+
3133+ /**
3134+ * setVertexAttrib_Array uses Vertex Array
3135+ * @param vb
3136+ */
3137+ public void setVertexAttrib_Array(VertexBuffer vb) {
3138+ setVertexAttrib_Array(vb, null);
3139+ }
3140+
3141+ public void setAlphaToCoverage(boolean value) {
3142+ if (value) {
3143+ Gdx.gl20.glEnable(GL20.GL_SAMPLE_ALPHA_TO_COVERAGE);
3144+ } else {
3145+ Gdx.gl20.glDisable(GL20.GL_SAMPLE_ALPHA_TO_COVERAGE);
3146+ }
3147+ }
3148+
3149+ @Override
3150+ public void invalidateState() {
3151+ context.reset();
3152+ boundShader = null;
3153+ lastFb = null;
3154+ }
3155+
3156+ public void resetBoundsTexture() {
3157+ context.boundTextures[0] = null;
3158+ if (context.boundTextureUnit != 0) {
3159+ Gdx.gl20.glActiveTexture(GL20.GL_TEXTURE0);
3160+ context.boundTextureUnit = 0;
3161+ }
3162+// GLES20.glDisable(GLES20.GL_TEXTURE_2D);
3163+ Gdx.gl20.glBindTexture(GL20.GL_TEXTURE_2D, 0);
3164+ // context.boundTextureUnit = -2;
3165+// context.boundElementArrayVBO = -2;
3166+// context.boundShaderProgram = -1;
3167+// context.boundArrayVBO = -1;
3168+// context.boundElementArrayVBO = -1;
3169+
3170+ if (context.boundElementArrayVBO != 0) {
3171+
3172+
3173+ Gdx.gl20.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, 0);
3174+ context.boundElementArrayVBO = 0;
3175+ }
3176+ if (context.boundArrayVBO != 0) {
3177+ Gdx.gl20.glBindBuffer(GL20.GL_ARRAY_BUFFER, 0);
3178+ context.boundArrayVBO = 0;
3179+ }
3180+ if (context.boundShaderProgram != 0) {
3181+ Gdx.gl20.glUseProgram(0);
3182+ checkGLError();
3183+ boundShader = null;
3184+ context.boundShaderProgram = 0;
3185+ }
3186+ }
3187+}
--- /dev/null
+++ b/gdx/src/main/java/com/jme3/renderer/gdx/TextureUtilGdx.java
@@ -0,0 +1,499 @@
1+package com.jme3.renderer.gdx;
2+
3+import com.badlogic.gdx.Gdx;
4+import com.badlogic.gdx.graphics.GL10;
5+import com.badlogic.gdx.graphics.GL20;
6+import com.jme3.asset.DesktopAssetManager;
7+import com.jme3.math.FastMath;
8+import com.jme3.system.JmeSystem;
9+import com.jme3.texture.Image;
10+import com.jme3.texture.Image.Format;
11+import java.nio.ByteBuffer;
12+import java.util.logging.Logger;
13+
14+public class TextureUtilGdx {
15+ public static boolean ENABLE_COMPRESSION = true;
16+ private static boolean NPOT = false;
17+ private static boolean ETC1support = false;
18+ private static boolean DXT1 = false;
19+ private static boolean DEPTH24_STENCIL8 = false;
20+ private static boolean DEPTH_TEXTURE = true;
21+ private static boolean RGBA8 = false;
22+
23+ // Same constant used by both GL_ARM_rgba8 and GL_OES_rgb8_rgba8.
24+ private static final int GL_RGBA8 = 0x8058;
25+
26+ private static final int GL_DXT1 = 0x83F0;
27+ private static final int GL_DXT1A = 0x83F1;
28+
29+ private static final int GL_DEPTH_STENCIL_OES = 0x84F9;
30+ private static final int GL_UNSIGNED_INT_24_8_OES = 0x84FA;
31+ private static final int GL_DEPTH24_STENCIL8_OES = 0x88F0;
32+
33+ public static int convertTextureFormat(Format fmt){
34+ switch (fmt){
35+ case Alpha16:
36+ case Alpha8:
37+ return GL10.GL_ALPHA;
38+ case Luminance8Alpha8:
39+ case Luminance16Alpha16:
40+ return GL10.GL_LUMINANCE_ALPHA;
41+ case Luminance8:
42+ case Luminance16:
43+ return GL10.GL_LUMINANCE;
44+ case RGB10:
45+ case RGB16:
46+ case BGR8:
47+ case RGB8:
48+ case RGB565:
49+ return GL10.GL_RGB;
50+ case RGB5A1:
51+ case RGBA16:
52+ case RGBA8:
53+ return GL10.GL_RGBA;
54+
55+ case Depth:
56+ return Gdx.gl20.GL_DEPTH_COMPONENT;
57+ case Depth16:
58+ return Gdx.gl20.GL_DEPTH_COMPONENT16;
59+ case Depth24:
60+ case Depth32:
61+ case Depth32F:
62+ throw new UnsupportedOperationException("Unsupported depth format: " + fmt);
63+
64+ case DXT1A:
65+ throw new UnsupportedOperationException("Unsupported format: " + fmt);
66+ default:
67+ throw new UnsupportedOperationException("Unrecognized format: " + fmt);
68+ }
69+ }
70+ // TODO
71+// private static void buildMipmap(Bitmap bitmap) {
72+// int level = 0;
73+// int height = bitmap.getHeight();
74+// int width = bitmap.getWidth();
75+//
76+// while (height >= 1 || width >= 1) {
77+// //First of all, generate the texture from our bitmap and set it to the according level
78+//
79+// GLUtils.texImage2D(GL10.GL_TEXTURE_2D, level, bitmap, 0);
80+////checkGLError();
81+// if (height == 1 || width == 1) {
82+// break;
83+// }
84+//
85+// //Increase the mipmap level
86+// level++;
87+//
88+// height /= 2;
89+// width /= 2;
90+// Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap, width, height, true);
91+//
92+// bitmap.recycle();
93+// bitmap = bitmap2;
94+// }
95+// }bitmap2
96+// // TODO
97+// /**
98+// * <code>uploadTextureBitmap</code> uploads a native android bitmap
99+// * @param target
100+// * @param bitmap
101+// * @param generateMips
102+// * @param powerOf2
103+// */
104+// public static void uploadTextureBitmap(final int target, Bitmap bitmap, boolean generateMips, boolean powerOf2) {
105+// int MAX_RETRY_COUNT = 1;
106+// for(int retryCount = 0;retryCount<MAX_RETRY_COUNT;retryCount++) {
107+// try {
108+// uploadTextureBitmap2(target, bitmap, generateMips, powerOf2);
109+// }catch(OutOfMemoryError ex) {
110+// if (!(retryCount < MAX_RETRY_COUNT)){
111+// throw ex;
112+// }
113+// DesktopAssetManager assetManager =
114+// (DesktopAssetManager)((AndroidHarness)JmeSystem.getActivity())
115+// .getJmeApplication().getAssetManager();
116+// assetManager.clearCache();
117+// System.gc();
118+// System.runFinalization();
119+// }
120+// }
121+// }
122+// /**
123+// * <code>uploadTextureBitmap</code> uploads a native android bitmap
124+// * @param target
125+// * @param bitmap
126+// * @param generateMips
127+// * @param powerOf2
128+// */
129+// private static void uploadTextureBitmap2(final int target, Bitmap bitmap, boolean generateMips, boolean powerOf2)
130+// {
131+// if (bitmap.isRecycled()) {
132+// throw new RuntimeException("bitmap is recycled.");
133+// }
134+// if (!powerOf2)
135+// {
136+// int width = bitmap.getWidth();
137+// int height = bitmap.getHeight();
138+// if (!FastMath.isPowerOfTwo(width) || !FastMath.isPowerOfTwo(height)
139+// /*|| width >= 512 || height >= 512*/)
140+// {
141+// // scale to power of two
142+// width = FastMath.nearestPowerOfTwo(width);
143+// height = FastMath.nearestPowerOfTwo(height);
144+//// while(width >= 512) {
145+//// width = width / 2;
146+//// }
147+//// while(height >= 512) {
148+//// height = height / 2;
149+//// }
150+// Logger.getLogger(TextureUtil.class.getName()).warning("texture size changed.");
151+// Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap, width, height, true);
152+// bitmap.recycle();
153+// bitmap = bitmap2;
154+// }
155+// }
156+//
157+// if (generateMips)
158+// {
159+// buildMipmap(bitmap);
160+// }
161+// else
162+// {
163+// // TODO
164+// GLUtils.texImage2D(target, 0, bitmap, 0);
165+////checkGLError();
166+////bitmap.recycle();
167+// }
168+// }
169+ private static void unsupportedFormat(Format fmt) {
170+ throw new UnsupportedOperationException("The image format '" + fmt + "' is unsupported by the video hardware.");
171+ }
172+
173+ public static AndroidGLImageFormat getImageFormat(Format fmt) throws UnsupportedOperationException {
174+ AndroidGLImageFormat imageFormat = new AndroidGLImageFormat();
175+ switch (fmt) {
176+ case RGBA16:
177+ case RGB16:
178+ case RGB10:
179+ case Luminance16:
180+ case Luminance16Alpha16:
181+ case Alpha16:
182+ case Depth32:
183+ case Depth32F:
184+ throw new UnsupportedOperationException("The image format '"
185+ + fmt + "' is not supported by OpenGL ES 2.0 specification.");
186+ case Alpha8:
187+ imageFormat.format = GL20.GL_ALPHA;
188+ imageFormat.dataType = GL20.GL_UNSIGNED_BYTE;
189+ if (RGBA8) {
190+ imageFormat.renderBufferStorageFormat = GL_RGBA8;
191+ } else {
192+ // Highest precision alpha supported by vanilla OGLES2
193+ imageFormat.renderBufferStorageFormat = GL20.GL_RGBA4;
194+ }
195+ break;
196+ case Luminance8:
197+ imageFormat.format = GL20.GL_LUMINANCE;
198+ imageFormat.dataType = GL20.GL_UNSIGNED_BYTE;
199+ if (RGBA8) {
200+ imageFormat.renderBufferStorageFormat = GL_RGBA8;
201+ } else {
202+ // Highest precision luminance supported by vanilla OGLES2
203+ imageFormat.renderBufferStorageFormat = GL20.GL_RGB565;
204+ }
205+ break;
206+ case Luminance8Alpha8:
207+ imageFormat.format = GL20.GL_LUMINANCE_ALPHA;
208+ imageFormat.dataType = GL20.GL_UNSIGNED_BYTE;
209+ if (RGBA8) {
210+ imageFormat.renderBufferStorageFormat = GL_RGBA8;
211+ } else {
212+ imageFormat.renderBufferStorageFormat = GL20.GL_RGBA4;
213+ }
214+ break;
215+ case RGB565:
216+ imageFormat.format = GL20.GL_RGB;
217+ imageFormat.dataType = GL20.GL_UNSIGNED_SHORT_5_6_5;
218+ imageFormat.renderBufferStorageFormat = GL20.GL_RGB565;
219+ break;
220+ case ARGB4444:
221+ imageFormat.format = GL20.GL_RGBA4;
222+ imageFormat.dataType = GL20.GL_UNSIGNED_SHORT_4_4_4_4;
223+ imageFormat.renderBufferStorageFormat = GL20.GL_RGBA4;
224+ break;
225+ case RGB5A1:
226+ imageFormat.format = GL20.GL_RGBA;
227+ imageFormat.dataType = GL20.GL_UNSIGNED_SHORT_5_5_5_1;
228+ imageFormat.renderBufferStorageFormat = GL20.GL_RGB5_A1;
229+ break;
230+ case RGB8:
231+ imageFormat.format = GL20.GL_RGB;
232+ imageFormat.dataType = GL20.GL_UNSIGNED_BYTE;
233+ if (RGBA8) {
234+ imageFormat.renderBufferStorageFormat = GL_RGBA8;
235+ } else {
236+ // Fallback: Use RGB565 if RGBA8 is not available.
237+ imageFormat.renderBufferStorageFormat = GL20.GL_RGB565;
238+ }
239+ break;
240+ case BGR8:
241+ imageFormat.format = GL20.GL_RGB;
242+ imageFormat.dataType = GL20.GL_UNSIGNED_BYTE;
243+ if (RGBA8) {
244+ imageFormat.renderBufferStorageFormat = GL_RGBA8;
245+ } else {
246+ imageFormat.renderBufferStorageFormat = GL20.GL_RGB565;
247+ }
248+ break;
249+ case RGBA8:
250+ imageFormat.format = GL20.GL_RGBA;
251+ imageFormat.dataType = GL20.GL_UNSIGNED_BYTE;
252+ if (RGBA8) {
253+ imageFormat.renderBufferStorageFormat = GL_RGBA8;
254+ } else {
255+ imageFormat.renderBufferStorageFormat = GL20.GL_RGBA4;
256+ }
257+ break;
258+ case Depth:
259+ case Depth16:
260+ if (!DEPTH_TEXTURE) {
261+ unsupportedFormat(fmt);
262+ }
263+ imageFormat.format = GL20.GL_DEPTH_COMPONENT;
264+ imageFormat.dataType = GL20.GL_UNSIGNED_SHORT;
265+ imageFormat.renderBufferStorageFormat = GL20.GL_DEPTH_COMPONENT16;
266+ break;
267+ case Depth24:
268+// case Depth24Stencil8:
269+// if (!DEPTH_TEXTURE) {
270+// unsupportedFormat(fmt);
271+// }
272+// if (DEPTH24_STENCIL8) {
273+// // NEW: True Depth24 + Stencil8 format.
274+// imageFormat.format = GL_DEPTH_STENCIL_OES;
275+// imageFormat.dataType = GL_UNSIGNED_INT_24_8_OES;
276+// imageFormat.renderBufferStorageFormat = GL_DEPTH24_STENCIL8_OES;
277+// } else {
278+// // Vanilla OGLES2, only Depth16 available.
279+// imageFormat.format = GLES20.GL_DEPTH_COMPONENT;
280+// imageFormat.dataType = GLES20.GL_UNSIGNED_SHORT;
281+// imageFormat.renderBufferStorageFormat = GLES20.GL_DEPTH_COMPONENT16;
282+// }
283+// break;
284+ case DXT1:
285+ if (!DXT1) {
286+ unsupportedFormat(fmt);
287+ }
288+ imageFormat.format = GL_DXT1;
289+ imageFormat.dataType = GL20.GL_UNSIGNED_BYTE;
290+ imageFormat.compress = true;
291+ break;
292+ case DXT1A:
293+ if (!DXT1) {
294+ unsupportedFormat(fmt);
295+ }
296+ imageFormat.format = GL_DXT1A;
297+ imageFormat.dataType = GL20.GL_UNSIGNED_BYTE;
298+ imageFormat.compress = true;
299+ break;
300+ default:
301+ throw new UnsupportedOperationException("Unrecognized format: " + fmt);
302+ }
303+ return imageFormat;
304+ }
305+ public static class AndroidGLImageFormat {
306+
307+ boolean compress = false;
308+ int format = -1;
309+ int renderBufferStorageFormat = -1;
310+ int dataType = -1;
311+ }
312+ public static void uploadTexture(
313+ Image img,
314+ int target,
315+ int index,
316+ int border,
317+ boolean tdc,
318+ boolean generateMips,
319+ boolean powerOf2){
320+ // TODO
321+// if (img.getEfficentData() instanceof Bitmap){
322+// Bitmap bitmap = (Bitmap) img.getEfficentData();
323+// uploadTextureBitmap(target, bitmap, generateMips, powerOf2);
324+// return;
325+// }
326+
327+ Format fmt = img.getFormat();
328+ ByteBuffer data;
329+ if (index >= 0 || img.getData() != null && img.getData().size() > 0){
330+ data = img.getData(index);
331+ }else{
332+ data = null;
333+ }
334+
335+ int width = img.getWidth();
336+ int height = img.getHeight();
337+ int depth = img.getDepth();
338+
339+ boolean compress = false;
340+ int internalFormat = -1;
341+ int format = -1;
342+ int dataType = -1;
343+
344+ switch (fmt){
345+ case Alpha16:
346+ case Alpha8:
347+ format = GL20.GL_ALPHA;
348+ dataType = GL20.GL_UNSIGNED_BYTE;
349+ break;
350+ case Luminance8:
351+ format = GL20.GL_LUMINANCE;
352+ dataType = GL20.GL_UNSIGNED_BYTE;
353+ break;
354+ case Luminance8Alpha8:
355+ format = GL20.GL_LUMINANCE_ALPHA;
356+ dataType = GL20.GL_UNSIGNED_BYTE;
357+ break;
358+ case Luminance16Alpha16:
359+ format = GL20.GL_LUMINANCE_ALPHA;
360+ dataType = GL20.GL_UNSIGNED_BYTE;
361+ break;
362+ case Luminance16:
363+ format = GL20.GL_LUMINANCE;
364+ dataType = GL20.GL_UNSIGNED_BYTE;
365+ break;
366+ case RGB565:
367+ format = GL20.GL_RGB;
368+ internalFormat = GL20.GL_RGB565;
369+ dataType = GL20.GL_UNSIGNED_SHORT_5_6_5;
370+ break;
371+ case ARGB4444:
372+ format = GL20.GL_RGBA;
373+ dataType = GL20.GL_UNSIGNED_SHORT_4_4_4_4;
374+ break;
375+ case RGB10:
376+ format = GL20.GL_RGB;
377+ dataType = GL20.GL_UNSIGNED_BYTE;
378+ break;
379+ case RGB16:
380+ format = GL20.GL_RGB;
381+ dataType = GL20.GL_UNSIGNED_BYTE;
382+ break;
383+ case RGB5A1:
384+ format = GL20.GL_RGBA;
385+ internalFormat = GL20.GL_RGB5_A1;
386+ dataType = GL20.GL_UNSIGNED_SHORT_5_5_5_1;
387+ break;
388+ case RGB8:
389+ format = GL20.GL_RGB;
390+ dataType = GL20.GL_UNSIGNED_BYTE;
391+ break;
392+ case BGR8:
393+ format = GL20.GL_RGB;
394+ dataType = GL20.GL_UNSIGNED_BYTE;
395+ break;
396+ case RGBA16:
397+ format = GL20.GL_RGBA;
398+ internalFormat = GL20.GL_RGBA4;
399+ dataType = GL20.GL_UNSIGNED_BYTE;
400+ break;
401+ case RGBA8:
402+ format = GL20.GL_RGBA;
403+ dataType = GL20.GL_UNSIGNED_BYTE;
404+ break;
405+ case DXT1A:
406+ format = GL20.GL_COMPRESSED_TEXTURE_FORMATS;
407+ dataType = GL20.GL_UNSIGNED_BYTE;
408+ case Depth:
409+ format = GL20.GL_DEPTH_COMPONENT;
410+ dataType = GL20.GL_UNSIGNED_BYTE;
411+ break;
412+ case Depth16:
413+ format = GL20.GL_DEPTH_COMPONENT;
414+ internalFormat = GL20.GL_DEPTH_COMPONENT16;
415+ dataType = GL20.GL_UNSIGNED_BYTE;
416+ break;
417+ case Depth24:
418+ case Depth32:
419+ case Depth32F:
420+ throw new UnsupportedOperationException("Unsupported depth format: " + fmt);
421+ default:
422+ throw new UnsupportedOperationException("Unrecognized format: " + fmt);
423+ }
424+
425+ if (internalFormat == -1)
426+ {
427+ internalFormat = format;
428+ }
429+
430+ if (data != null)
431+ Gdx.gl20.glPixelStorei(GL20.GL_UNPACK_ALIGNMENT, 1);
432+
433+ int[] mipSizes = img.getMipMapSizes();
434+ int pos = 0;
435+ if (mipSizes == null){
436+ if (data != null)
437+ mipSizes = new int[]{ data.capacity() };
438+ else
439+ mipSizes = new int[]{ width * height * fmt.getBitsPerPixel() / 8 };
440+ }
441+
442+ // XXX: might want to change that when support
443+ // of more than paletted compressions is added..
444+ if (compress){
445+ data.clear();
446+ Gdx.gl20.glCompressedTexImage2D(GL20.GL_TEXTURE_2D,
447+ 1 - mipSizes.length,
448+ format,
449+ width,
450+ height,
451+ 0,
452+ data.capacity(),
453+ data);
454+//checkGLError();
455+return;
456+ }
457+
458+ for (int i = 0; i < mipSizes.length; i++){
459+ int mipWidth = Math.max(1, width >> i);
460+ int mipHeight = Math.max(1, height >> i);
461+ int mipDepth = Math.max(1, depth >> i);
462+
463+ if (data != null){
464+ data.position(pos);
465+ data.limit(pos + mipSizes[i]);
466+ }
467+
468+ if (compress && data != null){
469+ Gdx.gl20.glCompressedTexImage2D(GL20.GL_TEXTURE_2D,
470+ i,
471+ format,
472+ mipWidth,
473+ mipHeight,
474+ 0,
475+ data.remaining(),
476+ data);
477+//checkGLError();
478+ }else{
479+ Gdx.gl20.glTexImage2D(GL20.GL_TEXTURE_2D,
480+ i,
481+ internalFormat,
482+ mipWidth,
483+ mipHeight,
484+ 0,
485+ format,
486+ dataType,
487+ data);
488+ }
489+//checkGLError();
490+ pos += mipSizes[i];
491+ }
492+ }
493+// private static void checkGLError() {
494+// int error;
495+// while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
496+// throw new RuntimeException("glError " + error);
497+// }
498+// }
499+}
--- /dev/null
+++ b/gdx/src/main/java/com/jme3/system/JmeSystemDelegateImpl.java
@@ -0,0 +1,133 @@
1+package com.jme3.system;
2+
3+import com.jme3.app.Application;
4+import com.jme3.asset.*;
5+import com.jme3.asset.gdx.GdxAssetManager;
6+import com.jme3.audio.*;
7+import com.jme3.system.gdx.GdxAudioRenderer;
8+import com.jme3.system.gdx.GdxContext;
9+//import com.jme3.audio.DummyAudioRenderer;
10+import com.jme3.system.JmeContext.Type;
11+import com.jme3.util.JmeFormatter;
12+
13+import java.io.InputStream;
14+import java.util.logging.Handler;
15+import java.util.logging.Level;
16+import java.util.logging.Logger;
17+
18+import java.net.URL;
19+
20+public class JmeSystemDelegateImpl implements JmeSystemDelegate {
21+
22+ private static final Logger logger = Logger.getLogger(JmeSystemDelegateImpl.class.getName());
23+ private boolean initialized = false;
24+ private boolean lowPermissions = false;
25+ private static ThreadLocal<Application> app = new ThreadLocal<Application>();
26+
27+ public void initialize(AppSettings settings) {
28+ if (initialized) {
29+ return;
30+ }
31+
32+ initialized = true;
33+ try {
34+ JmeFormatter formatter = new JmeFormatter();
35+
36+// Handler consoleHandler = new AndroidLogHandler();
37+// consoleHandler.setFormatter(formatter);
38+ } catch (SecurityException ex) {
39+ logger.log(Level.SEVERE, "Security error in creating log file", ex);
40+ }
41+ logger.log(Level.INFO, "Running on {0}", getFullName());
42+ }
43+
44+ public String getFullName() {
45+ return "MikuMikuStudio gdx 1.0.0";
46+ }
47+
48+ public void setLowPermissions(boolean lowPerm) {
49+ lowPermissions = lowPerm;
50+ }
51+
52+ public boolean isLowPermissions() {
53+ return lowPermissions;
54+ }
55+
56+ public JmeContext newContext(AppSettings settings, Type contextType) {
57+ initialize(settings);
58+ if (settings.getRenderer().startsWith("LiveWallpaper")) {
59+
60+ }
61+ return new GdxContext();
62+ }
63+
64+ // TODO
65+ public AudioRenderer newAudioRenderer(AppSettings settings) {
66+ return new GdxAudioRenderer();
67+ }
68+
69+// public static void setResources(Resources res) {
70+// JmeSystem.res = res;
71+// }
72+
73+// public static Resources getResources() {
74+// return res;
75+// }
76+
77+// public static void setActivity(Context activity) {
78+// JmeSystem.activity = activity;
79+//
80+// }
81+ public void setApplication(Application app) {
82+ JmeSystem.app.set(app);
83+ }
84+ public Application getApplication() {
85+ return app.get();
86+ }
87+
88+// public static Context getActivity() {
89+// return activity;
90+// }
91+
92+ public AssetManager newAssetManager() {
93+ logger.log(Level.INFO, "newAssetManager()");
94+ AssetManager am = new GdxAssetManager();
95+
96+ return am;
97+ }
98+
99+ public AssetManager newAssetManager(URL url) {
100+ logger.log(Level.INFO, "newAssetManager({0})", url);
101+ AssetManager am = new GdxAssetManager();
102+
103+ return am;
104+ }
105+
106+ public boolean showSettingsDialog(AppSettings settings, boolean loadSettings) {
107+ return true;
108+ }
109+
110+ public Platform getPlatform() {
111+ String arch = System.getProperty("os.arch").toLowerCase();
112+ if (arch.contains("arm")){
113+ if (arch.contains("v5")){
114+ return Platform.Android_ARM5;
115+ }else if (arch.contains("v6")){
116+ return Platform.Android_ARM6;
117+ }else if (arch.contains("v7")){
118+ return Platform.Android_ARM7;
119+ }else{
120+ return Platform.Android_ARM5; // unknown ARM
121+ }
122+ }else{
123+ throw new UnsupportedOperationException("Unsupported Android Platform");
124+ }
125+ }
126+ public InputStream getResourceAsStream(String name) {
127+ return JmeSystem.class.getResourceAsStream(name);
128+ }
129+
130+ public URL getResource(String name) {
131+ return JmeSystem.class.getResource(name);
132+ }
133+}
--- /dev/null
+++ b/gdx/src/main/java/com/jme3/system/gdx/GdxAssetCache.java
@@ -0,0 +1,27 @@
1+package com.jme3.system.gdx;
2+
3+import com.badlogic.gdx.Gdx;
4+import com.badlogic.gdx.files.FileHandle;
5+
6+import java.io.File;
7+import java.io.IOException;
8+import java.io.InputStream;
9+
10+/**
11+ * Created by kobayasi on 2013/12/29.
12+ */
13+public class GdxAssetCache {
14+ public static FileHandle getFileHandle(String path) {
15+ FileHandle fileHandle = Gdx.files.local("gdxtemp/"+path);
16+ if (!fileHandle.exists()) {
17+ InputStream is = GdxAssetCache.class.getClassLoader().getResourceAsStream(path);
18+ fileHandle.write(is, false);
19+ try {
20+ is.close();
21+ } catch (IOException e) {
22+ e.printStackTrace();
23+ }
24+ }
25+ return fileHandle;
26+ }
27+}
--- /dev/null
+++ b/gdx/src/main/java/com/jme3/system/gdx/GdxAudioData.java
@@ -0,0 +1,64 @@
1+package com.jme3.system.gdx;
2+
3+import com.jme3.asset.AssetKey;
4+import com.jme3.audio.AudioData;
5+import com.jme3.audio.AudioRenderer;
6+import com.jme3.util.NativeObject;
7+
8+/**
9+ * Created by kobayasi on 2013/12/29.
10+ */
11+public class GdxAudioData extends AudioData{
12+ protected AssetKey assetKey;
13+ protected float currentVolume = 0f;
14+
15+ public GdxAudioData(){
16+ super();
17+ }
18+
19+ protected GdxAudioData(int id){
20+ super(id);
21+ }
22+
23+ public AssetKey getAssetKey() {
24+ return assetKey;
25+ }
26+
27+ public void setAssetKey(AssetKey assetKey) {
28+ this.assetKey = assetKey;
29+ }
30+
31+ @Override
32+ public DataType getDataType() {
33+ return DataType.Buffer;
34+ }
35+
36+ @Override
37+ public float getDuration() {
38+ return 0; // TODO: ???
39+ }
40+
41+ @Override
42+ public void resetObject() {
43+ this.id = -1;
44+ setUpdateNeeded();
45+ }
46+
47+ @Override
48+ public void deleteObject(Object rendererObject) {
49+ ((AudioRenderer)rendererObject).deleteAudioData(this);
50+ }
51+
52+ public float getCurrentVolume() {
53+ return currentVolume;
54+ }
55+
56+ public void setCurrentVolume(float currentVolume) {
57+ this.currentVolume = currentVolume;
58+ }
59+
60+ @Override
61+ public NativeObject createDestructableClone() {
62+ return new GdxAudioData(id);
63+ }
64+}
--- /dev/null
+++ b/gdx/src/main/java/com/jme3/system/gdx/GdxAudioLoader.java
@@ -0,0 +1,26 @@
1+package com.jme3.system.gdx;
2+
3+import com.jme3.asset.AssetInfo;
4+import com.jme3.asset.AssetLoader;
5+
6+import java.io.IOException;
7+import java.io.InputStream;
8+
9+/**
10+ * Created by kobayasi on 2013/12/29.
11+ */
12+public class GdxAudioLoader implements AssetLoader {
13+ @Override
14+ public Object load(AssetInfo assetInfo) throws IOException
15+ {
16+
17+ InputStream in = assetInfo.openStream();
18+ if (in != null)
19+ {
20+ in.close();
21+ }
22+ GdxAudioData result = new GdxAudioData();
23+ result.setAssetKey( assetInfo.getKey() );
24+ return result;
25+ }
26+}
--- /dev/null
+++ b/gdx/src/main/java/com/jme3/system/gdx/GdxAudioRenderer.java
@@ -0,0 +1,193 @@
1+package com.jme3.system.gdx;
2+
3+import com.badlogic.gdx.Application;
4+import com.badlogic.gdx.Gdx;
5+import com.badlogic.gdx.audio.Music;
6+import com.jme3.audio.*;
7+
8+import java.util.HashMap;
9+
10+/**
11+ * Created by kobayasi on 2013/12/28.
12+ */
13+public class GdxAudioRenderer implements AudioRenderer{
14+ private boolean audioDisabled = false;
15+ private Listener listener;
16+ private final HashMap<AudioNode, Music> musicMap = new HashMap<AudioNode, Music>();
17+ @Override
18+ public void setListener(Listener listener) {
19+ Gdx.app.log("GdxAudioRenderer", "setListener");
20+ if (audioDisabled) {
21+ return;
22+ }
23+
24+ if (this.listener != null) {
25+ // previous listener no longer associated with current
26+ // renderer
27+ this.listener.setRenderer(null);
28+ }
29+
30+ this.listener = listener;
31+ this.listener.setRenderer(this);
32+
33+ }
34+ @Override
35+ public void setEnvironment(Environment environment) {
36+ Gdx.app.log("GdxAudioRenderer", "setEnvironment");
37+ }
38+
39+ @Override
40+ public void playSourceInstance(AudioNode audioNode) {
41+ Gdx.app.log("GdxAudioRenderer", "playSourceInstance");
42+ GdxAudioData audioData;
43+ audioData = (GdxAudioData) audioNode.getAudioData();
44+ Music music = musicMap.get(audioNode);
45+ if (Gdx.app.getType() == Application.ApplicationType.iOS && audioData.getAssetKey().getName().endsWith(".ogg")) {
46+ return;
47+ }
48+ if (music == null) {
49+ music = Gdx.audio.newMusic(GdxAssetCache.getFileHandle(audioData.getAssetKey().getName()));
50+ musicMap.put(audioNode, music);
51+ }
52+ music.stop();
53+ music.play();
54+ audioNode.setStatus(AudioNode.Status.Playing);
55+ }
56+
57+ @Override
58+ public void playSource(AudioNode audioNode) {
59+ Gdx.app.log("GdxAudioRenderer", "playSource");
60+ if (audioNode.getStatus() == AudioNode.Status.Playing) {
61+ stopSource(audioNode);
62+ playSourceInstance(audioNode);
63+ } else if (audioNode.getStatus() == AudioNode.Status.Stopped) {
64+ playSourceInstance(audioNode);
65+ }
66+ }
67+
68+ @Override
69+ public void pauseSource(AudioNode src) {
70+ Gdx.app.log("GdxAudioRenderer", "pauseSource");
71+ if (src.getStatus() == AudioNode.Status.Playing) {
72+ if (src.getAudioData() instanceof GdxAudioData) {
73+ GdxAudioData audioData = (GdxAudioData) src.getAudioData();
74+ if (audioData.getAssetKey() instanceof AudioKey) {
75+ AudioKey assetKey = (AudioKey) audioData.getAssetKey();
76+
77+ if (assetKey.isStream()) {
78+ Music mp;
79+ if (musicMap.containsKey(src)) {
80+ mp = musicMap.get(src);
81+ mp.pause();
82+ src.setStatus(AudioNode.Status.Paused);
83+ }
84+ } else {
85+ assert src.getChannel() != -1;
86+
87+ if (src.getChannel() > 0) {
88+// soundPool.pause(src.getChannel());
89+ src.setStatus(AudioNode.Status.Paused);
90+ }
91+ }
92+ }
93+ }
94+
95+ }
96+ }
97+
98+ @Override
99+ public void stopSource(AudioNode src) {
100+ Gdx.app.log("GdxAudioRenderer", "stopSource");
101+ if (src.getStatus() != AudioNode.Status.Stopped) {
102+ if (src.getAudioData() instanceof GdxAudioData) {
103+ GdxAudioData audioData = (GdxAudioData) src.getAudioData();
104+ if (audioData.getAssetKey() instanceof AudioKey) {
105+ AudioKey assetKey = (AudioKey) audioData.getAssetKey();
106+ if (assetKey.isStream()) {
107+ Music mp;
108+ if (musicMap.containsKey(src)) {
109+ mp = musicMap.get(src);
110+ mp.stop();
111+ src.setStatus(AudioNode.Status.Stopped);
112+ src.setChannel(-1);
113+ }
114+ } else {
115+ int chan = src.getChannel();
116+ assert chan != -1; // if it's not stopped, must have id
117+
118+ if (src.getChannel() > 0) {
119+// soundPool.stop(src.getChannel());
120+ src.setChannel(-1);
121+ }
122+
123+ src.setStatus(AudioNode.Status.Stopped);
124+
125+ if (audioData.getId() > 0) {
126+// soundPool.unload(audioData.getId());
127+ }
128+ audioData.setId(-1);
129+
130+
131+
132+ }
133+ }
134+ }
135+
136+ }
137+
138+ }
139+
140+ @Override
141+ public void updateSourceParam(AudioNode audioNode, AudioParam audioParam) {
142+ Gdx.app.log("GdxAudioRenderer", "updateSourceParam");
143+ }
144+
145+ @Override
146+ public void updateListenerParam(Listener listener, ListenerParam listenerParam) {
147+ Gdx.app.log("GdxAudioRenderer", "updateListenerParam");
148+
149+ }
150+
151+ @Override
152+ public void deleteFilter(Filter filter) {
153+ Gdx.app.log("GdxAudioRenderer", "deleteFilter");
154+
155+ }
156+
157+ @Override
158+ public void deleteAudioData(AudioData audioData) {
159+ Gdx.app.log("GdxAudioRenderer", "deleteAudioData");
160+
161+ }
162+
163+ @Override
164+ public void initialize() {
165+ Gdx.app.log("GdxAudioRenderer", "initialize");
166+
167+ }
168+
169+ @Override
170+ public void update(float v) {
171+// Gdx.app.log("GdxAudioRenderer", "update");
172+ for(AudioNode src : musicMap.keySet()) {
173+ Music music = musicMap.get(src);
174+ if (src.getStatus() == AudioNode.Status.Playing) {
175+ if (!music.isPlaying()) {
176+ Gdx.app.log("GdxAudioRenderer","music Stopped");
177+ src.setStatus(AudioNode.Status.Stopped);
178+ } else {
179+ }
180+ }
181+ }
182+
183+ }
184+
185+ @Override
186+ public void cleanup() {
187+ Gdx.app.log("GdxAudioRenderer", "cleanup");
188+ for(Music music : musicMap.values()) {
189+ music.dispose();
190+ }
191+ musicMap.clear();
192+ }
193+}
--- /dev/null
+++ b/gdx/src/main/java/com/jme3/system/gdx/GdxContext.java
@@ -0,0 +1,145 @@
1+package com.jme3.system.gdx;
2+
3+import com.badlogic.gdx.Gdx;
4+import com.badlogic.gdx.input.GestureDetector;
5+import com.jme3.input.*;
6+import com.jme3.input.dummy.DummyKeyInput;
7+import com.jme3.input.dummy.DummyMouseInput;
8+import com.jme3.renderer.Renderer;
9+import com.jme3.renderer.gdx.GdxRenderer;
10+import com.jme3.system.AppSettings;
11+import com.jme3.system.JmeContext;
12+import com.jme3.system.SystemListener;
13+import com.jme3.system.Timer;
14+
15+/**
16+ * Created with IntelliJ IDEA.
17+ * User: kobayasi
18+ * Date: 13/10/07
19+ * Time: 20:59
20+ * To change this template use File | Settings | File Templates.
21+ */
22+public class GdxContext implements JmeContext {
23+ private SystemListener systemListener;
24+ private AppSettings settings;
25+ private GdxRenderer renderer;
26+ private boolean created = false;
27+ private boolean renderable = false;
28+ private boolean autoFlush = true;
29+ private GdxTimer timer;
30+ private boolean needInitialize = true;
31+
32+ public GdxContext() {
33+ timer = new GdxTimer();
34+ }
35+
36+ @Override
37+ public Type getType() {
38+ return Type.Display;
39+ }
40+
41+ @Override
42+ public void setSettings(AppSettings appSettings) {
43+ System.out.println("GdxContext.setSettings");
44+ if (appSettings == null) {
45+ throw new RuntimeException("GdxContext.setSettings appSettings == null");
46+ }
47+ this.settings = appSettings;
48+ }
49+
50+ @Override
51+ public void setSystemListener(SystemListener systemListener) {
52+ System.out.println("setSystemListener");
53+ this.systemListener = systemListener;
54+ }
55+
56+ @Override
57+ public AppSettings getSettings() {
58+ return settings;
59+ }
60+
61+ @Override
62+ public Renderer getRenderer() {
63+ return renderer; //To change body of implemented methods use File | Settings | File Templates.
64+ }
65+
66+ @Override
67+ public MouseInput getMouseInput() {
68+ return new DummyMouseInput();
69+ }
70+
71+ @Override
72+ public KeyInput getKeyInput() {
73+ return new DummyKeyInput();
74+ }
75+
76+ @Override
77+ public JoyInput getJoyInput() {
78+ return null; //To change body of implemented methods use File | Settings | File Templates.
79+ }
80+
81+ @Override
82+ public TouchInput getTouchInput() {
83+ GdxInput input = new GdxInput();
84+ Gdx.input.setInputProcessor(new GestureDetector(input));
85+ return input;
86+ //return null; //To change body of implemented methods use File | Settings | File Templates.
87+ }
88+
89+ @Override
90+ public Timer getTimer() {
91+ return timer;
92+ }
93+
94+ @Override
95+ public void setTitle(String s) {
96+ }
97+
98+ @Override
99+ public boolean isCreated() {
100+ return created;
101+ }
102+
103+ @Override
104+ public boolean isRenderable() {
105+ return renderable;
106+ }
107+
108+ @Override
109+ public void setAutoFlushFrames(boolean b) {
110+ this.autoFlush = b;
111+ }
112+
113+ @Override
114+ public void create(boolean b) {
115+ System.out.println("GdxContext.create()");
116+ renderer = new GdxRenderer();
117+ renderable = true;
118+ created = true;
119+ }
120+
121+ @Override
122+ public void restart() {
123+ }
124+
125+ @Override
126+ public void destroy(boolean b) {
127+ renderable = false;
128+ }
129+
130+ public void onDrawFrame() {
131+ if (needInitialize) {
132+ renderer.initialize();
133+ systemListener.initialize();
134+ needInitialize = false;
135+ }
136+ if (isRenderable()) {
137+ if (systemListener != null) {
138+ systemListener.update();
139+ }
140+ if (autoFlush) {
141+ renderer.onFrame();
142+ }
143+ }
144+ }
145+}
--- /dev/null
+++ b/gdx/src/main/java/com/jme3/system/gdx/GdxInput.java
@@ -0,0 +1,426 @@
1+package com.jme3.system.gdx;
2+
3+import com.badlogic.gdx.Gdx;
4+import com.badlogic.gdx.InputProcessor;
5+import com.badlogic.gdx.input.GestureDetector;
6+import com.badlogic.gdx.math.Vector2;
7+import com.jme3.input.RawInputListener;
8+import com.jme3.input.TouchInput;
9+import com.jme3.input.event.MouseButtonEvent;
10+import com.jme3.input.event.MouseMotionEvent;
11+import com.jme3.input.event.TouchEvent;
12+import com.jme3.math.Vector2f;
13+import com.jme3.util.RingBuffer;
14+
15+import java.util.HashMap;
16+import java.util.logging.Logger;
17+
18+/**
19+ * Created by kobayasi on 2013/12/27.
20+ */
21+public class GdxInput implements TouchInput, InputProcessor, GestureDetector.GestureListener {
22+ private static final Logger logger = Logger.getLogger(GdxInput.class.getName());
23+ final private static int MAX_EVENTS = 1024;
24+
25+ public boolean mouseEventsEnabled = true;
26+ public boolean mouseEventsInvertX = false;
27+ public boolean mouseEventsInvertY = false;
28+ public boolean keyboardEventsEnabled = false;
29+ public boolean dontSendHistory = false;
30+ private RawInputListener listener = null;
31+ final private RingBuffer<TouchEvent> eventQueue = new RingBuffer<TouchEvent>(MAX_EVENTS);
32+ final private RingBuffer<TouchEvent> eventPoolUnConsumed = new RingBuffer<TouchEvent>(MAX_EVENTS);
33+ final private RingBuffer<TouchEvent> eventPool = new RingBuffer<TouchEvent>(MAX_EVENTS);
34+ final private HashMap<Integer, Vector2f> lastPositions = new HashMap<Integer, Vector2f>();
35+ private int lastX = -1;
36+ private int lastY = -1;
37+ private boolean isInitialized = false;
38+
39+ @Override
40+ public void setSimulateMouse(boolean b) {
41+ mouseEventsEnabled = b;
42+ }
43+
44+ @Override
45+ public void setSimulateKeyboard(boolean b) {
46+ keyboardEventsEnabled = b;
47+ }
48+
49+ @Override
50+ public void setOmitHistoricEvents(boolean b) {
51+ dontSendHistory = b;
52+ }
53+
54+ @Override
55+ public void initialize() {
56+ TouchEvent item;
57+ for (int i = 0; i < MAX_EVENTS; i++)
58+ {
59+ item = new TouchEvent();
60+ eventPool.push(item);
61+ }
62+ isInitialized = true;
63+ }
64+
65+ @Override
66+ public void update() {
67+ if (listener != null) {
68+ TouchEvent event;
69+ MouseButtonEvent btn;
70+ int newX;
71+ int newY;
72+ while (!eventQueue.isEmpty()) {
73+ synchronized (eventQueue) {
74+ event = eventQueue.pop();
75+ }
76+ if (event != null) {
77+ listener.onTouchEvent(event);
78+ if (mouseEventsEnabled) {
79+ if (mouseEventsInvertX)
80+ newX = Gdx.graphics.getWidth() - (int) event.getX();
81+ else
82+ newX = (int) event.getX();
83+
84+ if (mouseEventsInvertY)
85+ newY = Gdx.graphics.getHeight() - (int) event.getY();
86+ else
87+ newY = (int) event.getY();
88+ switch (event.getType()) {
89+ case DOWN:
90+ // Handle mouse down event
91+ btn = new MouseButtonEvent(0, true, newX, newY);
92+ btn.setTime(event.getTime());
93+ listener.onMouseButtonEvent(btn);
94+ // Store current pos
95+ lastX = -1;
96+ lastY = -1;
97+ //lastX = newX;
98+ //lastY = newY;
99+// System.err.println("DOWN x = " + btn.getX() + " y = " + btn.getY());
100+ break;
101+
102+ case UP:
103+ // Handle mouse up event
104+ btn = new MouseButtonEvent(0, false, newX, newY);
105+ btn.setTime(event.getTime());
106+ listener.onMouseButtonEvent(btn);
107+ // Store current pos
108+ lastX = -1;
109+ lastY = -1;
110+ //lastX = newX;
111+ //lastY = newY;
112+// System.err.println("UP x = " + btn.getX() + " y = " + btn.getY());
113+ break;
114+
115+ case MOVE:
116+ int dx;
117+ int dy;
118+ if (lastX != -1) {
119+ dx = newX - lastX;
120+ dy = newY - lastY;
121+ } else {
122+ dx = 1;
123+ dy = 0;
124+ }
125+ MouseMotionEvent mot = new MouseMotionEvent(newX, newY, dx, dy, 0, 0);
126+ mot.setTime(event.getTime());
127+ listener.onMouseMotionEvent(mot);
128+ lastX = newX;
129+ lastY = newY;
130+ break;
131+ }
132+ }
133+ }
134+ if (event.isConsumed() == false) {
135+ synchronized (eventPoolUnConsumed) {
136+ try {
137+ eventPoolUnConsumed.push(event);
138+ } catch(Exception ex) {
139+ ex.printStackTrace();
140+ }
141+ }
142+
143+ } else {
144+ synchronized (eventPool) {
145+ try {
146+ eventPool.push(event);
147+ } catch(Exception ex) {
148+ ex.printStackTrace();
149+ }
150+ }
151+ }
152+ }
153+ }
154+
155+ }
156+
157+ @Override
158+ public void destroy() {
159+
160+ }
161+
162+ @Override
163+ public boolean isInitialized() {
164+ return isInitialized;
165+ }
166+
167+ @Override
168+ public void setInputListener(RawInputListener rawInputListener) {
169+ this.listener = rawInputListener;
170+ }
171+
172+ @Override
173+ public long getInputTimeNanos() {
174+ return System.nanoTime();
175+ }
176+
177+ private void processEvent(TouchEvent event) {
178+ synchronized (eventQueue) {
179+ try {
180+ eventQueue.push(event);
181+ } catch(Exception ex) {
182+ ex.printStackTrace();
183+ }
184+ }
185+ }
186+
187+ private TouchEvent getNextFreeTouchEvent() {
188+ return getNextFreeTouchEvent(false);
189+ }
190+ private TouchEvent getNextFreeTouchEvent(boolean wait)
191+ {
192+ TouchEvent evt = null;
193+ synchronized(eventPoolUnConsumed)
194+ {
195+ int size = eventPoolUnConsumed.size();
196+ while (size > 0)
197+ {
198+ evt = eventPoolUnConsumed.pop();
199+ if (!evt.isConsumed())
200+ {
201+ eventPoolUnConsumed.push(evt);
202+ evt = null;
203+ }
204+ else
205+ {
206+ break;
207+ }
208+ size--;
209+ }
210+ }
211+
212+
213+ if (evt == null)
214+ {
215+ if (eventPool.isEmpty() && wait)
216+ {
217+ logger.warning("eventPool buffer underrun");
218+ boolean isEmpty;
219+ do
220+ {
221+ synchronized(eventPool)
222+ {
223+ isEmpty = eventPool.isEmpty();
224+ }
225+ try { Thread.sleep(50); } catch (InterruptedException e) { }
226+ }
227+ while (isEmpty);
228+ synchronized(eventPool)
229+ {
230+ evt = eventPool.pop();
231+ }
232+ }
233+ else if (eventPool.isEmpty())
234+ {
235+ evt = new TouchEvent();
236+ logger.warning("eventPool buffer underrun");
237+ }
238+ else
239+ {
240+ synchronized(eventPool)
241+ {
242+ evt = eventPool.pop();
243+ }
244+ }
245+ }
246+ return evt;
247+ }
248+
249+ // InputProcessor methods.
250+
251+ @Override
252+ public boolean keyDown(int keycode) {
253+ return false;
254+ }
255+
256+ @Override
257+ public boolean keyUp(int keycode) {
258+ return false;
259+ }
260+
261+ @Override
262+ public boolean keyTyped(char character) {
263+ return false;
264+ }
265+
266+ @Override
267+ public boolean touchDown(int screenX, int screenY, int pointer, int button) {
268+ //mouseMoved2(screenX, screenY);
269+ TouchEvent event = getNextFreeTouchEvent();
270+ //event.set(TouchEvent.Type.MOVE, screenX, Gdx.graphics.getHeight() - screenY, 0, 0);
271+ //event.setPointerId(0);
272+ //event.setTime(System.nanoTime());
273+ //processEvent(event);
274+
275+ //event = getNextFreeTouchEvent();
276+ event.set(TouchEvent.Type.DOWN, screenX, Gdx.graphics.getHeight() - screenY, 0, 0);
277+ event.setPointerId(0);
278+ event.setTime(System.nanoTime());
279+ processEvent(event);
280+
281+ Vector2f lastPos = lastPositions.get(pointer);
282+ if (lastPos == null)
283+ {
284+ lastPos = new Vector2f(screenX, Gdx.graphics.getHeight() - screenY);
285+ lastPositions.put(pointer, lastPos);
286+ }
287+ lastPos.set(screenX, Gdx.graphics.getHeight() - screenY);
288+
289+ System.err.println("touchDown x = " + screenX + " y = " + screenY);
290+ return false;
291+ }
292+
293+ @Override
294+ public boolean touchUp(int screenX, int screenY, int pointer, int button) {
295+ TouchEvent event = getNextFreeTouchEvent();
296+ event.set(TouchEvent.Type.UP, screenX, Gdx.graphics.getHeight() - screenY, 0, 0);
297+ event.setPointerId(pointer);
298+ event.setTime(System.nanoTime());
299+ processEvent(event);
300+ System.err.println("touchUp x = " + screenX + " y = " + screenY);
301+ return false;
302+ }
303+
304+ @Override
305+ public boolean touchDragged(int screenX, int screenY, int pointer) {
306+ if (screenX < 0 || screenY < 0) {
307+ return false;
308+ }
309+ Vector2f lastPos = lastPositions.get(pointer);
310+ if (lastPos == null)
311+ {
312+ lastPos = new Vector2f(screenX, Gdx.graphics.getHeight() - screenY);
313+ lastPositions.put(pointer, lastPos);
314+ }
315+ TouchEvent event = getNextFreeTouchEvent();
316+ event.set(TouchEvent.Type.MOVE, screenX, Gdx.graphics.getHeight() - screenY, screenX - lastPos.x, Gdx.graphics.getHeight() - screenY - lastPos.y);
317+ event.setPointerId(pointer);
318+ event.setTime(System.nanoTime());
319+ processEvent(event);
320+ System.err.println("touchDragged x = " + screenX + " y = " + screenY);
321+ lastPos.set(screenX, Gdx.graphics.getHeight() - screenY);
322+ return false;
323+ }
324+
325+ @Override
326+ public boolean mouseMoved(int screenX, int screenY) {
327+ return mouseMoved2(screenX, screenY);
328+ }
329+ public boolean mouseMoved2(int screenX, int screenY) {
330+ if (screenX < 0 || screenY < 0) {
331+ return false;
332+ }
333+ Vector2f lastPos = lastPositions.get(0);
334+ if (lastPos == null)
335+ {
336+ lastPos = new Vector2f(screenX, Gdx.graphics.getHeight() - screenY);
337+ lastPositions.put(0, lastPos);
338+ }
339+
340+
341+ TouchEvent event = getNextFreeTouchEvent();
342+ event.set(TouchEvent.Type.MOVE, screenX, Gdx.graphics.getHeight() - screenY, screenX - lastPos.x, Gdx.graphics.getHeight() - screenY - lastPos.y);
343+ event.setPointerId(0);
344+ event.setTime(System.nanoTime());
345+ processEvent(event);
346+// System.err.println("mouseMoved x = " + screenX + " y = " + screenY);
347+ lastPos.set(screenX, Gdx.graphics.getHeight() - screenY);
348+ return false;
349+ }
350+
351+ @Override
352+ public boolean scrolled(int amount) {
353+// System.err.println("scrolled amount = " + amount);
354+ return false;
355+ }
356+ public boolean isMouseEventsInvertY() {
357+ return mouseEventsInvertY;
358+ }
359+
360+ public void setMouseEventsInvertY(boolean mouseEventsInvertY) {
361+ this.mouseEventsInvertY = mouseEventsInvertY;
362+ }
363+
364+ public boolean isMouseEventsInvertX() {
365+ return mouseEventsInvertX;
366+ }
367+
368+ public void setMouseEventsInvertX(boolean mouseEventsInvertX) {
369+ this.mouseEventsInvertX = mouseEventsInvertX;
370+ }
371+
372+ // GestureListener
373+
374+ @Override
375+ public boolean touchDown(float x, float y, int pointer, int button) {
376+ System.err.println("touchDown2");
377+ return touchDown((int)x, (int)y, pointer, button);
378+ }
379+
380+ @Override
381+ public boolean tap(float x, float y, int count, int button) {
382+ System.err.println("tap");
383+ return touchUp((int)x, (int)y, count, button);
384+ }
385+
386+ @Override
387+ public boolean longPress(float x, float y) {
388+ System.err.println("longPress");
389+ return false;
390+ }
391+
392+ @Override
393+ public boolean fling(float velocityX, float velocityY, int button) {
394+ System.err.println("fling");
395+ return false;
396+ }
397+
398+ @Override
399+ public boolean pan(float x, float y, float deltaX, float deltaY) {
400+ System.err.println("pan");
401+ return touchDragged((int)x, (int)y, 0);
402+ }
403+
404+ @Override
405+ public boolean panStop(float x, float y, int pointer, int button) {
406+ System.err.println("panStop");
407+ return touchUp((int)x,(int)y,pointer, button);
408+ }
409+
410+ @Override
411+ public boolean zoom(float initialDistance, float distance) {
412+ System.err.println("zoom "+initialDistance+" "+distance);
413+ TouchEvent event = getNextFreeTouchEvent();
414+ event.set(TouchEvent.Type.SCALE_MOVE, initialDistance, distance, 0, 0);
415+ event.setPointerId(0);
416+ event.setTime(System.nanoTime());
417+ processEvent(event);
418+ return false;
419+ }
420+
421+ @Override
422+ public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2) {
423+ System.err.println("pinch");
424+ return false;
425+ }
426+}
--- /dev/null
+++ b/gdx/src/main/java/com/jme3/system/gdx/GdxTimer.java
@@ -0,0 +1,97 @@
1+/*
2+ * Copyright (c) 2003-2009 jMonkeyEngine
3+ * All rights reserved.
4+ *
5+ * Redistribution and use in source and binary forms, with or without
6+ * modification, are permitted provided that the following conditions are
7+ * met:
8+ *
9+ * * Redistributions of source code must retain the above copyright
10+ * notice, this list of conditions and the following disclaimer.
11+ *
12+ * * Redistributions in binary form must reproduce the above copyright
13+ * notice, this list of conditions and the following disclaimer in the
14+ * documentation and/or other materials provided with the distribution.
15+ *
16+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17+ * may be used to endorse or promote products derived from this software
18+ * without specific prior written permission.
19+ *
20+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+ */
32+
33+package com.jme3.system.gdx;
34+
35+import com.jme3.system.Timer;
36+
37+/**
38+ * <code>GdxTimer</code> is a System.nanoTime implementation of <code>Timer</code>.
39+ */
40+public class GdxTimer extends Timer {
41+
42+ //private static final long TIMER_RESOLUTION = 1000L;
43+ //private static final float INVERSE_TIMER_RESOLUTION = 1f/1000L;
44+ private static final long TIMER_RESOLUTION = 1000000000L;
45+ private static final float INVERSE_TIMER_RESOLUTION = 1f/1000000000L;
46+
47+ private long startTime;
48+ private float previousTime;
49+ private float tpf;
50+ private float fps;
51+
52+ public GdxTimer() {
53+ //startTime = System.currentTimeMillis();
54+ startTime = System.nanoTime();
55+ }
56+
57+ /**
58+ * Returns the time in seconds. The timer starts
59+ * at 0.0 seconds.
60+ *
61+ * @return the current time in seconds
62+ */
63+ @Override
64+ public float getTimeInSeconds() {
65+ return getTime() * INVERSE_TIMER_RESOLUTION;
66+ }
67+
68+ public long getTime() {
69+ //return System.currentTimeMillis() - startTime;
70+ return System.nanoTime() - startTime;
71+ }
72+
73+ public long getResolution() {
74+ return TIMER_RESOLUTION;
75+ }
76+
77+ public float getFrameRate() {
78+ return fps;
79+ }
80+
81+ public float getTimePerFrame() {
82+ return tpf;
83+ }
84+
85+ public void update() {
86+ long timeNow = getTime();
87+ tpf = (timeNow) * (1.0f / TIMER_RESOLUTION) - previousTime;
88+ fps = 1.0f / tpf;
89+ previousTime = previousTime += tpf;
90+ }
91+
92+ public void reset() {
93+ //startTime = System.currentTimeMillis();
94+ startTime = System.nanoTime();
95+ previousTime = 0;//getTime();
96+ }
97+}
--- /dev/null
+++ b/gdx/src/main/java/com/jme3/texture/plugins/gdx/GdxImageLoader.java
@@ -0,0 +1,140 @@
1+package com.jme3.texture.plugins.gdx;
2+
3+import com.badlogic.gdx.graphics.GL20;
4+import com.badlogic.gdx.graphics.Pixmap;
5+import com.jme3.asset.AssetInfo;
6+import com.jme3.asset.AssetLoader;
7+import com.jme3.asset.AssetNotFoundException;
8+import com.jme3.math.FastMath;
9+import com.jme3.texture.Image;
10+import com.jme3.util.BufferUtils;
11+
12+import java.io.IOException;
13+import java.io.InputStream;
14+import java.nio.ByteBuffer;
15+
16+/**
17+ * Created with IntelliJ IDEA.
18+ * User: kobayasi
19+ * Date: 13/10/10
20+ * Time: 23:54
21+ * To change this template use File | Settings | File Templates.
22+ */
23+public class GdxImageLoader implements AssetLoader{
24+ public GdxImageLoader() {
25+ }
26+
27+ @Override
28+ public Object load(AssetInfo assetInfo) throws IOException {
29+ Pixmap pixmap = null;
30+ InputStream is = null;
31+
32+ try {
33+ is = assetInfo.openStream();
34+ byte[] buf = new byte[is.available()];
35+ System.err.println(assetInfo.getKey()+" buf length = "+buf.length);
36+ int i = 0;
37+ while ( i < buf.length) {
38+ int len = is.read(buf, i, buf.length - i);
39+ if (len < 0) {
40+ throw new IOException();
41+ }
42+ i += len;
43+ }
44+ is.close();
45+ is = null;
46+ pixmap = new Pixmap(buf, 0, buf.length);
47+ Image.Format format;
48+ ByteBuffer bb = BufferUtils.clone(pixmap.getPixels());
49+ int height = pixmap.getHeight();
50+ int width = pixmap.getWidth();
51+ switch(pixmap.getGLFormat()) {
52+ case GL20.GL_RGBA:
53+ format = Image.Format.RGBA8;
54+ ByteBuffer bb2 = pixmap.getPixels();
55+ for(int y = 0;y<height;y++) {
56+ bb.position((y * width)*4);
57+ bb2.position(((height - y - 1) * width)*4);
58+ for(int i2=0;i2<width * 4;i2++) {
59+ bb.put(bb2.get());
60+ }
61+ }
62+ break;
63+ case GL20.GL_RGB:
64+ format = Image.Format.RGB8;
65+ bb2 = pixmap.getPixels();
66+ for(int y = 0;y<height;y++) {
67+ bb.position((y * width)*3);
68+ bb2.position(((height - y-1) * width)*3);
69+ for(int i2=0;i2<width * 3;i2++) {
70+ bb.put(bb2.get());
71+ }
72+ }
73+ break;
74+ default:
75+ throw new IOException("Invalid format "+pixmap.getGLFormat());
76+ }
77+ if (pixmap.getWidth() != FastMath.nearestPowerOfTwo(pixmap.getWidth())
78+ || pixmap.getHeight() != FastMath.nearestPowerOfTwo(pixmap.getHeight())) {
79+ if (pixmap.getGLFormat() == GL20.GL_RGBA) {
80+ bb = resize(pixmap.getWidth(), pixmap.getHeight(), FastMath.nearestPowerOfTwo(pixmap.getWidth()),FastMath.nearestPowerOfTwo(pixmap.getHeight()),bb);
81+ } else {
82+ bb = resize2(pixmap.getWidth(), pixmap.getHeight(), FastMath.nearestPowerOfTwo(pixmap.getWidth()),FastMath.nearestPowerOfTwo(pixmap.getHeight()),bb);
83+ }
84+ }
85+ Image image = new Image(format, FastMath.nearestPowerOfTwo(pixmap.getWidth()),FastMath.nearestPowerOfTwo(pixmap.getHeight()), bb, null);
86+ return image; //To change body of implemented methods use File | Settings | File Templates.
87+ } finally {
88+ if (pixmap != null) {
89+ pixmap.dispose();
90+ }
91+ if (is != null) {
92+ is.close();
93+ }
94+ }
95+ }
96+ private static ByteBuffer resize(int w1,int h1, int w2, int h2, ByteBuffer bb) {
97+// w2 = w1;
98+// h2 = h1;
99+ if (w1 == w2 && h1 == h2) {
100+ return bb;
101+ }
102+ ByteBuffer out = BufferUtils.createByteBuffer(w2 * h2 * 4);
103+ float f1 = ((float)w1) / (float)w2;
104+ float f2 = ((float)h1) / (float)h2;
105+ for(int x = 0;x<w2;x++) {
106+ for(int y = 0;y<h2;y++) {
107+ int index = (int)(((int)(f2 * (float)y)) * (float)w1 + f1 * (float)x);
108+ if (index >= w1 * h1) {
109+ index = 0;
110+ }
111+ for(int i=0;i<4;i++) {
112+ out.put((x + y * w2)*4+i,bb.get(index * 4 + i));
113+ }
114+ }
115+ }
116+ return out;
117+ }
118+ private static ByteBuffer resize2(int w1,int h1, int w2, int h2, ByteBuffer bb) {
119+// w2 = w1;
120+// h2 = h1;
121+ if (w1 == w2 && h1 == h2) {
122+ //return buf;
123+ }
124+ ByteBuffer out = BufferUtils.createByteBuffer(w2 * h2 * 3);
125+ float f1 = ((float)w1) / (float)w2;
126+ float f2 = ((float)h1) / (float)h2;
127+ for(int x = 0;x<w2;x++) {
128+ for(int y = 0;y<h2;y++) {
129+ int index = (int)(((int)(f2 * (float)y)) * (float)w1 + f1 * (float)x);
130+ if (index >= w1 * h1) {
131+ index = 0;
132+ }
133+ for(int i=0;i<3;i++) {
134+ out.put((x + y * w2)*3+i,bb.get(index * 3 + i));
135+ }
136+ }
137+ }
138+ return out;
139+ }
140+}
--- /dev/null
+++ b/gdx/src/main/java/com/jme3/texture/plugins/gdx/GdxTGALoader.java
@@ -0,0 +1,572 @@
1+/*
2+ * Copyright (c) 2009-2010 jMonkeyEngine
3+ * All rights reserved.
4+ *
5+ * Redistribution and use in source and binary forms, with or without
6+ * modification, are permitted provided that the following conditions are
7+ * met:
8+ *
9+ * * Redistributions of source code must retain the above copyright
10+ * notice, this list of conditions and the following disclaimer.
11+ *
12+ * * Redistributions in binary form must reproduce the above copyright
13+ * notice, this list of conditions and the following disclaimer in the
14+ * documentation and/or other materials provided with the distribution.
15+ *
16+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17+ * may be used to endorse or promote products derived from this software
18+ * without specific prior written permission.
19+ *
20+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+ */
32+
33+package com.jme3.texture.plugins.gdx;
34+
35+import com.jme3.math.FastMath;
36+import com.jme3.asset.AssetLoader;
37+import com.jme3.texture.Image;
38+import com.jme3.util.BufferUtils;
39+import com.jme3.asset.AssetInfo;
40+import com.jme3.asset.TextureKey;
41+import com.jme3.texture.Image.Format;
42+import java.io.BufferedInputStream;
43+import java.io.DataInputStream;
44+import java.io.IOException;
45+import java.io.InputStream;
46+import java.nio.ByteBuffer;
47+
48+/**
49+ * <code>TextureManager</code> provides static methods for building a
50+ * <code>Texture</code> object. Typically, the information supplied is the
51+ * filename and the texture properties.
52+ *
53+ * @author Mark Powell
54+ * @author Joshua Slack - cleaned, commented, added ability to read 16bit true color and color-mapped TGAs.
55+ * @author Kirill Vainer - ported to jME3
56+ * @version $Id: TGALoader.java 4131 2009-03-19 20:15:28Z blaine.dev $
57+ */
58+public final class GdxTGALoader implements AssetLoader {
59+
60+ // 0 - no image data in file
61+ public static final int TYPE_NO_IMAGE = 0;
62+
63+ // 1 - uncompressed, color-mapped image
64+ public static final int TYPE_COLORMAPPED = 1;
65+
66+ // 2 - uncompressed, true-color image
67+ public static final int TYPE_TRUECOLOR = 2;
68+
69+ // 3 - uncompressed, black and white image
70+ public static final int TYPE_BLACKANDWHITE = 3;
71+
72+ // 9 - run-length encoded, color-mapped image
73+ public static final int TYPE_COLORMAPPED_RLE = 9;
74+
75+ // 10 - run-length encoded, true-color image
76+ public static final int TYPE_TRUECOLOR_RLE = 10;
77+
78+ // 11 - run-length encoded, black and white image
79+ public static final int TYPE_BLACKANDWHITE_RLE = 11;
80+
81+ public Object load(AssetInfo info) throws IOException{
82+ if (!(info.getKey() instanceof TextureKey))
83+ throw new IllegalArgumentException("Texture assets must be loaded using a TextureKey");
84+
85+ boolean flip = ((TextureKey)info.getKey()).isFlipY();
86+ InputStream in = null;
87+ try {
88+ in = info.openStream();
89+ Image img = load(in, flip);
90+ return img;
91+ } finally {
92+ if (in != null){
93+ in.close();
94+ }
95+ }
96+ }
97+
98+ /**
99+ * <code>loadImage</code> is a manual image loader which is entirely
100+ * independent of AWT. OUT: RGB888 or RGBA8888 Image object
101+ *
102+ * @return <code>Image</code> object that contains the
103+ * image, either as a RGB888 or RGBA8888
104+ * @param flip
105+ * Flip the image vertically
106+ * @param exp32
107+ * Add a dummy Alpha channel to 24b RGB image.
108+ * @param fis
109+ * InputStream of an uncompressed 24b RGB or 32b RGBA TGA
110+ * @throws java.io.IOException
111+ */
112+ public static Image load(InputStream in, boolean flip) throws IOException {
113+ boolean flipH = false;
114+
115+ // open a stream to the file
116+ DataInputStream dis = new DataInputStream(new BufferedInputStream(in));
117+
118+ // ---------- Start Reading the TGA header ---------- //
119+ // length of the image id (1 byte)
120+ int idLength = dis.readUnsignedByte();
121+
122+ // Type of color map (if any) included with the image
123+ // 0 - no color map data is included
124+ // 1 - a color map is included
125+ int colorMapType = dis.readUnsignedByte();
126+
127+ // Type of image being read:
128+ int imageType = dis.readUnsignedByte();
129+
130+ // Read Color Map Specification (5 bytes)
131+ // Index of first color map entry (if we want to use it, uncomment and remove extra read.)
132+// short cMapStart = flipEndian(dis.readShort());
133+ dis.readShort();
134+ // number of entries in the color map
135+ short cMapLength = flipEndian(dis.readShort());
136+ // number of bits per color map entry
137+ int cMapDepth = dis.readUnsignedByte();
138+
139+ // Read Image Specification (10 bytes)
140+ // horizontal coordinate of lower left corner of image. (if we want to use it, uncomment and remove extra read.)
141+// int xOffset = flipEndian(dis.readShort());
142+ dis.readShort();
143+ // vertical coordinate of lower left corner of image. (if we want to use it, uncomment and remove extra read.)
144+// int yOffset = flipEndian(dis.readShort());
145+ dis.readShort();
146+ // width of image - in pixels
147+ int width = flipEndian(dis.readShort());
148+ // height of image - in pixels
149+ int height = flipEndian(dis.readShort());
150+ // bits per pixel in image.
151+ int pixelDepth = dis.readUnsignedByte();
152+ int imageDescriptor = dis.readUnsignedByte();
153+ if ((imageDescriptor & 32) != 0) // bit 5 : if 1, flip top/bottom ordering
154+ flip = !flip;
155+ if ((imageDescriptor & 16) != 0) // bit 4 : if 1, flip left/right ordering
156+ flipH = !flipH;
157+
158+ // ---------- Done Reading the TGA header ---------- //
159+
160+ // Skip image ID
161+ if (idLength > 0)
162+ in.skip(idLength);
163+
164+ ColorMapEntry[] cMapEntries = null;
165+ if (colorMapType != 0) {
166+ // read the color map.
167+ int bytesInColorMap = (cMapDepth * cMapLength) >> 3;
168+ int bitsPerColor = Math.min(cMapDepth/3 , 8);
169+
170+ byte[] cMapData = new byte[bytesInColorMap];
171+ in.read(cMapData);
172+
173+ // Only go to the trouble of constructing the color map
174+ // table if this is declared a color mapped image.
175+ if (imageType == TYPE_COLORMAPPED || imageType == TYPE_COLORMAPPED_RLE) {
176+ cMapEntries = new ColorMapEntry[cMapLength];
177+ int alphaSize = cMapDepth - (3*bitsPerColor);
178+ float scalar = 255f / (FastMath.pow(2, bitsPerColor) - 1);
179+ float alphaScalar = 255f / (FastMath.pow(2, alphaSize) - 1);
180+ for (int i = 0; i < cMapLength; i++) {
181+ ColorMapEntry entry = new ColorMapEntry();
182+ int offset = cMapDepth * i;
183+ entry.red = (byte)(int)(getBitsAsByte(cMapData, offset, bitsPerColor) * scalar);
184+ entry.green = (byte)(int)(getBitsAsByte(cMapData, offset+bitsPerColor, bitsPerColor) * scalar);
185+ entry.blue = (byte)(int)(getBitsAsByte(cMapData, offset+(2*bitsPerColor), bitsPerColor) * scalar);
186+ if (alphaSize <= 0)
187+ entry.alpha = (byte)255;
188+ else
189+ entry.alpha = (byte)(int)(getBitsAsByte(cMapData, offset+(3*bitsPerColor), alphaSize) * alphaScalar);
190+
191+ cMapEntries[i] = entry;
192+ }
193+ }
194+ }
195+
196+
197+ // Allocate image data array
198+ Format format;
199+ byte[] rawData = null;
200+ int dl;
201+ if (pixelDepth == 32) {
202+ rawData = new byte[width * height * 4];
203+ dl = 4;
204+ } else {
205+ rawData = new byte[width * height * 3];
206+ dl = 3;
207+ }
208+ int rawDataIndex = 0;
209+
210+ if (imageType == TYPE_TRUECOLOR) {
211+ byte red = 0;
212+ byte green = 0;
213+ byte blue = 0;
214+ byte alpha = 0;
215+
216+ // Faster than doing a 16-or-24-or-32 check on each individual pixel,
217+ // just make a seperate loop for each.
218+ if (pixelDepth == 16) {
219+ byte[] data = new byte[2];
220+ float scalar = 255f/31f;
221+ for (int i = 0; i <= (height - 1); i++) {
222+ if (!flip)
223+ rawDataIndex = (height - 1 - i) * width * dl;
224+ for (int j = 0; j < width; j++) {
225+ data[1] = dis.readByte();
226+ data[0] = dis.readByte();
227+ rawData[rawDataIndex++] = (byte)(int)(getBitsAsByte(data, 1, 5) * scalar);
228+ rawData[rawDataIndex++] = (byte)(int)(getBitsAsByte(data, 6, 5) * scalar);
229+ rawData[rawDataIndex++] = (byte)(int)(getBitsAsByte(data, 11, 5) * scalar);
230+ if (dl == 4) {
231+ // create an alpha channel
232+ alpha = getBitsAsByte(data, 0, 1);
233+ if (alpha == 1) alpha = (byte)255;
234+ rawData[rawDataIndex++] = alpha;
235+ } else {
236+ rawData[rawDataIndex++] = (byte)0xff;
237+ }
238+ }
239+ }
240+
241+ format = dl == 4 ? Format.RGBA8 : Format.RGB8;
242+ } else if (pixelDepth == 24){
243+ for (int y = 0; y < height; y++) {
244+ if (!flip)
245+ rawDataIndex = (height - 1 - y) * width * dl;
246+ else
247+ rawDataIndex = y * width * dl;
248+
249+// dis.readFully(rawData, rawDataIndex, width * dl);
250+ for (int x = 0; x < width; x++) {
251+// read scanline
252+ blue = dis.readByte();
253+ green = dis.readByte();
254+ red = dis.readByte();
255+ rawData[rawDataIndex++] = red;
256+ rawData[rawDataIndex++] = green;
257+ rawData[rawDataIndex++] = blue;
258+ }
259+ }
260+ format = Format.RGB8;
261+ } else if (pixelDepth == 32){
262+ for (int i = 0; i <= (height - 1); i++) {
263+ if (!flip)
264+ rawDataIndex = (height - 1 - i) * width * dl;
265+
266+ for (int j = 0; j < width; j++) {
267+ blue = dis.readByte();
268+ green = dis.readByte();
269+ red = dis.readByte();
270+ alpha = dis.readByte();
271+ rawData[rawDataIndex++] = red;
272+ rawData[rawDataIndex++] = green;
273+ rawData[rawDataIndex++] = blue;
274+ rawData[rawDataIndex++] = alpha;
275+ }
276+ }
277+ format = Format.RGBA8;
278+ }else{
279+ throw new IOException("Unsupported TGA true color depth: "+pixelDepth);
280+ }
281+ } else if( imageType == TYPE_TRUECOLOR_RLE ) {
282+ byte red = 0;
283+ byte green = 0;
284+ byte blue = 0;
285+ byte alpha = 0;
286+ // Faster than doing a 16-or-24-or-32 check on each individual pixel,
287+ // just make a seperate loop for each.
288+ if( pixelDepth == 32 ){
289+ for( int i = 0; i <= ( height - 1 ); ++i ){
290+ if( !flip ){
291+ rawDataIndex = ( height - 1 - i ) * width * dl;
292+ }
293+
294+ for( int j = 0; j < width; ++j ){
295+ // Get the number of pixels the next chunk covers (either packed or unpacked)
296+ int count = dis.readByte();
297+ if( ( count & 0x80 ) != 0 ){
298+ // Its an RLE packed block - use the following 1 pixel for the next <count> pixels
299+ count &= 0x07f;
300+ j += count;
301+ blue = dis.readByte();
302+ green = dis.readByte();
303+ red = dis.readByte();
304+ alpha = dis.readByte();
305+ while( count-- >= 0 ){
306+ rawData[rawDataIndex++] = red;
307+ rawData[rawDataIndex++] = green;
308+ rawData[rawDataIndex++] = blue;
309+ rawData[rawDataIndex++] = alpha;
310+ }
311+ } else{
312+ // Its not RLE packed, but the next <count> pixels are raw.
313+ j += count;
314+ while( count-- >= 0 ){
315+ blue = dis.readByte();
316+ green = dis.readByte();
317+ red = dis.readByte();
318+ alpha = dis.readByte();
319+ rawData[rawDataIndex++] = red;
320+ rawData[rawDataIndex++] = green;
321+ rawData[rawDataIndex++] = blue;
322+ rawData[rawDataIndex++] = alpha;
323+ }
324+ }
325+ }
326+ }
327+ format = Format.RGBA8;
328+ } else if( pixelDepth == 24 ){
329+ for( int i = 0; i <= ( height - 1 ); i++ ){
330+ if( !flip ){
331+ rawDataIndex = ( height - 1 - i ) * width * dl;
332+ }
333+ for( int j = 0; j < width; ++j ){
334+ // Get the number of pixels the next chunk covers (either packed or unpacked)
335+ int count = dis.readByte();
336+ if( ( count & 0x80 ) != 0 ){
337+ // Its an RLE packed block - use the following 1 pixel for the next <count> pixels
338+ count &= 0x07f;
339+ j += count;
340+ blue = dis.readByte();
341+ green = dis.readByte();
342+ red = dis.readByte();
343+ while( count-- >= 0 ){
344+ rawData[rawDataIndex++] = red;
345+ rawData[rawDataIndex++] = green;
346+ rawData[rawDataIndex++] = blue;
347+ }
348+ } else{
349+ // Its not RLE packed, but the next <count> pixels are raw.
350+ j += count;
351+ while( count-- >= 0 ){
352+ blue = dis.readByte();
353+ green = dis.readByte();
354+ red = dis.readByte();
355+ rawData[rawDataIndex++] = red;
356+ rawData[rawDataIndex++] = green;
357+ rawData[rawDataIndex++] = blue;
358+ }
359+ }
360+ }
361+ }
362+ format = Format.RGB8;
363+ } else if( pixelDepth == 16 ){
364+ byte[] data = new byte[ 2 ];
365+ float scalar = 255f / 31f;
366+ for( int i = 0; i <= ( height - 1 ); i++ ){
367+ if( !flip ){
368+ rawDataIndex = ( height - 1 - i ) * width * dl;
369+ }
370+ for( int j = 0; j < width; j++ ){
371+ // Get the number of pixels the next chunk covers (either packed or unpacked)
372+ int count = dis.readByte();
373+ if( ( count & 0x80 ) != 0 ){
374+ // Its an RLE packed block - use the following 1 pixel for the next <count> pixels
375+ count &= 0x07f;
376+ j += count;
377+ data[1] = dis.readByte();
378+ data[0] = dis.readByte();
379+ blue = (byte) (int) ( getBitsAsByte( data, 1, 5 ) * scalar );
380+ green = (byte) (int) ( getBitsAsByte( data, 6, 5 ) * scalar );
381+ red = (byte) (int) ( getBitsAsByte( data, 11, 5 ) * scalar );
382+ while( count-- >= 0 ){
383+ rawData[rawDataIndex++] = red;
384+ rawData[rawDataIndex++] = green;
385+ rawData[rawDataIndex++] = blue;
386+ }
387+ } else{
388+ // Its not RLE packed, but the next <count> pixels are raw.
389+ j += count;
390+ while( count-- >= 0 ){
391+ data[1] = dis.readByte();
392+ data[0] = dis.readByte();
393+ blue = (byte) (int) ( getBitsAsByte( data, 1, 5 ) * scalar );
394+ green = (byte) (int) ( getBitsAsByte( data, 6, 5 ) * scalar );
395+ red = (byte) (int) ( getBitsAsByte( data, 11, 5 ) * scalar );
396+ rawData[rawDataIndex++] = red;
397+ rawData[rawDataIndex++] = green;
398+ rawData[rawDataIndex++] = blue;
399+ }
400+ }
401+ }
402+ }
403+ format = Format.RGB8;
404+ } else{
405+ throw new IOException( "Unsupported TGA true color depth: " + pixelDepth );
406+ }
407+
408+ } else if( imageType == TYPE_COLORMAPPED ){
409+ int bytesPerIndex = pixelDepth / 8;
410+
411+ if (bytesPerIndex == 1) {
412+ for (int i = 0; i <= (height - 1); i++) {
413+ if (!flip)
414+ rawDataIndex = (height - 1 - i) * width * dl;
415+ for (int j = 0; j < width; j++) {
416+ int index = dis.readUnsignedByte();
417+ if (index >= cMapEntries.length || index < 0)
418+ throw new IOException("TGA: Invalid color map entry referenced: "+index);
419+
420+ ColorMapEntry entry = cMapEntries[index];
421+ rawData[rawDataIndex++] = entry.red;
422+ rawData[rawDataIndex++] = entry.green;
423+ rawData[rawDataIndex++] = entry.blue;
424+ if (dl == 4) {
425+ rawData[rawDataIndex++] = entry.alpha;
426+ } else {
427+ rawData[rawDataIndex++] = (byte)0xff;
428+ }
429+ }
430+ }
431+ } else if (bytesPerIndex == 2) {
432+ for (int i = 0; i <= (height - 1); i++) {
433+ if (!flip)
434+ rawDataIndex = (height - 1 - i) * width * dl;
435+ for (int j = 0; j < width; j++) {
436+ int index = flipEndian(dis.readShort());
437+ if (index >= cMapEntries.length || index < 0)
438+ throw new IOException("TGA: Invalid color map entry referenced: "+index);
439+
440+ ColorMapEntry entry = cMapEntries[index];
441+ rawData[rawDataIndex++] = entry.red;
442+ rawData[rawDataIndex++] = entry.green;
443+ rawData[rawDataIndex++] = entry.blue;
444+ if (dl == 4) {
445+ rawData[rawDataIndex++] = entry.alpha;
446+ } else {
447+ rawData[rawDataIndex++] = (byte)0xff;
448+ }
449+ }
450+ }
451+ } else {
452+ throw new IOException("TGA: unknown colormap indexing size used: "+bytesPerIndex);
453+ }
454+
455+ format = dl == 4 ? Format.RGBA8 : Format.RGB8;
456+ } else {
457+ throw new IOException("Grayscale TGA not supported");
458+ }
459+
460+
461+ in.close();
462+ Image textureImage = new Image();
463+ textureImage.setFormat(format);
464+ textureImage.setWidth(FastMath.nearestPowerOfTwo(width));
465+ textureImage.setHeight(FastMath.nearestPowerOfTwo(height));
466+ if (format != Format.RGBA8) {
467+ rawData = resize2(width, height, FastMath.nearestPowerOfTwo(width), FastMath.nearestPowerOfTwo(height), rawData);
468+ //textureImage.setFormat(Format.RGBA8);
469+ } else {
470+ rawData = resize(width, height, FastMath.nearestPowerOfTwo(width), FastMath.nearestPowerOfTwo(height), rawData);
471+ }
472+ ByteBuffer bb = BufferUtils.createByteBuffer(rawData.length);
473+ for(int i=0;i<rawData.length;i++) {
474+ bb.put(rawData[i]);
475+ }
476+ bb.position(0);
477+ textureImage.setData(bb);
478+ System.out.println("pixelDepth = "+pixelDepth);
479+ return textureImage;
480+ }
481+
482+ private static byte getBitsAsByte(byte[] data, int offset, int length) {
483+ int offsetBytes = offset / 8;
484+ int indexBits = offset % 8;
485+ int rVal = 0;
486+
487+ // start at data[offsetBytes]... spill into next byte as needed.
488+ for (int i = length; --i >=0;) {
489+ byte b = data[offsetBytes];
490+ int test = indexBits == 7 ? 1 : 2 << (6-indexBits);
491+ if ((b & test) != 0) {
492+ if (i == 0)
493+ rVal++;
494+ else
495+ rVal += (2 << i-1);
496+ }
497+ indexBits++;
498+ if (indexBits == 8) {
499+ indexBits = 0;
500+ offsetBytes++;
501+ }
502+ }
503+
504+ return (byte)rVal;
505+ }
506+
507+ /**
508+ * <code>flipEndian</code> is used to flip the endian bit of the header
509+ * file.
510+ *
511+ * @param signedShort
512+ * the bit to flip.
513+ * @return the flipped bit.
514+ */
515+ private static short flipEndian(short signedShort) {
516+ int input = signedShort & 0xFFFF;
517+ return (short) (input << 8 | (input & 0xFF00) >>> 8);
518+ }
519+
520+ static class ColorMapEntry {
521+ byte red, green, blue, alpha;
522+
523+ @Override
524+ public String toString() {
525+ return "entry: "+red+","+green+","+blue+","+alpha;
526+ }
527+ }
528+ private static byte[] resize(int w1,int h1, int w2, int h2, byte[] buf) {
529+// w2 = w1;
530+// h2 = h1;
531+ if (w1 == w2 && h1 == h2) {
532+ return buf;
533+ }
534+ byte[] out = new byte[w2 * h2 * 4];
535+ float f1 = ((float)w1) / (float)w2;
536+ float f2 = ((float)h1) / (float)h2;
537+ for(int x = 0;x<w2;x++) {
538+ for(int y = 0;y<h2;y++) {
539+ int index = (int)(((int)(f2 * (float)y)) * (float)w1 + f1 * (float)x);
540+ if (index >= w1 * h1) {
541+ index = 0;
542+ }
543+ for(int i=0;i<4;i++) {
544+ out[(x + y * w2)*4+i] = buf[index * 4 + i];
545+ }
546+ }
547+ }
548+ return out;
549+ }
550+ private static byte[] resize2(int w1,int h1, int w2, int h2, byte[] buf) {
551+// w2 = w1;
552+// h2 = h1;
553+ if (w1 == w2 && h1 == h2) {
554+ //return buf;
555+ }
556+ byte[] out = new byte[w2 * h2 * 3];
557+ float f1 = ((float)w1) / (float)w2;
558+ float f2 = ((float)h1) / (float)h2;
559+ for(int x = 0;x<w2;x++) {
560+ for(int y = 0;y<h2;y++) {
561+ int index = (int)(((int)(f2 * (float)y)) * (float)w1 + f1 * (float)x);
562+ if (index >= w1 * h1) {
563+ index = 0;
564+ }
565+ for(int i=0;i<3;i++) {
566+ out[(x + y * w2)*3+i] = buf[index * 3 + i];
567+ }
568+ }
569+ }
570+ return out;
571+ }
572+}
--- /dev/null
+++ b/gdx/src/main/java/com/jme3/util/RingBuffer.java
@@ -0,0 +1,75 @@
1+package com.jme3.util;
2+
3+import java.util.Iterator;
4+import java.util.NoSuchElementException;
5+
6+/**
7+ * Ring buffer (fixed size queue) implementation using a circular array (array with wrap-around).
8+ */
9+// suppress unchecked warnings in Java 1.5.0_6 and later
10+@SuppressWarnings("unchecked")
11+public class RingBuffer<Item> implements Iterable<Item> {
12+
13+ private Item[] buffer; // queue elements
14+ private int count = 0; // number of elements on queue
15+ private int indexOut = 0; // index of first element of queue
16+ private int indexIn = 0; // index of next available slot
17+
18+ // cast needed since no generic array creation in Java
19+ public RingBuffer(int capacity) {
20+ buffer = (Item[]) new Object[capacity];
21+ }
22+
23+ public boolean isEmpty() {
24+ return count == 0;
25+ }
26+
27+ public int size() {
28+ return count;
29+ }
30+
31+ public void push(Item item) {
32+ if (count == buffer.length) {
33+ throw new RuntimeException("Ring buffer overflow");
34+ }
35+ buffer[indexIn] = item;
36+ indexIn = (indexIn + 1) % buffer.length; // wrap-around
37+ count++;
38+ }
39+
40+ public Item pop() {
41+ if (isEmpty()) {
42+ throw new RuntimeException("Ring buffer underflow");
43+ }
44+ Item item = buffer[indexOut];
45+ buffer[indexOut] = null; // to help with garbage collection
46+ count--;
47+ indexOut = (indexOut + 1) % buffer.length; // wrap-around
48+ return item;
49+ }
50+
51+ public Iterator<Item> iterator() {
52+ return new RingBufferIterator();
53+ }
54+
55+ // an iterator, doesn't implement remove() since it's optional
56+ private class RingBufferIterator implements Iterator<Item> {
57+
58+ private int i = 0;
59+
60+ public boolean hasNext() {
61+ return i < count;
62+ }
63+
64+ public void remove() {
65+ throw new UnsupportedOperationException();
66+ }
67+
68+ public Item next() {
69+ if (!hasNext()) {
70+ throw new NoSuchElementException();
71+ }
72+ return buffer[i++];
73+ }
74+ }
75+}
--- /dev/null
+++ b/gdx/src/main/resources/asset/Desktop.cfg
@@ -0,0 +1,22 @@
1+LOCATOR / com.jme3.asset.plugins.ClasspathLocator
2+
3+LOADER com.jme3.audio.plugins.WAVLoader : wav
4+LOADER com.jme3.audio.plugins.OGGLoader : ogg
5+LOADER com.jme3.material.plugins.J3MLoader : j3m
6+LOADER com.jme3.material.plugins.J3MLoader : j3md
7+LOADER com.jme3.font.plugins.BitmapFontLoader : fnt
8+LOADER com.jme3.texture.plugins.DDSLoader : dds
9+LOADER com.jme3.texture.plugins.PFMLoader : pfm
10+LOADER com.jme3.texture.plugins.HDRLoader : hdr
11+LOADER com.jme3.texture.plugins.TGALoader : tga
12+LOADER com.jme3.export.binary.BinaryImporter : j3o
13+LOADER com.jme3.export.binary.BinaryImporter : j3f
14+LOADER com.jme3.scene.plugins.OBJLoader : obj
15+LOADER com.jme3.scene.plugins.MTLLoader : mtl
16+LOADER com.jme3.scene.plugins.ogre.MeshLoader : meshxml, mesh.xml
17+LOADER com.jme3.scene.plugins.ogre.SkeletonLoader : skeletonxml, skeleton.xml
18+LOADER com.jme3.scene.plugins.ogre.MaterialLoader : material
19+LOADER com.jme3.scene.plugins.ogre.SceneLoader : scene
20+LOADER com.jme3.shader.plugins.GLSLLoader : vert, frag, glsl, glsllib
21+LOADER projectkyoto.jme3.mmd.PMDLoaderGLSLSkinning2 : pmd
22+LOADER projectkyoto.jme3.mmd.VMDLoader : vmd
\ No newline at end of file