-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathProjectedObject3D.ts
167 lines (146 loc) · 5.22 KB
/
ProjectedObject3D.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
import { Object3D, Object3DMatricesType, Object3DTransformMatrix } from './Object3D'
import { GPUCurtains } from '../../curtains/GPUCurtains'
import { CameraRenderer, isCameraRenderer } from '../renderers/utils'
import { Mat4 } from '../../math/Mat4'
import { Camera } from '../camera/Camera'
/** Defines all kind of possible {@link ProjectedObject3D} matrix types */
export type ProjectedObject3DMatricesType = Object3DMatricesType | 'modelView' | 'modelViewProjection'
/** Defines all possible {@link Object3DTransformMatrix | matrix object} used by our {@link ProjectedObject3D} */
export type ProjectedObject3DMatrices = Record<ProjectedObject3DMatricesType, Object3DTransformMatrix>
/**
* Used to apply the {@link Camera#projectionMatrix | projection} and {@link Camera#viewMatrix | view} matrices of a {@link Camera} to an {@link Object3D}, in order to compute {@link ProjectedObject3D#modelViewMatrix | modelView} and {@link ProjectedObject3D#modelViewProjectionMatrix | modelViewProjection} matrices.
*/
export class ProjectedObject3D extends Object3D {
/** {@link Camera | Camera} object used to compute {@link ProjectedObject3D#modelViewMatrix | model view} and {@link ProjectedObject3D#modelViewProjectionMatrix | model view projection} matrices */
camera: Camera
/** {@link ProjectedObject3DMatrices | Matrices object} of the {@link ProjectedObject3D} */
matrices: ProjectedObject3DMatrices
/**
* ProjectedObject3D constructor
* @param renderer - {@link CameraRenderer} object or {@link GPUCurtains} class object used to create this {@link ProjectedObject3D}
*/
constructor(renderer: CameraRenderer | GPUCurtains) {
super()
// we could pass our curtains object OR our curtains renderer object
renderer = (renderer && (renderer as GPUCurtains).renderer) || (renderer as CameraRenderer)
isCameraRenderer(renderer, 'ProjectedObject3D')
this.camera = renderer.camera
}
/**
* Tell our projection matrix stack to update
*/
applyPosition() {
super.applyPosition()
this.shouldUpdateProjectionMatrixStack()
}
/**
* Tell our projection matrix stack to update
*/
applyRotation() {
super.applyRotation()
this.shouldUpdateProjectionMatrixStack()
}
/**
* Tell our projection matrix stack to update
*/
applyScale() {
super.applyScale()
this.shouldUpdateProjectionMatrixStack()
}
/**
* Tell our projection matrix stack to update
*/
applyTransformOrigin() {
super.applyTransformOrigin()
this.shouldUpdateProjectionMatrixStack()
}
/**
* Set our transform and projection matrices
*/
setMatrices() {
super.setMatrices()
this.matrices = {
...this.matrices,
modelView: {
matrix: new Mat4(),
shouldUpdate: false,
onUpdate: () => {
// our model view matrix is our model matrix multiplied with our camera view matrix
this.modelViewMatrix.multiplyMatrices(this.viewMatrix, this.worldMatrix)
},
},
modelViewProjection: {
matrix: new Mat4(),
shouldUpdate: false,
onUpdate: () => {
// our modelViewProjection matrix, useful for bounding box calculations and frustum culling
// this is the result of our projection matrix multiplied by our modelView matrix
this.modelViewProjectionMatrix.multiplyMatrices(this.projectionMatrix, this.modelViewMatrix)
},
},
}
}
/**
* Get our {@link modelViewMatrix | model view matrix}
*/
get modelViewMatrix(): Mat4 {
return this.matrices.modelView.matrix
}
/**
* Set our {@link modelViewMatrix | model view matrix}
* @param value - new {@link modelViewMatrix | model view matrix}
*/
set modelViewMatrix(value: Mat4) {
this.matrices.modelView.matrix = value
this.matrices.modelView.shouldUpdate = true
}
/**
* Get our {@link Camera#viewMatrix | camera view matrix}
* @readonly
*/
get viewMatrix(): Mat4 {
return this.camera.viewMatrix
}
/**
* Get our {@link Camera#projectionMatrix | camera projection matrix}
* @readonly
*/
get projectionMatrix(): Mat4 {
return this.camera.projectionMatrix
}
/**
* Get our {@link modelViewProjectionMatrix | model view projection matrix}
*/
get modelViewProjectionMatrix(): Mat4 {
return this.matrices.modelViewProjection.matrix
}
/**
* Set our {@link modelViewProjectionMatrix | model view projection matrix}
* @param value - new {@link modelViewProjectionMatrix | model view projection matrix}s
*/
set modelViewProjectionMatrix(value: Mat4) {
this.matrices.modelViewProjection.matrix = value
this.matrices.modelViewProjection.shouldUpdate = true
}
/**
* Set our projection matrices shouldUpdate flags to true (tell them to update)
*/
shouldUpdateProjectionMatrixStack() {
this.matrices.modelView.shouldUpdate = true
this.matrices.modelViewProjection.shouldUpdate = true
}
/**
* When the world matrix update, tell our projection matrix to update as well
*/
shouldUpdateWorldMatrix() {
super.shouldUpdateWorldMatrix()
this.shouldUpdateProjectionMatrixStack()
}
/**
* Tell all our matrices to update
*/
shouldUpdateMatrixStack() {
this.shouldUpdateModelMatrix()
this.shouldUpdateProjectionMatrixStack()
}
}