【Threejs进阶教程-算法篇】1.常用坐标系介绍与2d/3d随机点位算法

2024-05-12 22:12

本文主要是介绍【Threejs进阶教程-算法篇】1.常用坐标系介绍与2d/3d随机点位算法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2d/3d随机算法

  • 学习ThreeJS的捷径
  • 坐标系简介
    • 平面直角坐标系和极坐标系
    • 空间直角坐标系
    • 圆柱坐标系
    • 球坐标系
      • 球坐标系与直角坐标系的转换
  • 基于坐标系系统的随机点位算法
    • 平面直角坐标系随机
      • 平面直角坐标系随机的变形
    • 空间直角坐标系随机
    • 二维极坐标系随机
    • 圆柱坐标系随机
    • 基于Cylindercal(圆柱坐标系)的圆柱坐标系随机
    • 球坐标系随机
  • 随机算法的应用
    • 土星环(使用极坐标系)
    • 粒子球(使用球坐标系)

学习ThreeJS的捷径

本段内容会写在0篇以外所有的,本人所编写的Threejs教程中

对,学习ThreeJS有捷径
当你有哪个函数不懂的时候,第一时间去翻一翻文档
当你有哪个效果不会做的时候,第一时间去翻一翻所有的案例,也许就能找到你想要的效果
最重要的一点,就是,绝对不要怕问问题,越怕找找别人问题,你的问题就会被拖的越久

如果你确定要走WebGL/ThreeJS的开发者路线的话,以下行为可以让你更快的学习ThreeJS

  1. 没事就把所有的文档翻一遍,哪怕看不懂,也要留个印象,至少要知道Threejs有什么
  2. 没事多看看案例效果,当你记忆的案例效果足够多时,下次再遇到相似问题时,你就有可能第一时间来找对应的案例,能更快解决你自己的问题
  3. 上述案例不只是官网的案例,郭隆邦技术博客,跃焱邵隼,暮志未晚等站点均有不少优质案例,记得一并收藏
    http://www.yanhuangxueyuan.com/ 郭隆邦技术博客
    https://www.wellyyss.cn/ 跃焱邵隼
    http://www.wjceo.com/ 暮志未晚(暮老的站点暂时挂了,请查阅他之前的threejs相关文档)
    暮老的csdn首页
    这三个站点是我最常逛的站点,推荐各位有事没事逛一下,看看他们的案例和写法思路,绝对没坏处

坐标系简介

我们常见2D坐标系,一般有平面直角坐标系极坐标系
我们常见的3D坐标系,一般有空间直角坐标系圆柱坐标系球坐标系

平面直角坐标系和极坐标系

平面直角坐标系,一般以 (x,y) 两个数值来表示点位坐标
极坐标系,一般以(radius,theta),半径和旋转角度来表示点位坐标

极坐标系和平面直角坐标系可以互相转换:

	//平面直角坐标系转极坐标系let radius = Math.sqrt( x * x + y * y );let theta = Math.atan( y / x );//极坐标系转平面直角坐标系let x = radius * Math.cos(theta);let y = radius * Math.sin(theta);

空间直角坐标系

空间直角坐标系,一般使用(x,y,z)三个值来表示点位坐标,也就是我们在threejs中最常用的position

圆柱坐标系

圆柱坐标系,一般使用(radius,theta,height)来表示点位坐标,三个值可以根据实际使用情况做互换,圆柱坐标系,官方已经提供了相关API,我们可以查阅threejs的官方文档来更详细的了解圆柱坐标系
在这里插入图片描述
由于官方文档的内容就这些,所以这里就不贴文档源地址了,具体的圆柱坐标系到平面直角坐标系的转换算法,其实和上面极坐标算法相似,xz平面使用极坐标系来计算,y轴依然是用高度轴来计算,本质上圆柱坐标系就是极坐标系增加了高度轴的一种空间坐标系,转换公式参考极坐标系,这里不再赘述

球坐标系

球坐标系最常用的应用就是计算地球的经纬度,球坐标系一般用( radius,phi,theta)来表示点位坐标,phi可以视为纬度,theta可以视为经度,我们也可以参考threejs官方文档对球坐标系的解释
在这里插入图片描述

球坐标系与直角坐标系的转换

球坐标系到直角坐标系的互转,写法有点多,这里我贴出《3D数学基础》190页的内容,如果你的手边有这本书,书本内的183页到192页对球坐标系做了详细的介绍,这里请根据自身需求做了解即可
在这里插入图片描述
因为考虑到threejs使用右手坐标系,所以我们的公式以Threejs提供的为准

	//直角坐标系转球坐标系,这里我们以threejs官方开发包中//src/math/Spherical.js 中为准setFromCartesianCoords( x, y, z ) {this.radius = Math.sqrt( x * x + y * y + z * z );if ( this.radius === 0 ) {this.theta = 0;this.phi = 0;} else {this.theta = Math.atan2( x, z );this.phi = Math.acos( MathUtils.clamp( y / this.radius, - 1, 1 ) );}return this;}//球坐标系转换平面直角坐标系,这里我们以thrjeejs官方开发包中//src/math/Vector3.js 564行的算法为准setFromSphericalCoords( radius, phi, theta ) {const sinPhiRadius = Math.sin( phi ) * radius;this.x = sinPhiRadius * Math.sin( theta );this.y = Math.cos( phi ) * radius;this.z = sinPhiRadius * Math.cos( theta );return this;}

基于坐标系系统的随机点位算法

平面直角坐标系随机

默认的情况下,场景使用的是空间直角坐标系

	     for(let i = 0;i< 100;i++){let geometry = new THREE.BoxGeometry(1,1,1);let material = new THREE.MeshStandardMaterial({color:0xffffff * Math.random()});let mesh = new THREE.Mesh(geometry,material);mesh.position.x = Math.random() * 10 - 5;mesh.position.z = Math.random() * 10 - 5;scene.add(mesh);}

在这里插入图片描述
因为我们这里仅操作了x轴和z轴,高度轴均保持一致,这样的随机为平面直角坐标系的随机,当然,我们也可以选择随机x轴和y轴,随机y轴和z轴,根据你自身的需求来做即可

这样的以x轴和z轴为随机的方式,可以用于在某个地区生成随机数量的树木,我们在代码中,xz轴的随机范围均为 -5 ~ 5 ,所以我们实际上是在

Math.random()的取值范围为 0~1,Math.random() * 10的取值范围为0 ~ 10,Math.random() * 10 - 5的取值范围为 -5 ~ 5

平面直角坐标系随机的变形

变形其实非常简单,只需要控制position.x,position.y,position.z其中两个轴,就可以控制物体在哪个平面上随机

空间直角坐标系随机

基本上没啥说的,只是在上面的基础上,将三个轴都参与随机

二维极坐标系随机

	     for(let i = 0;i< 100;i++){let geometry = new THREE.BoxGeometry(1,1,1);let material = new THREE.MeshStandardMaterial({color:0xffffff * Math.random()});let mesh = new THREE.Mesh(geometry,material);let angle = Math.random() * Math.PI * 2;let radius = Math.random() * 10;let x = Math.cos(angle) * radius;let z = Math.sin(angle) * radius;mesh.position.x = x;mesh.position.z = z;scene.add(mesh);}

在这里插入图片描述
这样其实我们看的不太明显,我们可以选择随机的方块数量大幅增加,或者让半径不再随机
在这里插入图片描述

	替换随机的半径// let radius = Math.random() * 10;let radius = 10;

在这里插入图片描述
生成1000个盒子,只需要修改for循环的100为1000即可

圆柱坐标系随机

其实就是在极坐标系的基础上,增加对高度轴y轴的随机数即可
这里我们对半径不做随机,相对来说结果更显而易见,如果你需要在圆柱范围内随机,将固定的radius改为随机即可

	     for(let i = 0;i< 1000;i++){let geometry = new THREE.BoxGeometry(1,1,1);let material = new THREE.MeshStandardMaterial({color:0xffffff * Math.random()});let mesh = new THREE.Mesh(geometry,material);let angle = Math.random() * Math.PI * 2;let radius = 10;let x = Math.cos(angle) * radius;let z = Math.sin(angle) * radius;mesh.position.x = x;mesh.position.z = z;mesh.position.y = Math.random() * 10 - 5;scene.add(mesh);}

在这里插入图片描述

基于Cylindercal(圆柱坐标系)的圆柱坐标系随机

这里使用了上述的Cylindercal的概念,如果你实在绕不过来极坐标系,可以考虑使用这个

        let cylindrical = new THREE.Cylindrical();for(let i = 0;i< 1000;i++){let geometry = new THREE.BoxGeometry(1,1,1);let material = new THREE.MeshStandardMaterial({color:0xffffff * Math.random()});let mesh = new THREE.Mesh(geometry,material);cylindrical.radius = 10;cylindrical.theta = Math.random() * Math.PI * 2;cylindrical.y = Math.random() * 10 - 5;//文档在Vector3中mesh.position.setFromCylindrical(cylindrical);scene.add(mesh);}

效果与上面一致,这里不再截图

球坐标系随机

球坐标系随机,这里仅建议使用官方的Spherical来进行随机

        let spherical = new THREE.Spherical()for(let i = 0;i< 1000;i++){let geometry = new THREE.BoxGeometry(1,1,1);let material = new THREE.MeshStandardMaterial({color:0xffffff * Math.random()});let mesh = new THREE.Mesh(geometry,material);spherical.radius = 10;spherical.phi = Math.random() * Math.PI * 2;spherical.theta = Math.random() * Math.PI * 2;mesh.position.setFromSpherical(spherical);scene.add(mesh);}

在这里插入图片描述

随机算法的应用

土星环(使用极坐标系)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>*{margin: 0;padding: 0;border: 0;}body{width:100vw;height: 100vh;overflow: hidden;}</style>
</head>
<body><!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script><script type="importmap">{"imports": {"three": "../three/build/three.module.js","three/addons/": "../three/examples/jsm/"}}</script><script type="module">import * as THREE from "../three/build/three.module.js";import {OrbitControls} from "../three/examples/jsm/controls/OrbitControls.js";window.addEventListener('load',e=>{init();addMesh();render();})let scene,renderer,camera;let orbit;function init(){scene = new THREE.Scene();renderer = new THREE.WebGLRenderer({alpha:true,antialias:true});renderer.setSize(window.innerWidth,window.innerHeight);document.body.appendChild(renderer.domElement);camera = new THREE.PerspectiveCamera(50,window.innerWidth/window.innerHeight,0.1,2000);camera.add(new THREE.PointLight());camera.position.set(10,10,10);scene.add(camera);orbit = new OrbitControls(camera,renderer.domElement);orbit.enableDamping = true;scene.add(new THREE.GridHelper(10,10));}let groups = [];function addMesh() {//创建中心的球体let geometry = new THREE.SphereGeometry(10,32,32);let material = new THREE.MeshStandardMaterial({color:0xffffff * Math.random()});let mesh = new THREE.Mesh(geometry,material);scene.add(mesh);//创建5层土星环for(let i = 0;i< 5;i++){let group = new THREE.Group();let material2 = new THREE.MeshStandardMaterial({color:0xffffff * Math.random()})//每层土星环创造100个图块for(let j = 0;j < 100;j++){let geometry2 = new THREE.BoxGeometry();let mesh2 = new THREE.Mesh(geometry2,material2);group.add(mesh2);//在 15 ~ i*2的半径范围内,生成指定的星环let radius = Math.random() * i * 2 + 15;let theta = Math.random() * Math.PI * 2;mesh2.position.x = Math.cos(theta) * radius;mesh2.position.z = Math.sin(theta) * radius;//随机初始角度mesh2.rotation.set(Math.random() * Math.PI * 2,Math.random() * Math.PI * 2,Math.random() * Math.PI * 2,)//随机大小mesh2.scale.set(Math.random() * 2,Math.random() * 2,Math.random() * 2,)//注意,onBeforeRender,只有具有材质属性的物体,才生效,对group不生效mesh2.onBeforeRender = ()=>{mesh2.rotation.x += 0.01;mesh2.rotation.y += 0.01;}}scene.add(group);groups.push(group);}}function render() {renderer.render(scene,camera);orbit.update();requestAnimationFrame(render);//让每一层的星环转起来for(let i = 0;i< groups.length;i++){groups[i].rotation.y += 0.001 * (i+1);}}</script>
</body>
</html>

在这里插入图片描述
效果如上,我不是设计师,所以不用太纠结好看与不好看的问题

粒子球(使用球坐标系)

这里就不贴完整代码了

    function addMesh() {let spherical = new THREE.Spherical();let vectors = [];for(let i = 0;i< 1000;i++){spherical.radius = Math.random() * 100spherical.theta = Math.random() * Math.PI * 2;spherical.phi = Math.random() * Math.PI * 2;let vec = new THREE.Vector3().setFromSpherical(spherical);vectors.push(vec);}let geometry = new THREE.BufferGeometry().setFromPoints(vectors);let points = new THREE.Points(geometry,new THREE.PointsMaterial({sizeAttenuation:true,}));points.onBeforeRender = ()=>{points.rotation.x += 0.001;points.rotation.y += 0.001;}scene.add(points);}

在这里插入图片描述

有的人也许已经看出来了,粒子球可以用作创建星空(也不一定非要用球坐标系来创建也可以创建星空),粒子球也是烟花效果的基础

这篇关于【Threejs进阶教程-算法篇】1.常用坐标系介绍与2d/3d随机点位算法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/983876

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件