Three.js - 模拟太阳、地球、月亮的运动
简介
本节我们简单的模拟地球绕着太阳转,月球绕着地球转。从月球的角度看,它是在地球的 "局部空间 "中绕着地球转,地球和月球合成一组是在全局空间绕着太阳转。
基础场景
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <canvas id="canvas" width="1000" height="500"></canvas> <script type="module"> // 官网地址 import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r132/build/three.module.js' import { OrbitControls } from 'https://threejsfundamentals.org/threejs/resources/threejs/r132/examples/jsm/controls/OrbitControls.js' const canvas=document.querySelector('#canvas') const scene=new THREE.Scene(); const fov = 40 // 视野范围 const aspect = 2 // 相机默认值 画布的宽高比 canvas.width/canvas.height const near = 0.1 // 近平面 const far = 1000 // 远平面 const camera=new THREE.PerspectiveCamera(fov,aspect,near,far); camera.position.set(0,-30,50); camera.up.set(0,0,1); camera.lookAt(0,0,0); const controls = new OrbitControls(camera, canvas); controls.update(); // 渲染器 const renderer = new THREE.WebGLRenderer({ canvas, antialias: true }) // 纹理加载器 const loader = new THREE.TextureLoader(); const color = 0xffffff const intensity = 1 // 创建光源 const light = new THREE.PointLight (color, intensity) scene.add(light); function animation (time) { time *= 0.001 objects.forEach((obj) => { obj.rotation.y = time //obj.rotation.x = time } ) // 加载渲染器 renderer.render(scene, camera) // 开始动画 requestAnimationFrame(animation) } animation(); </script> </body> </html>
添加背景
-
添加星空背景,修改背景展示图片纹理。
-
const bgTexture = loader.load('../img/4.jpg') scene.background = bgTexture
添加太阳
-
// 物体网格对象 const objects = [] // 一球多用 const radius = 2 const widthSegments = 36 const heightSegments = 36 const sphereGeometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments) // 太阳 const sunTexture = loader.load('../img/1.jpg') const sunMaterial = new THREE.MeshBasicMaterial({ map: sunTexture }) const sunMesh = new THREE.Mesh(sphereGeometry, sunMaterial) // 放大3倍 sunMesh.scale.set(3, 3, 3) scene.add(sunMesh) // 放入控制对象 objects.push(sunMesh)
-
创建一个球几何体,太阳、地球、月亮都是球形,我们可以公用一个球体。
-
使用基础材质加载太阳纹理。因为灯光是点光源,发光点在中心,太阳也在中心,使用其他材质是无法接收光源。
-
太阳比其他球体大,放大3倍。
-
// 网格对象 旋转 objects.forEach((obj) => {obj.rotation.y = time })
在渲染循环中添加,使网格对象
(objects)中的物体旋转。 -
添加地球
-
View Code// 地球 const earthTexture = loader.load('../img/3.jpg') const earthMaterial = new THREE.MeshPhongMaterial({ map: earthTexture }) const earthMesh = new THREE.Mesh(sphereGeometry, earthMaterial) earthMesh.position.x = 20 scene.add(earthMesh) // 放入控制对象 objects.push(earthMesh)
这里重复使用
sphereGeometry球几何体,创建.MeshPhongMaterial()材质。将其定位在太阳的左边 20个单位。-
可以看到太阳和地球都在自转,但地球并没有绕着太阳转。
-
如果我们通过计算的方式修改地球的全局坐标围绕太阳转是可以的,但是这样很麻烦。这里我们添加一个新场景太阳系,把地球和太阳都放入场景中,旋转太阳系这个场景,因为太阳在中心,实现的效果就是地球围绕太阳转。
-
// 太阳系 物体对象 const solarSystem = new THREE.Object3D() scene.add(solarSystem) objects.push(solarSystem) solarSystem.add(sunMesh) solarSystem.add(earthMesh)
添加月球
- 同样的月球要围绕地球转,添加一个地月系到太阳系中旋转。
-
// 地月系 物体对象 const landOrbit = new THREE.Object3D() landOrbit.position.x = 20 solarSystem.add(landOrbit) objects.push(landOrbit)
定位地月系位置到原来地球的位置放入太阳系中,取消地球的定位和取消放入太阳系中
-
// 月球 const moonTexture = loader.load('../img/2.jpg') const moonMaterial = new THREE.MeshPhongMaterial({ map: moonTexture }) const moonMesh = new THREE.Mesh(sphereGeometry, moonMaterial) moonMesh.scale.set(0.5, 0.5, 0.5) moonMesh.position.x = 5 objects.push(moonMesh) // 加入地月系 landOrbit.add(earthMesh) landOrbit.add(moonMesh)
定位月球在地球左边5个单位,并缩小体积。然后全部加入地月系中。
-
-
浙公网安备 33010602011771号