refactor: nds as a 3d object
This commit is contained in:
72
src/nds.ts
Normal file
72
src/nds.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import * as THREE from "three";
|
||||
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
|
||||
|
||||
export class NDS extends THREE.Object3D {
|
||||
topScreenMesh: THREE.Mesh | undefined;
|
||||
bottomScreenMesh: THREE.Mesh | undefined;
|
||||
|
||||
public constructor(camera: THREE.Camera, domElement: HTMLCanvasElement) {
|
||||
super();
|
||||
|
||||
const loader = new GLTFLoader();
|
||||
// load model
|
||||
loader.load("/nintendo-ds/scene.gltf", ({ scene: model }) => {
|
||||
model.scale.set(50, 50, 50);
|
||||
|
||||
// find top and bottom screens
|
||||
model.traverse((child) => {
|
||||
if (child instanceof THREE.Mesh) {
|
||||
const material = child.material as THREE.Material;
|
||||
if (material.name?.includes("screen_up")) {
|
||||
this.topScreenMesh = child;
|
||||
} else if (material.name?.includes("screen_down")) {
|
||||
this.bottomScreenMesh = child;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!this.topScreenMesh) throw new Error(`Missing top screen`);
|
||||
if (!this.bottomScreenMesh) throw new Error(`Missing bottom screen`);
|
||||
|
||||
const { topScreenMesh, bottomScreenMesh } = this;
|
||||
|
||||
domElement.addEventListener("mousemove", (event) => {
|
||||
const rect = domElement.getBoundingClientRect();
|
||||
|
||||
const raycaster = new THREE.Raycaster();
|
||||
raycaster.setFromCamera(
|
||||
new THREE.Vector2(
|
||||
((event.clientX - rect.left) / rect.width) * 2 - 1,
|
||||
-((event.clientY - rect.top) / rect.height) * 2 + 1,
|
||||
),
|
||||
camera,
|
||||
);
|
||||
|
||||
const intersects = raycaster.intersectObjects([
|
||||
topScreenMesh,
|
||||
bottomScreenMesh,
|
||||
]);
|
||||
|
||||
if (intersects.length > 0) {
|
||||
const intersection = intersects[0];
|
||||
const mesh = intersection.object as THREE.Mesh;
|
||||
const uv = intersection.uv;
|
||||
|
||||
if (uv) {
|
||||
const x = Math.floor(uv.x * 256);
|
||||
const y =
|
||||
mesh === topScreenMesh
|
||||
? Math.floor(uv.y * (1024 / 404) * 192)
|
||||
: // invert coords only for bottom screen
|
||||
Math.floor(192 - (1 - uv.y) * (1024 / 532) * 192);
|
||||
|
||||
x;
|
||||
y;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
super.add(model);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user