1 /** 2 Copyright: Copyright (c) 2016-2017 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 module voxelman.model.ply; 7 8 import std.algorithm : startsWith; 9 import std.conv : to, parse; 10 import std..string : lineSplitter, stripLeft; 11 12 import voxelman.container.buffer : Buffer; 13 import voxelman.model.utils : Faces, unrollFaces; 14 import voxelman.model.mesh : Mesh; 15 16 enum HEADER_STR = "end_header"; 17 enum VERTEX_STR = "element vertex "; 18 enum FACE_STR = "element face "; 19 20 Vert[] readPlyFile(Vert)(string fileName) 21 { 22 import std.file : read; 23 string data = cast(string)read(fileName); 24 Mesh!Vert mesh = parsePly!Vert(data); 25 return unrollFaces(mesh.vertices, mesh.faces); 26 } 27 28 Mesh!Vert parsePly(Vert)(string fileData) 29 { 30 auto lines = fileData.lineSplitter; 31 32 size_t numVertices; 33 size_t numFaces; 34 35 // parse header 36 while(!lines.empty) 37 { 38 auto line = lines.front; 39 40 if (line.startsWith(HEADER_STR)) 41 { 42 lines.popFront; 43 break; 44 } 45 else if (line.startsWith(VERTEX_STR)) 46 { 47 numVertices = to!size_t(line[VERTEX_STR.length..$]); 48 } 49 else if (line.startsWith(FACE_STR)) 50 { 51 numFaces = to!size_t(line[FACE_STR.length..$]); 52 } 53 54 lines.popFront; 55 } 56 57 Buffer!Vert vertices; 58 59 // parse vertices 60 foreach (i; 0..numVertices) 61 { 62 auto line = lines.front; 63 64 Vert v; 65 v.position.x = parse!float(line); line = stripLeft(line); 66 v.position.y = parse!float(line); line = stripLeft(line); 67 v.position.z = parse!float(line); line = stripLeft(line); 68 v.color.r = parse!ubyte(line); line = stripLeft(line); 69 v.color.g = parse!ubyte(line); line = stripLeft(line); 70 v.color.b = parse!ubyte(line); 71 72 vertices.put(v); 73 74 lines.popFront; 75 } 76 77 Buffer!int faceData; 78 faceData.reserve(numFaces * 4); 79 80 // parse faces 81 foreach (i; 0..numFaces) 82 { 83 auto line = lines.front; 84 85 int numFaceVertices = parse!int(line); 86 faceData.put(numFaceVertices); 87 88 foreach (j; 0..numFaceVertices) 89 { 90 line = stripLeft(line); 91 faceData.put(parse!int(line)); 92 } 93 94 lines.popFront; 95 } 96 97 return Mesh!Vert( 98 vertices.data, 99 Faces(faceData.data, numFaces)); 100 }