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
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/sphere', ['src/shapes/sphere.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/gridtexture', ['src/textures/gridtexture.cpp'])
plugins += env.SharedLibrary('plugins/checkerboard', ['src/textures/checkerboard.cpp'])
plugins += env.SharedLibrary('plugins/vertexcolors', ['src/textures/vertexcolors.cpp'])
# Light sources
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 libjpeg by the Independent JPEG Group
\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 POSIX Threads for Win32 by Ross Johnson
\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
\texttt{MTS\_SSE}, \texttt{MTS\_HAS\_COHERENT\_RT}, and \texttt{MTS\_DEBUG\_FP}.
\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\_DEBUG\_FP}]Generated NaNs will cause floating point exceptions, which can be caught in a debugger. Warning: This is slow!
\end{description}

View File

@ -34,10 +34,21 @@ struct Vertex {
Point2 uv; ///< %Texture coordinates
Vector dpdu; ///< Partial derivative of the position with respect to \a u.
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 {
#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
&& dpdu == vert.dpdu && dpdv == vert.dpdv);
#endif
}
inline bool operator!=(const Vertex &vert) const {

View File

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

View File

@ -41,7 +41,14 @@ void GLGeometry::init() {
}
void GLGeometry::refresh() {
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;
Log(EDebug, "Uploading a GPU geometry object (\"%s\", " SIZE_T_FMT
@ -51,7 +58,7 @@ void GLGeometry::refresh() {
m_mesh->getTriangleCount(),
(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();
const Vertex *source = m_mesh->getVertexBuffer();
int pos = 0;
@ -68,6 +75,11 @@ void GLGeometry::refresh() {
vertices[pos++] = (float) vtx.dpdu.x;
vertices[pos++] = (float) vtx.dpdu.y;
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();

View File

@ -220,10 +220,17 @@ void GLRenderer::beginDrawingMeshes(bool transmitOnlyPositions) {
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE1);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
#if defined(MTS_HAS_VERTEX_COLORS)
glEnableClientState(GL_COLOR_ARRAY);
#endif
}
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;
#endif
glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV);
glEnableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV);
glVertexFormatNV(3, GL_FLOAT, stride);
@ -233,6 +240,7 @@ void GLRenderer::beginDrawingMeshes(bool transmitOnlyPositions) {
glTexCoordFormatNV(2, GL_FLOAT, stride);
glClientActiveTexture(GL_TEXTURE1);
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));
glBufferAddressRangeNV(GL_TEXTURE_COORD_ARRAY_ADDRESS_NV, 1, geometry->m_vertexAddr+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,
geometry->m_indexAddr, geometry->m_indexSize);
} else {
#if defined(MTS_HAS_VERTEX_COLORS)
const int stride = sizeof(GLfloat) * 14;
#else
const int stride = sizeof(GLfloat) * 11;
#endif
glBindBuffer(GL_ARRAY_BUFFER, geometry->m_vertexID);
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 */
glClientActiveTexture(GL_TEXTURE1);
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 */
glDrawElements(GL_TRIANGLES, (GLsizei) (mesh->getTriangleCount() * 3),
GL_UNSIGNED_INT, (GLvoid *) 0);
if (!m_capabilities->isSupported(RendererCapabilities::EBindless)) {
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
} else {
/* Draw the old-fashioned way without VBOs */
const GLchar *vertices = (const GLchar *) mesh->getVertexBuffer();
@ -290,7 +315,12 @@ void GLRenderer::drawTriMesh(const TriMesh *mesh) {
if (!m_transmitOnlyPositions) {
glNormalPointer(dataType, sizeof(Vertex),
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),
vertices + sizeof(Float) * 6);
@ -309,13 +339,16 @@ void GLRenderer::drawTriMesh(const TriMesh *mesh) {
void GLRenderer::endDrawingMeshes() {
glDisableClientState(GL_VERTEX_ARRAY);
if (!m_transmitOnlyPositions) {
#if defined(MTS_HAS_VERTEX_COLORS)
glDisableClientState(GL_COLOR_ARRAY);
#endif
glDisableClientState(GL_NORMAL_ARRAY);
glClientActiveTexture(GL_TEXTURE1);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
if (m_capabilities->isSupported(RendererCapabilities::EBindless)) {
glDisableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV);
glDisableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV);
@ -326,6 +359,8 @@ void GLRenderer::endDrawingMeshes() {
}
void GLRenderer::drawAll() {
if (true)
return;
GLRenderer::beginDrawingMeshes(true);
std::map<const TriMesh *, GPUGeometry *>::iterator it;
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
<< "varying vec3 normal, tangent, lightVec, camVec;" << endl
<< "varying vec2 uv;" << endl
#if defined(MTS_HAS_VERTEX_COLORS)
<< "varying vec3 vertexColor;" << endl
#endif
<< endl
<< "void main() {" << 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
<< " lightVec = vplPos - gl_Vertex.xyz;" << endl
<< " gl_Position = ftransform();" << endl
#if defined(MTS_HAS_VERTEX_COLORS)
<< " vertexColor = gl_Color.rgb;" << endl
#endif
<< "}" << endl;
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 vec2 vplUV;" << endl
<< "uniform bool diffuseSources, diffuseReceivers;" << endl
#if defined(MTS_HAS_VERTEX_COLORS)
<< "varying vec3 vertexColor;" << endl
#endif
<< endl
<< "/* Inputs <- Vertex program */" << endl
<< "varying vec3 normal, tangent, lightVec, camVec;" << endl

View File

@ -178,14 +178,21 @@ void KDTree::rayIntersectPacket(const Ray *rays, Intersection *its) const {
it.dpdu = v0.dpdu * b.x + v1.dpdu * b.y + v2.dpdu * 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.s = normalize(it.dpdu - it.shFrame.n
* dot(it.shFrame.n, it.dpdu));
it.geoFrame.t = cross(it.shFrame.n, it.shFrame.s);
it.wi = it.toLocal(-rayD);
it.hasUVPartials = false;
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 {
/* Non-triangle shape: intersect again to fill in details */
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.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.geoFrame.n = faceNormal;
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.wi = its.toLocal(-ray.d);
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 {
/* Non-triangle shape: intersect again to fill in details */
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.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)) {
its.dpdu = v0.dpdu * alpha + v1.dpdu * beta + v2.dpdu * gamma;
its.dpdv = v0.dpdv * alpha + v1.dpdv * beta + v2.dpdv * gamma;

View File

@ -144,8 +144,10 @@ void TriMesh::configure() {
return;
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_surfaceArea = m_areaPDF.build();
m_invSurfaceArea = 1.0f / m_surfaceArea;
/* 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) {
/* Calculate smooth normals if there aren't any */
int zeroArea = 0, zeroNormals = 0;
int zeroArea = 0, zeroNormals = 0, invalidNormals = 0;
if (!hasNormals) {
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;
} else {
/* Choose some bogus value */
if (complain)
Log(EWarn, "Could not generate correct mesh normals!");
invalidNormals++;
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) {
for (unsigned int i=0; i<m_vertexCount; i++)
m_vertexBuffer[i].n *= -1;
@ -314,8 +319,8 @@ void TriMesh::calculateTangentSpaceBasis(bool hasNormals, bool hasTexCoords, boo
}
if (complain && (zeroArea > 0 || zeroNormals > 0))
Log(EWarn, "Mesh contains invalid geometry: %i zero area triangles "
"and %i zero normals found!", zeroArea, zeroNormals);
Log(EWarn, "\"%s\": mesh contains invalid geometry: %i zero area triangles "
"and %i zero normals found!", m_name.c_str(), zeroArea, zeroNormals);
}
void TriMesh::serialize(Stream *stream, InstanceManager *manager) const {

View File

@ -50,6 +50,10 @@ AboutDialog::AboutDialog(QWidget *parent) :
configFlags += "MTS_HAS_COHERENT_RT ";
#endif
#if defined(MTS_HAS_VERTEX_COLORS)
configFlags += "MTS_HAS_VERTEX_COLORS ";
#endif
#if defined(MTS_HAS_COLLADA)
configFlags += "MTS_HAS_COLLADA ";
#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://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://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.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;

View File

@ -309,7 +309,7 @@ public:
if (currentMaterial)
mesh->addChild("", currentMaterial);
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(),
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