UNPKG

disfigure

Version:

A library to rig non-rigged 3D models

211 lines (132 loc) 4.67 kB
// disfigure // // Non-core functionality for creating a predefined 3D world. // This is mainly done to make concise demos and examples. import { CanvasTexture, CircleGeometry, Color, DirectionalLight, Mesh, MeshLambertMaterial, PCFSoftShadowMap, PerspectiveCamera, Scene, WebGPURenderer } from 'three'; import { OrbitControls } from "three/addons/controls/OrbitControls.js"; import Stats from 'three/addons/libs/stats.module.js'; var renderer, scene, camera, light, cameraLight, controls, ground, userAnimationLoop, stats, everybody = []; // creates a default world with primary attributes. the options // is a collection of flags that turn on/off specific features: // { // lights: true, // controls: true, // ground: true, // antialias: true, // shadows: true, // stats: false, // } class World { constructor( options ) { renderer = new WebGPURenderer( { antialias: options?.antialias ?? true } ); renderer.setSize( innerWidth, innerHeight ); renderer.shadowMap.enabled = options?.shadows ?? true; renderer.shadowMap.type = PCFSoftShadowMap; document.body.appendChild( renderer.domElement ); document.body.style.overflow = 'hidden'; document.body.style.margin = '0'; scene = new Scene(); scene.background = new Color( 'whitesmoke' ); camera = new PerspectiveCamera( 30, innerWidth/innerHeight ); camera.position.set( 0, 1.5, 4 ); if ( options?.stats ?? false ) { stats = new Stats(); document.body.appendChild( stats.dom ); } // stats if ( options?.lights ?? true ) { light = new DirectionalLight( 'white', 1.5 ); light.position.set( 0, 14, 7 ); if ( options?.shadows ?? true ) { light.shadow.mapSize.width = 2048; light.shadow.mapSize.height = light.shadow.mapSize.width; light.shadow.camera.near = 1; light.shadow.camera.far = 50; light.shadow.camera.left = -5; light.shadow.camera.right = 5; light.shadow.camera.top = 5; light.shadow.camera.bottom = -5; light.shadow.normalBias = 0.01; light.autoUpdate = false; light.castShadow = true; } // shadows scene.add( light ); cameraLight = new DirectionalLight( 'white', 1.5 ); cameraLight.target = scene; camera.add( cameraLight ); scene.add( camera ); } // lights if ( options?.controls ?? true ) { controls = new OrbitControls( camera, renderer.domElement ); controls.enableDamping = true; controls.target.set( 0, 0.9, 0 ); } // controls if ( options?.ground ?? true ) { // generate ground texture var canvas = document.createElement( 'CANVAS' ); canvas.width = 128; canvas.height = 128; var context = canvas.getContext( '2d' ); context.fillStyle = 'white'; context.filter = 'blur(10px)'; context.beginPath(); context.arc( 64, 64, 38, 0, 2*Math.PI ); context.fill(); ground = new Mesh( new CircleGeometry( 32 ), new MeshLambertMaterial( { color: 'antiquewhite', transparent: true, map: new CanvasTexture( canvas ) } ) ); ground.receiveShadow = true; ground.rotation.x = -Math.PI / 2; ground.renderOrder = -1; scene.add( ground ); } // ground window.addEventListener( "resize", ( /*event*/ ) => { camera.aspect = innerWidth/innerHeight; camera.updateProjectionMatrix( ); renderer.setSize( innerWidth, innerHeight ); } ); renderer.setAnimationLoop( defaultAnimationLoop ); } // World.constructor } // World class AnimateEvent extends Event { #target; constructor() { super( 'animate' ); } get target() { return this.#target; } set target( t ) { this.#target = t; } } var animateEvent = new AnimateEvent( ); // default animation loop that dispatches animation events // to the window and to each body in the scene function defaultAnimationLoop( time ) { try { animateEvent.time = time; window.dispatchEvent( animateEvent ); everybody.forEach( ( p )=>{ p.update( ); p.dispatchEvent( animateEvent ); } ); if ( userAnimationLoop ) userAnimationLoop( time ); if ( controls ) controls.update( ); if ( stats ) stats.update( ); renderer.render( scene, camera ); } catch ( err ) { renderer.setAnimationLoop( null ); throw ( err ); } } // function to set animation loop, for when the user is // scared to use events function setAnimationLoop( animationLoop ) { userAnimationLoop = animationLoop; } export { World, renderer, scene, camera, light, cameraLight, controls, ground, everybody, setAnimationLoop };