-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathBoxGeometry.ts
168 lines (130 loc) · 4.47 KB
/
BoxGeometry.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
import { IndexedGeometry } from '../../core/geometries/IndexedGeometry'
import { Vec3 } from '../../math/Vec3'
import { GeometryBaseParams } from '../../types/Geometries'
/**
* Parameters used to create a {@link BoxGeometry}
*/
export interface BoxGeometryParams extends GeometryBaseParams {
/** Number of segments along the X axis */
widthSegments?: number
/** Number of segments along the Y axis */
heightSegments?: number
/** Number of segments along the Z axis */
depthSegments?: number
}
/**
* Helper to easily create 3D box indexed geometries.
*
* @example
* ```javascript
* const boxGeometry = new BoxGeometry()
* ```
*/
export class BoxGeometry extends IndexedGeometry {
constructor(
{
widthSegments = 1,
heightSegments = 1,
depthSegments = 1,
instancesCount = 1,
vertexBuffers = [],
topology,
} = {} as BoxGeometryParams
) {
super({ verticesOrder: 'ccw', topology, instancesCount, vertexBuffers })
this.type = 'BoxGeometry'
// taken from threejs
// https://github.com/mrdoob/three.js/blob/dev/src/geometries/BoxGeometry.js
widthSegments = Math.floor(widthSegments)
heightSegments = Math.floor(heightSegments)
depthSegments = Math.floor(depthSegments)
const vertices = []
const uvs = []
const normals = []
const indices = []
let numberOfVertices = 0
const buildPlane = (u, v, w, udir, vdir, width, height, depth, gridX, gridY) => {
const segmentWidth = width / gridX
const segmentHeight = height / gridY
const widthHalf = width / 2
const heightHalf = height / 2
const depthHalf = depth / 2
const gridX1 = gridX + 1
const gridY1 = gridY + 1
let vertexCounter = 0
const vector = new Vec3()
// generate vertices, normals and uvs
for (let iy = 0; iy < gridY1; iy++) {
const y = iy * segmentHeight - heightHalf
for (let ix = 0; ix < gridX1; ix++) {
const x = ix * segmentWidth - widthHalf
// set values to correct vector component
vector[u] = x * udir
vector[v] = y * vdir
vector[w] = depthHalf
// now apply vector to vertex buffer
vertices.push(vector.x, vector.y, vector.z)
// set values to correct vector component
vector[u] = 0
vector[v] = 0
vector[w] = depth > 0 ? 1 : -1
// now apply vector to normal buffer
normals.push(vector.x, vector.y, vector.z)
// uvs
uvs.push(ix / gridX)
uvs.push(iy / gridY)
// counters
vertexCounter += 1
}
}
// indices
// 1. you need three indices to draw a single face
// 2. a single segment consists of two faces
// 3. so we need to generate six (2*3) indices per segment
for (let iy = 0; iy < gridY; iy++) {
for (let ix = 0; ix < gridX; ix++) {
const a = numberOfVertices + ix + gridX1 * iy
const b = numberOfVertices + ix + gridX1 * (iy + 1)
const c = numberOfVertices + (ix + 1) + gridX1 * (iy + 1)
const d = numberOfVertices + (ix + 1) + gridX1 * iy
// faces
indices.push(a, b, d)
indices.push(b, c, d)
// update total number of vertices
numberOfVertices += vertexCounter
}
}
}
buildPlane('z', 'y', 'x', -1, -1, 2, 2, 2, depthSegments, heightSegments) // px
buildPlane('z', 'y', 'x', 1, -1, 2, 2, -2, depthSegments, heightSegments) // nx
buildPlane('x', 'z', 'y', 1, 1, 2, 2, 2, widthSegments, depthSegments) // py
buildPlane('x', 'z', 'y', 1, -1, 2, 2, -2, widthSegments, depthSegments) // ny
buildPlane('x', 'y', 'z', 1, -1, 2, 2, 2, widthSegments, heightSegments) // pz
buildPlane('x', 'y', 'z', -1, -1, 2, 2, -2, widthSegments, heightSegments) // nz
this.setAttribute({
name: 'position',
type: 'vec3f',
bufferFormat: 'float32x3',
size: 3,
array: new Float32Array(vertices),
})
this.setAttribute({
name: 'uv',
type: 'vec2f',
bufferFormat: 'float32x2',
size: 2,
array: new Float32Array(uvs),
})
this.setAttribute({
name: 'normal',
type: 'vec3f',
bufferFormat: 'float32x3',
size: 3,
array: new Float32Array(normals),
})
this.setIndexBuffer({
array: this.useUint16IndexArray ? new Uint16Array(indices) : new Uint32Array(indices),
bufferFormat: this.useUint16IndexArray ? 'uint16' : 'uint32',
})
}
}