Changeset 110
- Timestamp:
- 11/13/07 22:49:48 (1 year ago)
- Files:
-
- trunk/OpenMeshD/OpenMesh/Apps/GLViewer/GLViewer.d (modified) (1 diff)
- trunk/OpenMeshD/OpenMesh/Apps/GLViewer/MeshDrawerT.d (modified) (1 diff)
- trunk/OpenMeshD/OpenMesh/Core/Geometry/VectorT.d (modified) (2 diffs)
- trunk/OpenMeshD/OpenMesh/Core/IO/BinaryHelper.d (modified) (10 diffs)
- trunk/OpenMeshD/OpenMesh/Core/IO/IOManager.d (modified) (1 diff)
- trunk/OpenMeshD/OpenMesh/Core/IO/MeshIO.d (modified) (1 diff)
- trunk/OpenMeshD/OpenMesh/Core/IO/exporter/BaseExporter.d (modified) (2 diffs)
- trunk/OpenMeshD/OpenMesh/Core/IO/importer/ImporterT.d (modified) (5 diffs)
- trunk/OpenMeshD/OpenMesh/Core/IO/reader/OFFReader.d (modified) (1 diff)
- trunk/OpenMeshD/OpenMesh/Core/IO/reader/PLYReader.d (modified) (19 diffs)
- trunk/OpenMeshD/OpenMesh/Core/IO/writer/PLYWriter.d (modified) (9 diffs)
- trunk/OpenMeshD/OpenMesh/Core/IO/writers.d (modified) (1 diff)
- trunk/OpenMeshD/OpenMesh/Core/Mesh/BaseKernel.d (modified) (4 diffs)
- trunk/OpenMeshD/OpenMesh/Core/Utils/PropertyContainer.d (modified) (1 diff)
- trunk/OpenMeshD/OpenMesh/Core/Utils/Std.d (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/OpenMeshD/OpenMesh/Apps/GLViewer/GLViewer.d
r104 r110 8 8 // Created: 01 Sep 2007 9 9 // Written in the D Programming Language (http://www.digitalmars.com/d) 10 //============================================================================11 // $Id:$12 10 //============================================================================ 13 11 trunk/OpenMeshD/OpenMesh/Apps/GLViewer/MeshDrawerT.d
r104 r110 122 122 dout.writefln( "File provides texture coordinates"); 123 123 124 { 125 auto vpit = mesh_.vprops_begin, vpend = mesh.vprops_end; 126 for(; vpit!=vpend; ++vpit) { 127 if (!vpit.val) { continue; } 128 string pname = vpit.val.name; 129 if (pname.length >= 2 && pname[0..2]=="v:") 130 continue; // reserved prop name 131 TypeInfo ptype = vpit.val.element_type; 132 dout.writefln("File provides per-vertex property '%s' of type %s", 133 pname, ptype); 134 } 135 136 } 137 { 138 auto vpit = mesh_.fprops_begin, vpend = mesh.fprops_end; 139 for(; vpit!=vpend; ++vpit) { 140 if (!vpit.val) { continue; } 141 string pname = vpit.val.name; 142 if (pname.length >= 2 && pname[0..2]=="f:") 143 continue; // reserved prop name 144 TypeInfo ptype = vpit.val.element_type; 145 dout.writefln("File provides per-face property '%s' of type %s", 146 pname, ptype); 147 } 148 } 124 149 125 150 // info trunk/OpenMeshD/OpenMesh/Core/Geometry/VectorT.d
r108 r110 293 293 assert(_i<N); values_[_i] = v; 294 294 } 295 int opApply(int delegate(ref Scalar) loop) { 296 foreach(ref x; values_) { 297 int ret = loop(x); 298 if (ret) return ret; 299 } 300 return 0; 301 } 302 int opApply(int delegate(ref size_t, ref Scalar) loop) { 303 foreach(i, ref x; values_) { 304 int ret = loop(i,x); 305 if (ret) return ret; 306 } 307 return 0; 308 } 309 int opApplyReverse(int delegate(ref Scalar) loop) { 310 foreach_reverse(ref x; values_) { 311 int ret = loop(x); 312 if (ret) return ret; 313 } 314 return 0; 315 } 316 int opApplyReverse(int delegate(ref size_t, ref Scalar) loop) { 317 foreach_reverse(i, ref x; values_) { 318 int ret = loop(i,x); 319 if (ret) return ret; 320 } 321 return 0; 322 } 323 324 295 325 //---------------------------------------------------------------- comparsion 296 326 /// component-wise comparison … … 720 750 alias VectorT!(double,4) Vec4d; 721 751 752 /* 753 template Vector2(T) { alias VectorT!(T,2) Vector2; } 754 template Vector3(T) { alias VectorT!(T,3) Vector3; } 755 template Vector4(T) { alias VectorT!(T,4) Vector4; } 756 template Vector5(T) { alias VectorT!(T,5) Vector5; } 757 template Vector6(T) { alias VectorT!(T,6) Vector6; } 758 template Vector7(T) { alias VectorT!(T,7) Vector7; } 759 template Vector8(T) { alias VectorT!(T,8) Vector8; } 760 */ 722 761 723 762 trunk/OpenMeshD/OpenMesh/Core/IO/BinaryHelper.d
r82 r110 9 9 // Written in the D Programming Language (http://www.digitalmars.com/d) 10 10 //============================================================================ 11 // $Id:$12 //============================================================================13 11 14 12 module OpenMesh.Core.IO.BinaryHelper; … … 75 73 union SC { short s; ubyte[2] c; } 76 74 union IC { int i; ubyte[4] c; } 75 union LC { long l; ubyte[8] c; } 77 76 union FC { float f; ubyte[4] c; } 78 77 union DC { double d; ubyte[8] c; } … … 106 105 } 107 106 107 /** Binary read a \c long from \c _in and perform byte swapping if 108 \c _swap is true */ 109 long read_long(Stream _in, bool _swap=false) 110 { 111 LC ic; 112 uint got = _in.read(ic.c); 113 assert(got==ic.c.length); 114 if (_swap) { 115 util.swap(ic.c[0], ic.c[7]); 116 util.swap(ic.c[1], ic.c[6]); 117 util.swap(ic.c[2], ic.c[5]); 118 util.swap(ic.c[3], ic.c[4]); 119 } 120 return ic.l; 121 } 122 108 123 /** Binary read a \c float from \c _is and perform byte swapping if 109 124 \c _swap is true */ … … 162 177 } 163 178 179 /** Binary write a \c long to \c _out and perform byte swapping if 180 \c _swap is true */ 181 void write_long(long _l, Stream _out, bool _swap=false) 182 { 183 LC ic; 184 ic.l = _l; 185 if (_swap) { 186 util.swap(ic.c[0], ic.c[7]); 187 util.swap(ic.c[1], ic.c[6]); 188 util.swap(ic.c[2], ic.c[5]); 189 util.swap(ic.c[3], ic.c[4]); 190 } 191 uint wrote = _out.write(ic.c); 192 assert(wrote == ic.c.length); 193 } 194 164 195 /** Binary write a \c float to \c _os and perform byte swapping if 165 196 \c _swap is true */ … … 193 224 194 225 226 /** Binary rean an elementary value from _in and perform byte swapping if 227 _swap is true */ 228 void read_binary(T)(ref T _v, Stream _in, bool _swap=false) 229 { 230 static if(is(T == ubyte)) { _in.read(_v); } 231 else static if(is(T == byte)) { _in.read(_v); } 232 else static if(is(T == bool)) { ubyte b; _in.read(b); _v=b; } 233 else static if(is(T == short)||is(T==ushort)) { _v = cast(T)read_short(_in,_swap); } 234 else static if(is(T == int)||is(T==uint)) { _v = cast(T)read_int(_in,_swap); } 235 else static if(is(T == long)||is(T==ulong)) { _v = cast(T)read_long(_in,_swap); } 236 else static if(is(T == float)) { _v = read_float(_in,_swap); } 237 else static if(is(T == double)) { _v = read_double(_in,_swap); } 238 else { 239 static assert(false, "read_binary: Unsupported type: "~T.stringof); 240 } 241 } 242 243 /** Binary write an elementary value to _out and perform byte swapping if 244 _swap is true */ 245 void write_binary(T)(T _v, Stream _out, bool _swap=false) 246 { 247 static if(is(T == ubyte)) { _out.write(_v); } 248 else static if(is(T == byte)) { _out.write(_v); } 249 else static if(is(T == bool)) { _out.write(cast(ubyte)_v); } 250 else static if(is(T == short)||is(T==ushort)) { write_short(cast(short)_v,_out,_swap); } 251 else static if(is(T == int)||is(T==uint)) { write_int(cast(int)_v,_out,_swap); } 252 else static if(is(T == long)||is(T==ulong)) { write_long(cast(long)_v,_out,_swap); } 253 else static if(is(T == float)) { write_float(_v,_out,_swap); } 254 else static if(is(T == double)) { write_double(_v,_out,_swap); } 255 else { 256 static assert(false, "write_binary: Unsupported type: "~T.stringof); 257 } 258 } 259 195 260 196 261 //------------------ FILE* interface ----------------------------- … … 214 279 } 215 280 281 /** Binary read a \c long from \c _is and perform byte swapping if 282 \c _swap is true */ 283 long read_long(FILE* _in, bool _swap=false) 284 { 285 scope _cin = new CFile(_in,FileMode.In); 286 scope(exit) _cin.file=null; 287 return read_long(_cin, _swap); 288 } 289 216 290 /** Binary read a \c float from \c _is and perform byte swapping if 217 291 \c _swap is true */ … … 239 313 scope _cout = new CFile(_out,FileMode.Out); 240 314 scope(exit) _cout.file=null; 241 returnwrite_short(_i, _cout, _swap);315 write_short(_i, _cout, _swap); 242 316 } 243 317 … … 248 322 scope _cout = new CFile(_out,FileMode.Out); 249 323 scope(exit) _cout.file=null; 250 return write_int(_i, _cout, _swap); 324 write_int(_i, _cout, _swap); 325 } 326 327 /** Binary write a \c long to \c _os and perform byte swapping if 328 \c _swap is true */ 329 void write_long(long _i, FILE* _out, bool _swap=false) 330 { 331 scope _cout = new CFile(_out,FileMode.Out); 332 scope(exit) _cout.file=null; 333 write_long(_i, _cout, _swap); 251 334 } 252 335 … … 257 340 scope _cout = new CFile(_out,FileMode.Out); 258 341 scope(exit) _cout.file=null; 259 returnwrite_float(_f, _cout, _swap);342 write_float(_f, _cout, _swap); 260 343 } 261 344 … … 266 349 scope _cout = new CFile(_out,FileMode.Out); 267 350 scope(exit) _cout.file=null; 268 returnwrite_double(_d, _cout, _swap);269 } 270 271 351 write_double(_d, _cout, _swap); 352 } 353 354 /** Swap the endian-ness of the data v */ 272 355 void swap_endian(T)(ref T v) 273 356 { trunk/OpenMeshD/OpenMesh/Core/IO/IOManager.d
r98 r110 8 8 // Created: 01 Sep 2007 9 9 // Written in the D Programming Language (http://www.digitalmars.com/d) 10 //============================================================================11 // $Id:$12 10 //============================================================================ 13 11 trunk/OpenMeshD/OpenMesh/Core/IO/MeshIO.d
r98 r110 76 76 Options opt; 77 77 return read_mesh(_mesh, _filename, opt); 78 if (_optout) *_optout = opt; 78 79 } 79 80 trunk/OpenMeshD/OpenMesh/Core/IO/exporter/BaseExporter.d
r5 r110 7 7 // Author: William V. Baxter III 8 8 // Created: 01 Sep 2007 9 // License: LGPL 2.1 9 10 // Written in the D Programming Language (http://www.digitalmars.com/d) 10 //============================================================================11 // $Id:$12 11 //============================================================================ 13 12 … … 100 99 bool has_face_normals() /*const*/ { return false; } 101 100 bool has_face_colors() /*const*/ { return false; } 101 102 103 102 104 } 103 105 trunk/OpenMeshD/OpenMesh/Core/IO/importer/ImporterT.d
r103 r110 9 9 // Written in the D Programming Language (http://www.digitalmars.com/d) 10 10 //============================================================================ 11 // $Id:$12 //============================================================================13 11 14 12 module OpenMesh.Core.IO.importer.ImporterT; … … 65 63 //=== IMPLEMENTATION ========================================================== 66 64 65 private { 66 const string[] supported_types = 67 ["byte","ubyte","short","ushort","int","uint","float","double", 68 "Vec3f","Vec3d","Vec3ub","Vec2f","Vec2d","Vec2ub","Vec4f","Vec4d","Vec4ub"]; 69 // Very simple compile-time pattern subsitution. 70 // Just replaces all % chars with sub 71 string ctfe_subs(string str, string sub) { 72 string ret; 73 foreach(c; str) { 74 if (c=='%') { ret ~= sub; } 75 else { ret ~= c; } 76 } 77 return ret; 78 } 79 // Assumes calling code has a TypeInfo ti variable. 80 // Assumes templ uses '%' as a stand-in for the type name 81 string do_type_cases(string templ) { 82 // Generates a big if-else block of the form 83 // if(false) {} 84 // else if(ti == typeid(int)) { <templ> } 85 // else if(ti == typeid(float)) { <templ> } 86 // ... 87 string ret = "if(false){}\n"; 88 foreach(t; supported_types) { 89 ret ~= "else if (ti == typeid("~t~")) { "; 90 ret ~= ctfe_subs(templ,t); 91 ret ~= " }\n"; 92 } 93 ret ~= "else assert(false, \"Unsupported type: \"~ti.toString);"; 94 return ret; 95 } 96 } 67 97 68 98 /** … … 183 213 184 214 /// check if a property type is supported 185 bool supports_property_data_type(TypeInfo _ti) { 186 if (_ti == typeid(int)) { 187 } 188 else if (_ti == typeid(float)) 189 { 190 } 191 else if (_ti == typeid(Vec3f)) 192 { 193 } 194 else if (_ti == typeid(Vec3ub)) 195 { 196 } 197 else 198 return false; 199 200 return true; 215 bool supports_property_data_type(TypeInfo ti) { 216 bool ok=false; 217 218 mixin(do_type_cases( "ok=true;" )); 219 220 return ok; 201 221 } 202 222 … … 245 265 } 246 266 247 if (ti == typeid(int)) { 248 set_vpropertyT!(int)(_vh, _propname, va_arg!(int)(aptr)); 249 } 250 else if (ti == typeid(float)) 251 { 252 set_vpropertyT!(float)(_vh, _propname, va_arg!(float)(aptr)); 253 } 254 else if (ti == typeid(Vec3f)) 255 { 256 set_vpropertyT!(Vec3f)(_vh, _propname, va_arg!(Vec3f)(aptr)); 257 } 258 else if (ti == typeid(Vec3ub)) 259 { 260 set_vpropertyT!(Vec3ub)(_vh, _propname, va_arg!(Vec3ub)(aptr)); 261 } 262 else 263 assert(0); 264 265 return; 266 //auto prop_ptr = mesh_.get_property(_propname); 267 //for (j = 0; j < arguments.length; ) 268 //{ 269 //} 267 mixin(do_type_cases( "set_vpropertyT!( % )(_vh, _propname, va_arg!( % )(aptr));" )); 268 270 269 } 271 270 … … 273 272 void set_property(FaceHandle _fh, string _propname, ...) 274 273 { 275 if (_arguments.length != 1) 276 throw new Exception("set_property takes exactly 1 value argument"); 274 if (_arguments.length == 0) 275 throw new Exception("set_property takes 1 value argument, or a typeinfo and a void*"); 276 277 277 TypeInfo ti = _arguments[0]; 278 if (ti == typeid(int)) { 279 set_fpropertyT!(int)(_fh, _propname, va_arg!(int)(_argptr)); 280 } 281 else if (ti == typeid(float)) 282 { 283 set_fpropertyT!(float)(_fh, _propname, va_arg!(float)(_argptr)); 284 } 285 else if (ti == typeid(Vec3f)) 286 { 287 set_fpropertyT!(Vec3f)(_fh, _propname, va_arg!(Vec3f)(_argptr)); 288 } 289 else if (ti == typeid(Vec3ub)) 290 { 291 set_fpropertyT!(Vec3ub)(_fh, _propname, va_arg!(Vec3ub)(_argptr)); 292 } 293 return; 278 void *aptr = _argptr; 279 //writefln("set_property(fh..) type:%s args.lengt: %s", _arguments[0], _arguments.length); 280 if (_arguments.length == 2) { 281 if (ti == typeid(TypeInfo)) { 282 //writefln( " ti was: ", ti); 283 ti = va_arg!(TypeInfo)(_argptr); 284 aptr = va_arg!(void*)(_argptr); 285 //writefln( " ti now: ", ti); 286 } 287 else { 288 throw new Exception("set_property with 2 arguments should have a typeinfo as arg 1"); 289 } 290 } 291 else if (_arguments.length>2 ) { 292 throw new Exception("set_property takes 1 value argument, or a typeinfo and a void*"); 293 } 294 295 mixin(do_type_cases( "set_fpropertyT!( % )(_fh, _propname, va_arg!( % )(_argptr));" )); 294 296 } 295 297 trunk/OpenMeshD/OpenMesh/Core/IO/reader/OFFReader.d
r98 r110 178 178 read_ascii(_in, _bi)); 179 179 180 // Can't tell if there were face colors or not till after you read it. 180 // Thanks to the foobar mess that is OFF format, 181 // You can't tell if there were face colors or not till after you read it. 181 182 if (options_.face_has_color) _opt += Options.FaceColor; 182 183 return ret; trunk/OpenMeshD/OpenMesh/Core/IO/reader/PLYReader.d
r103 r110 55 55 bool startsWith(string s, string sub) { 56 56 return (s.length>=sub.length && s[0..sub.length]==sub); 57 } 58 bool endsWith(string s, string sub) { 59 return (s.length>=sub.length && s[$-sub.length..$]==sub); 57 60 } 58 61 … … 280 283 // READ FACES 281 284 FaceHandle[] fh_list; fh_list.length = 10; 285 struct NamedBox { 286 string name; 287 boxer.Box box; 288 } 289 NamedBox[] extra_fprops; 282 290 for (int i=0; i<nF; ) 283 291 { … … 299 307 bool got_color = false; 300 308 boxer.Box ret; 309 int iextras = 0; 301 310 foreach(prop; _desc.fprops) { 311 //debug { dout.writefln("reading fprop.name = %s",prop.name).flush; } 302 312 if (is_binary) { 303 313 ret = prop.read_prop_binary(_in, _bi, _opt, _desc.need_swap); … … 318 328 case "vertex_indices": vids = unbox_convert!(uint[])(ret); break; 319 329 default: 320 //ignore 330 if (prop.type_supported) { 331 if (iextras+1>extra_fprops.length) { 332 extra_fprops.length = extra_fprops.length+1; 333 extra_fprops[$-1].name = prop.name.dup; 334 } 335 else { 336 assert(extra_fprops[iextras].name==prop.name, 337 "these prop names should be in sync"); 338 } 339 extra_fprops[iextras++].box = ret; 340 } 341 321 342 } 322 343 } … … 325 346 326 347 fh_list.length = 0; 327 _bi.add_face(vs, &fh_list); 348 _bi.add_face(vs, &fh_list); // returns list if face got triangulated 328 349 329 350 foreach(fh; fh_list) { … … 335 356 _bi.set_color(fh,color); 336 357 _opt += Options.FaceColor; 358 } 359 foreach (ref xprop; extra_fprops) { 360 // ack! need to go box to prop->box 361 TypeInfo[] types; void* data; 362 boxer.boxArrayToArguments([xprop.box], types, data); 363 _bi.set_property(fh, xprop.name, types[0], data); 337 364 } 338 365 } … … 351 378 alias std.string.split split; 352 379 353 string[string] known_vprops =354 [355 "x"[]:"x"[], "y":"y", "z":"z",356 "nx":"nx", "ny":"ny", "nz":"nz",357 "r":"r", "g":"g", "b":"b",358 "red":"r", "green":"g", "blue":"b",359 "t":"t", "s":"s",360 ];361 string[string] known_fprops =362 [363 "nx"[]:"nx"[], "ny":"ny", "nz":"nz",364 "r":"r", "g":"g", "b":"b",365 "red":"r", "green":"g", "blue":"b",366 "vertex_indices":"vertex_indices",367 ];368 string[] words;369 370 Prop[]* prop_ptr = null;371 string[string]* known_props_ptr = null;372 string cur_element;373 374 375 void update_desc_from_prop(ref string propname)376 {377 if (auto _ret = propname in *known_props_ptr) {378 propname = *_ret;379 }380 if (cur_element == "vertex") {381 switch(propname) {382 case "x": case "y": case "z":383 _desc.vertex_has_position = true; break;384 case "nx": case "ny": case "nz":385 _desc.vertex_has_normal = true; break;386 case "r": case "g": case "b":387 _desc.vertex_has_color = true; break;388 case "s": case "t":389 _desc.vertex_has_texcoord = true; break;390 default:391 _desc.vertex_has_other = true; break;392 }393 }394 else if (cur_element == "face") {395 switch(propname) {396 case "nx": case "ny": case "nz":397 _desc.face_has_normal = true; break;398 case "r": case "g": case "b":399 _desc.face_has_color = true; break;400 default:401 _desc.face_has_other = true; break;402 }403 }404 }405 void add_prop(string[] words) {406 string propname = words[1];407 update_desc_from_prop(propname);408 bool ok = _bi.supports_property_data_type(ply_data_type_typeid(words[0]));409 (*prop_ptr) ~= new ScalarProp(propname, words[0], ok);410 }411 void add_list_prop(string[] words) {412 string propname = words[2];413 update_desc_from_prop(propname);414 bool ok = _bi.supports_property_data_type(ply_data_type_typeid(words[1]));415 (*prop_ptr) ~= new ListProp(propname,words[0],words[1], ok);416 }417 418 380 char[] line; line.length = 4; 381 419 382 _is.readExact(line.ptr,4); 420 383 if (line != "ply\n") { … … 422 385 "File is not a PLY file. Missing magic number 'ply\\n' (first line was '"~line~"'"); 423 386 } 424 387 388 string[] words; 389 string[][] fprops,vprops; 390 string cur_element; 391 425 392 bool got_end_header = false; 426 393 for(int lnum=2; !_is.eof(); ++lnum) … … 473 440 if (words[1] == "vertex") { 474 441 _desc.n_vertices = std.conv.toUint(words[2]); 475 prop_ptr = &_desc.vprops;476 known_props_ptr = &known_vprops;442 //prop_ptr = &_desc.vprops; 443 //known_props_ptr = &known_vprops; 477 444 cur_element = "vertex"; 478 445 } 479 446 else if (words[1] == "face") { 480 447 _desc.n_faces = std.conv.toUint(words[2]); 481 prop_ptr = &_desc.fprops;482 known_props_ptr = &known_fprops;448 //prop_ptr = &_desc.fprops; 449 //known_props_ptr = &known_fprops; 483 450 cur_element = "face"; 484 451 } … … 492 459 if (_bi) { // skip the work if we're just scanning header, not actually importing 493 460 words = line.split(); 494 495 if (words[1] == "list") { 496 add_list_prop(words[2..$]); 497 if (!(words[4] in *known_props_ptr)) { 498 derr.writefln( 499 "line: %s: Ignoring unsupported %s list property: ", lnum,words[3],words[4]).flush; 500 } 461 if (cur_element=="vertex") { 462 vprops ~= words.dup; 501 463 } 502 503 else { 504 add_prop(words[1..$]); 505 506 if (!(words[2] in *known_props_ptr)) { 507 if ((*prop_ptr)[$-1].type_supported) { 508 dlog.writefln("reading extra %s property, '%s'", lnum, words[1],words[2]).flush; 509 } else { 510 derr.writefln("line: %s: Ignoring unsupported %s property: ", lnum, words[1],words[2]).flush; 511 } 512 } 513 } 514 } 464 else if (cur_element == "face") { 465 fprops ~= words.dup; 466 } 467 } 515 468 } 516 469 else { … … 523 476 } 524 477 478 if (_bi) { 479 _process_property_descriptions(_desc, _bi, vprops,fprops); 480 } 525 481 return true; 482 } 483 484 private void _process_property_descriptions(_Descrip _desc, BaseImporter _bi, 485 string[][] vprops, string[][] fprops) 486 { 487 string[string] known_vprops = 488 [ 489 "x"[]:"x"[], "y":"y", "z":"z", 490 "nx":"nx", "ny":"ny", "nz":"nz", 491 "r":"r", "g":"g", "b":"b", 492 "red":"r", "green":"g", "blue":"b", 493 "t":"t", "s":"s", 494 ]; 495 string[string] known_fprops = 496 [ 497 "nx"[]:"nx"[], "ny":"ny", "nz":"nz", 498 "r":"r", "g":"g", "b":"b", 499 "red":"r", "green":"g", "blue":"b", 500 "vertex_indices":"vertex_indices", 501 ]; 502 string[][string] known_vector_suffixes = 503 // These can also be preceeded by an '_' 504 [ 505 "x"[] : cast(string[])["x","y","z","w"], 506 "r" : ["r", "g", "b", "a"], 507 "s" : ["s", "t", "r", "q"], 508 "red" : ["red", "green", "blue", "alpha"], 509 "0" : ["0","1","2","3"], 510 "1" : ["1","2","3","4"], 511 ]; 512 string[] words; 513 514 enum ElemT { BadElem=-1,VertexElem=0,FaceElem=1 }; 515 Prop[]*[2] prop_ptrs = [&_desc.vprops, &_desc.fprops]; 516 string[string][2] known_props = [known_vprops,known_fprops]; 517 ElemT cur_element=ElemT.BadElem; 518 519 void update_desc_from_prop(ref string propname) 520 { 521 if (auto _ret = propname in known_props[cur_element]) { 522 propname = *_ret; 523 } 524 if (cur_element == ElemT.VertexElem) { 525 switch(propname) { 526 case "x": case "y": case "z": 527 _desc.vertex_has_position = true; break; 528 case "nx": case "ny": case "nz": 529 _desc.vertex_has_normal = true; break; 530 case "r": case "g": case "b": 531 _desc.vertex_has_color = true; break; 532 case "s": case "t": 533 _desc.vertex_has_texcoord = true; break; 534 default: 535 _desc.vertex_has_other = true; break; 536 } 537 } 538 else if (cur_element == ElemT.FaceElem) { 539 switch(propname) { 540 case "nx": case "ny": case "nz": 541 _desc.face_has_normal = true; break; 542 case "r": case "g": case "b": 543 _desc.face_has_color = true; break; 544 default: 545 _desc.face_has_other = true; break; 546 } 547 } 548 } 549 void add_prop(string[] words) { 550 // words is like ["float32", "x"] -- "property" stripped 551 string propname = words[1]; 552 update_desc_from_prop(propname); 553 bool ok = _bi.supports_property_data_type(ply_data_type_typeid(words[0])); 554 *prop_ptrs[cur_element] ~= new ScalarProp(propname, words[0], ok); 555 if (!(words[1] in known_props[cur_element])) { 556 if ((*prop_ptrs[cur_element])[$-1].type_supported) { 557 dlog.writefln("PLYReader: reading extra %s property, '%s'", 558 words[0],words[1]).flush; 559 } else { 560 derr.writefln("PLYReader: Ignoring unsupported %s property, '%s'", 561 words[0],words[1]).flush; 562 } 563 } 564 } 565 void add_vector_prop(string[][] lines, string first_suffix, int N) 566 { 567 // each lines[i] is like ["property", "float32", "pos_x"] 568 // merge the sequence into one VectorT prop 569 string prop_base_name = lines[0][2][0..$-first_suffix.length]; 570 string prop_type = lines[0][1]; 571 572 TypeInfo ti; 573 switch(N) { 574 case 2: ti = ply_data_vector_type_typeid!(2)(prop_type); break; 575 case 3: ti = ply_data_vector_type_typeid!(3)(prop_type); break; 576 case 4: ti = ply_data_vector_type_typeid!(4)(prop_type); break; 577 default: 578 assert(false, "Unsupported vector length"); 579 } 580 bool ok = _bi.supports_property_data_type(ti); 581 *prop_ptrs[cur_element] ~= new VectorProp(prop_base_name, N, prop_type, ok); 582 if ((*prop_ptrs[cur_element])[$-1].type_supported) { 583 dlog.writefln("PLYReader: reading extra %s-vector %s property, '%s'", 584 N,prop_type,prop_base_name).flush; 585 } else { 586 derr.writefln("PLYReader: Ignoring unsupported %s-vector %s property: ", 587 N,prop_type,prop_base_name).flush; 588 } 589 } 590 591 void add_list_prop(string[] words) { 592 // words is a tokenized ply list property line without the 593 // leading "property list" part. 594 // Something like: ["uint8", "int32", "vertex_indices"] 595 string propname = words[2]; 596 update_desc_from_prop(propname); 597 bool ok = _bi.supports_property_data_type(ply_data_type_typeid(words[1])); 598 *prop_ptrs[cur_element] ~= new ListProp(propname,words[0],words[1], ok); 599 if (!(words[2] in known_props[cur_element])) { 600 derr.writefln( 601 "PLYReader: Ignoring unsupported %s list property: ", 602 words[1],words[2]).flush; 603 } 604 } 605 606 607 int vector_sequence_length(string prop_lines[][], ref string first_suffix) 608 { 609 // prop_lines[0] is regular tokenized ply prop line 610 // like ["property", "float32", "ambient_r"] 611 // see if there is a sequence following this one like "ambient_g","ambient_b" 612 // If so make it a vector. 613 string pname0 = prop_lines[0][2]; 614 // known props like just r,g,b are handled separately 615 if (pname0 in known_props[cur_element]) return 0; 616 string ptype0 = prop_lines[0][1]; 617 foreach(start,suffixes; known_vector_suffixes) 618 { 619 bool got_start=false; 620 string sep = ""; 621 if (pname0.endsWith("_"~start)) { got_start=true; sep="_";} 622 else if (pname0.endsWith(start)) { got_start=true; } 623 if (got_start) { 624 // see how big the sequence is 625 string basename0 = pname0[0..$-start.length]; 626 int i=1; 627 while(i<suffixes.length 628 && i<prop_lines.length 629 && prop_lines[i][1]==ptype0 /* catches "list" too*/ 630 && prop_lines[i][2].startsWith(basename0) 631 && prop_lines[i][2].endsWith(sep~suffixes[i])) 632 { ++i; } 633 634 if (i>1) { 635 first_suffix = sep~start; 636 return i; 637 } 638 } 639 } 640 return 0; 641 } 642 643 void process_category(ElemT cur_el, string[][] prop_lines) 644 { 645 cur_element = cur_el; 646 647 for(int idx = 0; idx<prop_lines.length; ++idx) 648 { 649 string[] words = prop_lines[idx]; 650 if (words[1] == "list") { 651 add_list_prop(words[2..$]); 652 } 653 else { 654 string first_suffix; 655 int len = vector_sequence_length(prop_lines[idx..$], first_suffix); 656 switch(len) { 657 case 0: case 1: 658 add_prop(words[1..$]); break; 659 660 case 2: case 3: case 4: 661 add_vector_prop(prop_lines[idx..idx+len], first_suffix, len); idx+=len-1; break; 662 default: 663 assert(false, "bad length for vector property"); 664 } 665 } 666 } 667 } 668 669 process_category(ElemT.VertexElem, vprops); 670 671 process_category(ElemT.FaceElem, fprops); 526 672 } 527 673 … … 555 701 case "float64": return typeid(double); 556 702 703 default: return null; 704 } 705 } 706 static TypeInfo ply_data_vector_type_typeid(int N)(string type) { 707 switch(type) { 708 case "int8": return typeid(VectorT!(byte,N)); 709 case "uint8": return typeid(VectorT!(ubyte,N)); 710 case "int16": return typeid(VectorT!(short,N)); 711 case "uint16": return typeid(VectorT!(ushort,N)); 712 case "int32": return typeid(VectorT!(int,N));<
