diff --git a/public/textures/Bedroom.jpeg b/public/textures/Bedroom.jpeg new file mode 100644 index 0000000..7cfce7d Binary files /dev/null and b/public/textures/Bedroom.jpeg differ diff --git a/public/textures/Office.jpeg b/public/textures/Office.jpeg new file mode 100644 index 0000000..a330c70 Binary files /dev/null and b/public/textures/Office.jpeg differ diff --git a/src/MMDScene.tsx b/src/MMDScene.tsx index 5c43d05..75837d5 100644 --- a/src/MMDScene.tsx +++ b/src/MMDScene.tsx @@ -10,6 +10,7 @@ import { Matrix, Mesh, MeshBuilder, + PhotoDome, Quaternion, Scene, SceneLoader, @@ -25,6 +26,9 @@ import type { IMmdRuntimeLinkedBone } from "babylon-mmd/esm/Runtime/IMmdRuntimeL import ammoPhysics from "./ammo/ammo.wasm" import { Box, FormControl, InputLabel, MenuItem, Select, SelectChangeEvent } from "@mui/material" +const defaultScene = "Static" +const availableScenes = ["Static", "Office", "Bedroom"] + const defaultModel = "深空之眼-托特" const availableModels = [ "深空之眼-托特", @@ -55,10 +59,16 @@ function MMDScene({ const canvasRef = useRef(null) const sceneRef = useRef(null) const [sceneRendered, setSceneRendered] = useState(false) + const [selectedScene, setSelectedScene] = useState(defaultScene) const [selectedModel, setSelectedModel] = useState(defaultModel) const mmdModelRef = useRef(null) const mmdRuntimeRef = useRef(null) const shadowGeneratorRef = useRef(null) + const domeRef = useRef(null) + + const handleSceneChange = (event: SelectChangeEvent): void => { + setSelectedScene(event.target.value) + } const handleModelChange = (event: SelectChangeEvent): void => { setSelectedModel(event.target.value) @@ -128,6 +138,26 @@ function MMDScene({ } }, [setFps, setSceneRendered]) + useEffect(() => { + if (domeRef.current) { + domeRef.current.dispose() + } + if (sceneRef.current && selectedScene !== "Static") { + domeRef.current = new PhotoDome( + "testdome", + `/textures/${selectedScene}.jpeg`, + { + resolution: 32, + size: 500, + useDirectMapping: false, + }, + sceneRef.current + ) + domeRef.current.imageMode = PhotoDome.MODE_MONOSCOPIC + domeRef.current.position.y = 0 + } + }, [sceneRendered, sceneRef, selectedScene]) + useEffect(() => { const loadMMD = async (): Promise => { if (!sceneRendered || !selectedModel || !mmdRuntimeRef.current) return @@ -214,7 +244,7 @@ function MMDScene({ const neckPos = leftShoulder.add(rightShoulder).scale(0.5) const headDir = nose.subtract(neckPos).normalize() - const forwardDir = new Vector3(-headDir.x, 0, headDir.z).normalize() + const forwardDir = new Vector3(headDir.x, 0, headDir.z).normalize() const tiltAngle = Math.atan2(-headDir.y, forwardDir.length()) @@ -678,6 +708,24 @@ function MMDScene({ return ( <> + + + Scene + + + Model diff --git a/src/assets/main.css b/src/assets/main.css index 85e3d5a..7c126c5 100644 --- a/src/assets/main.css +++ b/src/assets/main.css @@ -129,6 +129,12 @@ video { height: 100vh; } +.scene-selector { + position: absolute; + bottom: 5.5rem; + right: 1rem; +} + .model-selector { position: absolute; bottom: 0.5rem;