use of org.vitrivr.cineast.core.data.m3d.Mesh in project cineast by vitrivr.
the class ModularMeshDecoder method getNext.
/**
* Fetches the next piece of content of type T and returns it. This method can be safely invoked until complete() returns false. From which on this method will return null.
*
* @return Content of type T.
*/
@Override
public Mesh getNext() {
final String contenttype = MimeTypeHelper.getContentType(this.inputFile.toFile());
/* Try to detach decoder from the list of cached decoders. */
Decoder<Mesh> decoder = this.cachedDecoders.get(contenttype);
/* If decoder is null, create a new one. */
if (decoder == null) {
decoder = decoderForContenttype(contenttype);
}
/* If decoder is still null, return an emtpy Mesh. */
if (decoder == null) {
LOGGER.warn("Could not find mesh decoder for provided contenttype {}.", contenttype);
return Mesh.EMPTY;
} else {
this.cachedDecoders.put(contenttype, decoder);
}
/* Initialize the decoder and return the decoded mesh. */
decoder.init(this.inputFile, null, null);
Mesh mesh = decoder.getNext();
this.complete.set(true);
return mesh;
}
use of org.vitrivr.cineast.core.data.m3d.Mesh in project cineast by vitrivr.
the class ModularMeshDecoder method convert.
/**
* Converts a single file to a QueryContainer.
*
* @param path Path the file that should be converted.
* @return QueryContainer for the specified file.
*/
@Override
public AbstractQueryTermContainer convert(Path path) {
final String contenttype = MimeTypeHelper.getContentType(path.toFile());
/* Try to detach decoder from the list of cached decoders. */
Decoder<Mesh> decoder = this.cachedDecoders.get(contenttype);
/* If decoder is null, create a new one. */
if (decoder == null) {
decoder = decoderForContenttype(contenttype);
}
/* If decoder is still null, return an emtpy Mesh. */
if (decoder == null) {
LOGGER.warn("Could not find mesh decoder for provided contenttype {}.", contenttype);
return null;
} else {
this.cachedDecoders.put(contenttype, decoder);
}
/* Initialize the decoder and return the decoded mesh. */
decoder.init(path, null, null);
Mesh mesh = decoder.getNext();
return new ModelQueryTermContainer(mesh);
}
use of org.vitrivr.cineast.core.data.m3d.Mesh in project cineast by vitrivr.
the class STLMeshDecoder method readBinary.
/**
* Reads a binary STL file.
*
* @param is InputStream to read from.
* @param skip Number of bytes to skip before reading the STL file.
* @return Mesh
* @throws IOException If an error occurs during reading.
*/
private Mesh readBinary(InputStream is, int skip) throws IOException {
/* Prepare a ByteBuffer to read the rest of the STL file. */
byte[] bytes = new byte[50];
ByteBuffer buffer = ByteBuffer.wrap(bytes);
buffer.order(ByteOrder.LITTLE_ENDIAN);
/* Skip the STL header! */
is.skip(skip);
/* Read the bytes for the size (unsigned 32 bit int, little-endian). */
byte[] sizeBytes = new byte[4];
is.read(sizeBytes, 0, 4);
long triangles = ((sizeBytes[0] & 0xFF)) | ((sizeBytes[1] & 0xFF) << 8) | ((sizeBytes[2] & 0xFF) << 16) | ((sizeBytes[3] & 0xFF) << 24);
/* TODO: Properly handle models whose triangles > MAX_TRIANGLES. */
if (triangles <= 0) {
LOGGER.error("The number of triangles in the Mesh seems to be smaller than zero. This STL file is probably corrupt!");
return null;
} else if (triangles > MAX_TRIANGLES) {
LOGGER.error("The number of triangles in the Mesh exceeds the limit that can currently be processed by STLMeshDecoder. The Mesh will be downsampled!");
return null;
}
/* Prepare Mesh. */
Mesh mesh = new Mesh((int) triangles, (int) triangles);
/* Prepare helper structures. */
TObjectIntHashMap<Vector3f> vertexBuffer = new TObjectIntHashMap<>();
int index = 0;
int[] vertexindices = new int[3];
/* Now add all triangles. */
for (int i = 0; i < triangles; i++) {
/* Ready 48 bytes from the stream. */
buffer.rewind();
is.read(bytes);
/* Read and ignore three floats. */
buffer.getFloat();
buffer.getFloat();
buffer.getFloat();
/* Add the vertices and the vertex-normal to the mesh. */
for (int vidx = 0; vidx < 3; vidx++) {
Vector3f vertex = new Vector3f(buffer.getFloat(), buffer.getFloat(), buffer.getFloat());
if (!vertexBuffer.containsKey(vertex)) {
mesh.addVertex(vertex);
vertexBuffer.put(vertex, index);
index++;
}
vertexindices[vidx] = vertexBuffer.get(vertex);
}
/* Add a new face to the Mesh. */
if (!mesh.addFace(new Vector3i(vertexindices[0], vertexindices[1], vertexindices[2]))) {
LOGGER.warn("Could not add face {}/{}/{} because index points to non-existing vertex.", vertexindices[0], vertexindices[1], vertexindices[2]);
}
}
/* Closes the InputStream. */
is.close();
return mesh;
}
use of org.vitrivr.cineast.core.data.m3d.Mesh in project cineast by vitrivr.
the class STLMeshDecoder method readAscii.
/**
* Reads an ASCII STL file.
*
* @param is InputStream to read from.
* @return Mesh
* @throws IOException If an error occurs during reading.
*/
private Mesh readAscii(InputStream is) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
/* Prepare empty mesh. */
Mesh mesh = new Mesh(100, 100);
/* Prepare helper structures. */
TObjectIntHashMap<Vector3f> vertexBuffer = new TObjectIntHashMap<>();
int index = 0;
int[] vertexindices = new int[3];
while ((line = br.readLine()) != null && !line.startsWith("endsolid")) {
line = line.trim();
/* Detect end of STL file. */
if (line.startsWith("endsolid")) {
break;
}
/* Detect begin of facet. */
if (line.startsWith("facet normal ")) {
int vidx = 0;
while ((line = br.readLine()) != null) {
line = line.trim();
/* Detect end of facet. */
if (line.equals("endfacet")) {
break;
}
/* Detect vertex. */
if (line.startsWith("vertex")) {
String[] splitVertex = line.split("\\s+");
Vector3f vertex = new Vector3f(Float.parseFloat(splitVertex[1]), Float.parseFloat(splitVertex[2]), Float.parseFloat(splitVertex[3]));
if (!vertexBuffer.containsKey(vertex)) {
mesh.addVertex(vertex);
vertexBuffer.put(vertex, index);
index++;
}
vertexindices[vidx] = vertexBuffer.get(vertex);
vidx++;
}
}
/* Add a new face to the Mesh. */
mesh.addFace(new Vector3i(vertexindices[0], vertexindices[1], vertexindices[2]));
}
}
/* Close the buffered reader. */
br.close();
/* This covers the case, where the file starts with 'solid ' but is not an ASCII file. Unfortunately, such files do exist. */
if (mesh.numberOfVertices() == 0) {
LOGGER.warn("The provided ASCII STL file does not seem to contain any normals or vertices. Trying to decode it as binary STL even though it was marked as being ASCII.");
InputStream newIs = Files.newInputStream(this.inputFile);
return this.readBinary(newIs, 80);
} else {
return mesh;
}
}
use of org.vitrivr.cineast.core.data.m3d.Mesh in project cineast by vitrivr.
the class MeshColoringUtil method normalColoring.
public static void normalColoring(WritableMesh mesh) {
Vector3f axis = new Vector3f(1.0f, 0.0f, 0.0f);
Vector3fc center = mesh.barycenter();
Mesh.Vertex farthestVertex = MeshMathUtil.farthestVertex(mesh, center);
float ds_max = center.distance(farthestVertex.getPosition());
for (int i = 0; i < mesh.numberOfVertices(); i++) {
float hue = (float) (axis.angle(mesh.getVertex(i).getNormal()) / Math.PI);
float saturation = center.distance(mesh.getVertex(i).getPosition()) / ds_max;
Color color = Color.getHSBColor(hue, saturation, 1.0f);
mesh.updateColor(i, color);
}
}
Aggregations