/**
* Copyright 2012 Jason Sorensen (sorensenj@smert.net)
*
* 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 net.smert.frameworkgl.opengl.renderable.shared;
import net.smert.frameworkgl.opengl.GL;
import net.smert.frameworkgl.opengl.VertexArrayObject;
import net.smert.frameworkgl.opengl.VertexBufferObject;
import net.smert.frameworkgl.opengl.VertexBufferObjectInterleaved;
import net.smert.frameworkgl.opengl.mesh.Mesh;
import net.smert.frameworkgl.opengl.renderable.AbstractRenderable;
import net.smert.frameworkgl.opengl.renderable.Renderable;
import net.smert.frameworkgl.opengl.renderable.RenderableConfiguration;
/**
*
* @author Jason Sorensen <sorensenj@smert.net>
*/
public abstract class AbstractVertexArrayObjectInterleavedRenderable extends AbstractRenderable {
protected boolean hasColors;
protected boolean hasNormals;
protected boolean hasTexCoords;
protected boolean hasVertices;
protected int bufferUsage;
protected int renderableConfigID;
protected RenderCall renderCall;
protected VertexArrayObject vao;
protected VertexBufferObject vboVertexIndex;
protected VertexBufferObjectInterleaved vboInterleaved;
public AbstractVertexArrayObjectInterleavedRenderable() {
hasColors = false;
hasNormals = false;
hasTexCoords = false;
hasVertices = false;
bufferUsage = -1;
renderableConfigID = -1;
renderCall = null;
vboVertexIndex = null;
vboInterleaved = null;
}
protected void bindGL3() {
// Bind VAO
Renderable.bindState.bindVAO(vao.getVaoID());
// Bind VBO for each type
if (hasColors) {
GL.vboHelper.enableVertexAttribArray(Renderable.bindState.getColorIndex());
} else {
GL.vboHelper.disableVertexAttribArray(Renderable.bindState.getColorIndex());
}
if (hasNormals) {
GL.vboHelper.enableVertexAttribArray(Renderable.bindState.getNormalIndex());
} else {
GL.vboHelper.disableVertexAttribArray(Renderable.bindState.getNormalIndex());
}
if (hasTexCoords) {
GL.vboHelper.enableVertexAttribArray(Renderable.bindState.getTexCoord0Index());
} else {
GL.vboHelper.disableVertexAttribArray(Renderable.bindState.getTexCoord0Index());
}
if (hasVertices) {
GL.vboHelper.enableVertexAttribArray(Renderable.bindState.getVertexIndex());
} else {
GL.vboHelper.disableVertexAttribArray(Renderable.bindState.getVertexIndex());
}
if (vboVertexIndex != null) {
Renderable.bindState.bindVertexIndex(vboVertexIndex.getVboID());
} else {
Renderable.bindState.bindVertexIndex(0);
}
}
protected void createGL3(Mesh mesh) {
// Get configuration
renderableConfigID = mesh.getRenderableConfigID();
RenderableConfiguration config = Renderable.configPool.get(renderableConfigID);
// Destroy existing VAO and VBOs
destroy();
// Create VAO and bind
vao = GL.glFactory.createVertexArrayObject();
vao.create();
GL.vaoHelper.bind(vao.getVaoID());
// Create interleaved buffer data, VBO and send interleaved buffer data
if (mesh.hasColors() || mesh.hasNormals() || mesh.hasTexCoords() || mesh.hasVertices()) {
vboInterleaved = GL.glFactory.createVertexBufferObjectInterleaved();
vboInterleaved.create();
Renderable.renderableBuilder.calculateOffsetsAndStride(mesh, vboInterleaved, config);
Renderable.renderableBuilder.createInterleavedBufferData(mesh, vboInterleaved.getStrideBytes(),
Renderable.byteBuffers, config);
GL.vboHelper.setBufferData(vboInterleaved.getVboID(), Renderable.byteBuffers.getInterleaved(),
bufferUsage);
}
hasColors = mesh.hasColors();
hasNormals = mesh.hasNormals();
hasTexCoords = mesh.hasTexCoords();
hasVertices = mesh.hasVertices();
// Update VAO state
if (hasColors) {
GL.vboHelper.bindVertexAttrib(vboInterleaved.getVboID(), GL.defaultAttribLocations.getIndex("color"),
config.getColorSize(), config.getColorType(), vboInterleaved.getStrideBytes(),
vboInterleaved.getColorOffsetBytes());
}
if (hasNormals) {
GL.vboHelper.bindVertexAttrib(vboInterleaved.getVboID(), GL.defaultAttribLocations.getIndex("normal"),
config.getNormalSize(), config.getNormalType(), vboInterleaved.getStrideBytes(),
vboInterleaved.getNormalOffsetBytes());
}
if (hasTexCoords) {
GL.vboHelper.bindVertexAttrib(vboInterleaved.getVboID(), GL.defaultAttribLocations.getIndex("texCoord0"),
config.getTexCoordSize(), config.getTexCoordType(), vboInterleaved.getStrideBytes(),
vboInterleaved.getTexCoordOffsetBytes());
}
if (hasVertices) {
GL.vboHelper.bindVertexAttrib(vboInterleaved.getVboID(), GL.defaultAttribLocations.getIndex("vertex"),
config.getVertexSize(), config.getVertexType(), vboInterleaved.getStrideBytes(),
vboInterleaved.getVertexOffsetBytes());
}
// Create VBO, byte buffer data and send byte buffer data for indexes
if (mesh.hasIndexes()) {
vboVertexIndex = GL.glFactory.createVertexBufferObject();
vboVertexIndex.create();
Renderable.renderableBuilder.createIndexBufferData(mesh, Renderable.byteBuffers, config);
GL.vboHelper.setBufferElementData(vboVertexIndex.getVboID(), Renderable.byteBuffers.getVertexIndex(),
bufferUsage);
}
GL.vboHelper.unbind();
GL.vaoHelper.unbind();
// Create render call
renderCall = Renderable.vboDrawCallBuilder.createRenderCall(mesh, config);
}
protected void renderGL3() {
bindGL3();
renderCall.render();
}
protected void updateGL3(Mesh mesh) {
// Get configuration
renderableConfigID = mesh.getRenderableConfigID();
RenderableConfiguration config = Renderable.configPool.get(renderableConfigID);
// Create interleaved buffer data and send interleaved buffer data
if (mesh.hasColors() || mesh.hasNormals() || mesh.hasTexCoords() || mesh.hasVertices()) {
Renderable.renderableBuilder.calculateOffsetsAndStride(mesh, vboInterleaved, config);
Renderable.renderableBuilder.createInterleavedBufferData(
mesh, vboInterleaved.getStrideBytes(), Renderable.byteBuffers, config);
GL.vboHelper.updateBufferData(vboInterleaved.getVboID(), 0, Renderable.byteBuffers.getInterleaved());
}
hasColors = mesh.hasColors();
hasNormals = mesh.hasNormals();
hasTexCoords = mesh.hasTexCoords();
hasVertices = mesh.hasVertices();
// Create byte buffer data and send byte buffer data for indexes
if (mesh.hasIndexes() && (vboVertexIndex != null)) {
Renderable.renderableBuilder.createIndexBufferData(mesh, Renderable.byteBuffers, config);
GL.vboHelper.updateBufferElementData(vboVertexIndex.getVboID(), 0,
Renderable.byteBuffers.getVertexIndex());
}
GL.vboHelper.unbind();
// Create render call
renderCall = Renderable.vboDrawCallBuilder.createRenderCall(mesh, config);
}
@Override
public void destroy() {
if (vao != null) {
vao.destroy();
vao = null;
}
if (vboInterleaved != null) {
vboInterleaved.destroy();
vboInterleaved = null;
}
if (vboVertexIndex != null) {
vboVertexIndex.destroy();
vboVertexIndex = null;
}
hasColors = false;
hasNormals = false;
hasTexCoords = false;
hasVertices = false;
}
}