vertex color and PLY loading support

metadata
Wenzel Jakob 2010-09-28 19:47:16 +02:00
parent 7539f12bee
commit 4bb5e8c3d6
23 changed files with 1789 additions and 23 deletions

View File

@ -511,6 +511,8 @@ plugins += env.SharedLibrary('plugins/kkay', ['src/phase/kkay.cpp'])
# Shapes and triangle mesh loaders # Shapes and triangle mesh loaders
plugins += env.SharedLibrary('plugins/obj', ['src/shapes/obj.cpp']) plugins += env.SharedLibrary('plugins/obj', ['src/shapes/obj.cpp'])
plugins += env.SharedLibrary('plugins/ply', ['src/shapes/ply/ply.cpp', 'src/shapes/ply/ply_parser.cpp'],
CPPPATH = env['CPPPATH'] + ['src/shapes/ply'])
plugins += env.SharedLibrary('plugins/serialized', ['src/shapes/serialized.cpp']) plugins += env.SharedLibrary('plugins/serialized', ['src/shapes/serialized.cpp'])
plugins += env.SharedLibrary('plugins/sphere', ['src/shapes/sphere.cpp']) plugins += env.SharedLibrary('plugins/sphere', ['src/shapes/sphere.cpp'])
plugins += env.SharedLibrary('plugins/cylinder', ['src/shapes/cylinder.cpp']) plugins += env.SharedLibrary('plugins/cylinder', ['src/shapes/cylinder.cpp'])
@ -564,6 +566,7 @@ plugins += env.SharedLibrary('plugins/exrtexture', ['src/textures/exrtexture.cpp
plugins += env.SharedLibrary('plugins/ldrtexture', ['src/textures/ldrtexture.cpp']) plugins += env.SharedLibrary('plugins/ldrtexture', ['src/textures/ldrtexture.cpp'])
plugins += env.SharedLibrary('plugins/gridtexture', ['src/textures/gridtexture.cpp']) plugins += env.SharedLibrary('plugins/gridtexture', ['src/textures/gridtexture.cpp'])
plugins += env.SharedLibrary('plugins/checkerboard', ['src/textures/checkerboard.cpp']) plugins += env.SharedLibrary('plugins/checkerboard', ['src/textures/checkerboard.cpp'])
plugins += env.SharedLibrary('plugins/vertexcolors', ['src/textures/vertexcolors.cpp'])
# Light sources # Light sources
plugins += env.SharedLibrary('plugins/area', ['src/luminaires/area.cpp']) plugins += env.SharedLibrary('plugins/area', ['src/luminaires/area.cpp'])

View File

@ -15,6 +15,7 @@ Mitsuba makes heavy use of the following amazing libraries and tools:
\item COLLADA DOM by Sony Computer Entertainment \item COLLADA DOM by Sony Computer Entertainment
\item libjpeg by the Independent JPEG Group \item libjpeg by the Independent JPEG Group
\item libpng by Guy Eric Schalnat, Andreas Dilger, Glenn Randers-Pehrson and \mbox{others} \item libpng by Guy Eric Schalnat, Andreas Dilger, Glenn Randers-Pehrson and \mbox{others}
\item libply by Ares Lagae
\item BWToolkit by Brandon Walkin \item BWToolkit by Brandon Walkin
\item POSIX Threads for Win32 by Ross Johnson \item POSIX Threads for Win32 by Ross Johnson
\item The SCons build system by the SCons Foundation \item The SCons build system by the SCons Foundation

View File

@ -35,6 +35,8 @@ You may also set adjust certain compilation flags here:
\item[\texttt{DOUBLE\_PRECISION}] Do all computation in double precision. Incompatible with \item[\texttt{DOUBLE\_PRECISION}] Do all computation in double precision. Incompatible with
\texttt{MTS\_SSE}, \texttt{MTS\_HAS\_COHERENT\_RT}, and \texttt{MTS\_DEBUG\_FP}. \texttt{MTS\_SSE}, \texttt{MTS\_HAS\_COHERENT\_RT}, and \texttt{MTS\_DEBUG\_FP}.
\item[\texttt{MTS\_SSE}]Activate optimized SSE routines. \item[\texttt{MTS\_SSE}]Activate optimized SSE routines.
\item[\texttt{MTS\_HAS\_VERTEX\_COLORS}]Compile support for vertex colors. Turned off by
default.
\item[\texttt{MTS\_HAS\_COHERENT\_RT}]Include coherent ray tracing support (depends on \texttt{MTS\_SSE}). \item[\texttt{MTS\_HAS\_COHERENT\_RT}]Include coherent ray tracing support (depends on \texttt{MTS\_SSE}).
\item[\texttt{MTS\_DEBUG\_FP}]Generated NaNs will cause floating point exceptions, which can be caught in a debugger. Warning: This is slow! \item[\texttt{MTS\_DEBUG\_FP}]Generated NaNs will cause floating point exceptions, which can be caught in a debugger. Warning: This is slow!
\end{description} \end{description}

View File

@ -34,10 +34,21 @@ struct Vertex {
Point2 uv; ///< %Texture coordinates Point2 uv; ///< %Texture coordinates
Vector dpdu; ///< Partial derivative of the position with respect to \a u. Vector dpdu; ///< Partial derivative of the position with respect to \a u.
Vector dpdv; ///< Partial derivative of the position with respect to \a v. Vector dpdv; ///< Partial derivative of the position with respect to \a v.
#if defined(MTS_HAS_VERTEX_COLORS)
Float color[3];
#endif
inline bool operator==(const Vertex &vert) const { inline bool operator==(const Vertex &vert) const {
#if defined(MTS_HAS_VERTEX_COLORS)
return (p == vert.p && n == vert.n && uv == vert.uv
&& dpdu == vert.dpdu && dpdv == vert.dpdv
&& color[0] == vert.color[0]
&& color[1] == vert.color[1]
&& color[2] == vert.color[2]);
#else
return (p == vert.p && n == vert.n && uv == vert.uv return (p == vert.p && n == vert.n && uv == vert.uv
&& dpdu == vert.dpdu && dpdv == vert.dpdv); && dpdu == vert.dpdu && dpdv == vert.dpdv);
#endif
} }
inline bool operator!=(const Vertex &vert) const { inline bool operator!=(const Vertex &vert) const {

View File

@ -107,37 +107,42 @@ public:
/// Computes texture coordinate partials /// Computes texture coordinate partials
void computePartials(const RayDifferential &ray); void computePartials(const RayDifferential &ray);
/* Return a string representation */ /// Return a string representation
std::string toString() const; std::string toString() const;
public: public:
/* Incident direction in the local frame */ /// Incident direction in the local frame
Vector wi; Vector wi;
/* Distance traveled along the ray */ /// Distance traveled along the ray
Float t; Float t;
/* Intersection point in 3D coordinates */ /* Intersection point in 3D coordinates */
Point p; Point p;
/* Geometry frame */ /// Geometry frame
Frame geoFrame; Frame geoFrame;
/* Shading frame */ /// Shading frame
Frame shFrame; Frame shFrame;
/* UV surface coordinates */ /// UV surface coordinates
Point2 uv; Point2 uv;
/* Position partials wrt. to changes in texture-space */ /// Position partials wrt. to changes in texture-space
Vector dpdu, dpdv; Vector dpdu, dpdv;
/* Texture coordinate mapping partials wrt. changes in screen-space */ /// Texture coordinate mapping partials wrt. changes in screen-space
Float dudx, dudy, dvdx, dvdy; Float dudx, dudy, dvdx, dvdy;
/* Affected shape */ #if defined(MTS_HAS_VERTEX_COLORS)
/// Interpolated vertex color (if enabled)
Spectrum color;
#endif
/// Affected shape
const Shape *shape; const Shape *shape;
/* Have texture coordinate partials been computed */ /// Have texture coordinate partials been computed
bool hasUVPartials; bool hasUVPartials;
}; };

View File

@ -41,7 +41,14 @@ void GLGeometry::init() {
} }
void GLGeometry::refresh() { void GLGeometry::refresh() {
Assert(m_vertexID != 0 && m_indexID != 0); Assert(m_vertexID != 0 && m_indexID != 0);
m_vertexSize = m_mesh->getVertexCount() * sizeof(GLfloat) * 11; #if defined(MTS_HAS_VERTEX_COLORS)
const int floatsPerVertex = 14;
#else
const int floatsPerVertex = 11;
#endif
m_vertexSize = m_mesh->getVertexCount() * sizeof(GLfloat) *
floatsPerVertex;
m_indexSize = m_mesh->getTriangleCount() * sizeof(GLuint) * 3; m_indexSize = m_mesh->getTriangleCount() * sizeof(GLuint) * 3;
Log(EDebug, "Uploading a GPU geometry object (\"%s\", " SIZE_T_FMT Log(EDebug, "Uploading a GPU geometry object (\"%s\", " SIZE_T_FMT
@ -51,7 +58,7 @@ void GLGeometry::refresh() {
m_mesh->getTriangleCount(), m_mesh->getTriangleCount(),
(m_vertexSize + m_indexSize) / 1024.0f); (m_vertexSize + m_indexSize) / 1024.0f);
GLfloat *vertices = new GLfloat[m_mesh->getVertexCount() * 11]; GLfloat *vertices = new GLfloat[m_mesh->getVertexCount() * floatsPerVertex];
GLuint *indices = (GLuint *) m_mesh->getTriangles(); GLuint *indices = (GLuint *) m_mesh->getTriangles();
const Vertex *source = m_mesh->getVertexBuffer(); const Vertex *source = m_mesh->getVertexBuffer();
int pos = 0; int pos = 0;
@ -68,6 +75,11 @@ void GLGeometry::refresh() {
vertices[pos++] = (float) vtx.dpdu.x; vertices[pos++] = (float) vtx.dpdu.x;
vertices[pos++] = (float) vtx.dpdu.y; vertices[pos++] = (float) vtx.dpdu.y;
vertices[pos++] = (float) vtx.dpdu.z; vertices[pos++] = (float) vtx.dpdu.z;
#if defined(MTS_HAS_VERTEX_COLORS)
vertices[pos++] = (float) vtx.color[0];
vertices[pos++] = (float) vtx.color[1];
vertices[pos++] = (float) vtx.color[2];
#endif
} }
bind(); bind();

View File

@ -220,10 +220,17 @@ void GLRenderer::beginDrawingMeshes(bool transmitOnlyPositions) {
glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE1); glClientActiveTexture(GL_TEXTURE1);
glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
#if defined(MTS_HAS_VERTEX_COLORS)
glEnableClientState(GL_COLOR_ARRAY);
#endif
} }
if (m_capabilities->isSupported(RendererCapabilities::EBindless)) { if (m_capabilities->isSupported(RendererCapabilities::EBindless)) {
#if defined(MTS_HAS_VERTEX_COLORS)
const int stride = sizeof(GLfloat) * 14;
#else
const int stride = sizeof(GLfloat) * 11; const int stride = sizeof(GLfloat) * 11;
#endif
glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV); glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV);
glEnableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV); glEnableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV);
glVertexFormatNV(3, GL_FLOAT, stride); glVertexFormatNV(3, GL_FLOAT, stride);
@ -233,6 +240,7 @@ void GLRenderer::beginDrawingMeshes(bool transmitOnlyPositions) {
glTexCoordFormatNV(2, GL_FLOAT, stride); glTexCoordFormatNV(2, GL_FLOAT, stride);
glClientActiveTexture(GL_TEXTURE1); glClientActiveTexture(GL_TEXTURE1);
glTexCoordFormatNV(3, GL_FLOAT, stride); glTexCoordFormatNV(3, GL_FLOAT, stride);
glColorFormatNV(3, GL_FLOAT, stride);
} }
} }
} }
@ -252,11 +260,19 @@ void GLRenderer::drawTriMesh(const TriMesh *mesh) {
geometry->m_vertexSize - 6*sizeof(GLfloat)); geometry->m_vertexSize - 6*sizeof(GLfloat));
glBufferAddressRangeNV(GL_TEXTURE_COORD_ARRAY_ADDRESS_NV, 1, geometry->m_vertexAddr+8*sizeof(GLfloat), glBufferAddressRangeNV(GL_TEXTURE_COORD_ARRAY_ADDRESS_NV, 1, geometry->m_vertexAddr+8*sizeof(GLfloat),
geometry->m_vertexSize - 8*sizeof(GLfloat)); geometry->m_vertexSize - 8*sizeof(GLfloat));
#if defined(MTS_HAS_VERTEX_COLORS)
glBufferAddressRangeNV(GL_COLOR_ARRAY_ADDRESS_NV, 0, geometry->m_vertexAddr+11*sizeof(GLfloat),
geometry->m_vertexSize - 11*sizeof(GLfloat));
#endif
} }
glBufferAddressRangeNV(GL_ELEMENT_ARRAY_ADDRESS_NV, 0, glBufferAddressRangeNV(GL_ELEMENT_ARRAY_ADDRESS_NV, 0,
geometry->m_indexAddr, geometry->m_indexSize); geometry->m_indexAddr, geometry->m_indexSize);
} else { } else {
#if defined(MTS_HAS_VERTEX_COLORS)
const int stride = sizeof(GLfloat) * 14;
#else
const int stride = sizeof(GLfloat) * 11; const int stride = sizeof(GLfloat) * 11;
#endif
glBindBuffer(GL_ARRAY_BUFFER, geometry->m_vertexID); glBindBuffer(GL_ARRAY_BUFFER, geometry->m_vertexID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry->m_indexID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry->m_indexID);
@ -273,12 +289,21 @@ void GLRenderer::drawTriMesh(const TriMesh *mesh) {
/* Pass 'dpdu' as second set of texture coordinates */ /* Pass 'dpdu' as second set of texture coordinates */
glClientActiveTexture(GL_TEXTURE1); glClientActiveTexture(GL_TEXTURE1);
glTexCoordPointer(3, GL_FLOAT, stride, (GLfloat *) 0 + 8); glTexCoordPointer(3, GL_FLOAT, stride, (GLfloat *) 0 + 8);
#if defined(MTS_HAS_VERTEX_COLORS)
glColorPointer(3, GL_FLOAT, stride, (GLfloat *) 0 + 11);
#endif
} }
} }
/* Draw all triangles */ /* Draw all triangles */
glDrawElements(GL_TRIANGLES, (GLsizei) (mesh->getTriangleCount() * 3), glDrawElements(GL_TRIANGLES, (GLsizei) (mesh->getTriangleCount() * 3),
GL_UNSIGNED_INT, (GLvoid *) 0); GL_UNSIGNED_INT, (GLvoid *) 0);
if (!m_capabilities->isSupported(RendererCapabilities::EBindless)) {
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
} else { } else {
/* Draw the old-fashioned way without VBOs */ /* Draw the old-fashioned way without VBOs */
const GLchar *vertices = (const GLchar *) mesh->getVertexBuffer(); const GLchar *vertices = (const GLchar *) mesh->getVertexBuffer();
@ -290,7 +315,12 @@ void GLRenderer::drawTriMesh(const TriMesh *mesh) {
if (!m_transmitOnlyPositions) { if (!m_transmitOnlyPositions) {
glNormalPointer(dataType, sizeof(Vertex), glNormalPointer(dataType, sizeof(Vertex),
vertices + sizeof(Float) * 3); vertices + sizeof(Float) * 3);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
#if defined(MTS_HAS_VERTEX_COLORS)
glColorPointer(3, GL_FLOAT, sizeof(Vertex),
vertices + sizeof(Float) * 14);
#endif
glClientActiveTexture(GL_TEXTURE0);
glTexCoordPointer(2, dataType, sizeof(Vertex), glTexCoordPointer(2, dataType, sizeof(Vertex),
vertices + sizeof(Float) * 6); vertices + sizeof(Float) * 6);
@ -309,6 +339,9 @@ void GLRenderer::drawTriMesh(const TriMesh *mesh) {
void GLRenderer::endDrawingMeshes() { void GLRenderer::endDrawingMeshes() {
glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_VERTEX_ARRAY);
if (!m_transmitOnlyPositions) { if (!m_transmitOnlyPositions) {
#if defined(MTS_HAS_VERTEX_COLORS)
glDisableClientState(GL_COLOR_ARRAY);
#endif
glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_NORMAL_ARRAY);
glClientActiveTexture(GL_TEXTURE1); glClientActiveTexture(GL_TEXTURE1);
glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY);
@ -326,6 +359,8 @@ void GLRenderer::endDrawingMeshes() {
} }
void GLRenderer::drawAll() { void GLRenderer::drawAll() {
if (true)
return;
GLRenderer::beginDrawingMeshes(true); GLRenderer::beginDrawingMeshes(true);
std::map<const TriMesh *, GPUGeometry *>::iterator it; std::map<const TriMesh *, GPUGeometry *>::iterator it;
if (m_capabilities->isSupported(RendererCapabilities::EBindless)) { if (m_capabilities->isSupported(RendererCapabilities::EBindless)) {

View File

@ -318,6 +318,9 @@ void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf, const Luminai
<< "uniform vec3 vplPos, camPos;" << endl << "uniform vec3 vplPos, camPos;" << endl
<< "varying vec3 normal, tangent, lightVec, camVec;" << endl << "varying vec3 normal, tangent, lightVec, camVec;" << endl
<< "varying vec2 uv;" << endl << "varying vec2 uv;" << endl
#if defined(MTS_HAS_VERTEX_COLORS)
<< "varying vec3 vertexColor;" << endl
#endif
<< endl << endl
<< "void main() {" << endl << "void main() {" << endl
<< " normal = gl_Normal;" << endl << " normal = gl_Normal;" << endl
@ -326,6 +329,9 @@ void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf, const Luminai
<< " camVec = camPos - gl_Vertex.xyz;" << endl << " camVec = camPos - gl_Vertex.xyz;" << endl
<< " lightVec = vplPos - gl_Vertex.xyz;" << endl << " lightVec = vplPos - gl_Vertex.xyz;" << endl
<< " gl_Position = ftransform();" << endl << " gl_Position = ftransform();" << endl
#if defined(MTS_HAS_VERTEX_COLORS)
<< " vertexColor = gl_Color.rgb;" << endl
#endif
<< "}" << endl; << "}" << endl;
program->setSource(GPUProgram::EVertexProgram, oss.str()); program->setSource(GPUProgram::EVertexProgram, oss.str());
@ -339,6 +345,9 @@ void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf, const Luminai
<< "uniform float nearClip, invClipRange, minDist;" << endl << "uniform float nearClip, invClipRange, minDist;" << endl
<< "uniform vec2 vplUV;" << endl << "uniform vec2 vplUV;" << endl
<< "uniform bool diffuseSources, diffuseReceivers;" << endl << "uniform bool diffuseSources, diffuseReceivers;" << endl
#if defined(MTS_HAS_VERTEX_COLORS)
<< "varying vec3 vertexColor;" << endl
#endif
<< endl << endl
<< "/* Inputs <- Vertex program */" << endl << "/* Inputs <- Vertex program */" << endl
<< "varying vec3 normal, tangent, lightVec, camVec;" << endl << "varying vec3 normal, tangent, lightVec, camVec;" << endl

View File

@ -179,13 +179,20 @@ void KDTree::rayIntersectPacket(const Ray *rays, Intersection *its) const {
it.dpdv = v0.dpdv * b.x + v1.dpdv * b.y + v2.dpdv * b.z; it.dpdv = v0.dpdv * b.x + v1.dpdv * b.y + v2.dpdv * b.z;
it.shFrame.n = normalize(v0.n * b.x + v1.n * b.y + v2.n * b.z); it.shFrame.n = normalize(v0.n * b.x + v1.n * b.y + v2.n * b.z);
it.shFrame.s = normalize(it.dpdu - it.shFrame.n it.shFrame.s = normalize(it.dpdu - it.shFrame.n
* dot(it.shFrame.n, it.dpdu)); * dot(it.shFrame.n, it.dpdu));
it.geoFrame.t = cross(it.shFrame.n, it.shFrame.s); it.geoFrame.t = cross(it.shFrame.n, it.shFrame.s);
it.wi = it.toLocal(-rayD); it.wi = it.toLocal(-rayD);
it.hasUVPartials = false; it.hasUVPartials = false;
it.shape = shape; it.shape = shape;
#if defined(MTS_HAS_VERTEX_COLORS)
it.color.fromLinearRGB(
v0.color[0] * b.x + v1.color[0] * b.y + v2.color[0] * b.z,
v0.color[1] * b.x + v1.color[1] * b.y + v2.color[1] * b.z,
v0.color[2] * b.x + v1.color[2] * b.y + v2.color[2] * b.z
);
#endif
} else { } else {
/* Non-triangle shape: intersect again to fill in details */ /* Non-triangle shape: intersect again to fill in details */
shape->rayIntersect(rays[i], it); shape->rayIntersect(rays[i], it);

View File

@ -278,6 +278,7 @@ bool KDTree::rayIntersect(const Ray &ray, Intersection &its) const {
its.uv = v0.uv * b.x + v1.uv * b.y + v2.uv * b.z; its.uv = v0.uv * b.x + v1.uv * b.y + v2.uv * b.z;
its.dpdu = v0.dpdu * b.x + v1.dpdu * b.y + v2.dpdu * b.z; its.dpdu = v0.dpdu * b.x + v1.dpdu * b.y + v2.dpdu * b.z;
its.dpdv = v0.dpdv * b.x + v1.dpdv * b.y + v2.dpdv * b.z; its.dpdv = v0.dpdv * b.x + v1.dpdv * b.y + v2.dpdv * b.z;
its.geoFrame.n = faceNormal; its.geoFrame.n = faceNormal;
its.shape = shape; its.shape = shape;
@ -288,6 +289,14 @@ bool KDTree::rayIntersect(const Ray &ray, Intersection &its) const {
its.shFrame.t = cross(its.shFrame.n, its.shFrame.s); its.shFrame.t = cross(its.shFrame.n, its.shFrame.s);
its.wi = its.toLocal(-ray.d); its.wi = its.toLocal(-ray.d);
its.hasUVPartials = false; its.hasUVPartials = false;
#if defined(MTS_HAS_VERTEX_COLORS)
its.color.fromLinearRGB(
v0.color[0] * b.x + v1.color[0] * b.y + v2.color[0] * b.z,
v0.color[1] * b.x + v1.color[1] * b.y + v2.color[1] * b.z,
v0.color[2] * b.x + v1.color[2] * b.y + v2.color[2] * b.z
);
#endif
} else { } else {
/* Non-triangle shape: intersect again to fill in details */ /* Non-triangle shape: intersect again to fill in details */
if (!shape->rayIntersect(ray, its)) if (!shape->rayIntersect(ray, its))

View File

@ -300,6 +300,14 @@ void PreviewWorker::processCoherent(const WorkUnit *workUnit, WorkResult *workRe
its.shFrame.n = normalize(v0.n * alpha + v1.n * beta + v2.n * gamma); its.shFrame.n = normalize(v0.n * alpha + v1.n * beta + v2.n * gamma);
its.uv = v0.uv * alpha + v1.uv * beta + v2.uv * gamma; its.uv = v0.uv * alpha + v1.uv * beta + v2.uv * gamma;
#if defined(MTS_HAS_VERTEX_COLORS)
its.color.fromLinearRGB(
v0.color[0] * alpha + v1.color[0] * beta + v2.color[0] * gamma,
v0.color[1] * alpha + v1.color[1] * beta + v2.color[1] * gamma,
v0.color[2] * alpha + v1.color[2] * beta + v2.color[2] * gamma
);
#endif
if (EXPECT_NOT_TAKEN(bsdf->getType() != BSDF::EDiffuseReflection || !diffuseVPL)) { if (EXPECT_NOT_TAKEN(bsdf->getType() != BSDF::EDiffuseReflection || !diffuseVPL)) {
its.dpdu = v0.dpdu * alpha + v1.dpdu * beta + v2.dpdu * gamma; its.dpdu = v0.dpdu * alpha + v1.dpdu * beta + v2.dpdu * gamma;
its.dpdv = v0.dpdv * alpha + v1.dpdv * beta + v2.dpdv * gamma; its.dpdv = v0.dpdv * alpha + v1.dpdv * beta + v2.dpdv * gamma;

View File

@ -144,8 +144,10 @@ void TriMesh::configure() {
return; return;
AssertEx(m_triangleCount > 0, "Encountered an empty triangle mesh!"); AssertEx(m_triangleCount > 0, "Encountered an empty triangle mesh!");
for (size_t i=0; i<m_triangleCount; i++) for (size_t i=0; i<m_triangleCount; i++)
m_areaPDF.put(m_triangles[i].surfaceArea(m_vertexBuffer)); m_areaPDF.put(m_triangles[i].surfaceArea(m_vertexBuffer));
m_surfaceArea = m_areaPDF.build(); m_surfaceArea = m_areaPDF.build();
m_invSurfaceArea = 1.0f / m_surfaceArea; m_invSurfaceArea = 1.0f / m_surfaceArea;
/* Generate a bounding sphere */ /* Generate a bounding sphere */
@ -166,7 +168,7 @@ Float TriMesh::sampleArea(ShapeSamplingRecord &sRec, const Point2 &sample) const
void TriMesh::calculateTangentSpaceBasis(bool hasNormals, bool hasTexCoords, bool complain) { void TriMesh::calculateTangentSpaceBasis(bool hasNormals, bool hasTexCoords, bool complain) {
/* Calculate smooth normals if there aren't any */ /* Calculate smooth normals if there aren't any */
int zeroArea = 0, zeroNormals = 0; int zeroArea = 0, zeroNormals = 0, invalidNormals = 0;
if (!hasNormals) { if (!hasNormals) {
for (unsigned int i=0; i<m_vertexCount; i++) for (unsigned int i=0; i<m_vertexCount; i++)
@ -192,13 +194,16 @@ void TriMesh::calculateTangentSpaceBasis(bool hasNormals, bool hasTexCoords, boo
m_vertexBuffer[i].n /= length; m_vertexBuffer[i].n /= length;
} else { } else {
/* Choose some bogus value */ /* Choose some bogus value */
if (complain) invalidNormals++;
Log(EWarn, "Could not generate correct mesh normals!");
m_vertexBuffer[i].n = Normal(1, 0, 0); m_vertexBuffer[i].n = Normal(1, 0, 0);
} }
} }
} }
if (complain && invalidNormals > 0)
Log(EWarn, "\"%s\": mesh contains invalid geometry: unable "
"to generate %i normals!", m_name.c_str(), invalidNormals);
if (m_flipNormals) { if (m_flipNormals) {
for (unsigned int i=0; i<m_vertexCount; i++) for (unsigned int i=0; i<m_vertexCount; i++)
m_vertexBuffer[i].n *= -1; m_vertexBuffer[i].n *= -1;
@ -314,8 +319,8 @@ void TriMesh::calculateTangentSpaceBasis(bool hasNormals, bool hasTexCoords, boo
} }
if (complain && (zeroArea > 0 || zeroNormals > 0)) if (complain && (zeroArea > 0 || zeroNormals > 0))
Log(EWarn, "Mesh contains invalid geometry: %i zero area triangles " Log(EWarn, "\"%s\": mesh contains invalid geometry: %i zero area triangles "
"and %i zero normals found!", zeroArea, zeroNormals); "and %i zero normals found!", m_name.c_str(), zeroArea, zeroNormals);
} }
void TriMesh::serialize(Stream *stream, InstanceManager *manager) const { void TriMesh::serialize(Stream *stream, InstanceManager *manager) const {

View File

@ -50,6 +50,10 @@ AboutDialog::AboutDialog(QWidget *parent) :
configFlags += "MTS_HAS_COHERENT_RT "; configFlags += "MTS_HAS_COHERENT_RT ";
#endif #endif
#if defined(MTS_HAS_VERTEX_COLORS)
configFlags += "MTS_HAS_VERTEX_COLORS ";
#endif
#if defined(MTS_HAS_COLLADA) #if defined(MTS_HAS_COLLADA)
configFlags += "MTS_HAS_COLLADA "; configFlags += "MTS_HAS_COLLADA ";
#endif #endif

View File

@ -61,6 +61,7 @@ p, li { white-space: pre-wrap; }
&lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://glew.sourceforge.net/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;GLEW&lt;/span&gt;&lt;/a&gt; by Milan Ikits, Marcelo E. Magallon and Lev Povalahev&lt;/li&gt; &lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://glew.sourceforge.net/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;GLEW&lt;/span&gt;&lt;/a&gt; by Milan Ikits, Marcelo E. Magallon and Lev Povalahev&lt;/li&gt;
&lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://sourceforge.net/projects/collada-dom/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;COLLADA DOM&lt;/span&gt;&lt;/a&gt; by Sony Computer Entertainment&lt;/li&gt; &lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://sourceforge.net/projects/collada-dom/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;COLLADA DOM&lt;/span&gt;&lt;/a&gt; by Sony Computer Entertainment&lt;/li&gt;
&lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Mersenne Twister&lt;/span&gt;&lt;/a&gt; by Makoto Matsumoto and Takuji Nishimura&lt;/li&gt; &lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Mersenne Twister&lt;/span&gt;&lt;/a&gt; by Makoto Matsumoto and Takuji Nishimura&lt;/li&gt;
&lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://people.cs.kuleuven.be/~ares.lagae/libply/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;libply&lt;/span&gt;&lt;/a&gt; by Ares Lagae&lt;/li&gt;
&lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://www.ijg.org/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;libjpeg&lt;/span&gt;&lt;/a&gt; by the Independent JPEG Group&lt;/li&gt; &lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://www.ijg.org/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;libjpeg&lt;/span&gt;&lt;/a&gt; by the Independent JPEG Group&lt;/li&gt;
&lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://www.libpng.org/pub/png&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;libpng&lt;/span&gt;&lt;/a&gt; by Guy Eric Schalnat, Andreas Dilger, Glenn Randers-Pehrson and others&lt;/li&gt; &lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://www.libpng.org/pub/png&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;libpng&lt;/span&gt;&lt;/a&gt; by Guy Eric Schalnat, Andreas Dilger, Glenn Randers-Pehrson and others&lt;/li&gt;
&lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://www.brandonwalkin.com/bwtoolkit/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;BWToolkit&lt;/span&gt;&lt;/a&gt; by Brandon Walkin&lt;/li&gt; &lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://www.brandonwalkin.com/bwtoolkit/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;BWToolkit&lt;/span&gt;&lt;/a&gt; by Brandon Walkin&lt;/li&gt;

View File

@ -309,7 +309,7 @@ public:
if (currentMaterial) if (currentMaterial)
mesh->addChild("", currentMaterial); mesh->addChild("", currentMaterial);
m_meshes.push_back(mesh); m_meshes.push_back(mesh);
SLog(EInfo, "%s: Loaded " SIZE_T_FMT " triangles, " SIZE_T_FMT Log(EInfo, "%s: Loaded " SIZE_T_FMT " triangles, " SIZE_T_FMT
" vertices (merged " SIZE_T_FMT " vertices).", name.c_str(), " vertices (merged " SIZE_T_FMT " vertices).", name.c_str(),
triangles.size(), vertexBuffer.size(), numMerged); triangles.size(), vertexBuffer.size(), numMerged);
} }

262
src/shapes/ply/ply.cpp Normal file
View File

@ -0,0 +1,262 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include <mitsuba/render/trimesh.h>
#include <mitsuba/core/fresolver.h>
#include <mitsuba/core/properties.h>
#include <mitsuba/core/fstream.h>
#include <ply/ply_parser.hpp>
#include <tr1/functional>
using namespace std::tr1::placeholders;
MTS_NAMESPACE_BEGIN
/**
* PLY mesh loader using libply by Ares Lagae
* (http://people.cs.kuleuven.be/~ares.lagae/libply/)
*/
class PLYLoader : public TriMesh {
public:
PLYLoader(const Properties &props) : TriMesh(props) {
fs::path filePath = Thread::getThread()->getFileResolver()->resolve(
props.getString("filename"));
m_name = filePath.stem();
/* Load the geometry */
Log(EInfo, "Loading geometry from \"%s\" ..", filePath.leaf().c_str());
m_triangleCount = m_vertexCount = 0;
m_vertexCtr = m_triangleCtr = m_triangleIdxCtr = 0;
m_normal = Normal(0.0f);
m_uv = Point2(0.0f);
m_hasNormals = false;
m_hasTexCoords = false;
memset(&m_triangle, 0, sizeof(Triangle));
loadPLY(filePath);
if (m_triangleCount == 0 || m_vertexCount == 0)
Log(EError, "Unable to load \"%s\" (no triangles or vertices found)!");
Assert(m_triangleCtr == m_triangleCount);
Assert(m_vertexCtr == m_vertexCount);
calculateTangentSpaceBasis(m_hasNormals, m_hasTexCoords, true);
}
PLYLoader(Stream *stream, InstanceManager *manager) : TriMesh(stream, manager) { }
void loadPLY(const fs::path &path);
void info_callback(const std::string& filename, std::size_t line_number,
const std::string& message) {
Log(EInfo, "\"%s\" [line %i] info: %s", filename.c_str(), line_number,
message.c_str());
}
void warning_callback(const std::string& filename, std::size_t line_number,
const std::string& message) {
Log(EWarn, "\"%s\" [line %i] warning: %s", filename.c_str(), line_number,
message.c_str());
}
void error_callback(const std::string& filename, std::size_t line_number,
const std::string& message) {
Log(EError, "\"%s\" [line %i] error: %s", filename.c_str(), line_number,
message.c_str());
}
template<typename ValueType> std::tr1::function <void (ValueType)>
scalar_property_definition_callback(const std::string& element_name,
const std::string& property_name);
std::tr1::tuple<std::tr1::function<void()>, std::tr1::function<void()> >
element_definition_callback(const std::string& element_name, std::size_t count) {
if (element_name == "vertex") {
m_vertexCount = count;
m_vertexBuffer = new Vertex[count];
return std::tr1::tuple<std::tr1::function<void()>,
std::tr1::function<void()> >(
std::tr1::bind(&PLYLoader::vertex_begin_callback, this),
std::tr1::bind(&PLYLoader::vertex_end_callback, this)
);
} else if (element_name == "face") {
m_triangleCount = count;
m_triangles = new Triangle[m_triangleCount];
return std::tr1::tuple<std::tr1::function<void()>,
std::tr1::function<void()> >(
std::tr1::bind(&PLYLoader::face_begin_callback, this),
std::tr1::bind(&PLYLoader::face_end_callback, this)
);
} else {
return
std::tr1::tuple<std::tr1::function<void()>,
std::tr1::function<void()> >(0, 0);
}
}
std::tr1::tuple<std::tr1::function<void (ply::uint8)>,
std::tr1::function<void (ply::int32)>, std::tr1::function<void ()> >
list_property_definition_callback(const std::string& element_name,
const std::string& property_name) {
if ((element_name == "face") && (property_name == "vertex_indices")) {
return std::tr1::tuple<std::tr1::function<void (ply::uint8)>,
std::tr1::function<void (ply::int32)>, std::tr1::function<void ()> >(
std::tr1::bind(&PLYLoader::face_vertex_indices_begin, this, _1),
std::tr1::bind(&PLYLoader::face_vertex_indices_element, this, _1),
std::tr1::bind(&PLYLoader::face_vertex_indices_end, this)
);
} else {
return std::tr1::tuple<std::tr1::function<void (ply::uint8)>,
std::tr1::function<void (ply::int32)>,
std::tr1::function<void ()> >(0, 0, 0);
}
}
void vertex_begin_callback() { }
void vertex_x_callback(ply::float32 x) { m_position.x = x; }
void vertex_y_callback(ply::float32 y) { m_position.y = y; }
void vertex_z_callback(ply::float32 z) { m_position.z = z; }
void normal_x_callback(ply::float32 x) { m_normal.x = x; }
void normal_y_callback(ply::float32 y) { m_normal.y = y; }
void normal_z_callback(ply::float32 z) { m_normal.z = z; }
void texcoord_u_callback(ply::float32 x) { m_uv.x = x; }
void texcoord_v_callback(ply::float32 y) { m_uv.y = y; }
void vertex_end_callback() {
m_vertexBuffer[m_vertexCtr].p = m_position;
m_vertexBuffer[m_vertexCtr].n = m_normal;
m_vertexBuffer[m_vertexCtr].uv = m_uv;
m_vertexBuffer[m_vertexCtr].dpdu = Vector(0.0f);
m_vertexBuffer[m_vertexCtr].dpdv = Vector(0.0f);
#if defined(MTS_HAS_VERTEX_COLORS)
m_vertexBuffer[m_vertexCtr].color[0] = m_red;
m_vertexBuffer[m_vertexCtr].color[1] = m_green;
m_vertexBuffer[m_vertexCtr].color[2] = m_blue;
#endif
m_vertexCtr++;
}
void diffuse_red_callback(ply::uint8 r) { m_red = r / 255.0f; }
void diffuse_green_callback(ply::uint8 g) { m_green = g / 255.0f; }
void diffuse_blue_callback(ply::uint8 b) { m_blue = b / 255.0f; }
void face_begin_callback() { }
void face_end_callback() { }
void face_vertex_indices_begin(ply::uint8 size) {
AssertEx(size == 3, "Only triangle PLY meshes are supported for now.");
m_triangleIdxCtr = 0;
}
void face_vertex_indices_element(ply::int32 element) {
Assert(m_triangleIdxCtr < 3);
Assert((size_t) element < m_vertexCount);
m_triangle.idx[m_triangleIdxCtr++] = element;
}
void face_vertex_indices_end() {
Assert(m_triangleIdxCtr == 3);
m_triangles[m_triangleCtr++] = m_triangle;
}
MTS_DECLARE_CLASS()
private:
Point m_position;
Normal m_normal;
Float m_red, m_green, m_blue;
size_t m_vertexCtr, m_triangleCtr, m_triangleIdxCtr;
Triangle m_triangle;
bool m_hasNormals, m_hasTexCoords;
Point2 m_uv;
};
template<> std::tr1::function <void (ply::float32)>
PLYLoader::scalar_property_definition_callback(const std::string& element_name,
const std::string& property_name) {
if (element_name == "vertex") {
if (property_name == "x") {
return std::tr1::bind(&PLYLoader::vertex_x_callback, this, _1);
} else if (property_name == "y") {
return std::tr1::bind(&PLYLoader::vertex_y_callback, this, _1);
} else if (property_name == "z") {
return std::tr1::bind(&PLYLoader::vertex_z_callback, this, _1);
} else if (property_name == "nx") {
m_hasNormals = true;
return std::tr1::bind(&PLYLoader::normal_x_callback, this, _1);
} else if (property_name == "ny") {
return std::tr1::bind(&PLYLoader::normal_y_callback, this, _1);
} else if (property_name == "nz") {
return std::tr1::bind(&PLYLoader::normal_z_callback, this, _1);
} else if (property_name == "u") {
m_hasTexCoords = true;
return std::tr1::bind(&PLYLoader::texcoord_u_callback, this, _1);
} else if (property_name == "v") {
return std::tr1::bind(&PLYLoader::texcoord_v_callback, this, _1);
}
}
return 0;
}
template<> std::tr1::function <void (ply::uint8)>
PLYLoader::scalar_property_definition_callback(const std::string& element_name,
const std::string& property_name) {
if (element_name == "vertex") {
if (property_name == "diffuse_red" || property_name == "red") {
return std::tr1::bind(&PLYLoader::diffuse_red_callback, this, _1);
} else if (property_name == "diffuse_green" || property_name == "green") {
return std::tr1::bind(&PLYLoader::diffuse_green_callback, this, _1);
} else if (property_name == "diffuse_blue" || property_name == "blue") {
return std::tr1::bind(&PLYLoader::diffuse_blue_callback, this, _1);
}
}
return 0;
}
void PLYLoader::loadPLY(const fs::path &path) {
ply::ply_parser ply_parser;
ply_parser.info_callback(std::tr1::bind(&PLYLoader::info_callback,
this, std::tr1::ref(m_name), _1, _2));
ply_parser.warning_callback(std::tr1::bind(&PLYLoader::warning_callback,
this, std::tr1::ref(m_name), _1, _2));
ply_parser.error_callback(std::tr1::bind(&PLYLoader::error_callback,
this, std::tr1::ref(m_name), _1, _2));
ply_parser.element_definition_callback(std::tr1::bind(&PLYLoader::element_definition_callback,
this, _1, _2));
ply::ply_parser::scalar_property_definition_callbacks_type scalar_property_definition_callbacks;
ply::ply_parser::list_property_definition_callbacks_type list_property_definition_callbacks;
ply::at<ply::float32>(scalar_property_definition_callbacks) = std::tr1::bind(
&PLYLoader::scalar_property_definition_callback<ply::float32>, this, _1, _2);
ply::at<ply::uint8>(scalar_property_definition_callbacks) = std::tr1::bind(
&PLYLoader::scalar_property_definition_callback<ply::uint8>, this, _1, _2);
ply::at<ply::uint8, ply::int32>(list_property_definition_callbacks) =std::tr1::bind(
&PLYLoader::list_property_definition_callback, this, _1, _2);
ply_parser.scalar_property_definition_callbacks(scalar_property_definition_callbacks);
ply_parser.list_property_definition_callbacks(list_property_definition_callbacks);
ply_parser.parse(path.file_string());
Log(EInfo, "\"%s\": Loaded " SIZE_T_FMT " triangles, " SIZE_T_FMT
" vertices.", m_name.c_str(), m_triangleCount, m_vertexCount);
}
MTS_IMPLEMENT_CLASS_S(PLYLoader, false, TriMesh)
MTS_EXPORT_PLUGIN(PLYLoader, "PLY mesh loader");
MTS_NAMESPACE_END

View File

@ -0,0 +1,74 @@
#ifndef PLY_BYTE_ORDER_HPP_INCLUDED
#define PLY_BYTE_ORDER_HPP_INCLUDED
namespace ply {
#if defined(PLY_BIG_ENDIAN) || defined(PLY_LITTLE_ENDIAN)
# error
#endif
#if (defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) || defined(__ppc__) || defined(_M_PPC) || defined(__ARCH_PPC))
# define PLY_BIG_ENDIAN
#elif (defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || defined(__INTEL__)) \
|| (defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64))
# define PLY_LITTLE_ENDIAN
#else
# error
#endif
enum byte_order
{
little_endian_byte_order = 0,
big_endian_byte_order = 1,
#if defined(PLY_BIG_ENDIAN)
host_byte_order = big_endian_byte_order,
#elif defined(PLY_LITTLE_ENDIAN)
host_byte_order = little_endian_byte_order,
#else
# error
#endif
network_byte_order = big_endian_byte_order
};
#undef PLY_BIG_ENDIAN
#undef PLY_LITTLE_ENDIAN
template <std::size_t N>
void swap_byte_order(char* bytes);
template <>
inline void swap_byte_order<1>(char* bytes)
{
}
template <>
inline void swap_byte_order<2>(char* bytes)
{
std::swap(bytes[0], bytes[1]);
}
template <>
inline void swap_byte_order<4>(char* bytes)
{
std::swap(bytes[0], bytes[3]);
std::swap(bytes[1], bytes[2]);
}
template <>
inline void swap_byte_order<8>(char* bytes)
{
std::swap(bytes[0], bytes[7]);
std::swap(bytes[1], bytes[6]);
std::swap(bytes[2], bytes[5]);
std::swap(bytes[3], bytes[4]);
}
template <typename T>
void swap_byte_order(T& value)
{
swap_byte_order<sizeof(T)>(reinterpret_cast<char*>(&value));
}
} // namespace ply
#endif // PLY_BYTE_ORDER_HPP_INCLUDED

View File

@ -0,0 +1,141 @@
#ifndef _PLY_CONFIG_HPP
#define _PLY_CONFIG_HPP 1
/* ply/config.hpp. Generated automatically at end of configure. */
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* define if the Boost library is available */
#ifndef PLY_HAVE_BOOST
#define PLY_HAVE_BOOST
#endif
/* Define to 1 if you have the <dlfcn.h> header file. */
#ifndef PLY_HAVE_DLFCN_H
#define PLY_HAVE_DLFCN_H 1
#endif
/* Define to 1 if you have the <inttypes.h> header file. */
#ifndef PLY_HAVE_INTTYPES_H
#define PLY_HAVE_INTTYPES_H 1
#endif
/* Define to 1 if you have the <memory.h> header file. */
#ifndef PLY_HAVE_MEMORY_H
#define PLY_HAVE_MEMORY_H 1
#endif
/* Define to 1 if stdbool.h conforms to C99. */
#ifndef PLY_HAVE_STDBOOL_H
#define PLY_HAVE_STDBOOL_H 1
#endif
/* Define to 1 if you have the <stdint.h> header file. */
#ifndef PLY_HAVE_STDINT_H
#define PLY_HAVE_STDINT_H 1
#endif
/* Define to 1 if you have the <stdlib.h> header file. */
#ifndef PLY_HAVE_STDLIB_H
#define PLY_HAVE_STDLIB_H 1
#endif
/* Define to 1 if you have the <strings.h> header file. */
#ifndef PLY_HAVE_STRINGS_H
#define PLY_HAVE_STRINGS_H 1
#endif
/* Define to 1 if you have the <string.h> header file. */
#ifndef PLY_HAVE_STRING_H
#define PLY_HAVE_STRING_H 1
#endif
/* Define to 1 if you have the <sys/stat.h> header file. */
#ifndef PLY_HAVE_SYS_STAT_H
#define PLY_HAVE_SYS_STAT_H 1
#endif
/* Define to 1 if you have the <sys/types.h> header file. */
#ifndef PLY_HAVE_SYS_TYPES_H
#define PLY_HAVE_SYS_TYPES_H 1
#endif
/* Define to 1 if you have <tr1/cstdint>. */
#ifndef PLY_HAVE_TR1_CSTDINT
#define PLY_HAVE_TR1_CSTDINT 1
#endif
/* Define to 1 if you have <tr1/functional>. */
#ifndef PLY_HAVE_TR1_FUNCTIONAL
#define PLY_HAVE_TR1_FUNCTIONAL 1
#endif
/* Define to 1 if you have <tr1/tuple>. */
#ifndef PLY_HAVE_TR1_TUPLE
#define PLY_HAVE_TR1_TUPLE 1
#endif
/* Define to 1 if you have <tr1/memory>. */
#ifndef PLY_HAVE_TR1_memory
#define PLY_HAVE_TR1_memory 1
#endif
/* Define to 1 if you have the <unistd.h> header file. */
#ifndef PLY_HAVE_UNISTD_H
#define PLY_HAVE_UNISTD_H 1
#endif
/* Define to 1 if the system has the type `_Bool'. */
/* #undef HAVE__BOOL */
/* Name of package */
#ifndef PLY_PACKAGE
#define PLY_PACKAGE "ply"
#endif
/* Author of package */
#ifndef PLY_PACKAGE_AUTHOR
#define PLY_PACKAGE_AUTHOR "Ares Lagae"
#endif
/* Define to the address where bug reports for this package should be sent. */
#ifndef PLY_PACKAGE_BUGREPORT
#define PLY_PACKAGE_BUGREPORT "ares.lagae@cs.kuleuven.be"
#endif
/* Define to the full name of this package. */
#ifndef PLY_PACKAGE_NAME
#define PLY_PACKAGE_NAME "ply"
#endif
/* Define to the full name and version of this package. */
#ifndef PLY_PACKAGE_STRING
#define PLY_PACKAGE_STRING "ply 0.1"
#endif
/* Define to the one symbol short name of this package. */
#ifndef PLY_PACKAGE_TARNAME
#define PLY_PACKAGE_TARNAME "ply"
#endif
/* Define to the version of this package. */
#ifndef PLY_PACKAGE_VERSION
#define PLY_PACKAGE_VERSION "0.1"
#endif
/* Define to 1 if you have the ANSI C header files. */
/* #undef STDC_HEADERS */
/* Version number of package */
#ifndef PLY_VERSION
#define PLY_VERSION "0.1"
#endif
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
/* once: _PLY_CONFIG_HPP */
#endif

View File

@ -0,0 +1,54 @@
#ifndef PLY_IO_OPERATORS_HPP_INCLUDED
#define PLY_IO_OPERATORS_HPP_INCLUDED
#include <istream>
#include <limits>
#include <ostream>
namespace ply {
namespace io_operators {
inline std::istream& operator>>(std::istream& istream, int8 &value)
{
int16 tmp;
if (istream >> tmp) {
if (tmp <= std::numeric_limits<int8>::max()) {
value = static_cast<int8>(tmp);
}
else {
istream.setstate(std::ios_base::failbit);
}
}
return istream;
}
inline std::istream& operator>>(std::istream& istream, uint8 &value)
{
uint16 tmp;
if (istream >> tmp) {
if (tmp <= std::numeric_limits<uint8>::max()) {
value = static_cast<uint8>(tmp);
}
else {
istream.setstate(std::ios_base::failbit);
}
}
return istream;
}
inline std::ostream& operator<<(std::ostream& ostream, int8 value)
{
return ostream << static_cast<int16>(value);
}
inline std::ostream& operator<<(std::ostream& ostream, uint8 value)
{
return ostream << static_cast<uint16>(value);
}
} // namespace io_operators
} // namespace ply
#endif // PLY_IO_OPERATORS_HPP_INCLUDED

View File

@ -0,0 +1,53 @@
#ifndef PLY_PLY_HPP_INCLUDED
#define PLY_PLY_HPP_INCLUDED
#include <tr1/cstdint>
namespace ply {
typedef std::tr1::int8_t int8;
typedef std::tr1::int16_t int16;
typedef std::tr1::int32_t int32;
typedef std::tr1::uint8_t uint8;
typedef std::tr1::uint16_t uint16;
typedef std::tr1::uint32_t uint32;
typedef float float32;
typedef double float64;
template <typename ScalarType>
struct type_traits;
#ifdef PLY_TYPE_TRAITS
# error
#endif
#define PLY_TYPE_TRAITS(TYPE, NAME, OLD_NAME)\
template <>\
struct type_traits<TYPE>\
{\
typedef TYPE type;\
static const char* name() { return NAME; }\
static const char* old_name() { return OLD_NAME; }\
};
PLY_TYPE_TRAITS(int8, "int8", "char")
PLY_TYPE_TRAITS(int16, "int16", "short")
PLY_TYPE_TRAITS(int32, "int32", "int")
PLY_TYPE_TRAITS(uint8, "uint8", "uchar")
PLY_TYPE_TRAITS(uint16, "uint16", "ushort")
PLY_TYPE_TRAITS(uint32, "uint32", "uint")
PLY_TYPE_TRAITS(float32, "float32", "float")
PLY_TYPE_TRAITS(float64, "float64", "double")
#undef PLY_TYPE_TRAITS
typedef int format_type;
enum format {
binary_little_endian_format = 0,
binary_big_endian_format = 1,
ascii_format = 2
};
} // namespace ply
#endif // PLY_PLY_HPP_INCLUDED

View File

@ -0,0 +1,513 @@
#ifndef PLY_PLY_PARSER_HPP_INCLUDED
#define PLY_PLY_PARSER_HPP_INCLUDED
#include <fstream>
#include <iostream>
#include <istream>
#include <sstream>
#include <string>
#include <vector>
#include <tr1/functional>
#include <tr1/memory>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/inherit.hpp>
#include <boost/mpl/inherit_linearly.hpp>
#include <boost/mpl/joint_view.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/vector.hpp>
#include <ply/ply.hpp>
#include <ply/byte_order.hpp>
#include <ply/io_operators.hpp>
namespace ply {
class ply_parser
{
public:
typedef std::tr1::function<void (std::size_t, const std::string&)> info_callback_type;
typedef std::tr1::function<void (std::size_t, const std::string&)> warning_callback_type;
typedef std::tr1::function<void (std::size_t, const std::string&)> error_callback_type;
typedef std::tr1::function<void ()> magic_callback_type;
typedef std::tr1::function<void (format_type, const std::string&)> format_callback_type;
typedef std::tr1::function<void (const std::string&)> comment_callback_type;
typedef std::tr1::function<void (const std::string&)> obj_info_callback_type;
typedef std::tr1::function<bool ()> end_header_callback_type;
typedef std::tr1::function<void()> begin_element_callback_type;
typedef std::tr1::function<void()> end_element_callback_type;
typedef std::tr1::tuple<begin_element_callback_type, end_element_callback_type> element_callbacks_type;
typedef std::tr1::function<element_callbacks_type (const std::string&, std::size_t)> element_definition_callback_type;
template <typename ScalarType>
struct scalar_property_callback_type
{
typedef std::tr1::function<void (ScalarType)> type;
};
template <typename ScalarType>
struct scalar_property_definition_callback_type
{
typedef typename scalar_property_callback_type<ScalarType>::type scalar_property_callback_type;
typedef std::tr1::function<scalar_property_callback_type (const std::string&, const std::string&)> type;
};
typedef boost::mpl::vector<int8, int16, int32, uint8, uint16, uint32, float32, float64> scalar_types;
class scalar_property_definition_callbacks_type
{
private:
template <typename T>
struct callbacks_element
{
typedef T scalar_type;
typename scalar_property_definition_callback_type<scalar_type>::type callback;
};
typedef boost::mpl::inherit_linearly<
scalar_types,
boost::mpl::inherit<
boost::mpl::_1,
callbacks_element<boost::mpl::_2>
>
>::type callbacks;
callbacks callbacks_;
public:
template <typename ScalarType>
const typename scalar_property_definition_callback_type<ScalarType>::type& get() const
{
return static_cast<const callbacks_element<ScalarType>&>(callbacks_).callback;
}
template <typename ScalarType>
typename scalar_property_definition_callback_type<ScalarType>::type& get()
{
return static_cast<callbacks_element<ScalarType>&>(callbacks_).callback;
}
template <typename ScalarType>
friend typename scalar_property_definition_callback_type<ScalarType>::type& at(scalar_property_definition_callbacks_type& scalar_property_definition_callbacks)
{
return scalar_property_definition_callbacks.get<ScalarType>();
}
template <typename ScalarType>
friend const typename scalar_property_definition_callback_type<ScalarType>::type& at(const scalar_property_definition_callbacks_type& scalar_property_definition_callbacks)
{
return scalar_property_definition_callbacks.get<ScalarType>();
}
};
template <typename SizeType, typename ScalarType>
struct list_property_begin_callback_type
{
typedef std::tr1::function<void (SizeType)> type;
};
template <typename SizeType, typename ScalarType>
struct list_property_element_callback_type
{
typedef std::tr1::function<void (ScalarType)> type;
};
template <typename SizeType, typename ScalarType>
struct list_property_end_callback_type
{
typedef std::tr1::function<void ()> type;
};
template <typename SizeType, typename ScalarType>
struct list_property_definition_callback_type
{
typedef typename list_property_begin_callback_type<SizeType, ScalarType>::type list_property_begin_callback_type;
typedef typename list_property_element_callback_type<SizeType, ScalarType>::type list_property_element_callback_type;
typedef typename list_property_end_callback_type<SizeType, ScalarType>::type list_property_end_callback_type;
typedef std::tr1::function<
std::tr1::tuple<
list_property_begin_callback_type,
list_property_element_callback_type,
list_property_end_callback_type
>(const std::string&, const std::string&)> type;
};
typedef boost::mpl::vector<uint8, uint16, uint32> size_types;
class list_property_definition_callbacks_type
{
private:
template <typename T> struct pair_with : boost::mpl::pair<T,boost::mpl::_> {};
template<typename Sequence1, typename Sequence2>
struct sequence_product :
boost::mpl::fold<
Sequence1,
boost::mpl::vector0<>,
boost::mpl::joint_view<
boost::mpl::_1,
boost::mpl::transform<
Sequence2,
pair_with<boost::mpl::_2>
>
>
>
{};
template <typename T>
struct callbacks_element
{
typedef typename T::first size_type;
typedef typename T::second scalar_type;
typename list_property_definition_callback_type<size_type, scalar_type>::type callback;
};
typedef boost::mpl::inherit_linearly<
sequence_product<size_types, scalar_types>::type,
boost::mpl::inherit<
boost::mpl::_1,
callbacks_element<boost::mpl::_2>
>
>::type callbacks;
callbacks callbacks_;
public:
template <typename SizeType, typename ScalarType>
typename list_property_definition_callback_type<SizeType, ScalarType>::type& get()
{
return static_cast<callbacks_element<boost::mpl::pair<SizeType, ScalarType> >&>(callbacks_).callback;
}
template <typename SizeType, typename ScalarType>
const typename list_property_definition_callback_type<SizeType, ScalarType>::type& get() const
{
return static_cast<const callbacks_element<boost::mpl::pair<SizeType, ScalarType> >&>(callbacks_).callback;
}
template <typename SizeType, typename ScalarType>
friend typename list_property_definition_callback_type<SizeType, ScalarType>::type& at(list_property_definition_callbacks_type& list_property_definition_callbacks)
{
return list_property_definition_callbacks.get<SizeType, ScalarType>();
}
template <typename SizeType, typename ScalarType>
friend const typename list_property_definition_callback_type<SizeType, ScalarType>::type& at(const list_property_definition_callbacks_type& list_property_definition_callbacks)
{
return list_property_definition_callbacks.get<SizeType, ScalarType>();
}
};
void info_callback(const info_callback_type& info_callback);
void warning_callback(const warning_callback_type& warning_callback);
void error_callback(const error_callback_type& error_callback);
void magic_callback(const magic_callback_type& magic_callback);
void format_callback(const format_callback_type& format_callback);
void element_definition_callback(const element_definition_callback_type& element_definition_callback);
void scalar_property_definition_callbacks(const scalar_property_definition_callbacks_type& scalar_property_definition_callbacks);
void list_property_definition_callbacks(const list_property_definition_callbacks_type& list_property_definition_callbacks);
void comment_callback(const comment_callback_type& comment_callback);
void obj_info_callback(const obj_info_callback_type& obj_info_callback);
void end_header_callback(const end_header_callback_type& end_header_callback);
typedef int flags_type;
enum flags { };
ply_parser(flags_type flags = 0);
bool parse(std::istream& istream);
bool parse(const std::string& filename);
private:
struct property
{
property(const std::string& name) : name(name) {}
virtual ~property() {}
virtual bool parse(class ply_parser& ply_parser, format_type format, std::istream& istream) = 0;
std::string name;
};
template <typename ScalarType>
struct scalar_property : public property
{
typedef ScalarType scalar_type;
typedef typename scalar_property_callback_type<scalar_type>::type callback_type;
scalar_property(const std::string& name, callback_type callback) : property(name), callback(callback) {}
bool parse(class ply_parser& ply_parser, format_type format, std::istream& istream) { return ply_parser.parse_scalar_property<scalar_type>(format, istream, callback); }
callback_type callback;
};
template <typename SizeType, typename ScalarType>
struct list_property : public property
{
typedef SizeType size_type;
typedef ScalarType scalar_type;
typedef typename list_property_begin_callback_type<size_type, scalar_type>::type begin_callback_type;
typedef typename list_property_element_callback_type<size_type, scalar_type>::type element_callback_type;
typedef typename list_property_end_callback_type<size_type, scalar_type>::type end_callback_type;
list_property(const std::string& name, begin_callback_type begin_callback, element_callback_type element_callback, end_callback_type end_callback) : property(name), begin_callback(begin_callback), element_callback(element_callback), end_callback(end_callback) {}
bool parse(class ply_parser& ply_parser, format_type format, std::istream& istream) { return ply_parser.parse_list_property<size_type, scalar_type>(format, istream, begin_callback, element_callback, end_callback); }
begin_callback_type begin_callback;
element_callback_type element_callback;
end_callback_type end_callback;
};
struct element
{
element(const std::string& name, std::size_t count, const begin_element_callback_type& begin_element_callback, const end_element_callback_type& end_element_callback) : name(name), count(count), begin_element_callback(begin_element_callback), end_element_callback(end_element_callback) {}
std::string name;
std::size_t count;
begin_element_callback_type begin_element_callback;
end_element_callback_type end_element_callback;
std::vector<std::tr1::shared_ptr<property> > properties;
};
flags_type flags_;
info_callback_type info_callback_;
warning_callback_type warning_callback_;
error_callback_type error_callback_;
magic_callback_type magic_callback_;
format_callback_type format_callback_;
element_definition_callback_type element_definition_callbacks_;
scalar_property_definition_callbacks_type scalar_property_definition_callbacks_;
list_property_definition_callbacks_type list_property_definition_callbacks_;
comment_callback_type comment_callback_;
obj_info_callback_type obj_info_callback_;
end_header_callback_type end_header_callback_;
template <typename ScalarType> void parse_scalar_property_definition(const std::string& property_name);
template <typename SizeType, typename ScalarType> void parse_list_property_definition(const std::string& property_name);
template <typename ScalarType> bool parse_scalar_property(format_type format, std::istream& istream, const typename scalar_property_callback_type<ScalarType>::type& scalar_property_callback);
template <typename SizeType, typename ScalarType> bool parse_list_property(format_type format, std::istream& istream, const typename list_property_begin_callback_type<SizeType, ScalarType>::type& list_property_begin_callback, const typename list_property_element_callback_type<SizeType, ScalarType>::type& list_property_element_callback, const typename list_property_end_callback_type<SizeType, ScalarType>::type& list_property_end_callback);
std::size_t line_number_;
element* current_element_;
};
} // namespace ply
inline ply::ply_parser::ply_parser(flags_type flags)
: flags_(flags)
{
}
inline bool ply::ply_parser::parse(const std::string& filename)
{
std::ifstream ifstream(filename.c_str());
return parse(ifstream);
}
inline void ply::ply_parser::info_callback(const info_callback_type& info_callback)
{
info_callback_ = info_callback;
}
inline void ply::ply_parser::warning_callback(const warning_callback_type& warning_callback)
{
warning_callback_ = warning_callback;
}
inline void ply::ply_parser::error_callback(const error_callback_type& error_callback)
{
error_callback_ = error_callback;
}
inline void ply::ply_parser::magic_callback(const magic_callback_type& magic_callback)
{
magic_callback_ = magic_callback;
}
inline void ply::ply_parser::format_callback(const format_callback_type& format_callback)
{
format_callback_ = format_callback;
}
inline void ply::ply_parser::element_definition_callback(const element_definition_callback_type& element_definition_callback)
{
element_definition_callbacks_ = element_definition_callback;
}
inline void ply::ply_parser::scalar_property_definition_callbacks(const scalar_property_definition_callbacks_type& scalar_property_definition_callbacks)
{
scalar_property_definition_callbacks_ = scalar_property_definition_callbacks;
}
inline void ply::ply_parser::list_property_definition_callbacks(const list_property_definition_callbacks_type& list_property_definition_callbacks)
{
list_property_definition_callbacks_ = list_property_definition_callbacks;
}
inline void ply::ply_parser::comment_callback(const comment_callback_type& comment_callback)
{
comment_callback_ = comment_callback;
}
inline void ply::ply_parser::obj_info_callback(const obj_info_callback_type& obj_info_callback)
{
obj_info_callback_ = obj_info_callback;
}
inline void ply::ply_parser::end_header_callback(const end_header_callback_type& end_header_callback)
{
end_header_callback_ = end_header_callback;
}
template <typename ScalarType>
inline void ply::ply_parser::parse_scalar_property_definition(const std::string& property_name)
{
typedef ScalarType scalar_type;
typename scalar_property_definition_callback_type<scalar_type>::type& scalar_property_definition_callback = scalar_property_definition_callbacks_.get<scalar_type>();
typename scalar_property_callback_type<scalar_type>::type scalar_property_callback;
if (scalar_property_definition_callback) {
scalar_property_callback = scalar_property_definition_callback(current_element_->name, property_name);
}
if (!scalar_property_callback) {
if (warning_callback_) {
warning_callback_(line_number_, "property " + std::string(type_traits<scalar_type>::name()) + " " + property_name + " of element " + current_element_->name + " is not handled");
}
}
current_element_->properties.push_back(std::tr1::shared_ptr<property>(new scalar_property<scalar_type>(property_name, scalar_property_callback)));
}
template <typename SizeType, typename ScalarType>
inline void ply::ply_parser::parse_list_property_definition(const std::string& property_name)
{
typedef SizeType size_type;
typedef ScalarType scalar_type;
typename list_property_definition_callback_type<size_type, scalar_type>::type& list_property_definition_callback = list_property_definition_callbacks_.get<size_type, scalar_type>();
typedef typename list_property_begin_callback_type<size_type, scalar_type>::type list_property_begin_callback_type;
typedef typename list_property_element_callback_type<size_type, scalar_type>::type list_property_element_callback_type;
typedef typename list_property_end_callback_type<size_type, scalar_type>::type list_property_end_callback_type;
std::tr1::tuple<list_property_begin_callback_type, list_property_element_callback_type, list_property_end_callback_type> list_property_callbacks;
if (list_property_definition_callback) {
list_property_callbacks = list_property_definition_callback(current_element_->name, property_name);
}
if (!std::tr1::get<0>(list_property_callbacks) || !std::tr1::get<1>(list_property_callbacks) || !std::tr1::get<2>(list_property_callbacks)) {
if (warning_callback_) {
warning_callback_(line_number_, "property list " + std::string(type_traits<size_type>::name()) + " " + std::string(type_traits<scalar_type>::name()) + " " + property_name + " of element " + current_element_->name + " is not handled");
}
}
current_element_->properties.push_back(std::tr1::shared_ptr<property>(new list_property<size_type, scalar_type>(property_name, std::tr1::get<0>(list_property_callbacks), std::tr1::get<1>(list_property_callbacks), std::tr1::get<2>(list_property_callbacks))));
}
template <typename ScalarType>
inline bool ply::ply_parser::parse_scalar_property(format_type format, std::istream& istream, const typename scalar_property_callback_type<ScalarType>::type& scalar_property_callback)
{
using namespace io_operators;
typedef ScalarType scalar_type;
if (format == ascii_format) {
scalar_type value = 0;
char space = ' ';
istream >> value;
if (!istream.eof()) {
istream >> space >> std::ws;
}
if (!istream || !std::isspace(space)) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
if (scalar_property_callback) {
scalar_property_callback(value);
}
return true;
}
else {
scalar_type value = 0;
istream.read(reinterpret_cast<char*>(&value), sizeof(scalar_type));
if (!istream) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
if ((format == binary_big_endian_format && host_byte_order == little_endian_byte_order)
|| (format == binary_little_endian_format && host_byte_order == big_endian_byte_order)) {
swap_byte_order(value);
}
if (scalar_property_callback) {
scalar_property_callback(value);
}
return true;
}
}
template <typename SizeType, typename ScalarType>
inline bool ply::ply_parser::parse_list_property(format_type format, std::istream& istream, const typename list_property_begin_callback_type<SizeType, ScalarType>::type& list_property_begin_callback, const typename list_property_element_callback_type<SizeType, ScalarType>::type& list_property_element_callback, const typename list_property_end_callback_type<SizeType, ScalarType>::type& list_property_end_callback)
{
using namespace io_operators;
typedef SizeType size_type;
typedef ScalarType scalar_type;
if (format == ascii_format) {
size_type size = 0;
char space = ' ';
istream >> size;
if (!istream.eof()) {
istream >> space >> std::ws;
}
if (!istream || !std::isspace(space)) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
if (list_property_begin_callback) {
list_property_begin_callback(size);
}
for (std::size_t index = 0; index < size; ++index) {
scalar_type value = 0;
char space = ' ';
istream >> value;
if (!istream.eof()) {
istream >> space >> std::ws;
}
if (!istream || !std::isspace(space)) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
if (list_property_element_callback) {
list_property_element_callback(value);
}
}
if (list_property_end_callback) {
list_property_end_callback();
}
return true;
}
else {
size_type size = 0;
istream.read(reinterpret_cast<char*>(&size), sizeof(size_type));
if ((format == binary_big_endian_format && host_byte_order == little_endian_byte_order)
|| ((format == binary_little_endian_format && host_byte_order == big_endian_byte_order))) {
swap_byte_order(size);
}
if (!istream) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
if (list_property_begin_callback) {
list_property_begin_callback(size);
}
for (std::size_t index = 0; index < size; ++index) {
scalar_type value;
istream.read(reinterpret_cast<char*>(&value), sizeof(scalar_type));
if (!istream) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
if ((format == binary_big_endian_format && host_byte_order == little_endian_byte_order)
|| (format == binary_little_endian_format && host_byte_order == big_endian_byte_order)) {
swap_byte_order(value);
}
if (list_property_element_callback) {
list_property_element_callback(value);
}
}
if (list_property_end_callback) {
list_property_end_callback();
}
return true;
}
}
#endif // PLY_PLY_PARSER_HPP_INCLUDED

View File

@ -0,0 +1,455 @@
#include <ply/ply_parser.hpp>
bool ply::ply_parser::parse(std::istream& istream)
{
std::string line;
line_number_ = 0;
std::size_t number_of_format_statements = 0, number_of_element_statements = 0, number_of_property_statements = 0, number_of_obj_info_statements = 0, number_of_comment_statements = 0;
format_type format = ascii_format;
std::vector< std::tr1::shared_ptr<element> > elements;
// magic
char magic[3];
istream.read(magic, 3);
istream.ignore(1);
++line_number_;
if (!istream) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
if ((magic[0] != 'p') || (magic[1] != 'l') || (magic[2] != 'y')){
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
if (magic_callback_) {
magic_callback_();
}
while (std::getline(istream, line)) {
++line_number_;
std::istringstream stringstream(line);
stringstream.unsetf(std::ios_base::skipws);
stringstream >> std::ws;
if (stringstream.eof()) {
if (warning_callback_) {
warning_callback_(line_number_, "ignoring line " + line + "");
}
}
else {
std::string keyword;
stringstream >> keyword;
// format
if (keyword == "format") {
std::string format_string, version;
char space_format_format_string, space_format_string_version;
stringstream >> space_format_format_string >> std::ws >> format_string >> space_format_string_version >> std::ws >> version >> std::ws;
if (!stringstream || !stringstream.eof() || !std::isspace(space_format_format_string) || !std::isspace(space_format_string_version)) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
if (format_string == "ascii") {
format = ascii_format;
}
else if (format_string == "binary_big_endian") {
format = binary_big_endian_format;
}
else if (format_string == "binary_little_endian") {
format = binary_little_endian_format;
}
else {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
if (version != "1.0") {
if (error_callback_) {
error_callback_(line_number_, "version " + version + " is not supported");
}
return false;
}
if (number_of_format_statements > 0) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
++number_of_format_statements;
if (format_callback_) {
format_callback_(format, version);
}
}
// element
else if (keyword == "element") {
std::string name;
std::size_t count;
char space_element_name, space_name_count;
stringstream >> space_element_name >> std::ws >> name >> space_name_count >> std::ws >> count >> std::ws;
if (!stringstream || !stringstream.eof() || !std::isspace(space_element_name) || !std::isspace(space_name_count)) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
std::vector< std::tr1::shared_ptr<element> >::const_iterator iterator;
for (iterator = elements.begin(); iterator != elements.end(); ++iterator) {
const struct element& element = *(iterator->get());
if (element.name == name) {
break;
}
}
if (iterator != elements.end()) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
++number_of_element_statements;
element_callbacks_type element_callbacks;
if (element_definition_callbacks_) {
element_callbacks = element_definition_callbacks_(name, count);
}
std::tr1::shared_ptr<element> element_ptr(new element(name, count, std::tr1::get<0>(element_callbacks), std::tr1::get<1>(element_callbacks)));
elements.push_back(std::tr1::shared_ptr<element>(element_ptr));
current_element_ = element_ptr.get();
}
// property
else if (keyword == "property") {
std::string type_or_list;
char space_property_type_or_list;
stringstream >> space_property_type_or_list >> std::ws >> type_or_list;
if (!stringstream || !std::isspace(space_property_type_or_list)) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
if (type_or_list != "list") {
std::string name;
std::string& type = type_or_list;
char space_type_name;
stringstream >> space_type_name >> std::ws >> name >> std::ws;
if (!stringstream || !std::isspace(space_type_name)) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
if (number_of_element_statements == 0) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
std::vector< std::tr1::shared_ptr<property> >::const_iterator iterator;
for (iterator = current_element_->properties.begin(); iterator != current_element_->properties.end(); ++iterator) {
const struct property& property = *(iterator->get());
if (property.name == name) {
break;
}
}
if (iterator != current_element_->properties.end()) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
if ((type == type_traits<int8>::name()) || (type == type_traits<int8>::old_name())) {
parse_scalar_property_definition<int8>(name);
}
else if ((type == type_traits<int16>::name()) || (type == type_traits<int16>::old_name())) {
parse_scalar_property_definition<int16>(name);
}
else if ((type == type_traits<int32>::name()) || (type == type_traits<int32>::old_name())) {
parse_scalar_property_definition<int32>(name);
}
else if ((type == type_traits<uint8>::name()) || (type == type_traits<uint8>::old_name())) {
parse_scalar_property_definition<uint8>(name);
}
else if ((type == type_traits<uint16>::name()) || (type == type_traits<uint16>::old_name())) {
parse_scalar_property_definition<uint16>(name);
}
else if ((type == type_traits<uint32>::name()) || (type == type_traits<uint32>::old_name())) {
parse_scalar_property_definition<uint32>(name);
}
else if ((type == type_traits<float32>::name()) || (type == type_traits<float32>::old_name())) {
parse_scalar_property_definition<float32>(name);
}
else if ((type == type_traits<float64>::name()) || (type == type_traits<float64>::old_name())) {
parse_scalar_property_definition<float64>(name);
}
else {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
++number_of_property_statements;
}
else {
std::string name;
std::string size_type_string, scalar_type_string;
char space_list_size_type, space_size_type_scalar_type, space_scalar_type_name;
stringstream >> space_list_size_type >> std::ws >> size_type_string >> space_size_type_scalar_type >> std::ws >> scalar_type_string >> space_scalar_type_name >> std::ws >> name >> std::ws;
if (!stringstream || !std::isspace(space_list_size_type) || !std::isspace(space_size_type_scalar_type) || !std::isspace(space_scalar_type_name)) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
if (number_of_element_statements == 0) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
std::vector< std::tr1::shared_ptr<property> >::const_iterator iterator;
for (iterator = current_element_->properties.begin(); iterator != current_element_->properties.end(); ++iterator) {
const struct property& property = *(iterator->get());
if (property.name == name) {
break;
}
}
if (iterator != current_element_->properties.end()) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
if ((size_type_string == type_traits<uint8>::name()) || (size_type_string == type_traits<uint8>::old_name())) {
typedef uint8 size_type;
if ((scalar_type_string == type_traits<int8>::name()) || (scalar_type_string == type_traits<int8>::old_name())) {
parse_list_property_definition<size_type, int8>(name);
}
else if ((scalar_type_string == type_traits<int16>::name()) || (scalar_type_string == type_traits<int16>::old_name())) {
parse_list_property_definition<size_type, int16>(name);
}
else if ((scalar_type_string == type_traits<int32>::name()) || (scalar_type_string == type_traits<int32>::old_name())) {
parse_list_property_definition<size_type, int32>(name);
}
else if ((scalar_type_string == type_traits<uint8>::name()) || (scalar_type_string == type_traits<uint8>::old_name())) {
parse_list_property_definition<size_type, uint8>(name);
}
else if ((scalar_type_string == type_traits<uint16>::name()) || (scalar_type_string == type_traits<uint16>::old_name())) {
parse_list_property_definition<size_type, uint16>(name);
}
else if ((scalar_type_string == type_traits<uint32>::name()) || (scalar_type_string == type_traits<uint32>::old_name())) {
parse_list_property_definition<size_type, uint32>(name);
}
else if ((scalar_type_string == type_traits<float32>::name()) || (scalar_type_string == type_traits<float32>::old_name())) {
parse_list_property_definition<size_type, float32>(name);
}
else if ((scalar_type_string == type_traits<float64>::name()) || (scalar_type_string == type_traits<float64>::old_name())) {
parse_list_property_definition<size_type, float64>(name);
}
else {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
}
else if ((size_type_string == type_traits<uint16>::name()) || (size_type_string == type_traits<uint16>::old_name())) {
typedef uint16 size_type;
if ((scalar_type_string == type_traits<int8>::name()) || (scalar_type_string == type_traits<int8>::old_name())) {
parse_list_property_definition<size_type, int8>(name);
}
else if ((scalar_type_string == type_traits<int16>::name()) || (scalar_type_string == type_traits<int16>::old_name())) {
parse_list_property_definition<size_type, int16>(name);
}
else if ((scalar_type_string == type_traits<int32>::name()) || (scalar_type_string == type_traits<int32>::old_name())) {
parse_list_property_definition<size_type, int32>(name);
}
else if ((scalar_type_string == type_traits<uint8>::name()) || (scalar_type_string == type_traits<uint8>::old_name())) {
parse_list_property_definition<size_type, uint8>(name);
}
else if ((scalar_type_string == type_traits<uint16>::name()) || (scalar_type_string == type_traits<uint16>::old_name())) {
parse_list_property_definition<size_type, uint16>(name);
}
else if ((scalar_type_string == type_traits<uint32>::name()) || (scalar_type_string == type_traits<uint32>::old_name())) {
parse_list_property_definition<size_type, uint32>(name);
}
else if ((scalar_type_string == type_traits<float32>::name()) || (scalar_type_string == type_traits<float32>::old_name())) {
parse_list_property_definition<size_type, float32>(name);
}
else if ((scalar_type_string == type_traits<float64>::name()) || (scalar_type_string == type_traits<float64>::old_name())) {
parse_list_property_definition<size_type, float64>(name);
}
else {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
}
else if ((size_type_string == type_traits<uint32>::name()) || (size_type_string == type_traits<uint32>::old_name())) {
typedef uint32 size_type;
if ((scalar_type_string == type_traits<int8>::name()) || (scalar_type_string == type_traits<int8>::old_name())) {
parse_list_property_definition<size_type, int8>(name);
}
else if ((scalar_type_string == type_traits<int16>::name()) || (scalar_type_string == type_traits<int16>::old_name())) {
parse_list_property_definition<size_type, int16>(name);
}
else if ((scalar_type_string == type_traits<int32>::name()) || (scalar_type_string == type_traits<int32>::old_name())) {
parse_list_property_definition<size_type, int32>(name);
}
else if ((scalar_type_string == type_traits<uint8>::name()) || (scalar_type_string == type_traits<uint8>::old_name())) {
parse_list_property_definition<size_type, uint8>(name);
}
else if ((scalar_type_string == type_traits<uint16>::name()) || (scalar_type_string == type_traits<uint16>::old_name())) {
parse_list_property_definition<size_type, uint16>(name);
}
else if ((scalar_type_string == type_traits<uint32>::name()) || (scalar_type_string == type_traits<uint32>::old_name())) {
parse_list_property_definition<size_type, uint32>(name);
}
else if ((scalar_type_string == type_traits<float32>::name()) || (scalar_type_string == type_traits<float32>::old_name())) {
parse_list_property_definition<size_type, float32>(name);
}
else if ((scalar_type_string == type_traits<float64>::name()) || (scalar_type_string == type_traits<float64>::old_name())) {
parse_list_property_definition<size_type, float64>(name);
}
else {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
}
else {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
++number_of_property_statements;
}
}
// comment
else if (keyword == "comment") {
if (comment_callback_) {
comment_callback_(line);
}
++number_of_comment_statements;
}
// obj_info
else if (keyword == "obj_info") {
if (obj_info_callback_) {
obj_info_callback_(line);
}
++number_of_obj_info_statements;
}
// end_header
else if (keyword == "end_header") {
if (end_header_callback_) {
if (end_header_callback_() == false) {
return true;
}
}
break;
}
// unknown keyword
else {
if (warning_callback_) {
warning_callback_(line_number_, "ignoring line " + line + "");
}
}
}
}
if (number_of_format_statements == 0) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
// ascii
if (format == ascii_format) {
for (std::vector< std::tr1::shared_ptr<element> >::const_iterator element_iterator = elements.begin(); element_iterator != elements.end(); ++element_iterator) {
class element& element = *(element_iterator->get());
for (std::size_t element_index = 0; element_index < element.count; ++element_index) {
if (element.begin_element_callback) {
element.begin_element_callback();
}
if (!std::getline(istream, line)) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
++line_number_;
std::istringstream stringstream(line);
stringstream.unsetf(std::ios_base::skipws);
stringstream >> std::ws;
for (std::vector< std::tr1::shared_ptr<property> >::const_iterator property_iterator = element.properties.begin(); property_iterator != element.properties.end(); ++property_iterator) {
class property& property = *(property_iterator->get());
if (property.parse(*this, format, stringstream) == false) {
return false;
}
}
if (!stringstream.eof()) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
if (element.end_element_callback) {
element.end_element_callback();
}
}
}
istream >> std::ws;
if (istream.fail() || !istream.eof() || istream.bad()) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
return true;
}
// binary
else {
for (std::vector< std::tr1::shared_ptr<element> >::const_iterator element_iterator = elements.begin(); element_iterator != elements.end(); ++element_iterator) {
class element& element = *(element_iterator->get());
for (std::size_t element_index = 0; element_index < element.count; ++element_index) {
if (element.begin_element_callback) {
element.begin_element_callback();
}
for (std::vector< std::tr1::shared_ptr<property> >::const_iterator property_iterator = element.properties.begin(); property_iterator != element.properties.end(); ++property_iterator) {
class property& property = *(property_iterator->get());
if (property.parse(*this, format, istream) == false) {
return false;
}
}
if (element.end_element_callback) {
element.end_element_callback();
}
}
}
if (istream.fail() || (istream.rdbuf()->sgetc() != std::char_traits<char>::eof()) || istream.bad()) {
if (error_callback_) {
error_callback_(line_number_, "parse error");
}
return false;
}
return true;
}
}

View File

@ -0,0 +1,102 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include <mitsuba/render/texture.h>
#include <mitsuba/render/shape.h>
#include <mitsuba/core/properties.h>
MTS_NAMESPACE_BEGIN
/**
* Vertex colors passthrough texture
*/
class VertexColors : public Texture {
public:
VertexColors(const Properties &props) : Texture(props) {
}
VertexColors(Stream *stream, InstanceManager *manager)
: Texture(stream, manager) {
}
void serialize(Stream *stream, InstanceManager *manager) const {
}
Spectrum getValue(const Intersection &its) const {
#if defined(MTS_HAS_VERTEX_COLORS)
return its.color;
#else
Log(EError, "Vertex colors are not active -- recompile Mitsuba "
"with -DMTS_HAS_VERTEX_COLORS");
return Spectrum(0.0f);
#endif
}
bool usesRayDifferentials() const {
return false;
}
Spectrum getAverage() const {
return Spectrum(1.0f);
}
Spectrum getMaximum() const {
return Spectrum(1.0f);
}
std::string toString() const {
return "VertexColors[]";
}
Shader *createShader(Renderer *renderer) const;
MTS_DECLARE_CLASS()
protected:
Spectrum m_reflectance;
};
// ================ Hardware shader implementation ================
class VertexColorShader : public Shader {
public:
VertexColorShader(Renderer *renderer) : Shader(renderer, ETextureShader) {
}
void generateCode(std::ostringstream &oss,
const std::string &evalName,
const std::vector<std::string> &depNames) const {
oss << "vec3 " << evalName << "(vec2 uv) {" << endl
<< " return vertexColor;" << endl
<< "}" << endl;
}
MTS_DECLARE_CLASS()
private:
Spectrum m_brightReflectance;
Spectrum m_darkReflectance;
Float m_width;
};
Shader *VertexColors::createShader(Renderer *renderer) const {
return new VertexColorShader(renderer);
}
MTS_IMPLEMENT_CLASS(VertexColorShader, false, Shader)
MTS_IMPLEMENT_CLASS_S(VertexColors, false, Texture)
MTS_EXPORT_PLUGIN(VertexColors, "VertexColors texture");
MTS_NAMESPACE_END