import type Viewer from "../Viewer"; import { GUI } from "three/examples/jsm/libs/lil-gui.module.min"; import * as THREE from "three"; class Params { x: number = 0; y: number = 0; z: number = 100; size: number = 3; length: number = 10; radius: number = 16; visible: boolean = true; widthSegments: number = 64; heightSegments: number = 32; color: string = "#000"; } export default class Earth { protected viewer: Viewer; public particles_init_position!: number; public zprogress!: number; // 声明点在z轴上移动的进度 public zprogress_second!: number; // 声明同上(第二个几何点) public particles_first!: any[]; // 声明粒子1 public particles_second!: any[]; // 声明粒子1 public parameters!: any; // 声明点的参数 public materials!: any[]; // 声明点材质 public cloudParameter_first!: any; // 声明流动的云对象1(包含路径、云实例) public cloudParameter_second!: any; // 声明流动的云对象2(包含路径、云实例) public renderCloudMove_first!: any; // 声明云流动的渲染函数1 public renderCloudMove_second!: any; // 声明云流动的渲染函数1 public gui!: any; // 声明调试工具 constructor(viewer: Viewer) { this.viewer = viewer; this.materials = []; this.gui = new GUI(); this.particles_init_position = -this.viewer.zAxisNumber - this.viewer.depth / 2; this.zprogress = this.particles_init_position; this.zprogress_second = this.particles_init_position * 2; this.particles_first = this.initSceneStar(this.particles_init_position); this.particles_second = this.initSceneStar(this.zprogress_second); this.cloudParameter_first = this.initTubeRoute( [ new THREE.Vector3(-this.viewer.viewerDom.clientWidth / 10, 0, -this.viewer.depth / 2), new THREE.Vector3(-this.viewer.viewerDom.clientWidth / 4, this.viewer.viewerDom.clientHeight / 8, 0), new THREE.Vector3(-this.viewer.viewerDom.clientWidth / 4, 0, this.viewer.zAxisNumber) ], 400, 200 ); this.cloudParameter_second = this.initTubeRoute( [ new THREE.Vector3(this.viewer.viewerDom.clientWidth / 8, this.viewer.viewerDom.clientHeight / 8, -this.viewer.depth / 2), new THREE.Vector3(this.viewer.viewerDom.clientWidth / 8, this.viewer.viewerDom.clientHeight / 8, this.viewer.zAxisNumber) ], 200, 100 ); this.renderCloudMove_first = this.initCloudMove(this.cloudParameter_first, 0.0002); this.renderCloudMove_second = this.initCloudMove(this.cloudParameter_second, 0.0008, 0.001); this.initGUI(); const animate = () => { if (this.viewer.isDestroy) return; requestAnimationFrame(animate); this.renderStarMove(); this.renderCloudMove_first(); this.renderCloudMove_second(); this.viewer.updateDom(); this.viewer.renderDom(); }; animate(); } // 初始化gui public initGUI = () => { const params = new Params(); this.gui.add(params, "x", -1500, 1500).onChange((x: number) => { //点击颜色面板,e为返回的10进制颜色 this.viewer.Sphere_Group.position.x = x; }); this.gui.add(params, "y", -50, 1500).onChange((y: number) => { //点击颜色面板,e为返回的10进制颜色 this.viewer.Sphere_Group.position.y = y; }); this.gui.add(params, "z", -200, 1000).onChange((z: number) => { //点击颜色面板,e为返回的10进制颜色 this.viewer.Sphere_Group.position.z = z; }); // this.gui.add(params, "widthSegments", 0, 64).onChange((widthSegments: number) => { // //点击颜色面板,e为返回的10进制颜色 // // this.viewer.sphereGeometry.parameters.widthSegments = widthSegments; // }); // this.gui.add(params, "heightSegments", 0, 32).onChange((heightSegments: number) => { // //点击颜色面板,e为返回的10进制颜色 // // this.viewer.sphereGeometry.parameters.heightSegments = heightSegments; // }); // this.gui.add(params, "radius", 5, 30).onChange((radius: number) => { // //点击颜色面板,e为返回的10进制颜色 // // this.viewer.sphereGeometry.parameters.radius = radius; // this.viewer.renderer.render(this.viewer.scene, this.viewer.camera); // }); // this.gui.add(params, "visible").onChange((e: any) => { // //这是一个单选框,因为params.visible是一个布尔值,e返回所选布尔值 // // points.visible = e // }); // this.gui.addColor(params, "color").onChange((e: any) => { // //点击颜色面板,e为返回的10进制颜色 // // pointsMaterial.color.set(e) // }); }; private initSceneStar(initZposition: number) { const geometry = new THREE.BufferGeometry(); const vertices: number[] = []; const pointsGeometry: any[] = []; const textureLoader = new THREE.TextureLoader(); const sprite1 = textureLoader.load("/images/starflake1.png"); const sprite2 = textureLoader.load("/images/starflake2.png"); this.parameters = [ [[0.6, 100, 0.75], sprite1, 50], [[0, 0, 1], sprite2, 20] ]; // 初始化500个节点 for (let i = 0; i < 500; i++) { /** * const x: number = Math.random() * 2 * width - width * 等价 * THREE.MathUtils.randFloatSpread(width) */ const x: number = THREE.MathUtils.randFloatSpread(this.viewer.viewerDom.clientWidth); const y: number = _.random(0, this.viewer.viewerDom.clientHeight / 2); const z: number = _.random(-this.viewer.depth / 2, this.viewer.zAxisNumber); vertices.push(x, y, z); } geometry.setAttribute("position", new THREE.Float32BufferAttribute(vertices, 3)); // 创建2种不同的材质的节点(500 * 2) for (let i = 0; i < this.parameters.length; i++) { const color = this.parameters[i][0]; const sprite = this.parameters[i][1]; const size = this.parameters[i][2]; this.materials[i] = new THREE.PointsMaterial({ size, map: sprite, blending: THREE.AdditiveBlending, depthTest: true, transparent: true }); this.materials[i].color.setHSL(color[0], color[1], color[2]); const particles = new THREE.Points(geometry, this.materials[i]); particles.rotation.x = Math.random() * 0.2 - 0.15; particles.rotation.z = Math.random() * 0.2 - 0.15; particles.rotation.y = Math.random() * 0.2 - 0.15; particles.position.setZ(initZposition); pointsGeometry.push(particles); this.viewer.scene.add(particles); } return pointsGeometry; } // 渲染星星的运动 public renderStarMove() { const time = Date.now() * 0.00005; this.zprogress += 1; this.zprogress_second += 1; if (this.zprogress >= this.viewer.zAxisNumber + this.viewer.depth / 2) { this.zprogress = this.particles_init_position; } else { this.particles_first.forEach((item) => { item.position.setZ(this.zprogress); }); } if (this.zprogress_second >= this.viewer.zAxisNumber + this.viewer.depth / 2) { this.zprogress_second = this.particles_init_position; } else { this.particles_second.forEach((item) => { item.position.setZ(this.zprogress_second); }); } for (let i = 0; i < this.materials.length; i++) { const color = this.parameters[i][0]; const h = ((360 * (color[0] + time)) % 360) / 360; this.materials[i].color.setHSL(color[0], color[1], parseFloat(h.toFixed(2))); } } // 初始化云的运动函数 public initCloudMove = (cloudParameter: any, speed: number, scaleSpeed = 0.0006, maxScale = 1, startScale = 0) => { let cloudProgress = 0; return () => { if (startScale < maxScale) { startScale += scaleSpeed; cloudParameter.cloud.scale.setScalar(startScale); } if (cloudProgress > 1) { cloudProgress = 0; startScale = 0; } else { cloudProgress += speed; if (cloudParameter.curve) { const point = cloudParameter.curve.getPoint(cloudProgress); if (point && point.x) { cloudParameter.cloud.position.set(point.x, point.y, point.z); } } } }; }; // 初始化流动路径 private initTubeRoute(route?: any, geometryWidth?: number, geometryHeigh?: number) { const curve = new THREE.CatmullRomCurve3(route, false); const tubeGeometry = new THREE.TubeGeometry(curve, 100, 2, 50, false); const tubeMaterial = new THREE.MeshBasicMaterial({ // color: '0x4488ff', opacity: 0, transparent: true }); const tube = new THREE.Mesh(tubeGeometry, tubeMaterial); this.viewer.scene.add(tube); const clondGeometry = new THREE.PlaneGeometry(geometryWidth, geometryHeigh); const textureLoader = new THREE.TextureLoader(); const cloudTexture = textureLoader.load("/images/cloud.png"); const clondMaterial = new THREE.MeshBasicMaterial({ map: cloudTexture, blending: THREE.AdditiveBlending, depthTest: false, transparent: true }); const cloud = new THREE.Mesh(clondGeometry, clondMaterial); this.viewer.scene.add(cloud); return { cloud, curve }; } }