Hi everybody,
I have made a primitive mesh class for convex prisms wich are very useful in procedural generation of cities like mine
Uploaded with ImageShack.us’/>
The class can easily be optimized because I use ArrayList and then tables, but the 15 000 buildings of the picture are generated in no time so I leave it like this for now.
The constructor needs only an ArrayList of Vector2f wich store a linear counter-clockwise ring of 2D coordinates, with the last isEqual to the first. It also needs a positive height (if someone need to set negative mesh then tell me, I can integarte it). The pivot and center of the mesh is set at the first linear ring point and 0-y height.
The top and bottom faces are triangulated with a triangle fan shape. I don’t know if the texture coordinate are oriented the good way. If it’s not, I could modify it (I don’t know very well the UV standards). I also don’t know how to make the texture unique on the multiple triangles of the face. I could set textCoord of each corner to a complicated value but it seems hard to do. Is there any simple solution?
Does anyone can send me a source code for a triangulation of concave polygons (Monotone or by ears)? I can integrate it to make the same class accepting concave rings (and holes, if the triangulator supports it).
I hope that it will help.
[java]import java.util.ArrayList;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer.Type;
/**
- Convex Prism.
*
- Wiki : "In geometry, a prism is a polyhedron with an n-sided polygonal base, a translated copy
- (not in the same plane as the first), and n other faces (necessarily all parallelograms) joining
- corresponding sides of the two bases."
*
- @author Benoît Dumas
- @version $Id$
*/
public class ConvexPrism extends Mesh {
private ArrayList<Vector2f> polygonalBase;
private float height;
/**
- Constructs a new convex prism.
*
- @param polygonalBase
- This is a linear rings of points, with the first is equal to the last.
- The first point of the list is the pivot.
- @param height
- This is the height of the prism. Bottom base is set at 0-y coordinate.
/
public ConvexPrism(ArrayList<Vector2f> polygonalBase, float height) {
this.polygonalBase = polygonalBase;
this.height = height;
updateGeometry();
}
private void updateGeometry() {
ArrayList<Vector3f> verticesArray = new ArrayList<Vector3f>();
ArrayList<Vector2f> textCoordArray = new ArrayList<Vector2f>();
ArrayList<Vector3f> normalsArray = new ArrayList<Vector3f>();
ArrayList<Short> indicesArray = new ArrayList<Short>();
// faces
int numberOfFaces = polygonalBase.size()-1; // the last vertex is the same than the first
for (int i = 0; i < numberOfFaces; i++) {
// For each face
// add 4 vertices
int topLeftCorner = verticesArray.size();
verticesArray.add(new Vector3f(polygonalBase.get(i).x, height, polygonalBase.get(i).y)); // Top left corner
int topRightCorner = verticesArray.size();
verticesArray.add(new Vector3f(polygonalBase.get(i+1).x, height, polygonalBase.get(i+1).y)); // Top right corner
int bottomRightCorner = verticesArray.size();
verticesArray.add(new Vector3f(polygonalBase.get(i+1).x, 0, polygonalBase.get(i+1).y)); // Bottom right corner
int bottomLeftCorner = verticesArray.size();
verticesArray.add(new Vector3f(polygonalBase.get(i).x, 0, polygonalBase.get(i).y)); // bottom left corner
// add 6 indices
indicesArray.add((short) topLeftCorner);
indicesArray.add((short) topRightCorner);
indicesArray.add((short) bottomLeftCorner);
indicesArray.add((short) bottomLeftCorner);
indicesArray.add((short) topRightCorner);
indicesArray.add((short) bottomRightCorner);
// add 4 normals
float faceNormal = (float) (polygonalBase.get(i+1).subtract(polygonalBase.get(i)).getAngle()-1 - Math.PI/2);
float cosNormal = (float)Math.cos(faceNormal);
float sinNormal = (float)Math.sin(faceNormal);
normalsArray.add(new Vector3f(cosNormal, 0, sinNormal));
normalsArray.add(new Vector3f(cosNormal, 0, sinNormal));
normalsArray.add(new Vector3f(cosNormal, 0, sinNormal));
normalsArray.add(new Vector3f(cosNormal, 0, sinNormal));
// add 4 textCoord
textCoordArray.add(new Vector2f(1, 1));
textCoordArray.add(new Vector2f(0, 1));
textCoordArray.add(new Vector2f(0, 0));
textCoordArray.add(new Vector2f(1, 0));
}
// top face
int numberOfTriangles = polygonalBase.size()-2;
for (int i = 0; i < numberOfTriangles; i++) {
// for each triangle
// add 3 vertices
int firstCorner = verticesArray.size();
verticesArray.add(new Vector3f(polygonalBase.get(0).x, height, polygonalBase.get(0).y)); // first Corner is always the center of fan
int secondCorner = verticesArray.size();
verticesArray.add(new Vector3f(polygonalBase.get(i+1).x, height, polygonalBase.get(i+1).y)); // second corner
int thirdCorner = verticesArray.size();
verticesArray.add(new Vector3f(polygonalBase.get(i+2).x, height, polygonalBase.get(i+2).y)); // Bottom right corner
// add 3 indices
indicesArray.add((short) firstCorner);
indicesArray.add((short) thirdCorner);
indicesArray.add((short) secondCorner);
// add 3 texture coordinates
textCoordArray.add(new Vector2f(1, 1));
textCoordArray.add(new Vector2f(0, 1));
textCoordArray.add(new Vector2f(0, 0));
// add 3 normals
normalsArray.add(new Vector3f(0, 1, 0));
normalsArray.add(new Vector3f(0, 1, 0));
normalsArray.add(new Vector3f(0, 1, 0));
}
// bottom face
for (int i = 0; i < numberOfTriangles; i++) {
// for each triangle
// add 3 vertices
int firstCorner = verticesArray.size();
verticesArray.add(new Vector3f(polygonalBase.get(0).x, 0, polygonalBase.get(0).y)); // first Corner is always the center of fan
int secondCorner = verticesArray.size();
verticesArray.add(new Vector3f(polygonalBase.get(i+1).x, 0, polygonalBase.get(i+1).y)); // second corner
int thirdCorner = verticesArray.size();
verticesArray.add(new Vector3f(polygonalBase.get(i+2).x, 0, polygonalBase.get(i+2).y)); // Bottom right corner
// add 3 indices
indicesArray.add((short) firstCorner);
indicesArray.add((short) secondCorner);
indicesArray.add((short) thirdCorner);
// add 3 texture coordinates
textCoordArray.add(new Vector2f(1, 1));
textCoordArray.add(new Vector2f(0, 1));
textCoordArray.add(new Vector2f(0, 0));
// add 3 normals
normalsArray.add(new Vector3f(0, -1, 0));
normalsArray.add(new Vector3f(0, -1, 0));
normalsArray.add(new Vector3f(0, -1, 0));
}
float vertices[] = new float[verticesArray.size()*3];
float textCoord[] = new float[textCoordArray.size()*2];
float normals[] = new float[normalsArray.size()*3];
short indices[] = new short[indicesArray.size()];
int j = 0;
for (int i = 0; i < verticesArray.size()*3; i+:3) {
vertices = verticesArray.get(j).x;
vertices[i+1] = verticesArray.get(j).y;
vertices[i+2] = verticesArray.get(j).z;
j++;
}
j = 0;
for (int i = 0; i < textCoordArray.size()*2; i+=2) {
textCoord = textCoordArray.get(j).x;
textCoord[i+1] = textCoordArray.get(j).y;
j++;
}
j = 0;
for (int i = 0; i < normalsArray.size()*3; i+:3) {
normals = normalsArray.get(j).x;
normals[i+1] = normalsArray.get(j).y;
normals[i+2] = normalsArray.get(j).z;
j++;
}
for (int i = 0; i < indicesArray.size(); i++) {
indices = indicesArray.get(i);
}
setBuffer(Type.Position, 3, vertices);
setBuffer(Type.TexCoord, 2, textCoord);
setBuffer(Type.Normal, 3, normals);
setBuffer(Type.Index, 3, indices);
updateBound();
}
}[/java]