/* 3DHOP - 3D Heritage Online Presenter Copyright (c) 2014-2020, Visual Computing Lab, ISTI - CNR All rights reserved. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ var parsePly = (function(){ var canonicTypes = { "char" : "int8", "int8" : "int8", "uchar" : "uint8", "uint8" : "uint8", "short" : "int16", "int16" : "int16", "ushort" : "uint16", "uint16" : "uint16", "int" : "int32", "int32" : "int32", "uint" : "uint32", "uint32" : "uint32", "float" : "float32", "float32" : "float32", "double" : "float64", "float64" : "float64" }; function trim(s) { var r = s; var n = r.length; var i = 0; var blanks = " \n\r\t"; while ((i < n) && (blanks.indexOf(r.charAt(i)) >= 0)) { i++; } r = r.substring(i, r.length); i = r.length - 1; while ((i > 0) && (blanks.indexOf(r.charAt(i)) >= 0)) { i--; } r = r.substring(0, i+1); return r; } function extractHeader(data) { if (!data || !data.view || !data.view.buffer) return null; var u8 = new Uint8Array(data.view.buffer); var endHeaderToken = "end_header"; var header = ""; var found = false; var currC = null; var prevC = null; var pos = data.pos; var p = 0; var n = 0; for (pos=0, n=u8.byteLength; pos= endHeaderToken.length) { p = pos - endHeaderToken.length; if (prevC == "\r") p--; if (header.substring(p, p + endHeaderToken.length) == endHeaderToken) { found = true; break; } } } prevC = currC; } data.pos = pos; if (!found) { return null; } data.pos++; return header; } function splitHeader(header) { var lines = header.split("\n"); var trimmed = [ ]; var tokens = null; var s = null; for (var i=0, n=lines.length; i 0) { for (var j=0, m=tokens.length; j= 3) { info.format = { name : tokens[1], version : tokens[2], binary : (tokens[1].toLowerCase().indexOf("binary") >= 0), littleEndian : ((tokens[1].toLowerCase()) == "binary_little_endian") }; } break; case "comment": info.comments.push(tokens.slice(1)); break; case "element": if (tn >= 3) { elem = { name : tokens[1], count : parseInt(tokens[2]), properties : [ ], propertyMap : { } }; info.elements.push(elem); info.elementMap[elem.name.toLowerCase()] = elem; } break; case "property": if (elem && (tn >= 3)) { prop = { name : tokens[tn-1], type : tokens.slice(1, tn - 1) }; elem.properties.push(prop); elem.propertyMap[prop.name.toLowerCase()] = prop; } break; default: info.others.push(tokens.slice()); break; } } if (!info.format) { return false; } return info; } var tabStr = "\t"; function setupLines(lines, tabs) { for (var i=0, n=lines.length; i 0) { verticesCount = elem.count; props = elem.propertyMap; vertexLines = [ ]; vertexLines.push("function (header, elementInfo, index, element) {"); vertexLines.push(tabStr + "var littleEndian = SpiderGL.Type.LITTLE_ENDIAN;"); vertexLines.push(tabStr + "var sf32 = SpiderGL.Type.SIZEOF_FLOAT32;"); vertexLines.push(tabStr + "var sui8 = SpiderGL.Type.SIZEOF_UINT8;"); vertexLines.push(tabStr + "var offset = index * this._vertexStride;"); vertexLines.push(tabStr + "var view = this._view;"); vertexLines.push(""); ptypes = propertiesTypes(props["x"], props["y"], props["z"]); if (ptypes.length == 1) { hasPosition = true; switch (ptypes[0]) { case "float32": vertexLines.push(tabStr + "view.setFloat32(offset, element.x, littleEndian); offset += sf32;"); vertexLines.push(tabStr + "view.setFloat32(offset, element.y, littleEndian); offset += sf32;"); vertexLines.push(tabStr + "view.setFloat32(offset, element.z, littleEndian); offset += sf32;"); vertexLines.push(""); vertexAttributes["position"] = { size : 3, type : SpiderGL.Type.FLOAT32, offset : vertexStride }; vertexStride += 3 * SpiderGL.Type.SIZEOF_FLOAT32; break; default: break; } } ptypes = propertiesTypes(props["nx"], props["ny"], props["nz"]); if (ptypes.length == 1) { hasNormal = true; switch (ptypes[0]) { case "float32": vertexLines.push(tabStr + "view.setFloat32(offset, element.nx, littleEndian); offset += sf32;"); vertexLines.push(tabStr + "view.setFloat32(offset, element.ny, littleEndian); offset += sf32;"); vertexLines.push(tabStr + "view.setFloat32(offset, element.nz, littleEndian); offset += sf32;"); vertexLines.push(""); vertexAttributes["normal"] = { size : 3, type : SpiderGL.Type.FLOAT32, offset : vertexStride }; vertexStride += 3 * SpiderGL.Type.SIZEOF_FLOAT32; break; default: break; } } ptypes = propertiesTypes(props["red"], props["green"], props["blue"]); if (ptypes.length == 1) { hasColor = true; switch (ptypes[0]) { case "uint8": vertexLines.push(tabStr + "view.setUint8(offset, element.red ); offset += sui8;"); vertexLines.push(tabStr + "view.setUint8(offset, element.green); offset += sui8;"); vertexLines.push(tabStr + "view.setUint8(offset, element.blue ); offset += sui8;"); vertexLines.push(tabStr + "view.setUint8(offset, 255 ); offset += sui8;"); vertexLines.push(""); vertexAttributes["color"] = { size : 4, type : SpiderGL.Type.UINT8, offset : vertexStride, normalized : true }; vertexStride += 4 * SpiderGL.Type.SIZEOF_UINT8; break; case "float32": vertexLines.push(tabStr + "view.setFloat32(offset, element.red, littleEndian); offset += sf32;"); vertexLines.push(tabStr + "view.setFloat32(offset, element.green, littleEndian); offset += sf32;"); vertexLines.push(tabStr + "view.setFloat32(offset, element.blue, littleEndian); offset += sf32;"); vertexLines.push(tabStr + "view.setFloat32(offset, 1.0, littleEndian); offset += sf32;"); vertexLines.push(""); vertexAttributes["color"] = { size : 4, type : SpiderGL.Type.FLOAT32, offset : vertexStride }; vertexStride += 4 * SpiderGL.Type.SIZEOF_FLOAT32; break; default: break; } } ptypes = propertiesTypes(props["texture_u"], props["texture_v"]); if (ptypes.length == 1) { hasTexCoord = true; switch (ptypes[0]) { case "float32": vertexLines.push(tabStr + "view.setFloat32(offset, element.texture_u, littleEndian); offset += sf32;"); vertexLines.push(tabStr + "view.setFloat32(offset, element.texture_v, littleEndian); offset += sf32;"); vertexLines.push(""); vertexAttributes["texturecoord"] = { size : 2, type : SpiderGL.Type.FLOAT32, offset : vertexStride }; vertexStride += 2 * SpiderGL.Type.SIZEOF_FLOAT32; break; default: break; } } vertexLines.push("}"); } var facesCount = 0; var faceLines = null; elem = header.elementMap["face"]; if (elem && elem.count > 0) { facesCount = elem.count; props = elem.propertyMap; faceLines = [ ]; faceLines.push("function (header, elementInfo, index, element) {"); faceLines.push(tabStr + "var littleEndian = SpiderGL.Type.LITTLE_ENDIAN;"); faceLines.push(tabStr + "var sui32 = SpiderGL.Type.SIZEOF_UINT32;"); faceLines.push(tabStr + "var offset = index * 3 * sui32;"); faceLines.push(tabStr + "var view = this._view;"); faceLines.push(""); if (props["vertex_indices"]) { faceLines.push(tabStr + "view.setUint32(offset, element.vertex_indices[0], littleEndian); offset += sui32;"); faceLines.push(tabStr + "view.setUint32(offset, element.vertex_indices[1], littleEndian); offset += sui32;"); faceLines.push(tabStr + "view.setUint32(offset, element.vertex_indices[2], littleEndian); offset += sui32;"); } else if (props["vertex_index"]) { faceLines.push(tabStr + "view.setUint32(offset, element.vertex_index[0], littleEndian); offset += sui32;"); faceLines.push(tabStr + "view.setUint32(offset, element.vertex_index[1], littleEndian); offset += sui32;"); faceLines.push(tabStr + "view.setUint32(offset, element.vertex_index[2], littleEndian); offset += sui32;"); } else { facesCount = 0; } faceLines.push("}"); } this._mesh = null; this._hasPosition = hasPosition; this._hasNormal = hasNormal; this._hasColor = hasColor; this._hasTexCoord = hasTexCoord; this._verticesCount = verticesCount; this._vertexAttributes = vertexAttributes; this._vertexStride = vertexStride; this._vertexBuffer = null; this._handleVertex = emptyFunction; if (vertexStride > 0) { var vertexFuncStr = vertexLines.join("\n"); this._handleVertex = eval("(" + vertexFuncStr + ")"); } this._facesCount = facesCount; this._indexBuffer = null; this._handleFace = emptyFunction; if (facesCount > 0) { var faceFuncStr = faceLines.join("\n"); this._handleFace = eval("(" + faceFuncStr + ")"); } }, onBeginContent : function (header) { }, onBeginElements : function (header, elementInfo) { switch (elementInfo.name) { case "vertex": this._vertexBuffer = new ArrayBuffer(this._verticesCount * this._vertexStride); this._view = new DataView(this._vertexBuffer); this._handleElement = this._handleVertex; break; case "face": this._indexBuffer = new ArrayBuffer(this._facesCount * 3 * SpiderGL.Type.SIZEOF_UINT32); this._view = new DataView(this._indexBuffer); this._handleElement = this._handleFace; break; default: this._view = null; this._handleElement = emptyFunction; break; } }, onElement : function (header, elementInfo, index, element) { // bounding box calculation if (elementInfo.name=="vertex"){ if(element.x < this._boundingBox.min[0]) this._boundingBox.min[0] = element.x; if(element.y < this._boundingBox.min[1]) this._boundingBox.min[1] = element.y; if(element.z < this._boundingBox.min[2]) this._boundingBox.min[2] = element.z; if(element.x > this._boundingBox.max[0]) this._boundingBox.max[0] = element.x; if(element.y > this._boundingBox.max[1]) this._boundingBox.max[1] = element.y; if(element.z > this._boundingBox.max[2]) this._boundingBox.max[2] = element.z; } this._handleElement(header, elementInfo, index, element); }, onEndElements : function (header, elementInfo) { this._view = null; this._handleElement = emptyFunction; }, onEndContent : function () { }, onEnd : function () { if ((this._verticesCount <= 0) && (this._facesCount <= 0)) return; // var gl = this._gl; var modelDescriptor = { version : "0.0.1.0 EXP", meta : { }, data : { vertexBuffers : { }, indexBuffers : { } }, access : { vertexStreams : { }, primitiveStreams : { } }, semantic : { bindings : { }, chunks : { } }, logic : { parts : { } }, control : { }, extra : { } }; var modelVertexBuffers = modelDescriptor.data.vertexBuffers; var modelIndexBuffers = modelDescriptor.data.indexBuffers; var modelVertexStreams = modelDescriptor.access.vertexStreams; var modelPrimitiveStreams = modelDescriptor.access.primitiveStreams; var modelBindings = modelDescriptor.semantic.bindings; var modelChunks = modelDescriptor.semantic.chunks; var modelParts = modelDescriptor.logic.parts; modelDescriptor.extra.boundingBox = this._boundingBox; modelDescriptor.extra.renderMode = this._renderMode; modelDescriptor.extra.hasPosition = this._hasPosition; modelDescriptor.extra.hasNormal = this._hasNormal; modelDescriptor.extra.hasColor = this._hasColor; modelDescriptor.extra.hasTexCoord = this._hasTexCoord; modelDescriptor.extra.textureUrl = this._textureUrl; var maxVerticesCount = (1 << 16) - 1; var baseVertexBufferName = "mainVertexBuffer"; var baseIndexBufferName = "mainIndexBuffer"; var baseBindingName = "mainBinding"; var baseChunkName = "mainChunk"; var basePointStreamName = "vertices"; var baseTriStreamName = "triangles"; var basePartName = "mainPart"; if (this._facesCount > 0) { var littleEndian = SpiderGL.Type.LITTLE_ENDIAN; var indexStride = SpiderGL.Type.SIZEOF_UINT32; var wholeSize = Float64Array.BYTES_PER_ELEMENT; var stride = this._vertexStride; var partCount = stride % wholeSize; var wholeCount = (stride - partCount) / wholeSize; var vertexBufferView = new Uint8Array(this._vertexBuffer); var indexBufferView = new Uint32Array(this._indexBuffer); var chunksCount = 0; var chunkVertexBuffers = [ ]; var chunkVerticesCount = [ ]; var chunkIndexBuffers = [ ]; var chunkIndicesCount = [ ]; var facesLeft = this._facesCount; var currFaceIndex = 0; var indicesBuffer = new Uint32Array(this._facesCount * 3); while (facesLeft > 0) { var verticesMap = new Uint32Array(this._verticesCount); var verticesNew = new Uint32Array(maxVerticesCount); var verticesCount = 0; var indicesCount = 0; var facesCount = 0; while ((verticesCount <= (maxVerticesCount - 3)) && (facesLeft > 0)) { for (var k=0; k<3; ++k, ++currFaceIndex) { var v = indexBufferView[currFaceIndex]; var r = verticesMap[v]; if (!r) { verticesNew[verticesCount++] = v; verticesMap[v] = verticesCount; } indicesBuffer[indicesCount++] = v; } facesLeft--; facesCount++; } if (facesCount <= 0) continue; var chunkVertexBuffer = new ArrayBuffer(verticesCount * stride); var chunkVertexBufferView = new Uint8Array(chunkVertexBuffer); var chunkIndexBuffer = new Uint16Array(indicesCount); for (var i=0; i 0) { var vertexBufferName = baseVertexBufferName; modelVertexBuffers[vertexBufferName] = { typedArray : this._vertexBuffer }; for (var a in this._vertexAttributes) { var attr = this._vertexAttributes[a]; modelVertexStreams[a] = { buffer : vertexBufferName, size : attr.size, type : attr.type, stride : this._vertexStride, offset : attr.offset, normalized : !!attr.normalized }; binding.vertexStreams[a.toUpperCase()] = [a]; } modelPrimitiveStreams[basePointStreamName] = { mode : SpiderGL.Type.POINTS, count : this._verticesCount }; binding.primitiveStreams["POINT"] = [basePointStreamName]; } if ((this._verticesCount > 0) || (this._facesCount > 0)) { modelChunks[baseChunkName] = { techniques : { "common" : { binding : baseBindingName } } }; modelParts[basePartName] = { chunks : [baseChunkName] }; } } this._modelDescriptor = modelDescriptor; } }; function mainImportPly(buffer) { var handler = new PlyHandler(buffer); parsePly(buffer, handler); var modelDescriptor = handler.modelDescriptor; return modelDescriptor; }; return mainImportPly; })();