import * as THREE from "three" import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' import { Object3D, Mesh, ShaderMaterial, IcosahedronGeometry, TextureLoader, MeshStandardMaterial, Scene } from "three"; import { GameController } from "./controller" import { VaringBox } from "./shader_test" export class FooGame { scene: THREE.Scene; camera: THREE.Camera; renderer: THREE.WebGLRenderer; cam_fov = 70; //视角大小 cam_aspect = window.innerWidth / window.innerHeight; gltfLoader: GLTFLoader; textureLoader: TextureLoader; updateMap: Object; controller: GameController; constructor() { this.camera = new THREE.PerspectiveCamera(this.cam_fov, this.cam_aspect, 0.01, 10) this.camera.position.x = -1; this.camera.position.y = 1; this.camera.position.z = 1; this.scene = new THREE.Scene(); this.renderer = new THREE.WebGLRenderer(); this.renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(this.renderer.domElement); this.gltfLoader = new GLTFLoader(); this.updateMap = {}; this.controller = new GameController(document.body); this.controller.bindMoveKeys(this.camera); this.controller.bindMouseLookAt(this.camera, this.scene); this.textureLoader = new TextureLoader(); this.animate(); } animate() { requestAnimationFrame(() => { this.animate(); }); this.updateObjects(this.scene); this.renderer.render(this.scene, this.camera); } private updateObjects(obj: Object3D) { if ("update" in obj && (typeof obj["update"] == "function")) { var f: Function = obj["update"]; f.call(obj, obj); } if (obj.children && obj.children.length > 0) { obj.children.forEach(child => { this.updateObjects(child); }); } } findObjectByName(name: string, parent: Object3D = this.scene) { let obj = parent.getObjectByName(name); if (obj) return obj; if (parent.children && parent.children.length > 0) { parent.children.forEach(child => { obj = this.findObjectByName(name, child); if (obj) { return obj; } }); } } static setUpdate(obj: Object3D, fn: Function) { Object.defineProperty(obj, "update", { writable: true, value: fn }); } /** * 创建球体 */ createSphere() { let geo = new THREE.SphereBufferGeometry(15, 100,100); //let geo = new THREE.BoxBufferGeometry(5,5,5); let mat = new THREE.MeshStandardMaterial(); mat.side = THREE.BackSide; //设置渲染面会背面 mat.blending = THREE.NormalBlending; let obj = new THREE.Mesh(geo, mat); return obj; } /** * 加载场景 * @param callback */ loadScene(callback: Function) { this.gltfLoader.load("./scenes/foo.gltf", gltf => { this.scene.add(gltf.scene); let s = this.findObjectByName("Sphere"); if(s && s instanceof Mesh){ let mesh :Mesh = s; if(mesh.material instanceof MeshStandardMaterial){ let mat:MeshStandardMaterial = mesh.material; mat .side = THREE.BackSide; } } /** * 加载二位图片作为场景背景 */ this.textureLoader.load("./textures/skybox2.jpg", (tex) => { //this.scene.background = tex; //直接设置二维背景 //设置天空盒子背景 let skybox = this.createSphere(); if (skybox.material instanceof MeshStandardMaterial) { let mat: MeshStandardMaterial = skybox.material; mat.emissive = new THREE.Color(0x00ffff); mat.emissiveMap = tex; } //this.scene.add(skybox); }); /** * 加载完毕,回调 */ callback(); }); } } let game = new FooGame(); game.loadScene(() => { let vBox = new VaringBox(); vBox.material.wireframe = true; let geo = new IcosahedronGeometry(1, 4); let box2 = new THREE.Mesh(geo, vBox.material); box2.position.x = 2; box2.position.z = 1; box2.position.y = 2; game.scene.add(box2); FooGame.setUpdate(box2, (obj: Mesh) => { obj.rotateY(0.01); obj.material = vBox.material; if (obj.material instanceof ShaderMaterial) { let mat: ShaderMaterial = obj.material; mat.uniforms.time.value = performance.now() / 500; } }); game.camera.lookAt(new THREE.Vector3(0, 0, 0)); })