-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathIndexedGeometry.ts
148 lines (134 loc) · 4.1 KB
/
IndexedGeometry.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
import { Geometry } from './Geometry'
import { GeometryParams } from '../../types/Geometries'
/**
* Defines the available options to create an {@link IndexedGeometry#indexBuffer | index buffer}
*/
export interface IndexedGeometryIndexBufferOptions {
/** index buffer format */
bufferFormat?: GPUIndexFormat
/** index buffer array */
array?: Uint16Array | Uint32Array
}
/**
* Defines an {@link IndexedGeometry#indexBuffer | index buffer}
*/
export interface IndexBuffer {
/** index buffer format */
bufferFormat: GPUIndexFormat
/** index buffer array */
array: Uint16Array | Uint32Array
/** index buffer length */
bufferLength: number
/** index buffer {@link GPUBuffer} */
buffer?: GPUBuffer
}
/**
* Used to create an {@link IndexedGeometry} which holds an index array to use as an index buffer.
*
* The index array represents the order in which the attributes should be processed. This allows to create smaller vertex, uv and normal arrays.
*
* During the {@link IndexedGeometry#render | render}, the {@link IndexedGeometry} is responsible for setting the {@link IndexedGeometry#vertexBuffers | vertexBuffers} and drawing the indexed vertices.
*
* @example
* ```javascript
* const vertices = new Float32Array([
* -1, -1, 0,
* 1, -1, 0,
* -1, 1, 0,
* 1, 1, 0
* ])
*
* // vertices index (order in which they should be drawn)
* const indexArray = new Uint16Array([0, 2, 1, 1, 2, 3])
*
* // create an indexed quad geometry made of 4 vertices
* const indexedGeometry = new IndexedGeometry()
*
* indexedGeometry.setAttribute({
* name: 'position',
* type: 'vec3f',
* bufferFormat: 'float32x3',
* size: 3,
* bufferLength: vertices.length,
* array: vertices,
* })
*
* indexedGeometry.setIndexBuffer({
* array: indexArray,
* bufferFormat: 'uint16',
* })
* ```
*/
export class IndexedGeometry extends Geometry {
/** Object containing our index buffer format & length, array and GPUBuffer */
indexBuffer: IndexBuffer
/**
* IndexedGeometry constructor
* @param parameters - {@link GeometryParams | parameters} used to create our IndexedGeometry
*/
constructor({
verticesOrder = 'ccw',
topology = 'triangle-list',
instancesCount = 1,
vertexBuffers = [],
}: GeometryParams = {}) {
super({ verticesOrder, topology, instancesCount, vertexBuffers })
this.type = 'IndexedGeometry'
}
/**
* Get whether this geometry is ready to draw, i.e. it has been computed, all its vertex buffers have been created and its index buffer has been created as well
* @readonly
*/
get ready(): boolean {
return (
!this.shouldCompute &&
!this.vertexBuffers.find((vertexBuffer) => !vertexBuffer.buffer) &&
this.indexBuffer &&
!!this.indexBuffer.buffer
)
}
/**
* If we have less than 65.536 vertices, we should use a Uin16Array to hold our index buffer values
* @readonly
*/
get useUint16IndexArray(): boolean {
return this.verticesCount < 256 * 256
}
/**
* Set our {@link indexBuffer}
* @param parameters - {@link IndexedGeometryIndexBufferOptions | parameters} used to create our index buffer
*/
setIndexBuffer({ bufferFormat = 'uint32', array = new Uint32Array(0) }: IndexedGeometryIndexBufferOptions) {
this.indexBuffer = {
array,
bufferFormat,
bufferLength: array.length,
buffer: null,
}
}
/** RENDER **/
/**
* First, set our render pass geometry vertex buffers
* Then, set our render pass geometry index buffer
* @param pass - current render pass
*/
setGeometryBuffers(pass: GPURenderPassEncoder) {
super.setGeometryBuffers(pass)
pass.setIndexBuffer(this.indexBuffer.buffer, this.indexBuffer.bufferFormat)
}
/**
* Override the parentMesh draw method to draw indexed geometry
* @param pass - current render pass
*/
drawGeometry(pass: GPURenderPassEncoder) {
pass.drawIndexed(this.indexBuffer.bufferLength, this.instancesCount)
}
/**
* Destroy our indexed geometry vertex buffers and index buffer
*/
destroy() {
super.destroy()
this.indexBuffer?.buffer?.destroy()
this.indexBuffer.buffer = null
}
}