Created
May 16, 2024 00:52
-
-
Save danpaldev/b92a69e6142d1ce0f4b55ba843feb744 to your computer and use it in GitHub Desktop.
mmd_model_ortho_camera
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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