import { Points, Mesh, MeshBasicMaterial, VertexColors, TrianglesDrawMode } from 'three' import { scene } from '../renderer' import DRACOLoader from '../../util/vendor/DRACOLoader' import GeometryHelper from '../../util/vendor/geometryHelper' DRACOLoader.setDecoderPath('/assets/js/vendor/draco/') const dracoLoader = new DRACOLoader() DRACOLoader.getDecoderModule() export function load(name) { dracoLoader.load('/assets/data/faces/' + name + '.drc', (geometry) => { geometry.computeVertexNormals() const material = new MeshBasicMaterial({ vertexColors: VertexColors }) const mesh = new Mesh(geometry, material) scene.add(mesh) console.log(name) // Release the cached decoder module. DRACOLoader.releaseDecoderModule() }) } export function update(name) { load(name) } function setDequantizationForMaterial(material, bufferGeometry) { material.onBeforeCompile = (shader) => { // Add uniform variables needed for dequantization. const posAttribute = bufferGeometry.attributes.position shader.uniforms.normConstant = { value: posAttribute.maxRange / (1 << posAttribute.numQuantizationBits) } shader.uniforms.minPos = { value: posAttribute.minValues } shader.vertexShader = 'uniform float maxRange;\n' + 'uniform float normConstant;\n' + 'uniform vec3 minPos;\n' + shader.vertexShader shader.vertexShader = shader.vertexShader.replace( '#include ', 'vec3 transformed = minPos + position * normConstant;' ) } } export function loadFromFile(buf) { // Enable logging to console output. dracoLoader.setVerbosity(1) // To use triangle strips use: // dracoLoader.setDrawMode(THREE.TriangleStripDrawMode) dracoLoader.setDrawMode(TrianglesDrawMode) // Skip dequantization of the position attribute. It will be done on the GPU. dracoLoader.setSkipDequantization('position', true) dracoLoader.decodeDracoFile(buf, (bufferGeometry) => { // if (dracoLoader.decode_time !== undefined) { // fileDisplayArea.innerText = 'Decode time = ' + dracoLoader.decode_time + '\n' + // 'Import time = ' + dracoLoader.import_time // } const material = new MeshBasicMaterial({ vertexColors: VertexColors }) material.wireframe = true // If the position attribute is quantized, modify the material to perform // dequantization on the GPU. if (bufferGeometry.attributes.position.isQuantized) { setDequantizationForMaterial(material, bufferGeometry) } let geometry // Point cloud does not have face indices. if (bufferGeometry.index === null) { geometry = new Points(bufferGeometry, material) } else { if (bufferGeometry.attributes.normal === undefined) { const geometryHelper = new GeometryHelper() geometryHelper.computeVertexNormals(bufferGeometry) } geometry = new Mesh(bufferGeometry, material) geometry.drawMode = dracoLoader.drawMode } // Compute range of the geometry coordinates for proper rendering. bufferGeometry.computeBoundingBox() if (bufferGeometry.attributes.position.isQuantized) { // If the geometry is quantized, transform the bounding box to the dequantized // coordinates. const posAttribute = bufferGeometry.attributes.position const normConstant = posAttribute.maxRange / (1 << posAttribute.numQuantizationBits) const minPos = posAttribute.minValues bufferGeometry.boundingBox.max.x = minPos[0] + bufferGeometry.boundingBox.max.x * normConstant bufferGeometry.boundingBox.max.y = minPos[1] + bufferGeometry.boundingBox.max.y * normConstant bufferGeometry.boundingBox.max.z = minPos[2] + bufferGeometry.boundingBox.max.z * normConstant bufferGeometry.boundingBox.min.x = minPos[0] + bufferGeometry.boundingBox.min.x * normConstant bufferGeometry.boundingBox.min.y = minPos[1] + bufferGeometry.boundingBox.min.y * normConstant bufferGeometry.boundingBox.min.z = minPos[2] + bufferGeometry.boundingBox.min.z * normConstant } const sizeX = bufferGeometry.boundingBox.max.x - bufferGeometry.boundingBox.min.x const sizeY = bufferGeometry.boundingBox.max.y - bufferGeometry.boundingBox.min.y const sizeZ = bufferGeometry.boundingBox.max.z - bufferGeometry.boundingBox.min.z const diagonalSize = Math.sqrt(sizeX * sizeX + sizeY * sizeY + sizeZ * sizeZ) const scale = 1.0 / diagonalSize const midX = (bufferGeometry.boundingBox.min.x + bufferGeometry.boundingBox.max.x) / 2 const midY = (bufferGeometry.boundingBox.min.y + bufferGeometry.boundingBox.max.y) / 2 const midZ = (bufferGeometry.boundingBox.min.z + bufferGeometry.boundingBox.max.z) / 2 geometry.scale.multiplyScalar(scale) geometry.position.x = -midX * scale geometry.position.y = -midY * scale geometry.position.z = -midZ * scale // geometry.castShadow = true // geometry.receiveShadow = true const selectedObject = scene.getObjectByName("my_mesh") scene.remove(selectedObject) geometry.name = "my_mesh" scene.add(geometry) }) }