Skip to content

Commit

Permalink
Replace a boring cube with some particles.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jhuighuy committed Feb 7, 2025
1 parent 76ea788 commit 186ff15
Showing 1 changed file with 109 additions and 9 deletions.
118 changes: 109 additions & 9 deletions source/titfront/src/components/Viewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export class Viewer {
this.camera.position.set(0, 0, 5);
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.controls.enablePan = true;
this.setControlsRotation(Math.PI / 3, Math.PI / 4);
// this.setControlsRotation(Math.PI / 3, Math.PI / 4);
// TODO: This does not work properly.
const resizeObserver = new ResizeObserver(() => {
const width = 0.9 * this.container.clientWidth;
Expand All @@ -64,14 +64,114 @@ export class Viewer {
light.position.set(10, 10, -10).normalize();
this.scene.add(light);

// Add a test cube.
const length = 4;
const width = 2;
const depth = 2;
const geometry = new THREE.BoxGeometry(length, width, depth);
const material = new THREE.MeshPhongMaterial({ color: 0x888888 });
const cube = new THREE.Mesh(geometry, material);
this.scene.add(cube);
const vertices: number[] = [];
const values: number[] = [];
const N_FIXED = 4;
const H = 0.6;
const L = 2 * H;
const dr = H / 80.0;
const POOL_WIDTH = 5.366 * H;
const POOL_HEIGHT = 2.5 * H;
const POOL_M = Math.round(POOL_WIDTH / dr);
const POOL_N = Math.round(POOL_HEIGHT / dr);
const WATER_M = Math.round(L / dr);
const WATER_N = Math.round(H / dr);
const g = 9.81;
const rho_0 = 1000;
for (let i = -N_FIXED; i < POOL_M + N_FIXED; ++i) {
for (let j = -N_FIXED; j < POOL_N; ++j) {
const is_fixed = i < 0 || i >= POOL_M || j < 0;
const is_fluid = i < WATER_M && j < WATER_N;

if (!is_fixed && !is_fluid) continue;

vertices.push(dr * (i + 0.5), dr * (j + 0.5), 0);
values.push(0);
}
}
for (let i = 0; i < vertices.length / 3; i++) {
const x = vertices[i * 3];
const y = vertices[i * 3 + 1];
if (x < 0 || x >= L || y < 0 || y >= H) continue;

let pressure = rho_0 * g * (H - y);
for (let n = 1; n < 2; n += 2) {
const pi = Math.PI;
pressure -=
(((8 * rho_0 * g * H) / (pi * pi)) *
(Math.exp((n * pi * (x - L)) / (2 * H)) *
Math.cos((n * pi * y) / (2 * H)))) /
(n * n);
}
values[i] = pressure;
}
let minValue = Infinity;
let maxValue = -Infinity;
for (let i = 0; i < values.length; i++) {
minValue = Math.min(minValue, values[i]);
maxValue = Math.max(maxValue, values[i]);
}
const range = maxValue - minValue;
for (let i = 0; i < values.length; i++) {
values[i] = (values[i] - minValue) / range;
vertices[i * 3] -= POOL_WIDTH / 2;
vertices[i * 3 + 1] -= POOL_HEIGHT / 2;
}

const geometry = new THREE.BufferGeometry();
geometry.setAttribute(
"position",
new THREE.Float32BufferAttribute(vertices, 3)
);
geometry.setAttribute("value", new THREE.Float32BufferAttribute(values, 1));
const material = new THREE.ShaderMaterial({
uniforms: {
pointSize: { value: 0.0075 },
cameraNear: { value: this.camera.near },
cameraFar: { value: this.camera.far },
lightPosition: { value: new THREE.Vector3(10, 10, -10) },
ambientLightColor: { value: new THREE.Color(0xaaaaaa) },
pointLightColor: { value: new THREE.Color(0xffffff) },
},
vertexShader: `
uniform float pointSize;
uniform float cameraNear;
uniform float cameraFar;
uniform vec3 lightPosition;
in float value;
out float fragValue;
void main() {
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_PointSize = pointSize * (cameraFar - cameraNear) / length(mvPosition.xyz);
gl_Position = projectionMatrix * mvPosition;
fragValue = value;
}
`,
fragmentShader: `
in float fragValue;
uniform vec3 lightPosition;
uniform vec3 ambientLightColor;
uniform vec3 pointLightColor;
vec3 jetColormap(float t) {
t = clamp(t, 0.0, 1.0);
float r = smoothstep(0.375, 0.625, t) + smoothstep(0.75, 1.0, t);
float g = smoothstep(0.0, 0.5, t) - smoothstep(0.75, 1.0, t);
float b = smoothstep(0.0, 0.25, t) - smoothstep(0.5, 0.75, t);
return vec3(r, g, b);
}
void main() {
vec2 pos = gl_PointCoord.xy - vec2(0.5);
vec3 normal = normalize(vec3(pos, sqrt(1.0 - dot(pos, pos))));
if (length(pos) > 0.5) discard;
vec3 lightDirection = normalize(lightPosition - vec3(gl_FragCoord));
float lightIntensity = max(dot(lightDirection, normal), 0.0);
vec3 color = ambientLightColor + pointLightColor * lightIntensity;
gl_FragColor = vec4(color * jetColormap(fragValue), 1.0);
}
`,
});
const particles = new THREE.Points(geometry, material);
this.scene.add(particles);
}

setControlsRotation(polar: number, azimuthal: number) {
Expand Down

0 comments on commit 186ff15

Please sign in to comment.