-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathapp.ts
More file actions
112 lines (96 loc) · 3.25 KB
/
app.ts
File metadata and controls
112 lines (96 loc) · 3.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import ObjLoader from "./ObjLoader";
import WebGPUCanvas from "./WebGPUCanvas";
import Camera from "./PerspectiveCamera";
import DefaultProgram from "./programs/DefaultProgram";
import Transformation from "./Transformation";
import Cloth from "./Cloth";
// For the simulation to work with collisions,
// it is wise to use equal spacing between all the particles.
// This is possible to do in Blender even if the cloth as a whole is a rectangle.
const OBJECT_URL: string = "cloth_20_30_l.obj";
const VERTEX_SPACING = 0.05;
(async () => {
try {
const objLoader = new ObjLoader();
const [objFile, gpuCanvas] = await Promise.all([
objLoader.load(OBJECT_URL),
WebGPUCanvas.init("canvas-container"),
]);
// Create mesh data
const mesh = objLoader.parse(objFile);
const modelTransformation = new Transformation();
modelTransformation.translation = [0,0,0];
modelTransformation.scale = [1, 1, 1];
modelTransformation.rotationXYZ = [0, 1, 0];
// Create Buffers and Bind Groups
const meshBuffers = gpuCanvas.createMeshBuffers(mesh);
// Initialize WebGPU program
const program = DefaultProgram.init(gpuCanvas);
program.registerModelMatrices(1);
// Initalize Scene objects
const lightModel = new Transformation();
lightModel.translation = [5.0, 0.0, 100.0];
lightModel.rotationXYZ = [0, 0, 0];
const perspectiveCamera = new Camera(
(2 * Math.PI) / 5,
gpuCanvas.aspectRatio,
0.01,
10000
);
perspectiveCamera.translation = [0, 0.0, 2.1];
// Create Physics Object
// thickness and spacing in hash table needed adjusting.
const thickness = VERTEX_SPACING;
const cloth = new Cloth(mesh, thickness);
// Initialize physics parameters
const dt = 1.0 / 60.0;
const steps = 10;
const sdt = dt / steps;
const gravity = new Float32Array([-1.1, -9.8, 2.5]);
cloth.registerDistanceConstraint(0.0);
cloth.registerPerformantBendingConstraint(1.0);
cloth.registerSelfCollision();
// cloth.registerIsometricBendingConstraint(10.0)
// Start animation loop
gpuCanvas.draw((renderPassAPI) => {
gravity[2] = Math.cos(Date.now() / 2000) * 15.5;
cloth.preIntegration(sdt);
for (let i = 0; i < steps; i++) {
cloth.preSolve(sdt, gravity);
cloth.solve(sdt);
cloth.postSolve(sdt);
}
cloth.updateVertexNormals();
gpuCanvas.device.queue.writeBuffer(
meshBuffers.position.data,
0,
cloth.positions,
0,
meshBuffers.position.length
);
gpuCanvas.device.queue.writeBuffer(
meshBuffers.normals.data,
0,
cloth.normals,
0,
meshBuffers.normals.length
);
program
.activate(renderPassAPI)
.updateCameraUniforms(perspectiveCamera)
.updateModelUniforms(
modelTransformation.modelMatrix,
modelTransformation.getNormalMatrix(perspectiveCamera.viewMatrix),
0
)
.updateLightModelPositionUniform(lightModel.position)
.render(renderPassAPI, meshBuffers);
});
} catch (e) {
const errorContainerEl = document.getElementById("error-text");
if (errorContainerEl) {
errorContainerEl.innerHTML = e as string;
}
throw e;
}
})();