feat: compute mouse position for each screen
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<div id="coord-display"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
61
src/main.ts
61
src/main.ts
@@ -33,6 +33,23 @@ const nds = await loader.loadAsync("/nintendo-ds/scene.gltf");
|
||||
nds.scene.scale.set(50, 50, 50);
|
||||
scene.add(nds.scene);
|
||||
|
||||
let topScreenMesh: THREE.Mesh | undefined = undefined;
|
||||
let bottomScreenMesh: THREE.Mesh | undefined = undefined;
|
||||
|
||||
nds.scene.traverse((child) => {
|
||||
if (child instanceof THREE.Mesh) {
|
||||
const material = child.material as THREE.Material;
|
||||
if (material.name?.includes("screen_up")) {
|
||||
topScreenMesh = child;
|
||||
} else if (material.name?.includes("screen_down")) {
|
||||
bottomScreenMesh = child;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!topScreenMesh) throw new Error(`Top screen mesh not found`);
|
||||
if (!bottomScreenMesh) throw new Error(`Bottom screen mesh not found`);
|
||||
|
||||
// create light
|
||||
const color = 0xffffff;
|
||||
const intensity = 3;
|
||||
@@ -44,6 +61,50 @@ directional.target = nds.scene;
|
||||
directional.position.set(0, 100, 0);
|
||||
scene.add(directional);
|
||||
|
||||
const coordDisplay = document.getElementById("coord-display")!;
|
||||
|
||||
renderer.domElement.addEventListener("mousemove", (event) => {
|
||||
const rect = renderer.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) {
|
||||
coordDisplay.hidden = false;
|
||||
|
||||
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);
|
||||
|
||||
const screenName = mesh === topScreenMesh ? "top" : "bottom";
|
||||
coordDisplay.textContent = `${screenName} | pos: (${x}, ${y})`;
|
||||
} else {
|
||||
coordDisplay.hidden = true;
|
||||
}
|
||||
} else {
|
||||
coordDisplay.hidden = true;
|
||||
}
|
||||
});
|
||||
|
||||
// main loop
|
||||
renderer.setAnimationLoop(() => {
|
||||
controls.update();
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#coord-display {
|
||||
position: fixed;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
color: white;
|
||||
font-family: monospace;
|
||||
font-size: 16px;
|
||||
background-color: #000000;
|
||||
padding: 10px;
|
||||
pointer-events: none;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user