/******************************************************************************* * Copyright 2011 See AUTHORS file. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. ******************************************************************************/ package com.badlogic.gdx.graphics.glutils; import java.nio.FloatBuffer; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.GL10; import com.badlogic.gdx.math.Matrix4; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.utils.BufferUtils; import com.badlogic.gdx.utils.GdxRuntimeException; /** * An ImmediateModeRenderer allows you to perform immediate mode rendering as you were accustomed to in your desktop * OpenGL environment. In order to draw something you first have to call {@link ImmediateModeRenderer10#begin(int)} with * the primitive type you want to render. Next you specify as many vertices as you want by first defining the vertex * color, normal and texture coordinates followed by the vertex position which finalizes the definition of a single * vertex. When you are done specifying the geometry you have to call {@link ImmediateModeRenderer10#end()} to make the * renderer render the geometry. Internally the renderer uses vertex arrays to render the provided geometry. This is not * the best performing way to do this so use this class only for non performance critical low vertex count geometries * while debugging. * * Note that this class of course only works with OpenGL ES 1.x. * * @author mzechner */ public class ImmediateModeRenderer10 implements ImmediateModeRenderer { /** the primitive type **/ private int primitiveType; /** the vertex position array and buffer **/ private float[] positions; private FloatBuffer positionsBuffer; /** the vertex color array and buffer **/ private float[] colors; private FloatBuffer colorsBuffer; /** the vertex normal array and buffer **/ private float[] normals; private FloatBuffer normalsBuffer; /** the texture coordinate array and buffer **/ private float[] texCoords; private FloatBuffer texCoordsBuffer; /** the current vertex attribute indices **/ private int idxPos = 0; private int idxCols = 0; private int idxNors = 0; private int idxTexCoords = 0; private boolean hasCols; private boolean hasNors; private boolean hasTexCoords; private final int maxVertices; private int numVertices; /** Constructs a new ImmediateModeRenderer */ public ImmediateModeRenderer10() { this(2000); } /** Constructs a new ImmediateModeRenderer */ public ImmediateModeRenderer10(int maxVertices) { this.maxVertices = maxVertices; if (Gdx.graphics.isGL20Available()) throw new GdxRuntimeException("ImmediateModeRenderer can only be used with OpenGL ES 1.0/1.1"); this.positions = new float[3 * maxVertices]; this.positionsBuffer = BufferUtils.newFloatBuffer(3 * maxVertices); this.colors = new float[4 * maxVertices]; this.colorsBuffer = BufferUtils.newFloatBuffer(4 * maxVertices); this.normals = new float[3 * maxVertices]; this.normalsBuffer = BufferUtils.newFloatBuffer(3 * maxVertices); this.texCoords = new float[2 * maxVertices]; this.texCoordsBuffer = BufferUtils.newFloatBuffer(2 * maxVertices); } public void begin(Matrix4 projModelView, int primitiveType) { GL10 gl = Gdx.gl10; gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadMatrixf(projModelView.val, 0); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); begin(primitiveType); } /** * Starts a new list of primitives. The primitiveType specifies which primitives to draw. Can be any of * GL10.GL_TRIANGLES, GL10.GL_LINES and so on. A maximum of 6000 vertices can be drawn at once. * * @param primitiveType * the primitive type. */ public void begin(int primitiveType) { this.primitiveType = primitiveType; numVertices = 0; idxPos = 0; idxCols = 0; idxNors = 0; idxTexCoords = 0; hasCols = false; hasNors = false; hasTexCoords = false; } /** * Specifies the color of the current vertex * * @param r * the red component * @param g * the green component * @param b * the blue component * @param a * the alpha component */ public void color(float r, float g, float b, float a) { colors[idxCols] = r; colors[idxCols + 1] = g; colors[idxCols + 2] = b; colors[idxCols + 3] = a; hasCols = true; } /** * Specifies the normal of the current vertex * * @param x * the x component * @param y * the y component * @param z * the z component */ public void normal(float x, float y, float z) { normals[idxNors] = x; normals[idxNors + 1] = y; normals[idxNors + 2] = z; hasNors = true; } /** * Specifies the texture coordinates of the current vertex * * @param u * the u coordinate * @param v * the v coordinate */ public void texCoord(float u, float v) { texCoords[idxTexCoords] = u; texCoords[idxTexCoords + 1] = v; hasTexCoords = true; } /** * Specifies the position of the current vertex and finalizes it. After a call to this method you will effectively * define a new vertex afterwards. * * @param x * the x component * @param y * the y component * @param z * the z component */ public void vertex(float x, float y, float z) { positions[idxPos++] = x; positions[idxPos++] = y; positions[idxPos++] = z; if (hasCols) idxCols += 4; if (hasNors) idxNors += 3; if (hasTexCoords) idxTexCoords += 2; numVertices++; } public int getNumVertices() { return numVertices; } public int getMaxVertices() { return maxVertices; } /** Renders the primitives just defined. */ public void end() { if (idxPos == 0) return; GL10 gl = Gdx.gl10; gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); positionsBuffer.clear(); BufferUtils.copy(positions, positionsBuffer, idxPos, 0); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, positionsBuffer); if (hasCols) { gl.glEnableClientState(GL10.GL_COLOR_ARRAY); colorsBuffer.clear(); BufferUtils.copy(colors, colorsBuffer, idxCols, 0); gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorsBuffer); } if (hasNors) { gl.glEnableClientState(GL10.GL_NORMAL_ARRAY); normalsBuffer.clear(); BufferUtils.copy(normals, normalsBuffer, idxNors, 0); gl.glNormalPointer(GL10.GL_FLOAT, 0, normalsBuffer); } if (hasTexCoords) { gl.glClientActiveTexture(GL10.GL_TEXTURE0); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); texCoordsBuffer.clear(); BufferUtils.copy(texCoords, texCoordsBuffer, idxTexCoords, 0); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texCoordsBuffer); } gl.glDrawArrays(primitiveType, 0, idxPos / 3); if (hasCols) gl.glDisableClientState(GL10.GL_COLOR_ARRAY); if (hasNors) gl.glDisableClientState(GL10.GL_NORMAL_ARRAY); if (hasTexCoords) gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); } public void vertex(Vector3 point) { vertex(point.x, point.y, point.z); } @Override public void dispose() { } }