@math.gl/geometry 5.0.0-alpha.15 → 5.0.0-alpha.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/geometries/primitive-mesh-builder.d.ts +24 -0
- package/dist/geometries/primitive-mesh-builder.d.ts.map +1 -0
- package/dist/geometries/primitive-mesh-builder.js +74 -0
- package/dist/geometries/primitive-mesh-builder.js.map +1 -0
- package/dist/geometries/prism-geometry.d.ts +13 -0
- package/dist/geometries/prism-geometry.d.ts.map +1 -0
- package/dist/geometries/prism-geometry.js +34 -0
- package/dist/geometries/prism-geometry.js.map +1 -0
- package/dist/geometries/ring-geometry.d.ts +15 -0
- package/dist/geometries/ring-geometry.d.ts.map +1 -0
- package/dist/geometries/ring-geometry.js +64 -0
- package/dist/geometries/ring-geometry.js.map +1 -0
- package/dist/index.cjs +164 -9
- package/dist/index.cjs.map +3 -3
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/parametric/torus-geometry.d.ts +5 -1
- package/dist/parametric/torus-geometry.d.ts.map +1 -1
- package/dist/parametric/torus-geometry.js +60 -7
- package/dist/parametric/torus-geometry.js.map +1 -1
- package/dist/parametric.cjs +58 -6
- package/dist/parametric.cjs.map +1 -1
- package/package.json +3 -3
- package/src/geometries/primitive-mesh-builder.ts +84 -0
- package/src/geometries/prism-geometry.ts +57 -0
- package/src/geometries/ring-geometry.ts +102 -0
- package/src/index.ts +6 -0
- package/src/parametric/torus-geometry.ts +75 -8
|
@@ -1,36 +1,89 @@
|
|
|
1
1
|
// math.gl
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// SPDX-FileCopyrightText: Copyright (c) vis.gl contributors
|
|
4
|
-
import {
|
|
4
|
+
import { Geometry } from "../lib/geometry.js";
|
|
5
|
+
import { assertPositive, assertSegments, makeIndices } from "../geometries/geometry-helpers.js";
|
|
5
6
|
import { ParametricGeometry } from "./parametric-geometry.js";
|
|
6
7
|
/** Ring torus around Y, with outward analytic normals and separate UV seam rows. */
|
|
7
8
|
export class TorusGeometry extends ParametricGeometry {
|
|
8
9
|
constructor(props = {}) {
|
|
9
|
-
const { majorRadius = 1, minorRadius = 0.3, majorSegments = 48, minorSegments = 24, arc = Math.PI * 2 } = props;
|
|
10
|
+
const { majorRadius = 1, minorRadius = 0.3, majorSegments = 48, minorSegments = 24, arc = Math.PI * 2, startAngle = 0, cap = false } = props;
|
|
10
11
|
assertPositive(majorRadius, 'majorRadius');
|
|
11
12
|
assertPositive(minorRadius, 'minorRadius');
|
|
12
13
|
if (minorRadius >= majorRadius)
|
|
13
14
|
throw new RangeError('Ring torus requires minorRadius < majorRadius');
|
|
14
15
|
if (!Number.isFinite(arc) || arc <= 0 || arc > Math.PI * 2)
|
|
15
16
|
throw new RangeError('arc must be in (0, 2π]');
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
assertSegments(majorSegments, 'majorSegments', 3);
|
|
18
|
+
assertSegments(minorSegments, 'minorSegments', 3);
|
|
19
|
+
if (!Number.isFinite(startAngle))
|
|
20
|
+
throw new RangeError('startAngle must be finite');
|
|
21
|
+
const hasCaps = cap && arc < Math.PI * 2;
|
|
18
22
|
super({
|
|
19
23
|
...props,
|
|
24
|
+
attributes: hasCaps ? undefined : props.attributes,
|
|
20
25
|
uSegments: majorSegments,
|
|
21
26
|
vSegments: minorSegments,
|
|
22
27
|
periodicU: arc === Math.PI * 2,
|
|
23
28
|
periodicV: true,
|
|
24
29
|
sample: (u, v) => {
|
|
25
|
-
const theta = u * arc, phi = v * Math.PI * 2, radius = majorRadius + minorRadius * Math.cos(phi);
|
|
30
|
+
const theta = startAngle + u * arc, phi = v * Math.PI * 2, radius = majorRadius + minorRadius * Math.cos(phi);
|
|
26
31
|
return [radius * Math.cos(theta), minorRadius * Math.sin(phi), -radius * Math.sin(theta)];
|
|
27
32
|
},
|
|
28
33
|
normal: (u, v) => [
|
|
29
|
-
Math.cos(v * Math.PI * 2) * Math.cos(u * arc),
|
|
34
|
+
Math.cos(v * Math.PI * 2) * Math.cos(startAngle + u * arc),
|
|
30
35
|
Math.sin(v * Math.PI * 2),
|
|
31
|
-
-Math.cos(v * Math.PI * 2) * Math.sin(u * arc)
|
|
36
|
+
-Math.cos(v * Math.PI * 2) * Math.sin(startAngle + u * arc)
|
|
32
37
|
]
|
|
33
38
|
});
|
|
39
|
+
if (hasCaps) {
|
|
40
|
+
const surfacePositions = this.attributes['POSITION'].value;
|
|
41
|
+
const positions = Array.from(surfacePositions);
|
|
42
|
+
const normals = Array.from(this.attributes['NORMAL'].value);
|
|
43
|
+
const textureCoordinates = Array.from(this.attributes['TEXCOORD_0'].value);
|
|
44
|
+
const indices = Array.from(this.indices.value);
|
|
45
|
+
for (const [angle, direction] of [
|
|
46
|
+
[startAngle, -1],
|
|
47
|
+
[startAngle + arc, 1]
|
|
48
|
+
]) {
|
|
49
|
+
const normal = [-Math.sin(angle) * direction, 0, -Math.cos(angle) * direction];
|
|
50
|
+
const centerIndex = positions.length / 3;
|
|
51
|
+
positions.push(majorRadius * Math.cos(angle), 0, -majorRadius * Math.sin(angle));
|
|
52
|
+
normals.push(...normal);
|
|
53
|
+
textureCoordinates.push(0.5, 0.5);
|
|
54
|
+
for (let minorSegment = 0; minorSegment <= minorSegments; minorSegment++) {
|
|
55
|
+
// The final disk vertex duplicates the first exactly, matching the tube UV seam.
|
|
56
|
+
const tubeAngle = ((minorSegment % minorSegments) * Math.PI * 2) / minorSegments;
|
|
57
|
+
// Copy boundary positions so disk and tube edges match bit for bit.
|
|
58
|
+
const boundaryOffset = (minorSegment * (majorSegments + 1) + (direction < 0 ? 0 : majorSegments)) * 3;
|
|
59
|
+
positions.push(...surfacePositions.slice(boundaryOffset, boundaryOffset + 3));
|
|
60
|
+
normals.push(...normal);
|
|
61
|
+
textureCoordinates.push((Math.cos(tubeAngle) + 1) / 2, (Math.sin(tubeAngle) + 1) / 2);
|
|
62
|
+
if (minorSegment < minorSegments) {
|
|
63
|
+
const firstIndex = centerIndex + minorSegment + 1;
|
|
64
|
+
const secondIndex = firstIndex + 1;
|
|
65
|
+
indices.push(centerIndex, ...(direction > 0 ? [secondIndex, firstIndex] : [firstIndex, secondIndex]));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const cappedGeometry = new Geometry({
|
|
70
|
+
id: this.id,
|
|
71
|
+
topology: this.topology,
|
|
72
|
+
indices: makeIndices(positions.length / 3, indices),
|
|
73
|
+
attributes: {
|
|
74
|
+
POSITION: { size: 3, value: new Float32Array(positions) },
|
|
75
|
+
NORMAL: { size: 3, value: new Float32Array(normals) },
|
|
76
|
+
TEXCOORD_0: { size: 2, value: new Float32Array(textureCoordinates) },
|
|
77
|
+
...props.attributes
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
// Finish construction with validated cap data while retaining ParametricGeometry inheritance.
|
|
81
|
+
Object.assign(this, {
|
|
82
|
+
attributes: cappedGeometry.attributes,
|
|
83
|
+
indices: cappedGeometry.indices,
|
|
84
|
+
vertexCount: cappedGeometry.vertexCount
|
|
85
|
+
});
|
|
86
|
+
}
|
|
34
87
|
}
|
|
35
88
|
}
|
|
36
89
|
//# sourceMappingURL=torus-geometry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"torus-geometry.js","sourceRoot":"","sources":["../../src/parametric/torus-geometry.ts"],"names":[],"mappings":"AAAA,UAAU;AACV,+BAA+B;AAC/B,4DAA4D;AAC5D,OAAO,EAAC,cAAc,
|
|
1
|
+
{"version":3,"file":"torus-geometry.js","sourceRoot":"","sources":["../../src/parametric/torus-geometry.ts"],"names":[],"mappings":"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"}
|
package/dist/parametric.cjs
CHANGED
|
@@ -119,6 +119,9 @@ function assertSegments(value, name, minimum = 1) {
|
|
|
119
119
|
if (!Number.isInteger(value) || value < minimum)
|
|
120
120
|
throw new Error(`${name} must be an integer >= ${minimum}`);
|
|
121
121
|
}
|
|
122
|
+
function makeIndices(vertexCount, values) {
|
|
123
|
+
return vertexCount > 65535 ? new Uint32Array(values) : new Uint16Array(values);
|
|
124
|
+
}
|
|
122
125
|
|
|
123
126
|
// dist/parametric/parametric-geometry.js
|
|
124
127
|
var ParametricGeometry = class extends Geometry {
|
|
@@ -204,31 +207,80 @@ function normalized(vector) {
|
|
|
204
207
|
// dist/parametric/torus-geometry.js
|
|
205
208
|
var TorusGeometry = class extends ParametricGeometry {
|
|
206
209
|
constructor(props = {}) {
|
|
207
|
-
const { majorRadius = 1, minorRadius = 0.3, majorSegments = 48, minorSegments = 24, arc = Math.PI * 2 } = props;
|
|
210
|
+
const { majorRadius = 1, minorRadius = 0.3, majorSegments = 48, minorSegments = 24, arc = Math.PI * 2, startAngle = 0, cap = false } = props;
|
|
208
211
|
assertPositive(majorRadius, "majorRadius");
|
|
209
212
|
assertPositive(minorRadius, "minorRadius");
|
|
210
213
|
if (minorRadius >= majorRadius)
|
|
211
214
|
throw new RangeError("Ring torus requires minorRadius < majorRadius");
|
|
212
215
|
if (!Number.isFinite(arc) || arc <= 0 || arc > Math.PI * 2)
|
|
213
216
|
throw new RangeError("arc must be in (0, 2\u03C0]");
|
|
214
|
-
|
|
215
|
-
|
|
217
|
+
assertSegments(majorSegments, "majorSegments", 3);
|
|
218
|
+
assertSegments(minorSegments, "minorSegments", 3);
|
|
219
|
+
if (!Number.isFinite(startAngle))
|
|
220
|
+
throw new RangeError("startAngle must be finite");
|
|
221
|
+
const hasCaps = cap && arc < Math.PI * 2;
|
|
216
222
|
super({
|
|
217
223
|
...props,
|
|
224
|
+
attributes: hasCaps ? void 0 : props.attributes,
|
|
218
225
|
uSegments: majorSegments,
|
|
219
226
|
vSegments: minorSegments,
|
|
220
227
|
periodicU: arc === Math.PI * 2,
|
|
221
228
|
periodicV: true,
|
|
222
229
|
sample: (u, v) => {
|
|
223
|
-
const theta = u * arc, phi = v * Math.PI * 2, radius = majorRadius + minorRadius * Math.cos(phi);
|
|
230
|
+
const theta = startAngle + u * arc, phi = v * Math.PI * 2, radius = majorRadius + minorRadius * Math.cos(phi);
|
|
224
231
|
return [radius * Math.cos(theta), minorRadius * Math.sin(phi), -radius * Math.sin(theta)];
|
|
225
232
|
},
|
|
226
233
|
normal: (u, v) => [
|
|
227
|
-
Math.cos(v * Math.PI * 2) * Math.cos(u * arc),
|
|
234
|
+
Math.cos(v * Math.PI * 2) * Math.cos(startAngle + u * arc),
|
|
228
235
|
Math.sin(v * Math.PI * 2),
|
|
229
|
-
-Math.cos(v * Math.PI * 2) * Math.sin(u * arc)
|
|
236
|
+
-Math.cos(v * Math.PI * 2) * Math.sin(startAngle + u * arc)
|
|
230
237
|
]
|
|
231
238
|
});
|
|
239
|
+
if (hasCaps) {
|
|
240
|
+
const surfacePositions = this.attributes["POSITION"].value;
|
|
241
|
+
const positions = Array.from(surfacePositions);
|
|
242
|
+
const normals = Array.from(this.attributes["NORMAL"].value);
|
|
243
|
+
const textureCoordinates = Array.from(this.attributes["TEXCOORD_0"].value);
|
|
244
|
+
const indices = Array.from(this.indices.value);
|
|
245
|
+
for (const [angle, direction] of [
|
|
246
|
+
[startAngle, -1],
|
|
247
|
+
[startAngle + arc, 1]
|
|
248
|
+
]) {
|
|
249
|
+
const normal = [-Math.sin(angle) * direction, 0, -Math.cos(angle) * direction];
|
|
250
|
+
const centerIndex = positions.length / 3;
|
|
251
|
+
positions.push(majorRadius * Math.cos(angle), 0, -majorRadius * Math.sin(angle));
|
|
252
|
+
normals.push(...normal);
|
|
253
|
+
textureCoordinates.push(0.5, 0.5);
|
|
254
|
+
for (let minorSegment = 0; minorSegment <= minorSegments; minorSegment++) {
|
|
255
|
+
const tubeAngle = minorSegment % minorSegments * Math.PI * 2 / minorSegments;
|
|
256
|
+
const boundaryOffset = (minorSegment * (majorSegments + 1) + (direction < 0 ? 0 : majorSegments)) * 3;
|
|
257
|
+
positions.push(...surfacePositions.slice(boundaryOffset, boundaryOffset + 3));
|
|
258
|
+
normals.push(...normal);
|
|
259
|
+
textureCoordinates.push((Math.cos(tubeAngle) + 1) / 2, (Math.sin(tubeAngle) + 1) / 2);
|
|
260
|
+
if (minorSegment < minorSegments) {
|
|
261
|
+
const firstIndex = centerIndex + minorSegment + 1;
|
|
262
|
+
const secondIndex = firstIndex + 1;
|
|
263
|
+
indices.push(centerIndex, ...direction > 0 ? [secondIndex, firstIndex] : [firstIndex, secondIndex]);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
const cappedGeometry = new Geometry({
|
|
268
|
+
id: this.id,
|
|
269
|
+
topology: this.topology,
|
|
270
|
+
indices: makeIndices(positions.length / 3, indices),
|
|
271
|
+
attributes: {
|
|
272
|
+
POSITION: { size: 3, value: new Float32Array(positions) },
|
|
273
|
+
NORMAL: { size: 3, value: new Float32Array(normals) },
|
|
274
|
+
TEXCOORD_0: { size: 2, value: new Float32Array(textureCoordinates) },
|
|
275
|
+
...props.attributes
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
Object.assign(this, {
|
|
279
|
+
attributes: cappedGeometry.attributes,
|
|
280
|
+
indices: cappedGeometry.indices,
|
|
281
|
+
vertexCount: cappedGeometry.vertexCount
|
|
282
|
+
});
|
|
283
|
+
}
|
|
232
284
|
}
|
|
233
285
|
};
|
|
234
286
|
|
package/dist/parametric.cjs.map
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/parametric.ts", "../src/lib/geometry.ts", "../src/geometries/geometry-helpers.ts", "../src/parametric/parametric-geometry.ts", "../src/parametric/torus-geometry.ts", "../src/parametric/lathe-geometry.ts"],
|
|
4
|
-
"mappings": "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
|
|
4
|
+
"mappings": "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",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
9
|
-
"version": "5.0.0-alpha.
|
|
9
|
+
"version": "5.0.0-alpha.16",
|
|
10
10
|
"keywords": [
|
|
11
11
|
"geometry",
|
|
12
12
|
"gltf",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"src"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@math.gl/types": "5.0.0-alpha.
|
|
42
|
+
"@math.gl/types": "5.0.0-alpha.16"
|
|
43
43
|
},
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "95d9d242bd9a2060ab8a0aaeb32d6657c3f06b3b"
|
|
45
45
|
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// math.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// SPDX-FileCopyrightText: Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import type {GeometryProps} from '../lib/geometry';
|
|
6
|
+
import {assertSegments, makeIndices, type PrimitiveGeometryProps} from './geometry-helpers';
|
|
7
|
+
export const FULL_CIRCLE = Math.PI * 2;
|
|
8
|
+
export type Vector = [number, number, number];
|
|
9
|
+
export type Vertex = {position: Vector; normal: Vector; textureCoordinates: [number, number]};
|
|
10
|
+
export function radial(angle: number, direction = 1): Vector {
|
|
11
|
+
return [Math.cos(angle) * direction, 0, -Math.sin(angle) * direction];
|
|
12
|
+
}
|
|
13
|
+
export function vertex(
|
|
14
|
+
radius: number,
|
|
15
|
+
height: number,
|
|
16
|
+
angle: number,
|
|
17
|
+
normal: Vector,
|
|
18
|
+
textureCoordinates?: [number, number]
|
|
19
|
+
): Vertex {
|
|
20
|
+
return {
|
|
21
|
+
position: [radius * Math.cos(angle), height, -radius * Math.sin(angle)],
|
|
22
|
+
normal,
|
|
23
|
+
textureCoordinates: textureCoordinates ?? [(Math.cos(angle) + 1) / 2, (Math.sin(angle) + 1) / 2]
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function validateArc(segments: number, startAngle: number, sweepAngle: number): void {
|
|
27
|
+
assertSegments(segments, 'segments', 3);
|
|
28
|
+
if (!Number.isFinite(startAngle)) throw new Error('startAngle must be finite');
|
|
29
|
+
if (!Number.isFinite(sweepAngle) || sweepAngle <= 0 || sweepAngle > FULL_CIRCLE)
|
|
30
|
+
throw new Error('sweepAngle must be positive and at most 2π');
|
|
31
|
+
}
|
|
32
|
+
export class PrimitiveMeshBuilder {
|
|
33
|
+
private positions: number[] = [];
|
|
34
|
+
private normals: number[] = [];
|
|
35
|
+
private textureCoordinates: number[] = [];
|
|
36
|
+
private indices: number[] = [];
|
|
37
|
+
private addVertex(current: Vertex): number {
|
|
38
|
+
const index = this.positions.length / 3;
|
|
39
|
+
this.positions.push(...current.position);
|
|
40
|
+
this.normals.push(...current.normal);
|
|
41
|
+
this.textureCoordinates.push(...current.textureCoordinates);
|
|
42
|
+
return index;
|
|
43
|
+
}
|
|
44
|
+
private addTriangle(first: Vertex, second: Vertex, third: Vertex, indices: number[]): void {
|
|
45
|
+
const firstEdge = second.position.map((value, index) => value - first.position[index]);
|
|
46
|
+
const secondEdge = third.position.map((value, index) => value - first.position[index]);
|
|
47
|
+
const cross = [
|
|
48
|
+
firstEdge[1] * secondEdge[2] - firstEdge[2] * secondEdge[1],
|
|
49
|
+
firstEdge[2] * secondEdge[0] - firstEdge[0] * secondEdge[2],
|
|
50
|
+
firstEdge[0] * secondEdge[1] - firstEdge[1] * secondEdge[0]
|
|
51
|
+
];
|
|
52
|
+
const orientation = cross.reduce(
|
|
53
|
+
(sum, value, index) =>
|
|
54
|
+
sum + value * (first.normal[index] + second.normal[index] + third.normal[index]),
|
|
55
|
+
0
|
|
56
|
+
);
|
|
57
|
+
this.indices.push(...(orientation < 0 ? [indices[0], indices[2], indices[1]] : indices));
|
|
58
|
+
}
|
|
59
|
+
triangle(first: Vertex, second: Vertex, third: Vertex): void {
|
|
60
|
+
this.addTriangle(first, second, third, [
|
|
61
|
+
this.addVertex(first),
|
|
62
|
+
this.addVertex(second),
|
|
63
|
+
this.addVertex(third)
|
|
64
|
+
]);
|
|
65
|
+
}
|
|
66
|
+
quad(first: Vertex, second: Vertex, third: Vertex, fourth: Vertex): void {
|
|
67
|
+
const indices = [first, second, third, fourth].map(current => this.addVertex(current));
|
|
68
|
+
this.addTriangle(first, second, third, indices.slice(0, 3));
|
|
69
|
+
this.addTriangle(first, third, fourth, [indices[0], indices[2], indices[3]]);
|
|
70
|
+
}
|
|
71
|
+
getProps(props: PrimitiveGeometryProps): GeometryProps {
|
|
72
|
+
return {
|
|
73
|
+
id: props.id,
|
|
74
|
+
topology: 'triangle-list',
|
|
75
|
+
indices: makeIndices(this.positions.length / 3, this.indices),
|
|
76
|
+
attributes: {
|
|
77
|
+
POSITION: {size: 3, value: new Float32Array(this.positions)},
|
|
78
|
+
NORMAL: {size: 3, value: new Float32Array(this.normals)},
|
|
79
|
+
TEXCOORD_0: {size: 2, value: new Float32Array(this.textureCoordinates)},
|
|
80
|
+
...props.attributes
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// math.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// SPDX-FileCopyrightText: Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import {Geometry} from '../lib/geometry';
|
|
6
|
+
import {assertPositive, type PrimitiveGeometryProps} from './geometry-helpers';
|
|
7
|
+
import {
|
|
8
|
+
PrimitiveMeshBuilder,
|
|
9
|
+
FULL_CIRCLE,
|
|
10
|
+
radial,
|
|
11
|
+
validateArc,
|
|
12
|
+
vertex,
|
|
13
|
+
type Vector,
|
|
14
|
+
type Vertex
|
|
15
|
+
} from './primitive-mesh-builder';
|
|
16
|
+
export type PrismGeometryProps = PrimitiveGeometryProps & {
|
|
17
|
+
radius?: number;
|
|
18
|
+
height?: number;
|
|
19
|
+
sides?: number;
|
|
20
|
+
startAngle?: number;
|
|
21
|
+
};
|
|
22
|
+
/** Closed regular prism, centered at the origin with Y vertical and flat side normals. */
|
|
23
|
+
export class PrismGeometry extends Geometry {
|
|
24
|
+
constructor(props: PrismGeometryProps = {}) {
|
|
25
|
+
const {radius = 1, height = 1, sides = 6, startAngle = 0} = props;
|
|
26
|
+
assertPositive(radius, 'radius');
|
|
27
|
+
assertPositive(height, 'height');
|
|
28
|
+
validateArc(sides, startAngle, FULL_CIRCLE);
|
|
29
|
+
const mesh = new PrimitiveMeshBuilder();
|
|
30
|
+
for (let segment = 0; segment < sides; segment++) {
|
|
31
|
+
const firstAngle = startAngle + (segment * FULL_CIRCLE) / sides;
|
|
32
|
+
const secondAngle = startAngle + ((segment + 1) * FULL_CIRCLE) / sides;
|
|
33
|
+
const normal = radial((firstAngle + secondAngle) / 2);
|
|
34
|
+
const secondCornerAngle = segment === sides - 1 ? startAngle : secondAngle;
|
|
35
|
+
mesh.quad(
|
|
36
|
+
vertex(radius, -height / 2, firstAngle, normal, [segment / sides, 0]),
|
|
37
|
+
vertex(radius, height / 2, firstAngle, normal, [segment / sides, 1]),
|
|
38
|
+
vertex(radius, height / 2, secondCornerAngle, normal, [(segment + 1) / sides, 1]),
|
|
39
|
+
vertex(radius, -height / 2, secondCornerAngle, normal, [(segment + 1) / sides, 0])
|
|
40
|
+
);
|
|
41
|
+
for (const direction of [-1, 1]) {
|
|
42
|
+
const capNormal: Vector = [0, direction, 0];
|
|
43
|
+
const center: Vertex = {
|
|
44
|
+
position: [0, (direction * height) / 2, 0],
|
|
45
|
+
normal: capNormal,
|
|
46
|
+
textureCoordinates: [0.5, 0.5]
|
|
47
|
+
};
|
|
48
|
+
mesh.triangle(
|
|
49
|
+
center,
|
|
50
|
+
vertex(radius, (direction * height) / 2, firstAngle, capNormal),
|
|
51
|
+
vertex(radius, (direction * height) / 2, secondCornerAngle, capNormal)
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
super(mesh.getProps(props));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// math.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// SPDX-FileCopyrightText: Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import {Geometry} from '../lib/geometry';
|
|
6
|
+
import {assertPositive, type PrimitiveGeometryProps} from './geometry-helpers';
|
|
7
|
+
import {
|
|
8
|
+
PrimitiveMeshBuilder,
|
|
9
|
+
FULL_CIRCLE,
|
|
10
|
+
radial,
|
|
11
|
+
validateArc,
|
|
12
|
+
vertex,
|
|
13
|
+
type Vector
|
|
14
|
+
} from './primitive-mesh-builder';
|
|
15
|
+
export type RingGeometryProps = PrimitiveGeometryProps & {
|
|
16
|
+
innerRadius?: number;
|
|
17
|
+
outerRadius?: number;
|
|
18
|
+
height?: number;
|
|
19
|
+
segments?: number;
|
|
20
|
+
startAngle?: number;
|
|
21
|
+
sweepAngle?: number;
|
|
22
|
+
};
|
|
23
|
+
/** Closed annular sector in XZ, centered vertically with hard top, bottom and end caps. */
|
|
24
|
+
export class RingGeometry extends Geometry {
|
|
25
|
+
constructor(props: RingGeometryProps = {}) {
|
|
26
|
+
const {
|
|
27
|
+
innerRadius = 0.5,
|
|
28
|
+
outerRadius = 1,
|
|
29
|
+
height = 0.1,
|
|
30
|
+
segments = 48,
|
|
31
|
+
startAngle = 0,
|
|
32
|
+
sweepAngle = FULL_CIRCLE
|
|
33
|
+
} = props;
|
|
34
|
+
assertPositive(innerRadius, 'innerRadius');
|
|
35
|
+
assertPositive(outerRadius, 'outerRadius');
|
|
36
|
+
assertPositive(height, 'height');
|
|
37
|
+
if (innerRadius >= outerRadius) throw new Error('innerRadius must be smaller than outerRadius');
|
|
38
|
+
validateArc(segments, startAngle, sweepAngle);
|
|
39
|
+
const mesh = new PrimitiveMeshBuilder();
|
|
40
|
+
for (let segment = 0; segment < segments; segment++) {
|
|
41
|
+
const firstAngle = startAngle + (segment * sweepAngle) / segments;
|
|
42
|
+
const secondAngle =
|
|
43
|
+
segment === segments - 1
|
|
44
|
+
? sweepAngle === FULL_CIRCLE
|
|
45
|
+
? startAngle
|
|
46
|
+
: startAngle + sweepAngle
|
|
47
|
+
: startAngle + ((segment + 1) * sweepAngle) / segments;
|
|
48
|
+
const makeCapVertex = (radius: number, height: number, angle: number, normal: Vector) =>
|
|
49
|
+
vertex(radius, height, angle, normal, [
|
|
50
|
+
((radius * Math.cos(angle)) / outerRadius + 1) / 2,
|
|
51
|
+
((radius * Math.sin(angle)) / outerRadius + 1) / 2
|
|
52
|
+
]);
|
|
53
|
+
for (const direction of [-1, 1]) {
|
|
54
|
+
const normal: Vector = [0, direction, 0];
|
|
55
|
+
mesh.quad(
|
|
56
|
+
makeCapVertex(innerRadius, (direction * height) / 2, firstAngle, normal),
|
|
57
|
+
makeCapVertex(outerRadius, (direction * height) / 2, firstAngle, normal),
|
|
58
|
+
makeCapVertex(outerRadius, (direction * height) / 2, secondAngle, normal),
|
|
59
|
+
makeCapVertex(innerRadius, (direction * height) / 2, secondAngle, normal)
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
for (const [radius, direction] of [
|
|
63
|
+
[innerRadius, -1],
|
|
64
|
+
[outerRadius, 1]
|
|
65
|
+
]) {
|
|
66
|
+
mesh.quad(
|
|
67
|
+
vertex(radius, -height / 2, firstAngle, radial(firstAngle, direction), [
|
|
68
|
+
segment / segments,
|
|
69
|
+
0
|
|
70
|
+
]),
|
|
71
|
+
vertex(radius, height / 2, firstAngle, radial(firstAngle, direction), [
|
|
72
|
+
segment / segments,
|
|
73
|
+
1
|
|
74
|
+
]),
|
|
75
|
+
vertex(radius, height / 2, secondAngle, radial(secondAngle, direction), [
|
|
76
|
+
(segment + 1) / segments,
|
|
77
|
+
1
|
|
78
|
+
]),
|
|
79
|
+
vertex(radius, -height / 2, secondAngle, radial(secondAngle, direction), [
|
|
80
|
+
(segment + 1) / segments,
|
|
81
|
+
0
|
|
82
|
+
])
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (sweepAngle < FULL_CIRCLE) {
|
|
87
|
+
for (const [angle, direction] of [
|
|
88
|
+
[startAngle, -1],
|
|
89
|
+
[startAngle + sweepAngle, 1]
|
|
90
|
+
]) {
|
|
91
|
+
const normal: Vector = [-Math.sin(angle) * direction, 0, -Math.cos(angle) * direction];
|
|
92
|
+
mesh.quad(
|
|
93
|
+
vertex(innerRadius, -height / 2, angle, normal, [0, 0]),
|
|
94
|
+
vertex(outerRadius, -height / 2, angle, normal, [1, 0]),
|
|
95
|
+
vertex(outerRadius, height / 2, angle, normal, [1, 1]),
|
|
96
|
+
vertex(innerRadius, height / 2, angle, normal, [0, 1])
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
super(mesh.getProps(props));
|
|
101
|
+
}
|
|
102
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -26,3 +26,9 @@ export {TruncatedConeGeometry} from './geometries/truncated-cone-geometry';
|
|
|
26
26
|
export type {TruncatedConeGeometryProps} from './geometries/truncated-cone-geometry';
|
|
27
27
|
export {IcoSphereGeometry} from './geometries/ico-sphere-geometry';
|
|
28
28
|
export type {IcoSphereGeometryProps} from './geometries/ico-sphere-geometry';
|
|
29
|
+
|
|
30
|
+
export {PrismGeometry} from './geometries/prism-geometry';
|
|
31
|
+
export type {PrismGeometryProps} from './geometries/prism-geometry';
|
|
32
|
+
|
|
33
|
+
export {RingGeometry} from './geometries/ring-geometry';
|
|
34
|
+
export type {RingGeometryProps} from './geometries/ring-geometry';
|
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
// math.gl
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// SPDX-FileCopyrightText: Copyright (c) vis.gl contributors
|
|
4
|
-
import {
|
|
4
|
+
import {Geometry} from '../lib/geometry';
|
|
5
|
+
import {
|
|
6
|
+
assertPositive,
|
|
7
|
+
assertSegments,
|
|
8
|
+
makeIndices,
|
|
9
|
+
type PrimitiveGeometryProps
|
|
10
|
+
} from '../geometries/geometry-helpers';
|
|
5
11
|
import {ParametricGeometry} from './parametric-geometry';
|
|
6
12
|
export type TorusGeometryProps = PrimitiveGeometryProps & {
|
|
7
13
|
majorRadius?: number;
|
|
8
14
|
minorRadius?: number;
|
|
9
15
|
majorSegments?: number;
|
|
10
16
|
minorSegments?: number;
|
|
11
|
-
/** Sweep in radians, (0, 2π]. Partial sweeps have open ends. */
|
|
17
|
+
/** Sweep in radians, (0, 2π]. Partial sweeps have open ends unless cap is enabled. */
|
|
12
18
|
arc?: number;
|
|
19
|
+
/** Rotation in radians about Y; positive angles turn toward negative Z. */
|
|
20
|
+
startAngle?: number;
|
|
21
|
+
/** Close partial sweeps with flat end disks. Ignored for a full revolution. */
|
|
22
|
+
cap?: boolean;
|
|
13
23
|
};
|
|
14
24
|
/** Ring torus around Y, with outward analytic normals and separate UV seam rows. */
|
|
15
25
|
export class TorusGeometry extends ParametricGeometry {
|
|
@@ -19,7 +29,9 @@ export class TorusGeometry extends ParametricGeometry {
|
|
|
19
29
|
minorRadius = 0.3,
|
|
20
30
|
majorSegments = 48,
|
|
21
31
|
minorSegments = 24,
|
|
22
|
-
arc = Math.PI * 2
|
|
32
|
+
arc = Math.PI * 2,
|
|
33
|
+
startAngle = 0,
|
|
34
|
+
cap = false
|
|
23
35
|
} = props;
|
|
24
36
|
assertPositive(majorRadius, 'majorRadius');
|
|
25
37
|
assertPositive(minorRadius, 'minorRadius');
|
|
@@ -27,25 +39,80 @@ export class TorusGeometry extends ParametricGeometry {
|
|
|
27
39
|
throw new RangeError('Ring torus requires minorRadius < majorRadius');
|
|
28
40
|
if (!Number.isFinite(arc) || arc <= 0 || arc > Math.PI * 2)
|
|
29
41
|
throw new RangeError('arc must be in (0, 2π]');
|
|
30
|
-
|
|
31
|
-
|
|
42
|
+
assertSegments(majorSegments, 'majorSegments', 3);
|
|
43
|
+
assertSegments(minorSegments, 'minorSegments', 3);
|
|
44
|
+
if (!Number.isFinite(startAngle)) throw new RangeError('startAngle must be finite');
|
|
45
|
+
const hasCaps = cap && arc < Math.PI * 2;
|
|
32
46
|
super({
|
|
33
47
|
...props,
|
|
48
|
+
attributes: hasCaps ? undefined : props.attributes,
|
|
34
49
|
uSegments: majorSegments,
|
|
35
50
|
vSegments: minorSegments,
|
|
36
51
|
periodicU: arc === Math.PI * 2,
|
|
37
52
|
periodicV: true,
|
|
38
53
|
sample: (u, v) => {
|
|
39
|
-
const theta = u * arc,
|
|
54
|
+
const theta = startAngle + u * arc,
|
|
40
55
|
phi = v * Math.PI * 2,
|
|
41
56
|
radius = majorRadius + minorRadius * Math.cos(phi);
|
|
42
57
|
return [radius * Math.cos(theta), minorRadius * Math.sin(phi), -radius * Math.sin(theta)];
|
|
43
58
|
},
|
|
44
59
|
normal: (u, v) => [
|
|
45
|
-
Math.cos(v * Math.PI * 2) * Math.cos(u * arc),
|
|
60
|
+
Math.cos(v * Math.PI * 2) * Math.cos(startAngle + u * arc),
|
|
46
61
|
Math.sin(v * Math.PI * 2),
|
|
47
|
-
-Math.cos(v * Math.PI * 2) * Math.sin(u * arc)
|
|
62
|
+
-Math.cos(v * Math.PI * 2) * Math.sin(startAngle + u * arc)
|
|
48
63
|
]
|
|
49
64
|
});
|
|
65
|
+
if (hasCaps) {
|
|
66
|
+
const surfacePositions = this.attributes['POSITION'].value;
|
|
67
|
+
const positions = Array.from(surfacePositions);
|
|
68
|
+
const normals = Array.from(this.attributes['NORMAL'].value);
|
|
69
|
+
const textureCoordinates = Array.from(this.attributes['TEXCOORD_0'].value);
|
|
70
|
+
const indices = Array.from(this.indices!.value);
|
|
71
|
+
for (const [angle, direction] of [
|
|
72
|
+
[startAngle, -1],
|
|
73
|
+
[startAngle + arc, 1]
|
|
74
|
+
]) {
|
|
75
|
+
const normal = [-Math.sin(angle) * direction, 0, -Math.cos(angle) * direction];
|
|
76
|
+
const centerIndex = positions.length / 3;
|
|
77
|
+
positions.push(majorRadius * Math.cos(angle), 0, -majorRadius * Math.sin(angle));
|
|
78
|
+
normals.push(...normal);
|
|
79
|
+
textureCoordinates.push(0.5, 0.5);
|
|
80
|
+
for (let minorSegment = 0; minorSegment <= minorSegments; minorSegment++) {
|
|
81
|
+
// The final disk vertex duplicates the first exactly, matching the tube UV seam.
|
|
82
|
+
const tubeAngle = ((minorSegment % minorSegments) * Math.PI * 2) / minorSegments;
|
|
83
|
+
// Copy boundary positions so disk and tube edges match bit for bit.
|
|
84
|
+
const boundaryOffset =
|
|
85
|
+
(minorSegment * (majorSegments + 1) + (direction < 0 ? 0 : majorSegments)) * 3;
|
|
86
|
+
positions.push(...surfacePositions.slice(boundaryOffset, boundaryOffset + 3));
|
|
87
|
+
normals.push(...normal);
|
|
88
|
+
textureCoordinates.push((Math.cos(tubeAngle) + 1) / 2, (Math.sin(tubeAngle) + 1) / 2);
|
|
89
|
+
if (minorSegment < minorSegments) {
|
|
90
|
+
const firstIndex = centerIndex + minorSegment + 1;
|
|
91
|
+
const secondIndex = firstIndex + 1;
|
|
92
|
+
indices.push(
|
|
93
|
+
centerIndex,
|
|
94
|
+
...(direction > 0 ? [secondIndex, firstIndex] : [firstIndex, secondIndex])
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const cappedGeometry = new Geometry({
|
|
100
|
+
id: this.id,
|
|
101
|
+
topology: this.topology,
|
|
102
|
+
indices: makeIndices(positions.length / 3, indices),
|
|
103
|
+
attributes: {
|
|
104
|
+
POSITION: {size: 3, value: new Float32Array(positions)},
|
|
105
|
+
NORMAL: {size: 3, value: new Float32Array(normals)},
|
|
106
|
+
TEXCOORD_0: {size: 2, value: new Float32Array(textureCoordinates)},
|
|
107
|
+
...props.attributes
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
// Finish construction with validated cap data while retaining ParametricGeometry inheritance.
|
|
111
|
+
Object.assign(this, {
|
|
112
|
+
attributes: cappedGeometry.attributes,
|
|
113
|
+
indices: cappedGeometry.indices,
|
|
114
|
+
vertexCount: cappedGeometry.vertexCount
|
|
115
|
+
});
|
|
116
|
+
}
|
|
50
117
|
}
|
|
51
118
|
}
|