Научит вас создавать трехмерную солнечную систему с помощью Three.js.

внешний интерфейс JavaScript WebGL
Научит вас создавать трехмерную солнечную систему с помощью Three.js.

предисловие

Автор считает Three.js отличным фреймворком, почему я это говорю, потому что он позволяет нам легко создавать трехмерный мир, даже если автор написал этот урок, вы можете создать солнечную систему, в этом трехмерном мир ты создатель. Ха-ха! Кажется, это немного преувеличено! !

Полный эффект 3D солнечной системы

Изучите основы астрономии

Прежде чем научиться создавать эту трехмерную солнечную систему, сначала усвойте основные астрономические знания: в солнечной системе есть «восемь планет», а именно: Меркурий, Венера, Земля, Марс, Юпитер, Сатурн, Уран и Нептун в порядке убывания расстояния от них. солнце. Большинство направлений вращения восьми планет совпадают с направлениями их вращения. Единственными исключениями являются Венера и Уран. Венера вращается в направлении, противоположном ее вращению. Уран, напротив, «катится» по своей орбите. Например, вращение Земли составляет 23,9 часа в сутки, а ее оборот составляет 365,2 дня в году, тогда как вращение соседнего Марса составляет 24,6 часа в сутки, а его обращение составляет 687 дней в году.Другие планеты также имеют другую скорость вращения и вращения. С помощью этой информации вы можете определить некоторые основные правила

image.png

Узнайте о трех фреймворках

Некоторые основные концепции Three I am inСамый простой способ построить автосалон Three.js 3DВ этой статье также дается приблизительное введение.Чтобы углубить понимание учащихся, автор возьмет пример относительно Солнечной системы.

  1. СценыSenceЭто эквивалентно Солнечной системе. Во Вселенной существует бесчисленное множество галактик. Например, Солнечная система, о которой мы говорим сейчас. Другие галактики могут быть добавлены в будущем. Это не может добавляться вечно. o(╥﹏╥ )о
  2. камераCarmaНастоящий космический телескоп Хаббл
  3. геометрияGeometryЭквивалент солнца и восьми планет
  4. контрольControlsВы прямо "создатель"

С помощью этих концепций мы создаем некоторые функции, которые взаимно однозначно соответствуют

полный эффект

屏幕录制2021-07-12 下午2.34.26.gif

Введите учебник

Сначала представим объекты, которые будут использоваться Three

  import {
        Group,
        Mesh,
        MeshBasicMaterial,
        PerspectiveCamera,
        PointCloud,
        PointCloudMaterial,
        Scene,
        SphereGeometry,
        TextureLoader,
        Vector3,
        WebGLRenderer
    } from 'three'
     import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js'

Сцена (Солнечная система), Камера (телескоп Хаббл), Управление (Создатель)

//场景
const setScene = () => {
        scene = new Scene()
        renderer = new WebGLRenderer({
            antialias: true,
        })
        renderer.setSize(innerWidth, innerHeight)
        document.querySelector('#planet').appendChild(renderer.domElement)
    }
//相机
const setCamera = () => {
        camera = new PerspectiveCamera(60, innerWidth / innerHeight, 1, 100000)
        camera.position.set(0, 500, 2000)
        camera.lookAt(scene.position)
    }
//控制    
 const setControls = () => {
        controls = new OrbitControls(camera, renderer.domElement)
    }        

Создаем фон солнечной системы (звездный фон)

Этот эффект гипсофилы является фоном Солнечной системы.Применительно к системе частиц Three плотность планет может регулироваться сама по себе.

 const starForge = () => {
        const starQty = 10000
        const geometry = new SphereGeometry(10000, 100, 50)
        const materialOptions = {}
        const starStuff = new PointCloudMaterial(materialOptions)
        geometry.vertices = []
        for (let i = 0; i < starQty; i++) {
            let starVertex = new Vector3()
            starVertex.x = Math.random() * 20000 - 10000
            starVertex.y = Math.random() * 20000 - 10000
            starVertex.z = Math.random() * 20000 - 10000
            geometry.vertices.push(starVertex)
        }
        const stars = new PointCloud(geometry, starStuff)
        scene.add(stars)
    }

Эффект следующий:

image.png

Прежде чем создавать солнце и планеты, поговорим о законе вращения планет и обращения одновременно.

屏幕录制2021-07-12 上午11.23.20.gif

Режим вращения: существует три способа реализации функции вращения.

  1. Повернуть камеру
  2. Повернуть всю сцену (Scene)
  3. Повернуть один элемент

Потому что скорость вращения и скорость обращения каждой планеты здесь разные. Таким образом, установка общего поворота невозможна, поэтому задайте разные свойства поворота для каждого элемента.

Планеты должны установить для себя позиционное смещение, чтобы они могли вращаться вокруг Солнца. Возьмем, к примеру, Меркурий:mercury.position.x -= 300, при установкеmercury.rotation.yсобственности, он будет осуществлять вращение. Потому что его положение по оси Y изменилось.

когда мы переехалиmercuryчас,mercuryParentПоложениеmercuryParentсодержитmercury, так повернутьmercuryParentчас,mercuryТакже вращается вокруг начальной оси Y по умолчанию. Таким образом, создание стольких групп означает одновременное вращение каждой планеты с разными скоростями и оборотами. Что касается установки следующих кодовых значений, то они приблизительно определяются в соответствии со временем, которое требуется планете, чтобы совершить один оборот за один день и один оборот за один год.

//设置公转函数
const revolution = () => {
        mercuryParent.rotation.y += 0.015
        venusParent.rotation.y += 0.0065
        earthParent.rotation.y += 0.05
        marsParent.rotation.y += 0.03
        jupiterParent.rotation.y += 0.001
        saturnParent.rotation.y += 0.02
        uranusParent.rotation.y += 0.09
        neptuneParent.rotation.y += 0.001
    }
    //设置自转函数
    const selfRotation = () => {
        sun.rotation.y += 0.004
        mercury.rotation.y += 0.002
        venus.rotation.y += 0.005
        earth.rotation.y += 0.01
        mars.rotation.y += 0.01
        jupiter.rotation.y += 0.08
        saturn.rotation.y += 1.5
        uranus.rotation.y += 1
        neptune.rotation.y += 0.1
    }

Создайте солнце и восемь планет

Создавайте галактики с помощью геометрических сфер + текстурных карт

Сначала поговорим о том, как создается, используется солнцеSphereGeometryСоздайте сферу, используяMeshBasicMaterialДобавляя текстуры, солнце самое большое по массе, поэтому значение самое большое при настройке сферы. Изображение ниже представляет собой текстурную карту солнца.

sun.jpg

  // 添加设置太阳
    let sun, sunParent
    const setSun = () => {
        sun = new Group()//建立一个组
        sunParent = new Group()
        scene.add(sunParent) //把组都添加到场景里
        loader.load('src/assets/universe/sun.jpg', (texture) => {
            const geometry = new SphereGeometry(500, 20, 20) //球体模型
            const material = new MeshBasicMaterial({map: texture}) //材质 将图片解构成THREE能理解的材质
            const mesh = new Mesh(geometry, material)  //网孔对象 第一个参数是几何模型(结构),第二参数是材料(外观)
            sun.add(mesh)//添加到组里
            sunParent.add(sun)
        })
    }

image.png

Созданы один за другим в соответствии с ближайшими к солнцу

Создать Меркурий

Меркурий находится ближе всего к Солнцу и имеет наименьшую массу среди всех планет, поэтому значение сферы также имеет наименьшее значение. Текстурная карта Меркурия нижеmercury.jpg

 let mercury, mercuryParent
    const setMercury = () => {
        mercury = new Group()
        mercuryParent = new Group()
        scene.add(mercuryParent)
        loader.load('src/assets/universe/mercury.jpg', (texture) => {
            const geometry = new SphereGeometry(25, 20, 20) //球体模型
            const material = new MeshBasicMaterial({map: texture}) //材质 将图片解构成THREE能理解的材质
            const mesh = new Mesh(geometry, material)  //网孔对象 第一个参数是几何模型(结构),第二参数是材料(外观)
            mercury.position.x -= 600
            mercury.add(mesh)//添加到组里
            mercuryParent.add(mercury)
        })
    }

image.png

Создать Венеру

image.pngO(∩_∩)О, ха-ха~ Это должно быть изображение ниже, это карта текстуры планеты Венера, не используйте ее неправильно! !

venus.jpg

  let venus, venusParent
    const setVenus = () => {
        venus = new Group()//建立一个组
        venusParent = new Group()
        scene.add(venusParent)
        loader.load('src/assets/universe/venus.jpg', (texture) => {
            const geometry = new SphereGeometry(100, 20, 20) //球体模型
            const material = new MeshBasicMaterial({map: texture}) //材质 将图片解构成THREE能理解的材质
            const mesh = new Mesh(geometry, material)  //网孔对象 第一个参数是几何模型(结构),第二参数是材料(外观)
            venus.position.x -= 700
            venus.add(mesh)//添加到组里
            venusParent.add(venus)
        })
    }

image.png

земной шар

Как же нам не иметь своего дома, такой красивый дом нужно хорошо охранять! !

earth.jpg

let earth, earthParent
    const setEarth = () => {
        earth = new Group()//建立一个组
        earthParent = new Group()
        scene.add(earthParent)
        loader.load('src/assets/universe/earth.jpg', (texture) => {
            const geometry = new SphereGeometry(100, 20, 20) //球体模型
            const material = new MeshBasicMaterial({map: texture}) //材质 将图片解构成THREE能理解的材质
            const mesh = new Mesh(geometry, material)  //网孔对象 第一个参数是几何模型(结构),第二参数是材料(外观)
            earth.position.x -= 900
            earth.add(mesh)//添加到组里
            earthParent.add(earth)
        })
    }

image.png

Марс, Юпитер, Сатурн, Уран, Нептун

Следующие настройки планет одинаковы, различаются только параметры вращения, вращения и размера планеты.

Затем карты текстур, соответствующие планетам, также рассылаются всем по очереди.

текстурная карта Марса

mars.jpg

Текстурная карта Юпитера

jupiter.jpg

Текстурная карта Сатурна

saturn.jpg

Текстурная карта Урана

uranus.jpg

Текстурная карта Нептунаneptune.jpg

наконец

Была создана трехмерная солнечная система. Этот пример также очень подходит для студентов, которые только начали работать с three.js. Цель состоит в том, чтобы повысить их интерес к трехмерности и улучшить их чувство достижения. Конечно, мы также можем добавить некоторые функции в этот список, такие как позиционирование и маркировка информации о некоторых планетах, щелчок по планете, чтобы войти внутрь планеты, использование окна неба для создания эффекта панорамы VR и так далее. . Кроме того, моему брату нелегко найти эти карты текстур планет, особенно при поиске Венеры😏, я надеюсь, что если вам понравилась эта статья, вы можете поставить большой палец вверх и подбодрить меня. В будущем мой брат обязательно создаст для вас больше хороших статей, спасибо! ! ^_^

屏幕录制2021-07-12 下午2.34.26.gif

полный код

<template>
    <div id="planet">

    </div>
</template>
<script setup>
    import {onMounted} from 'vue'
    import {
        Group,
        Mesh,
        MeshBasicMaterial,
        PerspectiveCamera,
        PointCloud,
        PointCloudMaterial,
        Scene,
        SphereGeometry,
        TextureLoader,
        Vector3,
        WebGLRenderer
    } from 'three'
    import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js'

    const loader = new TextureLoader() //引入模型的loader实例
    let scene, camera, renderer, group, controls // 定义所有three实例变量

    // 创建场景
    const setScene = () => {
        scene = new Scene()
        renderer = new WebGLRenderer({
            antialias: true,
        })
        renderer.setSize(innerWidth, innerHeight)
        document.querySelector('#planet').appendChild(renderer.domElement)
    }

    // 创建相机
    const setCamera = () => {
        camera = new PerspectiveCamera(60, innerWidth / innerHeight, 1, 100000)
        camera.position.set(0, 500, 2000)
        camera.lookAt(scene.position)
    }

    // 设置模型控制
    const setControls = () => {
        controls = new OrbitControls(camera, renderer.domElement)
    }
    
    // 添加设置太阳
    let sun, sunParent
    const setSun = () => {
        sun = new Group()//建立一个组
        sunParent = new Group()
        scene.add(sunParent) //把组都添加到场景里
        loader.load('src/assets/universe/sun.jpg', (texture) => {
            const geometry = new SphereGeometry(500, 20, 20) //球体模型
            const material = new MeshBasicMaterial({map: texture}) //材质 将图片解构成THREE能理解的材质
            const mesh = new Mesh(geometry, material)  //网孔对象 第一个参数是几何模型(结构),第二参数是材料(外观)
            sun.add(mesh)//添加到组里
            sunParent.add(sun)
        })
    }

    // 设置水星
    let mercury, mercuryParent
    const setMercury = () => {
        mercury = new Group()//建立一个组
        mercuryParent = new Group()
        scene.add(mercuryParent)
        loader.load('src/assets/universe/mercury.jpg', (texture) => {
            const geometry = new SphereGeometry(25, 20, 20) //球体模型
            const material = new MeshBasicMaterial({map: texture}) //材质 将图片解构成THREE能理解的材质
            const mesh = new Mesh(geometry, material)  //网孔对象 第一个参数是几何模型(结构),第二参数是材料(外观)
            mercury.position.x -= 600
            mercury.add(mesh)//添加到组里
            mercuryParent.add(mercury)
        })
    }

    //设置金星
    let venus, venusParent
    const setVenus = () => {
        venus = new Group()//建立一个组
        venusParent = new Group()
        scene.add(venusParent)
        loader.load('src/assets/universe/venus.jpg', (texture) => {
            const geometry = new SphereGeometry(100, 20, 20) //球体模型
            const material = new MeshBasicMaterial({map: texture}) //材质 将图片解构成THREE能理解的材质
            const mesh = new Mesh(geometry, material)  //网孔对象 第一个参数是几何模型(结构),第二参数是材料(外观)
            venus.position.x -= 700
            venus.add(mesh)//添加到组里
            venusParent.add(venus)
        })
    }
    //设置地球
    let earth, earthParent
    const setEarth = () => {
        earth = new Group()//建立一个组
        earthParent = new Group()
        scene.add(earthParent)
        loader.load('src/assets/universe/earth.jpg', (texture) => {
            const geometry = new SphereGeometry(100, 20, 20) //球体模型
            const material = new MeshBasicMaterial({map: texture}) //材质 将图片解构成THREE能理解的材质
            const mesh = new Mesh(geometry, material)  //网孔对象 第一个参数是几何模型(结构),第二参数是材料(外观)
            earth.position.x -= 900
            earth.add(mesh)//添加到组里
            earthParent.add(earth)
        })
    }
//设置火星
    let mars, marsParent
    const setMars = () => {
        mars = new Group()//建立一个组
        marsParent = new Group()
        scene.add(marsParent)
        loader.load('src/assets/universe/mars.jpg', (texture) => {
            const geometry = new SphereGeometry(85, 20, 20) //球体模型
            const material = new MeshBasicMaterial({map: texture}) //材质 将图片解构成THREE能理解的材质
            const mesh = new Mesh(geometry, material)  //网孔对象 第一个参数是几何模型(结构),第二参数是材料(外观)
            mars.position.x -= 1200
            mars.add(mesh)//添加到组里
            marsParent.add(mars)
        })
    }

    // 设置木星
    let jupiter, jupiterParent
    const setJupiter = () => {
        jupiter = new Group()//建立一个组
        jupiterParent = new Group()
        scene.add(jupiterParent)
        loader.load('src/assets/universe/jupiter.jpg', (texture) => {
            const geometry = new SphereGeometry(150, 20, 20) //球体模型
            const material = new MeshBasicMaterial({map: texture}) //材质 将图片解构成THREE能理解的材质
            const mesh = new Mesh(geometry, material)  //网孔对象 第一个参数是几何模型(结构),第二参数是材料(外观)
            jupiter.position.x -= 1500
            jupiter.add(mesh)//添加到组里
            jupiterParent.add(jupiter)
        })
    }

    // 设置土星
    let saturn, saturnParent
    const setSaturn = () => {
        saturn = new Group()//建立一个组
        saturnParent = new Group()
        scene.add(saturnParent)
        loader.load('src/assets/universe/saturn.jpg', (texture) => {
            const geometry = new SphereGeometry(120, 20, 20) //球体模型
            const material = new MeshBasicMaterial({map: texture}) //材质 将图片解构成THREE能理解的材质
            const mesh = new Mesh(geometry, material)  //网孔对象 第一个参数是几何模型(结构),第二参数是材料(外观)
            saturn.position.x -= 1800
            saturn.add(mesh)//添加到组里
            saturnParent.add(saturn)
        })
    }

    //设置天王星
    let uranus, uranusParent
    const setUranus = () => {
        uranus = new Group()
        uranusParent = new Group()
        scene.add(uranusParent)
        loader.load('src/assets/universe/uranus.jpg', (texture) => {
            const geometry = new SphereGeometry(50, 20, 20) //球体模型
            const material = new MeshBasicMaterial({map: texture}) //材质 将图片解构成THREE能理解的材质
            const mesh = new Mesh(geometry, material)  //网孔对象 第一个参数是几何模型(结构),第二参数是材料(外观)
            uranus.position.x -= 2100
            uranus.add(mesh)//添加到组里
            saturnParent.add(uranus)
        })
    }

    //设置海王星
    let neptune, neptuneParent
    const setNeptune = () => {
        neptune = new Group()
        neptuneParent = new Group()
        scene.add(neptuneParent)
        loader.load('src/assets/universe/neptune.jpg', (texture) => {
            const geometry = new SphereGeometry(50, 20, 20) //球体模型
            const material = new MeshBasicMaterial({map: texture}) //材质 将图片解构成THREE能理解的材质
            const mesh = new Mesh(geometry, material)  //网孔对象 第一个参数是几何模型(结构),第二参数是材料(外观)
            neptune.position.x -= 2300
            neptune.add(mesh)//添加到组里
            neptuneParent.add(neptune)
        })
    }

//监听浏览器改变大小时重新渲染
    function onWindowResize() {
        const WIDTH = window.innerWidth,
            HEIGHT = window.innerHeight
        camera.aspect = WIDTH / HEIGHT
        camera.updateProjectionMatrix()
        renderer.setSize(WIDTH, HEIGHT)
    }

//设置公转函数
    const revolution = () => {
        mercuryParent.rotation.y += 0.015
        venusParent.rotation.y += 0.0065
        earthParent.rotation.y += 0.05
        marsParent.rotation.y += 0.03
        jupiterParent.rotation.y += 0.01
        saturnParent.rotation.y += 0.02
        uranusParent.rotation.y += 0.09
        neptuneParent.rotation.y += 0.01
    }

    //设置自转
    const selfRotation = () => {
        sun.rotation.y += 0.004
        mercury.rotation.y += 0.002
        venus.rotation.y += 0.005
        earth.rotation.y += 0.01
        mars.rotation.y += 0.01
        jupiter.rotation.y += 0.08
        saturn.rotation.y += 1.5
        uranus.rotation.y += 1
        neptune.rotation.y += 0.1
    }

    // 设置太阳系背景
    const starForge = () => {
        const starQty = 10000
        const geometry = new SphereGeometry(10000, 100, 50)
        const materialOptions = {}
        const starStuff = new PointCloudMaterial(materialOptions)
        geometry.vertices = []
        for (let i = 0; i < starQty; i++) {
            let starVertex = new Vector3()
            starVertex.x = Math.random() * 20000 - 10000
            starVertex.y = Math.random() * 20000 - 10000
            starVertex.z = Math.random() * 20000 - 10000
            geometry.vertices.push(starVertex)
        }
        const stars = new PointCloud(geometry, starStuff)
        scene.add(stars)
    }


    // 循环场景 、相机、 位置更新
    const loop = () => {
        requestAnimationFrame(loop)
        revolution()
        selfRotation()
        renderer.render(scene, camera)
        camera.lookAt(scene.position)
    }

  //初始化所有函数
    const init = () => {
        setScene() //设置场景
        setCamera() //设置相机
        setSun() // 设置太阳
        setMercury() //设置水星
        setVenus() //设置金星
        setEarth() // 地球
        setMars() //火星
        setJupiter() // 木星
        setSaturn() // 土星
        setUranus()// 天王星
        setNeptune()//海王星
        starForge()//设置满天星背景
        setControls() //设置可旋转控制
        loop() // 循环动画
    }

    onMounted(init)
    window.addEventListener('resize', onWindowResize)

</script>



image.png