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