Three.js--"Geometry vertex knowledge explanation

Table of contents

Geometry Vertex Position Data

Point line defines geometry vertex data

Mesh Model Definition Geometry Vertex Data

Vertex normal data

Implement array cube and camera adaptation

Introduction to Common Geometries

Geometry rotation, scaling, and translation methods


Geometry Vertex Position Data

This article mainly explains the vertex concept of geometry, which is relatively low-level, but after mastering it, you will have a deeper understanding of the geometry and model objects of three.js. Before understanding the vertex data, we need to understand, three.js cuboid BoxGeometry, sphere SphereGeometry, etc. Geometry is built based on the BufferGeometry class. BufferGeometry is an empty geometry without any shape. We can customize any geometric shape through BufferGeometry, specifically to define vertex data .

Point line defines geometry vertex data

Create a set of xyz coordinate data through the JS typed array Float32Array to represent the vertex coordinates of the geometry.

// 创建一个空的几何体顶对象
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坐标 
])

The three.js geometry vertex data is represented by the attribute buffer object BufferAttribute of three.js.

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

Set the value of the geometry vertex position property:

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

Set the point material to define the point model : Add the point model to the scene:

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

Set the line material to define the line model : add the line model to the scene (of course there are the following line methods, you can try it yourself):

// 设置线材质
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 Model Definition Geometry Vertex Data

The mesh model Mesh renders the vertex coordinates of the custom geometry BufferGeometry. Through this model, everyone will understand the concept of a triangular surface. The mesh model Mesh is actually a splicing of triangles (faces). Using the mesh model to render the geometry means that all the vertex coordinates of the geometry form a group of three to form a triangle. Multiple groups of vertices form multiple triangles, which can be used to simulate the surface of an object.

// 网格模型渲染几何体
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)

For example, I want to make a rectangular plane. Just modify the vertex data :

Geometry vertex index data : After the geometry BufferGeoMetry corresponding to the mesh model Mesh splits multiple triangles, it is possible that the coordinates of the vertex positions of many triangles are the same. If we want to reduce the amount of vertex coordinate data, we can use the geometry vertex index geometry.index To implement:

// 创建一个空的几何体顶对象
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)

Vertex normal data

The concept of normal in mathematics: For example, a plane, the normal is the vertical line of the plane, if it is a smooth surface, the normal of a certain point is the normal of the cut surface of the point. The concept of normal in three.js is similar to the normal in mathematics, but it is more flexible when defining and will be adjusted as needed:

// 每个顶点的法线数据和顶点位置数据一一对应
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)

Implement array cube and camera adaptation

Create a column of models through a for loop, and then I array cubes through a double for loop, the code is as follows:

// 添加物体,创建几何体
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
  }
}

Next, I can see a larger observation range by zooming out the position of the camera, as follows:

Introduction to Common Geometries

three.js provides many geometry APIs, as follows:

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) // 圆形平面

Of course, when we set the rectangular plane and the circular plane, by default, only the front side can be seen, and the back side cannot be seen. If you want to set the back side to be visible, you need to set the material additionally, as follows:

Of course, it can also be displayed in grid form:

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)

Geometry rotation, scaling, and translation methods

BufferGeometry can scale, translate, and rotate the geometry itself through the following methods, which essentially change the vertex data of the geometry.

The specific practical operation has been more or less mentioned in the previous article. If you want to know more, you can refer to the official document

The relevant knowledge is explained here, ok gives the note code of this article:

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()

Guess you like

Origin blog.csdn.net/qq_53123067/article/details/130471556