import * as THREE from "three"; import shaders from '../Shaders/index' import ScenesSystem from "../System/ScenesSystem"; import ComponentBase from "../Base/ComponentBase"; export interface IFile { name: string buffer?: ArrayBuffer uv?: ArrayLike normal?: ArrayLike position?: ArrayLike } export interface IModel { name: string transform: { translation: THREE.Vector3 } } export class Model extends THREE.Mesh { name: string positionV: THREE.Vector3 material: THREE.ShaderMaterial showProgress: number hideProgress: number private fade: number private visibility: boolean private static shaderMaterial = new THREE.ShaderMaterial({ uniforms: { opacity: { value: 0.5 }, u_alphatest: { value: 1 }, map: { value: undefined } }, vertexShader: shaders.mesh.vs, fragmentShader: shaders.mesh.fs, transparent: true, side: THREE.DoubleSide }) constructor(model: IModel) { super() this.name = model.name this.material = Model.shaderMaterial.clone() this.positionV = new THREE.Vector3().copy(model.transform.translation); this.showProgress = 0 this.hideProgress = 0 this.fade = 1 this.visibility = true this.frustumCulled = false } // public setVisible( visibility:boolean ) { // this.visibility = visibility; // } // public update( camera: THREE.Camera ) { // let distance = camera.position.distanceTo( this.positionV ); // this.fade = THREE.Math.clamp( this.fade + (this.visibility ? 0.016 / 2 : -0.016 / 2 ), 0, 1 ); // this.material.uniforms["u_alphatest"].value = this.fade; // this.visible = (distance < 30 && this.fade != 0); // } } /** * 模型组件 */ export class Component extends ComponentBase { private models: Map = new Map(); private static bufferGeometry = new THREE.BufferGeometry() private static texture = new THREE.Texture() get list() { return Array.from(this.models.values()) } add(model: IModel) { if (!model.name) { throw new Error('title.name is require') } this.models.set(model.name, new Model(model)) } get(name: string): Model { return this.models.get(name) } setObj(file: IFile) { const model = this.get(file.name) const geometry = Component.bufferGeometry.clone() geometry.addAttribute('normal', new THREE.BufferAttribute(new Float32Array(file.normal), 3, false)) geometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(file.position), 3, false)) geometry.addAttribute('uv', new THREE.BufferAttribute(new Float32Array(file.uv), 2, false)) model.geometry = geometry this.root.get(ScenesSystem.name).scene.add(model) } setTexture(file: IFile) { const material = this.get(file.name).material const texture = Component.texture.clone() const blob = new Blob([file.buffer]); const data = URL.createObjectURL(blob) const img = new Image(); img.src = data; img.onload = () => { texture.image = img texture.format = THREE.RGBFormat; texture.needsUpdate = true; material.uniforms.map.value = texture; material.needsUpdate = true } } } /** * 模型组件实例 */ export const ModelComponent = new Component()