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
00026 #include "waldtrianglemesh.h"
00027 #include "./plymesh/rply.h"
00028
00029 namespace lux
00030 {
00031
00032
00033 static int VertexCB(p_ply_argument argument)
00034 {
00035 long current_cmpnt = 0;
00036 void* pointer_usrdata = NULL;
00037 ply_get_argument_user_data(argument, &pointer_usrdata, ¤t_cmpnt);
00038
00039 PlyMesh* mesh = static_cast<PlyMesh*>(pointer_usrdata);
00040
00041 long vertindex;
00042 ply_get_argument_element(argument, NULL, &vertindex);
00043
00044 if(current_cmpnt == 0)
00045 mesh->p[vertindex].x = (float) ply_get_argument_value(argument);
00046 else if(current_cmpnt == 1)
00047 mesh->p[vertindex].y = (float) ply_get_argument_value(argument);
00048 else if(current_cmpnt == 2)
00049 mesh->p[vertindex].z = (float) ply_get_argument_value(argument);
00050
00051 return 1;
00052 }
00053
00054
00055 static int FaceCB(p_ply_argument argument)
00056 {
00057 void* pointer_usrdata = NULL;
00058 ply_get_argument_user_data(argument, &pointer_usrdata, NULL);
00059
00060 PlyMesh* mesh = static_cast<PlyMesh*>(pointer_usrdata);
00061
00062 long tri_index;
00063 ply_get_argument_element(argument, NULL, &tri_index);
00064
00065 long length, value_index;
00066 ply_get_argument_property(argument, NULL, &length, &value_index);
00067
00068 if(value_index >= 0 && value_index < 3)
00069 {
00070 mesh->vertexIndex[(tri_index * 3) + value_index] =
00071 (int)ply_get_argument_value(argument);
00072 }
00073
00074 return 1;
00075 }
00076
00077
00078 PlyMesh::PlyMesh(const Transform &o2w, bool ro, string filename, bool smooth)
00079 : Shape(o2w, ro) {
00080
00081 printf("Loading PLY mesh file: '%s'...\n", filename.c_str());
00082
00083 p_ply plyfile = ply_open(filename.c_str(), NULL);
00084
00085 if(!plyfile) {
00086 std::stringstream ss;
00087 ss<<"Unable to read PLY mesh file '"<<filename<<"'";
00088 luxError(LUX_BUG,LUX_ERROR,ss.str().c_str());
00089 return;
00090 }
00091
00092 if(!ply_read_header(plyfile)) {
00093 std::stringstream ss;
00094 ss<<"Unable to read PLY header '"<<filename<<"'";
00095 luxError(LUX_BUG,LUX_ERROR,ss.str().c_str());
00096 return;
00097 }
00098
00099 long plyNverts = ply_set_read_cb(plyfile, "vertex", "x", VertexCB, this, 0);
00100 nverts = (int) plyNverts;
00101 p = new Point[nverts];
00102 ply_set_read_cb(plyfile, "vertex", "y", VertexCB, this, 1);
00103 ply_set_read_cb(plyfile, "vertex", "z", VertexCB, this, 2);
00104
00105 long plyNtris = ply_set_read_cb(plyfile, "face", "vertex_indices", FaceCB, this, 0);
00106 ntris = (int) plyNtris;
00107 vertexIndex = new int[3 * ntris];
00108
00109 uvs = NULL;
00110 n = NULL;
00111 s = NULL;
00112
00113 if(!ply_read(plyfile)) {
00114 std::stringstream ss;
00115 ss<<"Unable to parse PLY file '"<<filename<<"'";
00116 luxError(LUX_BUG,LUX_ERROR,ss.str().c_str());
00117 nverts = ntris = 0;
00118 return;
00119 }
00120
00121 ply_close(plyfile);
00122
00123
00124 for (int i = 0; i < nverts; ++i)
00125 p[i] = ObjectToWorld(p[i]);
00126
00127 if(!smooth) return;
00128
00129
00130
00131
00132
00133
00134 n = new Normal[nverts];
00135 int *nf = new int[nverts];
00136 for(int i=0; i < nverts; i++) {
00137 n[i] = Normal(0., 0., 0.);
00138 nf[i] = 0;
00139 }
00140
00141 for(int tri=0; tri < ntris; tri++) {
00142
00143 float x10 = p[vertexIndex[(3*tri)+1]].x - p[vertexIndex[(3*tri)]].x;
00144 float y10 = p[vertexIndex[(3*tri)+1]].y - p[vertexIndex[(3*tri)]].y;
00145 float z10 = p[vertexIndex[(3*tri)+1]].z - p[vertexIndex[(3*tri)]].z;
00146 float x12 = p[vertexIndex[(3*tri)+1]].x - p[vertexIndex[(3*tri)+2]].x;
00147 float y12 = p[vertexIndex[(3*tri)+1]].y - p[vertexIndex[(3*tri)+2]].y;
00148 float z12 = p[vertexIndex[(3*tri)+1]].z - p[vertexIndex[(3*tri)+2]].z;
00149
00150
00151 float cpx = (z10 * y12) - (y10 * z12);
00152 float cpy = (x10 * z12) - (z10 * x12);
00153 float cpz = (y10 * x12) - (x10 * y12);
00154
00155
00156 float r = sqrtf(cpx * cpx + cpy * cpy + cpz * cpz);
00157 float nx = cpx / r;
00158 float ny = cpy / r;
00159 float nz = cpz / r;
00160 Normal fn = Normal(nx, ny, nz);
00161
00162
00163 n[vertexIndex[3*tri]] += fn;
00164 n[vertexIndex[(3*tri)+1]] += fn;
00165 n[vertexIndex[(3*tri)+2]] += fn;
00166
00167
00168 nf[vertexIndex[3*tri]]++;
00169 nf[vertexIndex[(3*tri)+1]]++;
00170 nf[vertexIndex[(3*tri)+2]]++;
00171 }
00172
00173
00174 for(int i=0; i < nverts; i++) {
00175 n[i] /= nf[i];
00176 }
00177
00178 delete[] nf;
00179
00180 printf("Done.\n");
00181 }
00182 PlyMesh::~PlyMesh() {
00183 delete[] vertexIndex;
00184 delete[] p;
00185 delete[] s;
00186 delete[] n;
00187 delete[] uvs;
00188 }
00189 BBox PlyMesh::ObjectBound() const {
00190 BBox bobj;
00191 for (int i = 0; i < nverts; i++)
00192 bobj = Union(bobj, WorldToObject(p[i]));
00193 return bobj;
00194 }
00195 BBox PlyMesh::WorldBound() const {
00196 BBox worldBounds;
00197 for (int i = 0; i < nverts; i++)
00198 worldBounds = Union(worldBounds, p[i]);
00199 return worldBounds;
00200 }
00201
00202 void
00203 PlyMesh::Refine(vector<boost::shared_ptr<Shape> > &refined)
00204 const {
00205 for (int i = 0; i < ntris; ++i) {
00206 boost::shared_ptr<Shape> o (new WaldTriangle(ObjectToWorld,
00207 reverseOrientation,
00208 (WaldTriangleMesh *)this,
00209 i));
00210 refined.push_back(o);
00211 }
00212 }
00213
00214 Shape* PlyMesh::CreateShape(const Transform &o2w,
00215 bool reverseOrientation, const ParamSet ¶ms) {
00216 string filename = params.FindOneString("filename", "none");
00217 bool smooth = params.FindOneBool("smooth", false);
00218 return new PlyMesh(o2w, reverseOrientation, filename, smooth);
00219 }
00220
00221 }
00222