1
+ // scene/demo-specific variables go here
2
+ let initialBoxGeometry ;
3
+ let boxGeometry , boxMaterial , boxMesh ;
4
+
5
+ let torus ;
6
+ let torusRotationAngle = 0 ;
7
+ let torusScale = 0 ;
8
+ let torusHeight = 0 ;
9
+ let torusHoleSize = 0 ;
10
+ let scaleFactor = 0 ;
11
+
12
+ let torus_ScaleObject , torus_ScaleController ;
13
+ let needChangeTorusScale = false ;
14
+ let torus_HeightObject , torus_HeightController ;
15
+ let needChangeTorusHeight = false ;
16
+ let torus_HoleSizeObject , torus_HoleSizeController ;
17
+ let needChangeTorusHoleSize = false ;
18
+ let torus_HoleSizeFineObject , torus_HoleSizeFineController ;
19
+ let needChangeTorusHoleSizeFine = false ;
20
+ let showTorusAABB_ToggleController , showTorusAABB_ToggleObject ;
21
+ let needChangeShowTorusAABB = false ;
22
+
23
+ let material_TypeObject , material_TypeController ;
24
+ let needChangeMaterialType = false ;
25
+ let matType = 0 ;
26
+ let material_ColorObject , material_ColorController ;
27
+ let needChangeMaterialColor = false ;
28
+ let matColor ;
29
+ let rotation_Folder ;
30
+ let transform_RotationXController , transform_RotationXObject ;
31
+ let transform_RotationYController , transform_RotationYObject ;
32
+ let transform_RotationZController , transform_RotationZObject ;
33
+ let needChangeRotation = false ;
34
+
35
+
36
+ function init_GUI ( )
37
+ {
38
+ torus_ScaleObject = { torusScale : 7 } ;
39
+ torus_HeightObject = { torusHeight : 0.5 } ;
40
+ torus_HoleSizeFineObject = { torusHoleSizeFine : 0.01 } ;
41
+ torus_HoleSizeObject = { torusHoleSize : 0.01 } ;
42
+ material_TypeObject = { torus_Material : 'Diffuse' } ;
43
+ material_ColorObject = { torus_Color : [ 1 , 1 , 1 ] } ;
44
+ showTorusAABB_ToggleObject = { show_torusAABB : false }
45
+ transform_RotationXObject = { rotationX : 0 } ;
46
+ transform_RotationYObject = { rotationY : 0 } ;
47
+ transform_RotationZObject = { rotationZ : 0 } ;
48
+
49
+ function handleTorusScaleChange ( ) { needChangeTorusScale = true ; }
50
+ function handleTorusHeightChange ( ) { needChangeTorusHeight = true ; }
51
+ function handleTorusHoleSizeFineChange ( ) { needChangeTorusHoleSizeFine = true ; }
52
+ function handleTorusHoleSizeChange ( ) { needChangeTorusHoleSize = true ; }
53
+ function handleMaterialTypeChange ( ) { needChangeMaterialType = true ; }
54
+ function handleMaterialColorChange ( ) { needChangeMaterialColor = true ; }
55
+ function handleShowTorusAABBChange ( ) { needChangeShowTorusAABB = true ; }
56
+ function handleRotationChange ( ) { needChangeRotation = true ; }
57
+
58
+ torus_ScaleController = gui . add ( torus_ScaleObject , 'torusScale' , 1 , 30 , 0.1 ) . onChange ( handleTorusScaleChange ) ;
59
+
60
+ rotation_Folder = gui . addFolder ( 'Rotation' ) ;
61
+ transform_RotationXController = rotation_Folder . add ( transform_RotationXObject , 'rotationX' , 0 , 359 , 1 ) . onChange ( handleRotationChange ) ;
62
+ transform_RotationYController = rotation_Folder . add ( transform_RotationYObject , 'rotationY' , 0 , 359 , 1 ) . onChange ( handleRotationChange ) ;
63
+ transform_RotationZController = rotation_Folder . add ( transform_RotationZObject , 'rotationZ' , 0 , 359 , 1 ) . onChange ( handleRotationChange ) ;
64
+
65
+ torus_HeightController = gui . add ( torus_HeightObject , 'torusHeight' , 0.005 , 0.7 , 0.01 ) . onChange ( handleTorusHeightChange ) ;
66
+ torus_HoleSizeFineController = gui . add ( torus_HoleSizeFineObject , 'torusHoleSizeFine' , 0 , 0.1 , 0.0001 ) . onChange ( handleTorusHoleSizeFineChange ) ;
67
+ torus_HoleSizeController = gui . add ( torus_HoleSizeObject , 'torusHoleSize' , 0 , 0.99 , 0.001 ) . onChange ( handleTorusHoleSizeChange ) ;
68
+ material_TypeController = gui . add ( material_TypeObject , 'torus_Material' , [ 'Diffuse' ,
69
+ 'Metal' , 'ClearCoat Diffuse' , 'Transparent Refractive' ] ) . onChange ( handleMaterialTypeChange ) ;
70
+ material_ColorController = gui . addColor ( material_ColorObject , 'torus_Color' ) . onChange ( handleMaterialColorChange ) ;
71
+ showTorusAABB_ToggleController = gui . add ( showTorusAABB_ToggleObject , 'show_torusAABB' , false ) . onChange ( handleShowTorusAABBChange ) ;
72
+
73
+ handleTorusScaleChange ( ) ;
74
+ handleTorusHeightChange ( ) ;
75
+ handleTorusHoleSizeChange ( ) ;
76
+ handleTorusHoleSizeFineChange ( ) ;
77
+ handleMaterialTypeChange ( ) ;
78
+ handleMaterialColorChange ( ) ;
79
+ handleShowTorusAABBChange ( ) ;
80
+ handleRotationChange ( ) ;
81
+
82
+ } // end function init_GUI()
83
+
84
+
85
+
86
+ // called automatically from within initTHREEjs() function (located in InitCommon.js file)
87
+ function initSceneData ( )
88
+ {
89
+ demoFragmentShaderFileName = 'Cheap_Torus_Fragment.glsl' ;
90
+
91
+ // scene/demo-specific three.js objects setup goes here
92
+ sceneIsDynamic = false ;
93
+
94
+ edgeSharpenSpeed = 0.1 ;
95
+
96
+ cameraFlightSpeed = 50 ;
97
+
98
+ // pixelRatio is resolution - range: 0.5(half resolution) to 1.0(full resolution)
99
+ pixelRatio = mouseControl ? 0.75 : 0.75 ;
100
+
101
+ EPS_intersect = 0.001 ;
102
+
103
+ // set camera's field of view
104
+ worldCamera . fov = 60 ;
105
+ focusDistance = 100.0 ;
106
+ apertureChangeSpeed = 10 ;
107
+
108
+ // position and orient camera
109
+ cameraControlsObject . position . set ( 0 , 20 , 30 ) ;
110
+ ///cameraControlsYawObject.rotation.y = 0.0;
111
+ // look slightly up or down
112
+ cameraControlsPitchObject . rotation . x = - 0.58 ;
113
+
114
+
115
+ torus = new THREE . Object3D ( ) ;
116
+ torus . position . set ( 0 , 0 , 0 ) ;
117
+
118
+ // even though this will eventually produce/render a box, instead of using THREE.BoxGeometry(2,2,2) (unit radius of 1 in all axes),
119
+ // I found that using THREE.CylinderGeometry produces a tighter-fitting AABB when the torus shape is rotated
120
+ initialBoxGeometry = new THREE . CylinderGeometry ( ) ; // use Cylinder as a starting point instead of Box
121
+ boxGeometry = new THREE . CylinderGeometry ( ) ; // use Cylinder as a starting point instead of Box
122
+ boxMaterial = new THREE . MeshBasicMaterial ( ) ;
123
+ boxMesh = new THREE . Mesh ( boxGeometry , boxMaterial ) ;
124
+
125
+
126
+ // scene/demo-specific uniforms go here
127
+ pathTracingUniforms . uTorus_InvMatrix = { value : new THREE . Matrix4 ( ) } ;
128
+ pathTracingUniforms . uBoxMinCorner = { value : new THREE . Vector3 ( ) } ;
129
+ pathTracingUniforms . uBoxMaxCorner = { value : new THREE . Vector3 ( ) } ;
130
+ pathTracingUniforms . uTorusHoleSize = { value : 0.01 } ;
131
+ pathTracingUniforms . uMaterialType = { value : 0 } ;
132
+ pathTracingUniforms . uMaterialColor = { value : new THREE . Color ( 1.0 , 0.0 , 1.0 ) } ;
133
+ pathTracingUniforms . uShowTorusAABB = { type : "b1" , value : false } ;
134
+
135
+ init_GUI ( ) ;
136
+
137
+ } // end function initSceneData()
138
+
139
+
140
+
141
+
142
+
143
+ // called automatically from within the animate() function (located in InitCommon.js file)
144
+ function updateVariablesAndUniforms ( )
145
+ {
146
+
147
+ if ( needChangeMaterialType )
148
+ {
149
+ matType = material_TypeController . getValue ( ) ;
150
+
151
+ if ( matType == 'Diffuse' )
152
+ {
153
+ pathTracingUniforms . uMaterialType . value = 1 ;
154
+ pathTracingUniforms . uMaterialColor . value . setRGB ( 0.01 , 0.6 , 0.6 ) ;
155
+ }
156
+ else if ( matType == 'Metal' )
157
+ {
158
+ pathTracingUniforms . uMaterialType . value = 3 ;
159
+ //pathTracingUniforms.uMaterialColor.value.setRGB(1.000000, 0.765557, 0.336057);
160
+ pathTracingUniforms . uMaterialColor . value . setRGB ( 0.955008 , 0.637427 , 0.538163 ) ;
161
+ }
162
+ else if ( matType == 'ClearCoat Diffuse' )
163
+ {
164
+ pathTracingUniforms . uMaterialType . value = 4 ;
165
+ pathTracingUniforms . uMaterialColor . value . setRGB ( 0.3 , 0.01 , 0.8 ) ;
166
+ }
167
+ else if ( matType == 'Transparent Refractive' )
168
+ {
169
+ pathTracingUniforms . uMaterialType . value = 2 ;
170
+ pathTracingUniforms . uMaterialColor . value . setRGB ( 0.1 , 1.0 , 0.6 ) ;
171
+ }
172
+
173
+ material_ColorController . setValue ( [ pathTracingUniforms . uMaterialColor . value . r ,
174
+ pathTracingUniforms . uMaterialColor . value . g ,
175
+ pathTracingUniforms . uMaterialColor . value . b ] ) ;
176
+
177
+ cameraIsMoving = true ;
178
+ needChangeMaterialType = false ;
179
+ }
180
+
181
+ if ( needChangeMaterialColor )
182
+ {
183
+ matColor = material_ColorController . getValue ( ) ;
184
+ pathTracingUniforms . uMaterialColor . value . setRGB ( matColor [ 0 ] , matColor [ 1 ] , matColor [ 2 ] ) ;
185
+
186
+ cameraIsMoving = true ;
187
+ needChangeMaterialColor = false ;
188
+ }
189
+
190
+ if ( needChangeRotation )
191
+ {
192
+ torus . rotation . set ( THREE . MathUtils . degToRad ( transform_RotationXController . getValue ( ) ) ,
193
+ THREE . MathUtils . degToRad ( transform_RotationYController . getValue ( ) ) ,
194
+ THREE . MathUtils . degToRad ( transform_RotationZController . getValue ( ) ) ) ;
195
+
196
+ torus . updateMatrixWorld ( true ) ;
197
+ pathTracingUniforms . uTorus_InvMatrix . value . copy ( torus . matrixWorld ) . invert ( ) ;
198
+
199
+ boxMesh . rotation . copy ( torus . rotation ) ;
200
+ boxMesh . updateMatrixWorld ( true ) ;
201
+ boxMesh . geometry . copy ( initialBoxGeometry ) ;
202
+ boxMesh . geometry . applyMatrix4 ( boxMesh . matrixWorld ) ;
203
+ boxMesh . geometry . computeBoundingBox ( ) ;
204
+ pathTracingUniforms . uBoxMinCorner . value . copy ( boxMesh . geometry . boundingBox . min ) ;
205
+ pathTracingUniforms . uBoxMaxCorner . value . copy ( boxMesh . geometry . boundingBox . max ) ;
206
+
207
+ cameraIsMoving = true ;
208
+ needChangeRotation = false ;
209
+ }
210
+
211
+ if ( needChangeTorusScale || needChangeTorusHeight || needChangeTorusHoleSize || needChangeTorusHoleSizeFine )
212
+ {
213
+ if ( needChangeTorusHoleSizeFine )
214
+ torus_HoleSizeController . setValue ( torus_HoleSizeFineController . getValue ( ) ) ;
215
+
216
+ if ( needChangeTorusHoleSize && torus_HoleSizeController . getValue ( ) <= 0.1 )
217
+ torus_HoleSizeFineController . setValue ( torus_HoleSizeController . getValue ( ) ) ;
218
+
219
+ torusScale = torus_ScaleController . getValue ( ) ;
220
+ torusHeight = torus_HeightController . getValue ( ) ;
221
+ torusHoleSize = torus_HoleSizeController . getValue ( ) ;
222
+
223
+ if ( needChangeTorusHoleSize )
224
+ {
225
+ // note: I tried to be clever and come up with a function f(x) that hits the following points on the sort-of exponential-looking
226
+ // curve which decreases the size of the torus height radius as a function of the torus hole getting bigger, but alas I failed.
227
+ // Therefore, I did the next best thing and defined some points along that elbow-curve that I wanted to hit, and then did a
228
+ // linear interpolation from point to point along the curve (kind of like moving a video game character/camera along a pre-defined
229
+ // path). In the end though, 'torusHeight'(radius) is re-writable, if these points do not satisfy the torus shape you're after.
230
+ if ( torusHoleSize < 0.01 ) torus_HeightController . setValue ( THREE . MathUtils . mapLinear ( torusHoleSize , 0.0 , 0.01 , 0.65 , 0.4 ) ) ;
231
+ else if ( torusHoleSize < 0.03 ) torus_HeightController . setValue ( THREE . MathUtils . mapLinear ( torusHoleSize , 0.01 , 0.03 , 0.4 , 0.2 ) ) ;
232
+ else if ( torusHoleSize < 0.05 ) torus_HeightController . setValue ( THREE . MathUtils . mapLinear ( torusHoleSize , 0.03 , 0.05 , 0.2 , 0.15 ) ) ;
233
+ else if ( torusHoleSize < 0.1 ) torus_HeightController . setValue ( THREE . MathUtils . mapLinear ( torusHoleSize , 0.05 , 0.1 , 0.15 , 0.1 ) ) ;
234
+ else if ( torusHoleSize < 0.2 ) torus_HeightController . setValue ( THREE . MathUtils . mapLinear ( torusHoleSize , 0.1 , 0.2 , 0.1 , 0.055 ) ) ;
235
+ else if ( torusHoleSize < 0.3 ) torus_HeightController . setValue ( THREE . MathUtils . mapLinear ( torusHoleSize , 0.2 , 0.3 , 0.055 , 0.035 ) ) ;
236
+ else if ( torusHoleSize < 0.4 ) torus_HeightController . setValue ( THREE . MathUtils . mapLinear ( torusHoleSize , 0.3 , 0.4 , 0.035 , 0.03 ) ) ;
237
+ else if ( torusHoleSize < 0.5 ) torus_HeightController . setValue ( THREE . MathUtils . mapLinear ( torusHoleSize , 0.4 , 0.5 , 0.03 , 0.025 ) ) ;
238
+ else if ( torusHoleSize < 0.6 ) torus_HeightController . setValue ( THREE . MathUtils . mapLinear ( torusHoleSize , 0.5 , 0.6 , 0.025 , 0.02 ) ) ;
239
+ else if ( torusHoleSize < 0.8 ) torus_HeightController . setValue ( THREE . MathUtils . mapLinear ( torusHoleSize , 0.6 , 0.8 , 0.02 , 0.015 ) ) ;
240
+ else if ( torusHoleSize < 1.01 ) torus_HeightController . setValue ( THREE . MathUtils . mapLinear ( torusHoleSize , 0.8 , 1.0 , 0.015 , 0.01 ) ) ;
241
+
242
+ torusHeight = torus_HeightController . getValue ( ) ;
243
+ }
244
+
245
+
246
+ //torus.rotation.set(0, 0, Math.PI * 0.5);
247
+ scaleFactor = THREE . MathUtils . mapLinear ( torusHoleSize , 0 , 1 , 1 , 50 ) ;
248
+ scaleFactor = 1 / Math . sqrt ( scaleFactor ) ;
249
+ torus . scale . set ( torusScale * scaleFactor , torusScale * torusHeight , torusScale * scaleFactor ) ;
250
+ torus . updateMatrixWorld ( true ) ;
251
+ // the following multiplication (torusHoleSize * 100) is for the quadric shape definition of the hyperboloid inside the fragment shader
252
+ pathTracingUniforms . uTorusHoleSize . value = torusHoleSize * 100 ;
253
+ pathTracingUniforms . uTorus_InvMatrix . value . copy ( torus . matrixWorld ) . invert ( ) ;
254
+
255
+ boxMesh . scale . set ( torusScale * 1.45 , torusScale * torusHeight * 2 , torusScale * 1.45 ) ;
256
+ boxMesh . updateMatrixWorld ( true ) ;
257
+ boxMesh . geometry . copy ( initialBoxGeometry ) ;
258
+ boxMesh . geometry . applyMatrix4 ( boxMesh . matrixWorld ) ;
259
+ boxMesh . geometry . computeBoundingBox ( ) ;
260
+ pathTracingUniforms . uBoxMinCorner . value . copy ( boxMesh . geometry . boundingBox . min ) ;
261
+ pathTracingUniforms . uBoxMaxCorner . value . copy ( boxMesh . geometry . boundingBox . max ) ;
262
+
263
+
264
+ cameraIsMoving = true ;
265
+ needChangeTorusScale = false ;
266
+ needChangeTorusHeight = false ;
267
+ needChangeTorusHoleSize = false ;
268
+ needChangeTorusHoleSizeFine = false ;
269
+ } // end if (needChangeTorusScale || needChangeTorusHeight || needChangeTorusHoleSize || needChangeTorusHoleSizeFine)
270
+
271
+
272
+ if ( needChangeShowTorusAABB )
273
+ {
274
+ pathTracingUniforms . uShowTorusAABB . value = showTorusAABB_ToggleController . getValue ( ) ;
275
+ cameraIsMoving = true ;
276
+ needChangeShowTorusAABB = false ;
277
+ }
278
+
279
+ // torusRotationAngle += (0.4 * frameTime);
280
+ // torusRotationAngle %= TWO_PI;
281
+ // torus.rotation.set(0, torusRotationAngle, Math.PI * 0.1);
282
+ // torus.updateMatrixWorld(true);
283
+ // pathTracingUniforms.uTorus_InvMatrix.value.copy(torus.matrixWorld).invert();
284
+
285
+
286
+ // INFO
287
+ cameraInfoElement . innerHTML = "FOV: " + worldCamera . fov + " / Aperture: " + apertureSize . toFixed ( 2 ) + " / FocusDistance: " + focusDistance + "<br>" + "Samples: " + sampleCounter ;
288
+
289
+ } // end function updateVariablesAndUniforms()
290
+
291
+
292
+
293
+ init ( ) ; // init app and start animating
0 commit comments