@footgun/cobalt 0.1.1 → 0.3.0

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.
@@ -1,99 +1,110 @@
1
- import { vec2 } from '../deps.js'
1
+ import cdt2d from 'cdt2d'
2
+ import poly2pslg from 'https://cdn.skypack.dev/poly-to-pslg'
3
+ //import cleanPSLG from 'https://cdn.skypack.dev/pin/clean-pslg@v1.1.2-Vmc159bOYXS2a4zKtz3Q/mode=imports,min/optimized/clean-pslg.js'
4
+ import { mat3, vec2 } from 'wgpu-matrix'
2
5
 
3
6
 
4
- function line (cobalt, node, start, end, color, lineWidth=1) {
5
-
6
- const delta = vec2.sub(end, start)
7
+ // works similarly to the HTML Canvas transforms:
8
+ // https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Transformations
9
+ export default {
10
+ line,
7
11
 
8
- const unitBasis = vec2.normalize(delta)
9
- const perp = perpendicularComponent(unitBasis)
12
+ save: function (cobalt, node) {
13
+ node.data.transforms.push(mat3.clone(node.data.transforms.at(-1)))
14
+ },
10
15
 
11
- const halfLineWidth = lineWidth / 2
12
-
13
- let i = node.data.vertexCount * 6 // 2 floats position + 4 floats color per vertex
16
+ restore: function (cobalt, node) {
17
+ if (node.data.transforms.length > 1) // don't remove the identity matrix
18
+ node.data.transforms.pop()
19
+ },
14
20
 
15
- // triangle 1
16
- // pt 1
17
- node.data.vertices[i + 0] = start[0] + perp[0] * halfLineWidth
18
- node.data.vertices[i + 1] = start[1] + perp[1] * halfLineWidth
21
+ translate: function (cobalt, node, translation) {
22
+ const m = node.data.transforms.at(-1)
23
+ mat3.translate(m, translation, m)
24
+ },
19
25
 
20
- // pt1 color
21
- node.data.vertices[i + 2] = color[0]
22
- node.data.vertices[i + 3] = color[1]
23
- node.data.vertices[i + 4] = color[2]
24
- node.data.vertices[i + 5] = color[3]
26
+ rotate: function (cobalt, node, radians) {
27
+ const m = node.data.transforms.at(-1)
28
+ mat3.rotate(m, radians, m)
29
+ },
25
30
 
26
- // pt 2
27
- node.data.vertices[i + 6] = start[0] - perp[0] * halfLineWidth
28
- node.data.vertices[i + 7] = start[1] - perp[1] * halfLineWidth
31
+ scale: function (cobalt, node, scale) {
32
+ const m = node.data.transforms.at(-1)
33
+ mat3.scale(m, scale, m)
34
+ },
29
35
 
30
- // pt2 color
31
- node.data.vertices[i + 8] = color[0]
32
- node.data.vertices[i + 9] = color[1]
33
- node.data.vertices[i + 10] = color[2]
34
- node.data.vertices[i + 11] = color[3]
36
+ strokePath: function (cobalt, node, segments, color, lineWidth=1) {
37
+ for (const s of segments)
38
+ line(cobalt, node, s[0], s[1], color, lineWidth)
39
+ },
35
40
 
36
- // pt 3
37
- node.data.vertices[i + 12] = end[0] + perp[0] * halfLineWidth
38
- node.data.vertices[i + 13] = end[1] + perp[1] * halfLineWidth
41
+ filledPath: function (cobalt, node, points, color) {
39
42
 
40
- // pt3 color
41
- node.data.vertices[i + 14] = color[0]
42
- node.data.vertices[i + 15] = color[1]
43
- node.data.vertices[i + 16] = color[2]
44
- node.data.vertices[i + 17] = color[3]
45
-
43
+ const edges = [ ]
46
44
 
47
- // triangle 2
48
- // pt 2
49
- node.data.vertices[i + 18] = start[0] - perp[0] * halfLineWidth
50
- node.data.vertices[i + 19] = start[1] - perp[1] * halfLineWidth
45
+ for (let i=1; i < points.length; i++)
46
+ edges.push([ i-1, i ])
51
47
 
52
- // pt2 color
53
- node.data.vertices[i + 20] = color[0]
54
- node.data.vertices[i + 21] = color[1]
55
- node.data.vertices[i + 22] = color[2]
56
- node.data.vertices[i + 23] = color[3]
57
-
58
- // pt 3
59
- node.data.vertices[i + 24] = end[0] + perp[0] * halfLineWidth
60
- node.data.vertices[i + 25] = end[1] + perp[1] * halfLineWidth
48
+ const pslg = poly2pslg(points)
49
+ const triangles = cdt2d(pslg.points, pslg.edges, { exterior: true })
61
50
 
62
- // pt3 color
63
- node.data.vertices[i + 26] = color[0]
64
- node.data.vertices[i + 27] = color[1]
65
- node.data.vertices[i + 28] = color[2]
66
- node.data.vertices[i + 29] = color[3]
51
+ // The flag {exterior: false} tells it to remove exterior faces
52
+ //const triangles = cdt2d(points, edges, { exterior: true })
67
53
 
68
- // pt 4
69
- node.data.vertices[i + 30] = end[0] - perp[0] * halfLineWidth
70
- node.data.vertices[i + 31] = end[1] - perp[1] * halfLineWidth
71
54
 
72
- // pt4 color
73
- node.data.vertices[i + 32] = color[0]
74
- node.data.vertices[i + 33] = color[1]
75
- node.data.vertices[i + 34] = color[2]
76
- node.data.vertices[i + 35] = color[3]
77
55
 
56
+ const m = node.data.transforms.at(-1)
78
57
 
79
- node.data.vertexCount += 6
58
+ let i = node.data.vertexCount * 6 // 2 floats position + 4 floats color per vertex
80
59
 
81
- node.data.dirty = true
82
- }
60
+ const pos = vec2.create()
83
61
 
62
+ for (const tri of triangles) {
84
63
 
85
- // return component of vector perpendicular to a unit basis vector
86
- // (IMPORTANT NOTE: assumes "basis" has unit magnitude (length==1))
87
- function perpendicularComponent (inp) {
88
- return [ -inp[1], inp[0] ]
89
- }
64
+ // pt 1
65
+ vec2.transformMat3(points[tri[0]], m, pos)
66
+ node.data.vertices[i + 0] = pos[0]
67
+ node.data.vertices[i + 1] = pos[1]
90
68
 
69
+ // pt1 color
70
+ node.data.vertices[i + 2] = color[0]
71
+ node.data.vertices[i + 3] = color[1]
72
+ node.data.vertices[i + 4] = color[2]
73
+ node.data.vertices[i + 5] = color[3]
74
+
75
+ // pt 2
76
+ vec2.transformMat3(points[tri[1]], m, pos)
77
+ node.data.vertices[i + 6] = pos[0]
78
+ node.data.vertices[i + 7] = pos[1]
79
+
80
+ // pt2 color
81
+ node.data.vertices[i + 8] = color[0]
82
+ node.data.vertices[i + 9] = color[1]
83
+ node.data.vertices[i + 10] = color[2]
84
+ node.data.vertices[i + 11] = color[3]
85
+
86
+ // pt 3
87
+ vec2.transformMat3(points[tri[2]], m, pos)
88
+ node.data.vertices[i + 12] = pos[0]
89
+ node.data.vertices[i + 13] = pos[1]
90
+
91
+ // pt3 color
92
+ node.data.vertices[i + 14] = color[0]
93
+ node.data.vertices[i + 15] = color[1]
94
+ node.data.vertices[i + 16] = color[2]
95
+ node.data.vertices[i + 17] = color[3]
96
+
97
+ i += 18
98
+ }
99
+
100
+ node.data.vertexCount += (3 * triangles.length)
101
+
102
+ node.data.dirty = true
103
+ },
91
104
 
92
- export default {
93
- line,
94
105
 
95
106
  ellipse: function (cobalt, node, center, halfWidth, halfHeight, numSegments, color, lineWidth=1) {
96
-
107
+
97
108
  const [ x, y ] = center
98
109
 
99
110
  // angle between each segment
@@ -122,6 +133,8 @@ export default {
122
133
  // angle between each segment
123
134
  const deltaAngle = 2 * Math.PI / numSegments
124
135
 
136
+ const m = node.data.transforms.at(-1)
137
+
125
138
  // Generate points for the ellipsoid
126
139
  for (let i = 0; i < numSegments; i++) {
127
140
  // Angle for this and the next segment
@@ -141,8 +154,9 @@ export default {
141
154
  const vi = (node.data.vertexCount * 6) + (i * stride)
142
155
 
143
156
  // position
144
- node.data.vertices[vi + 0] = x
145
- node.data.vertices[vi + 1] = y
157
+ const pos = vec2.transformMat3([ x, y ], m)
158
+ node.data.vertices[vi + 0] = pos[0]
159
+ node.data.vertices[vi + 1] = pos[1]
146
160
 
147
161
  // color
148
162
  node.data.vertices[vi + 2] = color[0]
@@ -154,8 +168,9 @@ export default {
154
168
  // Second triangle vertex (current point on ellipse)
155
169
 
156
170
  // position
157
- node.data.vertices[vi + 6] = currX
158
- node.data.vertices[vi + 7] = currY
171
+ vec2.transformMat3([ currX, currY ], m, pos)
172
+ node.data.vertices[vi + 6] = pos[0]
173
+ node.data.vertices[vi + 7] = pos[1]
159
174
 
160
175
  // color
161
176
  node.data.vertices[vi + 8] = color[0]
@@ -166,8 +181,9 @@ export default {
166
181
 
167
182
  // Third triangle vertex (next point on ellipse)
168
183
  // position
169
- node.data.vertices[vi + 12] = nextX
170
- node.data.vertices[vi + 13] = nextY
184
+ vec2.transformMat3([ nextX, nextY ], m, pos)
185
+ node.data.vertices[vi + 12] = pos[0]
186
+ node.data.vertices[vi + 13] = pos[1]
171
187
 
172
188
  // color
173
189
  node.data.vertices[vi + 14] = color[0]
@@ -181,8 +197,7 @@ export default {
181
197
  node.data.dirty = true
182
198
  },
183
199
 
184
- // @param Number angle rotation (radians)
185
- box: function (cobalt, node, center, width, height, color, angle=0, lineWidth=1) {
200
+ box: function (cobalt, node, center, width, height, color, lineWidth=1) {
186
201
  const [ x, y ] = center
187
202
 
188
203
  const halfWidth = width / 2
@@ -193,43 +208,25 @@ export default {
193
208
  const bottomLeft = [ x - halfWidth, y + halfHeight ]
194
209
  const bottomRight = [ x + halfWidth, y + halfHeight ]
195
210
 
196
- if (angle !== 0) {
197
- // rotate the point by <angle> rads around origin
198
- // point origin rads out
199
- _rotate(topLeft, center, angle, topLeft)
200
- _rotate(topRight, center, angle, topRight)
201
- _rotate(bottomLeft, center, angle, bottomLeft)
202
- _rotate(bottomRight, center, angle, bottomRight)
203
- }
204
-
205
211
  line(cobalt, node, topLeft, topRight, color, lineWidth)
206
212
  line(cobalt, node, bottomLeft, bottomRight, color, lineWidth)
207
213
  line(cobalt, node, topLeft, bottomLeft, color, lineWidth)
208
214
  line(cobalt, node, topRight, bottomRight, color, lineWidth)
209
215
  },
210
216
 
211
-
212
-
213
- // @param Number angle rotation (radians)
214
- filledBox: function (cobalt, node, center, width, height, color, angle=0) {
217
+ filledBox: function (cobalt, node, center, width, height, color) {
218
+
215
219
  const [ x, y ] = center
216
220
 
217
221
  const halfWidth = width / 2
218
222
  const halfHeight = height / 2
219
223
 
220
- const topLeft = [ x - halfWidth, y - halfHeight ];
221
- const topRight = [ x + halfWidth, y - halfHeight ];
222
- const bottomLeft = [ x - halfWidth, y + halfHeight ];
223
- const bottomRight = [ x + halfWidth, y + halfHeight ];
224
-
225
- if (angle !== 0) {
226
- // rotate the point by <angle> rads around origin
227
- // point origin rads out
228
- _rotate(topLeft, center, angle, topLeft)
229
- _rotate(topRight, center, angle, topRight)
230
- _rotate(bottomLeft, center, angle, bottomLeft)
231
- _rotate(bottomRight, center, angle, bottomRight)
232
- }
224
+ const m = node.data.transforms.at(-1)
225
+
226
+ const topLeft = vec2.transformMat3([ x - halfWidth, y - halfHeight ], m)
227
+ const topRight = vec2.transformMat3([ x + halfWidth, y - halfHeight ], m)
228
+ const bottomLeft = vec2.transformMat3([ x - halfWidth, y + halfHeight ], m)
229
+ const bottomRight = vec2.transformMat3([ x + halfWidth, y + halfHeight ], m)
233
230
 
234
231
  let i = node.data.vertexCount * 6 // 2 floats position + 4 floats color per vertex
235
232
 
@@ -305,21 +302,99 @@ export default {
305
302
 
306
303
  clear: function (cobalt, node) {
307
304
  node.data.vertexCount = 0
305
+ node.data.transforms.length = 1 // remove all transform matrices except the first one
306
+ mat3.identity(node.data.transforms[0])
308
307
  node.data.dirty = true
309
308
  },
310
309
  }
311
310
 
312
311
 
313
- function _rotate (a, b, rad, out) {
314
- //Translate point to the origin
315
- let p0 = a[0] - b[0],
316
- p1 = a[1] - b[1],
317
- sinC = Math.sin(rad),
318
- cosC = Math.cos(rad);
312
+ function line (cobalt, node, start, end, color, lineWidth=1) {
313
+
314
+ const m = node.data.transforms.at(-1)
315
+ start = vec2.transformMat3(start, m)
316
+ end = vec2.transformMat3(end, m)
317
+
318
+ const delta = vec2.sub(end, start)
319
+
320
+ const unitBasis = vec2.normalize(delta)
321
+ const perp = perpendicularComponent(unitBasis)
322
+
323
+ const halfLineWidth = lineWidth / 2
324
+
325
+ let i = node.data.vertexCount * 6 // 2 floats position + 4 floats color per vertex
326
+
327
+ // triangle 1
328
+ // pt 1
329
+ node.data.vertices[i + 0] = start[0] + perp[0] * halfLineWidth
330
+ node.data.vertices[i + 1] = start[1] + perp[1] * halfLineWidth
331
+
332
+ // pt1 color
333
+ node.data.vertices[i + 2] = color[0]
334
+ node.data.vertices[i + 3] = color[1]
335
+ node.data.vertices[i + 4] = color[2]
336
+ node.data.vertices[i + 5] = color[3]
337
+
338
+ // pt 2
339
+ node.data.vertices[i + 6] = start[0] - perp[0] * halfLineWidth
340
+ node.data.vertices[i + 7] = start[1] - perp[1] * halfLineWidth
319
341
 
320
- //perform rotation and translate to correct position
321
- out[0] = p0 * cosC - p1 * sinC + b[0];
322
- out[1] = p0 * sinC + p1 * cosC + b[1];
323
- return out;
342
+ // pt2 color
343
+ node.data.vertices[i + 8] = color[0]
344
+ node.data.vertices[i + 9] = color[1]
345
+ node.data.vertices[i + 10] = color[2]
346
+ node.data.vertices[i + 11] = color[3]
347
+
348
+ // pt 3
349
+ node.data.vertices[i + 12] = end[0] + perp[0] * halfLineWidth
350
+ node.data.vertices[i + 13] = end[1] + perp[1] * halfLineWidth
351
+
352
+ // pt3 color
353
+ node.data.vertices[i + 14] = color[0]
354
+ node.data.vertices[i + 15] = color[1]
355
+ node.data.vertices[i + 16] = color[2]
356
+ node.data.vertices[i + 17] = color[3]
357
+
358
+
359
+ // triangle 2
360
+ // pt 2
361
+ node.data.vertices[i + 18] = start[0] - perp[0] * halfLineWidth
362
+ node.data.vertices[i + 19] = start[1] - perp[1] * halfLineWidth
363
+
364
+ // pt2 color
365
+ node.data.vertices[i + 20] = color[0]
366
+ node.data.vertices[i + 21] = color[1]
367
+ node.data.vertices[i + 22] = color[2]
368
+ node.data.vertices[i + 23] = color[3]
369
+
370
+ // pt 3
371
+ node.data.vertices[i + 24] = end[0] + perp[0] * halfLineWidth
372
+ node.data.vertices[i + 25] = end[1] + perp[1] * halfLineWidth
373
+
374
+ // pt3 color
375
+ node.data.vertices[i + 26] = color[0]
376
+ node.data.vertices[i + 27] = color[1]
377
+ node.data.vertices[i + 28] = color[2]
378
+ node.data.vertices[i + 29] = color[3]
379
+
380
+ // pt 4
381
+ node.data.vertices[i + 30] = end[0] - perp[0] * halfLineWidth
382
+ node.data.vertices[i + 31] = end[1] - perp[1] * halfLineWidth
383
+
384
+ // pt4 color
385
+ node.data.vertices[i + 32] = color[0]
386
+ node.data.vertices[i + 33] = color[1]
387
+ node.data.vertices[i + 34] = color[2]
388
+ node.data.vertices[i + 35] = color[3]
389
+
390
+
391
+ node.data.vertexCount += 6
392
+ node.data.dirty = true
324
393
  }
325
394
 
395
+
396
+ // return component of vector perpendicular to a unit basis vector
397
+ // (IMPORTANT NOTE: assumes "basis" has unit magnitude (length==1))
398
+ function perpendicularComponent (inp) {
399
+ return [ -inp[1], inp[0] ]
400
+ }
@@ -3,7 +3,8 @@ import createTextureFromBuffer from '../create-texture-from-buffer.js'
3
3
  import createTextureFromUrl from '../create-texture-from-url.js'
4
4
  import readSpriteSheet from './read-spritesheet.js'
5
5
  import spriteWGSL from './sprite.wgsl'
6
- import { round, mat4, vec3 } from '../deps.js'
6
+ import round from 'round-half-up-symmetric'
7
+ import { mat4, vec3 } from 'wgpu-matrix'
7
8
 
8
9
 
9
10
  // shared spritesheet resource, used by each sprite render node
@@ -1,8 +0,0 @@
1
- export default function componentAnimation (obj) {
2
- return {
3
- name: obj.name || '',
4
- frame: obj.frame || 0,
5
- accumulator: obj.accumulator || 0,
6
- done: false,
7
- }
8
- }
@@ -1,13 +0,0 @@
1
- import { vec3 } from './deps.js'
2
-
3
-
4
- export default function componentTransform (obj) {
5
- return {
6
- position: obj.position || vec3.create(0, 0, 0),
7
- rotation: obj.rotation || 0,
8
-
9
- // if set, this means the position is relative to another transform
10
- // rather than being in world space
11
- relativeTo: obj.relativeTo,
12
- }
13
- }
@@ -1,47 +0,0 @@
1
- import * as Cobalt from '../../bundle.js'
2
- import animationComponent from './component-animation.js'
3
- import transformComponent from './component-transform.js'
4
- import { ECS, vec3, vec4 } from './deps.js'
5
-
6
-
7
- export default function spriteEntity (world, opts) {
8
- const ENTITY = ECS.createEntity(world)
9
-
10
- ECS.addComponentToEntity(world, ENTITY, 'transform', transformComponent({
11
- position: vec3.create(opts.position[0], opts.position[1], 0)
12
- }))
13
-
14
- ECS.addComponentToEntity(world, ENTITY, 'animation', animationComponent({
15
- name: opts.name
16
- }))
17
-
18
- const tint = vec4.create(0, 0, 0, 0)
19
-
20
- const opacity = opts.opacity ?? 255
21
-
22
- const spriteNode = opts.spriteNode
23
-
24
- const cobaltSpriteId = spriteNode.addSprite(opts.name,
25
- opts.position,
26
- vec3.create(1, 1, 1),
27
- tint,
28
- opacity / 255,
29
- opts.rotation || 0,
30
- opts.zIndex)
31
-
32
- ECS.addComponentToEntity(world, ENTITY, 'sprite', {
33
- name: opts.name,
34
-
35
- layer: opts.layer,
36
- rotation: 0, // radians
37
- scale: vec3.create(1, 1, 1),
38
- opacity: 1, // 0 is transparent, 1 is opaque
39
- tint: vec4.create(0, 0, 0, 0),
40
-
41
- // cobalt references
42
- cobaltSpriteId,
43
- spriteNode,
44
- })
45
-
46
- return ENTITY
47
- }
package/src/deps.js DELETED
@@ -1,3 +0,0 @@
1
- export { default as removeArrayItems } from 'https://cdn.jsdelivr.net/gh/mreinstein/remove-array-items/src/remove-array-items.js'
2
- export { default as round } from 'https://cdn.skypack.dev/pin/round-half-up-symmetric@v2.0.0-pfMZ4UGGs9FcqO8UiEHO/mode=imports,min/optimized/round-half-up-symmetric.js'
3
- export { mat4, vec2, vec3, vec4 } from 'https://wgpu-matrix.org/dist/3.x/wgpu-matrix.module.js'
File without changes