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