simulationjsv2 0.2.3 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants.d.ts +4 -1
- package/dist/constants.js +4 -1
- package/dist/geometry.d.ts +103 -0
- package/dist/geometry.js +407 -0
- package/dist/graphics.d.ts +70 -54
- package/dist/graphics.js +290 -476
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/simulation.d.ts +8 -3
- package/dist/simulation.js +86 -97
- package/dist/types.d.ts +57 -2
- package/dist/utils.d.ts +15 -7
- package/dist/utils.js +103 -13
- package/package.json +1 -1
package/dist/graphics.js
CHANGED
|
@@ -1,30 +1,37 @@
|
|
|
1
|
-
import { vec3,
|
|
2
|
-
import { Vertex, VertexCache, cloneBuf, color, colorFromVector4,
|
|
1
|
+
import { vec3, mat4, vec2, vec4 } from 'wgpu-matrix';
|
|
2
|
+
import { Vertex, VertexCache, cloneBuf, color, colorFromVector4, vector3ToPixelRatio, vector2, vector3, vertex, Color, transitionValues, logger, vector2FromVector3, matrix4, rotateMat4, vector3FromVector2 } from './utils.js';
|
|
3
|
+
import { CircleGeometry, CubeGeometry, Line2dGeometry, Line3dGeometry, PlaneGeometry, PolygonGeometry, SplineGeometry, SquareGeometry } from './geometry.js';
|
|
3
4
|
export class SimulationElement {
|
|
4
|
-
pos;
|
|
5
5
|
color;
|
|
6
|
-
|
|
6
|
+
wireframe;
|
|
7
7
|
vertexCache;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
8
|
+
rotation;
|
|
9
|
+
is3d;
|
|
10
|
+
/**
|
|
11
|
+
* @param pos - Expected to be adjusted to devicePixelRatio before reaching constructor
|
|
12
|
+
*/
|
|
13
|
+
constructor(color = new Color(), rotation, is3d = true) {
|
|
15
14
|
this.color = color;
|
|
16
15
|
this.vertexCache = new VertexCache();
|
|
17
|
-
this.
|
|
16
|
+
this.is3d = is3d;
|
|
17
|
+
this.wireframe = false;
|
|
18
|
+
this.rotation = rotation;
|
|
18
19
|
}
|
|
19
|
-
|
|
20
|
-
this.
|
|
20
|
+
getGeometryType() {
|
|
21
|
+
return this.geometry.getType();
|
|
22
|
+
}
|
|
23
|
+
setWireframe(wireframe) {
|
|
24
|
+
this.wireframe = wireframe;
|
|
25
|
+
}
|
|
26
|
+
isWireframe() {
|
|
27
|
+
return this.wireframe;
|
|
28
|
+
}
|
|
29
|
+
getColor() {
|
|
30
|
+
return this.color;
|
|
21
31
|
}
|
|
22
32
|
getPos() {
|
|
23
33
|
return this.pos;
|
|
24
34
|
}
|
|
25
|
-
setCamera(camera) {
|
|
26
|
-
this.camera = camera;
|
|
27
|
-
}
|
|
28
35
|
fill(newColor, t = 0, f) {
|
|
29
36
|
const diff = newColor.diff(this.color);
|
|
30
37
|
const finalColor = newColor.clone();
|
|
@@ -39,16 +46,79 @@ export class SimulationElement {
|
|
|
39
46
|
this.vertexCache.updated();
|
|
40
47
|
}, t, f);
|
|
41
48
|
}
|
|
42
|
-
|
|
43
|
-
|
|
49
|
+
defaultUpdateMatrix(camera) {
|
|
50
|
+
const matrix = matrix4();
|
|
51
|
+
if (typeof this.rotation === 'number') {
|
|
52
|
+
const pos = vector3FromVector2(this.pos);
|
|
53
|
+
pos[1] = camera.getScreenSize()[1] - pos[1];
|
|
54
|
+
mat4.translate(matrix, pos, matrix);
|
|
55
|
+
mat4.rotateZ(matrix, this.rotation, matrix);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
mat4.translate(matrix, this.pos, matrix);
|
|
59
|
+
rotateMat4(matrix, this.rotation);
|
|
60
|
+
}
|
|
61
|
+
this.geometry.updateMatrix(matrix);
|
|
62
|
+
}
|
|
63
|
+
getBuffer(camera) {
|
|
64
|
+
if (this.vertexCache.shouldUpdate() || camera.hasUpdated()) {
|
|
65
|
+
this.updateMatrix(camera);
|
|
66
|
+
this.geometry.recompute();
|
|
67
|
+
let resBuffer = [];
|
|
68
|
+
if (this.isWireframe()) {
|
|
69
|
+
resBuffer = this.geometry.getWireframeBuffer(this.color);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
resBuffer = this.geometry.getTriangleBuffer(this.color);
|
|
73
|
+
}
|
|
74
|
+
this.vertexCache.setCache(resBuffer);
|
|
75
|
+
return resBuffer;
|
|
76
|
+
}
|
|
77
|
+
return this.vertexCache.getCache();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
export class SimulationElement3d extends SimulationElement {
|
|
81
|
+
pos;
|
|
82
|
+
rotation;
|
|
83
|
+
constructor(pos, rotation = vector3(), color) {
|
|
84
|
+
super(color, rotation);
|
|
85
|
+
this.pos = pos;
|
|
86
|
+
vector3ToPixelRatio(this.pos);
|
|
87
|
+
this.rotation = rotation;
|
|
88
|
+
}
|
|
89
|
+
rotate(amount, t = 0, f) {
|
|
90
|
+
const finalRotation = cloneBuf(this.rotation);
|
|
91
|
+
vec3.add(finalRotation, amount, finalRotation);
|
|
92
|
+
return transitionValues((p) => {
|
|
93
|
+
this.rotation[0] += amount[0] * p;
|
|
94
|
+
this.rotation[1] += amount[1] * p;
|
|
95
|
+
this.rotation[2] += amount[2] * p;
|
|
96
|
+
this.vertexCache.updated();
|
|
97
|
+
}, () => {
|
|
98
|
+
this.rotation = finalRotation;
|
|
99
|
+
this.vertexCache.updated();
|
|
100
|
+
}, t, f);
|
|
101
|
+
}
|
|
102
|
+
rotateTo(rot, t = 0, f) {
|
|
103
|
+
const diff = vector3();
|
|
104
|
+
vec3.sub(rot, this.rotation, diff);
|
|
105
|
+
return transitionValues((p) => {
|
|
106
|
+
this.rotation[0] += diff[0] * p;
|
|
107
|
+
this.rotation[1] += diff[1] * p;
|
|
108
|
+
this.rotation[2] += diff[2] * p;
|
|
109
|
+
this.vertexCache.updated();
|
|
110
|
+
}, () => {
|
|
111
|
+
this.rotation = rot;
|
|
112
|
+
this.vertexCache.updated();
|
|
113
|
+
}, t, f);
|
|
44
114
|
}
|
|
45
115
|
move(amount, t = 0, f) {
|
|
46
|
-
const finalPos =
|
|
47
|
-
vec3.add(finalPos,
|
|
116
|
+
const finalPos = cloneBuf(this.pos);
|
|
117
|
+
vec3.add(finalPos, amount, finalPos);
|
|
48
118
|
return transitionValues((p) => {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
119
|
+
this.pos[0] += amount[0] * p;
|
|
120
|
+
this.pos[1] += amount[1] * p;
|
|
121
|
+
this.pos[2] += amount[2] * p;
|
|
52
122
|
this.vertexCache.updated();
|
|
53
123
|
}, () => {
|
|
54
124
|
this.pos = finalPos;
|
|
@@ -56,110 +126,157 @@ export class SimulationElement {
|
|
|
56
126
|
}, t, f);
|
|
57
127
|
}
|
|
58
128
|
moveTo(pos, t = 0, f) {
|
|
59
|
-
const diff =
|
|
60
|
-
vec3.sub(
|
|
129
|
+
const diff = vector3();
|
|
130
|
+
vec3.sub(pos, this.pos, diff);
|
|
61
131
|
return transitionValues((p) => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
132
|
+
this.pos[0] += diff[0] * p;
|
|
133
|
+
this.pos[1] += diff[1] * p;
|
|
134
|
+
this.pos[2] += diff[2] * p;
|
|
65
135
|
this.vertexCache.updated();
|
|
66
136
|
}, () => {
|
|
67
|
-
|
|
68
|
-
this.pos[i] = pos[i];
|
|
69
|
-
}
|
|
137
|
+
this.pos = pos;
|
|
70
138
|
this.vertexCache.updated();
|
|
71
139
|
}, t, f);
|
|
72
140
|
}
|
|
73
141
|
}
|
|
74
|
-
export class
|
|
75
|
-
|
|
142
|
+
export class SimulationElement2d extends SimulationElement {
|
|
143
|
+
pos;
|
|
76
144
|
rotation;
|
|
77
|
-
constructor(pos,
|
|
78
|
-
super(
|
|
79
|
-
this.
|
|
145
|
+
constructor(pos, rotation = 0, color) {
|
|
146
|
+
super(color, rotation, false);
|
|
147
|
+
this.pos = pos;
|
|
80
148
|
this.rotation = rotation;
|
|
81
149
|
}
|
|
82
|
-
|
|
83
|
-
this.
|
|
150
|
+
rotate(rotation, t = 0, f) {
|
|
151
|
+
const finalRotation = this.rotation + rotation;
|
|
152
|
+
return transitionValues((p) => {
|
|
153
|
+
this.rotation += rotation * p;
|
|
154
|
+
this.vertexCache.updated();
|
|
155
|
+
}, () => {
|
|
156
|
+
this.rotation = finalRotation;
|
|
157
|
+
this.vertexCache.updated();
|
|
158
|
+
}, t, f);
|
|
84
159
|
}
|
|
85
|
-
|
|
86
|
-
const
|
|
160
|
+
rotateTo(newRotation, t = 0, f) {
|
|
161
|
+
const diff = newRotation - this.rotation;
|
|
87
162
|
return transitionValues((p) => {
|
|
88
|
-
|
|
89
|
-
vec3.scale(amount, p, step);
|
|
90
|
-
vec3.add(this.rotation, step, this.rotation);
|
|
163
|
+
this.rotation += diff * p;
|
|
91
164
|
this.vertexCache.updated();
|
|
92
165
|
}, () => {
|
|
93
|
-
|
|
94
|
-
this.rotation = initial;
|
|
166
|
+
this.rotation = newRotation;
|
|
95
167
|
this.vertexCache.updated();
|
|
96
168
|
}, t, f);
|
|
97
169
|
}
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
-
vec3.
|
|
170
|
+
move(amount, t = 0, f) {
|
|
171
|
+
const finalPos = vector2();
|
|
172
|
+
vec3.add(amount, this.pos, finalPos);
|
|
101
173
|
return transitionValues((p) => {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
vec3.add(this.rotation, toRotate, this.rotation);
|
|
174
|
+
this.pos[0] += amount[0] * p;
|
|
175
|
+
this.pos[1] += amount[1] * p;
|
|
105
176
|
this.vertexCache.updated();
|
|
106
177
|
}, () => {
|
|
107
|
-
this.
|
|
178
|
+
this.pos = finalPos;
|
|
108
179
|
this.vertexCache.updated();
|
|
109
180
|
}, t, f);
|
|
110
181
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
182
|
+
moveTo(pos, t = 0, f) {
|
|
183
|
+
const diff = vector2();
|
|
184
|
+
vec2.sub(pos, this.pos, diff);
|
|
185
|
+
return transitionValues((p) => {
|
|
186
|
+
this.pos[0] += diff[0] * p;
|
|
187
|
+
this.pos[1] += diff[1] * p;
|
|
188
|
+
this.vertexCache.updated();
|
|
189
|
+
}, () => {
|
|
190
|
+
this.pos = pos;
|
|
191
|
+
this.vertexCache.updated();
|
|
192
|
+
}, t, f);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
export class Plane extends SimulationElement3d {
|
|
196
|
+
geometry;
|
|
197
|
+
points;
|
|
198
|
+
constructor(pos, points, color, rotation = vector3()) {
|
|
199
|
+
super(pos, rotation, color);
|
|
200
|
+
this.rotation = rotation;
|
|
201
|
+
this.points = points;
|
|
202
|
+
this.geometry = new PlaneGeometry(points);
|
|
203
|
+
}
|
|
204
|
+
setPoints(newPoints) {
|
|
205
|
+
this.points = newPoints;
|
|
206
|
+
this.vertexCache.updated();
|
|
207
|
+
}
|
|
208
|
+
updateMatrix(camera) {
|
|
209
|
+
this.defaultUpdateMatrix(camera);
|
|
131
210
|
}
|
|
132
211
|
}
|
|
133
|
-
export class Square extends
|
|
212
|
+
export class Square extends SimulationElement2d {
|
|
213
|
+
geometry;
|
|
134
214
|
width;
|
|
135
215
|
height;
|
|
136
|
-
rotation;
|
|
137
216
|
vertexColors;
|
|
138
|
-
points;
|
|
139
217
|
/**
|
|
140
218
|
* @param vertexColors{Record<number, Color>} - 0 is top left vertex, numbers increase clockwise
|
|
141
219
|
*/
|
|
142
220
|
constructor(pos, width, height, color, rotation, vertexColors) {
|
|
143
|
-
super(pos, color);
|
|
221
|
+
super(pos, rotation, color);
|
|
144
222
|
this.width = width * devicePixelRatio;
|
|
145
223
|
this.height = height * devicePixelRatio;
|
|
146
|
-
this.
|
|
147
|
-
this.
|
|
148
|
-
this.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
224
|
+
this.vertexColors = this.cloneColorMap(vertexColors || {});
|
|
225
|
+
this.geometry = new SquareGeometry(this.width, this.height);
|
|
226
|
+
this.geometry.setVertexColorMap(this.vertexColors);
|
|
227
|
+
}
|
|
228
|
+
cloneColorMap(colorMap) {
|
|
229
|
+
const newColorMap = {};
|
|
230
|
+
Object.entries(colorMap).forEach(([key, value]) => {
|
|
231
|
+
newColorMap[+key] = value.clone();
|
|
232
|
+
});
|
|
233
|
+
return newColorMap;
|
|
234
|
+
}
|
|
235
|
+
setVertexColors(newColorMap, t = 0, f) {
|
|
236
|
+
const colorMap = this.cloneColorMap(newColorMap);
|
|
237
|
+
const diffMap = {};
|
|
238
|
+
Object.entries(colorMap).forEach(([key, value]) => {
|
|
239
|
+
if (!this.vertexColors[+key]) {
|
|
240
|
+
this.vertexColors[+key] = color();
|
|
241
|
+
}
|
|
242
|
+
diffMap[+key] = value.diff(this.vertexColors[+key] || color());
|
|
243
|
+
});
|
|
244
|
+
Object.entries(this.vertexColors).forEach(([key, value]) => {
|
|
245
|
+
if (!diffMap[+key]) {
|
|
246
|
+
const clone = value.clone();
|
|
247
|
+
clone.r *= -1;
|
|
248
|
+
clone.g *= -1;
|
|
249
|
+
clone.b *= -1;
|
|
250
|
+
diffMap[+key] = clone;
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
return transitionValues((p) => {
|
|
254
|
+
Object.entries(diffMap).forEach(([key, value]) => {
|
|
255
|
+
const color = this.vertexColors[+key];
|
|
256
|
+
color.r += value.r * p;
|
|
257
|
+
color.g += value.g * p;
|
|
258
|
+
color.b += value.b * p;
|
|
259
|
+
color.a += value.a * p;
|
|
260
|
+
this.vertexColors[+key] = color;
|
|
261
|
+
});
|
|
262
|
+
this.geometry.setVertexColorMap(this.vertexColors);
|
|
263
|
+
this.vertexCache.updated();
|
|
264
|
+
}, () => {
|
|
265
|
+
this.vertexColors = colorMap;
|
|
266
|
+
this.geometry.setVertexColorMap(this.vertexColors);
|
|
267
|
+
this.vertexCache.updated();
|
|
268
|
+
}, t, f);
|
|
154
269
|
}
|
|
155
270
|
scaleWidth(amount, t = 0, f) {
|
|
156
271
|
const finalWidth = this.width * amount;
|
|
157
272
|
const diffWidth = finalWidth - this.width;
|
|
158
273
|
return transitionValues((p) => {
|
|
159
274
|
this.width += diffWidth * p;
|
|
275
|
+
this.geometry.setWidth(this.width);
|
|
160
276
|
this.vertexCache.updated();
|
|
161
277
|
}, () => {
|
|
162
278
|
this.width = finalWidth;
|
|
279
|
+
this.geometry.setWidth(this.width);
|
|
163
280
|
this.vertexCache.updated();
|
|
164
281
|
}, t, f);
|
|
165
282
|
}
|
|
@@ -168,9 +285,11 @@ export class Square extends SimulationElement {
|
|
|
168
285
|
const diffHeight = finalHeight - this.height;
|
|
169
286
|
return transitionValues((p) => {
|
|
170
287
|
this.height += diffHeight * p;
|
|
288
|
+
this.geometry.setHeight(this.height);
|
|
171
289
|
this.vertexCache.updated();
|
|
172
290
|
}, () => {
|
|
173
291
|
this.height = finalHeight;
|
|
292
|
+
this.geometry.setHeight(this.height);
|
|
174
293
|
this.vertexCache.updated();
|
|
175
294
|
}, t, f);
|
|
176
295
|
}
|
|
@@ -182,10 +301,14 @@ export class Square extends SimulationElement {
|
|
|
182
301
|
return transitionValues((p) => {
|
|
183
302
|
this.width += diffWidth * p;
|
|
184
303
|
this.height += diffHeight * p;
|
|
304
|
+
this.geometry.setWidth(this.width);
|
|
305
|
+
this.geometry.setHeight(this.height);
|
|
185
306
|
this.vertexCache.updated();
|
|
186
307
|
}, () => {
|
|
187
308
|
this.width = finalWidth;
|
|
188
309
|
this.height = finalHeight;
|
|
310
|
+
this.geometry.setWidth(this.width);
|
|
311
|
+
this.geometry.setHeight(this.height);
|
|
189
312
|
this.vertexCache.updated();
|
|
190
313
|
}, t, f);
|
|
191
314
|
}
|
|
@@ -194,9 +317,11 @@ export class Square extends SimulationElement {
|
|
|
194
317
|
const diffWidth = num - this.width;
|
|
195
318
|
return transitionValues((p) => {
|
|
196
319
|
this.width += diffWidth * p;
|
|
320
|
+
this.geometry.setWidth(this.width);
|
|
197
321
|
this.vertexCache.updated();
|
|
198
322
|
}, () => {
|
|
199
323
|
this.width = num;
|
|
324
|
+
this.geometry.setWidth(this.width);
|
|
200
325
|
this.vertexCache.updated();
|
|
201
326
|
}, t, f);
|
|
202
327
|
}
|
|
@@ -205,75 +330,45 @@ export class Square extends SimulationElement {
|
|
|
205
330
|
const diffHeight = num - this.height;
|
|
206
331
|
return transitionValues((p) => {
|
|
207
332
|
this.height += diffHeight * p;
|
|
333
|
+
this.geometry.setHeight(this.height);
|
|
208
334
|
this.vertexCache.updated();
|
|
209
335
|
}, () => {
|
|
210
336
|
this.height = num;
|
|
337
|
+
this.geometry.setHeight(this.height);
|
|
211
338
|
this.vertexCache.updated();
|
|
212
339
|
}, t, f);
|
|
213
340
|
}
|
|
214
|
-
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
}
|
|
224
|
-
setRotation(newRotation, t = 0, f) {
|
|
225
|
-
const diff = newRotation - this.rotation;
|
|
226
|
-
return transitionValues((p) => {
|
|
227
|
-
this.rotation += diff * p;
|
|
228
|
-
this.vertexCache.updated();
|
|
229
|
-
}, () => {
|
|
230
|
-
this.rotation = newRotation;
|
|
231
|
-
this.vertexCache.updated();
|
|
232
|
-
}, t, f);
|
|
233
|
-
}
|
|
234
|
-
getBuffer(camera, force) {
|
|
235
|
-
if (this.vertexCache.shouldUpdate() || force) {
|
|
236
|
-
let resBuffer = [];
|
|
237
|
-
const vertexOrder = [0, 1, 2, 0, 2, 3];
|
|
238
|
-
const rotationMat = mat4.identity();
|
|
239
|
-
mat4.rotateZ(rotationMat, this.rotation, rotationMat);
|
|
240
|
-
const points = this.points.map((vec) => {
|
|
241
|
-
const pos = vector2();
|
|
242
|
-
vec2.add(vec, pos, pos);
|
|
243
|
-
vec2.transformMat4(vec, rotationMat, pos);
|
|
244
|
-
vec2.add(vec, this.getPos(), pos);
|
|
245
|
-
pos[1] = camera.getScreenSize()[1] - pos[1];
|
|
246
|
-
pos[0] += this.width / 2;
|
|
247
|
-
pos[1] -= this.height / 2;
|
|
248
|
-
return pos;
|
|
249
|
-
});
|
|
250
|
-
vertexOrder.forEach((vertex) => {
|
|
251
|
-
let vertexColor = this.vertexColors[vertex];
|
|
252
|
-
vertexColor = vertexColor ? vertexColor : this.getColor();
|
|
253
|
-
resBuffer = resBuffer.concat(vertexBuffer2d(points[vertex][0], points[vertex][1], vertexColor));
|
|
254
|
-
});
|
|
255
|
-
this.vertexCache.setCache(resBuffer);
|
|
256
|
-
return resBuffer;
|
|
257
|
-
}
|
|
258
|
-
return this.vertexCache.getCache();
|
|
341
|
+
updateMatrix(camera) {
|
|
342
|
+
const pos = cloneBuf(this.pos);
|
|
343
|
+
pos[1] = camera.getScreenSize()[1] - pos[1];
|
|
344
|
+
pos[0] += this.width / 2;
|
|
345
|
+
pos[1] -= this.height / 2;
|
|
346
|
+
const matrix = matrix4();
|
|
347
|
+
mat4.translate(matrix, vector3FromVector2(pos), matrix);
|
|
348
|
+
mat4.rotateZ(matrix, this.rotation, matrix);
|
|
349
|
+
this.geometry.updateMatrix(matrix);
|
|
259
350
|
}
|
|
260
351
|
}
|
|
261
|
-
export class Circle extends
|
|
352
|
+
export class Circle extends SimulationElement2d {
|
|
353
|
+
geometry;
|
|
262
354
|
radius;
|
|
263
|
-
detail
|
|
355
|
+
detail;
|
|
264
356
|
constructor(pos, radius, color, detail = 50) {
|
|
265
|
-
super(pos, color);
|
|
266
|
-
this.radius = radius
|
|
357
|
+
super(pos, 0, color);
|
|
358
|
+
this.radius = radius;
|
|
267
359
|
this.detail = detail;
|
|
360
|
+
this.geometry = new CircleGeometry(this.radius, this.detail);
|
|
268
361
|
}
|
|
269
362
|
setRadius(num, t = 0, f) {
|
|
270
363
|
num *= devicePixelRatio;
|
|
271
364
|
const diff = num - this.radius;
|
|
272
365
|
return transitionValues((p) => {
|
|
273
366
|
this.radius += diff * p;
|
|
367
|
+
this.geometry.setRadius(this.radius);
|
|
274
368
|
this.vertexCache.updated();
|
|
275
369
|
}, () => {
|
|
276
370
|
this.radius = num;
|
|
371
|
+
this.geometry.setRadius(this.radius);
|
|
277
372
|
this.vertexCache.updated();
|
|
278
373
|
}, t, f);
|
|
279
374
|
}
|
|
@@ -282,64 +377,26 @@ export class Circle extends SimulationElement {
|
|
|
282
377
|
const diff = finalRadius - this.radius;
|
|
283
378
|
return transitionValues((p) => {
|
|
284
379
|
this.radius += diff * p;
|
|
380
|
+
this.geometry.setRadius(this.radius);
|
|
285
381
|
this.vertexCache.updated();
|
|
286
382
|
}, () => {
|
|
287
383
|
this.radius = finalRadius;
|
|
384
|
+
this.geometry.setRadius(this.radius);
|
|
288
385
|
this.vertexCache.updated();
|
|
289
386
|
}, t, f);
|
|
290
387
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
const points = [];
|
|
294
|
-
const rotationInc = (Math.PI * 2) / this.detail;
|
|
295
|
-
for (let i = 0; i < this.detail; i++) {
|
|
296
|
-
const mat = mat4.identity();
|
|
297
|
-
mat4.rotateZ(mat, rotationInc * i, mat);
|
|
298
|
-
const vec = vector3(this.radius);
|
|
299
|
-
vec3.transformMat4(vec, mat, vec);
|
|
300
|
-
vec3.add(vec, this.getPos(), vec);
|
|
301
|
-
const screenSize = camera.getScreenSize();
|
|
302
|
-
points.push(new Vertex(vec[0], screenSize[1] - vec[1], vec[2], this.getColor(), false));
|
|
303
|
-
}
|
|
304
|
-
const vertices = lossyTriangulate(points).reduce((acc, curr) => {
|
|
305
|
-
curr.forEach((vertex) => acc.push(...vertex.toBuffer(this.getColor())));
|
|
306
|
-
return acc;
|
|
307
|
-
}, []);
|
|
308
|
-
this.vertexCache.setCache(vertices);
|
|
309
|
-
return vertices;
|
|
310
|
-
}
|
|
311
|
-
return this.vertexCache.getCache();
|
|
388
|
+
updateMatrix(camera) {
|
|
389
|
+
this.defaultUpdateMatrix(camera);
|
|
312
390
|
}
|
|
313
391
|
}
|
|
314
|
-
|
|
392
|
+
// TODO: litterally this whole thing
|
|
393
|
+
export class Polygon extends SimulationElement2d {
|
|
394
|
+
geometry;
|
|
315
395
|
vertices;
|
|
316
|
-
rotation
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
this.
|
|
320
|
-
const newVertex = vertex.clone();
|
|
321
|
-
newVertex.setZ(0);
|
|
322
|
-
newVertex.setIs3d(false);
|
|
323
|
-
return vertex;
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
rotate(amount, t = 0, f) {
|
|
327
|
-
const finalRotation = this.rotation + amount;
|
|
328
|
-
return transitionValues((p) => {
|
|
329
|
-
this.rotation += amount * p;
|
|
330
|
-
this.vertexCache.updated();
|
|
331
|
-
}, () => {
|
|
332
|
-
this.rotation = finalRotation;
|
|
333
|
-
}, t, f);
|
|
334
|
-
}
|
|
335
|
-
rotateTo(num, t = 0, f) {
|
|
336
|
-
const diff = num - this.rotation;
|
|
337
|
-
return transitionValues((p) => {
|
|
338
|
-
this.rotation += diff * p;
|
|
339
|
-
this.vertexCache.updated();
|
|
340
|
-
}, () => {
|
|
341
|
-
this.rotation = num;
|
|
342
|
-
}, t, f);
|
|
396
|
+
constructor(pos, points, color, rotation) {
|
|
397
|
+
super(pos, rotation, color);
|
|
398
|
+
this.vertices = points;
|
|
399
|
+
this.geometry = new PolygonGeometry(this.vertices);
|
|
343
400
|
}
|
|
344
401
|
getVertices() {
|
|
345
402
|
return this.vertices;
|
|
@@ -355,7 +412,7 @@ export class Polygon extends SimulationElement {
|
|
|
355
412
|
if (vertices.length > this.vertices.length) {
|
|
356
413
|
while (vertices.length > this.vertices.length) {
|
|
357
414
|
const lastPos = lastVert.getPos();
|
|
358
|
-
this.vertices.push(new Vertex(lastPos[0], lastPos[1], 0, lastVert.getColor() || this.
|
|
415
|
+
this.vertices.push(new Vertex(lastPos[0], lastPos[1], 0, lastVert.getColor() || this.color, false));
|
|
359
416
|
}
|
|
360
417
|
}
|
|
361
418
|
const initialPositions = this.vertices.map((p) => cloneBuf(p.getPos()));
|
|
@@ -373,16 +430,16 @@ export class Polygon extends SimulationElement {
|
|
|
373
430
|
})
|
|
374
431
|
: [])
|
|
375
432
|
];
|
|
376
|
-
const initialColors = this.vertices.map((vert) => (vert.getColor() || this.
|
|
433
|
+
const initialColors = this.vertices.map((vert) => (vert.getColor() || this.color).toVec4());
|
|
377
434
|
const colorChanges = [
|
|
378
435
|
...vertices.map((vert, i) => {
|
|
379
|
-
const diff = (vert.getColor() || this.
|
|
436
|
+
const diff = (vert.getColor() || this.color).diff(this.vertices[i].getColor() || this.color);
|
|
380
437
|
return diff.toVec4();
|
|
381
438
|
}),
|
|
382
439
|
...(this.vertices.length > vertices.length
|
|
383
440
|
? this.vertices.slice(vertices.length, this.vertices.length).map((vert) => {
|
|
384
441
|
const toColor = vertices[vertices.length - 1].getColor();
|
|
385
|
-
return (toColor || this.
|
|
442
|
+
return (toColor || this.color).diff(vert.getColor() || this.color).toVec4();
|
|
386
443
|
})
|
|
387
444
|
: [])
|
|
388
445
|
];
|
|
@@ -393,7 +450,7 @@ export class Polygon extends SimulationElement {
|
|
|
393
450
|
vec3.scale(posChange, p, posChange);
|
|
394
451
|
vec3.add(vert.getPos(), posChange, posChange);
|
|
395
452
|
vec4.scale(colorChange, p, colorChange);
|
|
396
|
-
vec4.add((vert.getColor() || this.
|
|
453
|
+
vec4.add((vert.getColor() || this.color).toVec4(), colorChange, colorChange);
|
|
397
454
|
vert.setPos(posChange);
|
|
398
455
|
vert.setColor(colorFromVector4(colorChange));
|
|
399
456
|
});
|
|
@@ -411,38 +468,21 @@ export class Polygon extends SimulationElement {
|
|
|
411
468
|
this.vertexCache.updated();
|
|
412
469
|
}, t, f);
|
|
413
470
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
let resBuffer = [];
|
|
417
|
-
const rotationMat = mat4.identity();
|
|
418
|
-
mat4.rotateZ(rotationMat, this.rotation, rotationMat);
|
|
419
|
-
lossyTriangulate(this.vertices)
|
|
420
|
-
.flat()
|
|
421
|
-
.forEach((vert) => {
|
|
422
|
-
const pos = vector3();
|
|
423
|
-
vec3.add(vert.getPos(), pos, pos);
|
|
424
|
-
vec3.transformMat4(pos, rotationMat, pos);
|
|
425
|
-
vec3.add(this.getPos(), pos, pos);
|
|
426
|
-
pos[1] = camera.getScreenSize()[1] - pos[1];
|
|
427
|
-
resBuffer = resBuffer.concat(vertexBuffer2d(pos[0], pos[1], vert.getColor() || this.getColor()));
|
|
428
|
-
});
|
|
429
|
-
this.vertexCache.setCache(resBuffer);
|
|
430
|
-
return resBuffer;
|
|
431
|
-
}
|
|
432
|
-
return this.vertexCache.getCache();
|
|
471
|
+
updateMatrix(camera) {
|
|
472
|
+
this.defaultUpdateMatrix(camera);
|
|
433
473
|
}
|
|
434
474
|
}
|
|
435
|
-
export class Line3d extends
|
|
475
|
+
export class Line3d extends SimulationElement3d {
|
|
476
|
+
geometry;
|
|
436
477
|
to;
|
|
437
|
-
toColor;
|
|
438
478
|
thickness;
|
|
439
479
|
constructor(pos, to, thickness) {
|
|
440
|
-
super(pos.getPos(), to.getColor() || undefined);
|
|
480
|
+
super(pos.getPos(), vector3(), to.getColor() || undefined);
|
|
441
481
|
this.thickness = thickness;
|
|
442
|
-
this.toColor = to.getColor() || this.getColor();
|
|
443
482
|
this.to = to.getPos();
|
|
444
483
|
vec3.scale(this.to, devicePixelRatio, this.to);
|
|
445
|
-
vec3.sub(this.to, this.
|
|
484
|
+
vec3.sub(this.to, this.pos, this.to);
|
|
485
|
+
this.geometry = new Line3dGeometry(this.pos, this.to, this.thickness);
|
|
446
486
|
}
|
|
447
487
|
setStart(pos, t = 0, f) {
|
|
448
488
|
return this.moveTo(pos, t, f);
|
|
@@ -462,56 +502,24 @@ export class Line3d extends SimulationElement {
|
|
|
462
502
|
this.vertexCache.updated();
|
|
463
503
|
}, t, f);
|
|
464
504
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
const normal = vector2(-this.to[1], this.to[0]);
|
|
468
|
-
vec2.normalize(normal, normal);
|
|
469
|
-
vec2.scale(normal, this.thickness / 2, normal);
|
|
470
|
-
const pos = this.getPos();
|
|
471
|
-
const resBuffer = [
|
|
472
|
-
...vertexBuffer3d(pos[0] + normal[0], pos[1] + normal[1], pos[2], this.getColor()),
|
|
473
|
-
...vertexBuffer3d(pos[0] - normal[0], pos[1] - normal[1], pos[2], this.getColor()),
|
|
474
|
-
...vertexBuffer3d(pos[0] + this.to[0] + normal[0], pos[1] + this.to[1] + normal[1], pos[2] + this.to[2], this.toColor || this.getColor()),
|
|
475
|
-
...vertexBuffer3d(pos[0] - normal[0], pos[1] - normal[1], pos[2], this.getColor()),
|
|
476
|
-
...vertexBuffer3d(pos[0] + this.to[0] + normal[0], pos[1] + this.to[1] + normal[1], pos[2] + this.to[2], this.toColor || this.getColor()),
|
|
477
|
-
...vertexBuffer3d(pos[0] + this.to[0] - normal[0], pos[1] + this.to[1] - normal[1], pos[2] + this.to[2], this.toColor || this.getColor())
|
|
478
|
-
];
|
|
479
|
-
this.vertexCache.setCache(resBuffer);
|
|
480
|
-
return resBuffer;
|
|
481
|
-
}
|
|
482
|
-
return this.vertexCache.getCache();
|
|
505
|
+
updateMatrix(camera) {
|
|
506
|
+
return this.defaultUpdateMatrix(camera);
|
|
483
507
|
}
|
|
484
508
|
}
|
|
485
|
-
export class Line2d extends
|
|
509
|
+
export class Line2d extends SimulationElement2d {
|
|
510
|
+
geometry;
|
|
486
511
|
to;
|
|
487
|
-
toColor;
|
|
488
512
|
thickness;
|
|
489
513
|
constructor(from, to, thickness = 1) {
|
|
490
|
-
super(from.getPos(), from.getColor() || undefined);
|
|
514
|
+
super(vector2FromVector3(from.getPos()), 0, from.getColor() || undefined);
|
|
491
515
|
this.thickness = thickness * devicePixelRatio;
|
|
492
|
-
this.toColor = to.getColor();
|
|
493
516
|
this.to = vector2FromVector3(to.getPos());
|
|
494
517
|
vec2.scale(this.to, devicePixelRatio, this.to);
|
|
495
|
-
vec2.sub(this.to, this.
|
|
496
|
-
|
|
497
|
-
setEndColor(newColor, t = 0, f) {
|
|
498
|
-
if (!this.toColor)
|
|
499
|
-
this.toColor = this.getColor();
|
|
500
|
-
const diff = newColor.diff(this.toColor);
|
|
501
|
-
const finalColor = newColor.clone();
|
|
502
|
-
return transitionValues((p) => {
|
|
503
|
-
this.toColor.r += diff.r * p;
|
|
504
|
-
this.toColor.g += diff.g * p;
|
|
505
|
-
this.toColor.b += diff.b * p;
|
|
506
|
-
this.toColor.a += diff.a * p;
|
|
507
|
-
this.vertexCache.updated();
|
|
508
|
-
}, () => {
|
|
509
|
-
this.toColor = finalColor;
|
|
510
|
-
this.vertexCache.updated();
|
|
511
|
-
}, t, f);
|
|
518
|
+
vec2.sub(this.to, this.pos, this.to);
|
|
519
|
+
this.geometry = new Line2dGeometry(this.pos, this.to, this.thickness);
|
|
512
520
|
}
|
|
513
521
|
setStart(pos, t = 0, f) {
|
|
514
|
-
return this.moveTo(
|
|
522
|
+
return this.moveTo(pos, t, f);
|
|
515
523
|
}
|
|
516
524
|
setEnd(pos, t = 0, f) {
|
|
517
525
|
const diff = vector3();
|
|
@@ -526,136 +534,33 @@ export class Line2d extends SimulationElement {
|
|
|
526
534
|
this.vertexCache.updated();
|
|
527
535
|
}, t, f);
|
|
528
536
|
}
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
const normal = vector2(-this.to[1], this.to[0]);
|
|
532
|
-
vec2.normalize(normal, normal);
|
|
533
|
-
vec2.scale(normal, this.thickness / 2, normal);
|
|
534
|
-
const screenSize = camera.getScreenSize();
|
|
535
|
-
const pos = this.getPos();
|
|
536
|
-
const resBuffer = [
|
|
537
|
-
...vertexBuffer2d(pos[0] + normal[0], screenSize[1] - pos[1] + normal[1], this.getColor()),
|
|
538
|
-
...vertexBuffer2d(pos[0] - normal[0], screenSize[1] - pos[1] - normal[1], this.getColor()),
|
|
539
|
-
...vertexBuffer2d(pos[0] + this.to[0] + normal[0], screenSize[1] - pos[1] + this.to[1] + normal[1], this.toColor || this.getColor()),
|
|
540
|
-
...vertexBuffer2d(pos[0] - normal[0], screenSize[1] - pos[1] - normal[1], this.getColor()),
|
|
541
|
-
...vertexBuffer2d(pos[0] + this.to[0] + normal[0], screenSize[1] - pos[1] + this.to[1] + normal[1], this.toColor || this.getColor()),
|
|
542
|
-
...vertexBuffer2d(pos[0] + this.to[0] - normal[0], screenSize[1] - pos[1] + this.to[1] - normal[1], this.toColor || this.getColor())
|
|
543
|
-
];
|
|
544
|
-
this.vertexCache.setCache(resBuffer);
|
|
545
|
-
return resBuffer;
|
|
546
|
-
}
|
|
547
|
-
return this.vertexCache.getCache();
|
|
537
|
+
updateMatrix(camera) {
|
|
538
|
+
return this.defaultUpdateMatrix(camera);
|
|
548
539
|
}
|
|
549
540
|
}
|
|
550
|
-
export class Cube extends
|
|
551
|
-
|
|
552
|
-
rotation;
|
|
541
|
+
export class Cube extends SimulationElement3d {
|
|
542
|
+
geometry;
|
|
553
543
|
width;
|
|
554
544
|
height;
|
|
555
545
|
depth;
|
|
556
|
-
wireframe;
|
|
557
|
-
wireframeLines;
|
|
558
|
-
static wireframeOrder = [
|
|
559
|
-
[0, 1],
|
|
560
|
-
[1, 2],
|
|
561
|
-
[2, 3],
|
|
562
|
-
[3, 0],
|
|
563
|
-
[4, 5],
|
|
564
|
-
[5, 6],
|
|
565
|
-
[6, 7],
|
|
566
|
-
[7, 4],
|
|
567
|
-
[0, 4],
|
|
568
|
-
[3, 7],
|
|
569
|
-
[1, 5],
|
|
570
|
-
[2, 6]
|
|
571
|
-
];
|
|
572
546
|
constructor(pos, width, height, depth, color, rotation) {
|
|
573
|
-
super(pos, color);
|
|
547
|
+
super(pos, rotation, color);
|
|
574
548
|
this.width = width * devicePixelRatio;
|
|
575
549
|
this.height = height * devicePixelRatio;
|
|
576
550
|
this.depth = depth * devicePixelRatio;
|
|
577
551
|
this.rotation = rotation || vector3();
|
|
578
|
-
this.
|
|
579
|
-
this.wireframeLines = [];
|
|
580
|
-
const numWireframeLines = 12;
|
|
581
|
-
const lineThickness = 0.025;
|
|
582
|
-
for (let i = 0; i < numWireframeLines; i++) {
|
|
583
|
-
this.wireframeLines.push(new Line3d(vertex(), vertex(), lineThickness));
|
|
584
|
-
}
|
|
585
|
-
this.vertices = [];
|
|
586
|
-
this.computeVertices();
|
|
587
|
-
this.shiftWireframeLines();
|
|
588
|
-
}
|
|
589
|
-
computeVertices() {
|
|
590
|
-
console.log(this.width, this.height);
|
|
591
|
-
this.vertices = [
|
|
592
|
-
// front face
|
|
593
|
-
vector3(-this.width / 2, -this.height / 2, this.depth / 2),
|
|
594
|
-
vector3(this.width / 2, -this.height / 2, this.depth / 2),
|
|
595
|
-
vector3(this.width / 2, this.height / 2, this.depth / 2),
|
|
596
|
-
vector3(-this.width / 2, this.height / 2, this.depth / 2),
|
|
597
|
-
// back face
|
|
598
|
-
vector3(-this.width / 2, -this.height / 2, -this.depth / 2),
|
|
599
|
-
vector3(this.width / 2, -this.height / 2, -this.depth / 2),
|
|
600
|
-
vector3(this.width / 2, this.height / 2, -this.depth / 2),
|
|
601
|
-
vector3(-this.width / 2, this.height / 2, -this.depth / 2)
|
|
602
|
-
];
|
|
603
|
-
}
|
|
604
|
-
shiftWireframeLines() {
|
|
605
|
-
let rotMatrix = mat4.identity();
|
|
606
|
-
mat4.rotateZ(rotMatrix, this.rotation[2], rotMatrix);
|
|
607
|
-
mat4.rotateY(rotMatrix, this.rotation[1], rotMatrix);
|
|
608
|
-
mat4.rotateX(rotMatrix, this.rotation[0], rotMatrix);
|
|
609
|
-
const pos = this.getPos();
|
|
610
|
-
Cube.wireframeOrder.forEach((lineVertices, index) => {
|
|
611
|
-
const line = this.wireframeLines[index];
|
|
612
|
-
const start = cloneBuf(this.vertices[lineVertices[0]]);
|
|
613
|
-
const endPoint = cloneBuf(this.vertices[lineVertices[1]]);
|
|
614
|
-
vec3.sub(endPoint, start, endPoint);
|
|
615
|
-
vec3.transformMat4(endPoint, rotMatrix, endPoint);
|
|
616
|
-
vec3.transformMat4(start, rotMatrix, start);
|
|
617
|
-
vec3.add(start, pos, start);
|
|
618
|
-
line.setStart(start);
|
|
619
|
-
line.setEnd(endPoint);
|
|
620
|
-
});
|
|
621
|
-
}
|
|
622
|
-
setWireframe(wireframe) {
|
|
623
|
-
this.wireframe = wireframe;
|
|
624
|
-
}
|
|
625
|
-
rotate(amount, t = 0, f) {
|
|
626
|
-
const finalRotation = cloneBuf(this.rotation);
|
|
627
|
-
vec3.add(finalRotation, amount, finalRotation);
|
|
628
|
-
return transitionValues((p) => {
|
|
629
|
-
this.rotation[0] += amount[0] * p;
|
|
630
|
-
this.rotation[1] += amount[1] * p;
|
|
631
|
-
this.rotation[2] += amount[2] * p;
|
|
632
|
-
this.vertexCache.updated();
|
|
633
|
-
}, () => {
|
|
634
|
-
this.rotation = finalRotation;
|
|
635
|
-
this.vertexCache.updated();
|
|
636
|
-
}, t, f);
|
|
637
|
-
}
|
|
638
|
-
setRotation(rot, t = 0, f) {
|
|
639
|
-
const diff = vector3();
|
|
640
|
-
vec3.sub(rot, this.rotation, diff);
|
|
641
|
-
return transitionValues((p) => {
|
|
642
|
-
this.rotation[0] += diff[0] * p;
|
|
643
|
-
this.rotation[1] += diff[1] * p;
|
|
644
|
-
this.rotation[2] += diff[2] * p;
|
|
645
|
-
this.vertexCache.updated();
|
|
646
|
-
}, () => {
|
|
647
|
-
this.rotation = rot;
|
|
648
|
-
this.vertexCache.updated();
|
|
649
|
-
}, t, f);
|
|
552
|
+
this.geometry = new CubeGeometry(this.width, this.height, this.depth);
|
|
650
553
|
}
|
|
651
554
|
setWidth(width, t = 0, f) {
|
|
652
555
|
width *= devicePixelRatio;
|
|
653
556
|
const diff = width - this.width;
|
|
654
557
|
return transitionValues((p) => {
|
|
655
558
|
this.width += diff * p;
|
|
559
|
+
this.geometry.setWidth(this.width);
|
|
656
560
|
this.vertexCache.updated();
|
|
657
561
|
}, () => {
|
|
658
562
|
this.width = width;
|
|
563
|
+
this.geometry.setWidth(this.width);
|
|
659
564
|
this.vertexCache.updated();
|
|
660
565
|
}, t, f);
|
|
661
566
|
}
|
|
@@ -664,9 +569,11 @@ export class Cube extends SimulationElement {
|
|
|
664
569
|
const diff = height - this.width;
|
|
665
570
|
return transitionValues((p) => {
|
|
666
571
|
this.height += diff * p;
|
|
572
|
+
this.geometry.setHeight(this.height);
|
|
667
573
|
this.vertexCache.updated();
|
|
668
574
|
}, () => {
|
|
669
575
|
this.height = height;
|
|
576
|
+
this.geometry.setHeight(this.height);
|
|
670
577
|
this.vertexCache.updated();
|
|
671
578
|
}, t, f);
|
|
672
579
|
}
|
|
@@ -675,9 +582,11 @@ export class Cube extends SimulationElement {
|
|
|
675
582
|
const diff = depth - this.width;
|
|
676
583
|
return transitionValues((p) => {
|
|
677
584
|
this.depth += diff * p;
|
|
585
|
+
this.geometry.setDepth(this.depth);
|
|
678
586
|
this.vertexCache.updated();
|
|
679
587
|
}, () => {
|
|
680
588
|
this.depth = depth;
|
|
589
|
+
this.geometry.setDepth(this.depth);
|
|
681
590
|
this.vertexCache.updated();
|
|
682
591
|
}, t, f);
|
|
683
592
|
}
|
|
@@ -692,46 +601,22 @@ export class Cube extends SimulationElement {
|
|
|
692
601
|
this.width += widthDiff * p;
|
|
693
602
|
this.height += heightDiff * p;
|
|
694
603
|
this.depth += depthDiff * p;
|
|
604
|
+
this.geometry.setWidth(this.width);
|
|
605
|
+
this.geometry.setHeight(this.height);
|
|
606
|
+
this.geometry.setDepth(this.depth);
|
|
695
607
|
this.vertexCache.updated();
|
|
696
608
|
}, () => {
|
|
697
609
|
this.width = finalWidth;
|
|
698
610
|
this.height = finalHeight;
|
|
699
611
|
this.depth = finalDepth;
|
|
612
|
+
this.geometry.setWidth(this.width);
|
|
613
|
+
this.geometry.setHeight(this.height);
|
|
614
|
+
this.geometry.setDepth(this.depth);
|
|
700
615
|
this.vertexCache.updated();
|
|
701
616
|
}, t, f);
|
|
702
617
|
}
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
this.computeVertices();
|
|
706
|
-
this.shiftWireframeLines();
|
|
707
|
-
const triangleOrder = [
|
|
708
|
-
0, 1, 2, 0, 2, 3,
|
|
709
|
-
4, 5, 6, 4, 6, 7,
|
|
710
|
-
0, 3, 7, 0, 7, 4,
|
|
711
|
-
0, 4, 5, 0, 5, 1,
|
|
712
|
-
1, 2, 6, 1, 5, 6,
|
|
713
|
-
2, 3, 7, 2, 6, 7
|
|
714
|
-
];
|
|
715
|
-
let rotMatrix = mat4.identity();
|
|
716
|
-
mat4.rotateZ(rotMatrix, this.rotation[2], rotMatrix);
|
|
717
|
-
mat4.rotateY(rotMatrix, this.rotation[1], rotMatrix);
|
|
718
|
-
mat4.rotateX(rotMatrix, this.rotation[0], rotMatrix);
|
|
719
|
-
const pos = this.getPos();
|
|
720
|
-
let resBuffer = [];
|
|
721
|
-
triangleOrder.forEach((index) => {
|
|
722
|
-
const vertex = cloneBuf(this.vertices[index]);
|
|
723
|
-
vec3.transformMat4(vertex, rotMatrix, vertex);
|
|
724
|
-
resBuffer = resBuffer.concat(vertexBuffer3d(vertex[0] + pos[0], vertex[1] + pos[1], vertex[2] + pos[2], this.getColor()));
|
|
725
|
-
});
|
|
726
|
-
if (this.wireframe) {
|
|
727
|
-
this.wireframeLines.forEach((line) => {
|
|
728
|
-
resBuffer = resBuffer.concat(line.getBuffer(camera, force));
|
|
729
|
-
});
|
|
730
|
-
}
|
|
731
|
-
this.vertexCache.setCache(resBuffer);
|
|
732
|
-
return resBuffer;
|
|
733
|
-
}
|
|
734
|
-
return this.vertexCache.getCache();
|
|
618
|
+
updateMatrix(camera) {
|
|
619
|
+
this.defaultUpdateMatrix(camera);
|
|
735
620
|
}
|
|
736
621
|
}
|
|
737
622
|
export class BezierCurve2d {
|
|
@@ -859,45 +744,31 @@ export class SplinePoint2d {
|
|
|
859
744
|
];
|
|
860
745
|
}
|
|
861
746
|
}
|
|
862
|
-
export class Spline2d extends
|
|
747
|
+
export class Spline2d extends SimulationElement2d {
|
|
748
|
+
geometry;
|
|
863
749
|
curves;
|
|
864
750
|
thickness;
|
|
865
751
|
detail;
|
|
866
752
|
interpolateStart;
|
|
867
753
|
interpolateLimit;
|
|
868
|
-
distance;
|
|
869
754
|
constructor(pos, points, thickness = devicePixelRatio, detail = 40) {
|
|
870
|
-
super(pos.getPos(), pos.getColor() || undefined);
|
|
755
|
+
super(vector2FromVector3(pos.getPos()), 0, pos.getColor() || undefined);
|
|
871
756
|
this.curves = [];
|
|
872
757
|
this.thickness = thickness * devicePixelRatio;
|
|
873
758
|
this.detail = detail;
|
|
874
759
|
this.interpolateStart = 0;
|
|
875
760
|
this.interpolateLimit = 1;
|
|
876
|
-
this.
|
|
877
|
-
for (let i = 0; i < points.length; i++) {
|
|
878
|
-
let prevControl = null;
|
|
879
|
-
let prevColor = null;
|
|
880
|
-
if (i > 0) {
|
|
881
|
-
prevControl = cloneBuf(points[i - 1].getRawControls()[1]);
|
|
882
|
-
vec2.negate(prevControl, prevControl);
|
|
883
|
-
const prevColors = points[i - 1].getColors();
|
|
884
|
-
if (prevColors.at(-1)) {
|
|
885
|
-
prevColor = prevColors.at(-1) || null;
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
const bezierPoints = points[i].getVectorArray(i > 0 ? vector2FromVector3(points[i - 1].getEnd().getPos()) : null, prevControl);
|
|
889
|
-
const curve = new CubicBezierCurve2d(bezierPoints, points[i].getDetail(), points[i].getColors(prevColor));
|
|
890
|
-
this.distance += curve.getLength();
|
|
891
|
-
this.curves.push(curve);
|
|
892
|
-
}
|
|
761
|
+
this.geometry = new SplineGeometry(points, this.getColor(), this.thickness, this.detail);
|
|
893
762
|
}
|
|
894
763
|
setInterpolateStart(start, t = 0, f) {
|
|
895
764
|
const diff = start - this.interpolateStart;
|
|
896
765
|
return transitionValues((p) => {
|
|
897
766
|
this.interpolateStart += diff * p;
|
|
767
|
+
this.geometry.updateInterpolationStart(this.interpolateStart);
|
|
898
768
|
this.vertexCache.updated();
|
|
899
769
|
}, () => {
|
|
900
770
|
this.interpolateStart = start;
|
|
771
|
+
this.geometry.updateInterpolationStart(this.interpolateStart);
|
|
901
772
|
this.vertexCache.updated();
|
|
902
773
|
}, t, f);
|
|
903
774
|
}
|
|
@@ -905,9 +776,11 @@ export class Spline2d extends SimulationElement {
|
|
|
905
776
|
const diff = limit - this.interpolateLimit;
|
|
906
777
|
return transitionValues((p) => {
|
|
907
778
|
this.interpolateLimit += diff * p;
|
|
779
|
+
this.geometry.updateInterpolationLimit(this.interpolateLimit);
|
|
908
780
|
this.vertexCache.updated();
|
|
909
781
|
}, () => {
|
|
910
782
|
this.interpolateLimit = limit;
|
|
783
|
+
this.geometry.updateInterpolationLimit(this.interpolateLimit);
|
|
911
784
|
this.vertexCache.updated();
|
|
912
785
|
}, t, f);
|
|
913
786
|
}
|
|
@@ -923,66 +796,7 @@ export class Spline2d extends SimulationElement {
|
|
|
923
796
|
const [vec] = this.interpolateSlope(t);
|
|
924
797
|
return vec;
|
|
925
798
|
}
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
const screenSize = camera.getScreenSize();
|
|
929
|
-
let verticesTop = [];
|
|
930
|
-
const verticesBottom = [];
|
|
931
|
-
let currentDistance = 0;
|
|
932
|
-
let interpolationStarted = false;
|
|
933
|
-
outer: for (let i = 0; i < this.curves.length; i++) {
|
|
934
|
-
const detail = this.curves[i].getDetail() || this.detail;
|
|
935
|
-
const step = 1 / detail;
|
|
936
|
-
const distanceRatio = currentDistance / this.distance;
|
|
937
|
-
if (distanceRatio > this.interpolateLimit)
|
|
938
|
-
break;
|
|
939
|
-
const curveLength = this.curves[i].getLength();
|
|
940
|
-
currentDistance += curveLength;
|
|
941
|
-
const sectionRatio = curveLength / this.distance;
|
|
942
|
-
for (let j = 0; j < detail + 1; j++) {
|
|
943
|
-
let currentInterpolation = step * j;
|
|
944
|
-
let atLimit = false;
|
|
945
|
-
if (step * j * sectionRatio + distanceRatio > this.interpolateLimit) {
|
|
946
|
-
atLimit = true;
|
|
947
|
-
currentInterpolation = (this.interpolateLimit - distanceRatio) / sectionRatio;
|
|
948
|
-
}
|
|
949
|
-
if (distanceRatio + currentInterpolation / this.curves.length < this.interpolateStart) {
|
|
950
|
-
continue;
|
|
951
|
-
}
|
|
952
|
-
if (!interpolationStarted) {
|
|
953
|
-
interpolationStarted = true;
|
|
954
|
-
currentInterpolation = (this.interpolateStart - distanceRatio) / sectionRatio;
|
|
955
|
-
j--;
|
|
956
|
-
}
|
|
957
|
-
const [point, slope] = this.curves[i].interpolateSlope(currentInterpolation);
|
|
958
|
-
const pos = this.getPos();
|
|
959
|
-
point[0] += pos[0];
|
|
960
|
-
point[1] += screenSize[1] - pos[1];
|
|
961
|
-
const normal = vector2(-slope[1], slope[0]);
|
|
962
|
-
vec2.normalize(normal, normal);
|
|
963
|
-
vec2.scale(normal, this.thickness / 2, normal);
|
|
964
|
-
const colors = this.curves[i].getColors().map((c) => (c ? c : this.getColor()));
|
|
965
|
-
const vertexColor = interpolateColors(colors, currentInterpolation);
|
|
966
|
-
const vertTop = vertex(point[0] + normal[0], point[1] + normal[1], 0, vertexColor);
|
|
967
|
-
verticesTop.push(vertTop);
|
|
968
|
-
const vertBottom = vertex(point[0] - normal[0], point[1] - normal[1], 0, vertexColor);
|
|
969
|
-
verticesBottom.unshift(vertBottom);
|
|
970
|
-
if (atLimit) {
|
|
971
|
-
break outer;
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
verticesTop = verticesTop.concat(verticesBottom);
|
|
976
|
-
let resBuffer = [];
|
|
977
|
-
lossyTriangulate(verticesTop)
|
|
978
|
-
.flat()
|
|
979
|
-
.forEach((vert) => {
|
|
980
|
-
const pos = vert.getPos();
|
|
981
|
-
resBuffer = resBuffer.concat(vertexBuffer2d(pos[0], pos[1], vert.getColor() || this.getColor()));
|
|
982
|
-
});
|
|
983
|
-
this.vertexCache.setCache(resBuffer);
|
|
984
|
-
return resBuffer;
|
|
985
|
-
}
|
|
986
|
-
return this.vertexCache.getCache();
|
|
799
|
+
updateMatrix(camera) {
|
|
800
|
+
this.defaultUpdateMatrix(camera);
|
|
987
801
|
}
|
|
988
802
|
}
|