/*
* Copyright 2013 MovingBlocks
*
* 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 org.terasology.rendering.assets.mesh;
import org.terasology.utilities.Assets;
import org.terasology.assets.ResourceUrn;
import org.terasology.math.geom.Vector2f;
import org.terasology.math.geom.Vector3f;
import org.terasology.module.sandbox.API;
import org.terasology.rendering.nui.Color;
/**
*/
public class MeshBuilder {
private static final float[] VERTICES = {
// Front face
0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f,
// Back face
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
// Top face
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 0.0f,
// Bottom face
0.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
// Right face
1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f,
// Left face
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 0.0f
};
private static final int[] INDICES = {
0, 1, 2, 0, 2, 3, // front
4, 5, 6, 4, 6, 7, // back
8, 9, 10, 8, 10, 11, // top
12, 13, 14, 12, 14, 15, // bottom
16, 17, 18, 16, 18, 19, // right
20, 21, 22, 20, 22, 23 // left
};
private MeshData meshData = new MeshData();
private int vertexCount;
private TextureMapper textureMapper;
public MeshBuilder addVertex(Vector3f v) {
meshData.getVertices().add(v.x);
meshData.getVertices().add(v.y);
meshData.getVertices().add(v.z);
vertexCount++;
return this;
}
public MeshBuilder addPoly(Vector3f v1, Vector3f v2, Vector3f v3, Vector3f... vn) {
for (int i = 0; i < vn.length + 1; i++) {
addIndices(vertexCount, vertexCount + i + 2, vertexCount + i + 1);
}
addVertex(v1);
addVertex(v2);
addVertex(v3);
for (Vector3f v : vn) {
addVertex(v);
}
return this;
}
public MeshBuilder addColor(Color c1, Color... colors) {
meshData.getColors().add(c1.rf());
meshData.getColors().add(c1.gf());
meshData.getColors().add(c1.bf());
meshData.getColors().add(c1.af());
for (Color c : colors) {
meshData.getColors().add(c.rf());
meshData.getColors().add(c.gf());
meshData.getColors().add(c.bf());
meshData.getColors().add(c.af());
}
return this;
}
public MeshBuilder addTexCoord(float x, float y) {
meshData.getTexCoord0().add(x);
meshData.getTexCoord0().add(y);
return this;
}
public MeshBuilder addTexCoord(Vector2f v) {
return addTexCoord(v.x, v.y);
}
public MeshBuilder addIndex(int index) {
meshData.getIndices().add(index);
return this;
}
public MeshBuilder addIndices(int... indices) {
meshData.getIndices().add(indices);
return this;
}
public MeshData getMeshData() {
return meshData;
}
public Mesh build() {
return Assets.generateAsset(meshData, Mesh.class);
}
public Mesh build(ResourceUrn urn) {
return Assets.generateAsset(urn, meshData, Mesh.class);
}
/**
* Add vertices, texture coordinate and indices for a box specified by offset and size.
* <br><br>
* Use the texture mapper to change how texture coordinates (u and v) are applied to each vertex.
*/
public MeshBuilder addBox(Vector3f offset, Vector3f size, float u, float v) {
int vertexId = vertexCount;
textureMapper.initialize(offset, size);
for (int i = 0; i < VERTICES.length / 3; i++) {
addVertex(new Vector3f(offset.x + size.x * VERTICES[i * 3], offset.y + size.y * VERTICES[i * 3 + 1], offset.z + size.z * VERTICES[i * 3 + 2]));
addTexCoord(textureMapper.map(i, u, v));
}
for (int i : INDICES) {
addIndex(vertexId + i);
}
return this;
}
public void setTextureMapper(TextureMapper textureMapper) {
this.textureMapper = textureMapper;
}
@API
public interface TextureMapper {
void initialize(Vector3f offset, Vector3f size);
Vector2f map(int vertexIndex, float u, float v);
}
}