From fc506495c93327aa816f331ea7a413be0ffa29c0 Mon Sep 17 00:00:00 2001 From: Pihkaal Date: Thu, 8 Jan 2026 13:10:26 +0100 Subject: [PATCH] feat(nds): improve 3d model and texture display --- app/components/NDS.vue | 70 +- app/components/Screen.vue | 13 +- app/utils/screen.ts | 9 +- public/nds/models/nintendo-ds/license.txt | 11 - public/nds/models/nintendo-ds/scene.gltf | 1706 -------------- .../textures/screen_down.002_baseColor.png | Bin 30408 -> 0 bytes .../textures/screen_up.002_baseColor.png | Bin 28892 -> 0 bytes .../base.002_baseColor.png | Bin .../base.002_metallicRoughness.png | Bin .../base.002_normal.png | Bin .../button_general.001_baseColor.png | Bin .../scene.bin => nitendo-ds/model.bin} | Bin 3106104 -> 2291336 bytes public/nds/models/nitendo-ds/model.blend | Bin 0 -> 9935369 bytes public/nds/models/nitendo-ds/model.blend1 | Bin 0 -> 9961438 bytes public/nds/models/nitendo-ds/model.gltf | 1975 +++++++++++++++++ .../nitendo-ds/screen_down.002_baseColor.png | Bin 0 -> 148233 bytes .../screen_down.002_metallicRoughness.png | Bin .../screen_down.002_normal.png | Bin .../nitendo-ds/screen_up.002_baseColor.png | Bin 0 -> 148233 bytes .../screen_up.002_metallicRoughness.png | Bin .../screen_up.002_normal.png | Bin .../top.002_baseColor.png | Bin .../top.002_metallicRoughness.png | Bin .../top.002_normal.png | Bin 24 files changed, 2027 insertions(+), 1757 deletions(-) delete mode 100644 public/nds/models/nintendo-ds/license.txt delete mode 100644 public/nds/models/nintendo-ds/scene.gltf delete mode 100644 public/nds/models/nintendo-ds/textures/screen_down.002_baseColor.png delete mode 100644 public/nds/models/nintendo-ds/textures/screen_up.002_baseColor.png rename public/nds/models/{nintendo-ds/textures => nitendo-ds}/base.002_baseColor.png (100%) rename public/nds/models/{nintendo-ds/textures => nitendo-ds}/base.002_metallicRoughness.png (100%) rename public/nds/models/{nintendo-ds/textures => nitendo-ds}/base.002_normal.png (100%) rename public/nds/models/{nintendo-ds/textures => nitendo-ds}/button_general.001_baseColor.png (100%) rename public/nds/models/{nintendo-ds/scene.bin => nitendo-ds/model.bin} (51%) create mode 100644 public/nds/models/nitendo-ds/model.blend create mode 100644 public/nds/models/nitendo-ds/model.blend1 create mode 100644 public/nds/models/nitendo-ds/model.gltf create mode 100644 public/nds/models/nitendo-ds/screen_down.002_baseColor.png rename public/nds/models/{nintendo-ds/textures => nitendo-ds}/screen_down.002_metallicRoughness.png (100%) rename public/nds/models/{nintendo-ds/textures => nitendo-ds}/screen_down.002_normal.png (100%) create mode 100644 public/nds/models/nitendo-ds/screen_up.002_baseColor.png rename public/nds/models/{nintendo-ds/textures => nitendo-ds}/screen_up.002_metallicRoughness.png (100%) rename public/nds/models/{nintendo-ds/textures => nitendo-ds}/screen_up.002_normal.png (100%) rename public/nds/models/{nintendo-ds/textures => nitendo-ds}/top.002_baseColor.png (100%) rename public/nds/models/{nintendo-ds/textures => nitendo-ds}/top.002_metallicRoughness.png (100%) rename public/nds/models/{nintendo-ds/textures => nitendo-ds}/top.002_normal.png (100%) diff --git a/app/components/NDS.vue b/app/components/NDS.vue index 012739c..fa016fd 100644 --- a/app/components/NDS.vue +++ b/app/components/NDS.vue @@ -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(); @@ -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, }), ); diff --git a/app/components/Screen.vue b/app/components/Screen.vue index 838d452..20f05d2 100644 --- a/app/components/Screen.vue +++ b/app/components/Screen.vue @@ -1,4 +1,6 @@