Skip to content
Snippets Groups Projects
Commit c8d95027 authored by Radek Ošlejšek's avatar Radek Ošlejšek
Browse files

Merge branch 'master' into 'issue16'

# Conflicts:
#   MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/MeshObjLoader.java
parents 9bda05d1 e5bc6640
No related branches found
No related tags found
No related merge requests found
...@@ -10,6 +10,7 @@ import com.mokiat.data.front.parser.OBJObject; ...@@ -10,6 +10,7 @@ import com.mokiat.data.front.parser.OBJObject;
import com.mokiat.data.front.parser.OBJParser; import com.mokiat.data.front.parser.OBJParser;
import com.mokiat.data.front.parser.OBJTexCoord; import com.mokiat.data.front.parser.OBJTexCoord;
import com.mokiat.data.front.parser.OBJVertex; import com.mokiat.data.front.parser.OBJVertex;
import cz.fidentis.analyst.mesh.core.CornerTableRow;
import cz.fidentis.analyst.mesh.core.MeshFacet; import cz.fidentis.analyst.mesh.core.MeshFacet;
import cz.fidentis.analyst.mesh.core.MeshModel; import cz.fidentis.analyst.mesh.core.MeshModel;
import cz.fidentis.analyst.mesh.core.MeshPoint; import cz.fidentis.analyst.mesh.core.MeshPoint;
...@@ -21,10 +22,11 @@ import java.io.FileNotFoundException; ...@@ -21,10 +22,11 @@ import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
//import cz.fidentis.analyst.mesh.core.MeshEdge; import java.util.Objects;
//import cz.fidentis.analyst.mesh.core.MeshFace; import javax.vecmath.Vector3d;
/** /**
...@@ -33,7 +35,20 @@ import java.util.List; ...@@ -33,7 +35,20 @@ import java.util.List;
* @author Marek Bařinka * @author Marek Bařinka
*/ */
public class MeshObjLoader { public class MeshObjLoader {
/**
* Opens file and loads data into MeshModel
* @param file File containing face to load into a MeshModel
* @return Complete MeshModel
* @throws FileNotFoundException Requested file was not found
* @throws IOException There was problem with reading the file
*/
public static MeshModel read(File file) throws FileNotFoundException, IOException {
try (InputStream is = new FileInputStream(file)) {
return read(is);
}
}
/** /**
* Loads data into MeshModel * Loads data into MeshModel
* @param is Input data stream with model * @param is Input data stream with model
...@@ -47,23 +62,10 @@ public class MeshObjLoader { ...@@ -47,23 +62,10 @@ public class MeshObjLoader {
if (model.getObjects().isEmpty()) { if (model.getObjects().isEmpty()) {
throw new IOException("File doesn't contain any model"); throw new IOException("File doesn't contain any model");
} }
OBJObject object = model.getObjects().get(0); OBJObject object = model.getObjects().get(0);
return parseObjectToModel(model, object); return parseObjectToModel(model, object);
} }
/**
* Opens file and loads data into MeshModel
* @param file File containing face to load into a MeshModel
* @return Complete MeshModel
* @throws FileNotFoundException Requested file was not found
* @throws IOException There was problem with reading the file
*/
public static MeshModel read(File file) throws FileNotFoundException, IOException {
try (InputStream is = new FileInputStream(file)) {
return read(is);
}
}
/** /**
* Parse OBJObject into MeshModel * Parse OBJObject into MeshModel
* @param model Model is needed in future. It's holding data pools * @param model Model is needed in future. It's holding data pools
...@@ -76,66 +78,94 @@ public class MeshObjLoader { ...@@ -76,66 +78,94 @@ public class MeshObjLoader {
// Our facet = loader mesh, create and fill all facets // Our facet = loader mesh, create and fill all facets
for (OBJMesh mesh : object.getMeshes()) { for (OBJMesh mesh : object.getMeshes()) {
MeshFacet meshFacet = parseMeshToFacet(model, mesh); MeshFacet meshFacet = parseMeshToFacet(model, mesh);
// meshModel.addChild(meshFacet); meshModel.addFacet(meshFacet);
} }
return meshModel; return meshModel;
} }
/** /**
* Parse OBJMesh into MeshFacet * Parse OBJMesh into MeshFacet containig corner table data
* @param model Model is needed in future. It's holding data pools * @param model Model is needed in future. It's holding data pools
* @param mesh Mesh to parse. It corespond to our MeshMacet * @param mesh Mesh to parse. It corespond to our MeshFacet
* @return Returns complete facet * @return Returns complete facet
* @throws IOException Data are corrupted * @throws IOException Data are corrupted
*/ */
private static MeshFacet parseMeshToFacet(OBJModel model, OBJMesh mesh) throws IOException { private static MeshFacet parseMeshToFacet(OBJModel model, OBJMesh mesh) throws IOException {
MeshFacet meshFacet = new MeshFacet(); MeshFacet meshFacet = new MeshFacet();
Map<MeshPoint, Integer> vertices = new HashMap();
Map<Edge, Integer> edges = new HashMap();
for (OBJFace face : mesh.getFaces()) { for (OBJFace face : mesh.getFaces()) {
// MeshFace meshFace = parseFaceToFace(model, face, meshFacet); processFace(model, face, meshFacet, vertices, edges);
// meshFacet.addChild(meshFace);
} }
return meshFacet; return meshFacet;
} }
/** /**
* Parse OBJFace into MeshFace * Process one face in source data into data and insert them into CornerTable
* @param model Model is needed in future. It's holding data pools * @param model Model is needed in future. It's holding data pools
* @param face Face to parse. It corespond to our MeshFace * @param face Face to process
* @param meshFacet Facet is holding our data pools * @param meshFacet MeshFacet containing data pools
* @return Returns complete face * @param vertices Map containing information about processed vertices
* and their index in CornerTable
* @param edges Map containing edges and index of their opposite vertex
* @throws IOException Data are corrupted * @throws IOException Data are corrupted
*/ */
/*
private static MeshFace parseFaceToFace(OBJModel model, OBJFace face, MeshFacet meshFacet) throws IOException {
List<MeshPoint> facePoints = getPointsFromFace(model, face, meshFacet);
MeshFace meshFace = new MeshFace();
if (facePoints.size() != 3) { private static void processFace(OBJModel model, OBJFace face, MeshFacet meshFacet,
throw new IOException("Data contains non-triangular face"); Map<MeshPoint, Integer> vertices, Map<Edge, Integer> edges) throws IOException {
List<MeshPoint> trianglePoints = parseFaceToTriangle(model, face);
List<Integer> vertexIndicies = new ArrayList();
// This cycle adds integer indices of new mesh points and add them to CornerTable
for (MeshPoint vertex : trianglePoints) {
Integer vertIndex = vertices.get(vertex);
if (vertIndex == null) {
int newIndex = meshFacet.getNumberOfVertexes();
vertices.put(vertex, newIndex);
meshFacet.addVertex(vertex);
vertIndex = newIndex;
}
vertexIndicies.add(vertIndex);
CornerTableRow cornerTableRow = new CornerTableRow(vertIndex, -1);
meshFacet.getCornerTable().addRow(cornerTableRow);
} }
// Create edges
for (int i = 1; i <= facePoints.size(); i++) { List<Edge> triangleEdges = new ArrayList();
MeshEdge meshEdge = new MeshEdge(facePoints.get((i-1)%facePoints.size()), triangleEdges.add(new Edge(trianglePoints.get(0).getPosition(),
facePoints.get((i)%facePoints.size())); trianglePoints.get(1).getPosition(), vertexIndicies.get(2)));
meshEdge = meshFacet.getEdge(meshEdge); triangleEdges.add(new Edge(trianglePoints.get(1).getPosition(),
meshFace.addChild(meshEdge); trianglePoints.get(2).getPosition(), vertexIndicies.get(0)));
triangleEdges.add(new Edge(trianglePoints.get(2).getPosition(),
trianglePoints.get(0).getPosition(), vertexIndicies.get(1)));
for (Edge e : triangleEdges) {
// We are processing edge which we already found
// We can set corner.opposite on both corners
if (edges.containsKey(e)) {
int oppositeCornerIndex = edges.get(e);
meshFacet.getCornerTable().getRow(oppositeCornerIndex).setOppositeCornerIndex(e.getCornerIndex());
meshFacet.getCornerTable().getRow(e.getCornerIndex()).setOppositeCornerIndex(oppositeCornerIndex);
edges.remove(e);
} else {
edges.put(e, e.getCornerIndex());
}
} }
return meshFace;
} }
*/
/** /**
* Creates list of points from one face * Parse face from face data into list of MeshPoint
* @param model Model holds points pool * @param model Model contains data pool
* @param face Face for which points are loaded * @param face Face contains information about actually processed triangle
* @param meshFacet Facet holds points pool * @return List containing three MeshPoints parsed from face
* @return List of all points from one face * @throws IOException If face is non-triangular
*/ */
private static List<MeshPoint> getPointsFromFace(OBJModel model, OBJFace face, MeshFacet meshFacet) { private static List<MeshPoint> parseFaceToTriangle(OBJModel model, OBJFace face) throws IOException {
List<MeshPoint> result = new ArrayList();
List<OBJDataReference> references = face.getReferences(); List<OBJDataReference> references = face.getReferences();
List<MeshPoint> points = new ArrayList();
for (OBJDataReference reference : references) { for (OBJDataReference reference : references) {
final OBJVertex vertex = model.getVertex(reference); final OBJVertex vertex = model.getVertex(reference);
Vector3d coords = new Vector3d(vertex.x, vertex.y, vertex.z); Vector3d coords = new Vector3d(vertex.x, vertex.y, vertex.z);
...@@ -149,9 +179,74 @@ public class MeshObjLoader { ...@@ -149,9 +179,74 @@ public class MeshObjLoader {
final OBJTexCoord texCoord = model.getTexCoord(reference); final OBJTexCoord texCoord = model.getTexCoord(reference);
texCoords = new Vector3d(texCoord.u, texCoord.v, texCoord.w); texCoords = new Vector3d(texCoord.u, texCoord.v, texCoord.w);
} }
// MeshPoint meshPoint = meshFacet.getPoint(new MeshPoint(coords, norm, texCoords)); result.add(new MeshPoint(coords, norm, texCoords));
// points.add(meshPoint); }
if (result.size() != 3) {
throw new IOException("Mesh contains non-triangular face");
}
return result;
}
/**
* Helper class for finding opposite corners
* @author Marek Bařinka
*/
private static class Edge {
private final Vector3d v1;
private final Vector3d v2;
private final int cornerIndex;
public Edge(Vector3d v1, Vector3d v2, int cornerIndex) {
this.v1 = v1;
this.v2 = v2;
this.cornerIndex = cornerIndex;
}
/**
* Returns new edge containing same vertices with opposite order
* and invalid cornerIndex value.
* @return Inverted edge in @method(equals) meaning
*/
public Edge getInvertedEdge() {
return new Edge(this.v2, this.v1, -1);
}
public int getCornerIndex() {
return cornerIndex;
}
/**
* Hash code must be generated this way because of @method(equals)
* @return hash code of edge
*/
@Override
public int hashCode() {
int hash = 3;
hash += Objects.hashCode(this.v1);
hash += Objects.hashCode(this.v2);
return hash;
}
/**
* Two edges are considered same if they have same vertices.
* @param obj Other edge to test
* @return true if edges are same with opposite direction
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Edge)) {
return false;
}
final Edge other = (Edge) obj;
return (other.v1.equals(this.v1) && other.v2.equals(this.v2)) ||
(other.v1.equals(this.v2) && other.v2.equals(this.v1));
} }
return points;
} }
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment