Skip to content

Commit 186ff15

Browse files
committed
Replace a boring cube with some particles.
1 parent 76ea788 commit 186ff15

File tree

1 file changed

+109
-9
lines changed

1 file changed

+109
-9
lines changed

source/titfront/src/components/Viewer.tsx

Lines changed: 109 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export class Viewer {
4545
this.camera.position.set(0, 0, 5);
4646
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
4747
this.controls.enablePan = true;
48-
this.setControlsRotation(Math.PI / 3, Math.PI / 4);
48+
// this.setControlsRotation(Math.PI / 3, Math.PI / 4);
4949
// TODO: This does not work properly.
5050
const resizeObserver = new ResizeObserver(() => {
5151
const width = 0.9 * this.container.clientWidth;
@@ -64,14 +64,114 @@ export class Viewer {
6464
light.position.set(10, 10, -10).normalize();
6565
this.scene.add(light);
6666

67-
// Add a test cube.
68-
const length = 4;
69-
const width = 2;
70-
const depth = 2;
71-
const geometry = new THREE.BoxGeometry(length, width, depth);
72-
const material = new THREE.MeshPhongMaterial({ color: 0x888888 });
73-
const cube = new THREE.Mesh(geometry, material);
74-
this.scene.add(cube);
67+
const vertices: number[] = [];
68+
const values: number[] = [];
69+
const N_FIXED = 4;
70+
const H = 0.6;
71+
const L = 2 * H;
72+
const dr = H / 80.0;
73+
const POOL_WIDTH = 5.366 * H;
74+
const POOL_HEIGHT = 2.5 * H;
75+
const POOL_M = Math.round(POOL_WIDTH / dr);
76+
const POOL_N = Math.round(POOL_HEIGHT / dr);
77+
const WATER_M = Math.round(L / dr);
78+
const WATER_N = Math.round(H / dr);
79+
const g = 9.81;
80+
const rho_0 = 1000;
81+
for (let i = -N_FIXED; i < POOL_M + N_FIXED; ++i) {
82+
for (let j = -N_FIXED; j < POOL_N; ++j) {
83+
const is_fixed = i < 0 || i >= POOL_M || j < 0;
84+
const is_fluid = i < WATER_M && j < WATER_N;
85+
86+
if (!is_fixed && !is_fluid) continue;
87+
88+
vertices.push(dr * (i + 0.5), dr * (j + 0.5), 0);
89+
values.push(0);
90+
}
91+
}
92+
for (let i = 0; i < vertices.length / 3; i++) {
93+
const x = vertices[i * 3];
94+
const y = vertices[i * 3 + 1];
95+
if (x < 0 || x >= L || y < 0 || y >= H) continue;
96+
97+
let pressure = rho_0 * g * (H - y);
98+
for (let n = 1; n < 2; n += 2) {
99+
const pi = Math.PI;
100+
pressure -=
101+
(((8 * rho_0 * g * H) / (pi * pi)) *
102+
(Math.exp((n * pi * (x - L)) / (2 * H)) *
103+
Math.cos((n * pi * y) / (2 * H)))) /
104+
(n * n);
105+
}
106+
values[i] = pressure;
107+
}
108+
let minValue = Infinity;
109+
let maxValue = -Infinity;
110+
for (let i = 0; i < values.length; i++) {
111+
minValue = Math.min(minValue, values[i]);
112+
maxValue = Math.max(maxValue, values[i]);
113+
}
114+
const range = maxValue - minValue;
115+
for (let i = 0; i < values.length; i++) {
116+
values[i] = (values[i] - minValue) / range;
117+
vertices[i * 3] -= POOL_WIDTH / 2;
118+
vertices[i * 3 + 1] -= POOL_HEIGHT / 2;
119+
}
120+
121+
const geometry = new THREE.BufferGeometry();
122+
geometry.setAttribute(
123+
"position",
124+
new THREE.Float32BufferAttribute(vertices, 3)
125+
);
126+
geometry.setAttribute("value", new THREE.Float32BufferAttribute(values, 1));
127+
const material = new THREE.ShaderMaterial({
128+
uniforms: {
129+
pointSize: { value: 0.0075 },
130+
cameraNear: { value: this.camera.near },
131+
cameraFar: { value: this.camera.far },
132+
lightPosition: { value: new THREE.Vector3(10, 10, -10) },
133+
ambientLightColor: { value: new THREE.Color(0xaaaaaa) },
134+
pointLightColor: { value: new THREE.Color(0xffffff) },
135+
},
136+
vertexShader: `
137+
uniform float pointSize;
138+
uniform float cameraNear;
139+
uniform float cameraFar;
140+
uniform vec3 lightPosition;
141+
in float value;
142+
out float fragValue;
143+
void main() {
144+
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
145+
gl_PointSize = pointSize * (cameraFar - cameraNear) / length(mvPosition.xyz);
146+
gl_Position = projectionMatrix * mvPosition;
147+
fragValue = value;
148+
}
149+
`,
150+
fragmentShader: `
151+
in float fragValue;
152+
uniform vec3 lightPosition;
153+
uniform vec3 ambientLightColor;
154+
uniform vec3 pointLightColor;
155+
vec3 jetColormap(float t) {
156+
t = clamp(t, 0.0, 1.0);
157+
float r = smoothstep(0.375, 0.625, t) + smoothstep(0.75, 1.0, t);
158+
float g = smoothstep(0.0, 0.5, t) - smoothstep(0.75, 1.0, t);
159+
float b = smoothstep(0.0, 0.25, t) - smoothstep(0.5, 0.75, t);
160+
return vec3(r, g, b);
161+
}
162+
void main() {
163+
vec2 pos = gl_PointCoord.xy - vec2(0.5);
164+
vec3 normal = normalize(vec3(pos, sqrt(1.0 - dot(pos, pos))));
165+
if (length(pos) > 0.5) discard;
166+
vec3 lightDirection = normalize(lightPosition - vec3(gl_FragCoord));
167+
float lightIntensity = max(dot(lightDirection, normal), 0.0);
168+
vec3 color = ambientLightColor + pointLightColor * lightIntensity;
169+
gl_FragColor = vec4(color * jetColormap(fragValue), 1.0);
170+
}
171+
`,
172+
});
173+
const particles = new THREE.Points(geometry, material);
174+
this.scene.add(particles);
75175
}
76176

77177
setControlsRotation(polar: number, azimuthal: number) {

0 commit comments

Comments
 (0)