Skip to content

Instantly share code, notes, and snippets.

@danpaldev
Created May 16, 2024 00:52
Show Gist options
  • Save danpaldev/b92a69e6142d1ce0f4b55ba843feb744 to your computer and use it in GitHub Desktop.
Save danpaldev/b92a69e6142d1ce0f4b55ba843feb744 to your computer and use it in GitHub Desktop.
mmd_model_ortho_camera
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - loaders - MMD loader</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
<style>
body {
background-color: #fff;
color: #444;
}
a {
color: #08f;
}
</style>
</head>
<body>
<script src="jsm/libs/ammo.wasm.js"></script>
<script type="importmap">
{
"imports": {
"three": "./build/three.module.js",
"three/addons/": "./jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
import { OutlineEffect } from 'three/addons/effects/OutlineEffect.js';
import { MMDLoader } from 'three/addons/loaders/MMDLoader.js';
import { MMDAnimationHelper } from 'three/addons/animation/MMDAnimationHelper.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
let camera, scene, renderer, effect;
let mesh, helper;
let controls;
let debugMatrix;
Ammo().then( function ( AmmoLib ) {
Ammo = AmmoLib;
init();
animate();
});
function mat4LookAt(eye, target, up) {
let z = new THREE.Vector3();
let x = new THREE.Vector3();
let y = new THREE.Vector3();
z.subVectors(target, eye).normalize();
x.crossVectors(up, z).normalize();
y.crossVectors(z, x);
let viewMatrix = new THREE.Matrix4();
viewMatrix.set(
x.x, x.y, x.z, -x.dot(eye),
y.x, y.y, y.z, -y.dot(eye),
z.x, z.y, z.z, -z.dot(eye),
0, 0, 0, 1
);
return viewMatrix;
}
let upDirection = new THREE.Vector3(0, 1, 0);
const MESH_WORLD_POSITION = new THREE.Vector3(0,0,1);
function getCameraPositionByDegrees_Y_rotation(degrees) {
const radians = THREE.MathUtils.degToRad(degrees);
const camera_height = 10.0;
const camera_depth = 10.0;
const x = camera_depth * Math.sin(radians);
const z = camera_depth * Math.cos(radians);
return new THREE.Vector3(x, camera_height, z);
}
function init() {
const container = document.createElement( 'div' );
document.body.appendChild( container );
const frustumSize = 25;
const aspect = window.innerWidth / window.innerHeight;
camera = new THREE.OrthographicCamera(
frustumSize * aspect / -2,
frustumSize * aspect / 2,
frustumSize / 2,
frustumSize / -2,
1, 1000
);
const cameraPosition = getCameraPositionByDegrees_Y_rotation(45);
camera.up.set(0, 1, 0);
camera.position.copy(MESH_WORLD_POSITION).add(getCameraPositionByDegrees_Y_rotation(0));
camera.lookAt(MESH_WORLD_POSITION);
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xffffff );
const ambient = new THREE.AmbientLight( 0xaaaaaa, 2.1 );
scene.add( ambient );
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5);
directionalLight.position.set(0, 0, -1);
scene.add(directionalLight);
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
effect = new OutlineEffect( renderer );
camera.matrixAutoUpdate = false;
function onProgress( xhr ) {
if ( xhr.lengthComputable ) {
const percentComplete = xhr.loaded / xhr.total * 100;
console.log( Math.round( percentComplete, 2 ) + '% downloaded' );
}
}
const modelFile = "models/mmd/cat_girl/ヨッシー式ラインクラフト.pmx";
helper = new MMDAnimationHelper();
const loader = new MMDLoader();
loader.load( modelFile, function ( object ) {
mesh = object;
for ( const material of mesh.material ) {
material.emissive.set( 0x000000 );
}
mesh.position.copy(MESH_WORLD_POSITION)
scene.add( mesh );
initGui();
}, onProgress, null );
window.addEventListener( 'resize', onWindowResize );
}
function initGui() {
const gui = new GUI();
const morphs = gui.addFolder('Morphs');
const morphTargetDictionary = mesh.morphTargetDictionary;
const morphTargetInfluences = mesh.morphTargetInfluences;
Object.keys(morphTargetDictionary).forEach((key) => {
const index = morphTargetDictionary[key];
gui.add(morphTargetInfluences, index, 0, 1, 0.01).name(key);
});
morphs.open();
}
function onWindowResize() {
const aspect = window.innerWidth / window.innerHeight;
camera.left = -frustumSize * aspect / 2;
camera.right = frustumSize * aspect / 2;
camera.top = frustumSize / 2;
camera.bottom = -frustumSize / 2;
camera.updateProjectionMatrix();
effect.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
let currentMatrixStr = camera.matrix.toArray().toString();
if (debugMatrix !== currentMatrixStr) {
console.log("@@@@@@@@@@@@@@@@@@@@@@@@")
debugMatrix = currentMatrixStr;
console.log("### Camera Matrix World ###")
console.log(camera.matrixWorld);
console.log("@@@@@@@@@@@@@@@@@@@@@@@@")
}
render();
}
function render() {
renderer.render(scene, camera)
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment