/*
This file is part of Mitsuba, a physically based rendering system.
Copyright (c) 2007-2010 by Wenzel Jakob and others.
Mitsuba is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License Version 3
as published by the Free Software Foundation.
Mitsuba is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#define MTS_FILEFORMAT_HEADER 0x041C
#define MTS_FILEFORMAT_VERSION_V1 0x01
#define MTS_FILEFORMAT_VERSION_V2 0x02
MTS_NAMESPACE_BEGIN
TriMesh::TriMesh(size_t triangleCount, size_t vertexCount)
: Shape(Properties()), m_triangleCount(triangleCount),
m_vertexCount(vertexCount), m_flipNormals(false) {
m_triangles = new Triangle[m_triangleCount];
m_vertexBuffer = new Vertex[m_vertexCount];
}
TriMesh::TriMesh(const std::string &name, Transform worldToObject, Triangle *triangles,
size_t triangleCount, Vertex *vertexBuffer, size_t vertexCount)
: Shape(Properties()), m_triangles(triangles), m_triangleCount(triangleCount),
m_vertexBuffer(vertexBuffer), m_vertexCount(vertexCount), m_flipNormals(false) {
m_name = name;
m_worldToObject = worldToObject;
m_objectToWorld.inverse();
}
TriMesh::TriMesh(const Properties &props)
: Shape(props) {
m_flipNormals = props.getBoolean("flipNormals", false);
m_triangles = NULL;
m_vertexBuffer = NULL;
}
TriMesh::TriMesh(Stream *stream, InstanceManager *manager)
: Shape(stream, manager) {
Assert(sizeof(Vertex) == 14*sizeof(Float));
Assert(sizeof(Triangle) == 3*sizeof(int));
m_vertexCount = (size_t) stream->readULong();
m_vertexBuffer = new Vertex[m_vertexCount];
stream->readFloatArray(reinterpret_cast(m_vertexBuffer),
m_vertexCount * sizeof(Vertex)/sizeof(Float));
m_triangleCount = (size_t) stream->readULong();
m_triangles = new Triangle[m_triangleCount];
stream->readIntArray(reinterpret_cast(m_triangles),
m_triangleCount * sizeof(Triangle)/sizeof(int));
m_flipNormals = false;
configure();
}
TriMesh::TriMesh(Stream *_stream) : Shape(Properties()) {
ref stream = _stream;
Assert(sizeof(Vertex) == 14*sizeof(Float));
Assert(sizeof(Triangle) == 3*sizeof(int));
if (stream->getByteOrder() != Stream::ENetworkByteOrder)
Log(EError, "Tried to unserialize a shape from a stream, "
"which was not previously set to network byte order!");
#if defined(SINGLE_PRECISION)
bool doublePrecision = false;
#else
bool doublePrecision = true;
#endif
if (stream->readShort() != MTS_FILEFORMAT_HEADER)
Log(EError, "Encountered an invalid file format!");
short version = stream->readShort();
if (version != MTS_FILEFORMAT_VERSION_V1 &&
version != MTS_FILEFORMAT_VERSION_V2)
Log(EError, "Encountered an incompatible file version!");
if (version == MTS_FILEFORMAT_VERSION_V2)
stream = new ZStream(stream);
bool fileDoublePrecision = stream->readBool();
m_vertexCount = (size_t) stream->readULong();
m_vertexBuffer = new Vertex[m_vertexCount];
size_t numEntries = m_vertexCount * sizeof(Vertex)/sizeof(Float);
Float *target = reinterpret_cast(m_vertexBuffer);
if ((doublePrecision && fileDoublePrecision) ||
(!doublePrecision && !fileDoublePrecision)) {
/* Precision matches - load directly into memory */
stream->readFloatArray(target, numEntries);
} else if (fileDoublePrecision) {
/* Double -> Single conversion */
double *temp = new double[numEntries];
stream->readDoubleArray(temp, numEntries);
for (size_t i=0; i Double conversion */
float *temp = new float[numEntries];
stream->readSingleArray(temp, numEntries);
for (size_t i=0; ireadULong();
m_triangles = new Triangle[m_triangleCount];
stream->readIntArray(reinterpret_cast(m_triangles),
m_triangleCount * sizeof(Triangle)/sizeof(int));
m_flipNormals = false;
configure();
}
TriMesh::~TriMesh() {
if (m_triangles)
delete[] m_triangles;
if (m_vertexBuffer)
delete[] m_vertexBuffer;
}
void TriMesh::configure() {
Shape::configure();
if (m_areaPDF.isReady())
return;
AssertEx(m_triangleCount > 0, "Encountered an empty triangle mesh!");
for (size_t i=0; i 0) {
dpdu /= (Float) sharers[i];
dpdv /= (Float) sharers[i];
}
}
m_vertexBuffer[i].dpdu = dpdu;
m_vertexBuffer[i].dpdv = dpdv;
}
delete[] sharers;
}
if (complain && (zeroArea > 0 || zeroNormals > 0))
Log(EWarn, "Mesh contains invalid geometry: %i zero area triangles "
"and %i zero normals found!", zeroArea, zeroNormals);
}
void TriMesh::serialize(Stream *stream, InstanceManager *manager) const {
Shape::serialize(stream, manager);
Assert(sizeof(Vertex) == 14*sizeof(Float));
Assert(sizeof(Triangle) == 3*sizeof(int));
stream->writeULong(m_vertexCount);
stream->writeFloatArray(reinterpret_cast(m_vertexBuffer),
m_vertexCount * sizeof(Vertex)/sizeof(Float));
stream->writeULong(m_triangleCount);
stream->writeIntArray(reinterpret_cast(m_triangles),
m_triangleCount * sizeof(Triangle)/sizeof(int));
}
void TriMesh::serialize(Stream *_stream) const {
ref stream = _stream;
Assert(sizeof(Vertex) == 14*sizeof(Float));
Assert(sizeof(Triangle) == 3*sizeof(int));
if (stream->getByteOrder() != Stream::ENetworkByteOrder)
Log(EError, "Tried to unserialize a shape from a stream, "
"which was not previously set to network byte order!");
#if defined(SINGLE_PRECISION)
bool doublePrecision = false;
#else
bool doublePrecision = true;
#endif
stream->writeShort(MTS_FILEFORMAT_HEADER);
stream->writeShort(MTS_FILEFORMAT_VERSION_V2);
stream = new ZStream(stream);
stream->writeBool(doublePrecision);
stream->writeULong(m_vertexCount);
stream->writeFloatArray(reinterpret_cast(m_vertexBuffer),
m_vertexCount * sizeof(Vertex)/sizeof(Float));
stream->writeULong(m_triangleCount);
stream->writeIntArray(reinterpret_cast(m_triangles),
m_triangleCount * sizeof(Triangle)/sizeof(int));
}
std::string TriMesh::toString() const {
std::ostringstream oss;
oss << getClass()->getName() << "[" << endl
<< " name = \"" << m_name<< "\"," << endl
<< " triangleCount = " << m_triangleCount << "," << endl
<< " vertexCount = " << m_vertexCount << "," << endl
<< " flipNormals = " << m_flipNormals << "," << endl
<< " surfaceArea = " << m_surfaceArea << "," << endl
<< " aabb = " << m_aabb.toString() << "," << endl
<< " bsphere = " << m_bsphere.toString() << "," << endl
<< " bsdf = " << indent(m_bsdf.toString()) << "," << endl
<< " subsurface = " << indent(m_subsurface.toString()) << "," << endl
<< " luminaire = " << indent(m_luminaire.toString()) << endl
<< "]";
return oss.str();
}
MTS_IMPLEMENT_CLASS_S(TriMesh, false, Shape)
MTS_NAMESPACE_END