feat(assets): load 3d models as well

This commit is contained in:
2025-12-17 18:00:11 +01:00
parent b85899617b
commit e190636544
7 changed files with 113 additions and 78 deletions

View File

@@ -1,5 +1,4 @@
<script setup lang="ts">
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { useLoop, useTresContext } from "@tresjs/core";
import * as THREE from "three";
@@ -8,12 +7,9 @@ const props = defineProps<{
bottomScreenCanvas: HTMLCanvasElement | null;
}>();
const { state: model } = useLoader(
GLTFLoader,
"/models/nintendo-ds/scene.gltf",
);
const { assets } = useAssets();
const scene = computed(() => model.value?.scene);
const model = assets.nintendoDs.scene.clone(true);
let topScreenTexture: THREE.CanvasTexture | null = null;
let bottomScreenTexture: THREE.CanvasTexture | null = null;
@@ -43,6 +39,15 @@ const requireMesh = (key: string): THREE.Mesh => {
const { camera, renderer } = useTresContext();
model.scale.set(100, 100, 100);
meshes.clear();
model.traverse((child) => {
if (child instanceof THREE.Mesh) {
meshes.set(child.name, child);
}
});
watch(
() => [props.topScreenCanvas, props.bottomScreenCanvas],
() => {
@@ -61,41 +66,22 @@ watch(
bottomScreenTexture.flipY = false;
bottomScreenTexture.repeat.set(1, 1024 / 532);
bottomScreenTexture.offset.set(0, -1024 / 532 + 1);
requireMesh(TOP_SCREEN).material = new THREE.MeshStandardMaterial({
map: topScreenTexture,
emissive: new THREE.Color(0x222222),
emissiveIntensity: 0.5,
});
requireMesh(BOTTOM_SCREEN).material = new THREE.MeshStandardMaterial({
map: bottomScreenTexture,
emissive: new THREE.Color(0x222222),
emissiveIntensity: 0.5,
});
},
{ immediate: true },
);
watch(scene, () => {
if (!scene.value) return;
meshes.clear();
scene.value.scale.set(100, 100, 100);
scene.value.traverse((child) => {
if (child instanceof THREE.Mesh) {
meshes.set(child.name, child);
}
});
if (!topScreenTexture || !bottomScreenTexture)
throw new Error(
"topScreenTexture and bottomScreenTexture should be initialized",
);
requireMesh(TOP_SCREEN).material = new THREE.MeshStandardMaterial({
map: topScreenTexture,
emissive: new THREE.Color(0x222222),
emissiveIntensity: 0.5,
});
requireMesh(BOTTOM_SCREEN).material = new THREE.MeshStandardMaterial({
map: bottomScreenTexture,
emissive: new THREE.Color(0x222222),
emissiveIntensity: 0.5,
});
});
const { onRender } = useLoop();
const physicalButtonsDown = new Set<string>();
@@ -192,8 +178,6 @@ const pressButton = (button: string) => {
};
const handleClick = (event: MouseEvent) => {
if (!scene.value) return;
const domElement = renderer.instance.domElement;
const rect = domElement.getBoundingClientRect();
@@ -206,7 +190,7 @@ const handleClick = (event: MouseEvent) => {
camera.activeCamera.value,
);
const intersects = raycaster.intersectObjects(scene.value.children, true);
const intersects = raycaster.intersectObjects(model.children, true);
const intersection = intersects[0];
if (!intersection?.uv) return;
@@ -311,5 +295,5 @@ onUnmounted(() => {
</script>
<template>
<primitive v-if="scene" :object="scene" />
<primitive :object="model" />
</template>