1 /** 2 * potree.js 3 * http://potree.org 4 * 5 * Copyright 2012, Markus Sch�tz 6 * Licensed under the GPL Version 2 or later. 7 * - http://potree.org/wp/?page_id=7 8 * - http://www.gnu.org/licenses/gpl-3.0.html 9 * 10 */ 11 12 /** 13 * List of possible ply file types 14 * 15 * @class 16 */ 17 function PlyFileType(){} 18 PlyFileType.ASCII = "ascii"; 19 PlyFileType.BINARY_LITTLE_ENDIAN = "binary_little_endian"; 20 PlyFileType.BINARY_BIG_ENDIAN = "binary_big_endian"; 21 22 /** 23 * represents a property definition in a ply file 24 * 25 * @class 26 * 27 */ 28 function PlyProperty(name, type){ 29 this.name = name; 30 this.type = type; 31 } 32 33 function PlyPropertyDataType(name, size){ 34 this.name = name; 35 this.size = size; 36 }; 37 38 /** 39 * represent an element in a ply file. (such as vertex/face/...) 40 * 41 * @class 42 * 43 */ 44 function PlyElement(name){ 45 this.name = name; 46 this.properties = new Array(); 47 this.size = 0; 48 } 49 50 PlyPropertyDataType.char = new PlyPropertyDataType("char", 1); 51 PlyPropertyDataType.uchar = new PlyPropertyDataType("uchar", 1); 52 PlyPropertyDataType.short = new PlyPropertyDataType("short", 2); 53 PlyPropertyDataType.ushort = new PlyPropertyDataType("ushort", 2); 54 PlyPropertyDataType.int = new PlyPropertyDataType("int", 4); 55 PlyPropertyDataType.uint = new PlyPropertyDataType("uint", 4); 56 PlyPropertyDataType.float = new PlyPropertyDataType("float", 4); 57 PlyPropertyDataType.double = new PlyPropertyDataType("double", 8); 58 59 /** 60 * holds ply header data 61 * 62 * @class 63 * 64 */ 65 function PlyHeader(){ 66 this.type = null; 67 this.byteSize = 0; 68 this.elements = new Array(); 69 } 70 71 /** 72 * Contains ply header and a buffer with byte-data 73 * 74 * @class 75 */ 76 function PlyFile(buffer){ 77 this.buffer = buffer; 78 this.header = new PlyHeader(); 79 } 80 81 /** 82 * This listener is called while a ply file is beeing loaded 83 */ 84 function PlyLoaderListener(){ 85 86 } 87 88 PlyLoaderListener.prototype.finishedLoading = function(pointcloud){ 89 90 }; 91 92 PlyLoaderListener.prototype.pointsLoaded = function(numLoadedPoints, numPoints){ 93 94 }; 95 96 PlyLoaderListener.prototype.onProgress = function(progress){ 97 98 }; 99 100 /** 101 * 102 * @class 103 */ 104 function PlyLoader(){ 105 106 } 107 108 /** 109 * Loads source in a background task. 110 * Once loading is finished, listener.finishedLoading(pointCloud) is called. 111 */ 112 PlyLoader.load = function(source, listener){ 113 var plyFile = new PlyFile(); 114 var worker = new Worker("src/loader/PlyLoaderWorker.js"); 115 worker.onmessage = function(event){ 116 if(event.data.type == "header"){ 117 plyFile.header = PlyLoader.parseHeader(event.data.header); 118 }else if(event.data.type == "progress"){ 119 listener.pointsLoaded(event.data.pointsLoaded, plyFile.header.elements[0].size); 120 }else if(event.data.type == "result"){ 121 var pointBuffer = event.data.buffer; 122 var aabb = event.data.aabb; 123 var vertexElement = plyFile.header.elements[0]; 124 var pointAttributes = PlyLoader.pointAttributesFromProperties(vertexElement.properties, true); 125 var numPoints = pointBuffer.byteLength / pointAttributes.byteSize; 126 var pointCloud = new PointCloud("test", pointAttributes); 127 pointCloud.setVertexBufferData(pointBuffer); 128 pointCloud.size = numPoints; 129 pointCloud.aabb = new AABB(); 130 var min = V3.$(aabb.lx, aabb.ly, aabb.lz); 131 var max = V3.$(aabb.ux, aabb.uy, aabb.uz); 132 pointCloud.aabb.setDimensionByMinMax(min, max); 133 134 listener.finishedLoading(pointCloud); 135 }else if(event.data.type == "log"){ 136 console.log(event.data.message); 137 }else{ 138 alert(event.data); 139 } 140 }; 141 worker.postMessage(source); 142 }; 143 144 PlyLoader.parseHeader = function PlyLoader_parseHeader(header){ 145 var lines = header.split('\n'); 146 var plyHeader = new PlyHeader(); 147 plyHeader.byteSize = header.length; 148 var vertexElement = new PlyElement("vertex"); 149 plyHeader.elements.push(vertexElement); 150 151 var formatPattern = /^format (ascii|binary_little_endian).*/; 152 var elementPattern = /element (\w*) (\d*)/; 153 var propertyPattern = /property (char|uchar|short|ushort|int|uint|float|double) (\w*)/; 154 155 while(lines.length > 0){ 156 //for(var i = 0; i < lines.length; i++){ 157 var line = lines.shift(); 158 159 if(line == "ply"){ 160 }else if(line.search(formatPattern) >= 0){ 161 var result = line.match(formatPattern); 162 plyHeader.type = PlyFileType[result[1].toUpperCase()]; 163 }else if(line.search(elementPattern) >= 0){ 164 var result = line.match(elementPattern); 165 var name = result[1]; 166 var count = parseInt(result[2]); 167 168 if(name != "vertex"){ 169 throw "As of now, only ply files with 'vertex' as the first element are supported."; 170 } 171 172 vertexElement.size = count; 173 // handle properties 174 while(lines[0].search(propertyPattern) >= 0){ 175 var result = lines.shift().match(propertyPattern); 176 var name = result[2]; 177 var type = PlyPropertyDataType[result[1]]; 178 var property = new PlyProperty(name, type); 179 vertexElement.properties.push(property); 180 } 181 break; 182 } 183 } 184 185 return plyHeader; 186 }; 187 188 PlyLoader.pointAttributesFromProperties = function PlyLoader_pointAttributesFromProperties(properties, forTargetBuffer){ 189 if(forTargetBuffer === undefined){ 190 forTargetBuffer = false; 191 } 192 var pointAttributes = new PointAttributes(); 193 var i = 0; 194 while(i < properties.length){ 195 var property = properties[i]; 196 197 if(property.name == "x"){ 198 var p0 = property; 199 var p1 = properties[i+1]; 200 var p2 = properties[i+2]; 201 202 if(p1.name != "y" || p2.name != "z"){ 203 throw "unsupported ply format"; 204 } 205 206 if((p0.type.name + p1.type.name + p2.type.name) != "floatfloatfloat"){ 207 throw "unsupported ply format"; 208 } 209 210 pointAttributes.add(PointAttribute.POSITION_CARTESIAN); 211 i+=3; 212 }else if(property.name == "nx"){ 213 var p0 = property; 214 var p1 = properties[i+1]; 215 var p2 = properties[i+2]; 216 217 if(p1.name != "ny" || p2.name != "nz"){ 218 throw "unsupported ply format"; 219 } 220 221 if((p0.type.name + p1.type.name + p2.type.name) != "floatfloatfloat"){ 222 throw "unsupported ply format"; 223 } 224 225 pointAttributes.add(PointAttribute.NORMAL_FLOATS); 226 i+=3; 227 }else if(property.name == "red"){ 228 var c0 = property; 229 var c1 = properties[i+1]; 230 var c2 = properties[i+2]; 231 232 if(c1.name != "green" || c2.name != "blue"){ 233 throw "unsupported ply format"; 234 } 235 236 if((c0.type.name + c1.type.name + c2.type.name) != "ucharucharuchar"){ 237 throw "unsupported ply format"; 238 } 239 240 if(forTargetBuffer){ 241 pointAttributes.add(PointAttribute.RGBA_PACKED); 242 }else{ 243 pointAttributes.add(PointAttribute.RGB_PACKED); 244 } 245 i+=3; 246 }else{ 247 248 if(!forTargetBuffer){ 249 var attribute = new PointAttribute(PointAttributeNames.FILLER, 250 PointAttributeTypes.DATA_TYPE_INT8, property.size); 251 pointAttributes.add(attribute); 252 } 253 i++; 254 } 255 } 256 257 return pointAttributes; 258 }; 259 260