1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
|
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - loaders - VRML loader</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<canvas class="3d_viewer" file="Node5.net_2_PCB"></canvas>
<div id="overlay">
<div id="text">Loading</div>
</div>
<script type="importmap">
{
"imports": {
"three": "./three.module.js"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import Stats from './stats.module.js';
import { OrbitControls } from './OrbitControls.js';
import { VRMLLoader } from './VRMLLoader.js';
// import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
window.addEventListener( 'resize', onWindowResize );
window.addEventListener('mousedown', onMouseDown);
window.addEventListener("touchstart", onMouseDown);
var canvases = document.getElementsByClassName('3d_viewer');
var canvas = canvases[0];
let camera, scene, renderer, stats, controls, loader, vrmlScene, model;
var spin = true;
/* // XYZ vector indicators
const axesHelper = new THREE.AxesHelper( 5 );
scene.add( axesHelper );
*/
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 10, 1e10 );
camera.position.set( - 10, 5, 10 );
scene = new THREE.Scene();
scene.add( camera );
// light
const ambientLight = new THREE.AmbientLight( 0xffffff, 1.2 );
scene.add( ambientLight );
const dirLight = new THREE.DirectionalLight( 0xffffff, 2.0 );
dirLight.position.set( 200, 200, 200 );
scene.add( dirLight );
loader = new VRMLLoader();
loadAsset(canvas.getAttribute("file"));
// renderer
renderer = new THREE.WebGLRenderer({canvas: canvas});
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animate );
document.body.appendChild( renderer.domElement );
// controls
controls = new OrbitControls( camera, renderer.domElement );
controls.minDistance = 1;
controls.maxDistance = 200;
controls.enableDamping = false;
controls.enablePan = true;
// FPS counter
stats = new Stats();
document.body.appendChild( stats.dom );
function onMouseDown(){
spin = false;
}
const fitCameraToCenteredObject = function (camera, object, offset, orbitControls ) {
// https://wejn.org/2020/12/cracking-the-threejs-object-fitting-nut/
const boundingBox = new THREE.Box3();
boundingBox.setFromObject( object );
var middle = new THREE.Vector3();
var size = new THREE.Vector3();
boundingBox.getSize(size);
// figure out how to fit the box in the view:
// 1. figure out horizontal FOV (on non-1.0 aspects)
// 2. figure out distance from the object in X and Y planes
// 3. select the max distance (to fit both sides in)
//
// The reason is as follows:
//
// Imagine a bounding box (BB) is centered at (0,0,0).
// Camera has vertical FOV (camera.fov) and horizontal FOV
// (camera.fov scaled by aspect, see fovh below)
//
// Therefore if you want to put the entire object into the field of view,
// you have to compute the distance as: z/2 (half of Z size of the BB
// protruding towards us) plus for both X and Y size of BB you have to
// figure out the distance created by the appropriate FOV.
//
// The FOV is always a triangle:
//
// (size/2)
// +--------+
// | /
// | /
// | /
// | F° /
// | /
// | /
// | /
// |/
//
// F° is half of respective FOV, so to compute the distance (the length
// of the straight line) one has to: `size/2 / Math.tan(F)`.
//
// FTR, from https://threejs.org/docs/#api/en/cameras/PerspectiveCamera
// the camera.fov is the vertical FOV.
const fov = camera.fov * ( Math.PI / 180 );
const fovh = 2*Math.atan(Math.tan(fov/2) * camera.aspect);
let dx = size.z / 2 + Math.abs( size.x / 2 / Math.tan( fovh / 2 ) );
let dy = size.z / 2 + Math.abs( size.y / 2 / Math.tan( fov / 2 ) );
let cameraZ = Math.max(dx, dy);
// offset the camera, if desired (to avoid filling the whole canvas)
if( offset !== undefined && offset !== 0 ) cameraZ *= offset;
camera.position.set( 0, 0, cameraZ );
// set the far plane of the camera so that it easily encompasses the whole object
const minZ = boundingBox.min.z;
const cameraToFarEdge = ( minZ < 0 ) ? -minZ + cameraZ : cameraZ - minZ;
camera.far = cameraToFarEdge * 3;
camera.updateProjectionMatrix();
if ( orbitControls !== undefined ) {
// set camera to rotate around the center
orbitControls.target = new THREE.Vector3(0, 0, 0);
// prevent camera from zooming out far enough to create far plane cutoff
orbitControls.maxDistance = cameraToFarEdge * 2;
}
};
function loadAsset(asset) {
loader.load( './' + asset + '.wrl',
// onLoad callback
function ( object ) {
vrmlScene = object;
scene.add( object );
document.getElementById('overlay').hidden = true;
// Center
const box = new THREE.Box3().setFromObject( object );
const center = box.getCenter( new THREE.Vector3() );
object.translateX( object.position.x - center.x );
object.translateY( object.position.y - center.y );
object.translateZ( object.position.z - center.z );
/*
object.position.x += ( object.position.x - center.x );
object.position.y += ( object.position.y - center.y );
object.position.z += ( object.position.z - center.z );
*/
controls.reset();
model = object;
fitCameraToCenteredObject(camera, model, 1.1, controls);
//console.log(model)
},
/*
// onProgress callback. Useless because it reaches 100% quickly, then hangs
function ( xhr ) {
console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
},
*/
);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
controls.update(); // to support damping
//console.log(isMouseDown)
if(model && spin){
model.rotation.y += 0.0015
}
renderer.render( scene, camera );
stats.update();
}
addEventListener("resize", (event) => {
fitCameraToCenteredObject(camera, model, 1.1, controls);
});
</script>
</body>
</html>
|