package com.framsticks.net.client3D.graphics.loaders; import java.util.ArrayList; import pl.vorg.mowa.core.graphics.FloatVertexAttrib; import pl.vorg.mowa.core.graphics.Geometry; import pl.vorg.mowa.core.graphics.GeometryGroup; import pl.vorg.mowa.core.graphics.IndexBuffer; import pl.vorg.mowa.core.graphics.PrimitiveType; import pl.vorg.mowa.core.graphics.Vec2; import pl.vorg.mowa.core.graphics.Vec3; import pl.vorg.mowa.core.graphics.VertexStream; import com.framsticks.net.client3D.Log; /** * A class converting OBJMesh to GeometryGroup, vertex arrays to VertexStreams, * etc. * * For now, it supports only uniform meshes (i.e., it contains only triangles). * * @author vorg */ public class OBJMeshConverter { public GeometryGroup convert(OBJMesh mesh) { Log.getInstance().log("dbg", "OBJMeshConverter.convert"); GeometryGroup group = new GeometryGroup(); ArrayList faces = mesh.getFaces(); int faceVertexCount = 0; for (OBJFace face : mesh.getFaces()) { if (faceVertexCount == 0) { faceVertexCount = face.getVertices().length; } else if (faceVertexCount != face.getVertices().length) { // Two different face types in the same mesh. The mesh // would have to be divided into smaller ones. Log.getInstance().log( "err", "OBJMeshConverter.convert unsupported mesh type" + "(faceVertexCount:" + face.getVertices().length + "!=" + faceVertexCount + ")"); return group; } } // Build indexes. ArrayList indexList = new ArrayList(); ArrayList faceVertexList = new ArrayList(); Geometry geometry = new Geometry(); if (faceVertexCount == 3) { geometry.setPrimitiveType(PrimitiveType.Triangles); } else if (faceVertexCount == 4) { geometry.setPrimitiveType(PrimitiveType.Quads); } else { Log.getInstance() .log("err", "OBJMeshConverter.convert only triangles and quads are supported (faceVertexCount:" + faceVertexCount + ")"); return group; } for (int i = 0; i < faces.size(); i++) { OBJFaceVertex[] faceVertices = faces.get(i).getVertices(); for (int j = 0; j < faceVertexCount; j++) { OBJFaceVertex v = faceVertices[j]; int index = faceVertexList.indexOf(v); if (index == -1) { faceVertexList.add(v); index = faceVertexList.size() - 1; } indexList.add(index); } } VertexStream vertexStream = buildBuffers(mesh, indexList, faceVertexList); geometry.setVertexStream(vertexStream); group.getChildren().add(geometry); group.updateBoundingBox(); return group; } private VertexStream buildBuffers(OBJMesh mesh, ArrayList indexList, ArrayList faceVertexList) { VertexStream vertexStream = new VertexStream(); IndexBuffer indexBuffer = new IndexBuffer(); int[] idxBuf = new int[indexList.size()]; for (int i = 0; i < indexList.size(); i++) { idxBuf[i] = indexList.get(i); } indexBuffer.setBuffer(idxBuf); vertexStream.setIndexBuffer(indexBuffer); ArrayList vertices = mesh.getVertices(); FloatVertexAttrib posAttrib = new FloatVertexAttrib("pos"); float[] posBuf = new float[3 * faceVertexList.size()]; for (int i = 0; i < faceVertexList.size(); i++) { Vec3 v = vertices.get(faceVertexList.get(i).getVertexIndex()); posBuf[i * 3] = v.getX(); posBuf[i * 3 + 1] = v.getY(); posBuf[i * 3 + 2] = v.getZ(); } posAttrib.setBuffer(posBuf); vertexStream.addAttrib(posAttrib); ArrayList normals = mesh.getNormals(); if (normals.size() > 0) { FloatVertexAttrib normalAttrib = new FloatVertexAttrib("normal"); float[] normalBuf = new float[3 * faceVertexList.size()]; for (int i = 0; i < faceVertexList.size(); i++) { Vec3 v = normals.get(faceVertexList.get(i).getNormalIndex()); normalBuf[i * 3] = v.getX(); normalBuf[i * 3 + 1] = v.getY(); normalBuf[i * 3 + 2] = v.getZ(); } normalAttrib.setBuffer(normalBuf); vertexStream.addAttrib(normalAttrib); } ArrayList texCoords = mesh.getTexCoords(); if (texCoords.size() > 0) { FloatVertexAttrib texCoord0Attrib = new FloatVertexAttrib( "texCoord0"); float[] texCoord0Buf = new float[2 * texCoords.size()]; for (int i = 0; i < texCoords.size(); i++) { Vec2 tc = texCoords.get(faceVertexList.get(i) .getTexCoordIndex()); texCoord0Buf[i * 2] = tc.getX(); texCoord0Buf[i * 2 + 1] = tc.getY(); } texCoord0Attrib.setBuffer(texCoord0Buf); vertexStream.addAttrib(texCoord0Attrib); } return vertexStream; } }