/** * 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; import java.nio.ByteBuffer; import net.smert.frameworkgl.math.MathHelper; import net.smert.frameworkgl.opengl.constants.GLTypes; /** * * @author Jason Sorensen <sorensenj@smert.net> */ public class RenderableConfiguration { private final static int NORMAL_SIZE = 3; private final static int NORMAL_TYPE = GLTypes.FLOAT; private final static int TEX_COORD_TYPE = GLTypes.FLOAT; private final static int VERTEX_TYPE = GLTypes.FLOAT; private int colorSize; private int colorType; private int indexType; private int texCoordSize; private int vertexSize; public RenderableConfiguration() { reset(); } public RenderableConfiguration(RenderableConfiguration config) { colorSize = config.colorSize; colorType = config.colorType; indexType = config.indexType; texCoordSize = config.texCoordSize; vertexSize = config.vertexSize; } public void convertColorToByteBuffer(float[] colors, int index, ByteBuffer byteBuffer) { assert ((colorSize == 3) || (colorSize == 4)); int offset = colorSize * index; float r = colors[offset + 0]; float g = colors[offset + 1]; float b = colors[offset + 2]; float a = 1f; assert ((r >= 0f) && (r <= 1f)); assert ((g >= 0f) && (g <= 1f)); assert ((b >= 0f) && (b <= 1f)); if (colorSize == 4) { a = colors[offset + 3]; assert ((a >= 0f) && (a <= 1f)); } // Depending on the GL type and size convert the data and put it into the byte buffer switch (colorType) { case GLTypes.BYTE: case GLTypes.UNSIGNED_BYTE: byteBuffer.put(convertFloatToByte(r)); byteBuffer.put(convertFloatToByte(g)); byteBuffer.put(convertFloatToByte(b)); if (colorSize == 4) { byteBuffer.put(convertFloatToByte(a)); } break; case GLTypes.FLOAT: byteBuffer.putFloat(r); byteBuffer.putFloat(g); byteBuffer.putFloat(b); if (colorSize == 4) { byteBuffer.putFloat(a); } break; default: throw new IllegalArgumentException("Unknown GL type constant for color: " + colorType); } } private byte convertFloatToByte(float value) { return (byte) (MathHelper.Clamp(value, 0f, 1f) * 255); } public int convertGLTypeToByteSize(int glType) { int byteSize = 0; // Convert the type to the byte size of the type switch (glType) { case GLTypes.BYTE: case GLTypes.UNSIGNED_BYTE: byteSize = 1; break; case GLTypes.SHORT: case GLTypes.UNSIGNED_SHORT: byteSize = 2; break; case GLTypes.FLOAT: case GLTypes.INT: case GLTypes.UNSIGNED_INT: byteSize = 4; break; default: throw new IllegalArgumentException("Unknown GL type constant: " + glType); } return byteSize; } public void convertNormalToByteBuffer(float[] normals, int index, ByteBuffer byteBuffer) { assert (NORMAL_SIZE == 3); int offset = NORMAL_SIZE * index; float x = normals[offset + 0]; float y = normals[offset + 1]; float z = normals[offset + 2]; assert ((x >= -1f) && (x <= 1f)); assert ((y >= -1f) && (y <= 1f)); assert ((z >= -1f) && (z <= 1f)); // Depending on the GL type put it into the byte buffer switch (NORMAL_TYPE) { case GLTypes.FLOAT: byteBuffer.putFloat(x); byteBuffer.putFloat(y); byteBuffer.putFloat(z); break; default: throw new IllegalArgumentException("Unknown GL type constant for normal: " + NORMAL_TYPE); } } public void convertTexCoordToByteBuffer(float[] texCoords, int index, ByteBuffer byteBuffer) { assert ((texCoordSize == 2) || (texCoordSize == 3)); int offset = texCoordSize * index; float s = texCoords[offset + 0]; float t = texCoords[offset + 1]; float r = 0f; assert ((s >= -1f) && (s <= 1f)); assert ((t >= -1f) && (t <= 1f)); if (texCoordSize == 3) { r = texCoords[offset + 2]; assert ((r >= -1f) && (r <= 1f)); } // Depending on the GL type and size put it into the byte buffer switch (TEX_COORD_TYPE) { case GLTypes.FLOAT: byteBuffer.putFloat(s); byteBuffer.putFloat(t); if (texCoordSize == 3) { byteBuffer.putFloat(r); } break; default: throw new IllegalArgumentException("Unknown GL type constant for texture coordinate: " + TEX_COORD_TYPE); } } public void convertVertexToByteBuffer(float[] vertices, int index, ByteBuffer byteBuffer) { assert ((vertexSize >= 2) && (vertexSize <= 4)); int offset = vertexSize * index; float x = vertices[offset + 0]; float y = vertices[offset + 1]; // Depending on the GL type and size put it into the byte buffer switch (VERTEX_TYPE) { case GLTypes.FLOAT: byteBuffer.putFloat(x); byteBuffer.putFloat(y); if (vertexSize >= 3) { float z = vertices[offset + 2]; byteBuffer.putFloat(z); } if (vertexSize == 4) { float w = vertices[offset + 3]; byteBuffer.putFloat(w); } break; default: throw new IllegalArgumentException("Unknown GL type constant for vertex: " + VERTEX_TYPE); } } public int getColorSize() { return colorSize; } public void setColorSize(int colorSize) { if ((colorSize != 3) && (colorSize != 4)) { throw new IllegalArgumentException("The color size must be 3 or 4. Was given: " + colorSize); } this.colorSize = colorSize; } public int getColorType() { return colorType; } public void setColorTypeByte() { this.colorType = GLTypes.BYTE; } public void setColorTypeFloat() { this.colorType = GLTypes.FLOAT; } public void setColorTypeUnsignedByte() { this.colorType = GLTypes.UNSIGNED_BYTE; } public int getIndexType() { return indexType; } public void setIndexTypeUnsignedInt() { this.indexType = GLTypes.UNSIGNED_INT; } public void setIndexTypeUnsignedShort() { this.indexType = GLTypes.UNSIGNED_SHORT; } public int getNormalSize() { return NORMAL_SIZE; } public int getNormalType() { return NORMAL_TYPE; } public int getTexCoordSize() { return texCoordSize; } public void setTexCoordSize(int texCoordSize) { if ((texCoordSize != 2) && (texCoordSize != 3)) { throw new IllegalArgumentException("The texture coordinate size must be 2 or 3. Was given: " + texCoordSize); } this.texCoordSize = texCoordSize; } public int getTexCoordType() { return TEX_COORD_TYPE; } public int getVertexSize() { return vertexSize; } public void setVertexSize(int vertexSize) { if ((vertexSize < 2) || (vertexSize > 4)) { throw new IllegalArgumentException("The vertex size must be 2, 3 or 4. Was given: " + vertexSize); } this.vertexSize = vertexSize; } public int getVertexType() { return VERTEX_TYPE; } public final void reset() { colorSize = 4; colorType = GLTypes.FLOAT; indexType = GLTypes.UNSIGNED_INT; texCoordSize = 2; vertexSize = 3; } @Override public RenderableConfiguration clone() { return new RenderableConfiguration(this); } @Override public int hashCode() { int hash = 5; hash = 29 * hash + this.colorSize; hash = 29 * hash + this.colorType; hash = 29 * hash + this.indexType; hash = 29 * hash + this.texCoordSize; hash = 29 * hash + this.vertexSize; return hash; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final RenderableConfiguration other = (RenderableConfiguration) obj; if (this.colorSize != other.colorSize) { return false; } if (this.colorType != other.colorType) { return false; } if (this.indexType != other.indexType) { return false; } if (this.texCoordSize != other.texCoordSize) { return false; } return this.vertexSize == other.vertexSize; } }