/** * 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.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 AbstractVertexBufferObjectInterleavedRenderable extends AbstractRenderable { protected boolean hasColors; protected boolean hasNormals; protected boolean hasTexCoords; protected boolean hasVertices; protected int bufferUsage; protected int renderableConfigID; protected RenderCall renderCall; protected VertexBufferObject vboVertexIndex; protected VertexBufferObjectInterleaved vboInterleaved; public AbstractVertexBufferObjectInterleavedRenderable() { hasColors = false; hasNormals = false; hasTexCoords = false; hasVertices = false; bufferUsage = -1; renderableConfigID = -1; renderCall = null; vboVertexIndex = null; vboInterleaved = null; } protected void bindGL1() { int strideBytes = vboInterleaved.getStrideBytes(); // Switch the renderable configuration first Renderable.bindState.switchRenderableConfiguration(renderableConfigID); // Bind VBO for each type if (hasColors) { GL.vboHelper.enableColors(); Renderable.bindState.bindColorGL1(vboInterleaved.getVboID(), strideBytes, vboInterleaved.getColorOffsetBytes()); } else { GL.vboHelper.disableColors(); } if (hasNormals) { GL.vboHelper.enableNormals(); Renderable.bindState.bindNormalGL1(vboInterleaved.getVboID(), strideBytes, vboInterleaved.getNormalOffsetBytes()); } else { GL.vboHelper.disableNormals(); } if (hasTexCoords) { GL.vboHelper.enableTexCoords(); Renderable.bindState.bindTexCoordGL1(vboInterleaved.getVboID(), strideBytes, vboInterleaved.getTexCoordOffsetBytes()); } else { GL.vboHelper.disableTexCoords(); } if (hasVertices) { GL.vboHelper.enableVertices(); Renderable.bindState.bindVertexGL1(vboInterleaved.getVboID(), strideBytes, vboInterleaved.getVertexOffsetBytes()); } else { GL.vboHelper.disableVertices(); } if (vboVertexIndex != null) { Renderable.bindState.bindVertexIndex(vboVertexIndex.getVboID()); } else { Renderable.bindState.bindVertexIndex(0); } } protected void bindGL2() { int strideBytes = vboInterleaved.getStrideBytes(); // Switch the renderable configuration first Renderable.bindState.switchRenderableConfiguration(renderableConfigID); // Bind VBO for each type if (hasColors) { GL.vboHelper.enableVertexAttribArray(Renderable.bindState.getColorIndex()); Renderable.bindState.bindColorGL2(vboInterleaved.getVboID(), strideBytes, vboInterleaved.getColorOffsetBytes()); } else { GL.vboHelper.disableVertexAttribArray(Renderable.bindState.getColorIndex()); } if (hasNormals) { GL.vboHelper.enableVertexAttribArray(Renderable.bindState.getNormalIndex()); Renderable.bindState.bindNormalGL2(vboInterleaved.getVboID(), strideBytes, vboInterleaved.getNormalOffsetBytes()); } else { GL.vboHelper.disableVertexAttribArray(Renderable.bindState.getNormalIndex()); } if (hasTexCoords) { GL.vboHelper.enableVertexAttribArray(Renderable.bindState.getTexCoord0Index()); Renderable.bindState.bindTexCoordGL2(vboInterleaved.getVboID(), strideBytes, vboInterleaved.getTexCoordOffsetBytes()); } else { GL.vboHelper.disableVertexAttribArray(Renderable.bindState.getTexCoord0Index()); } if (hasVertices) { GL.vboHelper.enableVertexAttribArray(Renderable.bindState.getVertexIndex()); Renderable.bindState.bindVertexGL2(vboInterleaved.getVboID(), strideBytes, vboInterleaved.getVertexOffsetBytes()); } else { GL.vboHelper.disableVertexAttribArray(Renderable.bindState.getVertexIndex()); } if (vboVertexIndex != null) { Renderable.bindState.bindVertexIndex(vboVertexIndex.getVboID()); } else { Renderable.bindState.bindVertexIndex(0); } } protected void createGL1AndGL2(Mesh mesh) { // Get configuration renderableConfigID = mesh.getRenderableConfigID(); RenderableConfiguration config = Renderable.configPool.get(renderableConfigID); // Destroy existing VBOs destroy(); // 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(); // 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(); // Create render call renderCall = Renderable.vboDrawCallBuilder.createRenderCall(mesh, config); } protected void renderGL1() { bindGL1(); renderCall.render(); } protected void renderGL2() { bindGL2(); renderCall.render(); } protected void updateGL1AndGL2(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 (vboInterleaved != null) { vboInterleaved.destroy(); vboInterleaved = null; } if (vboVertexIndex != null) { vboVertexIndex.destroy(); vboVertexIndex = null; } hasColors = false; hasNormals = false; hasTexCoords = false; hasVertices = false; } }