104 lines
2.8 KiB
TypeScript
104 lines
2.8 KiB
TypeScript
import {
|
|
BoxGeometry,
|
|
Camera,
|
|
Mesh,
|
|
MeshBasicMaterial,
|
|
PerspectiveCamera,
|
|
Scene,
|
|
Vector3,
|
|
WebGLRenderer,
|
|
} from "three";
|
|
|
|
import { buildDefaultLights } from "./build-default-lights";
|
|
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
|
|
|
|
export interface Extent {
|
|
xmin: number;
|
|
ymin: number;
|
|
xmax: number;
|
|
ymax: number;
|
|
zmin: number;
|
|
zmax: number;
|
|
}
|
|
|
|
let controls: OrbitControls;
|
|
let renderer: WebGLRenderer;
|
|
let camera: PerspectiveCamera;
|
|
let scene: Scene;
|
|
export async function buildScene(container: HTMLElement, extent: Extent) {
|
|
const size = Math.max(
|
|
extent.xmax - extent.xmin,
|
|
extent.ymax - extent.ymin,
|
|
extent.zmax - extent.zmin
|
|
);
|
|
|
|
const center = new Vector3(
|
|
(extent.xmin + extent.xmax) / 2,
|
|
(extent.ymin + extent.ymax) / 2,
|
|
0
|
|
);
|
|
|
|
const width = container.clientWidth;
|
|
const height = container.clientHeight;
|
|
|
|
camera = new PerspectiveCamera(30, width / height, 0.1, size * 100);
|
|
camera.position.set(center.x, center.y, size * 5);
|
|
camera.lookAt(center);
|
|
|
|
renderer = new WebGLRenderer({
|
|
alpha: true,
|
|
});
|
|
|
|
renderer.setPixelRatio(window.devicePixelRatio);
|
|
renderer.setSize(width, height);
|
|
//renderer.autoClear = false;
|
|
//renderer.setClearColor(0x000000, 0.0); // second param is opacity, 0 => transparent
|
|
|
|
// enable clipping
|
|
renderer.localClippingEnabled = true;
|
|
container.appendChild(renderer.domElement);
|
|
|
|
controls = new OrbitControls(camera, renderer.domElement);
|
|
controls.target.set(center.x, center.y, center.z); // Focus on the center
|
|
controls.enableDamping = true; // Smooth camera movement
|
|
controls.update();
|
|
|
|
// Scene will hold all our elements such as objects, cameras and lights
|
|
scene = new Scene();
|
|
|
|
buildDefaultLights(scene);
|
|
|
|
// const queryString = window.location.search;
|
|
// const urlParams = new URLSearchParams(queryString);
|
|
// const modelid = parseInt(urlParams.get("model_id") ?? "20", 10);
|
|
|
|
renderer.setAnimationLoop(animate);
|
|
|
|
window.addEventListener("resize", () => onWindowResize(container));
|
|
|
|
const testCube = new Mesh(
|
|
new BoxGeometry(size * 0.1, size * 0.1, size * 0.1),
|
|
new MeshBasicMaterial({ color: 0xff0000 })
|
|
);
|
|
testCube.position.copy(center);
|
|
scene.add(testCube);
|
|
|
|
return { renderer, scene, camera };
|
|
}
|
|
|
|
function onWindowResize(container: HTMLElement) {
|
|
// Update the camera's aspect ratio and the renderer's size to reflect
|
|
// the new screen dimensions upon a browser window resize.
|
|
camera.aspect = container.clientWidth / container.clientHeight;
|
|
camera.updateProjectionMatrix();
|
|
renderer.setSize(container.clientWidth, container.clientHeight);
|
|
|
|
// required if controls.enableDamping or controls.autoRotate are set to true
|
|
controls.update();
|
|
}
|
|
|
|
function animate() {
|
|
renderer.render(scene, camera);
|
|
// required if controls.enableDamping or controls.autoRotate are set to true
|
|
controls.update();
|
|
}
|