@perplexdotgg/bounce 1.0.1 → 1.0.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@perplexdotgg/bounce",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "license": "MIT",
5
5
  "description": "Bounce",
6
6
  "main": "./build/bounce.js",
@@ -1,71 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { Body, BodyPairNode, BodyPairsModule } from "../src/index";
3
-
4
- describe("BodyPairsModule", () => {
5
- it("should add body pairs", () => {
6
- const bodies = [];
7
- for (let i = 0; i < 5; i++) {
8
- const body = Body.create({
9
- position: { x: i, y: 0, z: 0 },
10
- orientation: { x: 0, y: 0, z: 0 },
11
- });
12
- bodies.push(body);
13
- }
14
- const pairs = new BodyPairsModule();
15
- pairs.createPair(bodies[0], bodies[1]); // AB
16
- pairs.createPair(bodies[1], bodies[2]); // BC
17
- pairs.createPair(bodies[0], bodies[2]); // AC
18
- pairs.createPair(bodies[3], bodies[4]); // DE
19
- pairs.createPair(bodies[0], bodies[3]); // AD
20
- pairs.createPair(bodies[4], bodies[0]); // AE
21
- pairs.destroyPair(bodies[0], bodies[3]); // AD
22
- const collectedPairs: BodyPairNode[] = [];
23
- collectedPairs.length = 0;
24
- for (const pair of pairs.iteratePairsOfOne(bodies[0])) {
25
- collectedPairs.push(pair);
26
- }
27
- collectedPairs.reverse();
28
- expect(collectedPairs.length).toBe(3);
29
- expect(collectedPairs[0].bodyA! === bodies[0]).toBe(true);
30
- expect(collectedPairs[0].bodyB! === bodies[1]).toBe(true);
31
- expect(collectedPairs[1].bodyA! === bodies[0]).toBe(true);
32
- expect(collectedPairs[1].bodyB! === bodies[2]).toBe(true);
33
- expect(collectedPairs[2].bodyA! === bodies[4]).toBe(true);
34
- expect(collectedPairs[2].bodyB! === bodies[0]).toBe(true);
35
- collectedPairs.length = 0;
36
- for (const pair of pairs.iteratePairsOfOne(bodies[1])) {
37
- collectedPairs.push(pair);
38
- }
39
- collectedPairs.reverse();
40
- expect(collectedPairs.length).toBe(2);
41
- expect(collectedPairs[0].bodyA! === bodies[0]).toBe(true);
42
- expect(collectedPairs[0].bodyB! === bodies[1]).toBe(true);
43
- expect(collectedPairs[1].bodyA! === bodies[1]).toBe(true);
44
- expect(collectedPairs[1].bodyB! === bodies[2]).toBe(true);
45
- collectedPairs.length = 0;
46
- for (const pair of pairs.iteratePairs()) {
47
- collectedPairs.push(pair);
48
- }
49
- expect(collectedPairs.length).toBe(5);
50
- expect(collectedPairs[0].bodyA! === bodies[0]).toBe(true);
51
- expect(collectedPairs[0].bodyB! === bodies[1]).toBe(true);
52
- expect(collectedPairs[1].bodyA! === bodies[1]).toBe(true);
53
- expect(collectedPairs[1].bodyB! === bodies[2]).toBe(true);
54
- expect(collectedPairs[2].bodyA! === bodies[0]).toBe(true);
55
- expect(collectedPairs[2].bodyB! === bodies[2]).toBe(true);
56
- expect(collectedPairs[3].bodyA! === bodies[3]).toBe(true);
57
- expect(collectedPairs[3].bodyB! === bodies[4]).toBe(true);
58
- expect(collectedPairs[4].bodyA! === bodies[4]).toBe(true);
59
- expect(collectedPairs[4].bodyB! === bodies[0]).toBe(true);
60
- pairs.destroyAllPairsOfOne(bodies[0]);
61
- collectedPairs.length = 0;
62
- for (const pair of pairs.iteratePairs()) {
63
- collectedPairs.push(pair);
64
- }
65
- expect(collectedPairs.length).toBe(2);
66
- expect(collectedPairs[0].bodyA! === bodies[1]);
67
- expect(collectedPairs[0].bodyB! === bodies[2]);
68
- expect(collectedPairs[1].bodyA! === bodies[3]);
69
- expect(collectedPairs[1].bodyB! === bodies[4]);
70
- });
71
- });
@@ -1,406 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { World, BvhTree, Aabb, Body } from "../src/index";
3
-
4
- interface Vec3Like {
5
- x: number;
6
- y: number;
7
- z: number;
8
- }
9
-
10
- function createTestBody(world: World, x: number, y: number, z: number, radius = 0.5) {
11
- const shape = world.createSphere({ radius });
12
- return world.createDynamicBody({
13
- shape,
14
- position: { x, y, z },
15
- orientation: { x: 0, y: 0, z: 0 },
16
- });
17
- }
18
-
19
- function createTestBodyWithExtents(world: World, min: Vec3Like, max: Vec3Like) {
20
- const shape = world.createSphere({ radius: 1.0 });
21
- const body = world.createDynamicBody({
22
- shape,
23
- position: { x: 0, y: 0, z: 0 },
24
- orientation: { x: 0, y: 0, z: 0 },
25
- });
26
- body.computedBounds.setExtents(min, max);
27
- return body;
28
- }
29
-
30
- function destroyTestBody(world: World, body: Body) {
31
- world.destroyBody(body);
32
- }
33
-
34
- function createSeededRng(seed: number) {
35
- let state = seed >>> 0;
36
- return () => {
37
- state = (1664525 * state + 1013904223) >>> 0;
38
- return state / 0x100000000;
39
- };
40
- }
41
-
42
- describe("BvhTree", () => {
43
- it("inserts and intersects one object", () => {
44
- const world = new World();
45
- const tree = new BvhTree({ maxDepth: 4, maxObjectsPerLeaf: 2, expansionMargin: 0 });
46
-
47
- const body = createTestBody(world, 0, 0, 0);
48
- tree.insert(body);
49
-
50
- const query = Aabb.create();
51
- query.setExtents({ x: -1, y: -1, z: -1 }, { x: 1, y: 1, z: 1 });
52
-
53
- let hitCount = 0;
54
- tree.intersectAabb(() => {
55
- hitCount++;
56
- return false;
57
- }, query);
58
-
59
- expect(hitCount).toBe(1);
60
- });
61
-
62
- it("removes objects correctly", () => {
63
- const world = new World();
64
- const tree = new BvhTree({ maxDepth: 4, maxObjectsPerLeaf: 2, expansionMargin: 0 });
65
-
66
- const body = createTestBody(world, 0, 0, 0);
67
- tree.insert(body);
68
- tree.remove(body);
69
-
70
- const query = Aabb.create();
71
- query.setExtents({ x: -1, y: -1, z: -1 }, { x: 1, y: 1, z: 1 });
72
-
73
- let hitCount = 0;
74
- tree.intersectAabb(() => {
75
- hitCount++;
76
- return false;
77
- }, query);
78
-
79
- expect(hitCount).toBe(0);
80
- });
81
-
82
- it("updates objects correctly", () => {
83
- const world = new World();
84
- const tree = new BvhTree({ maxDepth: 4, maxObjectsPerLeaf: 2, expansionMargin: 0 });
85
-
86
- const body = createTestBody(world, 0, 0, 0);
87
- tree.insert(body);
88
-
89
- body.computedBounds.setExtents({ x: 10, y: 10, z: 10 }, { x: 11, y: 11, z: 11 });
90
- tree.update(body);
91
-
92
- const nearQuery = Aabb.create();
93
- nearQuery.setExtents({ x: -1, y: -1, z: -1 }, { x: 1, y: 1, z: 1 });
94
-
95
- let nearHits = 0;
96
- tree.intersectAabb(() => {
97
- nearHits++;
98
- return false;
99
- }, nearQuery);
100
- expect(nearHits).toBe(0);
101
-
102
- const farQuery = Aabb.create();
103
- farQuery.setExtents({ x: 9, y: 9, z: 9 }, { x: 12, y: 12, z: 12 });
104
-
105
- let farHits = 0;
106
- tree.intersectAabb(() => {
107
- farHits++;
108
- return false;
109
- }, farQuery);
110
- expect(farHits).toBe(1);
111
- });
112
-
113
- it("inserts a single object into the root", () => {
114
- const tree = new BvhTree({ maxDepth: 10, maxObjectsPerLeaf: 2, expansionMargin: 0.1 });
115
-
116
- const object = Body.create(undefined);
117
- object.computedBounds.setExtents({ x: 0, y: 0, z: 0 }, { x: 1, y: 1, z: 1 });
118
-
119
- tree.insert(object);
120
-
121
- expect(tree.root).toBeDefined();
122
- expect(tree.root!.isLeaf()).toBe(true);
123
- expect(tree.root!.objects).toContain(object);
124
- expect(object.node).toBe(tree.root);
125
- });
126
-
127
- it("inserts two objects into the same leaf", () => {
128
- const tree = new BvhTree({ maxDepth: 10, maxObjectsPerLeaf: 2, expansionMargin: 0.1 });
129
-
130
- const a = Body.create(undefined);
131
- a.computedBounds.setExtents({ x: 0, y: 0, z: 0 }, { x: 1, y: 1, z: 1 });
132
-
133
- const b = Body.create(undefined);
134
- b.computedBounds.setExtents({ x: 2, y: 2, z: 2 }, { x: 3, y: 3, z: 3 });
135
-
136
- tree.insert(a);
137
- tree.insert(b);
138
-
139
- expect(tree.root).toBeDefined();
140
- expect(tree.root!.isLeaf()).toBe(true);
141
- expect(tree.root!.objects).toContain(a);
142
- expect(tree.root!.objects).toContain(b);
143
- });
144
-
145
- it("splits root when inserting third object", () => {
146
- const tree = new BvhTree({ maxDepth: 10, maxObjectsPerLeaf: 2, expansionMargin: 0.1 });
147
-
148
- const a = Body.create(undefined);
149
- a.computedBounds.setExtents({ x: 0, y: 0, z: 0 }, { x: 1, y: 1, z: 1 });
150
- const b = Body.create(undefined);
151
- b.computedBounds.setExtents({ x: 2, y: 2, z: 2 }, { x: 3, y: 3, z: 3 });
152
- const c = Body.create(undefined);
153
- c.computedBounds.setExtents({ x: 4, y: 4, z: 4 }, { x: 5, y: 5, z: 5 });
154
-
155
- tree.insert(a);
156
- tree.insert(b);
157
- tree.insert(c);
158
-
159
- const root = tree.root!;
160
- const rootLeft = root.left!;
161
- const rootRight = root.right!;
162
- expect(root.isLeaf()).toBe(false);
163
- expect(root.left).toBeDefined();
164
- expect(root.right).toBeDefined();
165
- expect(rootLeft.isLeaf()).toBe(true);
166
- expect(rootRight.isLeaf()).toBe(true);
167
-
168
- const all = [...rootLeft.objects, ...rootRight.objects];
169
- expect(all).toEqual(expect.arrayContaining([a, b, c]));
170
- });
171
-
172
- it("respects early exit from intersectAabb", () => {
173
- const world = new World();
174
- const tree = new BvhTree({ maxDepth: 4, maxObjectsPerLeaf: 2, expansionMargin: 0 });
175
-
176
- for (let i = 0; i < 10; i++) {
177
- const body = createTestBody(world, i * 2, 0, 0);
178
- tree.insert(body);
179
- }
180
-
181
- const query = Aabb.create();
182
- query.setExtents({ x: 0, y: -1, z: -1 }, { x: 20, y: 1, z: 1 });
183
-
184
- let called = 0;
185
- tree.intersectAabb(() => {
186
- called++;
187
- return true;
188
- }, query);
189
-
190
- expect(called).toBe(1);
191
- });
192
-
193
- it("handles multiple inserts and finds all", () => {
194
- const world = new World();
195
- const tree = new BvhTree({ maxDepth: 4, maxObjectsPerLeaf: 2, expansionMargin: 0 });
196
-
197
- const count = 50;
198
- for (let i = 0; i < count; i++) {
199
- const body = createTestBody(world, i * 2, 0, 0);
200
- tree.insert(body);
201
- }
202
-
203
- const query = Aabb.create();
204
- query.setExtents({ x: -1, y: -1, z: -1 }, { x: count * 2, y: 1, z: 1 });
205
-
206
- let hits = 0;
207
- tree.intersectAabb(() => {
208
- hits++;
209
- return false;
210
- }, query);
211
-
212
- expect(hits).toBe(count);
213
- });
214
-
215
- it("removes a middle object", () => {
216
- const tree = new BvhTree({ maxDepth: 10, maxObjectsPerLeaf: 2, expansionMargin: 0 });
217
-
218
- const objects = [];
219
- for (let i = 0; i < 6; i++) {
220
- const obj = Body.create(undefined);
221
- obj.computedBounds.setExtents({ x: i * 2, y: 0, z: 0 }, { x: i * 2 + 1, y: 1, z: 1 });
222
- objects.push(obj);
223
- }
224
-
225
- for (const obj of objects) {
226
- tree.insert(obj);
227
- }
228
-
229
- // remove a middle object
230
- tree.remove(objects[2]);
231
-
232
- const query = Aabb.create();
233
- query.setExtents({ x: 0, y: 0, z: 0 }, { x: 20, y: 1, z: 1 });
234
-
235
- let hitCount = 0;
236
- tree.intersectAabb(() => {
237
- hitCount++;
238
- return false;
239
- }, query);
240
-
241
- expect(hitCount).toBe(objects.length - 1);
242
- expect(objects[2].node).toBe(null);
243
- });
244
-
245
- it("removes the only object", () => {
246
- const tree = new BvhTree({ maxDepth: 4, maxObjectsPerLeaf: 1, expansionMargin: 0 });
247
-
248
- const obj = Body.create(undefined);
249
- obj.computedBounds.setExtents({ x: 0, y: 0, z: 0 }, { x: 1, y: 1, z: 1 });
250
-
251
- tree.insert(obj);
252
- tree.remove(obj);
253
-
254
- expect(tree.root).toBe(null);
255
- });
256
-
257
- it("updates an object to move across the tree", () => {
258
- const tree = new BvhTree({ maxDepth: 10, maxObjectsPerLeaf: 1, expansionMargin: 0 });
259
-
260
- const objectA = Body.create(undefined);
261
- objectA.computedBounds.setExtents({ x: 0, y: 0, z: 0 }, { x: 1, y: 1, z: 1 });
262
- objectA.node = null;
263
-
264
- const objectB = Body.create(undefined);
265
- objectB.computedBounds.setExtents({ x: 10, y: 0, z: 0 }, { x: 11, y: 1, z: 1 });
266
- objectB.node = null;
267
-
268
- tree.insert(objectA);
269
- tree.insert(objectB);
270
-
271
- objectA.computedBounds.setExtents({ x: 20, y: 0, z: 0 }, { x: 21, y: 1, z: 1 });
272
- tree.update(objectA);
273
-
274
- const query1 = Aabb.create();
275
- query1.setExtents({ x: 0, y: 0, z: 0 }, { x: 5, y: 1, z: 1 });
276
-
277
- let nearHits = 0;
278
- tree.intersectAabb(() => {
279
- nearHits++;
280
- return false;
281
- }, query1);
282
-
283
- expect(nearHits).toBe(0);
284
-
285
- const query2 = Aabb.create();
286
- query2.setExtents({ x: 19, y: 0, z: 0 }, { x: 22, y: 1, z: 1 });
287
-
288
- let farHits = 0;
289
- tree.intersectAabb(() => {
290
- farHits++;
291
- return false;
292
- }, query2);
293
-
294
- expect(farHits).toBe(1);
295
- expect(objectA.node).not.toBe(null);
296
- });
297
-
298
- it("updates object with no bounding box change", () => {
299
- const tree = new BvhTree({ maxDepth: 4, maxObjectsPerLeaf: 2, expansionMargin: 0 });
300
-
301
- const object = Body.create(undefined);
302
- object.computedBounds.setExtents({ x: 5, y: 5, z: 5 }, { x: 6, y: 6, z: 6 });
303
- object.node = null;
304
-
305
- tree.insert(object);
306
- tree.update(object);
307
-
308
- const query = Aabb.create();
309
- query.setExtents({ x: 4, y: 4, z: 4 }, { x: 7, y: 7, z: 7 });
310
-
311
- let hits = 0;
312
- tree.intersectAabb(() => {
313
- hits++;
314
- return false;
315
- }, query);
316
-
317
- expect(hits).toBe(1);
318
- });
319
-
320
- it("does not refit if update is within expansion margin", () => {
321
- const expansionMargin = 1.0;
322
- const tree = new BvhTree({ maxDepth: 4, maxObjectsPerLeaf: 2, expansionMargin });
323
-
324
- const object = Body.create(undefined);
325
- object.computedBounds.setExtents({ x: 0, y: 0, z: 0 }, { x: 1, y: 1, z: 1 });
326
- object.node = null;
327
-
328
- tree.insert(object);
329
-
330
- // move the object slightly, within the margin
331
- object.computedBounds.setExtents({ x: 0.2, y: 0.2, z: 0.2 }, { x: 1.2, y: 1.2, z: 1.2 });
332
-
333
- const didRefit = tree.update(object);
334
- expect(didRefit).toBe(false);
335
-
336
- const query = Aabb.create();
337
- query.setExtents({ x: 0, y: 0, z: 0 }, { x: 2, y: 2, z: 2 });
338
-
339
- let hits = 0;
340
- tree.intersectAabb(() => {
341
- hits++;
342
- return false;
343
- }, query);
344
-
345
- expect(hits).toBe(1);
346
- });
347
-
348
- it("handles many dynamic inserts, updates, and removals", () => {
349
- const tree = new BvhTree({ maxDepth: 8, maxObjectsPerLeaf: 4, expansionMargin: 0 });
350
- const rng = createSeededRng(42);
351
-
352
- const objects = [];
353
- const objectsInTheTree = new Set<Body>();
354
-
355
- const world = new World();
356
-
357
- const numObjects = 100;
358
- const numToMove = Math.floor(numObjects / 2);
359
- const numToRemove = Math.floor(numObjects / 2);
360
-
361
- for (let i = 0; i < numObjects; i++) {
362
- const min = { x: i * 2, y: 0, z: 0 };
363
- const max = { x: i * 2 + 1, y: 1, z: 1 };
364
- const obj = createTestBodyWithExtents(world, min, max);
365
- objects.push(obj);
366
- objectsInTheTree.add(obj);
367
- tree.insert(obj);
368
- }
369
-
370
- for (let i = 0; i < numToMove; i++) {
371
- const index = Math.floor(rng() * objects.length);
372
- const obj = objects[index];
373
-
374
- if (!obj.node) continue;
375
-
376
- const offset = rng() * numObjects;
377
- obj.computedBounds.setExtents({ x: offset, y: 0, z: 0 }, { x: offset + 1, y: 1, z: 1 });
378
- tree.update(obj);
379
- }
380
-
381
- for (let i = 0; i < numToRemove; i++) {
382
- const index = Math.floor(rng() * objects.length);
383
- const obj = objects[index];
384
- if (obj.node) {
385
- tree.remove(obj);
386
- objectsInTheTree.delete(obj);
387
- expect(obj.node).toBe(null);
388
- }
389
- }
390
-
391
- const query = Aabb.create();
392
- query.setExtents({ x: -10000, y: -10000, z: -10000 }, { x: +10000, y: +10000, z: +10000 });
393
-
394
- const actual: Array<Body> = [];
395
- const expected = [...objectsInTheTree];
396
- tree.intersectAabb(obj => {
397
- actual.push(obj);
398
- return false;
399
- }, query);
400
-
401
- expect(actual.length).toBe(expected.length);
402
- const actualSet = new Set(actual);
403
- const expectedSet = new Set(expected);
404
- expect(actualSet).toEqual(expectedSet);
405
- });
406
- });
package/tests/test.md DELETED
@@ -1,642 +0,0 @@
1
-
2
- tree---
3
-
4
- node 0
5
- parent: null
6
- left: null
7
- right: null
8
- height: 0
9
- objects: []
10
- node.isLeaf(): true
11
- node.isRoot(): true
12
-
13
- node 1
14
- parent: null
15
- left: null
16
- right: null
17
- height: 0
18
- objects: []
19
- node.isLeaf(): true
20
- node.isRoot(): true
21
-
22
- node 2
23
- parent: null
24
- left: null
25
- right: null
26
- height: 0
27
- objects: []
28
- node.isLeaf(): true
29
- node.isRoot(): true
30
-
31
- node 3
32
- parent: 6
33
- left: null
34
- right: null
35
- height: 0
36
- objects: [ 2, 3 ]
37
- node.isLeaf(): true
38
- node.isRoot(): false
39
-
40
- node 4
41
- parent: null
42
- left: null
43
- right: null
44
- height: 0
45
- objects: []
46
- node.isLeaf(): true
47
- node.isRoot(): true
48
-
49
- node 5
50
- parent: null
51
- left: null
52
- right: null
53
- height: 0
54
- objects: []
55
- node.isLeaf(): true
56
- node.isRoot(): true
57
-
58
- node 6
59
- parent: 10
60
- left: 3
61
- right: 15
62
- height: 1
63
- objects: []
64
- node.isLeaf(): false
65
- node.isRoot(): false
66
-
67
- node 7
68
- parent: null
69
- left: null
70
- right: null
71
- height: 0
72
- objects: []
73
- node.isLeaf(): true
74
- node.isRoot(): true
75
-
76
- node 8
77
- parent: 10
78
- left: 9
79
- right: 11
80
- height: 1
81
- objects: []
82
- node.isLeaf(): false
83
- node.isRoot(): false
84
-
85
- node 9
86
- parent: 8
87
- left: null
88
- right: null
89
- height: 0
90
- objects: [ 8 ]
91
- node.isLeaf(): true
92
- node.isRoot(): false
93
-
94
- node 10
95
- parent: 14
96
- left: 6
97
- right: 15
98
- height: 2
99
- objects: []
100
- node.isLeaf(): false
101
- node.isRoot(): false
102
-
103
- node 11
104
- parent: 8
105
- left: null
106
- right: null
107
- height: 0
108
- objects: [ 11 ]
109
- node.isLeaf(): true
110
- node.isRoot(): false
111
-
112
- node 12
113
- parent: null
114
- left: null
115
- right: null
116
- height: 0
117
- objects: []
118
- node.isLeaf(): true
119
- node.isRoot(): true
120
-
121
- node 13
122
- parent: null
123
- left: null
124
- right: null
125
- height: 0
126
- objects: []
127
- node.isLeaf(): true
128
- node.isRoot(): true
129
-
130
- node 14
131
- parent: 30
132
- left: 10
133
- right: 22
134
- height: 4
135
- objects: []
136
- node.isLeaf(): false
137
- node.isRoot(): false
138
-
139
- node 15
140
- parent: 6
141
- left: null
142
- right: null
143
- height: 0
144
- objects: [ 14 ]
145
- node.isLeaf(): true
146
- node.isRoot(): false
147
-
148
- node 16
149
- parent: 18
150
- left: 17
151
- right: 19
152
- height: 1
153
- objects: []
154
- node.isLeaf(): false
155
- node.isRoot(): false
156
-
157
- node 17
158
- parent: 16
159
- left: null
160
- right: null
161
- height: 0
162
- objects: [ 17 ]
163
- node.isLeaf(): true
164
- node.isRoot(): false
165
-
166
- node 18
167
- parent: 22
168
- left: 16
169
- right: 21
170
- height: 2
171
- objects: []
172
- node.isLeaf(): false
173
- node.isRoot(): false
174
-
175
- node 19
176
- parent: 16
177
- left: null
178
- right: null
179
- height: 0
180
- objects: [ 19 ]
181
- node.isLeaf(): true
182
- node.isRoot(): false
183
-
184
- node 20
185
- parent: null
186
- left: null
187
- right: null
188
- height: 0
189
- objects: []
190
- node.isLeaf(): true
191
- node.isRoot(): true
192
-
193
- node 21
194
- parent: 18
195
- left: null
196
- right: null
197
- height: 0
198
- objects: [ 20 ]
199
- node.isLeaf(): true
200
- node.isRoot(): false
201
-
202
- node 22
203
- parent: 14
204
- left: 18
205
- right: 26
206
- height: 3
207
- objects: []
208
- node.isLeaf(): false
209
- node.isRoot(): false
210
-
211
- node 23
212
- parent: null
213
- left: null
214
- right: null
215
- height: 0
216
- objects: []
217
- node.isLeaf(): true
218
- node.isRoot(): true
219
-
220
- node 24
221
- parent: 26
222
- left: 25
223
- right: 27
224
- height: 1
225
- objects: []
226
- node.isLeaf(): false
227
- node.isRoot(): false
228
-
229
- node 25
230
- parent: 24
231
- left: null
232
- right: null
233
- height: 0
234
- objects: [ 24 ]
235
- node.isLeaf(): true
236
- node.isRoot(): false
237
-
238
- node 26
239
- parent: 22
240
- left: 24
241
- right: 31
242
- height: 2
243
- objects: []
244
- node.isLeaf(): false
245
- node.isRoot(): false
246
-
247
- node 27
248
- parent: 24
249
- left: null
250
- right: null
251
- height: 0
252
- objects: [ 26 ]
253
- node.isLeaf(): true
254
- node.isRoot(): false
255
-
256
- node 28
257
- parent: null
258
- left: null
259
- right: null
260
- height: 0
261
- objects: []
262
- node.isLeaf(): true
263
- node.isRoot(): true
264
-
265
- node 29
266
- parent: null
267
- left: null
268
- right: null
269
- height: 0
270
- objects: []
271
- node.isLeaf(): true
272
- node.isRoot(): true
273
-
274
- node 30
275
- parent: null
276
- left: 14
277
- right: 62
278
- height: 5
279
- objects: []
280
- node.isLeaf(): false
281
- node.isRoot(): true
282
-
283
- node 31
284
- parent: 26
285
- left: null
286
- right: null
287
- height: 0
288
- objects: [ 31 ]
289
- node.isLeaf(): true
290
- node.isRoot(): false
291
-
292
- node 32
293
- parent: null
294
- left: null
295
- right: null
296
- height: 0
297
- objects: []
298
- node.isLeaf(): true
299
- node.isRoot(): true
300
-
301
- node 33
302
- parent: 38
303
- left: null
304
- right: null
305
- height: 0
306
- objects: [ 33 ]
307
- node.isLeaf(): true
308
- node.isRoot(): false
309
-
310
- node 34
311
- parent: 46
312
- left: 38
313
- right: 36
314
- height: 2
315
- objects: []
316
- node.isLeaf(): false
317
- node.isRoot(): false
318
-
319
- node 35
320
- parent: null
321
- left: null
322
- right: null
323
- height: 0
324
- objects: []
325
- node.isLeaf(): true
326
- node.isRoot(): true
327
-
328
- node 36
329
- parent: 34
330
- left: 37
331
- right: 39
332
- height: 1
333
- objects: []
334
- node.isLeaf(): false
335
- node.isRoot(): false
336
-
337
- node 37
338
- parent: 36
339
- left: null
340
- right: null
341
- height: 0
342
- objects: [ 36, 37 ]
343
- node.isLeaf(): true
344
- node.isRoot(): false
345
-
346
- node 38
347
- parent: 34
348
- left: 33
349
- right: 45
350
- height: 1
351
- objects: []
352
- node.isLeaf(): false
353
- node.isRoot(): false
354
-
355
- node 39
356
- parent: 36
357
- left: null
358
- right: null
359
- height: 0
360
- objects: [ 39 ]
361
- node.isLeaf(): true
362
- node.isRoot(): false
363
-
364
- node 40
365
- parent: null
366
- left: null
367
- right: null
368
- height: 0
369
- objects: []
370
- node.isLeaf(): true
371
- node.isRoot(): true
372
-
373
- node 41
374
- parent: null
375
- left: null
376
- right: null
377
- height: 0
378
- objects: []
379
- node.isLeaf(): true
380
- node.isRoot(): true
381
-
382
- node 42
383
- parent: null
384
- left: null
385
- right: null
386
- height: 0
387
- objects: []
388
- node.isLeaf(): true
389
- node.isRoot(): true
390
-
391
- node 43
392
- parent: null
393
- left: null
394
- right: null
395
- height: 0
396
- objects: []
397
- node.isLeaf(): true
398
- node.isRoot(): true
399
-
400
- node 44
401
- parent: null
402
- left: null
403
- right: null
404
- height: 0
405
- objects: []
406
- node.isLeaf(): true
407
- node.isRoot(): true
408
-
409
- node 45
410
- parent: 38
411
- left: null
412
- right: null
413
- height: 0
414
- objects: [ 45 ]
415
- node.isLeaf(): true
416
- node.isRoot(): false
417
-
418
- node 46
419
- parent: 62
420
- left: 34
421
- right: 66
422
- height: 3
423
- objects: []
424
- node.isLeaf(): false
425
- node.isRoot(): false
426
-
427
- node 47
428
- parent: null
429
- left: null
430
- right: null
431
- height: 0
432
- objects: []
433
- node.isLeaf(): true
434
- node.isRoot(): true
435
-
436
- node 48
437
- parent: null
438
- left: null
439
- right: null
440
- height: 0
441
- objects: []
442
- node.isLeaf(): true
443
- node.isRoot(): true
444
-
445
- node 49
446
- parent: 50
447
- left: null
448
- right: null
449
- height: 0
450
- objects: [ 18, 28 ]
451
- node.isLeaf(): true
452
- node.isRoot(): false
453
-
454
- node 50
455
- parent: 54
456
- left: 49
457
- right: 53
458
- height: 1
459
- objects: []
460
- node.isLeaf(): false
461
- node.isRoot(): false
462
-
463
- node 51
464
- parent: null
465
- left: null
466
- right: null
467
- height: 0
468
- objects: []
469
- node.isLeaf(): true
470
- node.isRoot(): true
471
-
472
- node 52
473
- parent: null
474
- left: null
475
- right: null
476
- height: 0
477
- objects: []
478
- node.isLeaf(): true
479
- node.isRoot(): true
480
-
481
- node 53
482
- parent: 50
483
- left: null
484
- right: null
485
- height: 0
486
- objects: [ 42, 32 ]
487
- node.isLeaf(): true
488
- node.isRoot(): false
489
-
490
- node 54
491
- parent: 62
492
- left: 50
493
- right: 58
494
- height: 3
495
- objects: []
496
- node.isLeaf(): false
497
- node.isRoot(): false
498
-
499
- node 55
500
- parent: null
501
- left: null
502
- right: null
503
- height: 0
504
- objects: []
505
- node.isLeaf(): true
506
- node.isRoot(): true
507
-
508
- node 56
509
- parent: null
510
- left: null
511
- right: null
512
- height: 0
513
- objects: []
514
- node.isLeaf(): true
515
- node.isRoot(): true
516
-
517
- node 57
518
- parent: null
519
- left: null
520
- right: null
521
- height: 0
522
- objects: []
523
- node.isLeaf(): true
524
- node.isRoot(): true
525
-
526
- node 58
527
- parent: 54
528
- left: 59
529
- right: 60
530
- height: 2
531
- objects: []
532
- node.isLeaf(): false
533
- node.isRoot(): false
534
-
535
- node 59
536
- parent: 58
537
- left: null
538
- right: null
539
- height: 0
540
- objects: [ 27 ]
541
- node.isLeaf(): true
542
- node.isRoot(): false
543
-
544
- node 60
545
- parent: 58
546
- left: 61
547
- right: 63
548
- height: 1
549
- objects: []
550
- node.isLeaf(): false
551
- node.isRoot(): false
552
-
553
- node 61
554
- parent: 60
555
- left: null
556
- right: null
557
- height: 0
558
- objects: [ 23, 1 ]
559
- node.isLeaf(): true
560
- node.isRoot(): false
561
-
562
- node 62
563
- parent: 30
564
- left: 46
565
- right: 66
566
- height: 4
567
- objects: []
568
- node.isLeaf(): false
569
- node.isRoot(): false
570
-
571
- node 63
572
- parent: 60
573
- left: null
574
- right: null
575
- height: 0
576
- objects: [ 34, 7 ]
577
- node.isLeaf(): true
578
- node.isRoot(): false
579
-
580
- node 64
581
- parent: null
582
- left: null
583
- right: null
584
- height: 0
585
- objects: []
586
- node.isLeaf(): true
587
- node.isRoot(): true
588
-
589
- node 65
590
- parent: null
591
- left: null
592
- right: null
593
- height: 0
594
- objects: []
595
- node.isLeaf(): true
596
- node.isRoot(): true
597
-
598
- node 66
599
- parent: 46
600
- left: 67
601
- right: 68
602
- height: 2
603
- objects: []
604
- node.isLeaf(): false
605
- node.isRoot(): false
606
-
607
- node 67
608
- parent: 66
609
- left: null
610
- right: null
611
- height: 0
612
- objects: [ 22, 4 ]
613
- node.isLeaf(): true
614
- node.isRoot(): false
615
-
616
- node 68
617
- parent: 66
618
- left: 69
619
- right: 70
620
- height: 1
621
- objects: []
622
- node.isLeaf(): false
623
- node.isRoot(): false
624
-
625
- node 69
626
- parent: 68
627
- left: null
628
- right: null
629
- height: 0
630
- objects: [ 49 ]
631
- node.isLeaf(): true
632
- node.isRoot(): false
633
-
634
- node 70
635
- parent: 68
636
- left: null
637
- right: null
638
- height: 0
639
- objects: [ 38, 41 ]
640
- node.isLeaf(): true
641
- node.isRoot(): false
642
- ---tree
@@ -1,12 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { Vec3 } from "../src";
3
-
4
- describe("Vec3", () => {
5
- it("should create a Vec3 instance", () => {
6
- const position = Vec3.create();
7
- expect(position).toBeInstanceOf(Vec3);
8
- expect(position.x).toBe(0);
9
- expect(position.y).toBe(0);
10
- expect(position.z).toBe(0);
11
- });
12
- });