import * as THREE from "three" import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader" import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; import { VRMLoaderPlugin } from "@pixiv/three-vrm"; import { createVRMAnimationClip, VRMAnimationLoaderPlugin } from "@pixiv/three-vrm-animation"; import { Color, DirectionalLight, Fog, HemisphereLight } from 'three'; import { GridHelper, Mesh, MeshLambertMaterial, BoxGeometry, Vector3 } from 'three'; window.addEventListener("DOMContentLoaded", () => { const canvas = document.getElementById("canvas"); if (canvas == null) return; const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 30, canvas.clientWidth/canvas.clientHeight, 0.1, 20); camera.position.set(0.0, 0.9, -4.0) camera.rotation.set(0.0, Math.PI, 0.0) camera.lookAt(new THREE.Vector3(0, 0, 0)); const renderer = new THREE.WebGLRenderer({antialias: true, alpha: true}); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(canvas.clientWidth, canvas.clientHeight); renderer.setClearColor(0x7fbfff, 1.0); renderer.shadowMap.enabled = true; renderer.outputColorSpace = THREE.SRGBColorSpace; //renderer.toneMapping = THREE.ACESFilmicToneMapping; //renderer.toneMappingExposure = 1; canvas.appendChild(renderer.domElement); const light = new THREE.DirectionalLight(0xffffff, Math.PI); light.position.set(1.0, 1.0, 1.0); scene.add(light); let currentVrm: any = undefined; let currentVrmAnimation: any = undefined; let currentMixer:any = undefined; function load(url: string) { loader.load( url, (gltf) => { tryInitVRM(gltf); tryInitVRMA(gltf); }, (progress) => console.log( "Loading model...", 100.0 * (progress.loaded / progress.total), "%" ), (error) => console.error(error) ); } function tryInitVRM(gltf: any) { const vrm = gltf.userData.vrm; if ( vrm == null ) { return; } currentVrm = vrm; scene.add(vrm.scene); initAnimationClip(); } function tryInitVRMA(gltf: any) { const vrmAnimations = gltf.userData.vrmAnimations; if (vrmAnimations == null) { return; } currentVrmAnimation = vrmAnimations[0] ?? null; initAnimationClip(); } function initAnimationClip() { if (currentVrm && currentVrmAnimation) { currentMixer = new THREE.AnimationMixer(currentVrm.scene); const clip = createVRMAnimationClip(currentVrmAnimation, currentVrm); currentMixer.clipAction(clip).play(); } } const loader = new GLTFLoader(); loader.register((parser) => { return new VRMLoaderPlugin(parser); }); loader.register((parser) => { return new VRMAnimationLoaderPlugin(parser); }); load("/vrma/ai.vrm"); load("/vrma/fly_c.vrma"); const clock = new THREE.Clock(); clock.start(); const update = () => { controls.update(); requestAnimationFrame(update); const deltaTime = clock.getDelta(); if (currentMixer) { currentMixer.update(deltaTime); } if (currentVrm) { currentVrm.update(deltaTime); } renderer.render(scene, camera); } scene.background = new THREE.Color( 0xffffff ); const directionalLight = new THREE.DirectionalLight(0xffffff); directionalLight.position.set(1, 1, 1); scene.add(directionalLight); const ambientLight = new THREE.AmbientLight(0x333333); scene.add(ambientLight); const controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.2; controls.enableRotate = true; controls.target.set( 0.0, 1.0, 0.0 ); function floor_default(){ const floor = new Mesh( new BoxGeometry(50, 100), new MeshLambertMaterial({ color: 0xffffff, depthWrite: true, }) ); floor.position.y = -1.0; floor.rotation.x = -Math.PI / 2; scene.add(floor); } function floor_grid(){ const grid = new GridHelper(50, 100, 0xffffff, 0xffffff); scene.add(grid); grid.position.set(Math.round(0), 0, Math.round(0)); } function floor_bg(){ scene.fog = new Fog(0xffffff, 3, 20); scene.fog?.color.set(0xffffff); } floor_default(); floor_grid(); floor_bg(); update(); setInterval(() => { const r = Math.floor(Math.random() * 4 + 1); load("/vrma/" + r + ".vrma"); setTimeout(() => { load("/vrma/fly_c.vrma"); }, 10000); }, 15000); })