/**
* 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 java.nio.ByteBuffer;
import net.smert.frameworkgl.opengl.VertexBufferObjectInterleaved;
import net.smert.frameworkgl.opengl.constants.GLTypes;
import net.smert.frameworkgl.opengl.mesh.Mesh;
import net.smert.frameworkgl.opengl.mesh.Segment;
import net.smert.frameworkgl.opengl.mesh.SegmentDataType;
import net.smert.frameworkgl.opengl.renderable.RenderableConfiguration;
/**
*
* @author Jason Sorensen <sorensenj@smert.net>
*/
public class RenderableBuilder {
private void createBufferData(Mesh mesh, RenderableConfiguration config, ByteBuffer colorByteBuffer,
ByteBuffer normalByteBuffer, ByteBuffer texCoordByteBuffer, ByteBuffer vertexByteBuffer) {
// For each segment in the mesh
for (int i = 0; i < mesh.getTotalSegments(); i++) {
Segment segment = mesh.getSegment(i);
float[] colors = segment.getData(SegmentDataType.COLOR);
float[] normals = segment.getData(SegmentDataType.NORMAL);
float[] texCoords = segment.getData(SegmentDataType.TEX_COORD0);
float[] vertices = segment.getData(SegmentDataType.VERTEX);
// For each vertex in the segment
for (int j = 0; j < segment.getElementCount(); j++) {
// For each type convert the data and add to the byte buffer
if (mesh.hasColors()) {
config.convertColorToByteBuffer(colors, j, colorByteBuffer);
}
if (mesh.hasNormals()) {
config.convertNormalToByteBuffer(normals, j, normalByteBuffer);
}
if (mesh.hasTexCoords()) {
config.convertTexCoordToByteBuffer(texCoords, j, texCoordByteBuffer);
}
if (mesh.hasVertices()) {
config.convertVertexToByteBuffer(vertices, j, vertexByteBuffer);
}
}
}
}
public void calculateOffsetsAndStride(Mesh mesh, VertexBufferObjectInterleaved vboInterleaved,
RenderableConfiguration config) {
int total = 0;
// Calculate byte size of each type and add to the total. Save the total as
// the current offset before increasing it.
if (mesh.hasColors()) {
vboInterleaved.setColorOffsetBytes(total);
int byteSize = config.convertGLTypeToByteSize(config.getColorType());
total += config.getColorSize() * byteSize;
}
if (mesh.hasNormals()) {
vboInterleaved.setNormalOffsetBytes(total);
int byteSize = config.convertGLTypeToByteSize(config.getNormalType());
total += config.getNormalSize() * byteSize;
}
if (mesh.hasTexCoords()) {
vboInterleaved.setTexCoordOffsetBytes(total);
int byteSize = config.convertGLTypeToByteSize(config.getTexCoordType());
total += config.getTexCoordSize() * byteSize;
}
if (mesh.hasVertices()) {
vboInterleaved.setVertexOffsetBytes(total);
int byteSize = config.convertGLTypeToByteSize(config.getVertexType());
total += config.getVertexSize() * byteSize;
}
vboInterleaved.setStrideBytes(total);
}
public void createIndexBufferData(Mesh mesh, MultipleBuffers multipleBuffers, RenderableConfiguration config) {
// Index byte buffer
int byteSize = config.convertGLTypeToByteSize(config.getIndexType());
int bufferSize = byteSize * mesh.getIndexes().length;
multipleBuffers.createVertexIndex(bufferSize);
// Fill byte buffer with indexes
int[] indexes = mesh.getIndexes();
for (int i = 0; i < indexes.length; i++) {
int index = indexes[i];
switch (config.getIndexType()) {
case GLTypes.UNSIGNED_INT:
multipleBuffers.getVertexIndex().putInt(index);
break;
case GLTypes.UNSIGNED_SHORT:
multipleBuffers.getVertexIndex().putShort((short) index);
break;
default:
throw new IllegalArgumentException("Unknown GL type constant for indexes: " + config.getIndexType());
}
}
// Don't forget to flip
multipleBuffers.getVertexIndex().flip();
}
public void createInterleavedBufferData(Mesh mesh, int strideBytes, MultipleBuffers multipleBuffers,
RenderableConfiguration config) {
// Create byte buffer to hold color, normal, texture coordinates and vertex data
int bufferSize = strideBytes * mesh.getTotalVerticies();
multipleBuffers.createInterleaved(bufferSize);
createBufferData(mesh, config, multipleBuffers.getInterleaved(), multipleBuffers.getInterleaved(),
multipleBuffers.getInterleaved(), multipleBuffers.getInterleaved());
// Missy Elliott that shit
multipleBuffers.getInterleaved().flip();
}
public void createNonInterleavedBufferData(Mesh mesh, MultipleBuffers multipleBuffers,
RenderableConfiguration config) {
int bufferSize, byteSize;
// Color byte buffer
if (mesh.hasColors()) {
byteSize = config.convertGLTypeToByteSize(config.getColorType());
bufferSize = byteSize * config.getColorSize() * mesh.getTotalVerticies();
multipleBuffers.createColor(bufferSize);
}
// Normal byte buffer
if (mesh.hasNormals()) {
byteSize = config.convertGLTypeToByteSize(config.getNormalType());
bufferSize = byteSize * config.getNormalSize() * mesh.getTotalVerticies();
multipleBuffers.createNormal(bufferSize);
}
// Texture coordinate byte buffer
if (mesh.hasTexCoords()) {
byteSize = config.convertGLTypeToByteSize(config.getTexCoordType());
bufferSize = byteSize * config.getTexCoordSize() * mesh.getTotalVerticies();
multipleBuffers.createTexCoord(bufferSize);
}
// Vertex byte buffer
if (mesh.hasVertices()) {
byteSize = config.convertGLTypeToByteSize(config.getVertexType());
bufferSize = byteSize * config.getVertexSize() * mesh.getTotalVerticies();
multipleBuffers.createVertex(bufferSize);
}
createBufferData(mesh, config, multipleBuffers.getColor(), multipleBuffers.getNormal(),
multipleBuffers.getTexCoord(), multipleBuffers.getVertex());
if (mesh.hasColors()) {
multipleBuffers.getColor().flip();
}
if (mesh.hasNormals()) {
multipleBuffers.getNormal().flip();
}
if (mesh.hasTexCoords()) {
multipleBuffers.getTexCoord().flip();
}
if (mesh.hasVertices()) {
multipleBuffers.getVertex().flip();
}
}
}