ThreeJS-太阳球围绕旋转(二十四)

数学小知识:

我们根据旋转角度θ可以计算出任意时刻的x,y

sinθ = y0/r; 因此y0= rsinθ,

cosθ = x0/r,因此x0= rcosθ,

小拓展: y0^ +x0^ - r^2*sinθ^2 + r^2*cosθ^2 = r^2*(sinθ^2 + cosθ^2) = r^2;

这也是为什么在极坐标方程中

y0= rsinθ,

x0= rcosθ,

可以代表一个圆的原因。

会极坐标方程的同学可以直接跳过该描述。

关键代码:

            //创建一个光球
            const sphereMesh = new THREE.Mesh(
            new THREE.SphereBufferGeometry(1, 50, 50), 
            new THREE.MeshBasicMaterial({color:0xFF0000})
            );
            sphereMesh.position.set(10, 5, 10);
            //将光源加入球
            sphereMesh.add(directionalLight);

//渲染下一帧的时候就会调用回调函数
            const clock = new THREE.Clock();
            let renderFun = () => {
                let time = clock.getElapsedTime();
                sphereMesh.position.x = Math.sin(time)*10;
                sphereMesh.position.z = Math.cos(time)*10;
                //更新阻尼数据
                controls.update();
                //需要重新绘制canvas画布
                render.render(scene, camera);
                //监听屏幕刷新(60HZ,120HZ),每次刷新触发一次requestAnimationFrame回调函数
                //但是requestAnimationFrame的回调函数注册生命只有一次,因此需要循环注册,才能达到一直调用的效果
                window.requestAnimationFrame(renderFun);
            }; 

完整代码:

<template>
    <div id="three_div"></div>
</template>

<script>
    import * as dat from 'dat.gui' //界面控制
    import * as THREE from "three";
    import {
        OrbitControls
    } from "three/examples/jsm/controls/OrbitControls";
    import {
        RGBELoader
    } from "three/examples/jsm/loaders/RGBELoader"
    export default {
        name: "HOME",
        components: {
            // vueQr,
            // glHome,
        },
        data() {
            return {};
        },
        mounted() {
            //使用控制器控制3D拖动旋转OrbitControls
            //控制3D物体移动

            //1.创建场景
            const scene = new THREE.Scene();
            console.log(scene);

            //2.创建相机
            const camera = new THREE.PerspectiveCamera(
                75,
                window.innerWidth / window.innerHeight,
                0.1,
                1000
            );
            //设置相机位置
            camera.position.set(0, 0, 10);
            //将相机添加到场景
            scene.add(camera);
            //添加物体
            //创建一个半径为1,经纬度分段数位20的球
            const cubeGeometry = new THREE.SphereBufferGeometry(2, 100, 100);
            //纹理加载器加载图片
            const cubeMaterial = new THREE.MeshStandardMaterial({
                //side: THREE.DoubleSide,
            });
            //根据几何体和材质创建物体
            const mesh = new THREE.Mesh(cubeGeometry, cubeMaterial);
            //将物体加入到场景
            scene.add(mesh);

            //创建平面几何体
            const planeGeometry = new THREE.PlaneBufferGeometry(50, 50);
            //创建平面物体
            const planeMesh = new THREE.Mesh(planeGeometry, cubeMaterial);
            planeMesh.position.set(0, -2, 0);
            planeMesh.rotation.x = -Math.PI / 2;
            //场景添加平面物体
            scene.add(planeMesh);

            //给场景所有的物体添加默认的环境贴图
            //添加坐标轴辅助器
            const axesHepler = new THREE.AxesHelper(5);
            scene.add(axesHepler);
            //标准材质需要借助灯光

            //添加周围环境灯光(由物体发出的灯光)参数(灯色,强度0-1)
            // const light = new THREE.AmbientLight(0xFFFFFF, 0.7);
            // scene.add(light);
            //创建点光源
            const directionalLight = new THREE.PointLight(0xFF0000, 0.7);
            // directionalLight.position.set(10, 10, 10);
            
            //创建一个光球
            const sphereMesh = new THREE.Mesh(
            new THREE.SphereBufferGeometry(1, 50, 50), 
            new THREE.MeshBasicMaterial({color:0xFF0000})
            );
            sphereMesh.position.set(10, 5, 10);
            //将光源加入球
            sphereMesh.add(directionalLight);
            //将光源球加入到场景
            scene.add(sphereMesh);
            //初始化渲染器
            const render = new THREE.WebGLRenderer();
            //设置渲染器的尺寸
            render.setSize(window.innerWidth, window.innerHeight);
            //使用渲染器,通过相机将场景渲染进来

            //创建轨道控制器,可以拖动,控制的是摄像头
            const controls = new OrbitControls(camera, render.domElement);
            //设置控制阻尼,让控制器有更真实的效果
            controls.enableDamping = true;


            //开启投影
            //开启渲染器投影
            render.shadowMap.enabled = true;
            //开启灯光动态投影
            directionalLight.castShadow = true;
            //开启物体投影
            mesh.castShadow = true;
            //开启平面接受投影
            planeMesh.receiveShadow = true;
            //投影模糊度
            directionalLight.shadow.radius = 10;
            //设置投影的宽度和高度
            directionalLight.shadow.mapSize.set(1024, 1024);

            //directionalLight.angle = Math.PI/10;
            //创建gui
            const gui = new dat.GUI();
            // gui.add(directionalLight.shadow.camera, 'near').min(1).max(25).step(1).name("相机近距离").onChange( () => {
            //     directionalLight.shadow.camera.updateProjectionMatrix();
            // })
            gui.add(mesh.position, 'x').min(-30).max(30).step(1).name("移动位置");
            //灯光有效距离,默认0表示不衰减
            directionalLight.distance = 0;
            gui.add(directionalLight, 'distance').min(0).max(100).step(1).name("灯光有效距离");
            //灯光衰减量控制
            directionalLight.decay = 2;
            gui.add(directionalLight, 'decay').min(-5).max(5).step(1).name("灯光衰减量");
            //控制灯光强度
            gui.add(directionalLight, 'intensity').min(0).max(30).step(1).name("灯光强度");
            
            //需要渲染器开启物理渲染
            render.physicallyCorrectLights =true;

            //将webgl渲染的canvas内容添加到body上
            document.getElementById("three_div").appendChild(render.domElement);

            //渲染下一帧的时候就会调用回调函数
            const clock = new THREE.Clock();
            let renderFun = () => {
                let time = clock.getElapsedTime();
                sphereMesh.position.x = Math.sin(time)*10;
                sphereMesh.position.z = Math.cos(time)*10;
                //更新阻尼数据
                controls.update();
                //需要重新绘制canvas画布
                render.render(scene, camera);
                //监听屏幕刷新(60HZ,120HZ),每次刷新触发一次requestAnimationFrame回调函数
                //但是requestAnimationFrame的回调函数注册生命只有一次,因此需要循环注册,才能达到一直调用的效果
                window.requestAnimationFrame(renderFun);
            };
            // window.requestAnimationFrame(renderFun);
            renderFun();

            //画布全屏
            window.addEventListener("dblclick", () => {
                if (document.fullscreenElement) {
                    document.exitFullscreen();
                } else {
                    //document.documentElement.requestFullscreen();
                    render.domElement.requestFullscreen();
                }
            });

            //监听画面变化,更新渲染画面,(自适应的大小)
            window.addEventListener("resize", () => {
                //更新摄像机的宽高比
                camera.aspect = window.innerWidth / window.innerHeight;
                //更新摄像机的投影矩阵
                camera.updateProjectionMatrix();
                //更新渲染器宽度和高度
                render.setSize(window.innerWidth, window.innerHeight);
                //设置渲染器的像素比
                render.setPixelRatio(window.devicePixelRatio);
                console.log("画面变化了");
            });
        },
        methods: {
            paush(animate) {
                animate.pause();
            },
        },
    };
</script>

<style scoped lang="scss">
</style>

效果图:

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

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

相关文章

15_I.MX6ULL_LCD显示原理

目录 LCD简介 分辨率 像素格式 LCD屏幕接口 LCD时间参数 RGB LCD屏幕时序 像素时钟 显存 LCD简介 LCD全称是Liquid Crystal Display,也就是液晶显示器,是现在最常用到的显示器,手机、电脑、各种人机交互设备等基本都用到了LCD,最常见就是手机和电脑显示器了。LCD的构造…

帮公司面试了一个32岁的程序员,只因这一个细节,被我一眼看穿是培训班出来的,没啥工作经验...

首先&#xff0c;我说一句&#xff1a;培训出来的&#xff0c;优秀学员大有人在&#xff0c;我不希望因为带着培训的标签而无法达到用人单位和候选人的双向匹配&#xff0c;是非常遗憾的事情。 最近&#xff0c;在网上看到这样一个留言&#xff0c;引发了程序员这个圈子不少的…

ChatGPT全球大封号!数10万企业停摆:第一批玩AI的人,被AI给玩了

观点| Mr.K 主笔| Wendy.L 编辑| Emma来源| 技术领导力(ID&#xff1a;jishulingdaoli)3月31日&#xff0c;Open AI就开始无征兆的进行全球大封号&#xff0c;其中亚洲是重灾区&#xff0c;官方没有给出任何声明&#xff0c;具体原因不得而知。并且暂停了这些地区新账号的注…

【从零开始学习 UVM】6.4、UVM 激励产生 —— uvm_do 宏详解

请注意,start方法的call_pre_post字段设置为0,这意味着在使用这些序列宏时,序列的pre_body和post_body方法将永远不会被调用。否则,执行流程与通过start方法执行序列时类似。 文章目录 执行序列宏介绍Example执行序列宏介绍 使用序列宏的优点是可以使用内联约束,但是您失…

实验一 跨VLAN访问

目录 一、按照拓扑图配置VLAN&#xff0c;并实现跨VLAN间的访问。 二、实验环境 三、实验步骤 一、按照拓扑图配置VLAN&#xff0c;并实现跨VLAN间的访问。 1、配置好交换机的VLAN和各个终端的地址&#xff0c;实现各个VLAN内能连通。 2、开启两个交换机的VTY连接&#xff0…

基于STM32F103——XGZP6847D压力传感器+串口打印

基于STM32F103—XGZP6847D压力传感器串口打印基本介绍概述产品特点引脚的连接 (IIC通信)名称含义的介绍I2C通信协议 (设备地址是 0x6D)寄存器描述工作模式寄存器Reg0x30&#xff08;测量命令寄存器&#xff09;Reg0xA5Reg0xA6模式说明组合数据采集模式休眠数据采集模式代码编写…

MyBatisPlus

今日目标基于MyBatisPlus完成标准Dao的增删改查功能掌握MyBatisPlus中的分页及条件查询构建掌握主键ID的生成策略了解MyBatisPlus的代码生成器1&#xff0c;MyBatisPlus入门案例与简介这一节我们来学习下MyBatisPlus的入门案例与简介&#xff0c;这个和其他课程都不太一样&…

[CF复盘] Codeforces Round 863 (Div. 3) 20230404

[TOC]([CF复盘] Codeforces Round 863 (Div. 3) 20230404 ) 一、本周周赛总结 做到E&#xff0c;但DE都TLE&#xff0c;很难受。 A 贪心。 B 坐标运算。 C 贪心构造。 D 分治DFS。 E 九进制模拟。 二、 A. Insert Digit 链接: A. Insert Digit 1. 题目描述 2. 思路分析…

skimage.filters.apply_hysteresis_threshold详解

本文内容均参考scipy1.9.1scipy1.9.1scipy1.9.1版本的源码&#xff0c;若有任何不当欢迎指出 我们截取官方注释如下&#xff1a; def apply_hysteresis_threshold(image, low, high):"""Apply hysteresis thresholding to image.This algorithm finds regions …

RabbitMQ中TTL

目录一、TTL1.控制后台演示消息过期2.代码实现2.1 队列统一过期2.2 消息过期一、TTL TTL 全称 Time To Live&#xff08;存活时间/过期时间&#xff09;。 当消息到达存活时间后&#xff0c;还没有被消费&#xff0c;会被自动清除。 RabbitMQ可以对消息设置过期时间&#xff0…

QT与Halcon联编应用开发-设置软件图标Icon

VS+Qt应用开发-设置软件图标 设置软件exe图标设置运行时标题栏和任务栏图标默认的Qt是没有图标的,如下图所示,可以在Qt应用程序发布时和应用程序运行时给应用程序加上图标。 任务栏图标: 软件左上角图标 可执行程序图标

原来count(*)是接口性能差的真凶

以下文章来源于苏三说技术 &#xff0c;作者苏三呀 一.前言 最近我在公司优化过几个慢查询接口的性能&#xff0c;总结了一些心得体会拿出来跟大家一起分享一下&#xff0c;希望对你会有所帮助。 我们使用的数据库是Mysql8&#xff0c;使用的存储引擎是Innodb。这次优化除了优…

通过Chrome打开IE浏览器并跳转到指定页面并传递参数

通过Chrome打开IE浏览器并跳转到指定页面并传递参数 方式一&#xff1a;通过浏览器打开ie浏览器&#xff08;可以换做其他应用&#xff09;&#xff0c;跳转到指定页面&#xff08;方式一只支持单个参数&#xff09; 1、新建alert.reg Windows Registry Editor Version 5.00…

IOC/DI的注解开发

IOC/DI注解开发3&#xff0c;IOC/DI注解开发3.1 环境准备3.2 注解开发定义bean步骤1:删除原XML配置步骤2:Dao上添加注解步骤3:配置Spring的注解包扫描步骤4&#xff1a;运行程序步骤5:Service上添加注解步骤6:运行程序知识点1:Component等3.2 纯注解开发模式3.2.1 思路分析3.2.…

https和ssl网关在各安全层面的应用场景及测评要点

1、https和https实现 SSL/TLS协议是独立的概念&#xff08;这里的重点是https和ssl v**&#xff0c;关于ssl/tls协议就不展开说了&#xff09;&#xff0c;可以实现对基于TCP/UDP应用的安全保护&#xff0c;如https和sftp等。 https是其中应用非常广泛的一种&#xff0c;即Hype…

RocketMQ 5.1 NameServer 启动流程

文章目录1 解析命令行参数和配置文件2 创建并启动 NamesrvController2.1 创建 NamesrvController 对象2.2 启动 NamesrvController 对象第一步&#xff1a;初始化 controller第二步&#xff1a;注册 JVM 钩子第二步&#xff1a;启动 controllerRocketMQ是一个分布式消息中间件&…

爬虫学习(网页解析)

目录 了解&#xff1a; 参考图 介绍 bs4库&#xff1a; 解析器&#xff1a; 解析方法 代码示例 lxml库&#xff1a; 解析器 解析方法 代码示例 了解&#xff1a; 参考图 (1) html解析器&#xff1a; (2) 解析方式&#xff1a; 介绍 ### 前言&#xff1a; 网页…

财政分权数据集:省级地级市财政分权度(1999-2021年)

财政分权是指中央政府和地方政府在财政收入和支出方面各自拥有一定的自主权&#xff0c;即政府财政权力在中央和地方之间进行分割和分配的一种制度安排。财政分权的实施可以促进地方政府的责任感和创造力&#xff0c;提高政府的效率和服务水平&#xff0c;同时也可以增强地方政…

蓝桥杯嵌入式第十三届(第二套客观题)

文章目录 前言一、题目1二、题目2三、题目3四、题目4五、题目5六、题目6七、题目7八、题目8九、题目9十、题目10总结前言 本篇文章继续讲解客观题。 一、题目1 这个其实属于送分题,了解嵌入式或者以后想要入行嵌入式的同学应该都对嵌入式特点有所了解。 A. 采用专用微控制…

KDZD-JP简易式机械碰撞试验台

一、产品制作标准 依据高压开关标准要求制作&#xff1a;GB7251-2013《低压成套开关设备和控制设备》、GB3906-2006 《3.6KV-40.5KV 交流金属封闭开关设备和控制设备》、GB/T 11022—2011《高压开关设备和控制设备标准的共用技术要求》、GB/T 1984—2014 《高压交流断路器》、…