00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "plymesh.h"
00024 #include "paramset.h"
00025 #include "dynload.h"
00026
00027 #include "mesh.h"
00028 #include "./plymesh/rply.h"
00029
00030 namespace lux
00031 {
00032
00033
00034 static int VertexCB(p_ply_argument argument)
00035 {
00036 long userIndex = 0;
00037 void *userData = NULL;
00038 ply_get_argument_user_data(argument, &userData, &userIndex);
00039
00040 Point* p = *static_cast<Point **>(userData);
00041
00042 long vertIndex;
00043 ply_get_argument_element(argument, NULL, &vertIndex);
00044
00045 if (userIndex == 0)
00046 p[vertIndex].x =
00047 static_cast<float>(ply_get_argument_value(argument));
00048 else if (userIndex == 1)
00049 p[vertIndex].y =
00050 static_cast<float>(ply_get_argument_value(argument));
00051 else if (userIndex == 2)
00052 p[vertIndex].z =
00053 static_cast<float>(ply_get_argument_value(argument));
00054
00055
00056
00057 return 1;
00058 }
00059
00060
00061 static int NormalCB(p_ply_argument argument)
00062 {
00063 long userIndex = 0;
00064 void *userData = NULL;
00065 ply_get_argument_user_data(argument, &userData, &userIndex);
00066
00067 Normal* n = *static_cast<Normal **>(userData);
00068
00069 long vertIndex;
00070 ply_get_argument_element(argument, NULL, &vertIndex);
00071
00072 if (userIndex == 0)
00073 n[vertIndex].x =
00074 static_cast<float>(ply_get_argument_value(argument));
00075 else if (userIndex == 1)
00076 n[vertIndex].y =
00077 static_cast<float>(ply_get_argument_value(argument));
00078 else if (userIndex == 2)
00079 n[vertIndex].z =
00080 static_cast<float>(ply_get_argument_value(argument));
00081
00082
00083
00084 return 1;
00085 }
00086
00087
00088 static int FaceCB(p_ply_argument argument)
00089 {
00090 void *userData = NULL;
00091 ply_get_argument_user_data(argument, &userData, NULL);
00092
00093 int *verts = *static_cast<int **>(userData);
00094
00095 long triIndex;
00096 ply_get_argument_element(argument, NULL, &triIndex);
00097
00098 long length, valueIndex;
00099 ply_get_argument_property(argument, NULL, &length, &valueIndex);
00100
00101 if (valueIndex >= 0 && valueIndex < 3) {
00102 verts[triIndex * 3 + valueIndex] =
00103 static_cast<int>(ply_get_argument_value(argument));
00104 }
00105
00106
00107 return 1;
00108 }
00109
00110 Shape* PlyMesh::CreateShape(const Transform &o2w,
00111 bool reverseOrientation, const ParamSet ¶ms) {
00112 string filename = params.FindOneString("filename", "none");
00113 bool smooth = params.FindOneBool("smooth", false);
00114
00115 std::stringstream ss;
00116 ss << "Loading PLY mesh file: '" << filename << "'...";
00117 luxError(LUX_NOERROR, LUX_INFO, ss.str().c_str());
00118
00119 p_ply plyfile = ply_open(filename.c_str(), NULL);
00120 if (!plyfile) {
00121 ss.str("");
00122 ss << "Unable to read PLY mesh file '" << filename << "'";
00123 luxError(LUX_SYSTEM, LUX_ERROR, ss.str().c_str());
00124 return NULL;
00125 }
00126
00127 if (!ply_read_header(plyfile)) {
00128 ss.str("");
00129 ss << "Unable to read PLY header from '" << filename << "'";
00130 luxError(LUX_BADFILE, LUX_ERROR, ss.str().c_str());
00131 return NULL;
00132 }
00133
00134 Point *p;
00135 long plyNbVerts = ply_set_read_cb(plyfile, "vertex", "x",
00136 VertexCB, &p, 0);
00137 ply_set_read_cb(plyfile, "vertex", "y", VertexCB, &p, 1);
00138 ply_set_read_cb(plyfile, "vertex", "z", VertexCB, &p, 2);
00139 if (plyNbVerts <= 0) {
00140 ss.str("");
00141 ss << "No vertices found in '" << filename << "'";
00142 luxError(LUX_BADFILE, LUX_ERROR, ss.str().c_str());
00143 return NULL;
00144 }
00145
00146 int *vertexIndex;
00147 long plyNbTris = ply_set_read_cb(plyfile, "face", "vertex_indices",
00148 FaceCB, &vertexIndex, 0);
00149 if (plyNbTris <= 0) {
00150 ss.str("");
00151 ss << "No triangles found in '" << filename << "'";
00152 luxError(LUX_BADFILE, LUX_ERROR, ss.str().c_str());
00153 return NULL;
00154 }
00155
00156 Normal *n;
00157 long plyNbNormals = ply_set_read_cb(plyfile, "vertex", "nx",
00158 NormalCB, &n, 0);
00159 ply_set_read_cb(plyfile, "vertex", "ny", NormalCB, &n, 1);
00160 ply_set_read_cb(plyfile, "vertex", "nz", NormalCB, &n, 2);
00161
00162 p = new Point[plyNbVerts];
00163 vertexIndex = new int[3 * plyNbTris];
00164 if (plyNbNormals <= 0)
00165 n = NULL;
00166 else
00167 n = new Normal[plyNbNormals];
00168
00169 if (!ply_read(plyfile)) {
00170 ss.str("");
00171 ss << "Unable to parse PLY file '" << filename << "'";
00172 luxError(LUX_SYSTEM, LUX_ERROR, ss.str().c_str());
00173 delete[] p;
00174 delete[] vertexIndex;
00175 delete[] n;
00176 return NULL;
00177 }
00178
00179 ply_close(plyfile);
00180
00181 if (smooth || plyNbVerts != plyNbNormals) {
00182 if (n) {
00183 ss.str("");
00184 ss << "Overriding plymesh normals";
00185 luxError(LUX_NOERROR, LUX_WARNING, ss.str().c_str());
00186 delete[] n;
00187 }
00188
00189 n = new Normal[plyNbVerts];
00190 int *nf = new int[plyNbVerts];
00191 for (int i = 0; i < plyNbVerts; ++i) {
00192 n[i] = Normal(0.f, 0.f, 0.f);
00193 nf[i] = 0.f;
00194 }
00195
00196 for (int tri = 0; tri < plyNbTris; ++tri) {
00197
00198 const Vector e10(p[vertexIndex[3 * tri + 1]] -
00199 p[vertexIndex[3 * tri]]);
00200 const Vector e12(p[vertexIndex[3 * tri + 1]] -
00201 p[vertexIndex[3 * tri + 2]]);
00202
00203 Normal fn(Normalize(Cross(e12, e10)));
00204
00205
00206 n[vertexIndex[3 * tri]] += fn;
00207 n[vertexIndex[3 * tri + 1]] += fn;
00208 n[vertexIndex[3 * tri + 2]] += fn;
00209
00210
00211 nf[vertexIndex[3 * tri]]++;
00212 nf[vertexIndex[3 * tri + 1]]++;
00213 nf[vertexIndex[3 * tri + 2]]++;
00214 }
00215
00216
00217 for (int i = 0; i < plyNbVerts; ++i)
00218 n[i] /= nf[i];
00219
00220 delete[] nf;
00221 }
00222
00223 Mesh *mesh = new Mesh(o2w, reverseOrientation, Mesh::ACCEL_AUTO,
00224 plyNbVerts, p, n, NULL, Mesh::TRI_AUTO, plyNbTris, vertexIndex,
00225 Mesh::QUAD_QUADRILATERAL, 0, NULL, Mesh::SUBDIV_LOOP, 0,
00226 boost::shared_ptr<Texture<float> >(), 1.f, 0.f,
00227 false, false);
00228 delete[] p;
00229 delete[] n;
00230 delete[] vertexIndex;
00231 return mesh;
00232 }
00233
00234 static DynamicLoader::RegisterShape<PlyMesh> r("plymesh");
00235
00236 }
00237