individual load let scene, renderer, camera, mesh, mesh2; let mixer1, mixer2, clock, cameraAnimation; const windowWidth = window.innerWidth; const windowHeight = window.innerHeight; function getQueryStringValue(key) { const urlParams = new URLSearchParams(window.location.search); return urlParams.get(key); } const pmx = getQueryStringValue('pmx'); const pmx2 = getQueryStringValue('pmx2'); const stage = getQueryStringValue('stage') || "/sorclair/sorclair.pmx"; let Pmx; let Pmx2; if (pmx) { Pmx = `./pmx/pronama/${pmx.trim()}`; console.log(`PMX: ${pmx.trim()}`); } else { console.log("No PMX selected."); } if (pmx2) { Pmx2 = `./pmx/pronama/${pmx2.trim()}`; console.log(`PMX2: ${pmx2.trim()}`); } else { console.log("No PMX2 selected."); } let StagePath = stage ? `./stages/${stage.trim()}` : './stages/sorclair/sorclair.pmx'; if (pmx) { Pmx = `./pmx/pronama/${pmx.trim()}`;console.log(`PMX: ${pmx.trim()}`);} else {console.log("No PMX selected.");} if (pmx2) {Pmx2 = `./pmx/pronama/${pmx2.trim()}`;console.log(`PMX2: ${pmx2.trim()}`);} else {console.log("No PMX2 selected.");} if (StagePath) {StagePath = `./stages${stage.trim()}`;} else {StagePath = './stages/sorclair/sorclair.pmx';} console.log('StagePath:', StagePath); if (StagePath) { const loader = new THREE.MMDLoader(); const lastIndex = StagePath.lastIndexOf("/"); const basePath = StagePath.substring(0, lastIndex); const vmd1Path = `${basePath}/001.vmd`; const vmd2Path = `${basePath}/002.vmd`; loader.load(StagePath, (stageObject) => { var ambientLight = new THREE.AmbientLight(0xffffff, 1.0); //hardcoded scene.add(ambientLight); scene.add(stageObject); const mixer = new THREE.AnimationMixer(stageObject); loader.loadAnimation(vmd1Path, stageObject, (vmd1Clip) => { vmd1Clip.name = "001"; console.log(`Loaded VMD: ${vmd1Path}`); const motionObject1 = MotionObjects.find(obj => obj.id === "001"); if (motionObject1) { motionObject1.VmdClip = vmd1Clip; const action1 = mixer.clipAction(vmd1Clip); action1.play(); } else { console.warn(`Motion object with id "001" not found.`); } }, onProgress, onError); loader.loadAnimation(vmd2Path, stageObject, (vmd2Clip) => { vmd2Clip.name = "002"; console.log(`Loaded VMD: ${vmd2Path}`); const motionObject2 = MotionObjects.find(obj => obj.id === "002"); if (motionObject2) { motionObject2.VmdClip = vmd2Clip; const action2 = mixer.clipAction(vmd2Clip); action2.play(); } else { console.warn(`Motion object with id "002" not found.`); } }, onProgress, onError); const clock = new THREE.Clock(); const animate = () => { requestAnimationFrame(animate); const delta = clock.getDelta(); mixer.update(delta); renderer.render(scene, camera); }; animate(); }, onProgress, onError); } else {console.warn('No valid stage path found.');} //if (!Stage) {Stage = stage ? `stages${stage}` : '/sorclair/sorclair.pmx';} if (!Pmx) {Pmx = `./pmx/pronama/AoiZaizen/AoiZaizen.pmx`;} console.log('StagePath:', StagePath); const MotionObjects = [ { id: "001", pose: "001", VmdClip: null, AudioClip: false }, { id: "002", pose: "002", VmdClip: null, AudioClip: false }, { id: "003", pose: "003", VmdClip: null, AudioClip: false }, { id: "004walknthink", pose: "004walknthink", VmdClip: null, AudioClip: false }, { id: "005hard-carry", pose: "005hard-carry", VmdClip: null, AudioClip: true }, { id: "bts-bestofme", pose: "bts-bestofme", VmdClip: null, AudioClip: true }, { id: "seniorita", pose: "seniorita", VmdClip: null, AudioClip: true }, { id: "test", pose: "test", VmdClip: null, AudioClip: false }, { id: "lupin", pose: "lupin", VmdClip: null, AudioClip: true }, { id: "lp-alightthatnevercomes", pose: "lp-alightthatnevercomes", VmdClip: null, AudioClip: true }, { id: "pillarmen", pose: "pillarmen", VmdClip: null, AudioClip: true }, ]; window.onload = () => { Init(); LoadStage(); LoadModels(); Render(); }; function Init() { document.getElementById("moveLeftButton").addEventListener("click", () => { camera.position.x -= 1; }); document.getElementById("moveRightButton").addEventListener("click", () => { camera.position.x += 1; }); document.getElementById("moveUpButton").addEventListener("click", () => { camera.position.y += 1; }); document.getElementById("moveDownButton").addEventListener("click", () => { camera.position.y -= 1; }); document.getElementById("rotaterightButton").addEventListener("click", () => { mesh.rotateY(Math.PI / 4); }); document.getElementById("rotateleftButton").addEventListener("click", () => { mesh.rotateY(-Math.PI / 4); }); scene = new THREE.Scene(); renderer = new THREE.WebGLRenderer({ alpha: true }); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); camera = new THREE.PerspectiveCamera(100, windowWidth / windowHeight, 1, 1000); camera.position.set(0, 19, 20); clock = new THREE.Clock(); } function LoadStage() { const loader = new THREE.MMDLoader(); loader.load(StagePath, (stageObject) => { scene.add(stageObject); const ambientLight = new THREE.AmbientLight(0xffffff, 1.0); scene.add(ambientLight); }); } async function LoadModels() { const loader = new THREE.MMDLoader(); function LoadPMX(path) { return new Promise(resolve => { loader.load(path, object => { resolve(object); }); }); } async function LoadModel1() { mesh = await LoadPMX(Pmx); scene.add(mesh); mixer1 = new THREE.AnimationMixer(mesh); LoadAnimationsForMesh(mesh, mixer1, "001"); } async function LoadModel2() { if (Pmx2) { mesh2 = await LoadPMX(Pmx2); mesh2.position.x += 15; scene.add(mesh2); mixer2 = new THREE.AnimationMixer(mesh2); LoadAnimationsForMesh(mesh2, mixer2, "002"); } } async function LoadAnimationsForMesh(mesh, mixer, id) { const vmdPath = `./vmd/${id}.vmd`; loader.loadAnimation(vmdPath, mesh, (vmdClip) => { vmdClip.name = id; const action = mixer.clipAction(vmdClip); action.play(); }, onProgress, onError); } await LoadModel1(); await LoadModel2(); } function onProgress(xhr) { if (xhr.lengthComputable) { const percentComplete = xhr.loaded / xhr.total * 100; console.log(Math.round(percentComplete, 2) + '% downloaded'); } } function onError(xhr) { console.log("ERROR", xhr); } function Render() { requestAnimationFrame(Render); const delta = clock.getDelta(); if (mixer1) mixer1.update(delta); if (mixer2) mixer2.update(delta); renderer.render(scene, camera); } const generatePoseClickEvent = (motionObjects) => { if (!Array.isArray(motionObjects)) { console.error("motionObjects is not an array."); return () => {}; } const functionBody = motionObjects.map(function (motion) { return "case '" + motion.pose + "':\n" + " console.log('Motion used:', '" + motion.pose + "');\n" + " VmdControl('" + motion.id + "', " + (motion.pose === "pose1") + ");\n" + " break;\n"; }).join(""); const poseClickEventFunction = new Function("id", "switch (id) { " + functionBody + " default: console.log('Default motion used:', '001'); VmdControl('001', true); break; }"); return poseClickEventFunction; }; const PoseClickEvent = generatePoseClickEvent(MotionObjects); document.querySelectorAll(".pose-button").forEach(button => { button.addEventListener("click", (event) => { const poseId = event.target.dataset.poseId; PoseClickEvent(poseId); }); });