use of com.jme3.scene.plugins.blender.meshes.Edge in project jmonkeyengine by jMonkeyEngine.
the class TemporalMesh method clone.
@Override
public TemporalMesh clone() {
try {
TemporalMesh result = new TemporalMesh(meshStructure, blenderContext, false);
result.name = name;
for (Vector3f v : vertices) {
result.vertices.add(v.clone());
}
for (Vector3f n : normals) {
result.normals.add(n.clone());
}
for (Map<String, Float> group : vertexGroups) {
result.vertexGroups.add(new HashMap<String, Float>(group));
}
for (byte[] vertColor : verticesColors) {
result.verticesColors.add(vertColor.clone());
}
result.materials = materials;
result.properties = properties;
result.boneIndexes.putAll(boneIndexes);
result.postMeshCreationModifiers.addAll(postMeshCreationModifiers);
for (Face face : faces) {
result.faces.add(face.clone());
}
for (Edge edge : edges) {
result.edges.add(edge.clone());
}
for (Point point : points) {
result.points.add(point.clone());
}
result.rebuildIndexesMappings();
return result;
} catch (BlenderFileException e) {
LOGGER.log(Level.SEVERE, "Error while cloning the temporal mesh: {0}. Returning null.", e.getLocalizedMessage());
}
return null;
}
use of com.jme3.scene.plugins.blender.meshes.Edge in project jmonkeyengine by jMonkeyEngine.
the class MaskModifier method removeVertexAt.
/**
* 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);
}
}
}
use of com.jme3.scene.plugins.blender.meshes.Edge in project jmonkeyengine by jMonkeyEngine.
the class Face method contains.
/**
* The method verifies if the edge is contained within the face.
* It means it cannot cross any other edge and it must be inside the face and not outside of it.
* @param edge
* the edge to be checked
* @return <b>true</b> if the given edge is contained within the face and <b>false</b> otherwise
*/
private boolean contains(Edge edge) {
int index1 = edge.getFirstIndex();
int index2 = edge.getSecondIndex();
// check if the line between the vertices is not a border edge of the face
if (!indexes.areNeighbours(index1, index2)) {
for (int i = 0; i < indexes.size(); ++i) {
int i1 = this.getIndex(i - 1);
int i2 = this.getIndex(i);
// check if the edges have no common verts (because if they do, they cannot cross)
if (i1 != index1 && i1 != index2 && i2 != index1 && i2 != index2) {
if (edge.cross(new Edge(i1, i2, 0, false, temporalMesh))) {
return false;
}
}
}
// computing the edge's middle point
Vector3f edgeMiddlePoint = edge.computeCentroid();
// computing the edge that is perpendicular to the given edge and has a length of 1 (length actually does not matter)
Vector3f edgeVector = edge.getSecondVertex().subtract(edge.getFirstVertex());
Vector3f edgeNormal = temporalMesh.getNormals().get(index1).cross(edgeVector).normalizeLocal();
Edge e = new Edge(edgeMiddlePoint, edgeNormal.add(edgeMiddlePoint));
// compute the vectors from the middle point to the crossing between the extended edge 'e' and other edges of the face
List<Vector3f> crossingVectors = new ArrayList<Vector3f>();
for (int i = 0; i < indexes.size(); ++i) {
int i1 = this.getIndex(i);
int i2 = this.getIndex(i + 1);
Vector3f crossPoint = e.getCrossPoint(new Edge(i1, i2, 0, false, temporalMesh), true, false);
if (crossPoint != null) {
crossingVectors.add(crossPoint.subtractLocal(edgeMiddlePoint));
}
}
if (crossingVectors.size() == 0) {
// edges do not cross
return false;
}
// use only distinct vertices (doubles may appear if the crossing point is a vertex)
List<Vector3f> distinctCrossingVectors = new ArrayList<Vector3f>();
for (Vector3f cv : crossingVectors) {
double minDistance = Double.MAX_VALUE;
for (Vector3f dcv : distinctCrossingVectors) {
minDistance = Math.min(minDistance, dcv.distance(cv));
}
if (minDistance > FastMath.FLT_EPSILON) {
distinctCrossingVectors.add(cv);
}
}
if (distinctCrossingVectors.size() == 0) {
throw new IllegalStateException("There MUST be at least 2 crossing vertices!");
}
// checking if all crossing vectors point to the same direction (if yes then the edge is outside the face)
// if at least one vector has different direction that this - it means that the edge is inside the face
float direction = Math.signum(distinctCrossingVectors.get(0).dot(edgeNormal));
for (int i = 1; i < distinctCrossingVectors.size(); ++i) {
if (direction != Math.signum(distinctCrossingVectors.get(i).dot(edgeNormal))) {
return true;
}
}
return false;
}
return true;
}
use of com.jme3.scene.plugins.blender.meshes.Edge in project jmonkeyengine by jMonkeyEngine.
the class Face method findClosestVertex.
/**
* The method finds the closest vertex to the one specified by <b>index</b>.
* If the vertexToIgnore is positive than it will be ignored in the result.
* The closest vertex must be able to create an edge that is fully contained
* within the face and does not cross any other edges. Also if the
* vertexToIgnore is not negative then the condition that the edge between
* the found index and the one to ignore is inside the face must also be
* met.
*
* @param index
* the index of the vertex that needs to have found the nearest
* neighbour
* @param indexToIgnore
* the index to ignore in the result (pass -1 if none is to be
* ignored)
* @return the index of the closest vertex to the given one
*/
private int findClosestVertex(int index, int indexToIgnore) {
int result = -1;
List<Vector3f> vertices = temporalMesh.getVertices();
Vector3f v1 = vertices.get(index);
float distance = Float.MAX_VALUE;
for (int i : indexes) {
if (i != index && i != indexToIgnore) {
Vector3f v2 = vertices.get(i);
float d = v2.distance(v1);
if (d < distance && this.contains(new Edge(index, i, 0, true, temporalMesh)) && (indexToIgnore < 0 || this.contains(new Edge(indexToIgnore, i, 0, true, temporalMesh)))) {
result = i;
distance = d;
}
}
}
return result;
}
use of com.jme3.scene.plugins.blender.meshes.Edge in project jmonkeyengine by jMonkeyEngine.
the class Edge method loadAll.
/**
* The method loads all edges from the given mesh structure that does not belong to any face.
* @param meshStructure
* the mesh structure
* @param temporalMesh
* the owner of the edges
* @return all edges without faces
* @throws BlenderFileException
* an exception is thrown when problems with file reading occur
*/
public static List<Edge> loadAll(Structure meshStructure, TemporalMesh temporalMesh) throws BlenderFileException {
LOGGER.log(Level.FINE, "Loading all edges that do not belong to any face from mesh: {0}", meshStructure.getName());
List<Edge> result = new ArrayList<Edge>();
Pointer pMEdge = (Pointer) meshStructure.getFieldValue("medge");
if (pMEdge.isNotNull()) {
List<Structure> edges = pMEdge.fetchData();
for (Structure edge : edges) {
int flag = ((Number) edge.getFieldValue("flag")).intValue();
int v1 = ((Number) edge.getFieldValue("v1")).intValue();
int v2 = ((Number) edge.getFieldValue("v2")).intValue();
// I do not know why, but blender stores (possibly only sometimes) crease as negative values and shows positive in the editor
float crease = Math.abs(((Number) edge.getFieldValue("crease")).floatValue());
boolean edgeInFace = (flag & Edge.FLAG_EDGE_NOT_IN_FACE) == 0;
result.add(new Edge(v1, v2, crease, edgeInFace, temporalMesh));
}
}
LOGGER.log(Level.FINE, "Loaded {0} edges.", result.size());
return result;
}
Aggregations