/**
* 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.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 AbstractVertexArrayObjectNonInterleavedRenderable extends AbstractRenderable {
protected int bufferUsage;
protected int renderableConfigID;
protected RenderCall renderCall;
protected VertexArrayObject vao;
protected VertexBufferObject vboColor;
protected VertexBufferObject vboNormal;
protected VertexBufferObject vboTexCoord;
protected VertexBufferObject vboVertex;
protected VertexBufferObject vboVertexIndex;
public AbstractVertexArrayObjectNonInterleavedRenderable() {
bufferUsage = -1;
renderableConfigID = -1;
renderCall = null;
vboColor = null;
vboNormal = null;
vboTexCoord = null;
vboVertex = null;
vboVertexIndex = null;
}
protected void bindGL3() {
// Bind VAO
Renderable.bindState.bindVAO(vao.getVaoID());
// Bind each VBO
if (vboColor != null) {
GL.vboHelper.enableVertexAttribArray(Renderable.bindState.getColorIndex());
} else {
GL.vboHelper.disableVertexAttribArray(Renderable.bindState.getColorIndex());
}
if (vboNormal != null) {
GL.vboHelper.enableVertexAttribArray(Renderable.bindState.getNormalIndex());
} else {
GL.vboHelper.disableVertexAttribArray(Renderable.bindState.getNormalIndex());
}
if (vboTexCoord != null) {
GL.vboHelper.enableVertexAttribArray(Renderable.bindState.getTexCoord0Index());
} else {
GL.vboHelper.disableVertexAttribArray(Renderable.bindState.getTexCoord0Index());
}
if (vboVertex != null) {
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 non interleaved buffer data
if (mesh.hasColors() || mesh.hasNormals() || mesh.hasTexCoords() || mesh.hasVertices()) {
Renderable.renderableBuilder.createNonInterleavedBufferData(mesh, Renderable.byteBuffers, config);
}
// Create VBO, send byte buffer data for colors and update VAO state
if (mesh.hasColors()) {
vboColor = GL.glFactory.createVertexBufferObject();
vboColor.create();
GL.vboHelper.setBufferData(vboColor.getVboID(), Renderable.byteBuffers.getColor(), bufferUsage);
GL.vboHelper.bindVertexAttrib(vboColor.getVboID(), GL.defaultAttribLocations.getIndex("color"),
config.getColorSize(), config.getColorType(), 0, 0);
}
// Create VBO, send byte buffer data for normals and update VAO state
if (mesh.hasNormals()) {
vboNormal = GL.glFactory.createVertexBufferObject();
vboNormal.create();
GL.vboHelper.setBufferData(vboNormal.getVboID(), Renderable.byteBuffers.getNormal(), bufferUsage);
GL.vboHelper.bindVertexAttrib(vboNormal.getVboID(), GL.defaultAttribLocations.getIndex("normal"),
config.getNormalSize(), config.getNormalType(), 0, 0);
}
// Create VBO, send byte buffer data for texture coordinates and update VAO state
if (mesh.hasTexCoords()) {
vboTexCoord = GL.glFactory.createVertexBufferObject();
vboTexCoord.create();
GL.vboHelper.setBufferData(vboTexCoord.getVboID(), Renderable.byteBuffers.getTexCoord(),
bufferUsage);
GL.vboHelper.bindVertexAttrib(vboTexCoord.getVboID(), GL.defaultAttribLocations.getIndex("texCoord0"),
config.getTexCoordSize(), config.getTexCoordType(), 0, 0);
}
// Create VBO, send byte buffer data for vertices and update VAO state
if (mesh.hasVertices()) {
vboVertex = GL.glFactory.createVertexBufferObject();
vboVertex.create();
GL.vboHelper.setBufferData(vboVertex.getVboID(), Renderable.byteBuffers.getVertex(), bufferUsage);
GL.vboHelper.bindVertexAttrib(vboVertex.getVboID(), GL.defaultAttribLocations.getIndex("vertex"),
config.getVertexSize(), config.getVertexType(), 0, 0);
}
// 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
RenderableConfiguration config = Renderable.configPool.get(renderableConfigID);
// Create non interleaved buffer data
if (mesh.hasColors() || mesh.hasNormals() || mesh.hasTexCoords() || mesh.hasVertices()) {
Renderable.renderableBuilder.createNonInterleavedBufferData(mesh, Renderable.byteBuffers, config);
}
// Send byte buffer data for colors
if (mesh.hasColors() && (vboColor != null)) {
GL.vboHelper.updateBufferData(vboColor.getVboID(), 0, Renderable.byteBuffers.getColor());
}
// Send byte buffer data for normals
if (mesh.hasNormals() && (vboNormal != null)) {
GL.vboHelper.updateBufferData(vboNormal.getVboID(), 0, Renderable.byteBuffers.getNormal());
}
// Send byte buffer data for texture coordinates
if (mesh.hasTexCoords() && (vboTexCoord != null)) {
GL.vboHelper.updateBufferData(vboTexCoord.getVboID(), 0, Renderable.byteBuffers.getTexCoord());
}
// Send byte buffer data for vertices
if (mesh.hasVertices() && (vboVertex != null)) {
GL.vboHelper.updateBufferData(vboVertex.getVboID(), 0, Renderable.byteBuffers.getVertex());
}
// 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 (vboColor != null) {
vboColor.destroy();
vboColor = null;
}
if (vboNormal != null) {
vboNormal.destroy();
vboNormal = null;
}
if (vboTexCoord != null) {
vboTexCoord.destroy();
vboTexCoord = null;
}
if (vboVertex != null) {
vboVertex.destroy();
vboVertex = null;
}
if (vboVertexIndex != null) {
vboVertexIndex.destroy();
vboVertexIndex = null;
}
}
}