LibGDX Drawing a 2D sprite into a 3D environment - java
I am trying to draw a 2d sprite into a 3d environment to try and get a delver style game. Since this is for a project I am using just LibGDX and no game engines. If anyone knows any good guide or at least point me in the right direction, anything is appreciated.
Luckily, Delvers source code is publicly available to review so you can see how Delver did it. I believe they did use Decals, possibly extending more functionality to them. Decal is definitely what you are looking for.
Here are a few samples from the Decals wiki on LibGDX
Instantiate:
Decal decal = Decal.newDecal(textureRegion, true);
Look at Camera (so its always facing it)
decal.lookAt(camera.position, camera.up);
DecalBatch is used to render the decal.
Check out the LibGDX wiki on Decals for a full breakdown.
Full example from LibGDX tests:
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.FPSLogger;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.g3d.decals.CameraGroupStrategy;
import com.badlogic.gdx.graphics.g3d.decals.Decal;
import com.badlogic.gdx.graphics.g3d.decals.DecalBatch;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.tests.utils.GdxTest;
import com.badlogic.gdx.tests.utils.PerspectiveCamController;
import com.badlogic.gdx.utils.Array;
public class SimpleDecalTest extends GdxTest {
private static final int NUM_DECALS = 3;
DecalBatch batch;
Array<Decal> decals = new Array<Decal>();
PerspectiveCamera camera;
PerspectiveCamController controller;
FPSLogger logger = new FPSLogger();
public void create () {
float width = Gdx.graphics.getWidth();
float height = Gdx.graphics.getHeight();
camera = new PerspectiveCamera(45, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.near = 1;
camera.far = 300;
camera.position.set(0, 0, 5);
controller = new PerspectiveCamController(camera);
Gdx.input.setInputProcessor(controller);
batch = new DecalBatch(new CameraGroupStrategy(camera));
TextureRegion[] textures = {new TextureRegion(new Texture(Gdx.files.internal("data/egg.png"))),
new TextureRegion(new Texture(Gdx.files.internal("data/wheel.png"))),
new TextureRegion(new Texture(Gdx.files.internal("data/badlogic.jpg")))};
Decal decal = Decal.newDecal(1, 1, textures[1]);
decal.setPosition(0, 0, 0);
decals.add(decal);
decal = Decal.newDecal(1, 1, textures[0], true);
decal.setPosition(0.5f, 0.5f, 1);
decals.add(decal);
decal = Decal.newDecal(1, 1, textures[0], true);
decal.setPosition(1, 1, -1);
decals.add(decal);
decal = Decal.newDecal(1, 1, textures[2]);
decal.setPosition(1.5f, 1.5f, -2);
decals.add(decal);
decal = Decal.newDecal(1, 1, textures[1]);
decal.setPosition(2, 2, -1.5f);
decals.add(decal);
}
Vector3 dir = new Vector3();
private boolean billboard = true;
public void render () {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
Gdx.gl.glEnable(GL20.GL_DEPTH_TEST);
camera.update();
for (int i = 0; i < decals.size; i++) {
Decal decal = decals.get(i);
if (billboard) {
// billboarding for ortho cam :)
// dir.set(-camera.direction.x, -camera.direction.y, -camera.direction.z);
// decal.setRotation(dir, Vector3.Y);
// billboarding for perspective cam
decal.lookAt(camera.position, camera.up);
}
batch.add(decal);
}
batch.flush();
logger.log();
}
#Override
public void dispose () {
batch.dispose();
}
}
Also, Delvers source code if interested: https://github.com/Interrupt/delverengine
Related
LibGdx Chess Board
I try to create a chess board, just the board in libGdx but for some reason, I can't. I still miss two other rows in the chess. I will show you my code, maybe you can find the problem in my code, if not, I can easily accept another solution. package com.mygdx.game; import com.badlogic.gdx.ApplicationAdapter; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Pixmap.Format; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.maps.MapLayers; import com.badlogic.gdx.maps.tiled.TiledMap; import com.badlogic.gdx.maps.tiled.TiledMapTileLayer; import com.badlogic.gdx.maps.tiled.TiledMapTileLayer.Cell; import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer; import com.badlogic.gdx.maps.tiled.tiles.StaticTiledMapTile; import com.badlogic.gdx.utils.ScreenUtils; import com.badlogic.gdx.utils.viewport.Viewport; public class MyGdxGame extends ApplicationAdapter { SpriteBatch batch; Texture img; private OrthographicCamera camera; private OrthogonalTiledMapRenderer render; private final static int width = 100, height = 80, layercount = 8; private TiledMap map; #Override public void create() { float w = Gdx.graphics.getWidth(); float h = Gdx.graphics.getHeight(); camera = new OrthographicCamera(w, h); Pixmap pixmap = new Pixmap(100, 80, Format.RGBA8888); pixmap.setColor(Color.WHITE); // add your 1 color here pixmap.fillRectangle(0, 0, 80, 80); pixmap.setColor(Color.BLACK); // add your 2 color here pixmap.fillRectangle(0, 0, 80, 80); // the outcome is an texture with an blue left square and an red right // square Texture t = new Texture(pixmap); TextureRegion reg1 = new TextureRegion(t, 0, 0, 80, 80); TextureRegion reg2 = new TextureRegion(t, 80, 0, 80, 80); TiledMap map = new TiledMap(); MapLayers layers = map.getLayers(); for (int l = 0; l < layercount; l++) { TiledMapTileLayer layer = new TiledMapTileLayer(width, height, 80, 80); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { Cell cell = new Cell(); if (y % 2!= 0) { if (x % 2 != 0) { cell.setTile(new StaticTiledMapTile(reg1)); } else { cell.setTile(new StaticTiledMapTile(reg2)); } } else { if (x % 2 != 0) { cell.setTile(new StaticTiledMapTile(reg2)); } else { cell.setTile(new StaticTiledMapTile(reg1)); } } layer.setCell(x, y, cell); } } layers.add(layer); } render = new OrthogonalTiledMapRenderer(map); render.setView(camera); camera.translate(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2); } #Override public void dispose() { render.dispose(); map.dispose(); } private static final float movmentspeed = 5f; #Override public void render() { Gdx.gl.glClearColor(1, 1, 1, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); camera.update(); render.setView(camera); render.render(); if (Gdx.input.isKeyPressed(Keys.LEFT)) { camera.translate(-movmentspeed, 0); } else if (Gdx.input.isKeyPressed(Keys.RIGHT)) { camera.translate(movmentspeed, 0); } else if (Gdx.input.isKeyPressed(Keys.UP)) { camera.translate(0, movmentspeed); } else if (Gdx.input.isKeyPressed(Keys.DOWN)) { camera.translate(0, -movmentspeed); } } #Override public void resize(int width, int height) { } #Override public void pause() { } #Override public void resume() { } } Here is my code. I need a solution to this as fast as possible if you can...
Your second call to pixmap.setColor(Color.BLACK); // add your 2 color here pixmap.fillRectangle(0, 0, 80, 80); overwrites the colour set by the first because you are writing to the same area. Within the nested loop iterating over the board, you could simplify finding the alternating cell type for the chessboard to if ((x+(y*8)) % 2 = 0 ) { //Cell is bottom left square color } else { //Cell is the other colour } Although its nice to generate the chess board for special effects later, you could also just import one from the tiled editor and then you can experiment more with how it looks. Tile map loaders absolutely not the pain you might imagine they are super short, literally a snippets worth, there is a written loader here https://gamefromscratch.com/libgdx-tutorial-11-tiled-maps-part-1-simple-orthogonal-maps/ (also and not relevant this Pixmap pixmap = new Pixmap(100, 80, Format.RGBA8888); is a larger region than you ever use.) There is a no AI libGDX chess game here as well if you want to just extend with AI. https://github.com/axlan/libgdx-chess
VAO does't render in color with shaders
I recently started learning OpenGL and I have been trying to write a program that displays a diamond on the screen using VAOs and VBOs with shaders. My code is mostly based on this tutorial: https://www.opengl.org/wiki/Tutorial2:_VAOs,_VBOs,_Vertex_and_Fragment_Shaders_%28C_/_SDL%29 and I also used the shaders from the tutorial. The diamond is supposed to be drawn using the color information from the vertex array object but instead it is just drawn in white. The shaders seem to be loading fine so I think it is a problem with my vertex and buffer array objects. Can someone please explain why my code is not working how I expected or show a clear example of how to render VAOs using colors from an array of color attributes. package windows; import java.awt.Frame; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.nio.FloatBuffer; import java.nio.IntBuffer; import javax.media.opengl.GL2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import javax.media.opengl.awt.GLCanvas; import javax.media.opengl.glu.GLU; import shaders.ShaderControl2; import com.jogamp.common.nio.Buffers; public class Test4 implements GLEventListener{ ShaderControl2 sc; FloatBuffer vertexPos, vertexCol; IntBuffer vao, vbo; GLU glu = new GLU(); public static void main(String[] args){ GLProfile glp = GLProfile.getDefault(); GLCapabilities caps = new GLCapabilities(glp); GLCanvas canvas = new GLCanvas(caps); Test4 t = new Test4(); canvas.addGLEventListener(t); Frame f = new Frame("TEST #4"); f.setSize(400,400); f.add(canvas); f.setVisible(true); f.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0); } }); } #Override public void display(GLAutoDrawable drawable) { GL2 gl = drawable.getGL().getGL2(); gl.glClearColor(0, 0, 0, 1f); gl.glClear(GL2.GL_COLOR_BUFFER_BIT); sc.useShader(gl); gl.glBindVertexArray(vao.get(0)); gl.glEnableVertexAttribArray(0); gl.glEnableVertexAttribArray(1); gl.glDrawArrays(GL2.GL_LINE_LOOP, 0 , 4); sc.dontUseShader(gl); } #Override public void dispose(GLAutoDrawable drawable) { // TODO Auto-generated method stub } #Override public void init(GLAutoDrawable drawable) { GL2 gl = drawable.getGL().getGL2(); System.out.println(gl.glGetString(GL2.GL_VERSION)); vertexPos = Buffers.newDirectFloatBuffer(8); vertexPos.put(new float[]{0f, 1f}); vertexPos.put(new float[]{1f, 0f}); vertexPos.put(new float[]{0f, -1f}); vertexPos.put(new float[]{-1f, 0}); vertexPos.flip(); vertexCol = Buffers.newDirectFloatBuffer(12); vertexCol.put(new float[]{1f, 0f, 0f}); vertexCol.put(new float[]{0f, 1f, 0f}); vertexCol.put(new float[]{0f, 0f, 1f}); vertexCol.put(new float[]{1f, 1f, 1f}); vertexCol.flip(); vao = IntBuffer.allocate(1); vbo = IntBuffer.allocate(2); gl.glGenVertexArrays(1, vao); gl.glGenBuffers(2, vbo); int bytesPerFloat = Float.SIZE/Byte.SIZE; gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo.get(0)); gl.glBufferData(GL2.GL_ARRAY_BUFFER, vertexPos.capacity() * bytesPerFloat, vertexPos, GL2.GL_STATIC_DRAW); gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo.get(1)); gl.glBufferData(GL2.GL_ARRAY_BUFFER, vertexCol.capacity() * bytesPerFloat, vertexCol, GL2.GL_STATIC_DRAW); gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0); gl.glBindVertexArray(vao.get()); gl.glEnableVertexAttribArray(0); gl.glEnableVertexAttribArray(1); gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo.get(0)); gl.glVertexAttribPointer(0, 2, GL2.GL_FLOAT, false, 0, 0); gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo.get(1)); gl.glVertexAttribPointer(1, 3, GL2.GL_FLOAT, false, 0, 0); gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0); sc = new ShaderControl2(); sc.vSrc = sc.loadShader("v.txt"); sc.fSrc = sc.loadShader("f.txt"); } #Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } } ShaderControl2 code: package shaders; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.ByteBuffer; import java.nio.IntBuffer; import javax.media.opengl.*; public class ShaderControl2 { private int vertexShaderProg, fragmentShaderProg, shaderProg; public String[] vSrc, fSrc; public String[] loadShader(String sFile){ String line = new String(); StringBuilder fileContent = new StringBuilder(); try{ InputStream is = getClass().getResourceAsStream(sFile); BufferedReader br = new BufferedReader(new InputStreamReader(is)); while((line = br.readLine()) != null){ fileContent.append(line + "\n"); } is.close(); } catch(Exception e){ e.printStackTrace(); } System.out.println("Shader file content:\n" + fileContent); return new String[]{fileContent.toString()}; } public void attachShader(GL2 gl){ IntBuffer isCompiledVS = IntBuffer.allocate(1), isCompiledFS = IntBuffer.allocate(1), isLinked = IntBuffer.allocate(1); IntBuffer vLogLength = IntBuffer.allocate(1), fLogLength = IntBuffer.allocate(1), linkLogLength = IntBuffer.allocate(1); ByteBuffer vertexInfoLog, fragmentInfoLog, linkInfoLog; int size; vertexShaderProg = gl.glCreateShader(GL2.GL_VERTEX_SHADER); gl.glShaderSource(vertexShaderProg, 1, vSrc, null); gl.glCompileShader(vertexShaderProg); gl.glGetShaderiv(vertexShaderProg, GL2.GL_COMPILE_STATUS, isCompiledVS); if(isCompiledVS.get(0) == 0){ System.out.println("Failed to compile vertexShaderProg"); gl.glGetShaderiv(vertexShaderProg, GL2.GL_INFO_LOG_LENGTH, vLogLength); size = vLogLength.get(0); vertexInfoLog = ByteBuffer.allocate(size); gl.glGetShaderInfoLog(vertexShaderProg, size, vLogLength, vertexInfoLog); for(byte b : vertexInfoLog.array()){ System.err.print((char)b); } } fragmentShaderProg = gl.glCreateShader(GL2.GL_VERTEX_SHADER); gl.glShaderSource(fragmentShaderProg, 1, vSrc, null); gl.glCompileShader(fragmentShaderProg); gl.glGetShaderiv(fragmentShaderProg, GL2.GL_COMPILE_STATUS, isCompiledFS); if(isCompiledFS.get(0) == 0){ System.out.println("Failed to compile fragmentShaderProg"); gl.glGetShaderiv(fragmentShaderProg, GL2.GL_INFO_LOG_LENGTH, fLogLength); size = fLogLength.get(0); fragmentInfoLog = ByteBuffer.allocate(size); gl.glGetShaderInfoLog(fragmentShaderProg, size, fLogLength, fragmentInfoLog); for(byte b : fragmentInfoLog.array()){ System.err.print((char)b); } } shaderProg = gl.glCreateProgram(); gl.glAttachShader(shaderProg, vertexShaderProg); gl.glAttachShader(shaderProg, fragmentShaderProg); gl.glBindAttribLocation(shaderProg, 0, "in_Position"); gl.glBindAttribLocation(shaderProg, 1, "in_Color"); gl.glLinkProgram(shaderProg); gl.glGetProgramiv(shaderProg, GL2.GL_LINK_STATUS, isLinked); if(isLinked.get(0) == 0){ System.out.println("Failed to link shaderProg"); gl.glGetShaderiv(shaderProg, GL2.GL_INFO_LOG_LENGTH, linkLogLength); size = linkLogLength.get(0); linkInfoLog = ByteBuffer.allocate(size); gl.glGetProgramInfoLog(shaderProg, size, linkLogLength, linkInfoLog); for(byte b : linkInfoLog.array()){ System.err.print((char)b); } } } public int useShader(GL2 gl){ gl.glUseProgram(shaderProg); return shaderProg; } public void dontUseShader(GL2 gl){ gl.glUseProgram(0); } } Shader Code f.txt: #version 210 // It was expressed that some drivers required this next line to function properly precision highp float; in vec3 ex_Color; out vec4 gl_FragColor; void main(void) { // Pass through our original color with full opacity. gl_FragColor = vec4(ex_Color,1.0); } v.txt: #version 210 // in_Position was bound to attribute index 0 and in_Color was bound to attribute index 1 in vec2 in_Position; in vec3 in_Color; // We output the ex_Color variable to the next shader in the chain out vec3 ex_Color; void main(void) { // Since we are using flat lines, our input only had two points: x and y. // Set the Z coordinate to 0 and W coordinate to 1 gl_Position = vec4(in_Position.x, in_Position.y, 0.0, 1.0); // GLSL allows shorthand use of vectors too, the following is also valid: // gl_Position = vec4(in_Position, 0.0, 1.0); // We're simply passing the color through unmodified ex_Color = in_Color; }
The reason you see just white lines is because the shader program is not being used at all. I can't see where you call attach shaders (you never call sc.attachShader(gl), I added sc.attachShader(gl) at the end of the init method. Now a lot of errors will appear. In attachshader, when you create fragmentShaderProg you create it as a GL_VERTEX_SHADER, it should be GL_FRAGMENT_SHADER, and just below that you are sending the source of the vertex shader in place of the fragment shader. version 210 of the GLSL language doesn't exist, change it to version 130. The thing with the GLSL version is that it is independent from the OpenGL version, https://github.com/mattdesl/lwjgl-basics/wiki/GLSL-Versions #version 130 Now add to the end of the init method sc.attachShader(gl) and change fragmentShaderProg = gl.glCreateShader(GL2.GL_VERTEX_SHADER); gl.glShaderSource(fragmentShaderProg, 1, vSrc, null); for fragmentShaderProg = gl.glCreateShader(GL2.GL_FRAGMENT_SHADER); gl.glShaderSource(fragmentShaderProg, 1, fSrc, null); now it works.
Face coloring in java3d
Using java3d, how can I colorize not on a per vertex base but on a per face base? I try to learn about java3d but what Shape3d I did produce does not look as expected. I want to colorize different triangles in different colors, but I don't see how to do it. Texture looks like an overkill, and what's more, I haven't mastered this part at all. As far as I've seen Materials work on a complete GeometryArray, so are no good here. Per vertex colors won't do the trick.
I fond the solution. "per vertex colors" really are per vertex reference, so each vertex can have a different color for each of its faces. Here is a working example (regrettably not very small): package examples; import javax.media.j3d.Alpha; import javax.media.j3d.AmbientLight; import javax.media.j3d.Appearance; import javax.media.j3d.BoundingSphere; import javax.media.j3d.Bounds; import javax.media.j3d.BranchGroup; import javax.media.j3d.DirectionalLight; import javax.media.j3d.GeometryArray; import javax.media.j3d.IndexedTriangleArray; import javax.media.j3d.Node; import javax.media.j3d.PolygonAttributes; import javax.media.j3d.RotationInterpolator; import javax.media.j3d.Shape3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.View; import javax.media.j3d.ViewPlatform; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Vector3f; import com.sun.j3d.utils.geometry.GeometryInfo; import com.sun.j3d.utils.geometry.NormalGenerator; import com.sun.j3d.utils.universe.MultiTransformGroup; import com.sun.j3d.utils.universe.SimpleUniverse; import com.sun.j3d.utils.universe.ViewingPlatform; public class Example { public static void main(final String[] args) { new Example(); } public Example() { final SimpleUniverse universe = new SimpleUniverse(); final BranchGroup group = new BranchGroup(); final TransformGroup tg = new TransformGroup(); final BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0); final Node blob = createMonster(); { //to enable rotation tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); tg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); } // Create rotation to see all sides of the object final Transform3D btrans = new Transform3D(); btrans.rotX(1); final Transform3D ztrans = new Transform3D(); ztrans.rotZ(-1); btrans.mul(ztrans); final RotationInterpolator ri = createRotation(tg, bounds, btrans, 7000); tg.addChild(ri); tg.addChild(blob); // group.addChild(tg); // addLight(group, new Color3f(1f, 1f, 0f), new Vector3f(4.0f, +7.0f, -12.0f)); addLight(group, new Color3f(1f, 1f, 1f)); // final ViewingPlatform viewingPlatform = universe.getViewingPlatform(); final ViewPlatform view = viewingPlatform.getViewPlatform(); view.setViewAttachPolicy(View.NOMINAL_SCREEN); viewingPlatform.setNominalViewingTransform(); final MultiTransformGroup mtg = viewingPlatform.getMultiTransformGroup(); final TransformGroup vtg = mtg.getTransformGroup(0); final Transform3D t1 = btrans; vtg.getTransform(t1); t1.setScale(2); vtg.setTransform(t1); group.compile(); // add the group of objects to the Universe universe.addBranchGraph(group); } private Node createMonster() { final Shape3D child = createShape(); final Appearance fillAppNode = new Appearance(); final PolygonAttributes pAtt = new PolygonAttributes(); // avoid trouble with clockwise faces pAtt.setCullFace(PolygonAttributes.CULL_NONE); pAtt.setBackFaceNormalFlip(true); fillAppNode.setPolygonAttributes(pAtt); child.setAppearance(fillAppNode); return child; } private Shape3D createShape() { final Point3d[] points = new Point3d[] {// new Point3d(-1, 1, 0), // new Point3d(1, 1, 0), // new Point3d(1, -1, 0), // new Point3d(-1, -1, 0), // new Point3d(0, 0, 1), // }; final int[] idxs = new int[] {// the triangle faces 0, 1, 2,// 2, 3, 0,// 1, 0, 4,// 1, 2, 4,// 2, 3, 4,// 3, 0, 4 }; final IndexedTriangleArray ita = new IndexedTriangleArray(points.length, GeometryArray.COORDINATES | GeometryArray.COLOR_3, idxs.length); ita.setCoordinates(0, points); ita.setCoordinateIndices(0, idxs); //per vertex colors really are per vertex reference //so each vertex can have a different color for each of its faces final Color3f[] colors = new Color3f[] {// new Color3f(1, 0, 1),// new Color3f(0, 1, 0),// new Color3f(0, 0, 1),// new Color3f(1, 1, 0),// new Color3f(1, 1, 1),// }; ita.setColors(0, colors); ita.setColorIndices(0, idxs); ita.setColorIndices(0, new int[] { 0, 0, 0, 1, 1, 1 }); // final GeometryInfo gi = new GeometryInfo(ita); //also generate normal vectors so that the surface can be light final NormalGenerator normalGenerator = new NormalGenerator(); normalGenerator.generateNormals(gi); final GeometryArray geometryArray = gi.getGeometryArray(); return new Shape3D(geometryArray); } private RotationInterpolator createRotation(final TransformGroup objScale, final Bounds bounds, final Transform3D btrans, final long milis) { final Alpha alpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0, milis, 0, 0, 0, 0, 0); final RotationInterpolator ri = new RotationInterpolator(alpha, objScale, btrans, 0.0f, (float) Math.PI * 2.0f); ri.setSchedulingBounds(bounds); return ri; } private void addLight(final BranchGroup group, final Color3f light1Color, final Vector3f ligthDirection) { { final BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0); final DirectionalLight light1 = new DirectionalLight(light1Color, ligthDirection); light1.setInfluencingBounds(bounds); group.addChild(light1); } } private void addLight(final BranchGroup group, final Color3f light1Color) { { final BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0); final AmbientLight light1 = new AmbientLight(light1Color); light1.setInfluencingBounds(bounds); group.addChild(light1); } } }
You will have to draw each face separately, assigning a color to each. For example: Appearance polygon1Appearance = new Appearance(); // set your color here QuadArray polygon1 = new QuadArray (4, QuadArray.COORDINATES); polygon1.setCoordinate(0, new Point3f (0f, 0f, 0f)); polygon1.setCoordinate(1, new Point3f (2f, 0f, 0f)); polygon1.setCoordinate(2, new Point3f (2f, 3f, 0f)); polygon1.setCoordinate(3, new Point3f (0f, 3f, 0f)); objRoot.addChild(new Shape3D(polygon1, polygon1Appearance));
How to play music using libgdx
I have had trouble playing music using libgdx. My code is as follows: package com.me.fixGame; import java.util.Random; import com.badlogic.gdx.ApplicationListener; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.audio.Sound; import com.badlogic.gdx.graphics.GL10; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; //import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.utils.Scaling; import com.sun.jmx.snmp.tasks.Task; public class fixGame implements ApplicationListener { SpriteBatch batch; SpriteBatch spriteBatch; Texture trash; Texture paper; SpriteBatch spritebatch; Vector2 position; Vector2 pas; boolean collide; boolean countMe=false; Vector2 size; Vector2 size2; Vector2 pos; Rectangle bounds; float posSpeed=30; Rectangle bounds2; float delay = 1; // seconds boolean counted= false; int score = 3; //Texture Gogreen; String myScore; Texture background; CharSequence str = "Lives left: 3"; // = myScore; CharSequence line = "Score: 0"; // = myScore; String myLife; int life=0; BitmapFont font; float x; float y; Sound sound; boolean collision = false; #Override public void create() { //Gogreen = new Texture(Gdx.files.internal("data/gogreenNow.jpg")); background = new Texture(Gdx.files.internal("data/trash.png")); x= background.getWidth(); y=background.getHeight(); //float delaySeconds = 1; spriteBatch = new SpriteBatch(); trash = new Texture(Gdx.files.internal("data/trash.png")); paper = new Texture(Gdx.files.internal("data/paper1.jpg")); sound = Gdx.audio.newSound(Gdx.files.internal("data/testjava.mp3")); position = new Vector2(100, 50); pos = new Vector2(54, 14); batch = new SpriteBatch(); BitmapFont font = new BitmapFont(); size2 = new Vector2(trash.getWidth() ,trash.getHeight() ); //size2.y = trash.getHeight(); //size2.x = trash.getWidth(); size = new Vector2(paper.getWidth() ,paper.getHeight()); bounds= new Rectangle(pos.x, pos.y, size.x, size.y); bounds2= new Rectangle(position.x, position.y, size2.x, size2.y); } #Override public void dispose() { } public void update(){ bounds.set(pos.x, pos.y, size.x, size.y); bounds2.set(position.x, position.y, size2.x, size2.y); float pos1=Gdx.input.getAccelerometerX(); //if(pos1<0) // pos1=(-1)*pos1; position.x = position.x - 5*pos1; } #Override public void render() { sound.play(0.5f); sound.dispose(); if(bounds.overlaps(bounds2)){ collision=true; counted=true; }else{ collision=false; } if(collision==true){ } if(pos.y<640){ counted=false; } else if(pos.y > 640 && collision==false && counted==false){ counted=true; score= score-1; myScore = "Lives left: " + score; str = myScore; } if(bounds.overlaps(bounds2)){ countMe=true; life= life+50; myLife = "Score: " + life; line = myLife; } if(position.x<0){ position.x= position.x+11; } if(position.x>425){ position.x= position.x-11; } update(); Gdx.gl.glClearColor(1, 1, 1, 1); Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); pos.y=pos.y-posSpeed; //posSpeed = posSpeed+(2/3); if(pos.y<0){ pos.y = 700; Random randomGenerator = new Random(); pos.x = randomGenerator.nextInt(500); } BitmapFont font = new BitmapFont(); batch.begin(); batch.draw(background, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); if (!collision) { batch.draw(paper, pos.x, pos.y); } //batch.draw(paper, pos.x, pos.y); batch.draw(trash, position.x, position.y); font.setScale(3); font.setColor(0.0f, 0.0f, 1.0f,1.0f); font.draw(batch, str, 300,900); font.draw(batch, line, 300, 950); batch.end(); font.dispose(); } #Override public void resize(int width, int height) { } #Override public void pause() { } #Override public void resume() { } } My sound file I call over here: sound = Gdx.audio.newSound(Gdx.files.internal("data/testjava.mp3")); And the code I use to play it is: sound.play(); sound.dispose(); For some reason it does not work on my desktop and my phone. I tested the the sound file actually had some sound in it.
You need to get rid of the sound.dispose(); call right after playing the sound, since it will dispose the sound file ;) Just put it into your game's dispose(); method, so it will get removed after the game is done. Also, you shouldn't call sound.play(0.5f); within your render-loop. Remember this function will get called about 60 times a second and you don't want to have the sound start 60 times a second. So if it's some kind of sound effect that comes with a special event, like firing a bullet or hitting a target etc, just call sound.play(); one time, when you are actually firing the event. https://github.com/libgdx/libgdx/wiki/Sound-effects If you want to play background music, you should try streaming the music file. The wiki is awesome for that: https://github.com/libgdx/libgdx/wiki/Streaming-music Hope it helps :)
OpenGL ES Object is Displaying Strangely / Distorted - Android
EDIT OK - I grabbed a device and..guess what...it displays correctly ? Does anyone know why this would be happening on the simulator only ? Thank you. I am trying to draw an object using glDrawElements on Android. I am using the code below to read in my vertice and indice data and then draw the object in my render method. I am testing this on the simulator rather than a real device. This is my scene object code : import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; import javax.microedition.khronos.opengles.GL10; public class SceneObject { public FloatBuffer mVertexBuffer; public FloatBuffer mTextureBuffer; public ShortBuffer indexBuffer; public FloatBuffer mMatriceBuffer; public FloatBuffer mPivotBuffer; public short[] indicesTest = {0,1,2,3,4,5,3,5,6,7,5,8,7,8,9,10,7,9,11,10,9,12,1,0,13,12,14,15,13,14,14,10,11,15,14,11,0,14,12,16,17,18,19,16,18,18,20,19,21,16,19,22,21,19,22,19,23,4,24,25,25,26,27,25,27,28,4,25,28,5,4,28,5,28,8,29,30,31,29,31,19,29,19,20,32,33,31,32,31,30,32,34,33,35,22,23,36,35,23,37,36,23,37,23,38,39,37,38,40,39,38,41,40,38,41,38,1,42,41,1,12,43,1,42,1,43,17,27,26,26,18,17,44,45,46,46,47,44,48,49,50,51,52,53,53,54,51,55,51,54,54,56,55,57,48,50,50,58,57,52,59,60,60,53,52,59,44,47,47,60,59,61,62,63,63,64,61,65,66,67,67,68,65,69,70,71,71,72,69,66,69,72,72,67,66,73,65,68,68,74,73,70,75,76,76,71,70,75,61,64,64,76,75,77,78,79,79,80,77,81,82,62,62,61,81,83,81,61,61,75,83,84,63,62,62,82,84,63,84,85,86,87,88,89,90,91,92,93,87,87,86,92,94,95,96,96,97,94,98,99,100,100,101,98,102,103,104,104,105,102,106,107,108,108,109,106,110,111,112,78,77,113,114,115,78,112,111,116,117,118,115,119,116,120,121,122,123,123,124,121,125,126,127,127,128,125,129,130,131,132,133,5,5,133,6,5,134,135,135,134,136,134,137,136,137,138,136,129,139,130,139,140,141,140,142,141,137,141,138,141,142,138,141,130,139,143,144,145,144,146,145,147,145,146,144,148,146,148,149,146,146,149,150,151,132,152,153,152,154,154,152,155,152,132,155,132,5,155,155,5,135,156,157,158,158,157,146,146,157,147,159,160,158,158,160,156,34,160,159,149,161,150,161,162,150,162,163,150,150,163,164,163,165,164,165,166,164,166,167,164,164,167,129,167,168,129,169,139,129,129,168,169,154,143,153,145,153,143,170,171,172,173,172,171,174,175,176,177,178,179,180,179,178,178,181,180,182,180,181,175,183,176,184,176,183,185,177,186,179,186,177,171,185,173,186,173,185,187,188,189,190,189,188,191,192,193,194,193,192,195,196,197,198,197,196,196,191,198,193,198,191,192,199,194,200,194,199,201,195,202,197,202,195,188,201,190,202,190,201,203,204,205,206,205,204,207,208,187,188,187,208,208,209,188,201,188,209,189,210,187,207,187,210,210,189,211,212,213,214,215,216,217,218,219,220,221,220,219,222,223,224,225,226,227,228,229,230,231,230,229,232,233,234,235,236,237,238,239,240,241,242,243,123,244,124,245,246,203,204,203,246,247,248,203,249,250,251,252,253,247,248,247,253,159,33,34,254,255,256,256,257,254,255,244,123,123,256,255,244,258,121,121,124,244,259,260,125,125,128,259}; public float[] verticeTest = {20360.8f,20679.5f,611.547f,24248.7f,13527f,1074.93f,24207.4f,23005.5f,1503.19f,9819.59f,14845.7f,8.81875f,11126.3f,13982.2f,32.0718f,8379.01f,17678.5f,0.00115749f,8379.01f,15141.6f,0.00111471f,12137.8f,17973.8f,60.0461f,14591.9f,14509.2f,164.113f,15621.5f,15846.6f,223.075f,15136.7f,18549.5f,194.186f,16918.2f,16705.3f,310.215f,21081.8f,15846.6f,687.576f,19789f,16705.3f,554.435f,18467.9f,19868.7f,433.258f,18354.3f,17001.2f,423.539f,14591.9f,7402.34f,164.113f,13930.5f,9087.62f,131.015f,13039.7f,9096.18f,92.3283f,19110.4f,-8011.43f,490.311f,12811.7f,7228.03f,83.5128f,15621.5f,6064.9f,223.074f,16918.2f,5206.21f,310.215f,21807.5f,-426.492f,768.658f,11221.5f,13854f,34.3347f,12150f,12649.6f,60.4329f,12811.7f,10964.3f,83.513f,13702.6f,10955.8f,120.472f,13930.5f,12823.9f,131.015f,12150f,5542.76f,60.4327f,11119f,4205.31f,31.902f,15341.7f,-15792.9f,206.155f,9819.59f,3346.62f,8.81857f,10735.6f,-21752.5f,23.5976f,8379.01f,3050.73f,0.000981022f,18354.3f,4910.32f,423.538f,19789f,5206.21f,554.434f,21081.8f,6064.9f,687.576f,23336.1f,6399.27f,954.364f,22106.6f,7402.34f,803.393f,22764f,9087.62f,882.485f,22990.5f,10955.8f,910.595f,22764f,12823.9f,882.485f,22106.6f,14509.2f,803.393f,24248.7f,8492.36f,-3249.03f,24207.4f,17415.3f,-3297.97f,24207.4f,23005.5f,1503.19f,24248.7f,13527f,1074.93f,12728.3f,-24463.4f,-4243.56f,15341.7f,-20827.5f,-4117.81f,15341.7f,-15792.9f,206.155f,19110.4f,-13046f,-3833.65f,21807.5f,-5461.09f,-3555.3f,21807.5f,-426.492f,768.658f,19110.4f,-8011.43f,490.311f,15341.7f,-20827.5f,-4117.81f,15341.7f,-15792.9f,206.155f,10735.6f,-26787.1f,-4300.36f,10735.6f,-21752.5f,23.5976f,23336.1f,1364.68f,-3369.59f,23336.1f,6399.27f,954.364f,24883.8f,8123.11f,-2819.08f,24859.5f,16025.8f,-2803.12f,24207.4f,17415.3f,-3297.97f,24248.7f,8492.36f,-3249.03f,13363.4f,-24832.7f,-3813.62f,15976.8f,-21196.8f,-3687.86f,15341.7f,-20827.5f,-4117.81f,12728.3f,-24463.4f,-4243.56f,19745.5f,-13415.3f,-3403.7f,22442.7f,-5830.35f,-3125.36f,21807.5f,-5461.09f,-3555.3f,19110.4f,-13046f,-3833.65f,10915.8f,-27847.5f,-3863.23f,10735.6f,-26787.1f,-4300.36f,23222.6f,-2518.03f,-3057.67f,23336.1f,1364.68f,-3369.59f,10301.8f,-40240.8f,-15469.8f,10482f,-40907.1f,-14694f,10915.8f,-27847.5f,-3863.23f,10735.6f,-26787.1f,-4300.36f,25648.8f,8121.58f,-2817.31f,25624.5f,16024.2f,-2801.34f,24056.1f,-2550.94f,-3019.36f,25678.7f,16560.2f,-2907.29f,25594.2f,17951.2f,-3237.71f,25624.5f,-88046.9f,-92182.7f,25678.7f,-87767f,-92508.6f,25678.7f,16560.2f,-2907.29f,25678.7f,16560.2f,-2907.29f,25624.5f,16024.2f,-2801.34f,25624.5f,-88046.9f,-92182.7f,25624.5f,-88413.1f,-92497.2f,25678.7f,-88133.2f,-92823.1f,24765.7f,-88413.1f,-92497.2f,24820f,-88133.2f,-92823.1f,25678.7f,-88133.2f,-92823.1f,25624.5f,-88413.1f,-92497.2f,24765.7f,-89895.8f,-93770.7f,24820f,-89615.9f,-94096.6f,24820f,-88133.2f,-92823.1f,24765.7f,-88413.1f,-92497.2f,25678.7f,-89596.5f,-94079.9f,25678.7f,-88133.2f,-92823.1f,24820f,-88133.2f,-92823.1f,24820f,-89615.9f,-94096.6f,23222.6f,-93458.9f,-81162.2f,24056.1f,-93491.8f,-81123.9f,24056.1f,-2550.94f,-3019.36f,23222.6f,-2518.03f,-3057.67f,10579.6f,-102089f,-68973.2f,10579f,-102925f,-68042.7f,10482f,-40907.1f,-14694f,10579.6f,-102089f,-68973.2f,10579f,-102925f,-68042.7f,10482f,-41291.8f,-14246f,10579f,-102925f,-68042.7f,10489f,-103571f,-67018.6f,10482f,-41713.9f,-13886.7f,10482f,-41291.8f,-14246f,10489f,-103571f,-67018.6f,8379.01f,-102145f,-69021.7f,10579.6f,-102089f,-68973.2f,10301.8f,-40240.8f,-15469.8f,8379.01f,-68082.6f,-39554.7f,8379.01f,-101057f,-70411.1f,10735.6f,-101057f,-70411.1f,10579.6f,-102089f,-68973.2f,8379.01f,-102145f,-69021.7f,-7490.7f,13527f,1074.93f,-3602.79f,20679.5f,611.547f,-7449.35f,23005.5f,1503.19f,5631.77f,13982.2f,32.0718f,6938.43f,14845.7f,8.81875f,4620.19f,17973.8f,60.0461f,2166.16f,14509.2f,164.113f,1136.48f,15846.6f,223.075f,1621.29f,18549.5f,194.186f,-160.178f,16705.3f,310.215f,-4323.73f,15846.6f,687.576f,-3030.97f,16705.3f,554.435f,-1709.92f,19868.7f,433.258f,-1596.32f,17001.2f,423.539f,2827.51f,9087.62f,131.015f,2166.16f,7402.34f,164.113f,3718.3f,9096.18f,92.3283f,-2352.36f,-8011.43f,490.311f,3946.3f,7228.03f,83.5128f,1136.48f,6064.9f,223.074f,-160.182f,5206.21f,310.215f,-5049.53f,-426.492f,768.658f,5536.51f,13854f,34.3347f,4608.07f,12649.6f,60.4329f,3946.3f,10964.3f,83.513f,3055.44f,10955.8f,120.472f,2827.51f,12823.9f,131.015f,5639.04f,4205.31f,31.902f,4608.07f,5542.76f,60.4327f,1416.3f,-15792.9f,206.155f,6022.45f,-21752.5f,23.5976f,6938.43f,3346.62f,8.81857f,-1596.32f,4910.32f,423.538f,-3030.97f,5206.21f,554.434f,-4323.73f,6064.9f,687.576f,-6578.08f,6399.27f,954.364f,-5348.56f,7402.34f,803.393f,-6006f,9087.62f,882.485f,-6232.44f,10955.8f,910.595f,-6006f,12823.9f,882.485f,-5348.57f,14509.2f,803.393f,-7449.35f,17415.3f,-3297.97f,-7490.7f,8492.36f,-3249.03f,-7449.35f,23005.5f,1503.19f,-7490.7f,13527f,1074.93f,1416.3f,-20827.5f,-4117.81f,4029.77f,-24463.4f,-4243.56f,1416.3f,-15792.9f,206.155f,-5049.53f,-5461.09f,-3555.3f,-2352.36f,-13046f,-3833.65f,-5049.53f,-426.492f,768.658f,-2352.36f,-8011.43f,490.311f,1416.3f,-20827.5f,-4117.81f,1416.3f,-15792.9f,206.155f,6022.45f,-26787.1f,-4300.36f,6022.45f,-21752.5f,23.5976f,-6578.08f,1364.68f,-3369.59f,-6578.08f,6399.27f,954.364f,-8101.47f,16025.8f,-2803.12f,-8125.81f,8123.11f,-2819.08f,-7449.35f,17415.3f,-3297.97f,-7490.7f,8492.36f,-3249.03f,781.19f,-21196.8f,-3687.86f,3394.66f,-24832.7f,-3813.62f,1416.3f,-20827.5f,-4117.81f,4029.77f,-24463.4f,-4243.56f,-5684.64f,-5830.35f,-3125.36f,-2987.47f,-13415.3f,-3403.7f,-5049.53f,-5461.09f,-3555.3f,-2352.36f,-13046f,-3833.65f,5842.26f,-27847.5f,-3863.23f,6022.45f,-26787.1f,-4300.36f,-6464.54f,-2518.03f,-3057.67f,-6578.08f,1364.68f,-3369.59f,6276.06f,-40907.1f,-14694f,6456.25f,-40240.8f,-15469.8f,5842.26f,-27847.5f,-3863.23f,6022.45f,-26787.1f,-4300.36f,-8866.45f,16024.2f,-2801.34f,-8890.79f,8121.58f,-2817.31f,-7298.12f,-2550.94f,-3019.36f,-8920.72f,16560.2f,-2907.29f,-8836.13f,17951.2f,-3237.71f,-8920.72f,-87767f,-92508.6f,-8866.45f,-88046.9f,-92182.7f,-8920.72f,16560.2f,-2907.29f,-8866.45f,16024.2f,-2801.34f,-8920.72f,16560.2f,-2907.29f,-8866.45f,-88046.9f,-92182.7f,-8920.72f,-88133.2f,-92823.1f,-8866.45f,-88413.1f,-92497.2f,-8920.72f,-87767f,-92508.6f,-8866.45f,-88046.9f,-92182.7f,-8061.98f,-88133.2f,-92823.1f,-8007.72f,-88413.1f,-92497.2f,-8920.72f,-88133.2f,-92823.1f,-8866.45f,-88413.1f,-92497.2f,-8920.72f,-88133.2f,-92823.1f,-8007.72f,-88413.1f,-92497.2f,-8061.98f,-89615.9f,-94096.6f,-8007.72f,-89895.8f,-93770.7f,-8061.98f,-88133.2f,-92823.1f,-8007.72f,-88413.1f,-92497.2f,-8920.72f,-88133.2f,-92823.1f,-8920.72f,-89596.5f,-94079.9f,-8061.98f,-88133.2f,-92823.1f,-8061.98f,-89615.9f,-94096.6f,-8061.98f,-88133.2f,-92823.1f,-8920.72f,-89596.5f,-94079.9f,-7298.12f,-93491.8f,-81123.9f,-6464.54f,-93458.9f,-81162.2f,-7298.12f,-2550.94f,-3019.36f,-6464.54f,-2518.03f,-3057.67f,-7298.12f,-2550.94f,-3019.36f,-6464.54f,-93458.9f,-81162.2f,6456.25f,-40240.8f,-15469.8f,6179.01f,-102925f,-68042.7f,6178.41f,-102089f,-68973.2f,6276.06f,-41291.8f,-14246f,6179.01f,-102925f,-68042.7f,6179.01f,-102925f,-68042.7f,6276.06f,-40907.1f,-14694f,6179.01f,-102925f,-68042.7f,6276.06f,-41713.9f,-13886.7f,6269.01f,-103571f,-67018.6f,6022.45f,-21752.5f,23.5976f,6022.45f,-26787.1f,-4300.36f,10735.6f,-26787.1f,-4300.36f,10735.6f,-21752.5f,23.5976f,6178.41f,-102089f,-68973.2f,6178.41f,-102089f,-68973.2f,6022.45f,-101057f,-70411.1f }; public String objectName; public int triangleCount; public int verticeCount; public float[] vertices; public float[] normals; public float[] textures; public short[] indices; public float[] matrices; public float[] pivots; public float[] animations; public void awake() { ByteBuffer vbb = ByteBuffer.allocateDirect(verticeTest.length * 4); vbb.order(ByteOrder.nativeOrder()); mVertexBuffer = vbb.asFloatBuffer(); mVertexBuffer.put(verticeTest); mVertexBuffer.position(0); ByteBuffer tbb = ByteBuffer.allocateDirect(textures.length * 4); tbb.order(ByteOrder.nativeOrder()); mTextureBuffer = tbb.asFloatBuffer(); mTextureBuffer.put(textures); mTextureBuffer.position(0); //short has 2 bytes ByteBuffer ibb = ByteBuffer.allocateDirect(indicesTest.length*2); ibb.order(ByteOrder.nativeOrder()); indexBuffer = ibb.asShortBuffer(); indexBuffer.put(indicesTest); indexBuffer.position(0); verticeCount = (triangleCount*3); } public void draw(GL10 gl) { System.out.println("Draw Method Called in Object"); gl.glEnable(GL10.GL_TEXTURE_2D); //workaround bug 3623 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer); System.out.println("Triangle Vertice Count is "+verticeCount); int x = vertices.length; System.out.println("Rendering following number of vertices "+x); int y = indices.length; System.out.println("Rendering following number of indices "+y); gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer); } } And here is the code where I call the draw method : import java.nio.FloatBuffer; import java.util.ArrayList; import java.util.Iterator; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.opengl.GLSurfaceView; import android.opengl.GLU; class GLRenderer implements GLSurfaceView.Renderer { private static final String TAG = "GLRenderer"; private final Context context; private final GLCube cube = new GLCube(); private long startTime; private long fpsStartTime; private long numFrames; SceneObject drawObject; SceneObject object; //Used for object position and rotation. float zRotation; float xRotation; float yRotation; float kxRotation = 0.0f; float kyRotation = 0.0f; ArrayList<SceneObject> sceneObjects = new ArrayList<SceneObject>(); boolean SEE_THRU = false; GLRenderer(Context context) { this.context = context; } public void onSurfaceCreated(GL10 gl, EGLConfig config) { // Setup any OpenGL Options that are required. gl.glEnable(GL10.GL_DEPTH_TEST); gl.glDepthFunc(GL10.GL_LEQUAL); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); gl.glEnable(GL10.GL_TEXTURE_2D); if (SEE_THRU) { gl.glDisable(GL10.GL_DEPTH_TEST); gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); } //Optional - disable dither to boost peformance. //gl.glDisable(GL10.GL_DITHER); //Dithering enabled by default. //Turn on the lights. float lightAmbient[] = new float[] { 0.2f, 0.2f, 0.2f, 1}; float lightDiffuse[] = new float[] {1, 1, 1, 1}; float[] lightPos = new float[] {1 ,1 ,1 , 1}; gl.glEnable(GL10.GL_LIGHTING); gl.glEnable(GL10.GL_LIGHT0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbient, 0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuse, 0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPos, 0); //Specify which materials we should use. float matAmbient[] = new float[] {1, 1, 1, 1}; float matDiffuse[] = new float[] {1, 1, 1, 1}; gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, matAmbient, 0); gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, matDiffuse, 0); } public void onSurfaceChanged(GL10 gl, int width, int height) { //Define the view frustrum gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL10.GL_PROJECTION); float ratio = (float)width/height; gl.glLoadIdentity(); //gl.glOrthof(0, 480f, 800f, 0, 0, 1); GLU.gluPerspective(gl, 45.0f, ratio, 1.0f, 100f); } public void onDrawFrame (GL10 gl) { //Defs for rotation of object. float kzRotation = 0.0f; kyRotation +=1.0f; kxRotation =280.0f; gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); SceneObject object = sceneObjects.get(13); //Get the object //Position the model. gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0.0f, 0.0f, -30.0f); gl.glScalef(0.0001f, 0.0001f, 0.0001f); zRotation = kzRotation; xRotation = kxRotation; yRotation = kyRotation; gl.glRotatef(yRotation, 0.0f, 1.0f, 0.0f); gl.glRotatef(xRotation, 1.0f, 0.0f, 0.0f); gl.glRotatef(zRotation, 0.0f, 0.0f, 1.0f); object.draw(gl); } } } The problem is that the object is not displaying as it should, but instead looks warped and squashed. Can anyone spot what might be wrong ? EDIT - Changed the onSufaceChanged method as per Tim's answer below, however no improvement. I've added an image of how the object is rendering on Android and the same object rendering correct on the iPhone. The most noticeable problem is that the "legs" should be straight and not bend and overall the object should be much longer. I'm sure the vertices and indices in the code above are correct (they are exactly the same as the iPhone ones). In case it is relevant here is how I am setting up the surfaceview / view: public class SaxParserActivity extends Activity { /** Called when the activity is first created. */ ArrayList<SceneObject> sceneObjects = new ArrayList<SceneObject>(); #Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.main); GLView view; view = new GLView(this, sceneObjects); //Pass down our sceneObjects into the view class. //view.sceneObjects = sceneObjects; setContentView(view); } } class GLView extends GLSurfaceView { private final GLRenderer renderer; ArrayList<SceneObject> sceneObjects = new ArrayList<SceneObject>(); GLView(Context context, ArrayList<SceneObject> sceneObjects) { super (context); //Uncomment this to turn on error-checking and logging. //setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS); renderer = new GLRenderer(context); //Pass down our sceneObjects. renderer.sceneObjects = sceneObjects; setRenderer(renderer); } }
I'm a bit confused by what you're doing. Why do you wipe on the projection matrix in onDrawFrame, after setting it in onSurfaceChanged? You should set projection in onSurfaceChanged like so: public void onSurfaceChanged(GL10 gl, int width, int height) { gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); //make sure to reset before glOrthof gl.glOrthof(0, 320f, 480f, 0, 0, 1); } And then change back to modelview and don't disturb the projection matrix during onDrawFrame. You'll probably need to recalibrate your scale and translate in onDrawFrame as well after doing this.