From 34148aade24f55327c167640da07543114979fa4 Mon Sep 17 00:00:00 2001 From: Lobo Date: Sat, 21 Feb 2026 11:47:57 +0100 Subject: [PATCH] Added UI and painted pendulum in different colors --- .../conway-gol/conway-gol.component.html | 8 +- .../pathfinding/pathfinding.component.html | 6 +- .../pendulum/pendulum.component.html | 32 ++++- .../algorithms/pendulum/pendulum.component.ts | 73 ++++++++++-- .../algorithms/pendulum/pendulum.model.ts | 21 ++++ .../algorithms/pendulum/pendulum.shader.ts | 109 ++++++++++++------ src/assets/i18n/de.json | 10 ++ src/assets/i18n/en.json | 10 ++ src/styles.scss | 10 +- 9 files changed, 227 insertions(+), 52 deletions(-) create mode 100644 src/app/pages/algorithms/pendulum/pendulum.model.ts diff --git a/src/app/pages/algorithms/conway-gol/conway-gol.component.html b/src/app/pages/algorithms/conway-gol/conway-gol.component.html index 7bb078b..d0cfcc0 100644 --- a/src/app/pages/algorithms/conway-gol/conway-gol.component.html +++ b/src/app/pages/algorithms/conway-gol/conway-gol.component.html @@ -35,8 +35,8 @@ }

{{ 'SORTING.EXECUTION_TIME' | translate }}: {{ executionTime }} ms

-
- +
+ {{ 'ALGORITHM.GRID_HEIGHT' | translate }} - + {{ 'ALGORITHM.GRID_WIDTH' | translate }} - + {{ 'GOL.SPEED' | translate }}
-
- +
+ {{ 'ALGORITHM.GRID_HEIGHT' | translate }} - + {{ 'ALGORITHM.GRID_WIDTH' | translate }} - Ich bin ein Pendel - blub + {{ 'PENDULUM.TITLE' | translate }} +
+
+

{{ 'PENDULUM.TRAIL_DECAY_TIME' | translate }}

+ +

{{ 'PENDULUM.ATTRACTION' | translate }}

+ +
+
+

{{ 'PENDULUM.L1_LENGTH' | translate }}

+ +

{{ 'PENDULUM.L2_LENGTH' | translate }}

+ +
+
+

{{ 'PENDULUM.M1_MASS' | translate }}

+ +

{{ 'PENDULUM.M2_MASS' | translate }}

+ +
+
+

{{ 'PENDULUM.DAMPING' | translate }}

+ +
+
+ L1 + L2 + M1 + M2 +
+
= 10.0) { - isLine = true; - trailVal = trailVal - 10.0; // Remove flag to get the true trail value underneath + // 1. Check for overlays (Lines) + if (val >= 20.0) { + isLine2 = true; + val = val - 20.0; + } else if (val >= 10.0) { + isLine1 = true; + val = val - 10.0; } - let bgColor = vec3(0.1, 0.1, 0.15); - let massColor = vec3(1.0, 1.0, 1.0); - let lineColor = vec3(0.5, 0.5, 0.5); + // 2. Check which trail it is + var isTrail2 = false; + if (val >= 2.0) { + isTrail2 = true; + val = val - 2.0; + } + + // 3. What remains is purely the fading intensity (0.0 to 1.0) + let trailIntensity = val; + + // --- COLORS --- + let bgColor = vec3(0.1, 0.1, 0.15); + let mass1Color = vec3(1.0, 0.0, 0.0); // Red + let mass2Color = vec3(0.0, 1.0, 0.0); // Green + let line1Color = vec3(1.0, 1.0, 0.0); // Yellow + let line2Color = vec3(1.0, 0.0, 1.0); // Magenta + + var massColor = mass1Color; + if (isTrail2) { + massColor = mass2Color; + } // Calculate background blending with the trail - var finalColor = mix(bgColor, massColor, clamp(trailVal, 0.0, 1.0)); + var finalColor = mix(bgColor, massColor, clamp(trailIntensity, 0.0, 1.0)); - // Overwrite with the grey line if necessary - if (isLine) { - finalColor = lineColor; - } + // Overwrite with the line colors if necessary + if (isLine1) { finalColor = line1Color; } + if (isLine2) { finalColor = line2Color; } fragmentOutputs.color = vec4(finalColor, 1.0); return fragmentOutputs; @@ -152,17 +172,24 @@ export const PENDULUM_RENDER_COMPUTE_SHADER_WGSL = SHARED_STRUCTS + ` let aspect = p.width / p.height; let uv_corr = vec2(uv.x * aspect, uv.y); - // --- TRAIL EXTRACT & DECAY --- - let oldRaw = pixelBuffer[index]; - var oldTrail = oldRaw; + // --- 1. EXTRACT & DECAY OLD MEMORY --- + var memory = pixelBuffer[index]; - // If the pixel was a line last frame, remove the +10 flag to get the trail memory - if (oldTrail >= 10.0) { - oldTrail = oldTrail - 10.0; + // Strip line overlays from the previous frame + if (memory >= 20.0) { memory = memory - 20.0; } + else if (memory >= 10.0) { memory = memory - 10.0; } + + // Check if the memory belongs to Trail 2 + var isTrail2 = false; + if (memory >= 2.0) { + isTrail2 = true; + memory = memory - 2.0; } - var newVal = oldTrail * p.trailDecay; - // Pendulum geometry + // Apply decay to the pure intensity + memory = memory * p.trailDecay; + + // --- 2. CALCULATE GEOMETRY --- let origin = vec2(0.5 * aspect, 0.3); let displayScale = 0.15; @@ -174,18 +201,34 @@ export const PENDULUM_RENDER_COMPUTE_SHADER_WGSL = SHARED_STRUCTS + ` let dMass1 = length(uv_corr - p1); let dMass2 = length(uv_corr - p2); - let isLine = (dLine1 < 0.002 || dLine2 < 0.002); - let isMass = (dMass1 < 0.01 || dMass2 < 0.01); + // --- 3. SMART LAYERING --- + var baseVal = 0.0; - // --- SMART LAYERING --- - if (isMass) { - newVal = 1.0; - } else if (isLine) { - // Lines are marked with +10.0 to tell the fragment shader to paint them grey, - // WITHOUT overwriting the fading trail memory underneath! - newVal = newVal + 10.0; + // Base Layer (Masses & Trails) + if (dMass1 < 0.02) { + baseVal = 1.0; // Mass 1 = 1.0 (Trail 1 Max) + } else if (dMass2 < 0.02) { + baseVal = 3.0; // Mass 2 = 2.0 (Flag) + 1.0 (Trail 2 Max) + } else { + // Write fading memory back + if (isTrail2) { + baseVal = memory + 2.0; + } else { + baseVal = memory; + } } - pixelBuffer[index] = newVal; + // Overlay Layer (Lines) + var overlay = 0.0; + // Don't draw lines over the masses (Clean Z-Index) + if (dMass1 < 0.02 || dMass2 < 0.02) { + overlay = 0.0; + } else if (dLine1 < 0.003) { + overlay = 10.0; + } else if (dLine2 < 0.003) { + overlay = 20.0; + } + + pixelBuffer[index] = baseVal + overlay; } `; diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index 91fb19a..7e4c94e 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -415,6 +415,16 @@ "DISCLAIMER_4": "Licht & Schatten: Um die Tiefe sichtbar zu machen, werden Lichtreflexionen und Schatten (Ambient Occlusion) basierend auf der Krümmung der Formel simuliert." } }, + "PENDULUM": { + "TITLE": "Doppel-Pendel", + "TRAIL_DECAY_TIME": "Spurlänge", + "DAMPING": "Dämpfung", + "ATTRACTION": "Anziehungskraft", + "L1_LENGTH": "Länge L1", + "L2_LENGTH": "Länge L2", + "M1_MASS": "Masse M1", + "M2_MASS": "Masse M2" + }, "ALGORITHM": { "TITLE": "Algorithmen", "PATHFINDING": { diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 845b786..29d8324 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -414,6 +414,16 @@ "DISCLAIMER_4": "Light & Shadow: To visualize depth, light reflections and shadows (Ambient Occlusion) are simulated based on the curvature of the formula." } }, + "PENDULUM": { + "TITLE": "Double pendulum", + "TRAIL_DECAY_TIME": "Trail length", + "DAMPING": "Damping", + "ATTRACTION": "Attraction", + "L1_LENGTH": "Length L1", + "L2_LENGTH": "Length L2", + "M1_MASS": "Mass M1", + "M2_MASS": "Mass M2" + }, "ALGORITHM": { "TITLE": "Algorithms", "PATHFINDING": { diff --git a/src/styles.scss b/src/styles.scss index fdba66c..ff47d5c 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -262,13 +262,13 @@ a { } } -.grid-size { +.input-container { display: flex; gap: 0.75rem; align-items: center; flex-wrap: wrap; - .grid-field { + .input-field { width: 150px; } } @@ -301,6 +301,10 @@ canvas { &.path { background-color: gold; } &.empty { background-color: lightgray; } &.alive { background-color: black; } + &.L1 { background-color: yellow; } + &.L2 { background-color: magenta; } + &.M1 { background-color: red; } + &.M2 { background-color: green; } } } @@ -339,4 +343,4 @@ canvas { background-color: #4caf50; /* Green for sorted */ } } -} \ No newline at end of file +}