feat: compute mouse position for each screen
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
<div id="coord-display"></div>
|
||||||
<script type="module" src="/src/main.ts"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</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);
|
nds.scene.scale.set(50, 50, 50);
|
||||||
scene.add(nds.scene);
|
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
|
// create light
|
||||||
const color = 0xffffff;
|
const color = 0xffffff;
|
||||||
const intensity = 3;
|
const intensity = 3;
|
||||||
@@ -44,6 +61,50 @@ directional.target = nds.scene;
|
|||||||
directional.position.set(0, 100, 0);
|
directional.position.set(0, 100, 0);
|
||||||
scene.add(directional);
|
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
|
// main loop
|
||||||
renderer.setAnimationLoop(() => {
|
renderer.setAnimationLoop(() => {
|
||||||
controls.update();
|
controls.update();
|
||||||
|
|||||||
@@ -1,3 +1,16 @@
|
|||||||
body {
|
body {
|
||||||
margin: 0;
|
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