feat(nds): improve 3d model and texture display

This commit is contained in:
2026-01-08 13:10:26 +01:00
parent ec9f8cc264
commit 048610f15c
24 changed files with 2027 additions and 1757 deletions

View File

@@ -2,6 +2,7 @@
import { useLoop, useTresContext } from "@tresjs/core";
import * as THREE from "three";
import gsap from "gsap";
import { LOGICAL_WIDTH, LOGICAL_HEIGHT } from "~/utils/screen";
const INTRO_ANIMATION = {
MODEL_SPIN_DURATION: 3,
@@ -26,25 +27,25 @@ const props = defineProps<{
const { assets } = useAssets();
const app = useAppStore();
const model = assets.nintendoDs.scene.clone(true);
const model = assets.nitendoDs.model.clone(true);
let topScreenTexture: THREE.CanvasTexture | null = null;
let bottomScreenTexture: THREE.CanvasTexture | null = null;
/// meshes ///
// screens
const TOP_SCREEN = "Object_9";
const BOTTOM_SCREEN = "Object_28";
const LID = "Object_8";
const TOP_SCREEN = "top_screen";
const BOTTOM_SCREEN = "bottom_screen";
const LID = "lid";
// buttons
const CROSS_BUTTON = "Object_21";
const X_BUTTON = "Object_6";
const A_BUTTON = "Object_32";
const Y_BUTTON = "Object_4";
const B_BUTTON = "Object_30";
const SELECT_BUTTON = "Object_17";
const START_BUTTON = "Object_11";
const CROSS_BUTTON = "button_pad";
const X_BUTTON = "button_x";
const A_BUTTON = "button_a";
const Y_BUTTON = "button_y";
const B_BUTTON = "button_b";
const SELECT_BUTTON = "button_select";
const START_BUTTON = "button_start";
const meshes = new Map<string, THREE.Mesh>();
@@ -163,21 +164,25 @@ watch(
() => {
if (!props.topScreenCanvas || !props.bottomScreenCanvas) return;
topScreenTexture = new THREE.CanvasTexture(props.topScreenCanvas);
topScreenTexture.minFilter = THREE.NearestFilter;
topScreenTexture.magFilter = THREE.NearestFilter;
topScreenTexture.colorSpace = THREE.SRGBColorSpace;
topScreenTexture.flipY = false;
topScreenTexture.repeat.set(1, 1024 / 404);
topScreenTexture.offset.set(0, -4 / 1024);
const webglRenderer = renderer.instance;
if (!(webglRenderer instanceof THREE.WebGLRenderer)) return;
bottomScreenTexture = new THREE.CanvasTexture(props.bottomScreenCanvas);
bottomScreenTexture.minFilter = THREE.NearestFilter;
bottomScreenTexture.magFilter = THREE.NearestFilter;
bottomScreenTexture.colorSpace = THREE.SRGBColorSpace;
bottomScreenTexture.flipY = false;
bottomScreenTexture.repeat.set(1, 1024 / 532);
bottomScreenTexture.offset.set(0, -1024 / 532 + 1);
const createScreenTexture = (
canvas: HTMLCanvasElement,
): THREE.CanvasTexture => {
const texture = new THREE.CanvasTexture(canvas);
texture.minFilter = THREE.LinearFilter;
texture.magFilter = THREE.LinearFilter;
texture.colorSpace = THREE.SRGBColorSpace;
texture.wrapS = THREE.RepeatWrapping;
texture.repeat.x = -1;
texture.anisotropy = webglRenderer.capabilities.getMaxAnisotropy();
texture.generateMipmaps = false;
return texture;
};
topScreenTexture = createScreenTexture(props.topScreenCanvas);
bottomScreenTexture = createScreenTexture(props.bottomScreenCanvas);
requireMesh(TOP_SCREEN).material = new THREE.MeshStandardMaterial({
map: topScreenTexture,
@@ -314,7 +319,6 @@ const handleClick = (event: MouseEvent) => {
switch (intersection.object.name) {
case TOP_SCREEN:
case BOTTOM_SCREEN: {
console.log(intersection);
const canvas =
intersection.object.name === TOP_SCREEN
? props.topScreenCanvas
@@ -322,22 +326,16 @@ const handleClick = (event: MouseEvent) => {
if (!canvas) break;
const x = Math.floor(intersection.uv.x * 256);
let y: number;
if (intersection.object.name === TOP_SCREEN) {
y = Math.floor(intersection.uv.y * (1024 / 404) * 192);
} else {
y = Math.floor(192 - (1 - intersection.uv.y) * (1024 / 532) * 192);
}
const logicalX = (1 - intersection.uv.x) * LOGICAL_WIDTH;
const logicalY = (1 - intersection.uv.y) * LOGICAL_HEIGHT;
const rect = canvas.getBoundingClientRect();
canvas.dispatchEvent(
new MouseEvent("click", {
bubbles: true,
cancelable: true,
clientX: (x / 256) * rect.width + rect.left,
clientY: (y / 192) * rect.height + rect.top,
clientX: (logicalX / LOGICAL_WIDTH) * rect.width + rect.left,
clientY: (logicalY / LOGICAL_HEIGHT) * rect.height + rect.top,
}),
);