-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdataScript.js
More file actions
136 lines (102 loc) · 3.12 KB
/
Copy pathdataScript.js
File metadata and controls
136 lines (102 loc) · 3.12 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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
const MAX_PARTICLES = 10000
const MAX_EDGES = 20000
const posX = new Float32Array(MAX_PARTICLES)
const posY = new Float32Array(MAX_PARTICLES)
const prevX = new Float32Array(MAX_PARTICLES)
const prevY = new Float32Array(MAX_PARTICLES)
const edgeSet = new Set()
const edgeA = new Uint16Array(MAX_EDGES)
const edgeB = new Uint16Array(MAX_EDGES)
const restLength = new Float32Array(MAX_EDGES)
const pinned = new Uint8Array(MAX_PARTICLES)
let pointCount = 0
let edgeCount = 0
const EPSILON = 1e-4
function RESET() {
pointCount = 0
edgeCount = 0
edgeSet.clear()
}
function EDGE_KEY(a, b) {
if (a > b) [a, b] = [b, a];
return a * (MAX_PARTICLES * 2) + b;
}
function ADD_POINT(x, y, hooked = false) {
if (pointCount >= MAX_PARTICLES) return -1
const i = pointCount
posX[i] = x
posY[i] = y
prevX[i] = x
prevY[i] = y
pinned[i] = hooked ? 1 : 0
pointCount++
return i
}
function NORMALIZE_EDGE(a, b) {
return a < b ? [a, b] : [b, a];
}
function EDGE_KEY(a, b) {
const [normA, normB] = NORMALIZE_EDGE(a, b);
return normA * (MAX_PARTICLES * 2) + normB;
}
function SET_EDGE(i, a, b) {
const [normA, normB] = NORMALIZE_EDGE(a, b);
const key = EDGE_KEY(normA, normB);
// Remove old edge from set if one existed!!!!
if (i < edgeCount) {
const [oldA, oldB] = NORMALIZE_EDGE(edgeA[i], edgeB[i]);
edgeSet.delete(EDGE_KEY(oldA, oldB));
}
edgeA[i] = normA;
edgeB[i] = normB;
restLength[i] = Math.hypot(posX[normA] - posX[normB], posY[normA] - posY[normB]);
edgeSet.add(key);
}
function ADD_EDGE(a, b) {
if (
edgeCount >= MAX_EDGES ||
a === b ||
a < 0 || b < 0 ||
a >= pointCount || b >= pointCount
) return -1;
const key = EDGE_KEY(a, b);
if (edgeSet.has(key)) return -1;
const i = edgeCount++;
SET_EDGE(i, a, b);
return i;
}
function SPLIT_EDGE(i) {
if (edgeCount >= MAX_EDGES - 1) return -1;
const a = edgeA[i];
const b = edgeB[i];
const originalRestLength = restLength[i];
const mx = 0.5 * (posX[a] + posX[b]);
const my = 0.5 * (posY[a] + posY[b]);
// Create two separate points at the midpoint for the dangling
const m1 = ADD_POINT(mx, my);
if (m1 === -1) return -1;
const m2 = ADD_POINT(mx, my);
if (m2 === -1) return -1;
// Set their previous positions for proper velocity,
prevX[m1] = 0.5 * (prevX[a] + prevX[b]);
prevY[m1] = 0.5 * (prevY[a] + prevY[b]);
prevX[m2] = 0.5 * (prevX[a] + prevX[b]);
prevY[m2] = 0.5 * (prevY[a] + prevY[b]);
// Split rest length by HALF
const halfRestLength = originalRestLength * 0.5;
// Replace original edge (a, b) with (a, m1)
const [normA, normM1] = NORMALIZE_EDGE(a, m1);
edgeA[i] = normA;
edgeB[i] = normM1;
restLength[i] = halfRestLength;
edgeSet.delete(EDGE_KEY(a, b));
edgeSet.add(EDGE_KEY(normA, normM1));
// Create new edge (m2, b)
const j = edgeCount++;
const [normM2, normB] = NORMALIZE_EDGE(m2, b);
edgeA[j] = normM2;
edgeB[j] = normB;
restLength[j] = halfRestLength;
edgeSet.add(EDGE_KEY(normM2, normB));
return m1;
}