diff --git a/src/app/pages/algorithms/cloth/cloth.component.html b/src/app/pages/algorithms/cloth/cloth.component.html
index ccbe516..5bc709e 100644
--- a/src/app/pages/algorithms/cloth/cloth.component.html
+++ b/src/app/pages/algorithms/cloth/cloth.component.html
@@ -12,6 +12,15 @@
+
+
+
+
+
+
+
{
+ // Type 1.0 = horizontal/diagonal (no elongation), Type 2.0 = vertical (elongation applies)
+ const addHorizontalConstraint = (arr: number[], a: number, b: number): void => {
arr.push(a, b, config.spacing, 1.0);
};
+ const addVerticalConstraint = (arr: number[], a: number, b: number): void => {
+ arr.push(a, b, config.spacing, 2.0);
+ };
// Fill positions (Pin top row)
for (let y = 0; y < config.gridHeight; y++) {
@@ -186,14 +202,14 @@ export class ClothComponent {
// Graph Coloring (4 Phases)
for (let y = 0; y < config.gridHeight; y++) {
- for (let x = 0; x < config.gridWidth - 1; x += 2) addConstraint(constraintsP0, y * config.gridWidth + x, y * config.gridWidth + x + 1);
- for (let x = 1; x < config.gridWidth - 1; x += 2) addConstraint(constraintsP1, y * config.gridWidth + x, y * config.gridWidth + x + 1);
+ for (let x = 0; x < config.gridWidth - 1; x += 2) addHorizontalConstraint(constraintsP0, y * config.gridWidth + x, y * config.gridWidth + x + 1);
+ for (let x = 1; x < config.gridWidth - 1; x += 2) addHorizontalConstraint(constraintsP1, y * config.gridWidth + x, y * config.gridWidth + x + 1);
}
for (let y = 0; y < config.gridHeight - 1; y += 2) {
- for (let x = 0; x < config.gridWidth; x++) addConstraint(constraintsP2, y * config.gridWidth + x, (y + 1) * config.gridWidth + x);
+ for (let x = 0; x < config.gridWidth; x++) addVerticalConstraint(constraintsP2, y * config.gridWidth + x, (y + 1) * config.gridWidth + x);
}
for (let y = 1; y < config.gridHeight - 1; y += 2) {
- for (let x = 0; x < config.gridWidth; x++) addConstraint(constraintsP3, y * config.gridWidth + x, (y + 1) * config.gridWidth + x);
+ for (let x = 0; x < config.gridWidth; x++) addVerticalConstraint(constraintsP3, y * config.gridWidth + x, (y + 1) * config.gridWidth + x);
}
const constraintsP4: number[] = [];
@@ -228,7 +244,7 @@ export class ClothComponent {
constraintsP0, constraintsP1, constraintsP2, constraintsP3,
constraintsP4, constraintsP5, constraintsP6, constraintsP7
],
- params: new Float32Array(8)
+ params: new Float32Array(9)
};
}
@@ -331,7 +347,7 @@ export class ClothComponent {
// 6. RENDER LOOP
// ========================================================================
private startRenderLoop(engine: WebGPUEngine, scene: Scene, config: ClothConfig, buffers: ClothBuffers, pipelines: ClothPipelines): void {
- const paramsData = new Float32Array(8);
+ const paramsData = new Float32Array(9);
// Pre-calculate constraint dispatch sizes for the 4 phases
const constraintsLength = buffers.constraints.map(b => (b as any)._buffer.capacity / 4 / 4); // Elements / vec4 length
@@ -347,16 +363,23 @@ export class ClothComponent {
const windX = this.isWindActive ? 5.0 : 0.0;
const windY = 0.0;
const windZ = this.isWindActive ? 15.0 : 0.0;
- const scaledCompliance = 0.00001 * config.particleInvMass * config.spacing;
+
+ // Logarithmic compliance: stiffness=1 → very soft fabric, stiffness=100 → rigid metal sheet.
+ // alpha = compliance / dt² must be >> wSum (≈800) to be soft, << wSum to be rigid.
+ const softCompliance = 10.0;
+ const rigidCompliance = 0.00001;
+ const t = (this.stiffness - 1) / 99.0;
+ const compliance = softCompliance * Math.pow(rigidCompliance / softCompliance, t);
paramsData[0] = 0.016; // dt
paramsData[1] = -9.81; // gravity
- paramsData[2] = scaledCompliance;
+ paramsData[2] = compliance;
paramsData[3] = config.numVertices;
paramsData[4] = windX;
paramsData[5] = windY;
paramsData[6] = windZ;
paramsData[7] = this.simulationTime;
+ paramsData[8] = this.elongation;
buffers.params.update(paramsData);
diff --git a/src/app/pages/algorithms/cloth/cloth.shader.ts b/src/app/pages/algorithms/cloth/cloth.shader.ts
index 94652d7..33cbe35 100644
--- a/src/app/pages/algorithms/cloth/cloth.shader.ts
+++ b/src/app/pages/algorithms/cloth/cloth.shader.ts
@@ -13,7 +13,8 @@ export const CLOTH_SHARED_STRUCTS = `
wind_x: f32,
wind_y: f32,
wind_z: f32,
- time: f32
+ time: f32,
+ elongation: f32
};
`;
@@ -26,9 +27,8 @@ export const CLOTH_VERTEX_SHADER_WGSL = `
uniform viewProjection : mat4x4;
- // Varyings, um Daten an den Fragment-Shader zu senden
varying vUV : vec2;
- varying vWorldPos : vec3; // NEU: Wir brauchen die 3D-Position für das Licht!
+ varying vWorldPos : vec3;
@vertex
fn main(input : VertexInputs) -> FragmentInputs {
@@ -38,7 +38,7 @@ export const CLOTH_VERTEX_SHADER_WGSL = `
output.position = uniforms.viewProjection * vec4(worldPos, 1.0);
output.vUV = input.uv;
- output.vWorldPos = worldPos; // Position weitergeben
+ output.vWorldPos = worldPos;
return output;
}
@@ -133,13 +133,15 @@ export const CLOTH_SOLVE_COMPUTE_WGSL = CLOTH_SHARED_STRUCTS + `
if (idx >= arrayLength(&constraints)) { return; }
let constraint = constraints[idx];
- let isActive = constraint.w;
- if (isActive < 0.5) { return; }
+ // constraint.w: 0.0 = inactive, 1.0 = horizontal/diagonal, 2.0 = vertical
+ if (constraint.w < 0.5) { return; }
let idA = u32(constraint.x);
let idB = u32(constraint.y);
- let restLength = constraint.z;
+
+ // constraint.w encodes type: 1.0 = horizontal/diagonal, 2.0 = vertical (elongation applies)
+ let restLength =constraint.z * p.elongation;
var pA = positions[idA];
var pB = positions[idB];