@woosh/meep-engine 2.33.51 → 2.33.55
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/core/geom/3d/shape/AbstractShape3D.js +17 -0
- package/core/geom/3d/shape/TransformedShape3D.d.ts +10 -0
- package/core/geom/3d/shape/TransformedShape3D.js +28 -3
- package/core/geom/3d/shape/TransformedShape3D.spec.js +22 -0
- package/core/geom/3d/shape/UnionShape3D.d.ts +5 -0
- package/core/geom/3d/shape/UnionShape3D.js +29 -0
- package/core/geom/3d/shape/UnitCubeShape3D.d.ts +5 -0
- package/core/geom/3d/shape/UnitCubeShape3D.js +7 -1
- package/core/geom/3d/shape/UnitSphereShape3D.d.ts +5 -0
- package/core/geom/3d/shape/UnitSphereShape3D.js +7 -1
- package/core/geom/3d/shape/json/shape_from_json.js +19 -0
- package/core/geom/3d/shape/json/shape_to_json.js +21 -0
- package/core/geom/3d/shape/json/shape_to_type.js +23 -0
- package/core/geom/3d/shape/json/type_adapters.js +58 -0
- package/core/math/MathUtils.spec.js +0 -10
- package/core/math/hash/computeHashFloatArray.js +4 -15
- package/core/math/hash/computeHashFloatArray.spec.js +11 -0
- package/core/model/object/read_property.js +1 -1
- package/core/model/object/write_property.js +6 -6
- package/engine/animation/AnimationUtils.js +0 -120
- package/engine/animation/removeEntityGenericEffect.js +168 -0
- package/engine/animation/removeEntityWithMeshParticlesEffect.js +201 -0
- package/engine/graphics/particles/ecs/ParticleEmitterSystem.js +1 -22
- package/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +2 -2
- package/engine/graphics/particles/particular/engine/utils/volume/AttributeValue.js +54 -0
- package/engine/graphics/particles/particular/engine/utils/volume/ParticleVolume.js +50 -20
- package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +2 -3
- package/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.js +1 -1
- package/package.json +1 -1
|
@@ -62,4 +62,21 @@ export class AbstractShape3D {
|
|
|
62
62
|
get surface_area() {
|
|
63
63
|
throw new Error('Not Implemented');
|
|
64
64
|
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @template {AbstractShape3D} T
|
|
68
|
+
* @param {T} other
|
|
69
|
+
* @returns {boolean}
|
|
70
|
+
*/
|
|
71
|
+
equals(other) {
|
|
72
|
+
return this.constructor === other.constructor;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
*
|
|
77
|
+
* @returns {number}
|
|
78
|
+
*/
|
|
79
|
+
hash() {
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
65
82
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {AbstractShape3D} from "./AbstractShape3D";
|
|
2
|
+
|
|
3
|
+
export class TransformedShape3D extends AbstractShape3D {
|
|
4
|
+
|
|
5
|
+
static from_m4(subject: AbstractShape3D, matrix: ArrayLike<number>): TransformedShape3D
|
|
6
|
+
|
|
7
|
+
static from_translation_scale(subject: AbstractShape3D, translation: ArrayLike<number>, scale: ArrayLike<number>): TransformedShape3D
|
|
8
|
+
|
|
9
|
+
static from_scale(subject: AbstractShape3D, scale: ArrayLike<number>): TransformedShape3D
|
|
10
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { mat4, vec3 } from "gl-matrix";
|
|
2
2
|
import { AbstractShape3D } from "./AbstractShape3D.js";
|
|
3
3
|
import { sign } from "../../../math/sign.js";
|
|
4
|
+
import { isArrayEqualStrict } from "../../../collection/array/isArrayEqualStrict.js";
|
|
5
|
+
import { computeHashFloatArray } from "../../../math/hash/computeHashFloatArray.js";
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
*
|
|
@@ -140,9 +142,9 @@ export class TransformedShape3D extends AbstractShape3D {
|
|
|
140
142
|
// normalize gradient
|
|
141
143
|
const gd = distance / Math.hypot(scratch_v3_0[0], scratch_v3_0[1], scratch_v3_0[2]);
|
|
142
144
|
|
|
143
|
-
const scaled_dx = scaled_gx * gd
|
|
144
|
-
const scaled_dy = scaled_gy * gd
|
|
145
|
-
const scaled_dz = scaled_gz * gd
|
|
145
|
+
const scaled_dx = scaled_gx * gd;
|
|
146
|
+
const scaled_dy = scaled_gy * gd;
|
|
147
|
+
const scaled_dz = scaled_gz * gd;
|
|
146
148
|
|
|
147
149
|
// determine sign
|
|
148
150
|
const result_sign = sign(distance);
|
|
@@ -178,4 +180,27 @@ export class TransformedShape3D extends AbstractShape3D {
|
|
|
178
180
|
result[1] = scratch_v3_0[1];
|
|
179
181
|
result[2] = scratch_v3_0[2];
|
|
180
182
|
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
*
|
|
186
|
+
* @param {TransformedShape3D} other
|
|
187
|
+
* @returns {boolean}
|
|
188
|
+
*/
|
|
189
|
+
equals(other) {
|
|
190
|
+
return super.equals(other)
|
|
191
|
+
&& this.__subject.equals(other.subject)
|
|
192
|
+
&& isArrayEqualStrict(this.__matrix, other.__matrix)
|
|
193
|
+
;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
hash() {
|
|
197
|
+
// to avoid recursion, only use matrix for hash
|
|
198
|
+
return computeHashFloatArray(this.__matrix);
|
|
199
|
+
}
|
|
181
200
|
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* @readonly
|
|
204
|
+
* @type {boolean}
|
|
205
|
+
*/
|
|
206
|
+
TransformedShape3D.isTransformedShape3D = true;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { UnitCubeShape3D } from "./UnitCubeShape3D.js";
|
|
2
2
|
import { TransformedShape3D } from "./TransformedShape3D.js";
|
|
3
|
+
import { UnitSphereShape3D } from "./UnitSphereShape3D.js";
|
|
3
4
|
|
|
4
5
|
test('signed distance identity transform', () => {
|
|
5
6
|
|
|
@@ -31,3 +32,24 @@ test('signed distance scale', () => {
|
|
|
31
32
|
|
|
32
33
|
expect(s.signed_distance_at_point([2, 0, 0])).toBeCloseTo(1);
|
|
33
34
|
});
|
|
35
|
+
|
|
36
|
+
test('equals', () => {
|
|
37
|
+
|
|
38
|
+
const a = TransformedShape3D.from_translation_scale(new UnitCubeShape3D(), [0, 0, 0], [2, 2, 2]);
|
|
39
|
+
const b = TransformedShape3D.from_translation_scale(new UnitCubeShape3D(), [0, 0, 0], [2, 2, 2]);
|
|
40
|
+
|
|
41
|
+
expect(a.equals(b)).toBe(true);
|
|
42
|
+
|
|
43
|
+
const c = TransformedShape3D.from_translation_scale(new UnitCubeShape3D(), [0, 1, 0], [2, 2, 2]);
|
|
44
|
+
|
|
45
|
+
expect(a.equals(c)).toBe(false);
|
|
46
|
+
|
|
47
|
+
const d = TransformedShape3D.from_translation_scale(new UnitCubeShape3D(), [0, 0, 0], [2, 1, 2]);
|
|
48
|
+
|
|
49
|
+
expect(a.equals(d)).toBe(false);
|
|
50
|
+
|
|
51
|
+
const e = TransformedShape3D.from_translation_scale(new UnitSphereShape3D(), [0, 0, 0], [2, 2, 2]);
|
|
52
|
+
|
|
53
|
+
expect(a.equals(e)).toBe(false);
|
|
54
|
+
|
|
55
|
+
});
|
|
@@ -4,6 +4,7 @@ import { binarySearchHighIndex } from "../../../collection/array/binarySearchHig
|
|
|
4
4
|
import { compareNumbers } from "../../../primitives/numbers/compareNumbers.js";
|
|
5
5
|
import { min2 } from "../../../math/min2.js";
|
|
6
6
|
import { compute_signed_distance_gradient_by_sampling } from "./util/compute_signed_distance_gradient_by_sampling.js";
|
|
7
|
+
import { isArrayEqual } from "../../../collection/ArrayUtils.js";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* To avoid severe performance overhead, we limit number of possible rejections
|
|
@@ -119,6 +120,11 @@ export class UnionShape3D extends AbstractShape3D {
|
|
|
119
120
|
this.__volume_overlap_fraction = tap_overlaps / (VOLUME_OVERLAP_ESTIMATION_TAPS);
|
|
120
121
|
}
|
|
121
122
|
|
|
123
|
+
/**
|
|
124
|
+
*
|
|
125
|
+
* @param {AbstractShape3D[]} children
|
|
126
|
+
* @returns {UnionShape3D}
|
|
127
|
+
*/
|
|
122
128
|
static from(children) {
|
|
123
129
|
const r = new UnionShape3D();
|
|
124
130
|
|
|
@@ -252,4 +258,27 @@ export class UnionShape3D extends AbstractShape3D {
|
|
|
252
258
|
break;
|
|
253
259
|
}
|
|
254
260
|
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
*
|
|
264
|
+
* @param {UnionShape3D} other
|
|
265
|
+
* @returns {boolean}
|
|
266
|
+
*/
|
|
267
|
+
equals(other) {
|
|
268
|
+
return super.equals(other)
|
|
269
|
+
&& isArrayEqual(this.children, other.children);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
hash() {
|
|
273
|
+
const children = this.children;
|
|
274
|
+
const child_count = children.length;
|
|
275
|
+
|
|
276
|
+
let hash = child_count;
|
|
277
|
+
|
|
278
|
+
if (child_count > 0) {
|
|
279
|
+
hash ^= children[0].hash();
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return hash;
|
|
283
|
+
}
|
|
255
284
|
}
|
|
@@ -58,7 +58,7 @@ export class UnitCubeShape3D extends AbstractShape3D {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
signed_distance_gradient_at_point(result, point) {
|
|
61
|
-
return compute_signed_distance_gradient_by_sampling(result,this, point);
|
|
61
|
+
return compute_signed_distance_gradient_by_sampling(result, this, point);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
signed_distance_at_point(point) {
|
|
@@ -98,4 +98,10 @@ export class UnitCubeShape3D extends AbstractShape3D {
|
|
|
98
98
|
sample_random_point_in_volume(result, result_offset, random) {
|
|
99
99
|
randomPointInBox(random, result, result_offset);
|
|
100
100
|
}
|
|
101
|
+
|
|
102
|
+
hash() {
|
|
103
|
+
return 1;
|
|
104
|
+
}
|
|
101
105
|
}
|
|
106
|
+
|
|
107
|
+
UnitCubeShape3D.INSTANCE = new UnitCubeShape3D();
|
|
@@ -30,7 +30,7 @@ export class UnitSphereShape3D extends AbstractShape3D {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
signed_distance_gradient_at_point(result, point) {
|
|
33
|
-
return compute_signed_distance_gradient_by_sampling(result,this, point);
|
|
33
|
+
return compute_signed_distance_gradient_by_sampling(result, this, point);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
signed_distance_at_point(point) {
|
|
@@ -52,4 +52,10 @@ export class UnitSphereShape3D extends AbstractShape3D {
|
|
|
52
52
|
sample_random_point_in_volume(result, result_offset, random) {
|
|
53
53
|
randomPointInSphere(random, result, result_offset);
|
|
54
54
|
}
|
|
55
|
+
|
|
56
|
+
hash() {
|
|
57
|
+
return 13;
|
|
58
|
+
}
|
|
55
59
|
}
|
|
60
|
+
|
|
61
|
+
UnitSphereShape3D.INSTANCE = new UnitSphereShape3D();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type_adapters } from "./type_adapters.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {Object} j
|
|
6
|
+
* @returns {AbstractShape3D}
|
|
7
|
+
*/
|
|
8
|
+
export function shape_from_json(j) {
|
|
9
|
+
const type = j.type;
|
|
10
|
+
|
|
11
|
+
const adapter = type_adapters[type];
|
|
12
|
+
|
|
13
|
+
if (adapter === undefined) {
|
|
14
|
+
throw new Error(`Unsupported shape type '${type}'`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return adapter.read(j);
|
|
18
|
+
}
|
|
19
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { shape_to_type } from "./shape_to_type.js";
|
|
2
|
+
import { type_adapters } from "./type_adapters.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {AbstractShape3D} shape
|
|
7
|
+
* @returns {Object}
|
|
8
|
+
*/
|
|
9
|
+
export function shape_to_json(shape) {
|
|
10
|
+
const type = shape_to_type(shape);
|
|
11
|
+
|
|
12
|
+
const adapter = type_adapters[type];
|
|
13
|
+
|
|
14
|
+
if (adapter === undefined) {
|
|
15
|
+
throw new Error(`Unsupported shape type '${type}'`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const shape_json = adapter.write(shape);
|
|
19
|
+
|
|
20
|
+
return Object.assign({ type }, shape_json);
|
|
21
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { UnionShape3D } from "../UnionShape3D.js";
|
|
2
|
+
import { UnitCubeShape3D } from "../UnitCubeShape3D.js";
|
|
3
|
+
import { UnitSphereShape3D } from "../UnitSphereShape3D.js";
|
|
4
|
+
import { TransformedShape3D } from "../TransformedShape3D.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param {AbstractShape3D} shape
|
|
9
|
+
* @returns {string}
|
|
10
|
+
*/
|
|
11
|
+
export function shape_to_type(shape) {
|
|
12
|
+
if (shape instanceof UnionShape3D) {
|
|
13
|
+
return 'union';
|
|
14
|
+
} else if (shape instanceof UnitCubeShape3D) {
|
|
15
|
+
return 'cube';
|
|
16
|
+
} else if (shape instanceof UnitSphereShape3D) {
|
|
17
|
+
return 'sphere';
|
|
18
|
+
} else if (shape instanceof TransformedShape3D) {
|
|
19
|
+
return 'transform';
|
|
20
|
+
} else {
|
|
21
|
+
throw new Error('Unsupported shape');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { UnitCubeShape3D } from "../UnitCubeShape3D.js";
|
|
2
|
+
import { UnitSphereShape3D } from "../UnitSphereShape3D.js";
|
|
3
|
+
import { TransformedShape3D } from "../TransformedShape3D.js";
|
|
4
|
+
import { UnionShape3D } from "../UnionShape3D.js";
|
|
5
|
+
import { shape_from_json} from "./shape_from_json.js";
|
|
6
|
+
import { shape_to_json } from "./shape_to_json.js";
|
|
7
|
+
|
|
8
|
+
export const type_adapters = {
|
|
9
|
+
'cube': {
|
|
10
|
+
read() {
|
|
11
|
+
return UnitCubeShape3D.INSTANCE;
|
|
12
|
+
},
|
|
13
|
+
write() {
|
|
14
|
+
return {};
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
'sphere': {
|
|
18
|
+
read() {
|
|
19
|
+
return UnitSphereShape3D.INSTANCE;
|
|
20
|
+
},
|
|
21
|
+
write() {
|
|
22
|
+
return {};
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
'transform': {
|
|
26
|
+
read({ transform, subject }) {
|
|
27
|
+
const subject_shape = shape_from_json(subject);
|
|
28
|
+
|
|
29
|
+
return TransformedShape3D.from_m4(subject_shape, transform);
|
|
30
|
+
},
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
* @param {TransformedShape3D} object
|
|
34
|
+
*/
|
|
35
|
+
write(object) {
|
|
36
|
+
return {
|
|
37
|
+
subject: shape_to_json(object.subject),
|
|
38
|
+
transform: Array.from(object.transform)
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
'union': {
|
|
43
|
+
read({ members }) {
|
|
44
|
+
const member_shapes = members.map(shape_from_json);
|
|
45
|
+
|
|
46
|
+
return UnionShape3D.from(member_shapes);
|
|
47
|
+
},
|
|
48
|
+
/**
|
|
49
|
+
*
|
|
50
|
+
* @param {UnionShape3D} object
|
|
51
|
+
*/
|
|
52
|
+
write(object) {
|
|
53
|
+
return {
|
|
54
|
+
members: object.children.map(shape_to_json)
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
@@ -128,16 +128,6 @@ test("computeHashFloat", () => {
|
|
|
128
128
|
expect(computeHashFloat(500)).not.toEqual(computeHashFloat(400))
|
|
129
129
|
});
|
|
130
130
|
|
|
131
|
-
test("computeHashFloatArray", () => {
|
|
132
|
-
expect(computeHashFloatArray([1, 2, 1.5], 1, 2)).toEqual(computeHashFloatArray([1, 2, 1.5], 1, 2));
|
|
133
|
-
|
|
134
|
-
expect(computeHashFloatArray([1, 2, 1.5], 1, 3)).not.toEqual(computeHashFloatArray([1, 2, 1.5], 1, 2));
|
|
135
|
-
|
|
136
|
-
expect(computeHashFloatArray([1, 2, 1.5], 2, 3)).not.toEqual(computeHashFloatArray([1, 2, 1.5], 1, 3));
|
|
137
|
-
|
|
138
|
-
expect(computeHashFloatArray([1, 2, 3], 1, 3)).not.toEqual(computeHashFloatArray([1, 2, 1.5], 1, 3));
|
|
139
|
-
});
|
|
140
|
-
|
|
141
131
|
|
|
142
132
|
test('sign', () => {
|
|
143
133
|
expect(sign(1)).toBe(1);
|
|
@@ -3,28 +3,17 @@ import { computeHashFloat } from "./computeHashFloat.js";
|
|
|
3
3
|
/**
|
|
4
4
|
*
|
|
5
5
|
* @param {number[]|Float32Array|Float64Array} values
|
|
6
|
-
* @param {number} min
|
|
7
|
-
* @param {number} max
|
|
8
6
|
*/
|
|
9
|
-
export function computeHashFloatArray(values
|
|
7
|
+
export function computeHashFloatArray(values) {
|
|
10
8
|
const dataLength = values.length;
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
/*
|
|
15
|
-
hash min and max
|
|
16
|
-
*/
|
|
17
|
-
const minHash = computeHashFloat(min);
|
|
18
|
-
const maxHash = computeHashFloat(min);
|
|
19
|
-
|
|
20
|
-
let hash = ((minHash << 5) - minHash) + maxHash;
|
|
10
|
+
let hash = dataLength;
|
|
21
11
|
|
|
22
12
|
for (let i = 0; i < dataLength; i++) {
|
|
23
13
|
const singleValue = values[i];
|
|
24
|
-
|
|
25
|
-
const valueNormalized = (singleValue - min) / dataRange;
|
|
14
|
+
|
|
26
15
|
//scale value to integer range
|
|
27
|
-
const integerValue =
|
|
16
|
+
const integerValue = computeHashFloat(singleValue);
|
|
28
17
|
|
|
29
18
|
hash = ((hash << 5) - hash) + integerValue;
|
|
30
19
|
hash |= 0; // Convert to 32bit integer
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { computeHashFloatArray } from "./computeHashFloatArray.js";
|
|
2
|
+
|
|
3
|
+
test("computeHashFloatArray", () => {
|
|
4
|
+
expect(computeHashFloatArray([1, 2, 1.5])).toEqual(computeHashFloatArray([1, 2, 1.5]));
|
|
5
|
+
|
|
6
|
+
expect(computeHashFloatArray([1, 2, 1.5])).not.toEqual(computeHashFloatArray([1, 3, 1.5]));
|
|
7
|
+
|
|
8
|
+
expect(computeHashFloatArray([1, 2, 1.5])).not.toEqual(computeHashFloatArray([1, 2, 2.5]));
|
|
9
|
+
|
|
10
|
+
expect(computeHashFloatArray([1, 2, 3])).not.toEqual(computeHashFloatArray([1, 2, 1.5]));
|
|
11
|
+
});
|
|
@@ -16,7 +16,7 @@ export function read_property(root, parts, part_offset, part_count) {
|
|
|
16
16
|
|
|
17
17
|
const part = parts[i + part_offset];
|
|
18
18
|
|
|
19
|
-
if (thing
|
|
19
|
+
if (typeof thing[part] !== 'undefined') {
|
|
20
20
|
thing = thing[part];
|
|
21
21
|
} else {
|
|
22
22
|
const getter_name = `get${capitalize(part)}`;
|
|
@@ -17,8 +17,10 @@ export function write_property(root, parts, part_offset, part_count, value) {
|
|
|
17
17
|
|
|
18
18
|
const part = parts[i + part_offset];
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
const thing_part = thing[part];
|
|
21
|
+
|
|
22
|
+
if (typeof thing_part !== 'undefined') {
|
|
23
|
+
thing = thing_part;
|
|
22
24
|
} else {
|
|
23
25
|
|
|
24
26
|
const getter_name = `get${capitalize(part)}`;
|
|
@@ -42,11 +44,9 @@ export function write_property(root, parts, part_offset, part_count, value) {
|
|
|
42
44
|
if (typeof setter === "function") {
|
|
43
45
|
// resolve via setter
|
|
44
46
|
setter.call(thing, value);
|
|
45
|
-
} else if (thing.hasOwnProperty(last_part)) {
|
|
46
|
-
thing[last_part] = value;
|
|
47
47
|
} else {
|
|
48
|
-
//
|
|
49
|
-
|
|
48
|
+
// write directly to the field
|
|
49
|
+
thing[last_part] = value;
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -7,10 +7,8 @@ import { removeComponentsExcept } from "../ecs/util/removeComponentsExcept.js";
|
|
|
7
7
|
import { createSound, createTimer } from "../EntityCreator.js";
|
|
8
8
|
import Mesh from "../graphics/ecs/mesh/Mesh.js";
|
|
9
9
|
import Trail2D, { Trail2DFlags } from "../graphics/ecs/trail2d/Trail2D.js";
|
|
10
|
-
import { ParticleEmitterSystem } from "../graphics/particles/ecs/ParticleEmitterSystem.js";
|
|
11
10
|
import { ParticleEmitter } from "../graphics/particles/particular/engine/emitter/ParticleEmitter.js";
|
|
12
11
|
import { ParticleEmitterFlag } from "../graphics/particles/particular/engine/emitter/ParticleEmitterFlag.js";
|
|
13
|
-
import { distributeParticlesOnObject3D } from "../graphics/particles/particular/engine/utils/distributeParticlesOnObject3D.js";
|
|
14
12
|
import { SequenceBehavior } from "../intelligence/behavior/composite/SequenceBehavior.js";
|
|
15
13
|
import { BehaviorComponent } from "../intelligence/behavior/ecs/BehaviorComponent.js";
|
|
16
14
|
import { ActionBehavior } from "../intelligence/behavior/primitive/ActionBehavior.js";
|
|
@@ -118,124 +116,6 @@ export function stopEmitterAndNotifyOnceFinished(entity, ecd) {
|
|
|
118
116
|
}
|
|
119
117
|
|
|
120
118
|
|
|
121
|
-
/**
|
|
122
|
-
*
|
|
123
|
-
* @param {EntityManager} entityManager
|
|
124
|
-
* @param {EntityComponentDataset} ecd
|
|
125
|
-
* @param {number} entity
|
|
126
|
-
* @param {string} particles
|
|
127
|
-
* @returns {Promise<any>}
|
|
128
|
-
*/
|
|
129
|
-
export function removeEntityWithMeshParticlesEffect(
|
|
130
|
-
{
|
|
131
|
-
entityManager,
|
|
132
|
-
ecd,
|
|
133
|
-
entity,
|
|
134
|
-
particles = 'mesh-cloud-puff-0'
|
|
135
|
-
}
|
|
136
|
-
) {
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
*
|
|
140
|
-
* @type {ParticleEmitterSystem}
|
|
141
|
-
*/
|
|
142
|
-
const sPE = entityManager.getSystem(ParticleEmitterSystem);
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
*
|
|
146
|
-
* @type {ParticleEmitterLibrary}
|
|
147
|
-
*/
|
|
148
|
-
const emitterLibrary = sPE.library;
|
|
149
|
-
|
|
150
|
-
const emitter = emitterLibrary.create(particles);
|
|
151
|
-
|
|
152
|
-
//get entity mesh
|
|
153
|
-
|
|
154
|
-
const cMesh = ecd.getComponent(entity, Mesh);
|
|
155
|
-
|
|
156
|
-
if (cMesh !== undefined) {
|
|
157
|
-
if (cMesh.mesh !== null) {
|
|
158
|
-
const randomSeed = Math.random() * 1000000;
|
|
159
|
-
|
|
160
|
-
distributeParticlesOnObject3D(emitter, randomSeed, cMesh.mesh);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
//prevent further interactions
|
|
165
|
-
removeComponentsExcept(ecd, entity, [Mesh, ParticleEmitter, Trail2D, Transform]);
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
*
|
|
169
|
-
* @type {Transform}
|
|
170
|
-
*/
|
|
171
|
-
const originalTransform = ecd.getComponent(entity, Transform);
|
|
172
|
-
|
|
173
|
-
if (originalTransform === undefined) {
|
|
174
|
-
throw new Error(`entity ${entity} doesn't have Transform`);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
//create particle emitter
|
|
178
|
-
const effectBuilder = new EntityBuilder();
|
|
179
|
-
const effectEntity = effectBuilder
|
|
180
|
-
.add(emitter)
|
|
181
|
-
.add(originalTransform.clone())
|
|
182
|
-
.build(ecd);
|
|
183
|
-
|
|
184
|
-
Promise.all([
|
|
185
|
-
stopEntityAndNotifyWhenStopped(effectEntity, ecd)
|
|
186
|
-
])
|
|
187
|
-
.then(() => effectBuilder.destroy());
|
|
188
|
-
|
|
189
|
-
return stopEntityAndNotifyWhenStopped(entity, ecd)
|
|
190
|
-
.then(() => {
|
|
191
|
-
ecd.removeEntity(entity);
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
*
|
|
198
|
-
* @param {Engine} engine
|
|
199
|
-
* @param {EntityComponentDataset} ecd
|
|
200
|
-
* @param {number} entity
|
|
201
|
-
* @param {string} [particles]
|
|
202
|
-
* @param {string} [sound]
|
|
203
|
-
* @returns {Promise<any>}
|
|
204
|
-
*/
|
|
205
|
-
export function removeEntityGenericEffect(
|
|
206
|
-
{
|
|
207
|
-
engine,
|
|
208
|
-
ecd,
|
|
209
|
-
entity,
|
|
210
|
-
particles = 'cloud-puff',
|
|
211
|
-
sound = "data/sounds/effects/Magic_Game_Essentials/Magic_Vanish_3.wav"
|
|
212
|
-
}
|
|
213
|
-
) {
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
*
|
|
217
|
-
* @type {ParticleEmitterSystem}
|
|
218
|
-
*/
|
|
219
|
-
const sPE = engine.entityManager.getSystem(ParticleEmitterSystem);
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
*
|
|
223
|
-
* @type {ParticleEmitterLibrary}
|
|
224
|
-
*/
|
|
225
|
-
const emitterLibrary = sPE.library;
|
|
226
|
-
|
|
227
|
-
const emitter = emitterLibrary.create(particles);
|
|
228
|
-
|
|
229
|
-
const result = removeEntityWithEffect({
|
|
230
|
-
entity,
|
|
231
|
-
ecd,
|
|
232
|
-
emitter,
|
|
233
|
-
soundEffect: sound
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
return result;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
119
|
/**
|
|
240
120
|
*
|
|
241
121
|
* @param {number} entity
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { removeEntityWithEffect } from "./AnimationUtils.js";
|
|
2
|
+
import { ParticleEmitter } from "../graphics/particles/particular/engine/emitter/ParticleEmitter.js";
|
|
3
|
+
|
|
4
|
+
const lib = {
|
|
5
|
+
'cloud-puff': {
|
|
6
|
+
"position": {
|
|
7
|
+
"x": 56.41791044776119,
|
|
8
|
+
"y": -8.887834661270745,
|
|
9
|
+
"z": 223.65671641791042
|
|
10
|
+
},
|
|
11
|
+
"scale": {
|
|
12
|
+
"x": 1,
|
|
13
|
+
"y": 1,
|
|
14
|
+
"z": 1
|
|
15
|
+
},
|
|
16
|
+
"rotation": {
|
|
17
|
+
"x": 0,
|
|
18
|
+
"y": 0,
|
|
19
|
+
"z": 0,
|
|
20
|
+
"w": 1
|
|
21
|
+
},
|
|
22
|
+
"parameters": [
|
|
23
|
+
{
|
|
24
|
+
"name": "scale",
|
|
25
|
+
"itemSize": 1,
|
|
26
|
+
"defaultTrackValue": {
|
|
27
|
+
"itemSize": 1,
|
|
28
|
+
"data": [
|
|
29
|
+
1
|
|
30
|
+
],
|
|
31
|
+
"positions": [
|
|
32
|
+
0
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "color",
|
|
38
|
+
"itemSize": 4,
|
|
39
|
+
"defaultTrackValue": {
|
|
40
|
+
"itemSize": 4,
|
|
41
|
+
"data": [
|
|
42
|
+
1,
|
|
43
|
+
1,
|
|
44
|
+
1,
|
|
45
|
+
1
|
|
46
|
+
],
|
|
47
|
+
"positions": [
|
|
48
|
+
0
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"blendingMode": 0,
|
|
54
|
+
"layers": [
|
|
55
|
+
{
|
|
56
|
+
"imageURL": "data/textures/particle/smokeparticle.png",
|
|
57
|
+
"particleLife": {
|
|
58
|
+
"min": 1.2,
|
|
59
|
+
"max": 1.5
|
|
60
|
+
},
|
|
61
|
+
"particleSize": {
|
|
62
|
+
"min": 1,
|
|
63
|
+
"max": 1.2
|
|
64
|
+
},
|
|
65
|
+
"particleRotation": {
|
|
66
|
+
"min": 0,
|
|
67
|
+
"max": 0
|
|
68
|
+
},
|
|
69
|
+
"particleRotationSpeed": {
|
|
70
|
+
"min": 0,
|
|
71
|
+
"max": 0
|
|
72
|
+
},
|
|
73
|
+
"emissionShape": 1,
|
|
74
|
+
"emissionFrom": 1,
|
|
75
|
+
"emissionRate": 0,
|
|
76
|
+
"emissionImmediate": 25,
|
|
77
|
+
"parameterTracks": [
|
|
78
|
+
{
|
|
79
|
+
"name": "color",
|
|
80
|
+
"track": {
|
|
81
|
+
"itemSize": 4,
|
|
82
|
+
"data": [
|
|
83
|
+
0.9803921568627451,
|
|
84
|
+
0.9803921568627451,
|
|
85
|
+
0.9803921568627451,
|
|
86
|
+
0.3,
|
|
87
|
+
|
|
88
|
+
0.9882352941176471,
|
|
89
|
+
0.9882352941176471,
|
|
90
|
+
0.9882352941176471,
|
|
91
|
+
0.9880952380952381,
|
|
92
|
+
|
|
93
|
+
0.9882352941176471,
|
|
94
|
+
0.9882352941176471,
|
|
95
|
+
0.9882352941176471,
|
|
96
|
+
0.5,
|
|
97
|
+
|
|
98
|
+
0.9882352941176471,
|
|
99
|
+
0.9882352941176471,
|
|
100
|
+
0.9882352941176471,
|
|
101
|
+
0
|
|
102
|
+
],
|
|
103
|
+
"positions": [
|
|
104
|
+
0,
|
|
105
|
+
0.07,
|
|
106
|
+
0.8097826086956522,
|
|
107
|
+
1
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
],
|
|
112
|
+
"position": {
|
|
113
|
+
"x": 0,
|
|
114
|
+
"y": 0.6,
|
|
115
|
+
"z": 0
|
|
116
|
+
},
|
|
117
|
+
"scale": {
|
|
118
|
+
"x": 0.9,
|
|
119
|
+
"y": 0.5,
|
|
120
|
+
"z": 0.65
|
|
121
|
+
},
|
|
122
|
+
"particleVelocityDirection": {
|
|
123
|
+
"direction": {
|
|
124
|
+
"x": 0,
|
|
125
|
+
"y": 1,
|
|
126
|
+
"z": 0
|
|
127
|
+
},
|
|
128
|
+
"angle": 1.5
|
|
129
|
+
},
|
|
130
|
+
"particleSpeed": {
|
|
131
|
+
"min": 0.2,
|
|
132
|
+
"max": 0.5
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
*
|
|
141
|
+
* @param {Engine} engine
|
|
142
|
+
* @param {EntityComponentDataset} ecd
|
|
143
|
+
* @param {number} entity
|
|
144
|
+
* @param {string} [particles]
|
|
145
|
+
* @param {string} [sound]
|
|
146
|
+
* @returns {Promise<any>}
|
|
147
|
+
*/
|
|
148
|
+
export function removeEntityGenericEffect(
|
|
149
|
+
{
|
|
150
|
+
engine,
|
|
151
|
+
ecd,
|
|
152
|
+
entity,
|
|
153
|
+
particles = 'cloud-puff',
|
|
154
|
+
sound = "data/sounds/effects/Magic_Game_Essentials/Magic_Vanish_3.wav"
|
|
155
|
+
}
|
|
156
|
+
) {
|
|
157
|
+
|
|
158
|
+
const emitter = ParticleEmitter.fromJSON(lib[particles]);
|
|
159
|
+
|
|
160
|
+
const result = removeEntityWithEffect({
|
|
161
|
+
entity,
|
|
162
|
+
ecd,
|
|
163
|
+
emitter,
|
|
164
|
+
soundEffect: sound
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
return result;
|
|
168
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import Mesh from "../graphics/ecs/mesh/Mesh.js";
|
|
2
|
+
import { distributeParticlesOnObject3D } from "../graphics/particles/particular/engine/utils/distributeParticlesOnObject3D.js";
|
|
3
|
+
import { removeComponentsExcept } from "../ecs/util/removeComponentsExcept.js";
|
|
4
|
+
import { ParticleEmitter } from "../graphics/particles/particular/engine/emitter/ParticleEmitter.js";
|
|
5
|
+
import Trail2D from "../graphics/ecs/trail2d/Trail2D.js";
|
|
6
|
+
import { Transform } from "../ecs/transform/Transform.js";
|
|
7
|
+
import EntityBuilder from "../ecs/EntityBuilder.js";
|
|
8
|
+
import { stopEntityAndNotifyWhenStopped } from "./AnimatedActions.js";
|
|
9
|
+
|
|
10
|
+
const lib = {
|
|
11
|
+
'mesh-cloud-puff-0': {
|
|
12
|
+
"position": {
|
|
13
|
+
"x": 9.17416,
|
|
14
|
+
"y": -1.90031,
|
|
15
|
+
"z": 12.06082
|
|
16
|
+
},
|
|
17
|
+
"scale": {
|
|
18
|
+
"x": 1,
|
|
19
|
+
"y": 1,
|
|
20
|
+
"z": 1
|
|
21
|
+
},
|
|
22
|
+
"rotation": {
|
|
23
|
+
"x": 0,
|
|
24
|
+
"y": 0,
|
|
25
|
+
"z": 0,
|
|
26
|
+
"w": 1
|
|
27
|
+
},
|
|
28
|
+
"parameters": [
|
|
29
|
+
{
|
|
30
|
+
"name": "scale",
|
|
31
|
+
"itemSize": 1,
|
|
32
|
+
"defaultTrackValue": {
|
|
33
|
+
"itemSize": 1,
|
|
34
|
+
"data": [
|
|
35
|
+
1
|
|
36
|
+
],
|
|
37
|
+
"positions": [
|
|
38
|
+
0
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "color",
|
|
44
|
+
"itemSize": 4,
|
|
45
|
+
"defaultTrackValue": {
|
|
46
|
+
"itemSize": 4,
|
|
47
|
+
"data": [
|
|
48
|
+
1,
|
|
49
|
+
1,
|
|
50
|
+
1,
|
|
51
|
+
1
|
|
52
|
+
],
|
|
53
|
+
"positions": [
|
|
54
|
+
0
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
"preWarm": false,
|
|
60
|
+
"readDepth": true,
|
|
61
|
+
"softDepth": true,
|
|
62
|
+
"blendingMode": 0,
|
|
63
|
+
"layers": [
|
|
64
|
+
{
|
|
65
|
+
"imageURL": "data/textures/particle/smokeparticle.png",
|
|
66
|
+
"particleLife": {
|
|
67
|
+
"min": 0.6,
|
|
68
|
+
"max": 1.2
|
|
69
|
+
},
|
|
70
|
+
"particleSize": {
|
|
71
|
+
"min": 0.2,
|
|
72
|
+
"max": 0.3
|
|
73
|
+
},
|
|
74
|
+
"particleRotation": {
|
|
75
|
+
"min": 0,
|
|
76
|
+
"max": 0
|
|
77
|
+
},
|
|
78
|
+
"particleRotationSpeed": {
|
|
79
|
+
"min": 0,
|
|
80
|
+
"max": 0
|
|
81
|
+
},
|
|
82
|
+
"emissionShape": 1,
|
|
83
|
+
"emissionFrom": 1,
|
|
84
|
+
"emissionRate": 0,
|
|
85
|
+
"emissionImmediate": 1200,
|
|
86
|
+
"parameterTracks": [
|
|
87
|
+
{
|
|
88
|
+
"name": "color",
|
|
89
|
+
"track": {
|
|
90
|
+
"itemSize": 4,
|
|
91
|
+
"data": [
|
|
92
|
+
0.9803921568627451,
|
|
93
|
+
0.9803921568627451,
|
|
94
|
+
0.9803921568627451,
|
|
95
|
+
0.3,
|
|
96
|
+
0.9882352941176471,
|
|
97
|
+
0.9882352941176471,
|
|
98
|
+
0.9882352941176471,
|
|
99
|
+
0.265,
|
|
100
|
+
0.9882352941176471,
|
|
101
|
+
0.9882352941176471,
|
|
102
|
+
0.9882352941176471,
|
|
103
|
+
0
|
|
104
|
+
],
|
|
105
|
+
"positions": [
|
|
106
|
+
0,
|
|
107
|
+
0.7957639171068672,
|
|
108
|
+
1
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
],
|
|
113
|
+
"position": {
|
|
114
|
+
"x": 0,
|
|
115
|
+
"y": 0.6,
|
|
116
|
+
"z": 0
|
|
117
|
+
},
|
|
118
|
+
"scale": {
|
|
119
|
+
"x": 0.9,
|
|
120
|
+
"y": 0.5,
|
|
121
|
+
"z": 0.65
|
|
122
|
+
},
|
|
123
|
+
"particleVelocityDirection": {
|
|
124
|
+
"direction": {
|
|
125
|
+
"x": 0,
|
|
126
|
+
"y": 1,
|
|
127
|
+
"z": 0
|
|
128
|
+
},
|
|
129
|
+
"angle": 0
|
|
130
|
+
},
|
|
131
|
+
"particleSpeed": {
|
|
132
|
+
"min": 0.6,
|
|
133
|
+
"max": 1.1
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
*
|
|
142
|
+
* @param {EntityManager} entityManager
|
|
143
|
+
* @param {EntityComponentDataset} ecd
|
|
144
|
+
* @param {number} entity
|
|
145
|
+
* @param {string} particles
|
|
146
|
+
* @returns {Promise<any>}
|
|
147
|
+
*/
|
|
148
|
+
export function removeEntityWithMeshParticlesEffect(
|
|
149
|
+
{
|
|
150
|
+
entityManager,
|
|
151
|
+
ecd,
|
|
152
|
+
entity,
|
|
153
|
+
particles = 'mesh-cloud-puff-0'
|
|
154
|
+
}
|
|
155
|
+
) {
|
|
156
|
+
|
|
157
|
+
const emitter = ParticleEmitter.fromJSON(lib[particles]);
|
|
158
|
+
|
|
159
|
+
//get entity mesh
|
|
160
|
+
|
|
161
|
+
const cMesh = ecd.getComponent(entity, Mesh);
|
|
162
|
+
|
|
163
|
+
if (cMesh !== undefined) {
|
|
164
|
+
if (cMesh.mesh !== null) {
|
|
165
|
+
const randomSeed = Math.random() * 1000000;
|
|
166
|
+
|
|
167
|
+
distributeParticlesOnObject3D(emitter, randomSeed, cMesh.mesh);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
//prevent further interactions
|
|
172
|
+
removeComponentsExcept(ecd, entity, [Mesh, ParticleEmitter, Trail2D, Transform]);
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
*
|
|
176
|
+
* @type {Transform}
|
|
177
|
+
*/
|
|
178
|
+
const originalTransform = ecd.getComponent(entity, Transform);
|
|
179
|
+
|
|
180
|
+
if (originalTransform === undefined) {
|
|
181
|
+
throw new Error(`entity ${entity} doesn't have Transform`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
//create particle emitter
|
|
185
|
+
const effectBuilder = new EntityBuilder();
|
|
186
|
+
const effectEntity = effectBuilder
|
|
187
|
+
.add(emitter)
|
|
188
|
+
.add(originalTransform.clone())
|
|
189
|
+
.build(ecd);
|
|
190
|
+
|
|
191
|
+
Promise.all([
|
|
192
|
+
stopEntityAndNotifyWhenStopped(effectEntity, ecd)
|
|
193
|
+
])
|
|
194
|
+
.then(() => effectBuilder.destroy());
|
|
195
|
+
|
|
196
|
+
return stopEntityAndNotifyWhenStopped(entity, ecd)
|
|
197
|
+
.then(() => {
|
|
198
|
+
ecd.removeEntity(entity);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
}
|
|
@@ -4,7 +4,6 @@ import { ParticularEngine } from "../particular/engine/ParticularEngine.js";
|
|
|
4
4
|
import { Transform } from "../../../ecs/transform/Transform.js";
|
|
5
5
|
import { ParticleEmitterFlag } from "../particular/engine/emitter/ParticleEmitterFlag.js";
|
|
6
6
|
import { RenderPassType } from "../../render/RenderPassType.js";
|
|
7
|
-
import { ParticleEmitterLibrary } from "../ParticleEmitterLibrary.js";
|
|
8
7
|
import { ImageRGBADataLoader } from "../../../asset/loaders/image/ImageRGBADataLoader.js";
|
|
9
8
|
import { StandardFrameBuffers } from "../../StandardFrameBuffers.js";
|
|
10
9
|
import { assert } from "../../../../core/assert.js";
|
|
@@ -15,18 +14,9 @@ import { assert } from "../../../../core/assert.js";
|
|
|
15
14
|
* @returns {Group|Object3D}
|
|
16
15
|
*/
|
|
17
16
|
function extractRenderable(emitter) {
|
|
18
|
-
|
|
19
|
-
|
|
20
17
|
return emitter.mesh;
|
|
21
18
|
}
|
|
22
19
|
|
|
23
|
-
/**
|
|
24
|
-
*
|
|
25
|
-
* @param {ParticleEmitter} emitter
|
|
26
|
-
*/
|
|
27
|
-
function putEmitterToSleep(emitter) {
|
|
28
|
-
emitter.setFlag(ParticleEmitterFlag.Sleeping);
|
|
29
|
-
}
|
|
30
20
|
|
|
31
21
|
export class ParticleEmitterSystem extends System {
|
|
32
22
|
/**
|
|
@@ -73,20 +63,9 @@ export class ParticleEmitterSystem extends System {
|
|
|
73
63
|
*/
|
|
74
64
|
this.bvh = null;
|
|
75
65
|
|
|
76
|
-
/**
|
|
77
|
-
* @deprecated Use "Effect" API to achieve the same results
|
|
78
|
-
* @type {ParticleEmitterLibrary}
|
|
79
|
-
*/
|
|
80
|
-
this.__library = new ParticleEmitterLibrary(engine.assetManager);
|
|
81
|
-
|
|
82
66
|
this.__handlers = [];
|
|
83
67
|
}
|
|
84
68
|
|
|
85
|
-
get library() {
|
|
86
|
-
console.warn('Deprecated, use "Effect" API to achieve the same results');
|
|
87
|
-
return this.__library;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
69
|
get componentClass() {
|
|
91
70
|
return ParticleEmitter;
|
|
92
71
|
}
|
|
@@ -208,7 +187,7 @@ export class ParticleEmitterSystem extends System {
|
|
|
208
187
|
|
|
209
188
|
graphicsEngine.on.preRender.add(preRenderHook);
|
|
210
189
|
|
|
211
|
-
|
|
190
|
+
readyCallback();
|
|
212
191
|
}
|
|
213
192
|
|
|
214
193
|
shutdown(entityManager, readyCallback, errorCallback) {
|
|
@@ -296,8 +296,8 @@ export class ParameterLookupTable {
|
|
|
296
296
|
//special case, all values are the same
|
|
297
297
|
return computeHashIntegerArray(valueMin);
|
|
298
298
|
} else {
|
|
299
|
-
const dataHash = computeHashFloatArray(this.data
|
|
300
|
-
const positionHash = computeHashFloatArray(this.positions
|
|
299
|
+
const dataHash = computeHashFloatArray(this.data);
|
|
300
|
+
const positionHash = computeHashFloatArray(this.positions);
|
|
301
301
|
|
|
302
302
|
return computeHashIntegerArray(dataHash, positionHash, this.itemSize);
|
|
303
303
|
}
|
|
@@ -3,6 +3,7 @@ import { DataType2TypedArrayConstructorMapping } from "../../../../../../../core
|
|
|
3
3
|
import { array_copy } from "../../../../../../../core/collection/array/copyArray.js";
|
|
4
4
|
import { min2 } from "../../../../../../../core/math/min2.js";
|
|
5
5
|
import { assert } from "../../../../../../../core/assert.js";
|
|
6
|
+
import { ParameterLookupTable } from "../../parameter/ParameterLookupTable.js";
|
|
6
7
|
|
|
7
8
|
export class AttributeValue {
|
|
8
9
|
constructor() {
|
|
@@ -142,4 +143,57 @@ export class AttributeValue {
|
|
|
142
143
|
read_value(destination) {
|
|
143
144
|
array_copy(this.__value, 0, destination, 0, this.spec.itemSize);
|
|
144
145
|
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
*
|
|
149
|
+
* @param {number[]} [value]
|
|
150
|
+
* @param {Object} [lookup]
|
|
151
|
+
* @param {number} [lookup_value]
|
|
152
|
+
*/
|
|
153
|
+
fromJSON({
|
|
154
|
+
value,
|
|
155
|
+
lookup,
|
|
156
|
+
lookup_value
|
|
157
|
+
}) {
|
|
158
|
+
|
|
159
|
+
if (value !== undefined) {
|
|
160
|
+
if (Array.isArray(value)) {
|
|
161
|
+
|
|
162
|
+
if (lookup !== undefined) {
|
|
163
|
+
console.warn("Both 'lookup' and 'value' were specified, expected one or the other. Ignoring the value attribute.");
|
|
164
|
+
} else {
|
|
165
|
+
this.write_value(value);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
} else {
|
|
169
|
+
throw new Error(`Expected 'value' to be an array, instead got something else (=${value})`);
|
|
170
|
+
}
|
|
171
|
+
} else {
|
|
172
|
+
this.__value = [];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (lookup !== undefined) {
|
|
176
|
+
const lut = new ParameterLookupTable();
|
|
177
|
+
|
|
178
|
+
lut.fromJSON(lookup);
|
|
179
|
+
|
|
180
|
+
this.lookup = lut;
|
|
181
|
+
} else {
|
|
182
|
+
this.lookup = null;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (lookup_value !== undefined) {
|
|
186
|
+
assert.isNumber(lookup_value, 'lookup_value');
|
|
187
|
+
assert.isFiniteNumber(lookup_value, 'lookup_value');
|
|
188
|
+
|
|
189
|
+
if (lookup === undefined) {
|
|
190
|
+
console.warn("found 'lookup_value' attribute, but no 'lookup' table. Ignoring lookup value");
|
|
191
|
+
} else {
|
|
192
|
+
this.lookup_value = lookup_value;
|
|
193
|
+
}
|
|
194
|
+
} else if (lookup !== undefined) {
|
|
195
|
+
// supply a default lookup value
|
|
196
|
+
this.lookup_value = 0;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
145
199
|
}
|
|
@@ -12,6 +12,7 @@ import { AttributeValue } from "./AttributeValue.js";
|
|
|
12
12
|
import { PARTICULAR_PARTICLE_SPECIFICATION } from "../../emitter/PARTICULAR_PARTICLE_SPECIFICATION.js";
|
|
13
13
|
import { SerializationMetadata } from "../../../../../../ecs/components/SerializationMetadata.js";
|
|
14
14
|
import { UnitCubeShape3D } from "../../../../../../../core/geom/3d/shape/UnitCubeShape3D.js";
|
|
15
|
+
import { shape_from_json } from "../../../../../../../core/geom/3d/shape/json/shape_from_json.js";
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
*
|
|
@@ -154,28 +155,13 @@ export class ParticleVolume {
|
|
|
154
155
|
"track": {
|
|
155
156
|
"itemSize": 4,
|
|
156
157
|
"data": [
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
0.803921568627451,
|
|
162
|
-
0.803921568627451,
|
|
163
|
-
0.803921568627451,
|
|
164
|
-
0.28160919540229884,
|
|
165
|
-
0.803921568627451,
|
|
166
|
-
0.803921568627451,
|
|
167
|
-
0.803921568627451,
|
|
168
|
-
0.21264367816091953,
|
|
169
|
-
0.803921568627451,
|
|
170
|
-
0.803921568627451,
|
|
171
|
-
0.803921568627451,
|
|
172
|
-
0
|
|
158
|
+
1,
|
|
159
|
+
1,
|
|
160
|
+
1,
|
|
161
|
+
1,
|
|
173
162
|
],
|
|
174
163
|
"positions": [
|
|
175
|
-
0
|
|
176
|
-
0.18085106382978725,
|
|
177
|
-
0.7074468085106383,
|
|
178
|
-
1
|
|
164
|
+
0
|
|
179
165
|
]
|
|
180
166
|
}
|
|
181
167
|
},
|
|
@@ -335,6 +321,50 @@ export class ParticleVolume {
|
|
|
335
321
|
attributes.size.write_value_silent([particle_size]);
|
|
336
322
|
}
|
|
337
323
|
|
|
324
|
+
/**
|
|
325
|
+
*
|
|
326
|
+
* @param {number} density
|
|
327
|
+
* @param {boolean} [is_density_size_adjusted]
|
|
328
|
+
* @param {number} [particle_size]
|
|
329
|
+
* @param {Object} shape
|
|
330
|
+
* @param {boolean} [is_sorted]
|
|
331
|
+
* @param {string} sprite
|
|
332
|
+
* @param {Object<Object>} [attributes]
|
|
333
|
+
*/
|
|
334
|
+
fromJSON({
|
|
335
|
+
density,
|
|
336
|
+
is_density_size_adjusted = true,
|
|
337
|
+
particle_size = 1,
|
|
338
|
+
shape,
|
|
339
|
+
is_sorted = true,
|
|
340
|
+
sprite,
|
|
341
|
+
attributes = {}
|
|
342
|
+
}) {
|
|
343
|
+
|
|
344
|
+
const shape_object = shape_from_json(shape);
|
|
345
|
+
|
|
346
|
+
const actual_density = is_density_size_adjusted ? density / particle_size : density;
|
|
347
|
+
|
|
348
|
+
this.from({
|
|
349
|
+
density: actual_density,
|
|
350
|
+
shape: shape_object,
|
|
351
|
+
particle_size,
|
|
352
|
+
sort: is_sorted,
|
|
353
|
+
sprite
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
for (const attributesKey in attributes) {
|
|
357
|
+
const attribute_object = this.attributes[attributesKey];
|
|
358
|
+
|
|
359
|
+
if (attribute_object === undefined) {
|
|
360
|
+
console.warn(`No '${attributesKey}' attribute, skipping`);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const attribute_json = attributes[attributesKey];
|
|
364
|
+
attribute_object.fromJSON(attribute_json);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
338
368
|
/**
|
|
339
369
|
*
|
|
340
370
|
* @private
|
|
@@ -328,9 +328,8 @@ async function sample_scene_0(engine) {
|
|
|
328
328
|
ecd: ecd,
|
|
329
329
|
lut: heatmap_lut_0,
|
|
330
330
|
shape: UnionShape3D.from([
|
|
331
|
-
TransformedShape3D.from_m4(new UnitCubeShape3D(),
|
|
332
|
-
TransformedShape3D.from_m4(new UnitCubeShape3D(),
|
|
333
|
-
TransformedShape3D.from_m4(new UnitCubeShape3D(), [23.762890107594952, 0, 0, 0, 0, 2.812495250139616, 0, 0, 0, 0, 34.57956316503163, 0, 55.436098243647756, 1.568241402881399, 113.46988143189215, 1])
|
|
331
|
+
TransformedShape3D.from_m4(new UnitCubeShape3D(), mat_from_aabb3(new AABB3(67.73, 0, 89, 115.84, 3, 118.34))),
|
|
332
|
+
TransformedShape3D.from_m4(new UnitCubeShape3D(), mat_from_aabb3(new AABB3(98, 0, 76.5, 109.5, 3, 89)))
|
|
334
333
|
]),
|
|
335
334
|
particle_size: 2,
|
|
336
335
|
density: 1,
|
|
@@ -40,7 +40,7 @@ export class AmbientOcclusionPostProcessEffect extends EnginePlugin {
|
|
|
40
40
|
defines.PERSPECTIVE_CAMERA = 1;
|
|
41
41
|
|
|
42
42
|
// More samples = better quality
|
|
43
|
-
defines.NUM_SAMPLES =
|
|
43
|
+
defines.NUM_SAMPLES = 13;
|
|
44
44
|
|
|
45
45
|
// More rings = better quality
|
|
46
46
|
defines.NUM_RINGS = 4;
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"productName": "Meep",
|
|
6
6
|
"description": "production-ready JavaScript game engine based on Entity Component System Architecture",
|
|
7
7
|
"author": "Alexander Goldring",
|
|
8
|
-
"version": "2.33.
|
|
8
|
+
"version": "2.33.55",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|