|
1 | 1 | function ThreeJsViewer(){ |
2 | 2 |
|
3 | | - this.SELECTED_COLOR = 0xffff00; |
4 | | - this.UNSELECTED_COLOR = 0xFF0000; |
5 | | - this.meshes = {}; |
| 3 | + this.SELECTED_COLOR = 0xffff00; |
| 4 | + this.UNSELECTED_COLOR = 0xFF0000; |
| 5 | + this.meshes = {}; |
6 | 6 |
|
7 | | - this.init = function(container) { |
8 | | - |
9 | | - this.projector = new THREE.Projector(); |
10 | | - this.size = {width: container.width(), height: container.height()}; |
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 | | - this.root = new THREE.Object3D(); |
49 | | - this.scene.addObject(this.root); |
50 | | - |
51 | | - var light1 = new THREE.DirectionalLight(0xffffff, 2); |
52 | | - light1.position.x = .5; |
53 | | - light1.position.y = 1; |
54 | | - light1.position.z = 2; |
55 | | - light1.position.normalize(); |
56 | | - this.scene.addLight(light1); |
57 | | - |
58 | | - var light2 = new THREE.DirectionalLight(0x555555, 1); |
59 | | - light2.position.x = - 2; |
60 | | - light2.position.y = - 1; |
61 | | - light2.position.z = - .5; |
62 | | - light2.position.normalize(); |
63 | | - this.scene.addLight(light2); |
64 | | - |
65 | | - container.click(this.onMouseDown.bind(this)); |
66 | | - container.append(this.renderer.domElement); |
67 | | - this.container = container; |
68 | | - this.onclick = function(){}; |
69 | | - }; |
70 | | - |
71 | | - this.loadModel = function(modelUrl){ |
72 | | - var geometryLoader = new THREE.JSONLoader(true); |
73 | | - |
74 | | - var callback = function(partId) { return function(geometry) { |
75 | | - var material = new THREE.MeshPhongMaterial({ color: this.UNSELECTED_COLOR }); |
76 | | - var mesh = new THREE.Mesh(geometry, material); |
77 | | - mesh.doubleSided = false; |
78 | | - this.root.addChild(mesh); |
79 | | - this.meshes[mesh.geometry.id] = partId; |
80 | | - }.bind(this); }.bind(this); |
81 | | - |
82 | | - var texture_path = geometryLoader.extractUrlbase(modelUrl); |
83 | | - var worker = new Worker(modelUrl); |
84 | | - worker.onmessage = function ( event ) { |
85 | | - $.each(event.data, function(index, modelPart){ |
86 | | - geometryLoader.createModel( modelPart.geometry, callback(modelPart.id), texture_path ); |
87 | | - }); |
88 | | - var bb = this.computeBoundingBox(); |
89 | | - var ext = {x: bb.x[1] - bb.x[0], y: bb.y[1] - bb.y[0], z: bb.z[1] - bb.z[0]}; |
90 | | - // center mesh |
91 | | - this.root.position.x = ext.x * -.5 - bb.x[0]; |
92 | | - this.root.position.y = ext.y * -.5 - bb.y[0]; |
93 | | - this.root.position.z = ext.z * -.5 - bb.z[0]; |
94 | | - |
95 | | - var maxExtent = Math.max.apply(Math, [ext.x, ext.y, ext.z]); |
96 | | - this.camera.position = new THREE.Vector3(maxExtent, maxExtent, maxExtent); |
97 | | - |
98 | | - // TODO: adjust clipping |
99 | | - geometryLoader.onLoadComplete(); |
100 | | - }.bind(this); |
101 | | - geometryLoader.onLoadStart(); |
102 | | - worker.postMessage( new Date().getTime() ); |
103 | | - }; |
104 | | - this.clearModel = function(){ |
105 | | - this.scene.removeChild(this.root); |
106 | | - this.root = new THREE.Object3D(); |
107 | | - this.scene.addObject(this.root); |
108 | | - this.meshes = {}; |
109 | | - }; |
110 | | - this.computeBoundingBox = function(){ |
111 | | - this.root.children[0].geometry.computeBoundingBox(); |
112 | | - var initialBB = this.root.children[0].geometry.boundingBox; |
113 | | - var bb = {x: [initialBB.x[0], initialBB.x[1]], y: [initialBB.y[0], initialBB.y[1]], z: [initialBB.z[0], initialBB.z[1]]}; |
114 | | - THREE.SceneUtils.traverseHierarchy(this.root, function(object){ |
115 | | - object.geometry.computeBoundingBox(); |
116 | | - $.each(['x', 'y', 'z'], function(index, dimension){ |
117 | | - bb[dimension][0] = Math.min(bb[dimension][0], object.geometry.boundingBox[dimension][0]); |
118 | | - bb[dimension][1] = Math.max(bb[dimension][1], object.geometry.boundingBox[dimension][1]); |
119 | | - }); |
| 7 | + this.init = function(container) { |
| 8 | + |
| 9 | + this.projector = new THREE.Projector(); |
| 10 | + this.size = {width: container.width(), height: container.height()}; |
| 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, |
120 | 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 | + this.root = new THREE.Object3D(); |
| 49 | + this.scene.addObject(this.root); |
| 50 | + |
| 51 | + var light1 = new THREE.DirectionalLight(0xffffff, 2); |
| 52 | + light1.position.x = .5; |
| 53 | + light1.position.y = 1; |
| 54 | + light1.position.z = 2; |
| 55 | + light1.position.normalize(); |
| 56 | + this.scene.addLight(light1); |
| 57 | + |
| 58 | + var light2 = new THREE.DirectionalLight(0x555555, 1); |
| 59 | + light2.position.x = - 2; |
| 60 | + light2.position.y = - 1; |
| 61 | + light2.position.z = - .5; |
| 62 | + light2.position.normalize(); |
| 63 | + this.scene.addLight(light2); |
| 64 | + |
| 65 | + container.click(this.onMouseDown.bind(this)); |
| 66 | + container.append(this.renderer.domElement); |
| 67 | + this.container = container; |
| 68 | + this.onclick = function(){}; |
| 69 | + }; |
| 70 | + |
| 71 | + this.loadModel = function(modelUrl){ |
| 72 | + var geometryLoader = new THREE.JSONLoader(true); |
| 73 | + |
| 74 | + var callback = function(partId) { return function(geometry) { |
| 75 | + var material = new THREE.MeshPhongMaterial({ color: this.UNSELECTED_COLOR }); |
| 76 | + var mesh = new THREE.Mesh(geometry, material); |
| 77 | + mesh.doubleSided = false; |
| 78 | + this.root.addChild(mesh); |
| 79 | + this.meshes[mesh.geometry.id] = partId; |
| 80 | + }.bind(this); }.bind(this); |
| 81 | + |
| 82 | + var texture_path = geometryLoader.extractUrlbase(modelUrl); |
| 83 | + var worker = new Worker(modelUrl); |
| 84 | + worker.onmessage = function ( event ) { |
| 85 | + $.each(event.data, function(index, modelPart){ |
| 86 | + geometryLoader.createModel( modelPart.geometry, callback(modelPart.id), texture_path ); |
| 87 | + }); |
| 88 | + var bb = this.computeBoundingBox(); |
| 89 | + var ext = {x: bb.x[1] - bb.x[0], y: bb.y[1] - bb.y[0], z: bb.z[1] - bb.z[0]}; |
| 90 | + // center mesh |
| 91 | + this.root.position.x = ext.x * -.5 - bb.x[0]; |
| 92 | + this.root.position.y = ext.y * -.5 - bb.y[0]; |
| 93 | + this.root.position.z = ext.z * -.5 - bb.z[0]; |
| 94 | + |
| 95 | + var maxExtent = Math.max.apply(Math, [ext.x, ext.y, ext.z]); |
| 96 | + this.camera.position = new THREE.Vector3(maxExtent, maxExtent, maxExtent); |
| 97 | + |
| 98 | + // TODO: adjust clipping |
| 99 | + geometryLoader.onLoadComplete(); |
| 100 | + }.bind(this); |
| 101 | + geometryLoader.onLoadStart(); |
| 102 | + worker.postMessage( new Date().getTime() ); |
| 103 | + }; |
| 104 | + this.clearModel = function(){ |
| 105 | + this.scene.removeChild(this.root); |
| 106 | + this.root = new THREE.Object3D(); |
| 107 | + this.scene.addObject(this.root); |
| 108 | + this.meshes = {}; |
| 109 | + }; |
| 110 | + this.computeBoundingBox = function(){ |
| 111 | + this.root.children[0].geometry.computeBoundingBox(); |
| 112 | + var initialBB = this.root.children[0].geometry.boundingBox; |
| 113 | + var bb = {x: [initialBB.x[0], initialBB.x[1]], y: [initialBB.y[0], initialBB.y[1]], z: [initialBB.z[0], initialBB.z[1]]}; |
| 114 | + THREE.SceneUtils.traverseHierarchy(this.root, function(object){ |
| 115 | + object.geometry.computeBoundingBox(); |
| 116 | + $.each(['x', 'y', 'z'], function(index, dimension){ |
| 117 | + bb[dimension][0] = Math.min(bb[dimension][0], object.geometry.boundingBox[dimension][0]); |
| 118 | + bb[dimension][1] = Math.max(bb[dimension][1], object.geometry.boundingBox[dimension][1]); |
121 | 119 | }); |
122 | | - return bb; |
123 | | - }; |
124 | 120 |
|
125 | | - this.onMouseDown = function(event) { |
126 | | - event.preventDefault(); |
| 121 | + }); |
| 122 | + return bb; |
| 123 | + }; |
| 124 | + |
| 125 | + this.onMouseDown = function(event) { |
| 126 | + event.preventDefault(); |
127 | 127 |
|
128 | | - var mouse = new THREE.Vector3(0, 0, 0); |
129 | | - mouse.x = (event.pageX - this.container.offset().left) / this.size.width * 2 - 1; // ( event.clientX / this.size.width ) * 2 - 1; |
130 | | - mouse.y = - (event.pageY - this.container.offset().top) / this.size.height * 2 + 1; // - ( event.clientY / this.size.height ) * 2 + 1; |
| 128 | + var mouse = new THREE.Vector3(0, 0, 0); |
| 129 | + mouse.x = (event.pageX - this.container.offset().left) / this.size.width * 2 - 1; // ( event.clientX / this.size.width ) * 2 - 1; |
| 130 | + mouse.y = - (event.pageY - this.container.offset().top) / this.size.height * 2 + 1; // - ( event.clientY / this.size.height ) * 2 + 1; |
131 | 131 |
|
132 | | - this.projector.unprojectVector(mouse, this.camera); |
| 132 | + this.projector.unprojectVector(mouse, this.camera); |
133 | 133 |
|
134 | | - var ray = new THREE.Ray(this.camera.position, mouse.subSelf(this.camera.position).normalize()); |
| 134 | + var ray = new THREE.Ray(this.camera.position, mouse.subSelf(this.camera.position).normalize()); |
135 | 135 |
|
136 | | - var intersects = ray.intersectScene(this.scene); |
137 | | - if (intersects.length > 0) { |
138 | | - if (this.selected != intersects[0].object) { |
139 | | - if (this.selected) this.selected.materials[0].color.setHex(this.UNSELECTED_COLOR); |
140 | | - this.selected = intersects[0].object; |
141 | | - this.selected.materials[0].color.setHex(this.SELECTED_COLOR); |
142 | | - } |
143 | | - } else { |
| 136 | + var intersects = ray.intersectScene(this.scene); |
| 137 | + if (intersects.length > 0) { |
| 138 | + if (this.selected != intersects[0].object) { |
144 | 139 | if (this.selected) this.selected.materials[0].color.setHex(this.UNSELECTED_COLOR); |
145 | | - this.selected = null; |
| 140 | + this.selected = intersects[0].object; |
| 141 | + this.selected.materials[0].color.setHex(this.SELECTED_COLOR); |
146 | 142 | } |
147 | | - this.onClick(this.selected ? this.meshes[this.selected.geometry.id] : null); |
148 | | - }; |
149 | | - |
150 | | - this.animate = function() { |
151 | | - // Include examples/js/RequestAnimationFrame.js for cross-browser compatibility. |
152 | | - requestAnimationFrame(this.animate.bind(this)); |
153 | | - this.render(); |
154 | | - }; |
155 | | - |
156 | | - this.render = function() { |
157 | | - this.renderer.render(this.scene,this.camera); |
158 | | - }; |
| 143 | + } else { |
| 144 | + if (this.selected) this.selected.materials[0].color.setHex(this.UNSELECTED_COLOR); |
| 145 | + this.selected = null; |
| 146 | + } |
| 147 | + this.onClick(this.selected ? this.meshes[this.selected.geometry.id] : null); |
| 148 | + }; |
| 149 | + |
| 150 | + this.animate = function() { |
| 151 | + // Include examples/js/RequestAnimationFrame.js for cross-browser compatibility. |
| 152 | + requestAnimationFrame(this.animate.bind(this)); |
| 153 | + this.render(); |
| 154 | + }; |
| 155 | + |
| 156 | + this.render = function() { |
| 157 | + this.renderer.render(this.scene,this.camera); |
| 158 | + }; |
159 | 159 | } |
0 commit comments