git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10914 75d07b2b-3a1a-0410-a2c5-0572b91ccdcaexperimental
parent
69e4392ba9
commit
dd8b8fbd5f
@ -1,5 +1,163 @@ |
||||
package com.jme3.scene.plugins.blender.meshes.builders; |
||||
|
||||
/*package*/ class LineMeshBuilder { |
||||
//TODO: this will be implemented soon
|
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.logging.Logger; |
||||
|
||||
import com.jme3.math.Vector3f; |
||||
import com.jme3.scene.Mesh; |
||||
import com.jme3.scene.Mesh.Mode; |
||||
import com.jme3.scene.VertexBuffer; |
||||
import com.jme3.scene.VertexBuffer.Format; |
||||
import com.jme3.scene.VertexBuffer.Type; |
||||
import com.jme3.scene.VertexBuffer.Usage; |
||||
import com.jme3.scene.plugins.blender.BlenderContext; |
||||
import com.jme3.scene.plugins.blender.file.BlenderFileException; |
||||
import com.jme3.scene.plugins.blender.file.Pointer; |
||||
import com.jme3.scene.plugins.blender.file.Structure; |
||||
import com.jme3.util.BufferUtils; |
||||
|
||||
/** |
||||
* A builder that creates a lines mesh. The result is made of lines that do not belong to any face. |
||||
* |
||||
* @author Marcin Roguski (Kaelthas) |
||||
*/ |
||||
/* package */class LineMeshBuilder { |
||||
private static final Logger LOGGER = Logger.getLogger(LineMeshBuilder.class.getName()); |
||||
|
||||
private static final int EDGE_NOT_IN_FACE_FLAG = 0x80; |
||||
|
||||
/** An array of reference vertices. */ |
||||
private Vector3f[][] verticesAndNormals; |
||||
/** The vertices of the mesh. */ |
||||
private List<Vector3f> vertices = new ArrayList<Vector3f>(); |
||||
/** The normals of the mesh. */ |
||||
private List<Vector3f> normals = new ArrayList<Vector3f>(); |
||||
|
||||
/** |
||||
* This map's key is the vertex index from 'vertices 'table and the value are indices from 'vertexList' |
||||
* positions (it simply tells which vertex is referenced where in the result list). |
||||
*/ |
||||
private Map<Integer, List<Integer>> globalVertexReferenceMap; |
||||
|
||||
/** |
||||
* Constructor. Stores the given array (not copying it). |
||||
* The second argument describes if the model uses generated textures. If yes then no vertex amount optimisation is applied. |
||||
* The amount of vertices is always faceCount * 3. |
||||
* @param verticesAndNormals |
||||
* the reference vertices and normals array |
||||
*/ |
||||
public LineMeshBuilder(Vector3f[][] verticesAndNormals) { |
||||
this.verticesAndNormals = verticesAndNormals; |
||||
globalVertexReferenceMap = new HashMap<Integer, List<Integer>>(verticesAndNormals.length); |
||||
} |
||||
|
||||
/** |
||||
* The method reads the mesh. It loads only edges that are marked as not belonging to any face in their flag field. |
||||
* @param meshStructure |
||||
* the mesh structure |
||||
* @param blenderContext |
||||
* the blender context |
||||
* @throws BlenderFileException |
||||
* an exception thrown when reading from the blend file fails |
||||
*/ |
||||
public void readMesh(Structure meshStructure, BlenderContext blenderContext) throws BlenderFileException { |
||||
LOGGER.fine("Reading line mesh."); |
||||
Pointer pMEdge = (Pointer) meshStructure.getFieldValue("medge"); |
||||
|
||||
if (pMEdge.isNotNull()) { |
||||
List<Structure> edges = pMEdge.fetchData(blenderContext.getInputStream()); |
||||
int vertexIndex = 0;//vertex index in the result mesh
|
||||
for (Structure edge : edges) { |
||||
int flag = ((Number) edge.getFieldValue("flag")).intValue(); |
||||
if ((flag & EDGE_NOT_IN_FACE_FLAG) != 0) { |
||||
int v1 = ((Number) edge.getFieldValue("v1")).intValue(); |
||||
int v2 = ((Number) edge.getFieldValue("v2")).intValue(); |
||||
|
||||
vertices.add(verticesAndNormals[v1][0]); |
||||
normals.add(verticesAndNormals[v1][1]); |
||||
this.appendVertexReference(v1, vertexIndex++, globalVertexReferenceMap); |
||||
|
||||
vertices.add(verticesAndNormals[v2][0]); |
||||
normals.add(verticesAndNormals[v2][1]); |
||||
this.appendVertexReference(v2, vertexIndex++, globalVertexReferenceMap); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Builds the meshes. |
||||
* @return a map between material index and the mesh |
||||
*/ |
||||
public Map<Integer, Mesh> buildMeshes() { |
||||
LOGGER.fine("Building line mesh."); |
||||
Map<Integer, Mesh> result = new HashMap<Integer, Mesh>(1); |
||||
if (vertices.size() > 0) { |
||||
Mesh mesh = new Mesh(); |
||||
mesh.setMode(Mode.Lines); |
||||
|
||||
LOGGER.fine("Creating indices buffer."); |
||||
if (vertices.size() <= Short.MAX_VALUE) { |
||||
short[] indices = new short[vertices.size()]; |
||||
for (int i = 0; i < vertices.size(); ++i) { |
||||
indices[i] = (short) i; |
||||
} |
||||
mesh.setBuffer(Type.Index, 1, indices); |
||||
} else { |
||||
int[] indices = new int[vertices.size()]; |
||||
for (int i = 0; i < vertices.size(); ++i) { |
||||
indices[i] = i; |
||||
} |
||||
mesh.setBuffer(Type.Index, 1, indices); |
||||
} |
||||
|
||||
LOGGER.fine("Creating vertices buffer."); |
||||
VertexBuffer verticesBuffer = new VertexBuffer(Type.Position); |
||||
verticesBuffer.setupData(Usage.Static, 3, Format.Float, BufferUtils.createFloatBuffer(vertices.toArray(new Vector3f[vertices.size()]))); |
||||
mesh.setBuffer(verticesBuffer); |
||||
|
||||
LOGGER.fine("Creating normals buffer (in case of lines it is required if skeleton is applied)."); |
||||
VertexBuffer normalsBuffer = new VertexBuffer(Type.Normal); |
||||
normalsBuffer.setupData(Usage.Static, 3, Format.Float, BufferUtils.createFloatBuffer(normals.toArray(new Vector3f[normals.size()]))); |
||||
mesh.setBuffer(normalsBuffer); |
||||
|
||||
result.put(-1, mesh); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* @return <b>true</b> if the mesh has no vertices and <b>false</b> otherwise |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return vertices == null; |
||||
} |
||||
|
||||
public Map<Integer, List<Integer>> getGlobalVertexReferenceMap() { |
||||
return globalVertexReferenceMap; |
||||
} |
||||
|
||||
/** |
||||
* This method fills the vertex reference map. The vertices are loaded once and referenced many times in the model. This map is created |
||||
* to tell where the basic vertices are referenced in the result vertex lists. The key of the map is the basic vertex index, and its key |
||||
* - the reference indices list. |
||||
* |
||||
* @param basicVertexIndex |
||||
* the index of the vertex from its basic table |
||||
* @param resultIndex |
||||
* the index of the vertex in its result vertex list |
||||
* @param vertexReferenceMap |
||||
* the reference map |
||||
*/ |
||||
private void appendVertexReference(int basicVertexIndex, int resultIndex, Map<Integer, List<Integer>> vertexReferenceMap) { |
||||
List<Integer> referenceList = vertexReferenceMap.get(Integer.valueOf(basicVertexIndex)); |
||||
if (referenceList == null) { |
||||
referenceList = new ArrayList<Integer>(); |
||||
vertexReferenceMap.put(Integer.valueOf(basicVertexIndex), referenceList); |
||||
} |
||||
referenceList.add(Integer.valueOf(resultIndex)); |
||||
} |
||||
} |
||||
|
@ -1,5 +1,174 @@ |
||||
package com.jme3.scene.plugins.blender.meshes.builders; |
||||
|
||||
/*package*/ class PointMeshBuilder { |
||||
//TODO: this will be implemented soon
|
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.HashSet; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
import java.util.logging.Logger; |
||||
|
||||
import com.jme3.math.Vector3f; |
||||
import com.jme3.scene.Mesh; |
||||
import com.jme3.scene.Mesh.Mode; |
||||
import com.jme3.scene.VertexBuffer; |
||||
import com.jme3.scene.VertexBuffer.Format; |
||||
import com.jme3.scene.VertexBuffer.Type; |
||||
import com.jme3.scene.VertexBuffer.Usage; |
||||
import com.jme3.scene.plugins.blender.BlenderContext; |
||||
import com.jme3.scene.plugins.blender.file.BlenderFileException; |
||||
import com.jme3.scene.plugins.blender.file.Pointer; |
||||
import com.jme3.scene.plugins.blender.file.Structure; |
||||
import com.jme3.util.BufferUtils; |
||||
|
||||
/** |
||||
* A builder that creates a points mesh. The result is made of points that do not belong to any edge and face. |
||||
* |
||||
* @author Marcin Roguski (Kaelthas) |
||||
*/ |
||||
/* package */class PointMeshBuilder { |
||||
private static final Logger LOGGER = Logger.getLogger(PointMeshBuilder.class.getName()); |
||||
|
||||
/** An array of reference vertices. */ |
||||
private Vector3f[][] verticesAndNormals; |
||||
/** The vertices of the mesh. */ |
||||
private List<Vector3f> vertices = new ArrayList<Vector3f>(); |
||||
/** The normals of the mesh. */ |
||||
private List<Vector3f> normals = new ArrayList<Vector3f>(); |
||||
|
||||
/** |
||||
* This map's key is the vertex index from 'vertices 'table and the value are indices from 'vertexList' |
||||
* positions (it simply tells which vertex is referenced where in the result list). |
||||
*/ |
||||
private Map<Integer, List<Integer>> globalVertexReferenceMap; |
||||
|
||||
/** |
||||
* Constructor. Stores the given array (not copying it). |
||||
* The second argument describes if the model uses generated textures. If yes then no vertex amount optimisation is applied. |
||||
* The amount of vertices is always faceCount * 3. |
||||
* @param verticesAndNormals |
||||
* the reference vertices and normals array |
||||
*/ |
||||
public PointMeshBuilder(Vector3f[][] verticesAndNormals) { |
||||
this.verticesAndNormals = verticesAndNormals; |
||||
globalVertexReferenceMap = new HashMap<Integer, List<Integer>>(verticesAndNormals.length); |
||||
} |
||||
|
||||
/** |
||||
* The method reads the mesh. Since blender does not store the information in the vertex itself whether it belongs |
||||
* anywhere or not, we need to check all vertices and use here only those that are not used. |
||||
* @param meshStructure |
||||
* the mesh structure |
||||
* @param blenderContext |
||||
* the blender context |
||||
* @throws BlenderFileException |
||||
* an exception thrown when reading from the blend file fails |
||||
*/ |
||||
public void readMesh(Structure meshStructure, BlenderContext blenderContext) throws BlenderFileException { |
||||
LOGGER.fine("Reading points mesh."); |
||||
Pointer pMEdge = (Pointer) meshStructure.getFieldValue("medge"); |
||||
|
||||
if (pMEdge.isNotNull()) { |
||||
int count = ((Number) meshStructure.getFieldValue("totvert")).intValue(); |
||||
Set<Vector3f> usedVertices = new HashSet<Vector3f>(count); |
||||
List<Structure> edges = pMEdge.fetchData(blenderContext.getInputStream()); |
||||
|
||||
for (Structure edge : edges) { |
||||
int v1 = ((Number) edge.getFieldValue("v1")).intValue(); |
||||
int v2 = ((Number) edge.getFieldValue("v2")).intValue(); |
||||
usedVertices.add(verticesAndNormals[v1][0]); |
||||
usedVertices.add(verticesAndNormals[v2][0]); |
||||
} |
||||
|
||||
if (usedVertices.size() < count) { |
||||
vertices = new ArrayList<Vector3f>(count - usedVertices.size()); |
||||
int vertexIndex = 0, blenderVertexIndex = 0; |
||||
for (Vector3f[] vertAndNormal : verticesAndNormals) { |
||||
if (!usedVertices.contains(vertAndNormal[0])) { |
||||
vertices.add(vertAndNormal[0]); |
||||
normals.add(vertAndNormal[1]); |
||||
this.appendVertexReference(blenderVertexIndex, vertexIndex++, globalVertexReferenceMap); |
||||
} |
||||
++blenderVertexIndex; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Builds the meshes. |
||||
* @return a map between material index and the mesh |
||||
*/ |
||||
public Map<Integer, Mesh> buildMeshes() { |
||||
LOGGER.fine("Building point mesh."); |
||||
Map<Integer, Mesh> result = new HashMap<Integer, Mesh>(1); |
||||
|
||||
if (vertices.size() > 0) { |
||||
Mesh mesh = new Mesh(); |
||||
mesh.setMode(Mode.Points); |
||||
mesh.setPointSize(3); |
||||
|
||||
// the point mesh does not need index buffer, but some modifiers applied by importer need it
|
||||
// the 'alone point' situation should be quite rare so not too many resources are wasted here
|
||||
LOGGER.fine("Creating indices buffer."); |
||||
if (vertices.size() <= Short.MAX_VALUE) { |
||||
short[] indices = new short[vertices.size()]; |
||||
for (int i = 0; i < vertices.size(); ++i) { |
||||
indices[i] = (short) i; |
||||
} |
||||
mesh.setBuffer(Type.Index, 1, indices); |
||||
} else { |
||||
int[] indices = new int[vertices.size()]; |
||||
for (int i = 0; i < vertices.size(); ++i) { |
||||
indices[i] = i; |
||||
} |
||||
mesh.setBuffer(Type.Index, 1, indices); |
||||
} |
||||
|
||||
LOGGER.fine("Creating vertices buffer."); |
||||
VertexBuffer verticesBuffer = new VertexBuffer(Type.Position); |
||||
verticesBuffer.setupData(Usage.Static, 3, Format.Float, BufferUtils.createFloatBuffer(vertices.toArray(new Vector3f[vertices.size()]))); |
||||
mesh.setBuffer(verticesBuffer); |
||||
|
||||
LOGGER.fine("Creating normals buffer (in case of points it is required if skeleton is applied)."); |
||||
VertexBuffer normalsBuffer = new VertexBuffer(Type.Normal); |
||||
normalsBuffer.setupData(Usage.Static, 3, Format.Float, BufferUtils.createFloatBuffer(normals.toArray(new Vector3f[normals.size()]))); |
||||
mesh.setBuffer(normalsBuffer); |
||||
|
||||
result.put(-1, mesh); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* @return <b>true</b> if the mesh has no vertices and <b>false</b> otherwise |
||||
*/ |
||||
public boolean isEmpty() { |
||||
return vertices == null; |
||||
} |
||||
|
||||
public Map<Integer, List<Integer>> getGlobalVertexReferenceMap() { |
||||
return globalVertexReferenceMap; |
||||
} |
||||
|
||||
/** |
||||
* This method fills the vertex reference map. The vertices are loaded once and referenced many times in the model. This map is created |
||||
* to tell where the basic vertices are referenced in the result vertex lists. The key of the map is the basic vertex index, and its key |
||||
* - the reference indices list. |
||||
* |
||||
* @param basicVertexIndex |
||||
* the index of the vertex from its basic table |
||||
* @param resultIndex |
||||
* the index of the vertex in its result vertex list |
||||
* @param vertexReferenceMap |
||||
* the reference map |
||||
*/ |
||||
private void appendVertexReference(int basicVertexIndex, int resultIndex, Map<Integer, List<Integer>> vertexReferenceMap) { |
||||
List<Integer> referenceList = vertexReferenceMap.get(Integer.valueOf(basicVertexIndex)); |
||||
if (referenceList == null) { |
||||
referenceList = new ArrayList<Integer>(); |
||||
vertexReferenceMap.put(Integer.valueOf(basicVertexIndex), referenceList); |
||||
} |
||||
referenceList.add(Integer.valueOf(resultIndex)); |
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue