@carbonenginejs/runtime-utils 0.1.1 → 0.1.3
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/LICENSE +21 -21
- package/NOTICE +23 -23
- package/README.md +69 -69
- package/THIRD-PARTY-NOTICES.md +64 -64
- package/docs/README.md +74 -73
- package/docs/architecture.md +101 -101
- package/docs/concepts/foundation-consolidation.md +85 -85
- package/docs/concepts/model-lifecycle.md +111 -0
- package/docs/const-kb.md +85 -87
- package/docs/core-types/DECORATOR-TODOS.md +25 -25
- package/docs/core-types/README.md +229 -168
- package/docs/reference/api.md +105 -102
- package/docs/reference/classes/README.md +135 -135
- package/package.json +139 -139
- package/src/arrays.js +5 -5
- package/src/audio/audioFormats.js +34 -34
- package/src/audio/index.js +1 -1
- package/src/box3.js +331 -331
- package/src/bytes.js +56 -56
- package/src/compression.js +56 -56
- package/src/constants/index.js +7 -7
- package/src/constants/trinity.js +13 -13
- package/src/constants.js +15 -15
- package/src/curve.js +79 -79
- package/src/d3d/dxgiFormats.js +46 -46
- package/src/d3d/index.js +2 -2
- package/src/d3d/primitiveTopology.js +11 -11
- package/src/document/CjsCarbonDocument.js +212 -212
- package/src/document/CjsClassRegistry.js +373 -373
- package/src/document/CjsDocumentDehydrator.js +142 -142
- package/src/document/CjsDocumentHydrator.js +156 -156
- package/src/document/CjsStructRegistry.js +348 -348
- package/src/document/hydrationAdapter.js +129 -129
- package/src/document/index.js +6 -6
- package/src/errors/CjsError.js +286 -286
- package/src/errors/index.js +5 -5
- package/src/geometry/box.js +22 -22
- package/src/geometry/cylinder.js +22 -22
- package/src/geometry/helpers/earcut.js +1 -1
- package/src/geometry/helpers/misc.js +3 -3
- package/src/geometry/index.js +8 -8
- package/src/geometry/json.js +67 -67
- package/src/geometry/lathe.js +44 -44
- package/src/geometry/plane.js +14 -14
- package/src/geometry/shape.js +4 -4
- package/src/geometry/sphere.js +24 -24
- package/src/geometry/torus.js +14 -14
- package/src/graphics/colorSpaces.js +22 -22
- package/src/graphics/index.js +4 -4
- package/src/graphics/pixelFormats.js +158 -158
- package/src/graphics/textureDimensions.js +22 -22
- package/src/graphics/trinityEnums.js +87 -87
- package/src/index.js +62 -62
- package/src/is.js +108 -46
- package/src/json.js +23 -23
- package/src/lifecycle/CjsLifecycleState.js +77 -77
- package/src/lifecycle/index.js +1 -1
- package/src/lne3.js +70 -70
- package/src/lookup.js +48 -48
- package/src/mat3.js +51 -51
- package/src/mat4.js +699 -699
- package/src/math/index.js +25 -25
- package/src/math/scalar.js +63 -63
- package/src/media/index.js +1 -1
- package/src/media/mediaTypes.js +50 -50
- package/src/mesh.js +424 -424
- package/src/model/CjsEventEmitter.js +333 -333
- package/src/model/CjsModel.js +1589 -1544
- package/src/model/CjsModelState.js +72 -72
- package/src/model/index.js +4 -4
- package/src/model/sourceRecordUtils.js +54 -54
- package/src/noise.js +310 -310
- package/src/num.js +827 -827
- package/src/object.js +39 -39
- package/src/path.js +53 -53
- package/src/pln.js +125 -125
- package/src/pool.js +9 -9
- package/src/quat.js +144 -144
- package/src/ray3.js +188 -188
- package/src/renderContext/formats.js +145 -145
- package/src/renderContext/index.js +5 -5
- package/src/renderContext/presentation.js +125 -125
- package/src/renderContext/resources.js +27 -27
- package/src/renderContext/upscaling.js +22 -22
- package/src/renderContext/window.js +20 -20
- package/src/runtime/CjsRuntimeState.js +50 -50
- package/src/schema/CjsSchema.js +555 -318
- package/src/schema/index.js +4 -4
- package/src/shader/index.js +1 -1
- package/src/shader/shaderStages.js +37 -37
- package/src/sph3.js +181 -181
- package/src/tangent.js +288 -288
- package/src/text.js +40 -40
- package/src/tri3.js +98 -98
- package/src/types/carbonTypes.js +635 -635
- package/src/types/index.js +2 -2
- package/src/utils.js +58 -58
- package/src/validation.js +46 -46
- package/src/vec2.js +229 -229
- package/src/vec3.js +1188 -1172
- package/src/vec4.js +347 -347
- package/src/vertex.js +108 -108
- package/src/webgpu/index.js +1 -1
- package/src/webgpu/textureFormats.js +121 -121
package/src/geometry/cylinder.js
CHANGED
|
@@ -17,18 +17,18 @@ export function createCylinder(options = {})
|
|
|
17
17
|
openEnded = false,
|
|
18
18
|
thetaStart = 0,
|
|
19
19
|
thetaLength = Math.PI * 2
|
|
20
|
-
} = options;
|
|
21
|
-
|
|
22
|
-
if (![ radiusTop, radiusBottom, height, thetaStart, thetaLength ].every(Number.isFinite) ||
|
|
23
|
-
height === 0 ||
|
|
24
|
-
thetaLength === 0 ||
|
|
25
|
-
(radiusTop === 0 && radiusBottom === 0))
|
|
26
|
-
{
|
|
27
|
-
throw new Error("Invalid cylinder dimensions");
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
radialSegments = Math.max(3, Math.floor(Number.isFinite(radialSegments) ? radialSegments : 32));
|
|
31
|
-
heightSegments = Math.max(1, Math.floor(Number.isFinite(heightSegments) ? heightSegments : 1));
|
|
20
|
+
} = options;
|
|
21
|
+
|
|
22
|
+
if (![ radiusTop, radiusBottom, height, thetaStart, thetaLength ].every(Number.isFinite) ||
|
|
23
|
+
height === 0 ||
|
|
24
|
+
thetaLength === 0 ||
|
|
25
|
+
(radiusTop === 0 && radiusBottom === 0))
|
|
26
|
+
{
|
|
27
|
+
throw new Error("Invalid cylinder dimensions");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
radialSegments = Math.max(3, Math.floor(Number.isFinite(radialSegments) ? radialSegments : 32));
|
|
31
|
+
heightSegments = Math.max(1, Math.floor(Number.isFinite(heightSegments) ? heightSegments : 1));
|
|
32
32
|
|
|
33
33
|
// buffers
|
|
34
34
|
const
|
|
@@ -102,20 +102,20 @@ export function createCylinder(options = {})
|
|
|
102
102
|
// generate indices
|
|
103
103
|
for (let x = 0; x < radialSegments; x++)
|
|
104
104
|
{
|
|
105
|
-
for (let y = 0; y < heightSegments; y++)
|
|
106
|
-
{
|
|
105
|
+
for (let y = 0; y < heightSegments; y++)
|
|
106
|
+
{
|
|
107
107
|
// we use the index array to access the correct indices
|
|
108
108
|
const
|
|
109
109
|
a = indexArray[y][x],
|
|
110
110
|
b = indexArray[y + 1][x],
|
|
111
|
-
c = indexArray[y + 1][x + 1],
|
|
112
|
-
d = indexArray[y][x + 1],
|
|
113
|
-
upperRadius = (y / heightSegments) * (radiusBottom - radiusTop) + radiusTop,
|
|
114
|
-
lowerRadius = ((y + 1) / heightSegments) * (radiusBottom - radiusTop) + radiusTop;
|
|
115
|
-
|
|
116
|
-
// faces
|
|
117
|
-
if (upperRadius !== 0) indices.push(a, b, d);
|
|
118
|
-
if (lowerRadius !== 0) indices.push(b, c, d);
|
|
111
|
+
c = indexArray[y + 1][x + 1],
|
|
112
|
+
d = indexArray[y][x + 1],
|
|
113
|
+
upperRadius = (y / heightSegments) * (radiusBottom - radiusTop) + radiusTop,
|
|
114
|
+
lowerRadius = ((y + 1) / heightSegments) * (radiusBottom - radiusTop) + radiusTop;
|
|
115
|
+
|
|
116
|
+
// faces
|
|
117
|
+
if (upperRadius !== 0) indices.push(a, b, d);
|
|
118
|
+
if (lowerRadius !== 0) indices.push(b, c, d);
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
}
|
|
@@ -312,7 +312,7 @@ function eliminateHoles(data, holeIndices, outerNode, dim)
|
|
|
312
312
|
|
|
313
313
|
queue.sort(compareX);
|
|
314
314
|
|
|
315
|
-
// handle holes from left to right
|
|
315
|
+
// handle holes from left to right
|
|
316
316
|
for (i = 0; i < queue.length; i++)
|
|
317
317
|
{
|
|
318
318
|
outerNode = eliminateHole(queue[i], outerNode);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { num } from "../../num.js";
|
|
2
|
-
import { triangulate } from "./earcut.js";
|
|
1
|
+
import { num } from "../../num.js";
|
|
2
|
+
import { triangulate } from "./earcut.js";
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
// Ported from ThreeJS
|
|
@@ -15,7 +15,7 @@ export function getShapeArea(points)
|
|
|
15
15
|
let a = 0.0;
|
|
16
16
|
for (let p = n - 1, q = 0; q < n; p = q++)
|
|
17
17
|
{
|
|
18
|
-
a += points[p][0] * points[q][1] - points[q][0] * points[p][1];
|
|
18
|
+
a += points[p][0] * points[q][1] - points[q][0] * points[p][1];
|
|
19
19
|
}
|
|
20
20
|
return a * 0.5;
|
|
21
21
|
}
|
package/src/geometry/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export * from "./box.js";
|
|
2
|
-
export * from "./cylinder.js";
|
|
3
|
-
export * from "./plane.js";
|
|
4
|
-
export * from "./shape.js";
|
|
5
|
-
export * from "./sphere.js";
|
|
6
|
-
export * from "./torus.js";
|
|
7
|
-
export * from "./json.js";
|
|
8
|
-
export * from "./lathe.js";
|
|
1
|
+
export * from "./box.js";
|
|
2
|
+
export * from "./cylinder.js";
|
|
3
|
+
export * from "./plane.js";
|
|
4
|
+
export * from "./shape.js";
|
|
5
|
+
export * from "./sphere.js";
|
|
6
|
+
export * from "./torus.js";
|
|
7
|
+
export * from "./json.js";
|
|
8
|
+
export * from "./lathe.js";
|
package/src/geometry/json.js
CHANGED
|
@@ -21,63 +21,63 @@ function isAreaLike(value)
|
|
|
21
21
|
* @throw If required data is not provided
|
|
22
22
|
* @returns {Object}
|
|
23
23
|
*/
|
|
24
|
-
export function toJSON(indices, positions, uvs, normals, areas, tangents)
|
|
25
|
-
{
|
|
24
|
+
export function toJSON(indices, positions, uvs, normals, areas, tangents)
|
|
25
|
+
{
|
|
26
26
|
if (!indices || !positions || !uvs || !indices.length || !positions.length || !uvs.length)
|
|
27
27
|
{
|
|
28
28
|
throw new Error("Invalid inputs");
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
if (isAreaLike(normals))
|
|
31
|
+
if (isAreaLike(normals))
|
|
32
32
|
{
|
|
33
33
|
const temp = areas;
|
|
34
34
|
areas = normals;
|
|
35
|
-
normals = temp;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const vertexCount = positions.length / 3;
|
|
39
|
-
if (!Number.isInteger(vertexCount) ||
|
|
40
|
-
indices.length % 3 !== 0 ||
|
|
41
|
-
uvs.length !== vertexCount * 2)
|
|
42
|
-
{
|
|
43
|
-
throw new Error("Invalid geometry channel lengths");
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
for (let i = 0; i < indices.length; i++)
|
|
47
|
-
{
|
|
48
|
-
if (!Number.isInteger(indices[i]) || indices[i] < 0 || indices[i] >= vertexCount)
|
|
49
|
-
{
|
|
50
|
-
throw new Error(`Invalid vertex index at ${i}`);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (normals && normals.length && normals.length !== positions.length)
|
|
55
|
-
{
|
|
56
|
-
throw new Error("Invalid normal channel length");
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (tangents && tangents.length &&
|
|
60
|
-
tangents.length !== vertexCount * 3 &&
|
|
61
|
-
tangents.length !== vertexCount * 4)
|
|
62
|
-
{
|
|
63
|
-
throw new Error("Invalid tangent channel length");
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
areas = toArray(areas && areas.length !== 0 ? areas : { start: 0, count: indices.length });
|
|
67
|
-
for (const area of areas)
|
|
68
|
-
{
|
|
69
|
-
if (!area ||
|
|
70
|
-
!Number.isInteger(area.start) ||
|
|
71
|
-
!Number.isInteger(area.count) ||
|
|
72
|
-
area.start < 0 ||
|
|
73
|
-
area.count < 0 ||
|
|
74
|
-
area.start % 3 !== 0 ||
|
|
75
|
-
area.count % 3 !== 0 ||
|
|
76
|
-
area.start + area.count > indices.length)
|
|
77
|
-
{
|
|
78
|
-
throw new Error("Invalid geometry area");
|
|
79
|
-
}
|
|
80
|
-
}
|
|
35
|
+
normals = temp;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const vertexCount = positions.length / 3;
|
|
39
|
+
if (!Number.isInteger(vertexCount) ||
|
|
40
|
+
indices.length % 3 !== 0 ||
|
|
41
|
+
uvs.length !== vertexCount * 2)
|
|
42
|
+
{
|
|
43
|
+
throw new Error("Invalid geometry channel lengths");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
for (let i = 0; i < indices.length; i++)
|
|
47
|
+
{
|
|
48
|
+
if (!Number.isInteger(indices[i]) || indices[i] < 0 || indices[i] >= vertexCount)
|
|
49
|
+
{
|
|
50
|
+
throw new Error(`Invalid vertex index at ${i}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (normals && normals.length && normals.length !== positions.length)
|
|
55
|
+
{
|
|
56
|
+
throw new Error("Invalid normal channel length");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (tangents && tangents.length &&
|
|
60
|
+
tangents.length !== vertexCount * 3 &&
|
|
61
|
+
tangents.length !== vertexCount * 4)
|
|
62
|
+
{
|
|
63
|
+
throw new Error("Invalid tangent channel length");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
areas = toArray(areas && areas.length !== 0 ? areas : { start: 0, count: indices.length });
|
|
67
|
+
for (const area of areas)
|
|
68
|
+
{
|
|
69
|
+
if (!area ||
|
|
70
|
+
!Number.isInteger(area.start) ||
|
|
71
|
+
!Number.isInteger(area.count) ||
|
|
72
|
+
area.start < 0 ||
|
|
73
|
+
area.count < 0 ||
|
|
74
|
+
area.start % 3 !== 0 ||
|
|
75
|
+
area.count % 3 !== 0 ||
|
|
76
|
+
area.start + area.count > indices.length)
|
|
77
|
+
{
|
|
78
|
+
throw new Error("Invalid geometry area");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
81
|
|
|
82
82
|
if (!normals || !normals.length)
|
|
83
83
|
{
|
|
@@ -101,24 +101,24 @@ export function toJSON(indices, positions, uvs, normals, areas, tangents)
|
|
|
101
101
|
binormal: null,
|
|
102
102
|
blendIndice: null,
|
|
103
103
|
blendWeight: null
|
|
104
|
-
},
|
|
105
|
-
indices: areas.map(area =>
|
|
106
|
-
{
|
|
107
|
-
const faces = indices.slice(area.start, area.start + area.count);
|
|
108
|
-
const requires32Bit = faces.some(index => index > 0xffff);
|
|
109
|
-
const bytesPerIndex = area.bytesPerIndex ?? (requires32Bit ? 4 : 2);
|
|
110
|
-
if ((bytesPerIndex !== 2 && bytesPerIndex !== 4) ||
|
|
111
|
-
(bytesPerIndex === 2 && requires32Bit))
|
|
112
|
-
{
|
|
113
|
-
throw new Error("Invalid bytes per index");
|
|
114
|
-
}
|
|
115
|
-
return {
|
|
116
|
-
bytesPerIndex,
|
|
117
|
-
start: area.start,
|
|
118
|
-
count: area.count,
|
|
119
|
-
faces
|
|
120
|
-
};
|
|
121
|
-
})
|
|
104
|
+
},
|
|
105
|
+
indices: areas.map(area =>
|
|
106
|
+
{
|
|
107
|
+
const faces = indices.slice(area.start, area.start + area.count);
|
|
108
|
+
const requires32Bit = faces.some(index => index > 0xffff);
|
|
109
|
+
const bytesPerIndex = area.bytesPerIndex ?? (requires32Bit ? 4 : 2);
|
|
110
|
+
if ((bytesPerIndex !== 2 && bytesPerIndex !== 4) ||
|
|
111
|
+
(bytesPerIndex === 2 && requires32Bit))
|
|
112
|
+
{
|
|
113
|
+
throw new Error("Invalid bytes per index");
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
bytesPerIndex,
|
|
117
|
+
start: area.start,
|
|
118
|
+
count: area.count,
|
|
119
|
+
faces
|
|
120
|
+
};
|
|
121
|
+
})
|
|
122
122
|
} ]
|
|
123
123
|
};
|
|
124
124
|
}
|
package/src/geometry/lathe.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { num } from "../num.js";
|
|
2
|
-
import { vec2 } from "../vec2.js";
|
|
3
|
-
import { vec3 } from "../vec3.js";
|
|
1
|
+
import { num } from "../num.js";
|
|
2
|
+
import { vec2 } from "../vec2.js";
|
|
3
|
+
import { vec3 } from "../vec3.js";
|
|
4
4
|
import { toJSON } from "./json.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Creates a lathe
|
|
8
8
|
* @author Three.js converted
|
|
9
9
|
**/
|
|
10
|
-
export function createLathe(options = {})
|
|
10
|
+
export function createLathe(options = {})
|
|
11
11
|
{
|
|
12
12
|
let {
|
|
13
13
|
points = [
|
|
@@ -20,31 +20,31 @@ export function createLathe(options = {})
|
|
|
20
20
|
phiLength = Math.PI * 2
|
|
21
21
|
} = options;
|
|
22
22
|
|
|
23
|
-
segments = Math.max(3, Math.floor(Number.isFinite(segments) ? segments : 12));
|
|
24
|
-
if (!Array.isArray(points) || points.length < 2)
|
|
25
|
-
{
|
|
26
|
-
throw new Error("Lathe requires at least two profile points");
|
|
27
|
-
}
|
|
28
|
-
if (!Number.isFinite(phiStart) || !Number.isFinite(phiLength) || phiLength <= 0)
|
|
29
|
-
{
|
|
30
|
-
throw new Error("Invalid lathe sweep");
|
|
31
|
-
}
|
|
32
|
-
let hasRadius = false;
|
|
33
|
-
for (let i = 0; i < points.length; i++)
|
|
34
|
-
{
|
|
35
|
-
const point = points[i];
|
|
36
|
-
if (!point || point.length < 2 || !Number.isFinite(point[0]) || !Number.isFinite(point[1]))
|
|
37
|
-
{
|
|
38
|
-
throw new Error("Invalid lathe profile point");
|
|
39
|
-
}
|
|
40
|
-
hasRadius ||= point[0] !== 0;
|
|
41
|
-
if (i > 0 && point[0] === points[i - 1][0] && point[1] === points[i - 1][1])
|
|
42
|
-
{
|
|
43
|
-
throw new Error("Lathe profile contains a zero-length segment");
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
if (!hasRadius) throw new Error("Lathe profile must leave the rotation axis");
|
|
47
|
-
|
|
23
|
+
segments = Math.max(3, Math.floor(Number.isFinite(segments) ? segments : 12));
|
|
24
|
+
if (!Array.isArray(points) || points.length < 2)
|
|
25
|
+
{
|
|
26
|
+
throw new Error("Lathe requires at least two profile points");
|
|
27
|
+
}
|
|
28
|
+
if (!Number.isFinite(phiStart) || !Number.isFinite(phiLength) || phiLength <= 0)
|
|
29
|
+
{
|
|
30
|
+
throw new Error("Invalid lathe sweep");
|
|
31
|
+
}
|
|
32
|
+
let hasRadius = false;
|
|
33
|
+
for (let i = 0; i < points.length; i++)
|
|
34
|
+
{
|
|
35
|
+
const point = points[i];
|
|
36
|
+
if (!point || point.length < 2 || !Number.isFinite(point[0]) || !Number.isFinite(point[1]))
|
|
37
|
+
{
|
|
38
|
+
throw new Error("Invalid lathe profile point");
|
|
39
|
+
}
|
|
40
|
+
hasRadius ||= point[0] !== 0;
|
|
41
|
+
if (i > 0 && point[0] === points[i - 1][0] && point[1] === points[i - 1][1])
|
|
42
|
+
{
|
|
43
|
+
throw new Error("Lathe profile contains a zero-length segment");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (!hasRadius) throw new Error("Lathe profile must leave the rotation axis");
|
|
47
|
+
|
|
48
48
|
// clamp phiLength so it's in range of [ 0, 2PI ]
|
|
49
49
|
phiLength = num.clamp(phiLength, 0, Math.PI * 2);
|
|
50
50
|
|
|
@@ -56,12 +56,12 @@ export function createLathe(options = {})
|
|
|
56
56
|
initNormals = [],
|
|
57
57
|
normals = [];
|
|
58
58
|
|
|
59
|
-
// helper variables
|
|
60
|
-
const
|
|
61
|
-
inverseSegments = 1.0 / segments,
|
|
62
|
-
normal = vec3.alloc(),
|
|
63
|
-
curNormal = vec3.alloc(),
|
|
64
|
-
prevNormal = vec3.alloc();
|
|
59
|
+
// helper variables
|
|
60
|
+
const
|
|
61
|
+
inverseSegments = 1.0 / segments,
|
|
62
|
+
normal = vec3.alloc(),
|
|
63
|
+
curNormal = vec3.alloc(),
|
|
64
|
+
prevNormal = vec3.alloc();
|
|
65
65
|
|
|
66
66
|
let dx = 0,
|
|
67
67
|
dy = 0;
|
|
@@ -84,10 +84,10 @@ export function createLathe(options = {})
|
|
|
84
84
|
initNormals.push(normal[0], normal[1], normal[2]);
|
|
85
85
|
break;
|
|
86
86
|
|
|
87
|
-
case (points.length - 1): // special handling for last Vertex on path
|
|
88
|
-
vec3.normalize(prevNormal, prevNormal);
|
|
89
|
-
initNormals.push(prevNormal[0], prevNormal[1], prevNormal[2]);
|
|
90
|
-
break;
|
|
87
|
+
case (points.length - 1): // special handling for last Vertex on path
|
|
88
|
+
vec3.normalize(prevNormal, prevNormal);
|
|
89
|
+
initNormals.push(prevNormal[0], prevNormal[1], prevNormal[2]);
|
|
90
|
+
break;
|
|
91
91
|
|
|
92
92
|
default: // default handling for all positions in between
|
|
93
93
|
dx = points[j + 1][0] - points[j][0];
|
|
@@ -138,9 +138,9 @@ export function createLathe(options = {})
|
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
vec3.unalloc(normal);
|
|
142
|
-
vec3.unalloc(curNormal);
|
|
143
|
-
vec3.unalloc(prevNormal);
|
|
141
|
+
vec3.unalloc(normal);
|
|
142
|
+
vec3.unalloc(curNormal);
|
|
143
|
+
vec3.unalloc(prevNormal);
|
|
144
144
|
|
|
145
145
|
// indices
|
|
146
146
|
for (let i = 0; i < segments; i++)
|
|
@@ -155,8 +155,8 @@ export function createLathe(options = {})
|
|
|
155
155
|
d = base + 1;
|
|
156
156
|
|
|
157
157
|
// faces
|
|
158
|
-
if (points[j][0] !== 0) indices.push(a, b, d);
|
|
159
|
-
if (points[j + 1][0] !== 0) indices.push(c, d, b);
|
|
158
|
+
if (points[j][0] !== 0) indices.push(a, b, d);
|
|
159
|
+
if (points[j + 1][0] !== 0) indices.push(c, d, b);
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
162
|
|
package/src/geometry/plane.js
CHANGED
|
@@ -17,13 +17,13 @@ export function createPlane(options = {})
|
|
|
17
17
|
height = 1,
|
|
18
18
|
widthSegments = 1,
|
|
19
19
|
heightSegments = 1
|
|
20
|
-
} = options;
|
|
21
|
-
|
|
22
|
-
if (!Number.isFinite(width) || !Number.isFinite(height) || width === 0 || height === 0)
|
|
23
|
-
{
|
|
24
|
-
throw new Error("Plane dimensions must be finite and non-zero");
|
|
25
|
-
}
|
|
26
|
-
|
|
20
|
+
} = options;
|
|
21
|
+
|
|
22
|
+
if (!Number.isFinite(width) || !Number.isFinite(height) || width === 0 || height === 0)
|
|
23
|
+
{
|
|
24
|
+
throw new Error("Plane dimensions must be finite and non-zero");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
27
|
const
|
|
28
28
|
indices = [],
|
|
29
29
|
positions = [],
|
|
@@ -33,8 +33,8 @@ export function createPlane(options = {})
|
|
|
33
33
|
const
|
|
34
34
|
widthHalf = width / 2,
|
|
35
35
|
heightHalf = height / 2,
|
|
36
|
-
gridX = Math.max(1, Math.floor(Number.isFinite(widthSegments) ? widthSegments : 1)),
|
|
37
|
-
gridY = Math.max(1, Math.floor(Number.isFinite(heightSegments) ? heightSegments : 1)),
|
|
36
|
+
gridX = Math.max(1, Math.floor(Number.isFinite(widthSegments) ? widthSegments : 1)),
|
|
37
|
+
gridY = Math.max(1, Math.floor(Number.isFinite(heightSegments) ? heightSegments : 1)),
|
|
38
38
|
gridX1 = gridX + 1,
|
|
39
39
|
gridY1 = gridY + 1,
|
|
40
40
|
segmentWidth = width / gridX,
|
|
@@ -71,11 +71,11 @@ export function createPlane(options = {})
|
|
|
71
71
|
// Normalize
|
|
72
72
|
const result = toJSON(indices, positions, uvs, normals);
|
|
73
73
|
result.factory = createPlane;
|
|
74
|
-
result.options = {
|
|
75
|
-
width,
|
|
76
|
-
height,
|
|
77
|
-
widthSegments: gridX,
|
|
78
|
-
heightSegments: gridY
|
|
74
|
+
result.options = {
|
|
75
|
+
width,
|
|
76
|
+
height,
|
|
77
|
+
widthSegments: gridX,
|
|
78
|
+
heightSegments: gridY
|
|
79
79
|
};
|
|
80
80
|
return result;
|
|
81
81
|
}
|
package/src/geometry/shape.js
CHANGED
|
@@ -33,10 +33,10 @@ export function createShape(shapes)
|
|
|
33
33
|
areas.push({ start, count, index });
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
function addShape(shape)
|
|
37
|
-
{
|
|
38
|
-
let shapeVertices = shape.positions.map(point => Array.from(point)),
|
|
39
|
-
shapeHoles = (shape.holes || []).map(hole => hole.map(point => Array.from(point)));
|
|
36
|
+
function addShape(shape)
|
|
37
|
+
{
|
|
38
|
+
let shapeVertices = shape.positions.map(point => Array.from(point)),
|
|
39
|
+
shapeHoles = (shape.holes || []).map(hole => hole.map(point => Array.from(point)));
|
|
40
40
|
|
|
41
41
|
const indexOffset = positions.length / 3;
|
|
42
42
|
|
package/src/geometry/sphere.js
CHANGED
|
@@ -18,16 +18,16 @@ export function createSphere(options = {})
|
|
|
18
18
|
phiLength = Math.PI * 2,
|
|
19
19
|
thetaStart = 0,
|
|
20
20
|
thetaLength = Math.PI
|
|
21
|
-
} = options;
|
|
22
|
-
|
|
23
|
-
if (![ radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ].every(Number.isFinite) ||
|
|
24
|
-
radius <= 0 ||
|
|
25
|
-
phiLength <= 0 ||
|
|
26
|
-
thetaLength <= 0)
|
|
27
|
-
{
|
|
28
|
-
throw new Error("Invalid sphere dimensions");
|
|
29
|
-
}
|
|
30
|
-
|
|
21
|
+
} = options;
|
|
22
|
+
|
|
23
|
+
if (![ radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ].every(Number.isFinite) ||
|
|
24
|
+
radius <= 0 ||
|
|
25
|
+
phiLength <= 0 ||
|
|
26
|
+
thetaLength <= 0)
|
|
27
|
+
{
|
|
28
|
+
throw new Error("Invalid sphere dimensions");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
31
|
widthSegments = Math.max(3, Math.floor(widthSegments));
|
|
32
32
|
heightSegments = Math.max(2, Math.floor(heightSegments));
|
|
33
33
|
|
|
@@ -107,17 +107,17 @@ export function createSphere(options = {})
|
|
|
107
107
|
vec3.unalloc(normal);
|
|
108
108
|
|
|
109
109
|
const result = toJSON(indices, vertices, uvs, normals);
|
|
110
|
-
result.factory = createSphere;
|
|
111
|
-
result.options = {
|
|
112
|
-
radius,
|
|
113
|
-
widthSegments,
|
|
114
|
-
heightSegments,
|
|
115
|
-
phiStart,
|
|
116
|
-
phiLength,
|
|
117
|
-
thetaStart,
|
|
118
|
-
thetaLength
|
|
119
|
-
};
|
|
120
|
-
result.shape = { factory: result.factory, options: result.options };
|
|
121
|
-
|
|
122
|
-
return result;
|
|
123
|
-
}
|
|
110
|
+
result.factory = createSphere;
|
|
111
|
+
result.options = {
|
|
112
|
+
radius,
|
|
113
|
+
widthSegments,
|
|
114
|
+
heightSegments,
|
|
115
|
+
phiStart,
|
|
116
|
+
phiLength,
|
|
117
|
+
thetaStart,
|
|
118
|
+
thetaLength
|
|
119
|
+
};
|
|
120
|
+
result.shape = { factory: result.factory, options: result.options };
|
|
121
|
+
|
|
122
|
+
return result;
|
|
123
|
+
}
|
package/src/geometry/torus.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { toJSON } from "./json.js";
|
|
2
|
-
import { vec3 } from "../vec3.js";
|
|
1
|
+
import { toJSON } from "./json.js";
|
|
2
|
+
import { vec3 } from "../vec3.js";
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
export function createTorus(options = {})
|
|
@@ -10,18 +10,18 @@ export function createTorus(options = {})
|
|
|
10
10
|
radialSegments = 12,
|
|
11
11
|
tubularSegments = 49,
|
|
12
12
|
arc = Math.PI * 2
|
|
13
|
-
} = options;
|
|
14
|
-
|
|
15
|
-
if (![ radius, tube, radialSegments, tubularSegments, arc ].every(Number.isFinite) ||
|
|
16
|
-
radius <= 0 ||
|
|
17
|
-
tube <= 0 ||
|
|
18
|
-
arc === 0)
|
|
19
|
-
{
|
|
20
|
-
throw new Error("Invalid torus dimensions");
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
radialSegments = Math.max(3, Math.floor(Number.isFinite(radialSegments) ? radialSegments : 12));
|
|
24
|
-
tubularSegments = Math.max(3, Math.floor(Number.isFinite(tubularSegments) ? tubularSegments : 49));
|
|
13
|
+
} = options;
|
|
14
|
+
|
|
15
|
+
if (![ radius, tube, radialSegments, tubularSegments, arc ].every(Number.isFinite) ||
|
|
16
|
+
radius <= 0 ||
|
|
17
|
+
tube <= 0 ||
|
|
18
|
+
arc === 0)
|
|
19
|
+
{
|
|
20
|
+
throw new Error("Invalid torus dimensions");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
radialSegments = Math.max(3, Math.floor(Number.isFinite(radialSegments) ? radialSegments : 12));
|
|
24
|
+
tubularSegments = Math.max(3, Math.floor(Number.isFinite(tubularSegments) ? tubularSegments : 49));
|
|
25
25
|
|
|
26
26
|
const
|
|
27
27
|
indices = [],
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Canonical color space tokens for decoded image/texture payloads.
|
|
3
|
-
*/
|
|
4
|
-
export const ColorSpace = Object.freeze({
|
|
5
|
-
UNKNOWN: "unknown",
|
|
6
|
-
LINEAR: "linear",
|
|
7
|
-
SRGB: "srgb",
|
|
8
|
-
DISPLAY_P3: "display-p3",
|
|
9
|
-
REC709: "rec709",
|
|
10
|
-
REC2020: "rec2020"
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Normalize a color space token.
|
|
15
|
-
*
|
|
16
|
-
* @param {string} colorSpace Color space token.
|
|
17
|
-
* @returns {string} Canonical lowercase token or unknown.
|
|
18
|
-
*/
|
|
19
|
-
export function normalizeColorSpace(colorSpace)
|
|
20
|
-
{
|
|
21
|
-
return colorSpace ? String(colorSpace).trim().toLowerCase() : ColorSpace.UNKNOWN;
|
|
22
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Canonical color space tokens for decoded image/texture payloads.
|
|
3
|
+
*/
|
|
4
|
+
export const ColorSpace = Object.freeze({
|
|
5
|
+
UNKNOWN: "unknown",
|
|
6
|
+
LINEAR: "linear",
|
|
7
|
+
SRGB: "srgb",
|
|
8
|
+
DISPLAY_P3: "display-p3",
|
|
9
|
+
REC709: "rec709",
|
|
10
|
+
REC2020: "rec2020"
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Normalize a color space token.
|
|
15
|
+
*
|
|
16
|
+
* @param {string} colorSpace Color space token.
|
|
17
|
+
* @returns {string} Canonical lowercase token or unknown.
|
|
18
|
+
*/
|
|
19
|
+
export function normalizeColorSpace(colorSpace)
|
|
20
|
+
{
|
|
21
|
+
return colorSpace ? String(colorSpace).trim().toLowerCase() : ColorSpace.UNKNOWN;
|
|
22
|
+
}
|
package/src/graphics/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export * from "./pixelFormats.js";
|
|
2
|
-
export * from "./colorSpaces.js";
|
|
3
|
-
export * from "./textureDimensions.js";
|
|
4
|
-
export * from "./trinityEnums.js";
|
|
1
|
+
export * from "./pixelFormats.js";
|
|
2
|
+
export * from "./colorSpaces.js";
|
|
3
|
+
export * from "./textureDimensions.js";
|
|
4
|
+
export * from "./trinityEnums.js";
|