Skip to content

Commit 58f8c6c

Browse files
authored
Add files via upload
1 parent bad5449 commit 58f8c6c

File tree

1 file changed

+293
-0
lines changed

1 file changed

+293
-0
lines changed

js/Cheap_Torus.js

Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
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

Comments
 (0)