Three.js--》几何体顶点知识讲解

news2024/11/18 3:25:55

目录

几何体顶点位置数据

点线定义几何体顶点数据

网格模型定义几何体顶点数据

顶点法线数据

实现阵列立方体与相机适配

常见几何体简介

几何体的旋转、缩放、平移方法


几何体顶点位置数据

本篇文章主要讲解几何体的顶点概念,相对偏底层一些,不过掌握之后会更加深入理解three.js的几何体和模型对象,在了解顶点数据之前我们要明白,three.js的长方体BoxGeometry、球体SphereGeometry等几何体都是基于BufferGeometry类构建的,BufferGeometry是一个没有任何形状的空几何体,我们可以通过BufferGeometry自定义任何几何形状,具体一点说就是定义顶点数据

点线定义几何体顶点数据

通过JS类型化数组Float32Array创建一组xyz坐标数据用来表示几何体的顶点坐标。

// 创建一个空的几何体顶对象
const geometry = new THREE.BufferGeometry()
// 添加顶点数据
const vertices = new Float32Array([ // 数组里面编写顶点坐标数据
  0,0,0,   // 顶点1坐标
  50,0,0,  // 顶点2坐标 
  0,100,0, // 顶点3坐标 
  0,0,10,  // 顶点4坐标 
  0,0,100, // 顶点5坐标 
  50,0,10  // 顶点6坐标 
])

通过three.js的属性缓冲区对象 BufferAttribute 表示threejs几何体顶点数据。

// BufferAttribute属性缓冲对象表示顶点数据
const attribute = new THREE.BufferAttribute(vertices,3) // 3个为一组

设置几何体顶点位置属性的值:

// 设置几何体attribute属性的位置属性
geometry.attributes.position = attribute

设置点材质定义点模型:将点模型添加到场景当中:

// 设置点材质
const material = new THREE.PointsMaterial({
  color:0xffff00,
  size:0.2 ,
})
// 定义点模型
const points = new THREE.Points(geometry,material)
scene.add(points)

设置线材质定义线模型:将线模型添加到场景中(当然还有以下几种线条方式,可自行尝试):

// 设置线材质
const material = new THREE.LineBasicMaterial({
  color:0xffff00, // 黄色线条
})
const line = new THREE.Line(geometry,material) // 开放线条
// const line = new THREE.LineLoop(geometry,material) // 闭合线条
// const line = new THREE.LineSegments(geometry,material) // 非连续线条
scene.add(line)

网格模型定义几何体顶点数据

网格模型 Mesh 渲染自定义几何体 BufferGeometry 的顶点坐标,通过这个模型大家会理解三角形面的概念。网格模型Mesh其实就是一个一个三角形(面)拼接而成,使用网格模型渲染几何体,就是几何体的所有顶点坐标三个为一组,构成一个三角形,多组顶点构成多个三角形,就可以用来模拟表示物体的表面。

// 网格模型渲染几何体
const material = new THREE.MeshBasicMaterial({
  color:0x00ffff,
  // side:THREE.FrontSide, // 正面可见,反面不可见
  // side:THREE.BackSide, // 反面可见,正面不可见
  side:THREE.DoubleSide // 双面可看
})
const mesh = new THREE.Mesh(geometry,material)
scene.add(mesh)

比如我想弄一个矩形的平面。只要修改一下 顶点数据 即可:

几何顶点索引数据:网格模型Mesh对应的几何体BufferGeoMetry拆分多个三角之后,有可能很多三角形重合的顶点位置坐标是相同的,如果我们想减少顶点坐标数据量,可以借助几何体顶点索引 geometry.index 进行实现:

// 创建一个空的几何体顶对象
const geometry = new THREE.BufferGeometry()
// 添加顶点数据
const vertices = new Float32Array([ // 数组里面编写顶点坐标数据
  0,0,0,   // 顶点1坐标
  1,0,0,  // 顶点2坐标 
  1,1,0, // 顶点3坐标 

  0,1,0,  // 顶点4坐标 
])
// BufferAttribute属性缓冲对象表示顶点数据
const attribute = new THREE.BufferAttribute(vertices,3) // 3个为一组
// 设置几何体attribute属性的位置属性
geometry.attributes.position = attribute

// 类型化数组创建顶点数据
const indexs = new Uint16Array([
  0,1,2,0,2,3
])
// 几何体顶点索引的定义
geometry.index = new THREE.BufferAttribute(indexs,1)

顶点法线数据

数学上法线的概念:比如一个平面,法线就是该平面的垂线,如果是光滑曲面,某一点的法线就是该点切面的法线。three.js中法线和数学中的法线概念类似,只是定义的时候更加灵活,会根据需要进行调整:

// 每个顶点的法线数据和顶点位置数据一一对应
const normals = new Float32Array([
  0,0,1, // 顶点1法线
  0,0,1,
  0,0,1,
  0,0,1,
])
// 设置几何体的顶点法线数学
geometry.attributes.normal = new THREE.BufferAttribute(normals,3)

实现阵列立方体与相机适配

通过for循环创建一列模型,接下来我通过双重for循环阵列立方体,代码如下:

// 添加物体,创建几何体
const cubeGeometry = new THREE.BoxGeometry(1,1,1) // 设置几何体大小
const cubeMaterial = new THREE.MeshLambertMaterial({color:0xff0000}) // 设置几何体材质
// 阵列多个立方体网格模型
for(let i = 0;i < 10;i++){
  for(let j = 0;j < 10;j++){
    // 根据几何体和材质创建物体
    const cube = new THREE.Mesh(cubeGeometry,cubeMaterial)
    cube.position.set(i*2,0,j*2) // 沿着xz轴阵列
    scene.add(cube)
    cube.position.y=2
  }
}

接下来我通过将相机的位置拉远,可以看到更大的观察范围,如下:

常见几何体简介

three.js提供了很多几何体API,如下:

const cubeGeometry = new THREE.BoxGeometry(1,1,1) // 正方体
const cubeGeometry = new THREE.SphereGeometry(1) // 球体
const cubeGeometry = new THREE.CylinderGeometry(1,1,1) // 圆柱
const cubeGeometry = new THREE.PlaneGeometry(2,1) // 矩形平面
const cubeGeometry = new THREE.CircleGeometry(1) // 圆形平面

当然当我们设置矩形平面和圆形平面的时候,默认情况下是只有正面才可以看得到的,反面是看不到的,如果想设置反面可见的话,需要对材质进行另外设置,如下:

当然也可以以网格形式进行展现:

const geometry = new THREE.SphereGeometry(1)
// 网格模型渲染几何体
const material = new THREE.MeshBasicMaterial({
  color:0x00ffff,
  wireframe:true, // 网格形式展现
  // side:THREE.FrontSide, // 正面可见,反面不可见
  // side:THREE.BackSide, // 反面可见,正面不可见
  side:THREE.DoubleSide // 双面可看
})
const mesh = new THREE.Mesh(geometry,material)
scene.add(mesh)

几何体的旋转、缩放、平移方法

BufferGeometry通过以下等方法可以对几何体本身进行缩放、平移、旋转,这些方法本质上都是改变几何体的顶点数据。

具体的实践操作,在之前的文章或多或少都提及了一点,想了解更多的可自行参考官方文档

相关知识就讲解到这,ok给出本文的笔记代码:

import * as THREE from 'three';
// 导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

// 1.创建场景
const scene = new THREE.Scene();
// 2.创建相机
const camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000)
// 设置x、y、z轴坐标,即设置相机位置
camera.position.set(0,0,10)
// 将相机添加到场景之中
scene.add(camera)
// 3.添加物体,创建几何体
// // 创建一个空的几何体顶对象
// const geometry = new THREE.BufferGeometry()
// // 添加顶点数据
// const vertices = new Float32Array([ // 数组里面编写顶点坐标数据
//   0,0,0,   // 顶点1坐标
//   1,0,0,  // 顶点2坐标 
//   1,1,0, // 顶点3坐标 

//   0,1,0,  // 顶点4坐标 
// ])
// // BufferAttribute属性缓冲对象表示顶点数据
// const attribute = new THREE.BufferAttribute(vertices,3) // 3个为一组
// // 设置几何体attribute属性的位置属性
// geometry.attributes.position = attribute

// // 类型化数组创建顶点数据
// const indexs = new Uint16Array([
//   0,1,2,0,2,3
// ])
// // 几何体顶点索引的定义
// geometry.index = new THREE.BufferAttribute(indexs,1)

// // 每个顶点的法线数据和顶点位置数据一一对应
// const normals = new Float32Array([
//   0,0,1, // 顶点1法线
//   0,0,1,
//   0,0,1,
//   0,0,1,
// ])
// // 设置几何体的顶点法线数学
// geometry.attributes.normal = new THREE.BufferAttribute(normals,3)

// // 设置点材质
// const material = new THREE.PointsMaterial({
//   color:0xffff00,
//   size:0.2 ,
// })
// // 定义点模型
// const points = new THREE.Points(geometry,material)
// scene.add(points)

// // 设置线材质
// const material = new THREE.LineBasicMaterial({
//   color:0xffff00, // 黄色线条
// })
// const line = new THREE.Line(geometry,material) // 开放线条
// // const line = new THREE.LineLoop(geometry,material) // 闭合线条
// // const line = new THREE.LineSegments(geometry,material) // 非连续线条
// scene.add(line)

const geometry = new THREE.SphereGeometry(1)
// 网格模型渲染几何体
const material = new THREE.MeshBasicMaterial({
  color:0x00ffff,
  wireframe:true, // 网格形式展现
  // side:THREE.FrontSide, // 正面可见,反面不可见
  // side:THREE.BackSide, // 反面可见,正面不可见
  side:THREE.DoubleSide // 双面可看
})
const mesh = new THREE.Mesh(geometry,material)
scene.add(mesh)

// 4.初始化渲染器
const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth,window.innerHeight)
document.body.appendChild(renderer.domElement)

// 添加一个环境光
const ambient = new THREE.AmbientLight(0xffffff,0.9)
scene.add(ambient)

// 添加坐标轴辅助器
const axesHelper = new THREE.AxesHelper(5) // 数值代表线的长度
scene.add(axesHelper) // 添加到场景之中

// 创建轨道控制器
const controls =  new OrbitControls(camera,renderer.domElement)
// 设置控制器阻尼,让控制器更有真实效果,但必须在动画循环里调用 .update()
controls.enableDamping = true

export function render(){
  // 每次循环渲染时调用stats更新方法,来刷新时间
  controls.update()
  renderer.render(scene,camera) // 周期性执行相机的渲染功能,更新canvas画布上的内容
  requestAnimationFrame(render) // 接下来渲染下一帧的时候就会调用render函数
}
// 先开始就渲染一下
render()

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

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

相关文章

魔兽世界商业服务端定制商人自定义NPC教程

魔兽世界自定义NPC教程 大家好&#xff0c;我是艾西今天跟大家聊一下自定义NPC&#xff0c;自定义NPC可以添加自己想要售卖的物品以及定价等可以更好的将一个游戏设定以及游戏的拓展性有质的提升 creature表是游戏所有生物人物等表格 Creature_template是所有生物模板&#xf…

kafka快的原因(四)

四、kafka快的原因 4.1 顺序读写page cache 见上一节文件系统 使用6个7200rpm、SATA接口、RAID-5的磁盘阵列在JBOD配置下的顺序写入的性能约为600MB/秒&#xff0c;但随机写入的性能仅约为100k/秒&#xff0c;相差6000倍以上。 4.2 网络模型 4.2.1 reactor模型 4.2.2 epo…

kubernetes项目部署

目录 ​一、容器交付流程 二、k8s平台部署项目流程 三、在K8s平台部署项目 一、容器交付流程 容器交付流程通常分为四个阶&#xff1a;开发阶段、持续集成阶段、应用部署阶段和运维阶段。 开发阶段&#xff1a;开发应用程序&#xff0c;编写Dockerfile; 持续集成阶段&#…

gradle 模块

目录 ​settings.gradle文件的作用 SourceSet类的作用 Plugin 插件 Java 对 Plugin 的扩展 settings.gradle文件的作用 settings用于配置哪些工程是要被gradle集成的&#xff0c;gradle 通过 Settings.java 类来处理 settings.gradle 文件。 gradle的初始化阶段&#xff0c…

【音视频处理】RTMP、HLS、HTTP-FLV、WebRTC、RTSP的区别?直播协议详解

大家好&#xff0c;欢迎来到停止重构的频道。 本期我们详细讨论直播的相关协议&#xff0c;包括&#xff1a;HTTP-FLV、HLS、RTMP、Web-RTC、RTSP等等。 我们将会详细介绍这些协议的工作原理、应用场景、及延迟的原因。 我们按这样的顺序讨论​ 1、 RTMP、HTTP-FLV 2、 …

【五一创作】红黑树数据结构

现在JAVASE中HashMap中底层源码是由数组链表红黑树进行设计的&#xff0c;然后很多地方也是用到红黑树&#xff0c;这里单独对红黑树数据结构进行简单的介绍。 目录 红黑树概念 红黑树的性质 自平衡规则 代码 红黑树概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;…

flink-on-yarn两种提交模式及其区别

一、session模式 在yarn上启动一个flink集群&#xff0c;并重复使用该集群&#xff0c;后续提交的任务都是提交给该集群&#xff0c;资源会一直被占用&#xff0c;除非手动关闭。 特点&#xff1a;需要事先申请资源&#xff0c;启动JobManager和TaskManager。 优点&#xff1a…

网卡丢失导致集群异常

假期晚上有个电话&#xff0c;说集群故障&#xff0c;应用无法连接&#xff0c;节点一可以ssh登录&#xff0c;节点二已无法正常登录了&#xff0c;在节点一上需要ssh 私网ip地址才可以登录节点二&#xff0c;虽不是重点客户&#xff0c;有问题还是需要积极处理。 首先看集群状…

LeetCode - 239 滑动窗口最大值

目录 题目来源 题目描述 示例 提示 题目解析 算法源码 题目来源 239. 滑动窗口最大值 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k…

AutoCAD介绍——带你了解最强的CAD软件

AutoCAD介绍——带你了解最强的CAD软件 什么是AutoCAD应用领域功能特点版本发展总结 什么是AutoCAD Autodesk的AutoCAD是一款世界著名的CAD软件&#xff0c;其全称为“Auto Computer-Aided Design”&#xff0c;是一种计算机辅助设计工具&#xff0c;用于帮助用户创建和编辑二…

k8s之审计日志

一、为什么要有审计 Kube-Apiserver 的负载突然变高&#xff0c;大量访问失败&#xff0c;集群中到底发生了什么&#xff1f; 当集群发生问题时&#xff0c;这是Metric一般会失效&#xff0c;为了排查以上问题&#xff0c;k8s 提供了两种原生的日志形式——审计&#xff08;A…

PID整定二:基于Ziegler-Nichols的频域响应

PID整定二&#xff1a;基于Ziegler-Nichols的频域响应 1参考2连续Ziegler-Nichols方法的PID整定2.1整定方法2.2仿真示例 1参考 1.1根轨迹图的绘制及分析 1.2计算机控制技术01-3.4离散系统的根轨迹分析法 1.3PID控制算法学习笔记 2连续Ziegler-Nichols方法的PID整定 2.1整定…

2023软考中级《软件设计师》(备考冲刺版) | 知识产权与标准化

1.知识产权 1.1 保护对象和范围 1.2 保护期限 注意&#xff1a;注册商标续注可延长 1.3 知识产权人确定 1.3.1 职务作品&#xff08;区分个人和公司单位&#xff1a;大部分都是公司单位&#xff09; 1.3.2 委托开发、合作开发与同时申请 1.4 侵权判定 1.第二十五条对下列各…

操作系统——线程调度

0.关注博主有更多知识 操作系统入门知识合集 目录 6.1线程调度概念 思考题&#xff1a; 6.2典型调度算法 思考题&#xff1a; 6.3Linux线程调度 6.1线程调度概念 在第四章曾经介绍过&#xff0c;线程是操作系统调度的基本单位&#xff0c;那么本篇就不再以进程的视角去…

【操作系统OS】学习笔记第二章 进程与线程(下)【哈工大李治军老师】

基于本人观看学习 哈工大李治军老师主讲的操作系统课程 所做的笔记&#xff0c;仅进行交流分享。 特此鸣谢李治军老师&#xff0c;操作系统的神作&#xff01; 如果本篇笔记帮助到了你&#xff0c;还请点赞 关注 支持一下 ♡>&#x16966;<)!! 主页专栏有更多&#xff0…

基于rke部署的k8s集群如何配置kube-proxy工作在ipvs模式

kube-proxy默认工作在iptables模式下&#xff0c;在集群配置文件cluster.yml中添加如下配置项即可开启ipvs模式。然后执行 rke up 命令使配置生效。

软件测试的ABC

文章目录 一. 衡量软件测试结果的依据—需求1. 什么是需求2. 案例 - 平台支持邮箱注册3. 从测试人员角度看需求 二. 测试用例1. 测试用例的概念2. 案例3. 为什么要有测试用例 三. 软件错误 (BUG)1. 什么是bug2. 如何描述一个bug3. bug的级别4. bug的生命周期5. 如果因为bug和开…

Java面试题总结 | Java面试题总结8- Redis模块(持续更新)

Redis 文章目录 Redisredis的线程模型Redis的Mysql的区别Redis和传统的关系型数据库有什么不同&#xff1f;Redis常见的数据结构zset数据结构Redis中rehash过程redis为什么不考虑线程安全的问题呢Redis单线程为什么还能这么快&#xff1f;为什么Redis是单线程的&#xff1f;red…

【SpringMVC】| SpringMVC执行流程原理 | 常用注解 剥析

MVC目录 一. &#x1f981; MVC模型二. &#x1f981; SpringMVC1. SpringMVC执行流程&#xff08;重点&#xff09;Ⅰ. SpringMVC四大组件Ⅱ. 执行流程 2. RequestMapping3. RequestParam4. ReuqestHeader & CookieValue5. RESTful风格支持Ⅰ. 传统 vs restfulⅡ. PathVar…

5. Docker——先快速入门

本章讲解知识点 Docker 是什么为什么要使用 DockerDocker 引擎Docker 常用命令Docker 生命周期详解虽然我们上一章教大家搭建好了 Kubernetes + Docker 环境,但是我们本章是先从 Docker 讲起,为后面学习 Kubernetes 打好基础。 1. Docker 是什么 Docker 是一种开源的容器化…