Bugfix: fixed a bug that caused ba UV coordinates to be applied on the
face after triangulation Refactoring: made temporal mesh more exposed for external modifications; this allows modifiers to properly modify the mesh and to remove some modifier-specific code from the temporal mesh implementation
This commit is contained in:
parent
1992da3471
commit
6e05304d26
@ -18,7 +18,7 @@ import com.jme3.scene.plugins.blender.meshes.IndexesLoop.IndexPredicate;
|
||||
*
|
||||
* @author Marcin Roguski (Kaelthas)
|
||||
*/
|
||||
/* package */class Edge extends Line {
|
||||
public class Edge extends Line {
|
||||
private static final long serialVersionUID = 7172714692126675311L;
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(Edge.class.getName());
|
||||
|
@ -25,13 +25,13 @@ import com.jme3.scene.plugins.blender.file.Structure;
|
||||
*
|
||||
* @author Marcin Roguski (Kaelthas)
|
||||
*/
|
||||
/* package */class Face implements Comparator<Integer> {
|
||||
public class Face implements Comparator<Integer> {
|
||||
private static final Logger LOGGER = Logger.getLogger(Face.class.getName());
|
||||
|
||||
/** The indexes loop of the face. */
|
||||
private IndexesLoop indexes;
|
||||
|
||||
private List<IndexesLoop> triangulatedFaces;
|
||||
|
||||
private List<IndexesLoop> triangulatedFaces;
|
||||
/** Indicates if the face is smooth or solid. */
|
||||
private boolean smooth;
|
||||
/** The material index of the face. */
|
||||
@ -116,7 +116,14 @@ import com.jme3.scene.plugins.blender.file.Structure;
|
||||
}
|
||||
return indexes.get(indexPosition);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the mesh this face belongs to
|
||||
*/
|
||||
public TemporalMesh getTemporalMesh() {
|
||||
return temporalMesh;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the original indexes of the face
|
||||
*/
|
||||
@ -129,11 +136,11 @@ import com.jme3.scene.plugins.blender.file.Structure;
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<List<Integer>> getCurrentIndexes() {
|
||||
if(triangulatedFaces == null) {
|
||||
if (triangulatedFaces == null) {
|
||||
return Arrays.asList(indexes.getAll());
|
||||
}
|
||||
List<List<Integer>> result = new ArrayList<List<Integer>>(triangulatedFaces.size());
|
||||
for(IndexesLoop loop : triangulatedFaces) {
|
||||
for (IndexesLoop loop : triangulatedFaces) {
|
||||
result.add(loop.getAll());
|
||||
}
|
||||
return result;
|
||||
@ -155,9 +162,10 @@ import com.jme3.scene.plugins.blender.file.Structure;
|
||||
if (triangleIndexes.length != 3) {
|
||||
throw new IllegalArgumentException("Cannot detach triangle with that does not have 3 indexes!");
|
||||
}
|
||||
MeshHelper meshHelper = temporalMesh.getBlenderContext().getHelper(MeshHelper.class);
|
||||
List<Face> detachedFaces = new ArrayList<Face>();
|
||||
List<Integer> path = new ArrayList<Integer>(indexes.size());
|
||||
|
||||
|
||||
boolean[] edgeRemoved = new boolean[] { indexes.removeEdge(triangleIndexes[0], triangleIndexes[1]), indexes.removeEdge(triangleIndexes[0], triangleIndexes[2]), indexes.removeEdge(triangleIndexes[1], triangleIndexes[2]) };
|
||||
Integer[][] indexesPairs = new Integer[][] { new Integer[] { triangleIndexes[0], triangleIndexes[1] }, new Integer[] { triangleIndexes[0], triangleIndexes[2] }, new Integer[] { triangleIndexes[1], triangleIndexes[2] } };
|
||||
|
||||
@ -171,7 +179,8 @@ import com.jme3.scene.plugins.blender.file.Structure;
|
||||
throw new IllegalStateException("Triangulation failed. Cannot find path between two indexes. Please apply triangulation in Blender as a workaround.");
|
||||
}
|
||||
if (detachedFaces.size() == 0 && path.size() < indexes.size()) {
|
||||
detachedFaces.add(new Face(path.toArray(new Integer[path.size()]), smooth, materialNumber, faceUVCoords, vertexColors, temporalMesh));
|
||||
Integer[] indexesSublist = path.toArray(new Integer[path.size()]);
|
||||
detachedFaces.add(new Face(indexesSublist, smooth, materialNumber, meshHelper.selectUVSubset(this, indexesSublist), vertexColors, temporalMesh));
|
||||
for (int j = 0; j < path.size() - 1; ++j) {
|
||||
indexes.removeEdge(path.get(j), path.get(j + 1));
|
||||
}
|
||||
@ -244,17 +253,13 @@ import com.jme3.scene.plugins.blender.file.Structure;
|
||||
|
||||
/**
|
||||
* The method triangulates the face.
|
||||
* @param vertices
|
||||
* the vertices of the mesh (all verts and not only those belonging to the face)
|
||||
* @param normals
|
||||
* the normals of the mesh (all normals and not only those belonging to the face)
|
||||
*/
|
||||
public void triangulate(List<Vector3f> vertices, List<Vector3f> normals) {
|
||||
public void triangulate() {
|
||||
LOGGER.fine("Triangulating face.");
|
||||
assert indexes.size() >= 3 : "Invalid indexes amount for face. 3 is the required minimum!";
|
||||
triangulatedFaces = new ArrayList<IndexesLoop>(indexes.size() - 2);
|
||||
Integer[] indexes = new Integer[3];
|
||||
|
||||
|
||||
try {
|
||||
List<Face> facesToTriangulate = new ArrayList<Face>(Arrays.asList(this.clone()));
|
||||
while (facesToTriangulate.size() > 0) {
|
||||
@ -264,30 +269,27 @@ import com.jme3.scene.plugins.blender.file.Structure;
|
||||
indexes[0] = face.getIndex(0);
|
||||
indexes[1] = face.findClosestVertex(indexes[0], -1);
|
||||
indexes[2] = face.findClosestVertex(indexes[0], indexes[1]);
|
||||
|
||||
|
||||
LOGGER.finer("Veryfying improper triangulation of the temporal mesh.");
|
||||
if(indexes[0] < 0 || indexes[1] < 0 || indexes[2] < 0) {
|
||||
throw new BlenderFileException("Unable to find two closest vertices while triangulating face in mesh: " + temporalMesh +
|
||||
"Please apply triangulation modifier in blender as a workaround and load again!");
|
||||
if (indexes[0] < 0 || indexes[1] < 0 || indexes[2] < 0) {
|
||||
throw new BlenderFileException("Unable to find two closest vertices while triangulating face in mesh: " + temporalMesh + "Please apply triangulation modifier in blender as a workaround and load again!");
|
||||
}
|
||||
if(previousIndex1 == indexes[0] && previousIndex2 == indexes[1] && previousIndex3 == indexes[2]) {
|
||||
throw new BlenderFileException("Infinite loop detected during triangulation of mesh: " + temporalMesh +
|
||||
"Please apply triangulation modifier in blender as a workaround and load again!");
|
||||
if (previousIndex1 == indexes[0] && previousIndex2 == indexes[1] && previousIndex3 == indexes[2]) {
|
||||
throw new BlenderFileException("Infinite loop detected during triangulation of mesh: " + temporalMesh + "Please apply triangulation modifier in blender as a workaround and load again!");
|
||||
}
|
||||
previousIndex1 = indexes[0];
|
||||
previousIndex2 = indexes[1];
|
||||
previousIndex3 = indexes[2];
|
||||
|
||||
|
||||
Arrays.sort(indexes, this);
|
||||
facesToTriangulate.addAll(face.detachTriangle(indexes));
|
||||
triangulatedFaces.add(new IndexesLoop(indexes));
|
||||
}
|
||||
}
|
||||
} catch(BlenderFileException e) {
|
||||
LOGGER.log(Level.WARNING, "Errors occured during face triangulation: {0}. The face will be triangulated with the most direct algorithm, " +
|
||||
"but the results might not be identical to blender.", e.getLocalizedMessage());
|
||||
} catch (BlenderFileException e) {
|
||||
LOGGER.log(Level.WARNING, "Errors occured during face triangulation: {0}. The face will be triangulated with the most direct algorithm, " + "but the results might not be identical to blender.", e.getLocalizedMessage());
|
||||
indexes[0] = this.getIndex(0);
|
||||
for(int i=1;i<this.vertexCount() - 1;++i) {
|
||||
for (int i = 1; i < this.vertexCount() - 1; ++i) {
|
||||
indexes[1] = this.getIndex(i);
|
||||
indexes[2] = this.getIndex(i + 1);
|
||||
triangulatedFaces.add(new IndexesLoop(indexes));
|
||||
|
@ -36,6 +36,7 @@ import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@ -317,6 +318,29 @@ public class MeshHelper extends AbstractBlenderHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the proper subsets of UV coordinates for the given sublist of indexes.
|
||||
* @param face
|
||||
* the face with the original UV sets
|
||||
* @param indexesSublist
|
||||
* the sub list of indexes
|
||||
* @return a map of UV coordinates subsets
|
||||
*/
|
||||
public Map<String, List<Vector2f>> selectUVSubset(Face face, Integer... indexesSublist) {
|
||||
Map<String, List<Vector2f>> result = null;
|
||||
if (face.getUvSets() != null) {
|
||||
result = new HashMap<String, List<Vector2f>>();
|
||||
for (Entry<String, List<Vector2f>> entry : face.getUvSets().entrySet()) {
|
||||
List<Vector2f> uvs = new ArrayList<Vector2f>(indexesSublist.length);
|
||||
for (Integer index : indexesSublist) {
|
||||
uvs.add(entry.getValue().get(face.getIndexes().indexOf(index)));
|
||||
}
|
||||
result.put(entry.getKey(), uvs);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the black unshaded material. It is used for lines and points because that is how blender
|
||||
* renders it.
|
||||
|
@ -17,7 +17,7 @@ import com.jme3.scene.plugins.blender.meshes.IndexesLoop.IndexPredicate;
|
||||
*
|
||||
* @author Marcin Roguski (Kaelthas)
|
||||
*/
|
||||
/* package */class Point {
|
||||
public class Point {
|
||||
private static final Logger LOGGER = Logger.getLogger(Point.class.getName());
|
||||
|
||||
/** The point's index. */
|
||||
|
@ -4,15 +4,11 @@ import java.nio.IntBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@ -32,7 +28,6 @@ import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
|
||||
import com.jme3.scene.plugins.blender.file.BlenderFileException;
|
||||
import com.jme3.scene.plugins.blender.file.Structure;
|
||||
import com.jme3.scene.plugins.blender.materials.MaterialContext;
|
||||
import com.jme3.scene.plugins.blender.meshes.IndexesLoop.IndexPredicate;
|
||||
import com.jme3.scene.plugins.blender.meshes.MeshBuffers.BoneBuffersData;
|
||||
import com.jme3.scene.plugins.blender.modifiers.Modifier;
|
||||
import com.jme3.scene.plugins.blender.objects.Properties;
|
||||
@ -123,6 +118,62 @@ public class TemporalMesh extends Geometry {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the blender context
|
||||
*/
|
||||
public BlenderContext getBlenderContext() {
|
||||
return blenderContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the vertices of the mesh
|
||||
*/
|
||||
public List<Vector3f> getVertices() {
|
||||
return vertices;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the normals of the mesh
|
||||
*/
|
||||
public List<Vector3f> getNormals() {
|
||||
return normals;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all faces
|
||||
*/
|
||||
public List<Face> getFaces() {
|
||||
return faces;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all edges
|
||||
*/
|
||||
public List<Edge> getEdges() {
|
||||
return edges;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all points (do not mistake it with vertices)
|
||||
*/
|
||||
public List<Point> getPoints() {
|
||||
return points;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all vertices colors
|
||||
*/
|
||||
public List<byte[]> getVerticesColors() {
|
||||
return verticesColors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all vertex groups for the vertices (each map has groups for the proper vertex)
|
||||
*/
|
||||
public List<Map<String, Float>> getVertexGroups() {
|
||||
return vertexGroups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TemporalMesh clone() {
|
||||
try {
|
||||
@ -159,20 +210,6 @@ public class TemporalMesh extends Geometry {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the vertices of the mesh
|
||||
*/
|
||||
protected List<Vector3f> getVertices() {
|
||||
return vertices;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the normals of the mesh
|
||||
*/
|
||||
protected List<Vector3f> getNormals() {
|
||||
return normals;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateModelBound() {
|
||||
if (boundingBox == null) {
|
||||
@ -212,7 +249,7 @@ public class TemporalMesh extends Geometry {
|
||||
public void triangulate() {
|
||||
LOGGER.fine("Triangulating temporal mesh.");
|
||||
for (Face face : faces) {
|
||||
face.triangulate(vertices, normals);
|
||||
face.triangulate();
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,19 +285,6 @@ public class TemporalMesh extends Geometry {
|
||||
boneIndexes.putAll(mesh.boneIndexes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate all vertices by the given vector.
|
||||
* @param translation
|
||||
* the translation vector
|
||||
* @return this mesh after translation (NO new instance is created)
|
||||
*/
|
||||
public TemporalMesh translate(Vector3f translation) {
|
||||
for (Vector3f v : vertices) {
|
||||
v.addLocal(translation);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the properties of the mesh.
|
||||
* @param properties
|
||||
@ -304,47 +328,6 @@ public class TemporalMesh extends Geometry {
|
||||
return vertices.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vertex at the given position.
|
||||
* @param i
|
||||
* the vertex position
|
||||
* @return the vertex at the given position
|
||||
*/
|
||||
public Vector3f getVertex(int i) {
|
||||
return vertices.get(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the normal at the given position.
|
||||
* @param i
|
||||
* the normal position
|
||||
* @return the normal at the given position
|
||||
*/
|
||||
public Vector3f getNormal(int i) {
|
||||
return normals.get(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vertex groups at the given vertex index.
|
||||
* @param i
|
||||
* the vertex groups for vertex with a given index
|
||||
* @return the vertex groups at the given vertex index
|
||||
*/
|
||||
public Map<String, Float> getVertexGroups(int i) {
|
||||
return vertexGroups.size() > i ? vertexGroups.get(i) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a collection of vertex group names for this mesh
|
||||
*/
|
||||
public Collection<String> getVertexGroupNames() {
|
||||
Set<String> result = new HashSet<String>();
|
||||
for (Map<String, Float> groups : vertexGroups) {
|
||||
result.addAll(groups.keySet());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all vertices from the mesh.
|
||||
*/
|
||||
@ -358,86 +341,6 @@ public class TemporalMesh extends Geometry {
|
||||
points.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Every face, edge and point that contains
|
||||
* the vertex will be removed.
|
||||
* @param index
|
||||
* the index of a vertex to be removed
|
||||
* @throws IndexOutOfBoundsException
|
||||
* thrown when given index is negative or beyond the count of vertices
|
||||
*/
|
||||
public void removeVertexAt(final int index) {
|
||||
if (index < 0 || index >= vertices.size()) {
|
||||
throw new IndexOutOfBoundsException("The given index is out of bounds: " + index);
|
||||
}
|
||||
|
||||
vertices.remove(index);
|
||||
normals.remove(index);
|
||||
if(vertexGroups.size() > 0) {
|
||||
vertexGroups.remove(index);
|
||||
}
|
||||
if(verticesColors.size() > 0) {
|
||||
verticesColors.remove(index);
|
||||
}
|
||||
|
||||
IndexPredicate shiftPredicate = new IndexPredicate() {
|
||||
@Override
|
||||
public boolean execute(Integer i) {
|
||||
return i > index;
|
||||
}
|
||||
};
|
||||
for (int i = faces.size() - 1; i >= 0; --i) {
|
||||
Face face = faces.get(i);
|
||||
if (face.getIndexes().indexOf(index) >= 0) {
|
||||
faces.remove(i);
|
||||
} else {
|
||||
face.getIndexes().shiftIndexes(-1, shiftPredicate);
|
||||
}
|
||||
}
|
||||
for (int i = edges.size() - 1; i >= 0; --i) {
|
||||
Edge edge = edges.get(i);
|
||||
if (edge.getFirstIndex() == index || edge.getSecondIndex() == index) {
|
||||
edges.remove(i);
|
||||
} else {
|
||||
edge.shiftIndexes(-1, shiftPredicate);
|
||||
}
|
||||
}
|
||||
for (int i = points.size() - 1; i >= 0; --i) {
|
||||
Point point = points.get(i);
|
||||
if (point.getIndex() == index) {
|
||||
points.remove(i);
|
||||
} else {
|
||||
point.shiftIndexes(-1, shiftPredicate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flips the order of the mesh's indexes.
|
||||
*/
|
||||
public void flipIndexes() {
|
||||
for (Face face : faces) {
|
||||
face.flipIndexes();
|
||||
}
|
||||
for (Edge edge : edges) {
|
||||
edge.flipIndexes();
|
||||
}
|
||||
Collections.reverse(points);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flips UV coordinates.
|
||||
* @param u
|
||||
* indicates if U coords should be flipped
|
||||
* @param v
|
||||
* indicates if V coords should be flipped
|
||||
*/
|
||||
public void flipUV(boolean u, boolean v) {
|
||||
for (Face face : faces) {
|
||||
face.flipUV(u, v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The mesh builds geometries from the mesh. The result is stored in the blender context
|
||||
* under the mesh's OMA.
|
||||
@ -513,7 +416,8 @@ public class TemporalMesh extends Geometry {
|
||||
}
|
||||
}
|
||||
|
||||
meshBuffers.append(face.isSmooth(), tempVerts, tempNormals, face.getUvSets(), tempVertColors, boneBuffers);
|
||||
Map<String, List<Vector2f>> uvs = meshHelper.selectUVSubset(face, indexes.toArray(new Integer[indexes.size()]));
|
||||
meshBuffers.append(face.isSmooth(), tempVerts, tempNormals, uvs, tempVertColors, boneBuffers);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,15 +210,28 @@ import com.jme3.scene.shape.Curve;
|
||||
if (count > 0) {
|
||||
TemporalMesh originalMesh = temporalMesh.clone();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
temporalMesh.append(originalMesh.clone().translate(totalTranslation));
|
||||
TemporalMesh clone = originalMesh.clone();
|
||||
for (Vector3f v : clone.getVertices()) {
|
||||
v.addLocal(totalTranslation);
|
||||
}
|
||||
temporalMesh.append(clone);
|
||||
totalTranslation.addLocal(translationVector);
|
||||
}
|
||||
}
|
||||
if (caps[0] != null) {
|
||||
temporalMesh.append(caps[0].clone().translate(translationVector.multLocal(-1)));
|
||||
translationVector.multLocal(-1);
|
||||
TemporalMesh capsClone = caps[0].clone();
|
||||
for (Vector3f v : capsClone.getVertices()) {
|
||||
v.addLocal(translationVector);
|
||||
}
|
||||
temporalMesh.append(capsClone);
|
||||
}
|
||||
if (caps[1] != null) {
|
||||
temporalMesh.append(caps[1].clone().translate(totalTranslation));
|
||||
TemporalMesh capsClone = caps[1].clone();
|
||||
for (Vector3f v : capsClone.getVertices()) {
|
||||
v.addLocal(totalTranslation);
|
||||
}
|
||||
temporalMesh.append(capsClone);
|
||||
}
|
||||
} else {
|
||||
LOGGER.log(Level.WARNING, "Cannot find temporal mesh for node: {0}. The modifier will NOT be applied!", node);
|
||||
|
@ -1,10 +1,11 @@
|
||||
package com.jme3.scene.plugins.blender.modifiers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@ -14,6 +15,10 @@ import com.jme3.scene.plugins.blender.animations.BoneContext;
|
||||
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.scene.plugins.blender.meshes.Edge;
|
||||
import com.jme3.scene.plugins.blender.meshes.Face;
|
||||
import com.jme3.scene.plugins.blender.meshes.IndexesLoop.IndexPredicate;
|
||||
import com.jme3.scene.plugins.blender.meshes.Point;
|
||||
import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
|
||||
|
||||
/**
|
||||
@ -22,12 +27,12 @@ import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
|
||||
* @author Marcin Roguski (Kaelthas)
|
||||
*/
|
||||
/* package */class MaskModifier extends Modifier {
|
||||
private static final Logger LOGGER = Logger.getLogger(MaskModifier.class.getName());
|
||||
private static final Logger LOGGER = Logger.getLogger(MaskModifier.class.getName());
|
||||
|
||||
private static final int FLAG_INVERT_MASK = 0x01;
|
||||
private static final int FLAG_INVERT_MASK = 0x01;
|
||||
|
||||
private static final int MODE_VERTEX_GROUP = 0;
|
||||
private static final int MODE_ARMATURE = 1;
|
||||
private static final int MODE_VERTEX_GROUP = 0;
|
||||
private static final int MODE_ARMATURE = 1;
|
||||
|
||||
private Pointer pArmatureObject;
|
||||
private String vertexGroupName;
|
||||
@ -37,7 +42,7 @@ import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
|
||||
if (this.validate(modifierStructure, blenderContext)) {
|
||||
int flag = ((Number) modifierStructure.getFieldValue("flag")).intValue();
|
||||
invertMask = (flag & FLAG_INVERT_MASK) != 0;
|
||||
|
||||
|
||||
int mode = ((Number) modifierStructure.getFieldValue("mode")).intValue();
|
||||
if (mode == MODE_VERTEX_GROUP) {
|
||||
vertexGroupName = modifierStructure.getFieldValue("vgroup").toString();
|
||||
@ -78,7 +83,10 @@ import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
|
||||
// if the mesh has no vertex groups then remove all verts
|
||||
// if the mesh has at least one vertex group - then do nothing
|
||||
// I have no idea why we should do that, but blender works this way
|
||||
Collection<String> vertexGroupNames = temporalMesh.getVertexGroupNames();
|
||||
Set<String> vertexGroupNames = new HashSet<String>();
|
||||
for (Map<String, Float> groups : temporalMesh.getVertexGroups()) {
|
||||
vertexGroupNames.addAll(groups.keySet());
|
||||
}
|
||||
if (vertexGroupNames.size() == 0 && !invertMask || vertexGroupNames.size() > 0 && invertMask) {
|
||||
temporalMesh.clear();
|
||||
}
|
||||
@ -87,9 +95,9 @@ import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
|
||||
if (vertexGroupsToRemove.size() > 0) {
|
||||
List<Integer> vertsToBeRemoved = new ArrayList<Integer>();
|
||||
for (int i = 0; i < temporalMesh.getVertexCount(); ++i) {
|
||||
Map<String, Float> vertexGroups = temporalMesh.getVertexGroups(i);
|
||||
Map<String, Float> vertexGroups = temporalMesh.getVertexGroups().get(i);
|
||||
boolean hasVertexGroup = false;
|
||||
if(vertexGroups != null) {
|
||||
if (vertexGroups != null) {
|
||||
for (String groupName : vertexGroupsToRemove) {
|
||||
Float weight = vertexGroups.get(groupName);
|
||||
if (weight != null && weight > 0) {
|
||||
@ -106,7 +114,7 @@ import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
|
||||
|
||||
Collections.reverse(vertsToBeRemoved);
|
||||
for (Integer vertexIndex : vertsToBeRemoved) {
|
||||
temporalMesh.removeVertexAt(vertexIndex);
|
||||
this.removeVertexAt(vertexIndex, temporalMesh);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -115,6 +123,60 @@ import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Every face, edge and point that contains
|
||||
* the vertex will be removed.
|
||||
* @param index
|
||||
* the index of a vertex to be removed
|
||||
* @throws IndexOutOfBoundsException
|
||||
* thrown when given index is negative or beyond the count of vertices
|
||||
*/
|
||||
private void removeVertexAt(final int index, TemporalMesh temporalMesh) {
|
||||
if (index < 0 || index >= temporalMesh.getVertexCount()) {
|
||||
throw new IndexOutOfBoundsException("The given index is out of bounds: " + index);
|
||||
}
|
||||
|
||||
temporalMesh.getVertices().remove(index);
|
||||
temporalMesh.getNormals().remove(index);
|
||||
if (temporalMesh.getVertexGroups().size() > 0) {
|
||||
temporalMesh.getVertexGroups().remove(index);
|
||||
}
|
||||
if (temporalMesh.getVerticesColors().size() > 0) {
|
||||
temporalMesh.getVerticesColors().remove(index);
|
||||
}
|
||||
|
||||
IndexPredicate shiftPredicate = new IndexPredicate() {
|
||||
@Override
|
||||
public boolean execute(Integer i) {
|
||||
return i > index;
|
||||
}
|
||||
};
|
||||
for (int i = temporalMesh.getFaces().size() - 1; i >= 0; --i) {
|
||||
Face face = temporalMesh.getFaces().get(i);
|
||||
if (face.getIndexes().indexOf(index) >= 0) {
|
||||
temporalMesh.getFaces().remove(i);
|
||||
} else {
|
||||
face.getIndexes().shiftIndexes(-1, shiftPredicate);
|
||||
}
|
||||
}
|
||||
for (int i = temporalMesh.getEdges().size() - 1; i >= 0; --i) {
|
||||
Edge edge = temporalMesh.getEdges().get(i);
|
||||
if (edge.getFirstIndex() == index || edge.getSecondIndex() == index) {
|
||||
temporalMesh.getEdges().remove(i);
|
||||
} else {
|
||||
edge.shiftIndexes(-1, shiftPredicate);
|
||||
}
|
||||
}
|
||||
for (int i = temporalMesh.getPoints().size() - 1; i >= 0; --i) {
|
||||
Point point = temporalMesh.getPoints().get(i);
|
||||
if (point.getIndex() == index) {
|
||||
temporalMesh.getPoints().remove(i);
|
||||
} else {
|
||||
point.shiftIndexes(-1, shiftPredicate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the names of the bones from the given bone base.
|
||||
* @param boneBase
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.jme3.scene.plugins.blender.modifiers;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@ -10,6 +11,8 @@ 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.scene.plugins.blender.meshes.Edge;
|
||||
import com.jme3.scene.plugins.blender.meshes.Face;
|
||||
import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
|
||||
import com.jme3.scene.plugins.blender.objects.ObjectHelper;
|
||||
|
||||
@ -69,8 +72,8 @@ import com.jme3.scene.plugins.blender.objects.ObjectHelper;
|
||||
|
||||
tolerance = ((Number) modifierStructure.getFieldValue("tolerance")).floatValue();
|
||||
pMirrorObject = (Pointer) modifierStructure.getFieldValue("mirror_ob");
|
||||
|
||||
if(mirrorVGroup) {
|
||||
|
||||
if (mirrorVGroup) {
|
||||
LOGGER.warning("Mirroring vertex groups is currently not supported.");
|
||||
}
|
||||
}
|
||||
@ -117,8 +120,8 @@ import com.jme3.scene.plugins.blender.objects.ObjectHelper;
|
||||
|
||||
TemporalMesh mirror = temporalMesh.clone();
|
||||
for (int i = 0; i < mirror.getVertexCount(); ++i) {
|
||||
Vector3f vertex = mirror.getVertex(i);
|
||||
Vector3f normal = mirror.getNormal(i);
|
||||
Vector3f vertex = mirror.getVertices().get(i);
|
||||
Vector3f normal = mirror.getNormals().get(i);
|
||||
|
||||
if (mirrorAtPoint0) {
|
||||
d = Math.abs(vertex.get(mirrorIndex));
|
||||
@ -131,18 +134,27 @@ import com.jme3.scene.plugins.blender.objects.ObjectHelper;
|
||||
if (merge && d <= tolerance) {
|
||||
vertex.addLocal(shiftVector);
|
||||
normal.set(mirrorIndex, 0);
|
||||
temporalMesh.getVertex(i).addLocal(shiftVector);
|
||||
temporalMesh.getNormal(i).set(mirrorIndex, 0);
|
||||
temporalMesh.getVertices().get(i).addLocal(shiftVector);
|
||||
temporalMesh.getNormals().get(i).set(mirrorIndex, 0);
|
||||
} else {
|
||||
vertex.addLocal(shiftVector.multLocal(2));
|
||||
normal.set(mirrorIndex, -normal.get(mirrorIndex));
|
||||
}
|
||||
}
|
||||
|
||||
mirror.flipIndexes();
|
||||
// flipping the indexes
|
||||
for (Face face : mirror.getFaces()) {
|
||||
face.flipIndexes();
|
||||
}
|
||||
for (Edge edge : mirror.getEdges()) {
|
||||
edge.flipIndexes();
|
||||
}
|
||||
Collections.reverse(mirror.getPoints());
|
||||
|
||||
if (mirrorU || mirrorV) {
|
||||
mirror.flipUV(mirrorU, mirrorV);
|
||||
for (Face face : mirror.getFaces()) {
|
||||
face.flipUV(mirrorU, mirrorV);
|
||||
}
|
||||
}
|
||||
|
||||
temporalMesh.append(mirror);
|
||||
|
Loading…
x
Reference in New Issue
Block a user