package org.terasology.model.shapes;
import com.bulletphysics.linearmath.QuaternionUtil;
import org.terasology.rendering.primitives.ChunkMesh;
import javax.vecmath.Quat4f;
import javax.vecmath.Vector2f;
import javax.vecmath.Vector3f;
import javax.vecmath.Vector4f;
import java.util.Arrays;
/**
* Describes the elements composing part of a block mesh. Multiple parts are patched together to define the mesh
* for a block, or its appearance in the world.
*
* @author Immortius <immortius@gmail.com>
*/
public class BlockMeshPart {
private Vector3f[] vertices;
private Vector3f[] normals;
private Vector2f[] texCoords;
private int[] indices;
public BlockMeshPart(Vector3f[] vertices, Vector3f[] normals, Vector2f[] texCoords, int[] indices) {
this.vertices = Arrays.copyOf(vertices, vertices.length);
this.normals = Arrays.copyOf(normals, normals.length);
this.texCoords = Arrays.copyOf(texCoords, texCoords.length);
this.indices = Arrays.copyOf(indices, indices.length);
}
public int size() {
return vertices.length;
}
public int indicesSize() {
return indices.length;
}
public Vector3f getVertex(int i) {
return vertices[i];
}
public Vector3f getNormal(int i) {
return normals[i];
}
public Vector2f getTexCoord(int i) {
return texCoords[i];
}
public int getIndex(int i) {
return indices[i];
}
public BlockMeshPart mapTexCoords(Vector2f offset, float width) {
Vector2f[] newTexCoords = new Vector2f[texCoords.length];
for (int i = 0; i < newTexCoords.length; ++i) {
newTexCoords[i] = new Vector2f(offset.x + texCoords[i].x * width, offset.y + texCoords[i].y * width);
}
return new BlockMeshPart(vertices, normals, newTexCoords, indices);
}
public void appendTo(ChunkMesh chunk, int offsetX, int offsetY, int offsetZ, Vector4f colorOffset, int meshBit) {
for (Vector2f texCoord : texCoords) {
chunk._vertexElements[meshBit].tex.add(texCoord.x);
chunk._vertexElements[meshBit].tex.add(texCoord.y);
chunk._vertexElements[meshBit].tex.add(1.0f);
}
int nextIndex = chunk._vertexElements[meshBit].vertCount;
for (int vIdx = 0; vIdx < vertices.length; ++vIdx) {
chunk._vertexElements[meshBit].color.add(colorOffset.x);
chunk._vertexElements[meshBit].color.add(colorOffset.y);
chunk._vertexElements[meshBit].color.add(colorOffset.z);
chunk._vertexElements[meshBit].color.add(colorOffset.w);
chunk._vertexElements[meshBit].vertices.add(vertices[vIdx].x + offsetX);
chunk._vertexElements[meshBit].vertices.add(vertices[vIdx].y + offsetY);
chunk._vertexElements[meshBit].vertices.add(vertices[vIdx].z + offsetZ);
chunk._vertexElements[meshBit].normals.add(normals[vIdx].x);
chunk._vertexElements[meshBit].normals.add(normals[vIdx].y);
chunk._vertexElements[meshBit].normals.add(normals[vIdx].z);
}
chunk._vertexElements[meshBit].vertCount += vertices.length;
for (int i = 0; i < indices.length; ++i) {
chunk._vertexElements[meshBit].indices.add(indices[i] + nextIndex);
}
}
public BlockMeshPart rotate(Quat4f rotation) {
Vector3f[] newVertices = new Vector3f[vertices.length];
Vector3f[] newNormals = new Vector3f[normals.length];
for (int i = 0; i < newVertices.length; ++i) {
newVertices[i] = QuaternionUtil.quatRotate(rotation, vertices[i], new Vector3f());
newNormals[i] = QuaternionUtil.quatRotate(rotation, normals[i], new Vector3f());
}
return new BlockMeshPart(newVertices, newNormals, texCoords, indices);
}
}