Permalink
Browse files

Add support for faceIndices in PLY files

  • Loading branch information...
mmp committed Dec 25, 2017
1 parent 1b319b5 commit 6870bc7750b0f32c0e3ffa569eae2e8e0f8c268d
Showing with 115 additions and 84 deletions.
  1. +5 −1 src/core/api.cpp
  2. +60 −38 src/shapes/plymesh.cpp
  3. +48 −44 src/shapes/triangle.cpp
  4. +2 −1 src/shapes/triangle.h
View
@@ -371,8 +371,12 @@ std::vector<std::shared_ptr<Shape>> MakeShapes(const std::string &name,
}
const Normal3f *N = paramSet.FindNormal3f("N", &nni);
const Vector3f *S = paramSet.FindVector3f("S", &nsi);
int nfi;
const int *faceIndices = paramSet.FindInt("faceIndices", &nfi);
if (faceIndices) CHECK_EQ(nfi, nvi / 3);
if (!WritePlyFile(fn.c_str(), nvi / 3, vi, npi, P, S, N, uvs))
if (!WritePlyFile(fn.c_str(), nvi / 3, vi, npi, P, S, N, uvs,
faceIndices))
Error("Unable to write PLY file \"%s\"", fn.c_str());
printf("%*sShape \"plymesh\" \"string filename\" \"%s\" ",
View
@@ -47,7 +47,8 @@ struct CallbackContext {
Normal3f *n;
Point2f *uv;
int *indices;
int indexCtr;
int *faceIndices;
int indexCtr, faceIndexCtr;
int face[4];
bool error;
int vertexCount;
@@ -57,7 +58,9 @@ struct CallbackContext {
n(nullptr),
uv(nullptr),
indices(nullptr),
faceIndices(nullptr),
indexCtr(0),
faceIndexCtr(0),
error(false),
vertexCount(0) {}
@@ -66,6 +69,7 @@ struct CallbackContext {
delete[] n;
delete[] uv;
delete[] indices;
delete[] faceIndices;
}
};
@@ -95,45 +99,58 @@ int rply_vertex_callback(p_ply_argument argument) {
/* Callback to handle face data from RPly */
int rply_face_callback(p_ply_argument argument) {
long length, value_index;
ply_get_argument_property(argument, nullptr, &length, &value_index);
if (length != 3 && length != 4) {
Warning(
"plymesh: Ignoring face with %i vertices (only triangles and quads "
"are supported!)",
(int)length);
return 1;
} else if (value_index < 0) {
return 1;
}
CallbackContext *context;
ply_get_argument_user_data(argument, (void **)&context, nullptr);
if (value_index >= 0) {
int value = (int)ply_get_argument_value(argument);
if (value < 0 || value >= context->vertexCount) {
Error(
"plymesh: Vertex reference %i is out of bounds! "
"Valid range is [0..%i)",
value, context->vertexCount);
context->error = true;
long flags;
ply_get_argument_user_data(argument, (void **)&context, &flags);
if (flags == 0) {
// Vertex indices
long length, value_index;
ply_get_argument_property(argument, nullptr, &length, &value_index);
if (length != 3 && length != 4) {
Warning("plymesh: Ignoring face with %i vertices (only triangles and quads "
"are supported!)",
(int)length);
return 1;
} else if (value_index < 0) {
return 1;
}
if (length == 4)
CHECK(context->faceIndices == nullptr) <<
"face_indices not yet supported for quads";
if (value_index >= 0) {
int value = (int)ply_get_argument_value(argument);
if (value < 0 || value >= context->vertexCount) {
Error(
"plymesh: Vertex reference %i is out of bounds! "
"Valid range is [0..%i)",
value, context->vertexCount);
context->error = true;
}
context->face[value_index] = value;
}
context->face[value_index] = value;
}
if (value_index == length - 1) {
for (int i = 0; i < 3; ++i)
context->indices[context->indexCtr++] = context->face[i];
if (value_index == length - 1) {
for (int i = 0; i < 3; ++i)
context->indices[context->indexCtr++] = context->face[i];
if (length == 4) {
/* This was a quad */
context->indices[context->indexCtr++] = context->face[3];
context->indices[context->indexCtr++] = context->face[0];
context->indices[context->indexCtr++] = context->face[2];
if (length == 4) {
/* This was a quad */
context->indices[context->indexCtr++] = context->face[3];
context->indices[context->indexCtr++] = context->face[0];
context->indices[context->indexCtr++] = context->face[2];
}
}
} else {
CHECK_EQ(1, flags);
// Face indices
context->faceIndices[context->faceIndexCtr++] =
(int)ply_get_argument_value(argument);
}
return 1;
}
@@ -169,7 +186,7 @@ std::vector<std::shared_ptr<Shape>> CreatePLYMesh(
}
if (vertexCount == 0 || faceCount == 0) {
Error("PLY file \"%s\" is invalid! No face/vertex elements found!",
Error("%s: PLY file is invalid! No face/vertex elements found!",
filename.c_str());
return std::vector<std::shared_ptr<Shape>>();
}
@@ -184,7 +201,7 @@ std::vector<std::shared_ptr<Shape>> CreatePLYMesh(
0x032)) {
context.p = new Point3f[vertexCount];
} else {
Error("PLY file \"%s\": Vertex coordinate property not found!",
Error("%s: Vertex coordinate property not found!",
filename.c_str());
return std::vector<std::shared_ptr<Shape>>();
}
@@ -223,9 +240,13 @@ std::vector<std::shared_ptr<Shape>> CreatePLYMesh(
ply_set_read_cb(ply, "face", "vertex_indices", rply_face_callback, &context,
0);
if (ply_set_read_cb(ply, "face", "face_indices", rply_face_callback, &context,
1))
// Extra space in case they're quads
context.faceIndices = new int[faceCount];
if (!ply_read(ply)) {
Error("Unable to read the contents of PLY file \"%s\"",
Error("%s: unable to read the contents of PLY file",
filename.c_str());
ply_close(ply);
return std::vector<std::shared_ptr<Shape>>();
@@ -264,7 +285,8 @@ std::vector<std::shared_ptr<Shape>> CreatePLYMesh(
return CreateTriangleMesh(o2w, w2o, reverseOrientation,
context.indexCtr / 3, context.indices,
vertexCount, context.p, nullptr, context.n,
context.uv, alphaTex, shadowAlphaTex);
context.uv, alphaTex, shadowAlphaTex,
context.faceIndices);
}
} // namespace pbrt
View
@@ -111,56 +111,60 @@ std::vector<std::shared_ptr<Shape>> CreateTriangleMesh(
bool WritePlyFile(const std::string &filename, int nTriangles,
const int *vertexIndices, int nVertices, const Point3f *P,
const Vector3f *S, const Normal3f *N, const Point2f *UV) {
const Vector3f *S, const Normal3f *N, const Point2f *UV,
const int *faceIndices) {
p_ply plyFile =
ply_create(filename.c_str(), PLY_DEFAULT, PlyErrorCallback, 0, nullptr);
if (plyFile != nullptr) {
ply_add_element(plyFile, "vertex", nVertices);
ply_add_scalar_property(plyFile, "x", PLY_FLOAT);
ply_add_scalar_property(plyFile, "y", PLY_FLOAT);
ply_add_scalar_property(plyFile, "z", PLY_FLOAT);
if (N != nullptr) {
ply_add_scalar_property(plyFile, "nx", PLY_FLOAT);
ply_add_scalar_property(plyFile, "ny", PLY_FLOAT);
ply_add_scalar_property(plyFile, "nz", PLY_FLOAT);
}
if (UV != nullptr) {
ply_add_scalar_property(plyFile, "u", PLY_FLOAT);
ply_add_scalar_property(plyFile, "v", PLY_FLOAT);
if (plyFile == nullptr)
return false;
ply_add_element(plyFile, "vertex", nVertices);
ply_add_scalar_property(plyFile, "x", PLY_FLOAT);
ply_add_scalar_property(plyFile, "y", PLY_FLOAT);
ply_add_scalar_property(plyFile, "z", PLY_FLOAT);
if (N) {
ply_add_scalar_property(plyFile, "nx", PLY_FLOAT);
ply_add_scalar_property(plyFile, "ny", PLY_FLOAT);
ply_add_scalar_property(plyFile, "nz", PLY_FLOAT);
}
if (UV) {
ply_add_scalar_property(plyFile, "u", PLY_FLOAT);
ply_add_scalar_property(plyFile, "v", PLY_FLOAT);
}
if (S)
Warning("%s: PLY mesh will be missing tangent vectors \"S\".",
filename.c_str());
ply_add_element(plyFile, "face", nTriangles);
ply_add_list_property(plyFile, "vertex_indices", PLY_UINT8, PLY_INT);
ply_add_scalar_property(plyFile, "face_indices", PLY_INT);
ply_write_header(plyFile);
for (int i = 0; i < nVertices; ++i) {
ply_write(plyFile, P[i].x);
ply_write(plyFile, P[i].y);
ply_write(plyFile, P[i].z);
if (N) {
ply_write(plyFile, N[i].x);
ply_write(plyFile, N[i].y);
ply_write(plyFile, N[i].z);
}
if (S != nullptr)
Warning("PLY mesh in \"%s\" will be missing tangent vectors \"S\".",
filename.c_str());
ply_add_element(plyFile, "face", nTriangles);
ply_add_list_property(plyFile, "vertex_indices", PLY_UINT8, PLY_INT);
ply_write_header(plyFile);
for (int i = 0; i < nVertices; ++i) {
ply_write(plyFile, P[i].x);
ply_write(plyFile, P[i].y);
ply_write(plyFile, P[i].z);
if (N) {
ply_write(plyFile, N[i].x);
ply_write(plyFile, N[i].y);
ply_write(plyFile, N[i].z);
}
if (UV) {
ply_write(plyFile, UV[i].x);
ply_write(plyFile, UV[i].y);
}
if (UV) {
ply_write(plyFile, UV[i].x);
ply_write(plyFile, UV[i].y);
}
}
for (int i = 0; i < nTriangles; ++i) {
ply_write(plyFile, 3);
ply_write(plyFile, vertexIndices[3 * i]);
ply_write(plyFile, vertexIndices[3 * i + 1]);
ply_write(plyFile, vertexIndices[3 * i + 2]);
}
ply_close(plyFile);
return true;
for (int i = 0; i < nTriangles; ++i) {
ply_write(plyFile, 3);
ply_write(plyFile, vertexIndices[3 * i]);
ply_write(plyFile, vertexIndices[3 * i + 1]);
ply_write(plyFile, vertexIndices[3 * i + 2]);
if (faceIndices)
ply_write(plyFile, faceIndices[i]);
}
return false;
ply_close(plyFile);
return true;
}
Bounds3f Triangle::ObjectBound() const {
View
@@ -128,7 +128,8 @@ std::vector<std::shared_ptr<Shape>> CreateTriangleMeshShape(
bool WritePlyFile(const std::string &filename, int nTriangles,
const int *vertexIndices, int nVertices, const Point3f *P,
const Vector3f *S, const Normal3f *N, const Point2f *UV);
const Vector3f *S, const Normal3f *N, const Point2f *UV,
const int *faceIndices);
} // namespace pbrt

0 comments on commit 6870bc7

Please sign in to comment.