|
| 1 | +function ThreeJsViewer(){ |
| 2 | + |
| 3 | + this.SELECTED_COLOR = 0xffff00; |
| 4 | + this.UNSELECTED_COLOR = 0xFF0000; |
| 5 | + this.meshes = {}; |
| 6 | + |
| 7 | + this.init = function(modelUrl) { |
| 8 | + |
| 9 | + this.projector = new THREE.Projector(); |
| 10 | + this.size = {width: window.innerWidth - 1, height: window.innerHeight - 1} |
| 11 | + |
| 12 | + this.renderer = new THREE.WebGLRenderer(); |
| 13 | + this.renderer.sortObjects = false; |
| 14 | + this.renderer.setSize( this.size.width, this.size.height); |
| 15 | + |
| 16 | + this.camera = new THREE.TrackballCamera({ |
| 17 | + |
| 18 | + fov: 50, |
| 19 | + aspect: this.size.width / this.size.height, |
| 20 | + near: 1, |
| 21 | + far: 100000, |
| 22 | + |
| 23 | + rotateSpeed: 1.0, |
| 24 | + zoomSpeed: 1.2, |
| 25 | + panSpeed: 0.2, |
| 26 | + |
| 27 | + noZoom: false, |
| 28 | + noPan: false, |
| 29 | + |
| 30 | + staticMoving: false, |
| 31 | + dynamicDampingFactor: 0.3, |
| 32 | + |
| 33 | + minDistance: 0.1, |
| 34 | + maxDistance: 100000, |
| 35 | + |
| 36 | + keys: [ 65, 83, 68 ], // [ rotateKey, zoomKey, panKey ], |
| 37 | + |
| 38 | + domElement: this.renderer.domElement |
| 39 | + |
| 40 | + }); |
| 41 | + this.camera.up = new THREE.Vector3(0, 0, 1); |
| 42 | + this.camera.position = new THREE.Vector3(1, 1, 1); |
| 43 | + this.camera.target.position = new THREE.Vector3(0, 0, 0); |
| 44 | + this.camera.screen.width = this.size.width; |
| 45 | + this.camera.screen.height = this.size.height; |
| 46 | + |
| 47 | + this.scene = new THREE.Scene(); |
| 48 | + |
| 49 | + var light1 = new THREE.DirectionalLight(0xffffff, 2); |
| 50 | + light1.position.x = .5; |
| 51 | + light1.position.y = 1; |
| 52 | + light1.position.z = 2; |
| 53 | + light1.position.normalize(); |
| 54 | + this.scene.addLight(light1); |
| 55 | + |
| 56 | + var light2 = new THREE.DirectionalLight(0x555555, 1); |
| 57 | + light2.position.x = - 2; |
| 58 | + light2.position.y = - 1; |
| 59 | + light2.position.z = - .5; |
| 60 | + light2.position.normalize(); |
| 61 | + this.scene.addLight(light2); |
| 62 | + |
| 63 | + |
| 64 | + var geometryLoader = new THREE.JSONLoader(true); |
| 65 | + this.root = new THREE.Object3D(); |
| 66 | + this.scene.addObject(this.root); |
| 67 | + |
| 68 | + var callback = function(partId) { return function(geometry) { |
| 69 | + var material = new THREE.MeshPhongMaterial({ color: this.UNSELECTED_COLOR }); |
| 70 | + var mesh = new THREE.Mesh(geometry, material); |
| 71 | + mesh.doubleSided = false; |
| 72 | + this.root.addChild(mesh); |
| 73 | + this.meshes[mesh.geometry.id] = partId; |
| 74 | + }.bind(this); }.bind(this); |
| 75 | + |
| 76 | + var texture_path = geometryLoader.extractUrlbase(modelUrl); |
| 77 | + var worker = new Worker(modelUrl); |
| 78 | + worker.onmessage = function ( event ) { |
| 79 | + $.each(event.data, function(index, modelPart){ |
| 80 | + geometryLoader.createModel( modelPart.geometry, callback(modelPart.id), texture_path ); |
| 81 | + }); |
| 82 | + var bb = this.computeBoundingBox(); |
| 83 | + var ext = {x: bb.x[1] - bb.x[0], y: bb.y[1] - bb.y[0], z: bb.z[1] - bb.z[0]}; |
| 84 | + // center mesh |
| 85 | + this.root.position.x = ext.x * -.5 - bb.x[0]; |
| 86 | + this.root.position.y = ext.y * -.5 - bb.y[0]; |
| 87 | + this.root.position.z = ext.z * -.5 - bb.z[0]; |
| 88 | + |
| 89 | + var maxExtent = Math.max.apply(Math, [ext.x, ext.y, ext.z]); |
| 90 | + this.camera.position = new THREE.Vector3(maxExtent, maxExtent, maxExtent); |
| 91 | + |
| 92 | + // TODO: adjust clipping |
| 93 | + geometryLoader.onLoadComplete(); |
| 94 | + }.bind(this); |
| 95 | + geometryLoader.onLoadStart(); |
| 96 | + worker.postMessage( new Date().getTime() ); |
| 97 | + |
| 98 | + this.renderer.domElement.addEventListener('mousedown', this.onMouseDown.bind(this), false); |
| 99 | + document.body.appendChild(this.renderer.domElement); |
| 100 | + this.onclick = function(){}; |
| 101 | + }; |
| 102 | + |
| 103 | + this.computeBoundingBox = function(){ |
| 104 | + this.root.children[0].geometry.computeBoundingBox(); |
| 105 | + var initialBB = this.root.children[0].geometry.boundingBox; |
| 106 | + var bb = {x: [initialBB.x[0], initialBB.x[1]], y: [initialBB.y[0], initialBB.y[1]], z: [initialBB.z[0], initialBB.z[1]]}; |
| 107 | + THREE.SceneUtils.traverseHierarchy(this.root, function(object){ |
| 108 | + object.geometry.computeBoundingBox(); |
| 109 | + $.each(['x', 'y', 'z'], function(index, dimension){ |
| 110 | + bb[dimension][0] = Math.min(bb[dimension][0], object.geometry.boundingBox[dimension][0]); |
| 111 | + bb[dimension][1] = Math.max(bb[dimension][1], object.geometry.boundingBox[dimension][1]); |
| 112 | + }); |
| 113 | + |
| 114 | + }); |
| 115 | + return bb; |
| 116 | + }; |
| 117 | + |
| 118 | + this.onMouseDown = function(event) { |
| 119 | + event.preventDefault(); |
| 120 | + |
| 121 | + var mouse = new THREE.Vector3(0, 0, 0); |
| 122 | + mouse.x = ( event.clientX / this.size.width ) * 2 - 1; |
| 123 | + mouse.y = - ( event.clientY / this.size.height ) * 2 + 1; |
| 124 | + |
| 125 | + this.projector.unprojectVector(mouse, this.camera); |
| 126 | + |
| 127 | + var ray = new THREE.Ray(this.camera.position, mouse.subSelf(this.camera.position).normalize()); |
| 128 | + |
| 129 | + var intersects = ray.intersectScene(this.scene); |
| 130 | + if (intersects.length > 0) { |
| 131 | + if (this.selected != intersects[0].object) { |
| 132 | + if (this.selected) this.selected.materials[0].color.setHex(this.UNSELECTED_COLOR); |
| 133 | + this.selected = intersects[0].object; |
| 134 | + this.selected.materials[0].color.setHex(this.SELECTED_COLOR); |
| 135 | + } |
| 136 | + } else { |
| 137 | + if (this.selected) this.selected.materials[0].color.setHex(this.UNSELECTED_COLOR); |
| 138 | + this.selected = null; |
| 139 | + } |
| 140 | + this.onClick(this.selected ? this.meshes[this.selected.geometry.id] : 'nothing'); |
| 141 | + }; |
| 142 | + |
| 143 | + this.animate = function() { |
| 144 | + // Include examples/js/RequestAnimationFrame.js for cross-browser compatibility. |
| 145 | + requestAnimationFrame(this.animate.bind(this)); |
| 146 | + this.render(); |
| 147 | + }; |
| 148 | + |
| 149 | + this.render = function() { |
| 150 | + this.renderer.render(this.scene,this.camera); |
| 151 | + }; |
| 152 | +} |
0 commit comments