abstract-3d 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/lib/abstract-3d.d.ts +7 -0
- package/lib/abstract-3d.d.ts.map +1 -1
- package/lib/abstract-3d.js +108 -0
- package/lib/abstract-3d.js.map +1 -1
- package/lib/renderers/dxf/dxf.d.ts.map +1 -1
- package/lib/renderers/dxf/dxf.js +2 -2
- package/lib/renderers/dxf/dxf.js.map +1 -1
- package/lib/renderers/shared.d.ts +1 -2
- package/lib/renderers/shared.d.ts.map +1 -1
- package/lib/renderers/shared.js +1 -109
- package/lib/renderers/shared.js.map +1 -1
- package/lib/renderers/svg/svg-encoding.d.ts +2 -2
- package/lib/renderers/svg/svg-encoding.d.ts.map +1 -1
- package/lib/renderers/svg/svg-encoding.js +15 -10
- package/lib/renderers/svg/svg-encoding.js.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-box.d.ts +2 -2
- package/lib/renderers/svg/svg-geometries/svg-box.d.ts.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-box.js +6 -4
- package/lib/renderers/svg/svg-geometries/svg-box.js.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-cone.d.ts +2 -2
- package/lib/renderers/svg/svg-geometries/svg-cone.d.ts.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-cone.js +5 -3
- package/lib/renderers/svg/svg-geometries/svg-cone.js.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-cylinder.d.ts +2 -2
- package/lib/renderers/svg/svg-geometries/svg-cylinder.d.ts.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-cylinder.js +5 -3
- package/lib/renderers/svg/svg-geometries/svg-cylinder.js.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-plane.js +1 -1
- package/lib/renderers/svg/svg-geometries/svg-plane.js.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-polygon.d.ts +2 -2
- package/lib/renderers/svg/svg-geometries/svg-polygon.d.ts.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-polygon.js +3 -2
- package/lib/renderers/svg/svg-geometries/svg-polygon.js.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-shape.d.ts +2 -2
- package/lib/renderers/svg/svg-geometries/svg-shape.d.ts.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-shape.js +3 -2
- package/lib/renderers/svg/svg-geometries/svg-shape.js.map +1 -1
- package/lib/renderers/svg/svg.js +7 -8
- package/lib/renderers/svg/svg.js.map +1 -1
- package/package.json +2 -2
- package/src/abstract-3d.ts +117 -0
- package/src/renderers/dxf/dxf.ts +2 -1
- package/src/renderers/shared.ts +0 -117
- package/src/renderers/svg/svg-encoding.ts +15 -10
- package/src/renderers/svg/svg-geometries/svg-box.ts +7 -4
- package/src/renderers/svg/svg-geometries/svg-cone.ts +6 -3
- package/src/renderers/svg/svg-geometries/svg-cylinder.ts +6 -3
- package/src/renderers/svg/svg-geometries/svg-plane.ts +1 -1
- package/src/renderers/svg/svg-geometries/svg-polygon.ts +4 -3
- package/src/renderers/svg/svg-geometries/svg-shape.ts +4 -3
- package/src/renderers/svg/svg.ts +7 -8
package/src/abstract-3d.ts
CHANGED
|
@@ -427,6 +427,123 @@ export function bounds3FromVec3Array(vec3Array: ReadonlyArray<Vec3>): Bounds3 {
|
|
|
427
427
|
return bounds3(min, max);
|
|
428
428
|
}
|
|
429
429
|
|
|
430
|
+
export function boundsScene(scene: Scene): Bounds3 {
|
|
431
|
+
const bounds: Array<Bounds3> = [];
|
|
432
|
+
for (const group of scene.groups) {
|
|
433
|
+
bounds.push(...boundsGroup(group, vec3Zero, vec3Zero))
|
|
434
|
+
}
|
|
435
|
+
return bounds3Merge(...bounds);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
export function boundsGroup(group: Group, parentPos: Vec3, parentRot: Vec3): ReadonlyArray<Bounds3> {
|
|
439
|
+
const pos = vec3TransRot(group.pos, parentPos, parentRot);
|
|
440
|
+
const rot = vec3RotCombine(parentRot, group.rot ?? vec3Zero);
|
|
441
|
+
const bounds: Array<Bounds3> = [];
|
|
442
|
+
|
|
443
|
+
for (const childMesh of group.meshes ?? []) {
|
|
444
|
+
switch (childMesh.geometry.type) {
|
|
445
|
+
case "Sphere": {
|
|
446
|
+
bounds.push(boundsSphere(childMesh.geometry, pos, rot));
|
|
447
|
+
break;
|
|
448
|
+
}
|
|
449
|
+
case "Plane": {
|
|
450
|
+
bounds.push(boundsPlane(childMesh.geometry, pos, rot));
|
|
451
|
+
break;
|
|
452
|
+
}
|
|
453
|
+
case "Box": {
|
|
454
|
+
bounds.push(boundsBox(childMesh.geometry, pos, rot));
|
|
455
|
+
break;
|
|
456
|
+
}
|
|
457
|
+
case "Cylinder": {
|
|
458
|
+
bounds.push(boundsCylinder(childMesh.geometry, pos, rot));
|
|
459
|
+
break;
|
|
460
|
+
}
|
|
461
|
+
case "Cone": {
|
|
462
|
+
bounds.push(boundsCone(childMesh.geometry, pos, rot));
|
|
463
|
+
break;
|
|
464
|
+
}
|
|
465
|
+
default:
|
|
466
|
+
break;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
for (const childGroup of group.groups ?? []) {
|
|
471
|
+
bounds.push(...boundsGroup(childGroup, pos, rot));
|
|
472
|
+
}
|
|
473
|
+
return bounds;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
export function boundsSphere(s: Sphere, parentPos: Vec3, parentRot: Vec3): Bounds3 {
|
|
477
|
+
const pos = vec3TransRot(s.pos, parentPos, parentRot);
|
|
478
|
+
const half = vec3(s.radius, s.radius, s.radius);
|
|
479
|
+
return bounds3(vec3Sub(pos, half), vec3Add(pos, half));
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
export function boundsPlane(p: Plane, parentPos: Vec3, parentRot: Vec3): Bounds3 {
|
|
483
|
+
const pos = vec3TransRot(p.pos, parentPos, parentRot);
|
|
484
|
+
const rot = vec3RotCombine(parentRot, p.rot ?? vec3Zero);
|
|
485
|
+
const half = vec3(p.size.x / 2, p.size.y / 2, 0);
|
|
486
|
+
const points = [
|
|
487
|
+
vec3(-half.x, half.y, half.z),
|
|
488
|
+
vec3(half.x, half.y, half.z),
|
|
489
|
+
vec3(-half.x, half.y, -half.z),
|
|
490
|
+
vec3(half.x, half.y, -half.z),
|
|
491
|
+
vec3(-half.x, -half.y, half.z),
|
|
492
|
+
vec3(half.x, -half.y, half.z),
|
|
493
|
+
vec3(-half.x, -half.y, -half.z),
|
|
494
|
+
vec3(half.x, -half.y, -half.z),
|
|
495
|
+
].map((p) => vec3Add(pos, vec3Rot(p, vec3Zero, rot)));
|
|
496
|
+
return bounds3FromVec3Array(points);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
export function boundsBox(b: Box, parentPos: Vec3, parentRot: Vec3): Bounds3 {
|
|
500
|
+
const pos = vec3TransRot(b.pos, parentPos, parentRot);
|
|
501
|
+
const rot = vec3RotCombine(parentRot, b.rot ?? vec3Zero);
|
|
502
|
+
const half = vec3Scale(b.size, 0.5);
|
|
503
|
+
const points = [
|
|
504
|
+
vec3(-half.x, half.y, half.z),
|
|
505
|
+
vec3(half.x, half.y, half.z),
|
|
506
|
+
vec3(-half.x, half.y, -half.z),
|
|
507
|
+
vec3(half.x, half.y, -half.z),
|
|
508
|
+
vec3(-half.x, -half.y, half.z),
|
|
509
|
+
vec3(half.x, -half.y, half.z),
|
|
510
|
+
vec3(-half.x, -half.y, -half.z),
|
|
511
|
+
vec3(half.x, -half.y, -half.z),
|
|
512
|
+
].map((p) => vec3Add(pos, vec3Rot(p, vec3Zero, rot)));
|
|
513
|
+
return bounds3FromVec3Array(points);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
export function boundsCylinder(c: Cylinder, parentPos: Vec3, parentRot: Vec3): Bounds3 {
|
|
517
|
+
const pos = vec3TransRot(c.pos, parentPos, parentRot);
|
|
518
|
+
const rot = vec3RotCombine(parentRot, c.rot ?? vec3Zero);
|
|
519
|
+
const half = vec3(c.radius, c.length / 2, c.radius);
|
|
520
|
+
const points = [
|
|
521
|
+
vec3(-half.x, half.y, half.z),
|
|
522
|
+
vec3(half.x, half.y, half.z),
|
|
523
|
+
vec3(-half.x, half.y, -half.z),
|
|
524
|
+
vec3(half.x, half.y, -half.z),
|
|
525
|
+
vec3(-half.x, -half.y, half.z),
|
|
526
|
+
vec3(half.x, -half.y, half.z),
|
|
527
|
+
vec3(-half.x, -half.y, -half.z),
|
|
528
|
+
vec3(half.x, -half.y, -half.z),
|
|
529
|
+
].map((p) => vec3Add(pos, vec3Rot(p, vec3Zero, rot)));
|
|
530
|
+
return bounds3FromVec3Array(points);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
export function boundsCone(c: Cone, parentPos: Vec3, parentRot: Vec3): Bounds3 {
|
|
534
|
+
const pos = vec3TransRot(c.pos, parentPos, parentRot);
|
|
535
|
+
const rot = vec3RotCombine(parentRot, c.rot ?? vec3Zero);
|
|
536
|
+
const half = vec3(c.radius, c.length / 2, c.radius);
|
|
537
|
+
const points = [
|
|
538
|
+
vec3(0, half.y, 0),
|
|
539
|
+
vec3(-half.x, -half.y, half.z),
|
|
540
|
+
vec3(half.x, -half.y, half.z),
|
|
541
|
+
vec3(-half.x, -half.y, -half.z),
|
|
542
|
+
vec3(half.x, -half.y, -half.z),
|
|
543
|
+
].map((p) => vec3Add(pos, vec3Rot(p, vec3Zero, rot)));
|
|
544
|
+
return bounds3FromVec3Array(points);
|
|
545
|
+
}
|
|
546
|
+
|
|
430
547
|
// -- Transformations
|
|
431
548
|
|
|
432
549
|
const quaternion1 = new Quaternion();
|
package/src/renderers/dxf/dxf.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
group,
|
|
10
10
|
bounds3ToSize,
|
|
11
11
|
vec3,
|
|
12
|
+
boundsScene,
|
|
12
13
|
} from "../../abstract-3d.js";
|
|
13
14
|
import { dxfFooter, dxfHeader } from "./dxf-encoding.js";
|
|
14
15
|
import { dxfPlane } from "./dxf-geometries/dxf-plane.js";
|
|
@@ -16,7 +17,7 @@ import { dxfBox } from "./dxf-geometries/dxf-box.js";
|
|
|
16
17
|
import { dxfCylinder } from "./dxf-geometries/dxf-cylinder.js";
|
|
17
18
|
import { dxfCone } from "./dxf-geometries/dxf-cone.js";
|
|
18
19
|
import { dxfPolygon } from "./dxf-geometries/dxf-polygon.js";
|
|
19
|
-
import {
|
|
20
|
+
import { Optional, rotationForCameraPos } from "../shared.js";
|
|
20
21
|
|
|
21
22
|
export type DxfOrigin = "BottomLeftFront" | "Center";
|
|
22
23
|
export type DxfOptions = { readonly view: View; readonly origin: DxfOrigin };
|
package/src/renderers/shared.ts
CHANGED
|
@@ -211,121 +211,4 @@ export function shade(p: number, from: string, to?: string): string | undefined
|
|
|
211
211
|
);
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
export function boundsScene(scene: Scene): Bounds3 {
|
|
215
|
-
const bounds: Array<Bounds3> = [];
|
|
216
|
-
for (const group of scene.groups) {
|
|
217
|
-
bounds.push(...boundsGroup(group, vec3Zero, vec3Zero))
|
|
218
|
-
}
|
|
219
|
-
return bounds3Merge(...bounds);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
function boundsGroup(group: Group, parentPos: Vec3, parentRot: Vec3): ReadonlyArray<Bounds3> {
|
|
223
|
-
const pos = vec3TransRot(group.pos, parentPos, parentRot);
|
|
224
|
-
const rot = vec3RotCombine(parentRot, group.rot ?? vec3Zero);
|
|
225
|
-
const bounds: Array<Bounds3> = [];
|
|
226
|
-
|
|
227
|
-
for (const childMesh of group.meshes ?? []) {
|
|
228
|
-
switch (childMesh.geometry.type) {
|
|
229
|
-
case "Sphere": {
|
|
230
|
-
//bounds.push(boundsSphere(childMesh.geometry, pos, rot));
|
|
231
|
-
break;
|
|
232
|
-
}
|
|
233
|
-
case "Plane": {
|
|
234
|
-
bounds.push(boundsPlane(childMesh.geometry, pos, rot));
|
|
235
|
-
break;
|
|
236
|
-
}
|
|
237
|
-
case "Box": {
|
|
238
|
-
bounds.push(boundsBox(childMesh.geometry, pos, rot));
|
|
239
|
-
break;
|
|
240
|
-
}
|
|
241
|
-
case "Cylinder": {
|
|
242
|
-
bounds.push(boundsCylinder(childMesh.geometry, pos, rot));
|
|
243
|
-
break;
|
|
244
|
-
}
|
|
245
|
-
case "Cone": {
|
|
246
|
-
bounds.push(boundsCone(childMesh.geometry, pos, rot));
|
|
247
|
-
break;
|
|
248
|
-
}
|
|
249
|
-
default:
|
|
250
|
-
break;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
for (const childGroup of group.groups ?? []) {
|
|
255
|
-
bounds.push(...boundsGroup(childGroup, pos, rot));
|
|
256
|
-
}
|
|
257
|
-
return bounds;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
function boundsSphere(s: Sphere, parentPos: Vec3, parentRot: Vec3): Bounds3 {
|
|
261
|
-
const pos = vec3TransRot(s.pos, parentPos, parentRot);
|
|
262
|
-
const half = vec3(s.radius, s.radius, s.radius);
|
|
263
|
-
return bounds3(vec3Sub(pos, half), vec3Add(pos, half));
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
function boundsPlane(p: Plane, parentPos: Vec3, parentRot: Vec3): Bounds3 {
|
|
267
|
-
const pos = vec3TransRot(p.pos, parentPos, parentRot);
|
|
268
|
-
const rot = vec3RotCombine(parentRot, p.rot ?? vec3Zero);
|
|
269
|
-
const half = vec3(p.size.x / 2, p.size.y / 2, 0);
|
|
270
|
-
const points = [
|
|
271
|
-
vec3(-half.x, half.y, half.z),
|
|
272
|
-
vec3(half.x, half.y, half.z),
|
|
273
|
-
vec3(-half.x, half.y, -half.z),
|
|
274
|
-
vec3(half.x, half.y, -half.z),
|
|
275
|
-
vec3(-half.x, -half.y, half.z),
|
|
276
|
-
vec3(half.x, -half.y, half.z),
|
|
277
|
-
vec3(-half.x, -half.y, -half.z),
|
|
278
|
-
vec3(half.x, -half.y, -half.z),
|
|
279
|
-
].map((p) => vec3Add(pos, vec3Rot(p, vec3Zero, rot)));
|
|
280
|
-
return bounds3FromVec3Array(points);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
function boundsBox(b: Box, parentPos: Vec3, parentRot: Vec3): Bounds3 {
|
|
284
|
-
const pos = vec3TransRot(b.pos, parentPos, parentRot);
|
|
285
|
-
const rot = vec3RotCombine(parentRot, b.rot ?? vec3Zero);
|
|
286
|
-
const half = vec3Scale(b.size, 0.5);
|
|
287
|
-
const points = [
|
|
288
|
-
vec3(-half.x, half.y, half.z),
|
|
289
|
-
vec3(half.x, half.y, half.z),
|
|
290
|
-
vec3(-half.x, half.y, -half.z),
|
|
291
|
-
vec3(half.x, half.y, -half.z),
|
|
292
|
-
vec3(-half.x, -half.y, half.z),
|
|
293
|
-
vec3(half.x, -half.y, half.z),
|
|
294
|
-
vec3(-half.x, -half.y, -half.z),
|
|
295
|
-
vec3(half.x, -half.y, -half.z),
|
|
296
|
-
].map((p) => vec3Add(pos, vec3Rot(p, vec3Zero, rot)));
|
|
297
|
-
return bounds3FromVec3Array(points);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
function boundsCylinder(c: Cylinder, parentPos: Vec3, parentRot: Vec3): Bounds3 {
|
|
301
|
-
const pos = vec3TransRot(c.pos, parentPos, parentRot);
|
|
302
|
-
const rot = vec3RotCombine(parentRot, c.rot ?? vec3Zero);
|
|
303
|
-
const half = vec3(c.radius, c.length / 2, c.radius);
|
|
304
|
-
const points = [
|
|
305
|
-
vec3(-half.x, half.y, half.z),
|
|
306
|
-
vec3(half.x, half.y, half.z),
|
|
307
|
-
vec3(-half.x, half.y, -half.z),
|
|
308
|
-
vec3(half.x, half.y, -half.z),
|
|
309
|
-
vec3(-half.x, -half.y, half.z),
|
|
310
|
-
vec3(half.x, -half.y, half.z),
|
|
311
|
-
vec3(-half.x, -half.y, -half.z),
|
|
312
|
-
vec3(half.x, -half.y, -half.z),
|
|
313
|
-
].map((p) => vec3Add(pos, vec3Rot(p, vec3Zero, rot)));
|
|
314
|
-
return bounds3FromVec3Array(points);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
function boundsCone(c: Cone, parentPos: Vec3, parentRot: Vec3): Bounds3 {
|
|
318
|
-
const pos = vec3TransRot(c.pos, parentPos, parentRot);
|
|
319
|
-
const rot = vec3RotCombine(parentRot, c.rot ?? vec3Zero);
|
|
320
|
-
const half = vec3(c.radius, c.length / 2, c.radius);
|
|
321
|
-
const points = [
|
|
322
|
-
vec3(0, half.y, 0),
|
|
323
|
-
vec3(-half.x, -half.y, half.z),
|
|
324
|
-
vec3(half.x, -half.y, half.z),
|
|
325
|
-
vec3(-half.x, -half.y, -half.z),
|
|
326
|
-
vec3(half.x, -half.y, -half.z),
|
|
327
|
-
].map((p) => vec3Add(pos, vec3Rot(p, vec3Zero, rot)));
|
|
328
|
-
return bounds3FromVec3Array(points);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
214
|
export type Optional<T> = { readonly [K in keyof T]?: T[K] };
|
|
@@ -11,20 +11,20 @@ export const svgLine = (p1: Vec2, p2: Vec2, stroke: string, strokeWidth: number)
|
|
|
11
11
|
0
|
|
12
12
|
)}" stroke="${stroke}" stroke-width="${strokeWidth}" />`;
|
|
13
13
|
|
|
14
|
-
export function svgPolygon(factor: number, rot: Vec3, points: ReadonlyArray<Vec2>, fill: string, stroke: string, strokeWidth: number, holes?: ReadonlyArray<Hole>): string {
|
|
14
|
+
export function svgPolygon(factor: number, rot: Vec3, points: ReadonlyArray<Vec2>, fill: string, opacity: number, stroke: string, strokeWidth: number, holes?: ReadonlyArray<Hole>): string {
|
|
15
15
|
const bounds = bounds2FromVec2Array(points);
|
|
16
16
|
const size = vec2Sub(bounds.max, bounds.min);
|
|
17
|
-
const [mask,
|
|
17
|
+
const [mask, maskAttribute] = svgHoleMask(factor, rot, size, holes ?? []);
|
|
18
18
|
const pol = `<polygon points="${points
|
|
19
19
|
.reduce((a, c) => (a += `${c.x.toFixed(0)},${c.y.toFixed(0)} `), "")
|
|
20
|
-
.slice(0, -1)}" fill="${fill}" stroke="${stroke}" stroke-width="${strokeWidth}"
|
|
20
|
+
.slice(0, -1)}" fill="${fill}" fill-opacity="${opacity.toFixed(1)}" stroke="${stroke}" stroke-width="${strokeWidth}" ${maskAttribute}/>`;
|
|
21
21
|
return mask + pol;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export function svgCircle(radius: number, rot: Vec3, pos: Vec2, fill: string, stroke: string, strokeWidth: number, factor: number, holes?: ReadonlyArray<Hole>): string {
|
|
24
|
+
export function svgCircle(radius: number, rot: Vec3, pos: Vec2, fill: string, opacity: number, stroke: string, strokeWidth: number, factor: number, holes?: ReadonlyArray<Hole>): string {
|
|
25
25
|
const size = vec2Scale(vec2(radius, radius), 2);
|
|
26
|
-
const [mask,
|
|
27
|
-
const cir = `<circle r="${radius.toFixed(0)}" cx="${pos.x.toFixed(0)}" cy="${pos.y.toFixed(0)}" fill="${fill}" stroke="${stroke}" stroke-width="${strokeWidth}"
|
|
26
|
+
const [mask, maskAttribute] = svgHoleMask(factor, rot, size, holes ?? []);
|
|
27
|
+
const cir = `<circle r="${radius.toFixed(0)}" cx="${pos.x.toFixed(0)}" cy="${pos.y.toFixed(0)}" fill="${fill}" fill-opacity="${opacity.toFixed(1)}" stroke="${stroke}" stroke-width="${strokeWidth}" ${maskAttribute}/>`;
|
|
28
28
|
return mask + cir;
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -35,11 +35,16 @@ export const svgCircle2 = (radius: number, pos: Vec2, fill: string, stroke: stri
|
|
|
35
35
|
|
|
36
36
|
function svgHoleMask(factor: number, rot: Vec3, size: Vec2, holes: ReadonlyArray<Hole>): [string, string] {
|
|
37
37
|
const id = `mask_${counter()}`;
|
|
38
|
-
return
|
|
39
|
-
|
|
38
|
+
return holes.length > 0 ? [
|
|
39
|
+
`<mask id="${id}" mask-type="luminance" maskContentUnits="objectBoundingBox">
|
|
40
40
|
<rect x="0" y="0" width="1" height="1" fill="white" />
|
|
41
41
|
${svgMaskHoles(factor, rot, size, holes ?? [])}
|
|
42
|
-
</mask>\n
|
|
42
|
+
</mask>\n`,
|
|
43
|
+
`mask="url(#${id}) "`
|
|
44
|
+
] : [
|
|
45
|
+
"",
|
|
46
|
+
""
|
|
47
|
+
];
|
|
43
48
|
}
|
|
44
49
|
|
|
45
50
|
function svgMaskHoles(factor: number, rot: Vec3, size: Vec2, holes: ReadonlyArray<Hole>): string {
|
|
@@ -56,7 +61,7 @@ function svgMaskHoles(factor: number, rot: Vec3, size: Vec2, holes: ReadonlyArra
|
|
|
56
61
|
case "SquareHole":
|
|
57
62
|
const holeSizeRotated = vec3Rot(vec3(hole.size.x, hole.size.y, 0), vec3Zero, rot);
|
|
58
63
|
const holeSizeAbs = vec2(Math.abs(holeSizeRotated.x), Math.abs(holeSizeRotated.y));
|
|
59
|
-
const holeSize = vec2Scale(holeSizeAbs, factor
|
|
64
|
+
const holeSize = vec2Scale(holeSizeAbs, factor);
|
|
60
65
|
const halfSize = vec2Scale(holeSize, 0.5);
|
|
61
66
|
holeMasks.push(`<rect x="${(holePos.x - halfSize.x) / size.x}" y="${(holePos.y - halfSize.y) / size.y}" width="${holeSize.x / size.x}" height="${holeSize.y / size.y}" fill="black" />`)
|
|
62
67
|
break;
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
vec3Zero,
|
|
9
9
|
vec3,
|
|
10
10
|
vec3ZMean,
|
|
11
|
+
Material,
|
|
11
12
|
} from "../../../abstract-3d.js";
|
|
12
13
|
import { gray, black, zElem, zOrderElement, SvgOptions } from "./shared.js";
|
|
13
14
|
import { svgPolygon } from "../svg-encoding.js";
|
|
@@ -16,7 +17,7 @@ import { rgbGrayScale } from "../../shared.js";
|
|
|
16
17
|
export function box(
|
|
17
18
|
b: Box,
|
|
18
19
|
point: (x: number, y: number) => Vec2,
|
|
19
|
-
|
|
20
|
+
material: Material,
|
|
20
21
|
opts: SvgOptions,
|
|
21
22
|
parentPos: Vec3,
|
|
22
23
|
parentRot: Vec3,
|
|
@@ -57,13 +58,15 @@ export function box(
|
|
|
57
58
|
? [[point(v6.x, v6.y), point(v2.x, v2.y), point(v3.x, v3.y), point(v7.x, v7.y)], rightMean]
|
|
58
59
|
: [[point(v5.x, v5.y), point(v1.x, v1.y), point(v4.x, v4.y), point(v8.x, v8.y)], leftMean];
|
|
59
60
|
|
|
61
|
+
const color = material.normal;
|
|
62
|
+
const opacity = material.opacity ?? 1.0;
|
|
60
63
|
const [strokeColor, fill, strokeUse] = opts.onlyStroke
|
|
61
64
|
? [opts.grayScale ? gray : color, opts.onlyStrokeFill, opts.stroke]
|
|
62
65
|
: [black, opts.grayScale ? rgbGrayScale(color) : color, 0];
|
|
63
66
|
|
|
64
67
|
return [
|
|
65
|
-
zElem(svgPolygon(factor, rot, frontBackPoints, fill, strokeColor, strokeUse, b.holes), frontBackMean),
|
|
66
|
-
zElem(svgPolygon(factor, rot, topBotPoints, fill, strokeColor, strokeUse), topBotMean),
|
|
67
|
-
zElem(svgPolygon(factor, rot, rightLeftPoints, fill, strokeColor, strokeUse), rightLeftMean),
|
|
68
|
+
zElem(svgPolygon(factor, rot, frontBackPoints, fill, opacity, strokeColor, strokeUse, b.holes), frontBackMean),
|
|
69
|
+
zElem(svgPolygon(factor, rot, topBotPoints, fill, opacity, strokeColor, strokeUse), topBotMean),
|
|
70
|
+
zElem(svgPolygon(factor, rot, rightLeftPoints, fill, opacity, strokeColor, strokeUse), rightLeftMean),
|
|
68
71
|
];
|
|
69
72
|
}
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
vec3Zero,
|
|
9
9
|
vec3ZMean,
|
|
10
10
|
equals,
|
|
11
|
+
Material,
|
|
11
12
|
} from "../../../abstract-3d.js";
|
|
12
13
|
import { gray, stBW, zElem, zOrderElement, transparent, SvgOptions } from "./shared.js";
|
|
13
14
|
import { svgCircle, svgPolygon } from "../svg-encoding.js";
|
|
@@ -16,7 +17,7 @@ import { rgbGrayScale } from "../../shared.js";
|
|
|
16
17
|
export function cone(
|
|
17
18
|
c: Cone,
|
|
18
19
|
point: (x: number, y: number) => Vec2,
|
|
19
|
-
|
|
20
|
+
material: Material,
|
|
20
21
|
opts: SvgOptions,
|
|
21
22
|
parentPos: Vec3,
|
|
22
23
|
parentRot: Vec3,
|
|
@@ -27,6 +28,8 @@ export function cone(
|
|
|
27
28
|
const rot = vec3RotCombine(parentRot, c.rot ?? vec3Zero);
|
|
28
29
|
const vec3tr = (p: Vec3): Vec3 => vec3TransRot(p, pos, rot);
|
|
29
30
|
|
|
31
|
+
const color = material.normal;
|
|
32
|
+
const opacity = material.opacity ?? 1.0;
|
|
30
33
|
const [stroke, fill] = opts.onlyStroke
|
|
31
34
|
? [opts.grayScale ? gray : color, opts.onlyStrokeFill]
|
|
32
35
|
: [transparent, opts.grayScale ? rgbGrayScale(color) : color];
|
|
@@ -49,7 +52,7 @@ export function cone(
|
|
|
49
52
|
point(topPos.x, topPos.y),
|
|
50
53
|
point(topPos.x, topPos.y),
|
|
51
54
|
];
|
|
52
|
-
zOrderComponents.push(zElem(svgPolygon(factor, rot, points, fill, stroke, stBW), vec3ZMean(currBot, prevBot, topPos)));
|
|
55
|
+
zOrderComponents.push(zElem(svgPolygon(factor, rot, points, fill, opacity, stroke, stBW), vec3ZMean(currBot, prevBot, topPos)));
|
|
53
56
|
}
|
|
54
57
|
currentAngle += angleStep;
|
|
55
58
|
}
|
|
@@ -59,7 +62,7 @@ export function cone(
|
|
|
59
62
|
const cylBottom = vec3tr(vec3(0, -half.y, 0));
|
|
60
63
|
if (equals(cylTop.x, cylBottom.x, 0.1) && equals(cylTop.y, cylBottom.y, 0.1)) {
|
|
61
64
|
zOrderComponents.push(
|
|
62
|
-
zElem(svgCircle(factor * c.radius, rot, point(cylBottom.x, cylBottom.y), fill, stroke, stBW, factor), cylBottom.z)
|
|
65
|
+
zElem(svgCircle(factor * c.radius, rot, point(cylBottom.x, cylBottom.y), fill, opacity, stroke, stBW, factor), cylBottom.z)
|
|
63
66
|
);
|
|
64
67
|
}
|
|
65
68
|
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
vec3Zero,
|
|
9
9
|
vec3ZMean,
|
|
10
10
|
equals,
|
|
11
|
+
Material,
|
|
11
12
|
} from "../../../abstract-3d.js";
|
|
12
13
|
import { gray, stBW, SvgOptions, transparent, zElem, zOrderElement } from "./shared.js";
|
|
13
14
|
import { svgCircle, svgPolygon } from "../svg-encoding.js";
|
|
@@ -16,7 +17,7 @@ import { rgbGrayScale } from "../../shared.js";
|
|
|
16
17
|
export function cylinder(
|
|
17
18
|
c: Cylinder,
|
|
18
19
|
point: (x: number, y: number) => Vec2,
|
|
19
|
-
|
|
20
|
+
material: Material,
|
|
20
21
|
opts: SvgOptions,
|
|
21
22
|
parentPos: Vec3,
|
|
22
23
|
parentRot: Vec3,
|
|
@@ -27,6 +28,8 @@ export function cylinder(
|
|
|
27
28
|
const rot = vec3RotCombine(parentRot, c.rot ?? vec3Zero);
|
|
28
29
|
const vec3tr = (p: Vec3): Vec3 => vec3TransRot(p, pos, rot);
|
|
29
30
|
|
|
31
|
+
const color = material.normal;
|
|
32
|
+
const opacity = material.opacity ?? 1.0;
|
|
30
33
|
const [stroke, fill] = opts.onlyStroke
|
|
31
34
|
? [opts.grayScale ? gray : color, opts.onlyStrokeFill]
|
|
32
35
|
: [transparent, opts.grayScale ? rgbGrayScale(color) : color];
|
|
@@ -56,7 +59,7 @@ export function cylinder(
|
|
|
56
59
|
point(currTop.x, currTop.y),
|
|
57
60
|
];
|
|
58
61
|
zOrderComponents.push(
|
|
59
|
-
zElem(svgPolygon(factor, rot, points, fill, stroke, stBW), vec3ZMean(currBot, prevBot, currTop, prevTop))
|
|
62
|
+
zElem(svgPolygon(factor, rot, points, fill, opacity, stroke, stBW), vec3ZMean(currBot, prevBot, currTop, prevTop))
|
|
60
63
|
);
|
|
61
64
|
}
|
|
62
65
|
currentAngle += angleStep;
|
|
@@ -68,7 +71,7 @@ export function cylinder(
|
|
|
68
71
|
if (equals(circleTop.x, circleBottom.x, 0.1) && equals(circleTop.y, circleBottom.y, 0.1)) {
|
|
69
72
|
const circlePos = circleTop.z > circleBottom.z ? circleTop : circleBottom;
|
|
70
73
|
zOrderComponents.push(
|
|
71
|
-
zElem(svgCircle(factor * c.radius, rot, point(circlePos.x, circlePos.y), fill, stroke, stBW, factor, c.holes), circlePos.z)
|
|
74
|
+
zElem(svgCircle(factor * c.radius, rot, point(circlePos.x, circlePos.y), fill, opacity, stroke, stBW, factor, c.holes), circlePos.z)
|
|
72
75
|
);
|
|
73
76
|
}
|
|
74
77
|
}
|
|
@@ -59,7 +59,7 @@ export function plane(
|
|
|
59
59
|
const [strokeColor, fill, strokeThickness] = opts.onlyStroke
|
|
60
60
|
? [opts.grayScale ? gray : material.normal, opts.onlyStrokeFill, opts.stroke]
|
|
61
61
|
: [black, opts.grayScale ? rgbGrayScale(material.normal) : material.normal, 0];
|
|
62
|
-
return [zElem(svgPolygon(factor, rot, points, fill, strokeColor, strokeThickness, holes), vec3ZMean(v1, v2, v3, v4))];
|
|
62
|
+
return [zElem(svgPolygon(factor, rot, points, fill, material.opacity ?? 1.0, strokeColor, strokeThickness, holes), vec3ZMean(v1, v2, v3, v4))];
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
const rawSvgPrefix = "data:image/svg+xml,";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Polygon, vec3ZMean, Vec3, Vec2, vec3TransRot, vec3RotCombine, vec3Zero } from "../../../abstract-3d.js";
|
|
1
|
+
import { Polygon, vec3ZMean, Vec3, Vec2, vec3TransRot, vec3RotCombine, vec3Zero, Material } from "../../../abstract-3d.js";
|
|
2
2
|
import { gray, zElem, zOrderElement, transparent, SvgOptions } from "./shared.js";
|
|
3
3
|
import { svgPolygon } from "../svg-encoding.js";
|
|
4
4
|
import { rgbGrayScale } from "../../shared.js";
|
|
@@ -7,7 +7,7 @@ export function polygon(
|
|
|
7
7
|
p: Polygon,
|
|
8
8
|
point: (x: number, y: number) => Vec2,
|
|
9
9
|
factor: number,
|
|
10
|
-
|
|
10
|
+
material: Material,
|
|
11
11
|
opts: SvgOptions,
|
|
12
12
|
parentPos: Vec3,
|
|
13
13
|
parentRot: Vec3
|
|
@@ -16,8 +16,9 @@ export function polygon(
|
|
|
16
16
|
const rot = vec3RotCombine(parentRot, p.rot ?? vec3Zero);
|
|
17
17
|
const rotatedPoints = p.points.map((p) => vec3TransRot(p, pos, rot));
|
|
18
18
|
const points = rotatedPoints.map(({ x, y }) => point(x, y));
|
|
19
|
+
const color = material.normal;
|
|
19
20
|
const [strokeColor, fill, strokeThickness] = opts.onlyStroke
|
|
20
21
|
? [opts.grayScale ? gray : color, opts.onlyStrokeFill, opts.stroke]
|
|
21
22
|
: [transparent, opts.grayScale ? rgbGrayScale(color) : color, 0];
|
|
22
|
-
return [zElem(svgPolygon(factor, rot, points, fill, strokeColor, strokeThickness), vec3ZMean(...rotatedPoints))];
|
|
23
|
+
return [zElem(svgPolygon(factor, rot, points, fill, material.opacity ?? 1.0, strokeColor, strokeThickness), vec3ZMean(...rotatedPoints))];
|
|
23
24
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { vec3ZMean, Vec3, Vec2, vec3TransRot, vec3RotCombine, Shape, vec3, vec3Zero } from "../../../abstract-3d.js";
|
|
1
|
+
import { vec3ZMean, Vec3, Vec2, vec3TransRot, vec3RotCombine, Shape, vec3, vec3Zero, Material } from "../../../abstract-3d.js";
|
|
2
2
|
import { gray, zElem, zOrderElement, transparent, SvgOptions } from "./shared.js";
|
|
3
3
|
import { svgPolygon } from "../svg-encoding.js";
|
|
4
4
|
import { rgbGrayScale } from "../../shared.js";
|
|
@@ -7,7 +7,7 @@ export function shape(
|
|
|
7
7
|
s: Shape,
|
|
8
8
|
point: (x: number, y: number) => Vec2,
|
|
9
9
|
factor: number,
|
|
10
|
-
|
|
10
|
+
material: Material,
|
|
11
11
|
opts: SvgOptions,
|
|
12
12
|
parentPos: Vec3,
|
|
13
13
|
parentRot: Vec3
|
|
@@ -16,8 +16,9 @@ export function shape(
|
|
|
16
16
|
const rot = vec3RotCombine(parentRot, s.rot ?? vec3Zero);
|
|
17
17
|
const rotatedPoints = s.points.map((p) => vec3TransRot(vec3(p.x, p.y, 0), pos, rot));
|
|
18
18
|
const points = rotatedPoints.map(({ x, y }) => point(x, y));
|
|
19
|
+
const color = material.normal;
|
|
19
20
|
const [strokeColor, fill] = opts.onlyStroke
|
|
20
21
|
? [opts.grayScale ? gray : color, opts.onlyStrokeFill]
|
|
21
22
|
: [transparent, opts.grayScale ? rgbGrayScale(color) : color];
|
|
22
|
-
return [zElem(svgPolygon(factor, rot, points, fill, strokeColor, 0), vec3ZMean(...rotatedPoints))];
|
|
23
|
+
return [zElem(svgPolygon(factor, rot, points, fill, material.opacity ?? 1.0, strokeColor, 0), vec3ZMean(...rotatedPoints))];
|
|
23
24
|
}
|
package/src/renderers/svg/svg.ts
CHANGED
|
@@ -123,24 +123,23 @@ function svgMesh(
|
|
|
123
123
|
material: Material,
|
|
124
124
|
opts: SvgOptions
|
|
125
125
|
): ReadonlyArray<zOrderElement> {
|
|
126
|
-
const color = material.normal;
|
|
127
126
|
switch (mesh.geometry.type) {
|
|
128
127
|
case "Box":
|
|
129
|
-
return box(mesh.geometry, point,
|
|
128
|
+
return box(mesh.geometry, point, material, opts, parentPos, parentRot, factor);
|
|
130
129
|
case "Plane":
|
|
131
130
|
return plane(mesh.geometry, point, factor, material, opts, parentPos, parentRot);
|
|
132
131
|
case "Cylinder":
|
|
133
|
-
return cylinder(mesh.geometry, point,
|
|
132
|
+
return cylinder(mesh.geometry, point, material, opts, parentPos, parentRot, factor);
|
|
134
133
|
case "Cone":
|
|
135
|
-
return cone(mesh.geometry, point,
|
|
134
|
+
return cone(mesh.geometry, point, material, opts, parentPos, parentRot, factor);
|
|
136
135
|
case "Line":
|
|
137
|
-
return line(mesh.geometry, point,
|
|
136
|
+
return line(mesh.geometry, point, material.normal, opts, parentPos, parentRot);
|
|
138
137
|
case "Polygon":
|
|
139
|
-
return polygon(mesh.geometry, point, factor,
|
|
138
|
+
return polygon(mesh.geometry, point, factor, material, opts, parentPos, parentRot);
|
|
140
139
|
case "Shape":
|
|
141
|
-
return shape(mesh.geometry, point, factor,
|
|
140
|
+
return shape(mesh.geometry, point, factor, material, opts, parentPos, parentRot);
|
|
142
141
|
case "Text":
|
|
143
|
-
return text(mesh.geometry, point,
|
|
142
|
+
return text(mesh.geometry, point, material.normal, opts, parentPos, parentRot, factor);
|
|
144
143
|
case "Tube":
|
|
145
144
|
case "Sphere":
|
|
146
145
|
return [];
|