Vue ThreeJs实现银河系行星运动

预览

可通过右上角调整参数,进行光影练习

代码

<template>
    <div id="body"></div>
</template>
<script>

import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min';

/*场景,渲染器,镜头,背景星星,帧率器,第一人称控制*/
let scene, renderer, camera, particleSystem, control;
let Sun,
    Mercury,  //水星
    Venus,  //金星
    Earth,
    Mars,
    Jupiter, //木星
    Saturn, //土星
    Uranus, //天王
    Neptune, //海王
    stars = [];
const cameraFar = 3000;  //镜头视距

export default {
    mounted() {

        /*renderer*/
        //渲染器
        renderer = new THREE.WebGLRenderer({ alpha: true })
        renderer.physicallyCorrectLights = true;
        renderer.shadowMap.enabled = true; //辅助线
        renderer.shadowMapSoft = true; //柔和阴影
        renderer.setClearColor('black', 1);
        renderer.setSize(window.innerWidth, window.innerHeight)
        document.getElementById('body').appendChild(renderer.domElement);

        /*scene*/
        scene = new THREE.Scene();

        /*camera*/
        camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, cameraFar);
        camera.position.set(-200, 50, 0);
        camera.lookAt(new THREE.Vector3(0, 0, 0));
        scene.add(camera);

        control = new OrbitControls(camera, renderer.domElement)
        control.update()

        /*sun skin pic*/
        // const texture = new THREE.TextureLoader().load( 'textures/land_ocean_ice_cloud_2048.jpg' );
        let sunSkinPic = new THREE.TextureLoader().load(new URL('../assets/sunCore.jpg', import.meta.url), {}, () => {
            renderer.render(scene, camera);
        });

        /*sun*/
        Sun = new THREE.Mesh(new THREE.SphereGeometry(12, 16, 16),
            new THREE.MeshLambertMaterial({
                /*color: 0xffff00,*/
                emissive: 0xdd4422,
                map: sunSkinPic
            })
        );
        Sun.name = 'Sun';
        Sun.castShadow = false;
        Sun.receiveShadow = false;
        scene.add(Sun);
        /*opacity sun*/
        let opSun = new THREE.Mesh(new THREE.SphereGeometry(14, 16, 16),
            new THREE.MeshLambertMaterial({
                side: THREE.DoubleSide,
                color: 0xff0000,
                /*emissive: 0xdd4422,*/
                transparent: true,
                opacity: .35
            })
        );

        opSun.name = 'Sun';
        scene.add(opSun);

        const plane = new THREE.Mesh(new THREE.PlaneGeometry(500, 500),
            new THREE.MeshStandardMaterial({
                side: THREE.DoubleSide,
                color: 0xffffff,
                metalness: .7,
                roughness: 0.5,
                // emissive: 0xffffff,
            })
        );
        plane.rotateX(-Math.PI / 2)
        plane.position.y = -30
        // plane.castShadow = true;
        plane.receiveShadow = true;
        scene.add(plane)

        //gui
        const gui = new GUI()

        /*planets*/
        Mercury = this.initPlanet('Mercury', 0.02, 0, 'rgb(124,131,203)', 20, 2);
        stars.push(Mercury);

        Venus = this.initPlanet('Venus', 0.012, 0, 'rgb(190,138,44)', 30, 4);
        stars.push(Venus);

        Earth = this.initPlanet('Earth', 0.010, 0, 'rgb(46,69,119)', 40, 5);
        stars.push(Earth);

        Mars = this.initPlanet('Mars', 0.008, 0, 'rgb(210,81,16)', 50, 4);
        stars.push(Mars);

        Jupiter = this.initPlanet('Jupiter', 0.006, 0, 'rgb(254,208,101)', 70, 9);
        stars.push(Jupiter);

        Saturn = this.initPlanet('Saturn', 0.005, 0, 'rgb(210,140,39)', 100, 7, {
            color: 'rgb(136,75,30)',
            innerRedius: 9,
            outerRadius: 11
        });
        stars.push(Saturn);

        Uranus = this.initPlanet('Uranus', 0.003, 0, 'rgb(49,168,218)', 120, 4);
        stars.push(Uranus);

        Neptune = this.initPlanet('Neptune', 0.002, 0, 'rgb(84,125,204)', 150, 3);
        stars.push(Neptune);



        //环境光
        let ambient = new THREE.AmbientLight(0x999999, 3);
        scene.add(ambient);

        /*太阳光*/
        let sunLight = new THREE.PointLight(0xddddaa, 6500, 500);
        sunLight.castShadow = true;
        sunLight.position.set(0, 0)
        // sunLight.scale.set(25,25,25)
        opSun.add(sunLight);
        let sunAmbient = new THREE.AmbientLight(0x999999, 3);
        opSun.add(sunAmbient)
        sunLight.shadow.mapSize.set(2048, 2048)

        /*背景星星*/
        const particles = 20000;  //星星数量
        /*buffer做星星*/
        let bufferGeometry = new THREE.BufferGeometry();

        let positions = new Float32Array(particles * 3);
        let colors = new Float32Array(particles * 3);

        let color = new THREE.Color();

        const gap = 1000; // 定义星星的最近出现位置

        for (let i = 0; i < positions.length; i += 3) {

            // positions

            /*-2gap < x < 2gap */
            let x = (Math.random() * gap * 2) * (Math.random() < .5 ? -1 : 1);
            let y = (Math.random() * gap * 2) * (Math.random() < .5 ? -1 : 1);
            let z = (Math.random() * gap * 2) * (Math.random() < .5 ? -1 : 1);

            /*找出x,y,z中绝对值最大的一个数*/
            let biggest = Math.abs(x) > Math.abs(y) ? Math.abs(x) > Math.abs(z) ? 'x' : 'z' :
                Math.abs(y) > Math.abs(z) ? 'y' : 'z';

            let pos = { x, y, z };

            /*如果最大值比n要小(因为要在一个距离之外才出现星星)则赋值为n(-n)*/
            if (Math.abs(pos[biggest]) < gap) pos[biggest] = pos[biggest] < 0 ? -gap : gap;

            x = pos['x'];
            y = pos['y'];
            z = pos['z'];

            positions[i] = x;
            positions[i + 1] = y;
            positions[i + 2] = z;

            // colors

            /*70%星星有颜色*/
            let hasColor = Math.random() > 0.3;
            let vx, vy, vz;

            if (hasColor) {
                vx = (Math.random() + 1) / 2;
                vy = (Math.random() + 1) / 2;
                vz = (Math.random() + 1) / 2;
            } else {
                vx = 1;
                vy = 1;
                vz = 1;
            }

            /*let vx = ( Math.abs(x) / n*2 ) ;
            var vy = ( Math.abs(y) / n*2 ) ;
            var vz = ( Math.abs(z) / n*2 ) ;*/

            color.setRGB(vx, vy, vz);

            colors[i] = color.r;
            colors[i + 1] = color.g;
            colors[i + 2] = color.b;
        }

        bufferGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
        bufferGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
        bufferGeometry.computeBoundingSphere();

        /*星星的material*/
        let material = new THREE.PointsMaterial({ size: 6, vertexColors: THREE.VertexColors });
        particleSystem = new THREE.Points(bufferGeometry, material);
        scene.add(particleSystem);


        //帮助模块
        const axesHelper = new THREE.AxesHelper(500)
        scene.add(axesHelper)
        axesHelper.visible = false;
        const lightHelper = new THREE.PointLightHelper(sunLight, 1, 100);
        scene.add(lightHelper);
        lightHelper.visible = false;
        plane.visible = false;


        gui.add(Sun.position, 'y').name('太阳Y轴').min(-100).max(100).onChange((val) => {
            opSun.position.y = val;
        })
        gui.add(sunLight.position, 'y').name('光源Y轴').min(-100).max(100).onChange((val) => {
            sunLight.position.y = val;
        })
        gui.add(sunAmbient, 'intensity').name('太阳环境光强度').min(0).max(10)
        gui.add(sunLight, 'intensity').name('太阳点光照强度').min(0).max(20000)
        gui.add(sunLight, 'distance').name('太阳点光照距离').min(0).max(20000)
        gui.add(sunLight, 'decay').name('太阳点光照衰减').min(0).max(5)

        gui.add(plane, 'visible').name('显示平面')
        gui.add(axesHelper, 'visible').name('显示坐标轴')
        gui.add(lightHelper, 'visible').name('显示光源辅助')


        //渲染动画
        let run = { run: true };
        gui.add(run, 'run')
        const animate = () => {
            if (run.run) {
                /*行星公转*/
                stars.forEach(star =>
                    this.moveEachStar(star)
                )
                Sun.rotation.y = (Sun.rotation.y == 2 * Math.PI ? 0.0008 * Math.PI : Sun.rotation.y + 0.0008 * Math.PI);
            }
            requestAnimationFrame(animate)
            renderer.render(scene, camera)
            lightHelper.update()
        }
        requestAnimationFrame(animate)


    },
    methods: {
        /*每一颗行星的公转*/
        moveEachStar(star) {

            star.angle += star.speed;
            if (star.angle > Math.PI * star.distance) {
                star.angle -= Math.PI * star.distance;
            }

            star.Mesh.position.set(star.distance * Math.sin(star.angle), 0, star.distance * Math.cos(star.angle));

            /*碎星带*/
            if (star.ring) {
                star.ring.position.set(star.distance * Math.sin(star.angle), 0, star.distance * Math.cos(star.angle));
            }
        },
        initPlanet(name, speed, angle, color, distance, volume, ringMsg) {
            let mesh = new THREE.Mesh(new THREE.SphereGeometry(volume, 16, 16),
                new THREE.MeshStandardMaterial({
                    color, metalness: .7,
                    roughness: 0.5,
                })
            );
            mesh.position.x = distance;
            mesh.receiveShadow = true;
            mesh.castShadow = true;

            mesh.name = name;

            /*轨道*/
            let track = new THREE.Mesh(new THREE.RingGeometry(distance - 0.2, distance + 0.2, 64, 1),
                new THREE.MeshBasicMaterial({ color: 0x888888, side: THREE.DoubleSide })
            );
            track.rotation.x = - Math.PI / 2;
            scene.add(track);

            let star = {
                name,
                speed,
                angle,
                distance,
                volume,
                Mesh: mesh
            }

            /*如果有碎星带*/
            if (ringMsg) {
                let ring = new THREE.Mesh(new THREE.RingGeometry(ringMsg.innerRedius, ringMsg.outerRadius, 32, 6),
                    new THREE.MeshBasicMaterial({ color: ringMsg.color, side: THREE.DoubleSide, opacity: .7, transparent: true })
                );

                ring.name = `Ring of ${name}`;
                ring.rotation.x = - Math.PI / 3;
                ring.rotation.y = - Math.PI / 4;
                scene.add(ring);

                star.ring = ring;
            }


            scene.add(mesh);

            return star;
        },
    }
}
</script>

完整代码

ThreeJs DEMO: 通过行星模型辅助光源阴影的练习项目

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/275566.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(12)Linux 常见的三种进程状态

&#x1f4ad; 前言&#xff1a;本章我们专门讲解进程的状态。我们先学习具体的 Linux 系统状态&#xff0c;再去介绍 OS 学科面对的概念如何理解 —— 运行态、终止态、阻塞态以及挂起态。 进程状态&#xff08;Process Status&#xff09; 什么是进程状态&#xff1f; 进程…

深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第四节 参数传递对堆栈的影响 2

深入浅出图解C#堆与栈 C# Heaping VS Stacking 第四节 参数传递对堆栈的影响 2 [深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第一节 理解堆与栈](https://mp.csdn.net/mdeditor/101021023)[深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第二节 栈基本工作原理](htt…

蓝桥杯嵌入式ADC

1.ADC原理图 2.CubeMX配置 3.ADC相关代码

sheng的学习笔记-卷积神经网络

源自吴恩达的深度学习课程&#xff0c;仅用于笔记&#xff0c;便于自行复习 导论 1&#xff09;什么是卷积神经网络 卷积神经网络&#xff0c;也就是convolutional neural networks &#xff08;简称CNN&#xff09;&#xff0c;使用卷积算法的神经网络&#xff0c;常用于计…

Python从入门到熟练

文章目录 Python 环境Python 语法与使用基础语法数据类型注释数据类型介绍字符串列表元组集合字典 类型转换标识符运算符算数运算符赋值运算符复合运算符 字符串字符串拼接字符串格式化 判断语句bool 类型语法if 语句if else 语句if elif else 语句 循环语句while循环for 循环r…

2023年度业务风险报告:四个新风险趋势

目录 倒票的黄牛愈加疯狂 暴增的恶意网络爬虫 愈加猖獗的羊毛党 层出不穷的新风险 业务风险呈现四个趋势 防御云业务安全情报中心“2023年业务风险数据”统计显示&#xff0c;恶意爬虫风险最多&#xff0c;占总数的37.8%&#xff1b;其次是虚假账号注册&#xff0c;占18.79%&am…

【node-express】实现省县市/区三级联动接口

省县市/区三级联动接口 介绍接口步骤代码部分 介绍 源码地址&#xff1a;https://github.com/thinkasany/nestjs-course-code/tree/master/demo/address 使用 navicat 导入sql文件&#xff0c;新增表&#xff0c;然后只需要一个接口 localhost:3001/region?parentId1, 不断的…

12-28

#include <iostream>using namespace std; class Person {int *age;string &name; public:void ss(){cout<<"年龄:"<<*age<<endl<<"名字:"<<name<<endl;}//拷贝构造函数(深拷贝&#xff09;Person(const Pe…

考研结束,以下事情要抓紧做了!

Hello&#xff0c;大家好&#xff0c;我是 Sunday。 首先恭喜大家考研结束&#xff0c;也在这里祝各位考研的同学们可以 成功上岸 ✿✿ヽ(▽)ノ✿。 不过&#xff0c;考试结束并不是一个终点&#xff0c;而是另外一个新的起点。摆在大家面前的&#xff0c;还有很多新的问题&a…

echart地图的小demo12.27

图形&#xff1a; DataV.GeoAtlas地理小工具系列 点击以上链接进入--》 再点击箭头---》复制坐标到文件&#xff1a; 取名为 china.json中 &#xff08;文件名自定义&#xff09; <template><div class"map" ref"chartMap">地图</div>…

轻量应用服务器与云服务器CVM对比——腾讯云

腾讯云轻量服务器和云服务器CVM该怎么选&#xff1f;不差钱选云服务器CVM&#xff0c;追求性价比选择轻量应用服务器&#xff0c;轻量真优惠呀&#xff0c;活动 https://curl.qcloud.com/oRMoSucP 轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年&#xff0c;540元三…

科荣AIO UtilServlet存在任意文件读取漏洞

文章目录 产品简介漏洞概述指纹识别漏洞利用修复建议 产品简介 科荣AIO是一款企业管理软件&#xff0c;提供企业一体化管理解决方案。它整合了ERP&#xff08;如进销存、财务管理&#xff09;、OA&#xff08;办公自动化&#xff09;、CRM&#xff08;客户关系管理&#xff09…

【数据库系统概论】第6章-关系数据库理论

真别看吧&#xff0c;抄ppt而已啊 文章目录 6.1 引言6.2 规范化6.2.1 函数依赖6.2.2 码6.2.3 范式&#xff08;Normal Form&#xff09;6.2.4 BC范式6.2.5 规范化小结 6.1 引言 我们有这样一张表&#xff1a; but 为啥这样设计呢&#xff1f;由此引出怎样设计一个关系数据库…

1.2.3 TCP/IP参考模型

一、OSI参考模型与TCP/IP参考模型 1、应用层&#xff1a;将表示层和会话层都纳入其中&#xff0c;形成一个比较大的层次&#xff0c;包含所有的高层协议 2、传输层&#xff1a;实现端到端的&#xff0c;进程与进程之间的通信。 3、网际层&#xff1a;TCP/IOP模型中最关键的部…

VScode——下载、安装、配置C/C++环境(windows)

一.快速下载 还在因为vscode官方下载慢而头疼嘛&#xff0c;按这个步骤来直接起飞兄弟萌 首先进入vscode官方网站然后选择对应版本下载然后进入浏览器下载页面复制下载链接粘贴到地址栏 将地址中的/stable前换成vscode.cdn.azure.cn 即可实现超速下载 下面是一个国内镜像的下…

一种删除 KubeSphere 中一直卡在 Terminating 的 Namespace--KubeSphere Logging System的简单方法

文章目录 一、问题提出二、删除方法1&#xff0c;获取kubesphere-logging-syste的详细信息json文件2&#xff0c;编辑kubesphere-logging-system.json3&#xff0c;执行清理命令 三、检查结果 一、问题提出 在使用 KubeSphere 的时候发现有一个日志服务KubeSphere Logging Sys…

C语言——指针题目“指针探测器“

如果你觉得你指针学的自我感觉良好&#xff0c;甚至已经到达了炉火纯青的地步&#xff0c;不妨来试试这道题目&#xff1f; #include<stdio.h> int main() {char* c[] { "ENTER","NEW","POINT","FIRST" };char** cp[] { c 3…

我的NPI项目之行业黑话 -- 电子/机构/软件/认证

因为最近的NPI项目&#xff0c;参加了很多项目的会议&#xff0c;有电子/机构/软件/认证相关的各方面的专业词汇就出现了。这里我将之称为黑话&#xff0c;就是对我&#xff08;纯软件) 来说是黑盒的话。这里简单记录并用于理解。 EE有关&#xff1a; Layout&#xff0c;一直…

腾讯云轻量服务器和云服务器CVM该怎么选?区别一览

腾讯云轻量服务器和云服务器CVM该怎么选&#xff1f;不差钱选云服务器CVM&#xff0c;追求性价比选择轻量应用服务器&#xff0c;轻量真优惠呀&#xff0c;活动 https://curl.qcloud.com/oRMoSucP 轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年&#xff0c;540元三…