【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() * 100
            spherical.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);
    }

在这里插入图片描述

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

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

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

相关文章

MathType永久激活版写毕业论文必备神器以及破解版下载图文教程(附mathtype7镶嵌到word步骤)

前言 由于临近暑假&#xff0c;大学生和研究生都需要写自己的论文。使用的工具叫做MathType&#xff0c;它是加拿大的公司开发的&#xff0c;今天给大家带来的是Win和Mac版Mathtype最新破解版。 自从Mathtype7的发布&#xff0c;很多的老师和学生都不知道它从哪里下载和激活&…

Web前端一套全部清晰 ⑧ day5 CSS.3 选择器、PxCook软件、盒子模型

谁不是一路荆棘而过呢 —— 24.5.12 CSS.3 选择器、PxCook软件、盒子模型 一、选择器 1.结构伪类选择器 1.作用: 根据元素的结构关系查找元素。 选择器 说明 E:first-child 查找第一个 E元素 E:last-child 查找最后一个E元素 E:nth-chil…

Windows环境下VSCode加MinGw-W64搭建C/C++开发环境

前言&#xff1a; 本文记录了自己在配置 Windows环境下 VSCode&#xff0c;并安装MinGW-W64来搭建windows操作系统下下的C/C开发环境。本文重点参考了如下链接中知乎上的文章里介绍的方法&#xff0c;在windows上安装 MinGW-W64。 vscode c/c环境配置&#xff08;MinGW&…

crossover24中文破解版百度云免费下载 crossover永久免激活汉化包安装使用教程 crossover24激活码分享

原则上&#xff0c;我们不提倡各位使用破解版&#xff0c;这是处于对知识产权的保护&#xff0c;也是为了各位的长远利益。使用正版你可以获得更优质的服务和完善的产品功能。 但仍然有部分用户由于预算、使用习惯等原因&#xff0c;需要破解版。所以本文不讲原则&#xff0c;…

【科研绘图 基础版】01 使用Python绘制时间序列折线图

下面这段代码绘制了一个折线图&#xff0c;其中包含了实际平均温度数据和使用线性回归模型预测的平均温度数据&#xff08;用来近似地表示数据的整体趋势&#xff09;。 具体来说&#xff0c;图中的横轴表示年份&#xff0c;纵轴表示平均温度。蓝色的实心线代表了实际的平均温度…

电商购物系统首页的商品分类

如上图对商品的一个分类实际上和省市区的分类十分类似 , 都是通过自关联的方法来实现 , 但是这里不同的是 , 涉及到外键来获取数据 首先让我们来看一下最后通过后端返回数据的形式是什么样子的 """{1:{channels:[{id:1 , name:手机 , url:},{}{}],sub_cats:[{…

【机器学习300问】88、什么是Batch Norm算法?

一、什么是Batch Norm&#xff1f; &#xff08;1&#xff09;Batch Norm的本质 神经网络中的Batch Normalization&#xff08;批量归一化&#xff0c;简称BatchNorm或BN&#xff09;是一种改进神经网络训练过程的规范化方法&#xff0c;BatchNorm的主要目的是加速神经网络的训…

MFC的句柄概念以及句柄类型

在MFC&#xff08;Microsoft Foundation Class&#xff09;桌面应用程序中&#xff0c;窗口是通过句柄&#xff08;Handle&#xff09;来进行管理和操作的。 句柄是一个标识符&#xff0c;用于唯一标识和引用窗口、控件、设备上下文等对象。在MFC桌面应用程序中&#xff0c;常…

单片机的中断

1. 中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置 当中央处理机CPU正在处理某件事的时候外界发生紧急事件请求&#xff0c;要CPU暂停当前的工作&#xff0c;转而去处理这个紧急事件&#xff0c;处理完以后&#xff0c;再回到原来中断的地方&#xff0c;继续原…

[蓝桥杯]真题讲解:合并数列(双指针+贪心)

[蓝桥杯]真题讲解&#xff1a;班级活动&#xff08;贪心&#xff09; 一、视频讲解二、正解代码1、C2、python33、Java 一、视频讲解 [蓝桥杯]真题讲解&#xff1a;合并数列&#xff08;双指针贪心&#xff09; 二、正解代码 1、C #include<bits/stdc.h> #define in…

经典笔试题:快速排序 计数排序

Problem: 912. 排序数组 思路 &#x1f468;‍&#x1f3eb; 三叶题解 &#x1f496; AC&#xff1a;计数排序 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( n ) O(n) O(n) class Solution {public int[] sortArray(int[] nums) {int max -50001, min 50001;for (…

别人家的UI表单为什么这么漂亮?而你却千篇一律。

设计漂亮的移动UI页面表单页需要考虑以下几个方面&#xff1a; 布局和结构设计 合适的布局和结构&#xff0c;使表单页面看起来整洁、清晰&#xff0c;并且易于使用。可以使用网格系统或者栅格布局来对表单进行划分&#xff0c;使不同的表单元素有明确的位置和排列。 色彩和配…

猫头虎分享已解决Bug || **Vue.js脚手架安装失败** Error: unable to fetch template`

猫头虎分享已解决Bug &#x1f42f; || Vue.js脚手架安装失败 &#x1f6ab;Error: unable to fetch template 博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题…

Linux-笔记 开发板Uboot命令使用

将之前自学的知识整理了一下笔记&#xff0c;以便回忆 信息查询命令 1、help/?&#xff1a;查看所支持命令 > ? md md - memory displayUsage: md [.b, .w, .l] address [# of objects]2、bdinfo&#xff1a;查询板子信息 > bdinfo arch_number 0x00000000 boot_p…

ComStar系统架构介绍

中国外汇交易中心为适应市场需要&#xff0c;开发推出了ComStar外汇资金交易管理系统&#xff0c;该系统能够快速响应市场变化及监管机构的新要求&#xff0c;通过与交易中心银行间市场的外汇交易系统无缝连接&#xff0c;为市场成员提供了更为高效、便利、安全稳定的外汇资金业…

STL学习笔记

1 基本概念 1.1 STL STL(Standard Template Library,标准模板库)STL从广义上分为: 容器(container) 算法(algorithm) 选代器(iterator)容器和算法之间通过迭代器&#xff08;看作指针&#xff09;进行无缝连接STL 几乎所有的代码都采用了横板类或者模板函数 1.2 容器 STL容器…

鸿蒙开发接口Ability框架:【(AbilityContext)】

AbilityContext AbilityContext是Ability的上下文环境&#xff0c;继承自Context。 AbilityContext模块提供允许访问特定于ability的资源的能力&#xff0c;包括对Ability的启动、停止的设置、获取caller通信接口、拉起弹窗请求用户授权等。 说明&#xff1a; 本模块首批接口…

Midjourney与Stable Diffusion大比拼:AI绘画技术的未来

在当今快速发展的人工智能技术浪潮中&#xff0c;AI绘画软件成为了艺术和技术交汇的新领域。两大巨头——Midjourney和Stable Diffusion&#xff0c;在这一领域中引领风骚&#xff0c;它们以其独特的功能和强大的生成能力&#xff0c;让创作者能够将想象力化为现实。本文将深入…

Shell编程之循环语句之for

一.for循环语句 读取不同的变量值&#xff0c;用来逐个执行同一组命令 for 变量名 in 取值列表 do命令序列 done 示例&#xff1a; 1.计算从1到100所有整数的和 2.提示用户输入一个小于100的整数&#xff0c;并计算从1到该数之间所有整数的和 3.求从1到100所有整数的偶数和…

记忆化搜索专题

前言 如果要记忆化搜索的话&#xff0c;如果数据是10的九次方&#xff0c;我们不可能开一个那么大的数组来存储&#xff0c;所以我们要学会用map来存储 leecode1553 class Solution {unordered_map<int, int> memo; public:int minDays(int n) {if (n < 1) {return n;…