const THREE = require('three'); const toBufferGeometry = require('../utilities').toBufferGeometry; const createMeshForGeometry = (geometryIn, materialIn, options) => { // First copy the geometry let geometry = toBufferGeometry(geometryIn, options); let isTransparent = false; if (1.0 > options.opacity) isTransparent = true; let material = undefined; if (geometry._video === undefined) { const morphTargets = options.localTimeEnabled || options.localMorphColour; if (materialIn) { material = materialIn; material.morphTargets = morphTargets; material.morphNormals = options.localTimeEnabled; } else { if (geometry instanceof THREE.BufferGeometry && geometry.attributes.color === undefined) { material = new THREE.MeshPhongMaterial({ color : options.colour, morphTargets : morphTargets, morphNormals : options.localTimeEnabled, transparent : isTransparent, opacity : options.opacity, side : THREE.DoubleSide }); } else { material = new THREE.MeshPhongMaterial({ color : options.colour, morphTargets : morphTargets, morphNormals : options.localTimeEnabled, vertexColors : THREE.VertexColors, transparent : isTransparent, opacity : options.opacity, side : THREE.DoubleSide }); } } //material = PhongToToon(material); if (options.localMorphColour && geometry.morphAttributes[ "color" ]) { material.onBeforeCompile = (require("./augmentShader").augmentMorphColor)(); } } else { let videoTexture = geometry._video.createCanvasVideoTexture(); material = new THREE.MeshBasicMaterial({ morphTargets : options.localTimeEnabled, color : new THREE.Color(1, 1, 1), transparent : isTransparent, opacity : options.opacity, map : videoTexture, side : THREE.DoubleSide }); this.videoHandler = geometry._video; } return new THREE.Mesh(geometry, material); } /** * Provides an object which stores geometry and provides method which controls its animations. * This is created when a valid json file containging geometry is read into a {@link Zinc.Scene} * object. * * @class * @author Alan Wu * @return {Geometry} */ const Geometry = function () { (require('./zincObject').ZincObject).call(this); // THREE.Geometry or THREE.BufferGeometry this.videoHandler = undefined; this.isGeometry = true; /** * Create the mesh for rendering * * @param {THREE.Geomtry} geometryIn - Geometry to be rendered. * @param {THREE.Material} materialIn - Material to be set for the geometry. * @param {Object} options - Provide various options * @param {THREE.Color} options.colour - colour to be set for the geometry * @param {Boolean} options.localTimeEnabled - A flag to indicate either the geometry is * time dependent. * @param {Boolean} options.localMorphColour - A flag to indicate either the colour is * time dependent. * @param {Number} options.opacity - Opacity to be set for the geometry */ this.createMesh = (geometryIn, materialIn, options) => { //Skip if there is a morph already if (this.morph && this.morph.geometry && (geometryIn != undefined)) return; const mesh = createMeshForGeometry(geometryIn, materialIn, options); this.setMesh(mesh, options.localTimeEnabled, options.localMorphColour); } /** * Calculate the UV for texture rendering. */ this.calculateUVs = () => { //Multilayers this.geometry.computeBoundingBox(); const max = this.geometry.boundingBox.max, min = this.geometry.boundingBox.min; const offset = new THREE.Vector2(0 - min.x, 0 - min.y); const range = new THREE.Vector2(max.x - min.x, max.y - min.y); this.geometry.faceVertexUvs[0] = []; for (let i = 0; i < this.geometry.faces.length ; i++) { const v1 = this.geometry.vertices[this.geometry.faces[i].a]; const v2 = this.geometry.vertices[this.geometry.faces[i].b]; const v3 = this.geometry.vertices[this.geometry.faces[i].c]; geometry.faceVertexUvs[0].push( [ new THREE.Vector2((v1.x + offset.x)/range.x ,(v1.y + offset.y)/range.y), new THREE.Vector2((v2.x + offset.x)/range.x ,(v2.y + offset.y)/range.y), new THREE.Vector2((v3.x + offset.x)/range.x ,(v3.y + offset.y)/range.y) ]); } geometry.uvsNeedUpdate = true; } /** * Handle transparent mesh, create a clone for backside rendering if it is * transparent. */ this.checkTransparentMesh = function() { this._lod.checkTransparentMesh(); } /** * Set wireframe display for this geometry. * * @param {Boolean} wireframe - Flag to turn on/off wireframe display. */ this.setWireframe = wireframe => { this.morph.material.wireframe = wireframe; } /** * Edit Vertice in index. */ this.editVertices = function(coords, i) { if (coords && coords.length) { let mesh = this.getMorph(); const attribute = mesh.geometry.getAttribute("position"); if (!mesh || 0 > i) { return; } else { let index = i * 3; coords.forEach(coord => { attribute.array[index++] = coord[0]; attribute.array[index++] = coord[1]; attribute.array[index++] = coord[2]; }); attribute.needsUpdate = true; mesh.geometry.computeBoundingBox(); mesh.geometry.computeBoundingSphere(); this.boundingBoxUpdateRequired = true; } } } } Geometry.prototype = Object.create((require('./zincObject').ZincObject).prototype); exports.Geometry = Geometry;