--------------------------
Download: https://ry3yr.github.io/SampleWebMMD-master.zip
Src: https://github.com/Momijinn/SampleWebMMD
===/js/main.js =====
let scene, renderer, camera, mesh, helper, cameraAnimation;
let ready = false;
const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight;
const clock = new THREE.Clock();
function getQueryStringValue(key) {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get(key);
}
const pmx = getQueryStringValue('pmx');
const stage = getQueryStringValue('stage');
let Pmx;
let Stage;
if (pmx) {
Pmx = `./pmx/pronama/${pmx.trim()}`;
} else {
console.log("No PMX selected.");
}
if (stage) {
Stage = `./stages${stage.trim()}`;
} else {
console.log("No stage selected.");
}
if (!Pmx) {
Pmx = `./pmx/pronama/AoiZaizen/AoiZaizen.pmx`;
}
if (!Stage) {
Stage = "./stages/sorclair/sorclair.pmx";
}
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: "bts-bestofme", pose: "bts-bestofme", VmdClip: null, AudioClip: true },
];
window.onload = () => {
Init();
LoadModeler();
Render();
};
function Init() {
document.getElementById("moveLeftButton").addEventListener("click", moveCameraLeft);
document.getElementById("moveRightButton").addEventListener("click", moveCameraRight);
document.getElementById("moveUpButton").addEventListener("click", moveCameraUp);
document.getElementById("moveDownButton").addEventListener("click", moveCameraDown);
document.getElementById("rotaterightButton").addEventListener("click", rotateCameraRight);
document.getElementById("rotateleftButton").addEventListener("click", rotateCameraLeft);
function moveCameraLeft() { camera.position.x -= 1; }
function moveCameraRight() { camera.position.x += 1; }
function moveCameraUp() { camera.position.y += 1; }
function moveCameraDown() { camera.position.y -= 1; }
function rotateCameraRight() { mesh.rotateY(Math.PI / 4); }
function rotateCameraLeft() { mesh.rotateY(-Math.PI / 4); }
scene = new THREE.Scene();
const ambient = new THREE.AmbientLight(0xeeeeee);
scene.add(ambient);
renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xcccccc, 0);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(100, windowWidth / windowHeight, 1, 1000);
camera.position.set(0, 19, 20);
}
async function LoadModeler() {
const loader = new THREE.MMDLoader();
function LoadPMX() {
return new Promise(resolve => {
loader.load(Pmx, object => {
mesh = object;
scene.add(mesh);
resolve(true);
},);});}
function LoadVMD(id) {
return new Promise(resolve => {
const path = "./vmd/" + id + ".vmd";
const val = MotionObjects.findIndex(MotionObject => MotionObject.id == id);
loader.loadAnimation(path, mesh, vmd => {
vmd.name = id;
MotionObjects[val].VmdClip = vmd;
//newid = id;
//console.log(newid);
document.getElementById('readystate').innerHTML = "Checking motion vmd - " + id + ' (if stuck, click here)';
resolve(true);
},);});}
function LoadCamera(id) {
let camid;
if (new URLSearchParams(window.location.search).has('camera')) {
camid = new URLSearchParams(window.location.search).get('camera');
} else {
camid = localStorage.getItem('camid');
if (!camid) {
camid = 'bts-bestofme';
}
}
const path = "./camera/" + camid + ".vmd";
return new Promise((resolve, reject) => {
loader.loadAnimation(path, camera, cameraAnimation => {
cameraAnimation.name = path;
resolve(cameraAnimation);
console.log(path);
}, onProgress, (xhr) => reject(new Error(`Failed to load Camera VMD file: ${path}`)));
});
}
function LoadAudio(id) {
return new Promise(resolve => {
const path = "./audio/" + id + ".mp3";
const val = MotionObjects.findIndex(MotionObject => MotionObject.id == id);
if (MotionObjects[val].AudioClip) {
new THREE.AudioLoader().load(path, buffer => {
const listener = new THREE.AudioListener();
const audio = new THREE.Audio(listener).setBuffer(buffer);
MotionObjects[val].AudioClip = audio;
document.getElementById('readystate').innerHTML = "Checking audio - " + id + ' (if stuck, click here)';
resolve(true);
},);
} else {
resolve(false);}});}
const loadAdditionalPMX = () => {
return new Promise(resolve => {
loader.load(Stage, object => {
const additionalMesh = object;
scene.add(additionalMesh);
resolve(true);
const loadAdditionalPMX = () => {
return new Promise(resolve => {
loader.load(Stage, object => {
const additionalMesh = object;
scene.add(additionalMesh);
resolve(true);
});
});
};
let path; //preperations for 001.vmd and 002.vmd
try {path = `./stages${stage.trim()}`;} catch (e) {
path = '/default/default';}
const lastIndex = path.lastIndexOf("/");
const basePath = path.substring(0, lastIndex);
const vmd1 = `${basePath}/001.vmd`;
const vmd2 = `${basePath}/002.vmd`;
console.log(vmd1);
console.log(vmd2);
let mixer;
const url = window.location.href;
const isAnimated = url.indexOf('animated') !== -1;
if (isAnimated) {
function createMixer() {
mixer = new THREE.AnimationMixer(object);
}
function playAnimation(animationClip) {
const action = mixer.clipAction(animationClip);
action.play();
}
loader.loadAnimation(vmd1, object, (animationClip) => {
createMixer();
playAnimation(animationClip);
});
loader.loadAnimation(vmd2, object, (animationClip) => {
playAnimation(animationClip);
});
function animate() {
requestAnimationFrame(animate);
const deltaTime = clock.getDelta();
if (mixer) {
mixer.update(deltaTime);
}
renderer.render(scene, camera);
}
animate();
}
},);});};
await Promise.all([loadAdditionalPMX()]);
await LoadPMX();
await Promise.all(MotionObjects.map(async (MotionObject) => {return await LoadVMD(MotionObject.id);}));
await Promise.all(MotionObjects.map(async (MotionObject) => {return await LoadAudio(MotionObject.id);}));
cameraAnimation = await LoadCamera("camera-animation-id"); // Ensure to load camera animation
VmdControl("loop", true);}
function VmdControl(id, loop) {
const index = MotionObjects.findIndex(MotionObject => MotionObject.id == id);
if (index === -1) {
console.log("not Found ID");
//document.getElementById('readystate').textContent = "Default Camera: ready";
document.getElementById('readystate').textContent = "Camera: ready - " + localStorage.getItem('camid');
return;
}
ready = false;
helper = new THREE.MMDAnimationHelper({ afterglow: 2.0, resetPhysicsOnLoop: true });
const enablePhysics = localStorage.getItem("physicsareon") === "true";
helper.add(mesh, {
animation: MotionObjects[index].VmdClip,
physics: enablePhysics
});
if (MotionObjects[index].AudioClip) {
MotionObjects[index].AudioClip.play();
}
if (cameraAnimation) {
helper.add(camera, {animation: cameraAnimation});
}
const mixer = helper.objects.get(mesh).mixer;
if (!loop) {
mixer.existingAction(MotionObjects[index].VmdClip).setLoop(THREE.LoopOnce);
}
mixer.addEventListener("loop", (event) => {
console.log("loop");
});
mixer.addEventListener("finished", (event) => {
console.log("finished");
VmdControl("loop", true);
});
ready = true;
}
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);
renderer.clear();
renderer.render(scene, camera);
if (ready) {
helper.update(clock.getDelta());
}
}
const generatePoseClickEvent = (motionObjects) => {
const functionBody = motionObjects.map(function (motion) {
return "case '" + motion.pose + "':\n" +
" VmdControl('" + motion.id + "', " + (motion.pose === "pose1") + ");\n" +
" break;\n";
}).join("");
const poseClickEventFunction = new Function("id", "switch (id) { " + functionBody +
" default: VmdControl('001', true); break; }");
return poseClickEventFunction;
};
const PoseClickEvent = generatePoseClickEvent(MotionObjects);
console.log(PoseClickEvent);
===/index.html==
...
r/MMD (tools)