Three.js学习10:几何体(1)-平面几何体

news2025/3/10 21:06:37

 -----------------------------华丽的分割线---------------------

相关代码均已上传到 gitee 中:myThree: 学习 Three.js ,努力加油~!

Gitee 静态演示地址:Three JS 演示页面

 -----------------------------华丽的分割线---------------------

一、几何体 Geometry

Three.js 中物体都是由网格(mesh)构成的。一个网格物体(mesh)是由几何体 Geometry 和材质 material 组成。

几何体 Geometry 定义了网格的材质 material 定义了网格的

Three.js 中提供了一系列绘制几何体的类,如 BoxGeometry、SphereGeometry,PlaneGeometry、CircleGeometry、CylinderGeometry 等,使用这些类可以快速创建对应的几何体。

如果要做更复杂的几何体,可以使用几何体基类 BufferGeometry,它是 Three.js 的核心类之一。

网络上一些教程提到每个几何体都有一个 buffer 缓冲几何体与之对应,如 BoxGeometry 对应有 BoxBufferGeometry 之类。这些之前版本的Three.js 有,在目前的 Three.js 版本(r161 版)中,XXBufferGeometry 已经被取消。

Three.js 的几何体的面都是由三角形组成的。因此,很多内置几何体可以设置对应三角的个数(segment,份数,段数)以修改几何体的形状。

二、Three.js 内置几何体

Three.js 目前(r161 版)内置了 21 个几何体,以及 5 个附加几何体,分别是:

  • 二维几何体

      - CircleGeometry:圆形几何体
      - PlaneGeometry:平面几何体
      - RingGeometry:平面圆环几何体
      - ShapeGeometry:任意平面形状几何体
  • 常用三维几何体

      - BoxGeometry:立方体
      - SphereGeometry:球体
      - CylinderGeometry:圆柱体
      - TorusGeometry:立体圆环
      - CapsuleGeometry:胶囊体
      - ConeGeometry:圆锥体
  • 其他几何体

      - TetrahedronGeometry:四面几何体
      - OctahedronGeometry:八面几何体
      - DodecahedronGeometry:十二面几何体
      - IcosahedronGeometry:二十面几何体
      - PolyhedronGeometry:多面几何体
      - ExtrudeGeometry:挤压缓冲几何体
      - LatheGeometry:车削几何体
      - TorusKnotGeometry:环形扭结几何体
      - TubeGeometry:管道几何体
  • 辅助几何体

      - EdgesGeometry:边缘几何体。可以作为一个辅助对象来查看geometry的边缘。
      - WireframeGeometry:网格几何体。可以被用作一个辅助对象来查看geometry的线框。
  • 附加几何体。必须添加附加组件才能使用。

      - ConvexGeometry:凸包几何体
      - DecalGeometry:贴花几何体
      - ParametricGeometry:参数化几何体
      - TextGeometry:文本几何体
      - SDFGeometryGenerator:SDF几何体生成器

本文主要讨论二维平面几何体。

三、二维几何体

1. CircleGeometry:圆形几何体

CircleGeometry 是欧式几何的一个简单形状,它由围绕着一个中心点的三角分段的数量所构造,由给定的半径来延展。它可以创造圆形规则多边形

构造函数:

 CircleGeometry(radius : Float, segments : Integer, thetaStart : Float, thetaLength : Float)
属性是否必填描述
radius圆半径,默认1。
segments定义创建圆所用面的数量,最小为3,默认为32,数量越多圆越光滑。
thetaStart第一个分段的起始角度,默认为0。(钟面3点钟的位置)
thetaLength圆形扇区的中心角,通常被称为“θ”(西塔)。默认值是 2*Pi,这使其成为一个完整的圆。

代码示例:

const geometry = new THREE.CircleGeometry( 2, 32, Math.PI/4, Math.PI );
const material = new THREE.MeshBasicMaterial( { 
    color: 0xff3300 
} );
const circle = new THREE.Mesh( geometry, material );
scene.add( circle );

  • 渲染两面

不过,Three.js 默认渲染几何体只渲染前面(FrontSide),旋转相机,会发现背面(BackSide)什么都看不到。Three.js 这么做可以节约系统资源,提高渲染效率。

要看到背面,需要给材质(material)设置属性 side 值为 THREE.DoubleSide

const material = new THREE.MeshBasicMaterial( { 
    color: 0xff3300,
    side: THREE.DoubleSide 
});
  •  获取参数

通过 geometry.parameters 属性,可以获取构造函数里的各个参数。但是,当 Geometry 被实例化后,修改此属性并不会修改物体形状。如:

const geometry = new THREE.CircleGeometry( 2, 16, Math.PI/4, Math.PI );
// 修改属性值,不会修改Geometry形状
geometry.parameters.radius = 4;

只有销毁原来的 Geometry,重新创建一个 Geometry 。如,利用 GUI 控制一个立方体 box(部分代码)。

// 物体
const geometry = new THREE.BoxGeometry(1,1,1);
const material = new THREE.MeshBasicMaterial({
    color:"#ff3300"
});
const box = new THREE.Mesh( geometry, material );
scene.add( box );

// gui 控制
const params = {
    boxParam:{
        color:"#ff3300",
        width:1,
        height:1,
        depth:1
    }
}
// box控制
const folderBox = gui.addFolder("立方体控制");
folderBox.add(  params.boxParam,"width",1,10).onChange(function(value){
    box.geometry.dispose();
    box.geometry = new THREE.BoxGeometry( value ,params.boxParam.height, params.boxParam.depth);
});
folderBox.add(  params.boxParam,"height",1,10).onChange(function(value){
    box.geometry.dispose();
    box.geometry = new THREE.BoxGeometry( params.boxParam.width ,value, params.boxParam.depth);
});
  • 利用 GUI 调试几何体参数

此处以圆形几何体调试为例,其它几何体的参数调试大同小异。

HTML:

<script type="importmap">
    {
        "imports":{
            "three":"./js/three.module.min.js",
            "addons/":"./js/jsm/",
            "dat":"./js/gui/dat.gui.module.js"
        }
    }
</script>
<script type="module" src="js/myjs.js"></script>

 JS:

import * as THREE from "three";
import { OrbitControls } from "addons/controls/OrbitControls.js";
import * as dat from "dat";

let winH = window.innerHeight;
let winW = window.innerWidth;
let bili = winW / winH ;
// 场景
const scene = new THREE.Scene();
scene.background = new THREE.Color("#cccccc");

// grid
const gridHelper = new THREE.GridHelper(10,10);
scene.add( gridHelper);

// 相机
const camera = new THREE.PerspectiveCamera(50, bili, 1, 1000);
camera.position.set(0,5,5);
camera.lookAt(scene.position);

// 物体
const geometry = new THREE.CircleGeometry( 2, 16, Math.PI/4, Math.PI );
const material = new THREE.MeshBasicMaterial( { 
    color: 0xff3300,
    side: THREE.DoubleSide 
} );
const circle = new THREE.Mesh( geometry, material );

// 线框
const wireframe = new THREE.WireframeGeometry( geometry );
const line = new THREE.Line( wireframe );
line.material.depthTest = false;
line.material.opacity = 0.7;
line.material.transparent = true;
line.material.color = new THREE.Color("#ffff00");

const mesh = new THREE.Mesh();   // 创建空物体
mesh.add(circle);        // 给空物体添加子物体
mesh.add(line);          // 添加线框
scene.add( mesh );       // 在场景中添加物体

console.info(mesh);

// GUI
const data = {
    radius:geometry.parameters.radius,
    segments:geometry.parameters.segments,
    thetaStart:geometry.parameters.thetaStart,
    thetaLength:geometry.parameters.thetaLength
}
function updateGroupGeometry( mesh, geometry ) {
    mesh.children[0].geometry.dispose();
    mesh.children[0].geometry = geometry;

    mesh.children[1].geometry.dispose();
    mesh.children[1].geometry = new THREE.WireframeGeometry( geometry );
}
function changeGUI(){
    updateGroupGeometry( mesh,
        new THREE.CircleGeometry(
            data.radius, 
            data.segments, 
            data.thetaStart, 
            data.thetaLength
        )
    );
}
const gui = new dat.GUI();
const folder = gui.addFolder("CircleGeometry");
folder.add(data, "radius",1,10,1).onChange(changeGUI);
folder.add(data, "segments",3,64,1).onChange(changeGUI);
folder.add(data, "thetaStart",0,Math.PI*2).onChange(changeGUI);
folder.add(data, "thetaLength",0,Math.PI*2).onChange(changeGUI);
folder.open();
// 渲染器
const renderer  = new THREE.WebGLRenderer();
renderer.setSize( winW, winH );
document.body.appendChild( renderer.domElement );
renderer.render( scene, camera );

// 轨道控制器
const controls = new OrbitControls( camera, renderer.domElement );
controls.update();

// 动画
function animateFun(){
    controls.update();   // 现在动画里更新控制器
    // 渲染
    renderer.render( scene, camera);
    requestAnimationFrame(animateFun);
}
animateFun();
// 响应式
window.onresize = function(){
    winH = window.innerHeight;
    winW = window.innerWidth;
    renderer.setSize( winW, winH );
    camera.aspect = winW/winH;
    camera.updateProjectionMatrix();
    renderer.render( scene, camera );
}

2. PlaneGeometry:平面几何体

用于生成平面几何体。

构造函数:

 PlaneGeometry(width : Float, height : Float, widthSegments : Integer, heightSegments : Integer)
属性是否必填描述
width平面沿着 X 轴的宽度。默认值是 1
height平面沿着 Y 轴的高度。默认值是 1
widthSegments(可选)平面的宽度分段数,默认值是 1
heightSegments(可选)平面的高度分段数,默认值是 1

代码示例:

const geometry = new THREE.PlaneGeometry( 5, 5 );
const material = new THREE.MeshBasicMaterial( {
    color: 0xff3300,
    side: THREE.DoubleSide 
} );
const plane = new THREE.Mesh( geometry, material );
scene.add( plane );

3. RingGeometry:平面圆环几何体

用于生成二维圆环。

构造函数:

 RingGeometry(innerRadius : Float, outerRadius : Float, thetaSegments : Integer, phiSegments : Integer, thetaStart : Float, thetaLength : Float)
属性是否必填描述
innerRadius内部半径,默认值为 0.5
outerRadius外部半径,默认值是 1
thetaSegments圆环的分段数。这个值越大,圆环就越圆。最小值为 3,默认值为 32
phiSegments圆环半径的分段数字。最小值为1,默认值是 1
thetaStart起始角度,默认值为0。
thetaLength圆心角,默认值为 Math.PI * 2

示例代码:

const geometry = new THREE.RingGeometry(1,2,32 );
const material = new THREE.MeshBasicMaterial( { 
    color: 0xff3300,
    side: THREE.DoubleSide 
} );
const mesh = new THREE.Mesh( geometry, material );

4. ShapeGeometry:任意形状几何体

从一个或多个路径形状中创建一个单面几何体。

构造函数:

 ShapeGeometry(shapes : Array, curveSegments : Integer)
属性是否必填描述
shapes一个单独的shape,或者一个包含形状的Array。默认是一个三角形。
curveSegments每一个形状的分段数,默认值为 12

这里的 shape 形状,是指 Three.js 里定义的 Shape 对象。其基于Three.js 的 Path 类,该类定义了二维路径,提供了一些类似2D Canvas API的方法来创建或者构造二维路径。

具体参见 Three.js 官方文档。

示例代码:

const x = 0, y = 0;

const heartShape = new THREE.Shape();

heartShape.moveTo( x + 0.5, y + 0.5 );
heartShape.bezierCurveTo( x + 0.5, y + 0.5, x + 0.4, y, x, y );
heartShape.bezierCurveTo( x - 0.6, y, x - 0.6, y + 0.7,x - 0.6, y + 0.7 );
heartShape.bezierCurveTo( x - 0.6, y + 1.1, x - 0.3, y + 1.54, x + 0.5, y + 1.9 );
heartShape.bezierCurveTo( x + 1.2, y + 1.54, x + 1.6, y + 1.1, x + 1.6, y + 0.7 );
heartShape.bezierCurveTo( x + 1.6, y + 0.7, x + 1.6, y, x + 1, y );
heartShape.bezierCurveTo( x + 0.7, y, x + 0.5, y + 0.5, x + 0.5, y + 0.5 );

const geometry = new THREE.ShapeGeometry( heartShape );
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const mesh = new THREE.Mesh( geometry, material ) ;
scene.add( mesh );

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言—for循环(1)

for 语句在语法格式上&#xff0c;降低了提供循环结构时&#xff0c;遗忘循环三要素的几率。 for语句的应用场景&#xff1a;对循环次数预先可以获知的情况&#xff0c;如果预先无法获知次数时&#xff0c;推荐使用while语句 1.当型循环:(while) 特点&#xff1a; 先判断后执行…

Windows 安装和连接使用 PgSql数据库

一. PostgreSQL 安装详细步骤 下载地址&#xff1a;https://www.enterprisedb.com/postgresql-tutorial-resources-training-1?uuidd732dc13-c15a-484b-b783-307823940a11&campaignIdProduct_Trial_PostgreSQL_16 1. 双击打开安装包 2. 选择安装目录 3. 选择安装组件 4.…

[Flask]SSTI1 buuctf

声明&#xff1a;本篇文章csdn要我一天发两篇所以我来水的 跟ssti注入的详细知识我这里写了 https://blog.csdn.net/weixin_74790320/article/details/136154130 上面链接我复现了vulhub的SSTI&#xff0c;其实本质上是一道题 然后我们就用{{.__class__}}看类的类型&#xf…

java+vue_springboot企业设备安全信息系统14jbc

企业防爆安全信息系统采用B/S架构&#xff0c;数据库是MySQL。网站的搭建与开发采用了先进的java进行编写&#xff0c;使用了vue框架。该系统从三个对象&#xff1a;由管理员、人员和企业来对系统进行设计构建。主要功能包括&#xff1a;个人信息修改&#xff0c;对人员管理&am…

HBuilderX 插件开发指南(一):从插件开发到发布的完整流程

前端目前主流使用的IDE工具有VS Code、Sublime Text3、HBuilder X等等 本期我们主要了解HBuilder X&#xff0c;作为前端通用型开发工具&#xff0c;拥有可视化的操作方式&#xff0c;内置相关环境&#xff0c;开箱即用&#xff0c;无需配置nodejs等优点外&#xff0c;对uni-a…

Open CASCADE学习|用点分割边

在Open CASCADE Technology&#xff08;OCCT&#xff09;中&#xff0c;几何模型是由拓扑&#xff08;Topology&#xff09;和几何&#xff08;Geometry&#xff09;两部分组成的。拓扑部分描述了形状的拓扑结构&#xff0c;比如边、面、体等&#xff0c;而几何部分则定义了这些…

快速排序(2)——快速排序的优化

因为Hoare的快速排序写起来容易出错&#xff0c;并且有很多地方不太合适&#xff0c;于是&#xff0c;就有了一下几种优化。 基准值的优化 如果我们一直选取一组数据的第一个数据为基准值&#xff0c;如果遇到重复少的值的化&#xff0c;没什么问题。但是如果重复的值比较多的…

对称密钥的分配、公钥的分配

目录 密钥分配 1 对称密钥的分配 KDC 对会话密钥 KAB 的分配 对称密钥分配协议&#xff1a;Kerberos 2 公钥的分配 认证中心 CA (Certification Authority) 数字证书 (digital certificate) 已签名的 B 的数字证书的产生过程 X.509 数字证书 认证系统 证书链 证书…

2024.2.18 C++QT 作业

思维导图 练习题 1>定义一个基类 Animal&#xff0c;其中有一个虛函数perform&#xff08;)&#xff0c;用于在子类中实现不同的表演行为。 #include <iostream>using namespace std;class Animal { public:virtual void perform() {cout << "这是一个动…

红队攻防之office文件钓鱼制作ppt钓鱼

为众人抱薪者&#xff0c;不可使其冻毙于风雪&#xff1b;为自由开路者&#xff0c;不可使其困顿于荆棘。 PPT手势触发 这种攻击则利用的是鼠标轨迹来进行操作&#xff0c;比如鼠标点击、鼠标移动等。 首先&#xff0c;创建一个普通的PPTX文件&#xff0c;随便填入一些内容&…

《白话C++》第10章 STL和boost,Page74 10.4.4 std::unique_ptr

std::unique_ptr可以同时处理普通指针和指向数组的指针&#xff1a; unique_ptr像是auto_ptr的功能改良版 第一个改进就是可以管理指向单一对象的指针&#xff0c;也可以管理指向连续对象&#xff08;数组&#xff09;的指针。 第二个&#xff0c;unique_ptr改进的是&#xf…

huggingface入门玩耍LLM Starter

huggingface入门玩耍LLM Starter huggingface-cli 下载model 下载 本人macos系统&#xff0c;以下可参考 huggingface-cli 下载 brew install huggingface-climodel 下载 以 chatglm-6b 为例 huggingface-cli download --token hf_*** --resume-download THUDM/chatglm-6b-i…

C/C++ BM7 链表中环的入口结点

文章目录 前言题目解决方案一1.1 思路阐述1.2 源码 解决方案二2.1 思路阐述2.2 源码 总结 前言 BM6里面使用了双指针法和哈希的方式来查找环&#xff0c;BM7相对于BM6只多了一个查找第一个重复地址的过程。个人认为是用哈希是最简单&#xff0c;C11标准的set或者map。 题目 给…

洛谷 P1150 Peter 的烟

参考代码and代码解读 #include<iostream> using namespace std; int main() { int n,k,nonu; //n烟的数量&#xff0c;k需要多少根烟头换一支烟&#xff0c;nonu记录烟头的个数 cin>>n>>k; int sumn; //一开始就能吸n支烟 nonusum; …

C++友元->全局函数做友元、类做友元、成员函数做友元

全局函数做友元代码&#xff1a; #include<iostream> using namespace std; #include<string> //建筑物类 class Building { //告诉编译器 goodGay全局函数 是 Building类的好朋友&#xff0c;可以访问类中的私有内容 friend void goodGay(Building * bu…

linux kernel 内存踩踏之KASAN_HW_TAGS(MTE)(三)

一、背景 linux kernel 内存踩踏之KASAN&#xff08;一&#xff09;_kasan版本跟hasan版本区别-CSDN博客 linux kernel 内存踩踏之KASAN_SW_TAGS&#xff08;二&#xff09;-CSDN博客 最后来介绍一下KASAN_HW_TAGS&#xff0c;ARM64上就是MTE&#xff0c;这个特性在ARMv8.5支…

python in Vscode

背景 对于后端的语言选择&#xff1a; python&#xff0c;java&#xff0c;JavaScript备选。 选择Python 原因&#xff1a;可能是非IT专业的人中&#xff0c;会Python的人比较多。 目的 之前使用的IDE是VSCODE&#xff0c;在WSL的环境下使用。现在需要在在WSL的VSCODE下使…

分享几个丝滑oled代码

最近一段业余时间在捣鼓esp32&#xff0c;发现对于一个搞diy的来说&#xff0c;它的生态&#xff0c;不管是开发环境、氛围还是可玩度都是独一挡的&#xff0c;国内外基于此的扩展真是太多了&#xff0c;找了几个通过按键/旋钮进行0.96寸OLED控制的案例&#xff0c;超级丝滑&am…

【论文解读】Latency-Aware Collaborative Perception

Latency-Aware Collaborative Perception 摘要引言方法SystemSyncNet 实验 摘要 协作感知最近显示出提高单智能体感知感知能力的巨大潜力。现有的协同感知方法通常考虑理想的通信环境。然而&#xff0c;在实践中&#xff0c;通信系统不可避免地存在延迟问题&#xff0c;导致安…

2月16日openai又出了什么大招呢?

2024年2月16日通过google trends可以发现“sora”被大量的搜索与关注。那么什么是“sora”呢&#xff1f; Sora是OpenAI发布的一款文本到视频的AI模型&#xff0c;它能够根据文本指令生成逼真和富有想象力的场景。Sora 可以创建长达 60 秒的视频&#xff0c;其中包含高度详细的…