TriMesh: binary PLY export feature

metadata
Wenzel Jakob 2014-09-29 18:08:42 +02:00
parent beb85f9702
commit 70f08931b9
4 changed files with 83 additions and 3 deletions

View File

@ -304,9 +304,12 @@ public:
static ref<TriMesh> fromBlender(const std::string &name, size_t faceCount, void *facePtr, static ref<TriMesh> fromBlender(const std::string &name, size_t faceCount, void *facePtr,
size_t vertexCount, void *vertexPtr, void *uvPtr, void *colPtr, short matNr); size_t vertexCount, void *vertexPtr, void *uvPtr, void *colPtr, short matNr);
/// Export an Wavefront OBJ version of this file /// Export a Wavefront OBJ version of this file
void writeOBJ(const fs::path &path) const; void writeOBJ(const fs::path &path) const;
/// Export a Stanford PLY version of this file
void writePLY(const fs::path &path) const;
/// Return a string representation /// Return a string representation
std::string toString() const; std::string toString() const;

View File

@ -565,6 +565,7 @@ void export_render() {
.def("serialize", triMesh_serialize1) .def("serialize", triMesh_serialize1)
.def("serialize", triMesh_serialize2) .def("serialize", triMesh_serialize2)
.def("writeOBJ", &TriMesh::writeOBJ) .def("writeOBJ", &TriMesh::writeOBJ)
.def("writePLY", &TriMesh::writePLY)
.def("fromBlender", trimesh_fromBlender) .def("fromBlender", trimesh_fromBlender)
.staticmethod("fromBlender"); .staticmethod("fromBlender");

View File

@ -17,6 +17,7 @@
*/ */
#include <mitsuba/render/trimesh.h> #include <mitsuba/render/trimesh.h>
#include <mitsuba/core/version.h>
#include <mitsuba/core/random.h> #include <mitsuba/core/random.h>
#include <mitsuba/core/plugin.h> #include <mitsuba/core/plugin.h>
#include <mitsuba/core/zstream.h> #include <mitsuba/core/zstream.h>
@ -84,7 +85,6 @@ TriMesh::TriMesh(Stream *stream, int index)
loadCompressed(stream, index); loadCompressed(stream, index);
} }
/* Flags used to identify available data during serialization */ /* Flags used to identify available data during serialization */
enum ETriMeshFlags { enum ETriMeshFlags {
EHasNormals = 0x0001, EHasNormals = 0x0001,
@ -1057,6 +1057,81 @@ void TriMesh::writeOBJ(const fs::path &path) const {
os.close(); os.close();
} }
void TriMesh::writePLY(const fs::path &path) const {
fs::ofstream os(path, std::ios::out | std::ios::binary);
os << "ply\n";
if (Stream::getHostByteOrder() == Stream::ELittleEndian)
os << "format binary_little_endian 1.0\n";
else
os << "format binary_big_endian 1.0\n";
os << "comment generated by Mitsuba " << MTS_VERSION << "\n";
os << "element vertex " << getVertexCount() << "\n";
size_t storagePerVertex = 3 * sizeof(float);
os << "property float x\n";
os << "property float y\n";
os << "property float z\n";
if (m_normals) {
os << "property float nx\n";
os << "property float ny\n";
os << "property float nz\n";
storagePerVertex += 3 * sizeof(float);
}
if (m_texcoords) {
os << "property float u\n";
os << "property float v\n";
storagePerVertex += 2 * sizeof(float);
}
if (m_colors) {
os << "property uchar red\n";
os << "property uchar green\n";
os << "property uchar blue\n";
storagePerVertex += 3 * sizeof(uint8_t);
}
os << "element face " << m_triangleCount << "\n";
os << "property list uchar int vertex_indices\n";
os << "end_header\n";
size_t vertexStorageSize = storagePerVertex * (size_t) m_vertexCount;
uint8_t *vertexStorage = new uint8_t[vertexStorageSize], *ptr = vertexStorage;
for (size_t i=0; i< getVertexCount(); ++i) {
Vector3f p(m_positions[i]); memcpy(ptr, &p, sizeof(Vector3f)); ptr += sizeof(Vector3f);
if (m_normals) {
Vector3f n(m_normals[i]); memcpy(ptr, &n, sizeof(Vector3f)); ptr += sizeof(Vector3f);
}
if (m_texcoords) {
Vector2f uv(m_texcoords[i]); memcpy(ptr, &uv, sizeof(Vector2f)); ptr += sizeof(Vector2f);
}
if (m_colors) {
*ptr += (uint8_t) std::max(0.0f, std::min(255.0f, m_colors[i][0] * 255.0f + 0.5f));
*ptr += (uint8_t) std::max(0.0f, std::min(255.0f, m_colors[i][1] * 255.0f + 0.5f));
*ptr += (uint8_t) std::max(0.0f, std::min(255.0f, m_colors[i][2] * 255.0f + 0.5f));
}
}
Assert(ptr-vertexStorage == vertexStorageSize);
os.write((const char *) vertexStorage, vertexStorageSize);
delete[] vertexStorage;
size_t faceStorageSize = (sizeof(Triangle) + 1) * (size_t) getTriangleCount();
uint8_t *faceStorage = new uint8_t[faceStorageSize];
ptr = faceStorage;
for (size_t i=0; i<getTriangleCount(); ++i) {
*ptr++ = (uint8_t) 0x03;
memcpy(ptr, &m_triangles[i], sizeof(Triangle));
ptr += sizeof(Triangle);
}
Assert(ptr-faceStorage == faceStorageSize);
os.write((const char *) faceStorage, faceStorageSize);
delete[] faceStorage;
os.close();
}
void TriMesh::serialize(Stream *_stream) const { void TriMesh::serialize(Stream *_stream) const {
ref<Stream> stream = _stream; ref<Stream> stream = _stream;

View File

@ -273,7 +273,8 @@ public:
void face_vertex_indices_begin_uint8(ply::uint8 size) { void face_vertex_indices_begin_uint8(ply::uint8 size) {
if (size != 3 && size != 4) if (size != 3 && size != 4)
Log(EError, "Only triangle and quad-based PLY meshes are supported for now."); Log(EError, "Encountered a face with %i vertices! "
"Only triangle and quad-based PLY meshes are supported for now.", size);
m_indexCtr = 0; m_indexCtr = 0;
} }