abstract-3d 4.0.8 → 4.0.10

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.
Files changed (145) hide show
  1. package/lib/renderers/ifc/ifc.test.d.ts +2 -0
  2. package/lib/renderers/ifc/ifc.test.d.ts.map +1 -0
  3. package/lib/renderers/ifc/ifc.test.js +380 -0
  4. package/lib/renderers/ifc/ifc.test.js.map +1 -0
  5. package/lib/renderers/react/react-camera.d.ts +71 -0
  6. package/lib/renderers/react/react-camera.d.ts.map +1 -0
  7. package/lib/renderers/react/react-camera.js +201 -0
  8. package/lib/renderers/react/react-camera.js.map +1 -0
  9. package/lib/renderers/react/react-dimension.d.ts +27 -0
  10. package/lib/renderers/react/react-dimension.d.ts.map +1 -0
  11. package/lib/renderers/react/react-dimension.js +44 -0
  12. package/lib/renderers/react/react-dimension.js.map +1 -0
  13. package/lib/renderers/react/react-group.d.ts +29 -0
  14. package/lib/renderers/react/react-group.d.ts.map +1 -0
  15. package/lib/renderers/react/react-group.js +82 -0
  16. package/lib/renderers/react/react-group.js.map +1 -0
  17. package/lib/renderers/react/react-image-material.d.ts +30 -0
  18. package/lib/renderers/react/react-image-material.d.ts.map +1 -0
  19. package/lib/renderers/react/react-image-material.js +81 -0
  20. package/lib/renderers/react/react-image-material.js.map +1 -0
  21. package/lib/renderers/react/react-material.d.ts +19 -0
  22. package/lib/renderers/react/react-material.d.ts.map +1 -0
  23. package/lib/renderers/react/react-material.js +39 -0
  24. package/lib/renderers/react/react-material.js.map +1 -0
  25. package/lib/renderers/react/react-mesh.d.ts +11 -0
  26. package/lib/renderers/react/react-mesh.d.ts.map +1 -0
  27. package/lib/renderers/react/react-mesh.js +302 -0
  28. package/lib/renderers/react/react-mesh.js.map +1 -0
  29. package/lib/renderers/react/react-relation.d.ts +10 -0
  30. package/lib/renderers/react/react-relation.d.ts.map +1 -0
  31. package/lib/renderers/react/react-relation.js +31 -0
  32. package/lib/renderers/react/react-relation.js.map +1 -0
  33. package/lib/renderers/react/react-scene.d.ts +25 -0
  34. package/lib/renderers/react/react-scene.d.ts.map +1 -0
  35. package/lib/renderers/react/react-scene.js +13 -0
  36. package/lib/renderers/react/react-scene.js.map +1 -0
  37. package/lib/renderers/react/react-types.d.ts +7 -0
  38. package/lib/renderers/react/react-types.d.ts.map +1 -0
  39. package/lib/renderers/react/react-types.js +3 -0
  40. package/lib/renderers/react/react-types.js.map +1 -0
  41. package/lib/renderers/three/appearance/appearance.test.d.ts +2 -0
  42. package/lib/renderers/three/appearance/appearance.test.d.ts.map +1 -0
  43. package/lib/renderers/three/appearance/appearance.test.js +97 -0
  44. package/lib/renderers/three/appearance/appearance.test.js.map +1 -0
  45. package/lib/renderers/three/appearance.d.ts +41 -0
  46. package/lib/renderers/three/appearance.d.ts.map +1 -0
  47. package/lib/renderers/three/appearance.js +100 -0
  48. package/lib/renderers/three/appearance.js.map +1 -0
  49. package/lib/renderers/three/build/build.test.d.ts +2 -0
  50. package/lib/renderers/three/build/build.test.d.ts.map +1 -0
  51. package/lib/renderers/three/build/build.test.js +120 -0
  52. package/lib/renderers/three/build/build.test.js.map +1 -0
  53. package/lib/renderers/three/build/parts.js +7 -6
  54. package/lib/renderers/three/build/parts.js.map +1 -1
  55. package/lib/renderers/three/build.d.ts +50 -0
  56. package/lib/renderers/three/build.d.ts.map +1 -0
  57. package/lib/renderers/three/build.js +210 -0
  58. package/lib/renderers/three/build.js.map +1 -0
  59. package/lib/renderers/three/camera/camera.test.d.ts +2 -0
  60. package/lib/renderers/three/camera/camera.test.d.ts.map +1 -0
  61. package/lib/renderers/three/camera/camera.test.js +46 -0
  62. package/lib/renderers/three/camera/camera.test.js.map +1 -0
  63. package/lib/renderers/three/camera.d.ts +63 -0
  64. package/lib/renderers/three/camera.d.ts.map +1 -0
  65. package/lib/renderers/three/camera.js +85 -0
  66. package/lib/renderers/three/camera.js.map +1 -0
  67. package/lib/renderers/three/compile/compile.test.d.ts +2 -0
  68. package/lib/renderers/three/compile/compile.test.d.ts.map +1 -0
  69. package/lib/renderers/three/compile/compile.test.js +93 -0
  70. package/lib/renderers/three/compile/compile.test.js.map +1 -0
  71. package/lib/renderers/three/compile.d.ts +58 -0
  72. package/lib/renderers/three/compile.d.ts.map +1 -0
  73. package/lib/renderers/three/compile.js +89 -0
  74. package/lib/renderers/three/compile.js.map +1 -0
  75. package/lib/renderers/three/controls.d.ts +27 -0
  76. package/lib/renderers/three/controls.d.ts.map +1 -0
  77. package/lib/renderers/three/controls.js +115 -0
  78. package/lib/renderers/three/controls.js.map +1 -0
  79. package/lib/renderers/three/geometry/geometry.test.d.ts +2 -0
  80. package/lib/renderers/three/geometry/geometry.test.d.ts.map +1 -0
  81. package/lib/renderers/three/geometry/geometry.test.js +80 -0
  82. package/lib/renderers/three/geometry/geometry.test.js.map +1 -0
  83. package/lib/renderers/three/geometry.d.ts +20 -0
  84. package/lib/renderers/three/geometry.d.ts.map +1 -0
  85. package/lib/renderers/three/geometry.js +164 -0
  86. package/lib/renderers/three/geometry.js.map +1 -0
  87. package/lib/renderers/three/gizmo.d.ts +49 -0
  88. package/lib/renderers/three/gizmo.d.ts.map +1 -0
  89. package/lib/renderers/three/gizmo.js +172 -0
  90. package/lib/renderers/three/gizmo.js.map +1 -0
  91. package/lib/renderers/three/input.d.ts +25 -0
  92. package/lib/renderers/three/input.d.ts.map +1 -0
  93. package/lib/renderers/three/input.js +71 -0
  94. package/lib/renderers/three/input.js.map +1 -0
  95. package/lib/renderers/three/lines.d.ts +16 -0
  96. package/lib/renderers/three/lines.d.ts.map +1 -0
  97. package/lib/renderers/three/lines.js +63 -0
  98. package/lib/renderers/three/lines.js.map +1 -0
  99. package/lib/renderers/three/materials.d.ts +15 -0
  100. package/lib/renderers/three/materials.d.ts.map +1 -0
  101. package/lib/renderers/three/materials.js +70 -0
  102. package/lib/renderers/three/materials.js.map +1 -0
  103. package/lib/renderers/three/options.d.ts +68 -0
  104. package/lib/renderers/three/options.d.ts.map +1 -0
  105. package/lib/renderers/three/options.js +64 -0
  106. package/lib/renderers/three/options.js.map +1 -0
  107. package/lib/renderers/three/overlays.d.ts +25 -0
  108. package/lib/renderers/three/overlays.d.ts.map +1 -0
  109. package/lib/renderers/three/overlays.js +57 -0
  110. package/lib/renderers/three/overlays.js.map +1 -0
  111. package/lib/renderers/three/quality/quality.test.d.ts +2 -0
  112. package/lib/renderers/three/quality/quality.test.d.ts.map +1 -0
  113. package/lib/renderers/three/quality/quality.test.js +23 -0
  114. package/lib/renderers/three/quality/quality.test.js.map +1 -0
  115. package/lib/renderers/three/quality.d.ts +24 -0
  116. package/lib/renderers/three/quality.d.ts.map +1 -0
  117. package/lib/renderers/three/quality.js +67 -0
  118. package/lib/renderers/three/quality.js.map +1 -0
  119. package/lib/renderers/three/text/text.d.ts +4 -2
  120. package/lib/renderers/three/text/text.d.ts.map +1 -1
  121. package/lib/renderers/three/text/text.js +6 -4
  122. package/lib/renderers/three/text/text.js.map +1 -1
  123. package/lib/renderers/three/text/text.test.d.ts +2 -0
  124. package/lib/renderers/three/text/text.test.d.ts.map +1 -0
  125. package/lib/renderers/three/text/text.test.js +70 -0
  126. package/lib/renderers/three/text/text.test.js.map +1 -0
  127. package/lib/renderers/three/text.d.ts +53 -0
  128. package/lib/renderers/three/text.d.ts.map +1 -0
  129. package/lib/renderers/three/text.js +151 -0
  130. package/lib/renderers/three/text.js.map +1 -0
  131. package/lib/renderers/three/viewer/options.test.d.ts +2 -0
  132. package/lib/renderers/three/viewer/options.test.d.ts.map +1 -0
  133. package/lib/renderers/three/viewer/options.test.js +38 -0
  134. package/lib/renderers/three/viewer/options.test.js.map +1 -0
  135. package/lib/renderers/three/viewer/viewer.js +6 -0
  136. package/lib/renderers/three/viewer/viewer.js.map +1 -1
  137. package/lib/renderers/three/viewer.d.ts +38 -0
  138. package/lib/renderers/three/viewer.d.ts.map +1 -0
  139. package/lib/renderers/three/viewer.js +435 -0
  140. package/lib/renderers/three/viewer.js.map +1 -0
  141. package/package.json +3 -3
  142. package/src/renderers/three/build/parts.ts +7 -6
  143. package/src/renderers/three/text/text.test.ts +22 -17
  144. package/src/renderers/three/text/text.ts +6 -4
  145. package/src/renderers/three/viewer/viewer.ts +6 -0
@@ -0,0 +1,58 @@
1
+ import { Matrix4 } from "three";
2
+ import type { Group, Mesh, Relation, Scene, Vec3 } from "../../abstract-3d.js";
3
+ /** Scene → flat items with world matrices, with no GPU objects, so everything here is testable in Node */
4
+ /** How the item's geometry is drawn */
5
+ export type Role = "solid" | "text" | "line" | "image";
6
+ /** What the item belongs to, which decides its material and whether it's shown */
7
+ export type Style = "group" | "dimension" | "relation" | "outline";
8
+ /** What a pointer event on an item is about, and what hover and selection apply to */
9
+ export type Target = {
10
+ readonly kind: "group";
11
+ readonly id: string;
12
+ readonly root: number;
13
+ readonly rootData: Record<string, string> | undefined;
14
+ } | {
15
+ readonly kind: "dimension";
16
+ readonly id: string | undefined;
17
+ } | {
18
+ readonly kind: "relation";
19
+ readonly relation: Relation;
20
+ };
21
+ export type Item = {
22
+ readonly mesh: Mesh;
23
+ readonly role: Role;
24
+ readonly style: Style;
25
+ /** World matrix, or for an animated item its matrix relative to its animation's group */
26
+ readonly matrix: Matrix4;
27
+ readonly target: number;
28
+ /** The data of the group the mesh is in */
29
+ readonly data: Record<string, string> | undefined;
30
+ readonly animation: number | undefined;
31
+ };
32
+ export type Animation = {
33
+ readonly parent: number | undefined;
34
+ /** The matrix of the group's parent, in world space or relative to the parent animation's group */
35
+ readonly base: Matrix4;
36
+ readonly pos: Vec3;
37
+ readonly rot: Vec3;
38
+ /** Radians per second around x, y and z */
39
+ readonly speed: Vec3;
40
+ };
41
+ export type CompiledScene = {
42
+ readonly items: ReadonlyArray<Item>;
43
+ readonly targets: ReadonlyArray<Target>;
44
+ readonly animations: ReadonlyArray<Animation>;
45
+ /** World matrix of the scene's root, from its deprecated center and rotation */
46
+ readonly matrix: Matrix4;
47
+ /** World matrix of each top-level group */
48
+ readonly roots: ReadonlyArray<Matrix4>;
49
+ };
50
+ export type CompileOptions = {
51
+ readonly createGroupId?: (g: Group) => string;
52
+ };
53
+ export declare function compileScene(scene: Scene, options?: CompileOptions): CompiledScene;
54
+ /** The item's world matrix at `seconds` into its animations, written to `out` */
55
+ export declare function itemWorldMatrix(compiled: CompiledScene, item: Item, seconds: number, out: Matrix4): Matrix4;
56
+ /** Translation, then XYZ Euler rotation, then scale, as on a three.js Object3D */
57
+ export declare function transform(pos: Vec3, rot: Vec3 | undefined, out?: Matrix4, size?: Vec3 | undefined): Matrix4;
58
+ //# sourceMappingURL=compile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../../src/renderers/three/compile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ import { Euler, Matrix4, Quaternion, Vector3 } from "three";
2
+ import { dimensionConvertToTypeMesh, vec3, vec3Scale, vec3Zero } from "../../abstract-3d.js";
3
+ const outlineScale = 1.0125;
4
+ export function compileScene(scene, options = {}) {
5
+ const items = [];
6
+ const targets = [];
7
+ const animations = [];
8
+ const sceneMatrix = new Matrix4()
9
+ .makeTranslation(-(scene.center_deprecated?.x ?? 0), -(scene.center_deprecated?.y ?? 0), -(scene.center_deprecated?.z ?? 0))
10
+ .multiply(transform(vec3Zero, scene.rotation_deprecated));
11
+ const addMeshes = (meshes, parent, item) => meshes?.forEach((mesh) => {
12
+ items.push({ ...item, mesh, role: getRole(mesh), matrix: parent });
13
+ if (item.style === "relation" && mesh.geometry.type === "Box") {
14
+ const outline = { ...mesh.geometry, size: vec3Scale(mesh.geometry.size, outlineScale) };
15
+ items.push({ ...item, style: "outline", mesh: { ...mesh, geometry: outline }, role: "solid", matrix: parent });
16
+ }
17
+ });
18
+ const addGroup = (g, parent, animation, item) => {
19
+ const animated = g.animation !== undefined;
20
+ const ownAnimation = animated ? animations.push(createAnimation(g, parent, animation)) - 1 : animation;
21
+ const matrix = animated ? new Matrix4() : parent.clone().multiply(transform(g.pos, g.rot));
22
+ addMeshes(g.meshes, matrix, { ...item, data: g.data, animation: ownAnimation });
23
+ g.groups?.forEach((child) => addGroup(child, matrix, ownAnimation, item));
24
+ return matrix;
25
+ };
26
+ const roots = scene.groups.map((g, root) => {
27
+ const target = targets.push({ kind: "group", id: options.createGroupId?.(g) ?? "", root, rootData: g.data }) - 1;
28
+ addGroup(g, sceneMatrix, undefined, { style: "group", target });
29
+ return sceneMatrix.clone().multiply(transform(g.pos, g.rot));
30
+ });
31
+ scene.dimensions_deprecated?.dimensions.forEach((dimension) => {
32
+ const target = targets.push({ kind: "dimension", id: dimension.id }) - 1;
33
+ const mesh = dimensionConvertToTypeMesh(dimension, scene.rotation_deprecated ?? vec3Zero, scene.dimensions_deprecated?.material);
34
+ const matrix = sceneMatrix.clone().multiply(transform(mesh.pos, mesh.rot));
35
+ addMeshes(mesh.meshes, matrix, { style: "dimension", target, data: undefined, animation: undefined });
36
+ });
37
+ scene.relations?.forEach((relation) => {
38
+ const target = targets.push({ kind: "relation", relation }) - 1;
39
+ relation.groups?.forEach((g) => addGroup(g, sceneMatrix, undefined, { style: "relation", target }));
40
+ });
41
+ return { items, targets, animations, matrix: sceneMatrix, roots };
42
+ }
43
+ /** The item's world matrix at `seconds` into its animations, written to `out` */
44
+ export function itemWorldMatrix(compiled, item, seconds, out) {
45
+ return item.animation === undefined
46
+ ? out.copy(item.matrix)
47
+ : animationMatrix(compiled.animations, item.animation, seconds, out).multiply(item.matrix);
48
+ }
49
+ const scratchAnimation = new Matrix4();
50
+ function animationMatrix(animations, index, seconds, out) {
51
+ const a = animations[index];
52
+ const rot = vec3(a.rot.x + a.speed.x * seconds, a.rot.y + a.speed.y * seconds, a.rot.z + a.speed.z * seconds);
53
+ const local = out.copy(a.base).multiply(transform(a.pos, rot, scratchAnimation));
54
+ return a.parent === undefined ? local : local.premultiply(animationMatrix(animations, a.parent, seconds, new Matrix4()));
55
+ }
56
+ function createAnimation(g, parent, parentAnimation) {
57
+ const { transform: { rot }, duration, } = g.animation;
58
+ const perSecond = 1000 / duration;
59
+ return {
60
+ parent: parentAnimation,
61
+ base: parent.clone(),
62
+ pos: g.pos,
63
+ rot: g.rot ?? vec3Zero,
64
+ speed: vec3(rot.x * perSecond, rot.y * perSecond, rot.z * perSecond),
65
+ };
66
+ }
67
+ function getRole(mesh) {
68
+ switch (mesh.geometry.type) {
69
+ case "Text":
70
+ return "text";
71
+ case "Line":
72
+ case "CulledLine":
73
+ return "line";
74
+ case "Image":
75
+ return "image";
76
+ default:
77
+ return "solid";
78
+ }
79
+ }
80
+ const euler = new Euler();
81
+ const quaternion = new Quaternion();
82
+ const position = new Vector3();
83
+ const scale = new Vector3();
84
+ /** Translation, then XYZ Euler rotation, then scale, as on a three.js Object3D */
85
+ export function transform(pos, rot, out = new Matrix4(), size = undefined) {
86
+ quaternion.setFromEuler(euler.set(rot?.x ?? 0, rot?.y ?? 0, rot?.z ?? 0));
87
+ return out.compose(position.set(pos.x, pos.y, pos.z), quaternion, size ? scale.set(size.x, size.y, size.z) : scale.set(1, 1, 1));
88
+ }
89
+ //# sourceMappingURL=compile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile.js","sourceRoot":"","sources":["../../../src/renderers/three/compile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import CameraControls from "camera-controls";
2
+ import { type OrthographicCamera, type PerspectiveCamera, Vector3 } from "three";
3
+ import { OrbitControls } from "three/addons/controls/OrbitControls.js";
4
+ export type SmoothControlsOptions = Partial<Pick<CameraControls, "enabled" | "smoothTime" | "draggingSmoothTime" | "minDistance" | "maxDistance" | "minZoom" | "maxZoom" | "minPolarAngle" | "maxPolarAngle" | "minAzimuthAngle" | "maxAzimuthAngle" | "azimuthRotateSpeed" | "polarRotateSpeed" | "dollySpeed" | "truckSpeed" | "dollyToCursor">>;
5
+ export type OrbitControlsOptions = Partial<Pick<OrbitControls, "enabled" | "enableDamping" | "dampingFactor" | "enableZoom" | "zoomSpeed" | "enableRotate" | "rotateSpeed" | "enablePan" | "panSpeed" | "screenSpacePanning" | "minDistance" | "maxDistance" | "minZoom" | "maxZoom" | "minPolarAngle" | "maxPolarAngle" | "minAzimuthAngle" | "maxAzimuthAngle" | "zoomToCursor" | "autoRotate" | "autoRotateSpeed" | "keyPanSpeed">> & {
6
+ readonly onStart?: () => void;
7
+ readonly onChange?: () => void;
8
+ readonly onEnd?: () => void;
9
+ };
10
+ export type ControlsOptions = {
11
+ readonly type: "smooth";
12
+ readonly options?: SmoothControlsOptions;
13
+ } | {
14
+ readonly type: "orbit";
15
+ readonly options?: OrbitControlsOptions;
16
+ };
17
+ export type Rig = {
18
+ /** Moves the camera by input and transitions, true while it moves */
19
+ readonly update: (delta: number) => boolean;
20
+ readonly setPose: (position: Vector3, target: Vector3, animate: boolean) => void;
21
+ readonly getTarget: (out: Vector3) => Vector3;
22
+ /** The user drags the camera, and it has moved since the drag started */
23
+ readonly isDragging: () => boolean;
24
+ readonly dispose: () => void;
25
+ };
26
+ export declare function createRig(controls: ControlsOptions, camera: PerspectiveCamera | OrthographicCamera, element: HTMLElement, onInput: () => void): Rig;
27
+ //# sourceMappingURL=controls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controls.d.ts","sourceRoot":"","sources":["../../../src/renderers/three/controls.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAIL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EAMtB,OAAO,EAER,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AASvE,MAAM,MAAM,qBAAqB,GAAG,OAAO,CACzC,IAAI,CACF,cAAc,EACZ,SAAS,GACT,YAAY,GACZ,oBAAoB,GACpB,aAAa,GACb,aAAa,GACb,SAAS,GACT,SAAS,GACT,eAAe,GACf,eAAe,GACf,iBAAiB,GACjB,iBAAiB,GACjB,oBAAoB,GACpB,kBAAkB,GAClB,YAAY,GACZ,YAAY,GACZ,eAAe,CAClB,CACF,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,OAAO,CACxC,IAAI,CACF,aAAa,EACX,SAAS,GACT,eAAe,GACf,eAAe,GACf,YAAY,GACZ,WAAW,GACX,cAAc,GACd,aAAa,GACb,WAAW,GACX,UAAU,GACV,oBAAoB,GACpB,aAAa,GACb,aAAa,GACb,SAAS,GACT,SAAS,GACT,eAAe,GACf,eAAe,GACf,iBAAiB,GACjB,iBAAiB,GACjB,cAAc,GACd,YAAY,GACZ,iBAAiB,GACjB,aAAa,CAChB,CACF,GAAG;IACF,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,qBAAqB,CAAA;CAAE,GACrE;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,oBAAoB,CAAA;CAAE,CAAC;AAExE,MAAM,MAAM,GAAG,GAAG;IAChB,qEAAqE;IACrE,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAC5C,QAAQ,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACjF,QAAQ,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;IAC9C,yEAAyE;IACzE,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B,CAAC;AAEF,wBAAgB,SAAS,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,iBAAiB,GAAG,kBAAkB,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,GAAG,CAInJ"}
@@ -0,0 +1,115 @@
1
+ import CameraControls from "camera-controls";
2
+ import { Box3, MathUtils, Matrix4, Quaternion, Raycaster, Sphere, Spherical, Vector2, Vector3, Vector4, } from "three";
3
+ import { OrbitControls } from "three/addons/controls/OrbitControls.js";
4
+ /**
5
+ * Camera controls: smooth by default (camera-controls), or the r3f renderer's OrbitControls, kept as an option with its behavior: damping, callbacks
6
+ * and an animated turn to the gizmo's views
7
+ */
8
+ CameraControls.install({ THREE: { Vector2, Vector3, Vector4, Quaternion, Matrix4, Spherical, Box3, Sphere, Raycaster } });
9
+ export function createRig(controls, camera, element, onInput) {
10
+ return controls.type === "orbit"
11
+ ? createOrbitRig(controls.options ?? {}, camera, element, onInput)
12
+ : createSmoothRig(controls.options ?? {}, camera, element, onInput);
13
+ }
14
+ function createSmoothRig(options, camera, element, onInput) {
15
+ const controls = new CameraControls(camera, element);
16
+ Object.assign(controls, { smoothTime: 0.15, draggingSmoothTime: 0.08, ...options });
17
+ const drag = { active: false, moved: false };
18
+ controls.addEventListener("controlstart", () => {
19
+ Object.assign(drag, { active: true, moved: false });
20
+ onInput();
21
+ });
22
+ controls.addEventListener("control", () => {
23
+ drag.moved = drag.active;
24
+ onInput();
25
+ });
26
+ controls.addEventListener("controlend", () => Object.assign(drag, { active: false, moved: false }));
27
+ // The wheel doesn't emit control events
28
+ element.addEventListener("wheel", onInput, { passive: true });
29
+ return {
30
+ update: (delta) => controls.update(delta),
31
+ setPose: (position, target, animate) => void controls.setLookAt(position.x, position.y, position.z, target.x, target.y, target.z, animate),
32
+ getTarget: (out) => controls.getTarget(out),
33
+ isDragging: () => drag.moved,
34
+ dispose: () => {
35
+ element.removeEventListener("wheel", onInput);
36
+ controls.dispose();
37
+ },
38
+ };
39
+ }
40
+ const turnSeconds = 0.4;
41
+ function createOrbitRig(options, camera, element, onInput) {
42
+ const { onStart, onChange, onEnd, ...properties } = options;
43
+ const controls = new OrbitControls(camera, element);
44
+ // drei's OrbitControls default
45
+ Object.assign(controls, { enableDamping: true, ...properties });
46
+ const drag = { active: false, moved: false };
47
+ controls.addEventListener("start", () => {
48
+ Object.assign(drag, { active: true, moved: false });
49
+ onStart?.();
50
+ onInput();
51
+ });
52
+ controls.addEventListener("change", () => {
53
+ drag.moved = drag.active;
54
+ onChange?.();
55
+ onInput();
56
+ });
57
+ controls.addEventListener("end", () => {
58
+ Object.assign(drag, { active: false, moved: false });
59
+ onEnd?.();
60
+ });
61
+ // A turn to a new pose, rotating around the target on a sphere while the distance and target move linearly
62
+ const turn = {
63
+ elapsed: turnSeconds,
64
+ fromTarget: new Vector3(),
65
+ toTarget: new Vector3(),
66
+ from: new Quaternion(),
67
+ to: new Quaternion(),
68
+ fromDistance: 0,
69
+ toDistance: 0,
70
+ };
71
+ const direction = new Vector3();
72
+ const forward = new Vector3(0, 0, 1);
73
+ const step = (delta) => {
74
+ if (turn.elapsed >= turnSeconds) {
75
+ return false;
76
+ }
77
+ turn.elapsed = Math.min(turnSeconds, turn.elapsed + delta);
78
+ const t = MathUtils.smootherstep(turn.elapsed / turnSeconds, 0, 1);
79
+ controls.target.lerpVectors(turn.fromTarget, turn.toTarget, t);
80
+ direction.copy(forward).applyQuaternion(scratchQuaternion.slerpQuaternions(turn.from, turn.to, t));
81
+ camera.position.copy(controls.target).addScaledVector(direction, MathUtils.lerp(turn.fromDistance, turn.toDistance, t));
82
+ return true;
83
+ };
84
+ return {
85
+ update: (delta) => {
86
+ const turning = step(delta);
87
+ return controls.update(delta) || turning;
88
+ },
89
+ setPose: (position, target, animate) => {
90
+ if (!animate) {
91
+ turn.elapsed = turnSeconds;
92
+ controls.target.copy(target);
93
+ camera.position.copy(position);
94
+ controls.update();
95
+ return;
96
+ }
97
+ const fromOffset = scratchVector.subVectors(camera.position, controls.target);
98
+ turn.fromDistance = fromOffset.length();
99
+ turn.from.setFromUnitVectors(forward, fromOffset.normalize());
100
+ const toOffset = scratchVector.subVectors(position, target);
101
+ turn.toDistance = toOffset.length();
102
+ turn.to.setFromUnitVectors(forward, toOffset.normalize());
103
+ turn.fromTarget.copy(controls.target);
104
+ turn.toTarget.copy(target);
105
+ turn.elapsed = 0;
106
+ onInput();
107
+ },
108
+ getTarget: (out) => out.copy(controls.target),
109
+ isDragging: () => drag.moved,
110
+ dispose: () => controls.dispose(),
111
+ };
112
+ }
113
+ const scratchVector = new Vector3();
114
+ const scratchQuaternion = new Quaternion();
115
+ //# sourceMappingURL=controls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controls.js","sourceRoot":"","sources":["../../../src/renderers/three/controls.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=geometry.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geometry.test.d.ts","sourceRoot":"","sources":["../../../../src/renderers/three/geometry/geometry.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,80 @@
1
+ import { Vector3 } from "three";
2
+ import { describe, expect, it } from "vitest";
3
+ import { box, circleCurve, cone, cylinder, plane, polygon, roundHole, shape, sphere, tube, vec2, vec3, vec3Zero } from "../../../abstract-3d.js";
4
+ import { createSolidGeometry, getSolidShape, keepGeometries } from "./geometry.js";
5
+ const m = { normal: "rgb(0,0,0)" };
6
+ const local = (mesh, x, y, z) => new Vector3(x, y, z)
7
+ .applyMatrix4(getSolidShape(mesh.geometry).local)
8
+ .toArray()
9
+ .map((v) => Math.round(v * 1000) / 1000 + 0);
10
+ const key = (mesh) => getSolidShape(mesh.geometry).key;
11
+ const bounds = (mesh) => {
12
+ const geometry = createSolidGeometry(mesh.geometry);
13
+ geometry.computeBoundingBox();
14
+ return [...geometry.boundingBox.min.toArray(), ...geometry.boundingBox.max.toArray()].map((v) => Math.round(v * 1000) / 1000 + 0);
15
+ };
16
+ describe("getSolidShape", () => {
17
+ it("shares unit geometries between primitives of any size, scaled by the local matrix", () => {
18
+ expect(key(box(vec3(1, 2, 3), m))).toBe(key(box(vec3(4, 5, 6), m)));
19
+ expect(local(box(vec3(2, 4, 6), m, vec3(10, 0, 0)), 0.5, 0.5, 0.5)).toEqual([11, 2, 3]);
20
+ expect(local(plane(vec3Zero, vec2(2, 4), m), 0.5, 0.5, 0)).toEqual([1, 2, 0]);
21
+ expect(local(sphere(3, m, vec3(1, 0, 0)), 1, 0, 0)).toEqual([4, 0, 0]);
22
+ expect(local(cone(vec3Zero, 2, 10, m), 1, 0.5, 0)).toEqual([2, 5, 0]);
23
+ });
24
+ it("scales cylinders by their largest radius, with a geometry per radius ratio", () => {
25
+ expect(key(cylinder(vec3Zero, 1, 2, m))).toBe(key(cylinder(vec3Zero, 5, 7, m)));
26
+ expect(key(cylinder(vec3Zero, 1, 2, m))).not.toBe(key(cylinder(vec3Zero, 1, 2, m, vec3Zero, false, [], 0, Math.PI * 2, 2)));
27
+ expect(local(cylinder(vec3Zero, 1, 10, m, vec3Zero, false, [], 0, Math.PI * 2, 4), 1, 0.5, 0)).toEqual([4, 5, 0]);
28
+ });
29
+ it("ignores zero holes", () => {
30
+ expect(key(box(vec3(1, 1, 1), m, vec3Zero, vec3Zero, [roundHole(vec2(0, 0), 0)]))).toBe(key(box(vec3(2, 2, 2), m)));
31
+ });
32
+ it("extrudes primitives with holes into their own geometry, centered", () => {
33
+ const holed = box(vec3(10, 10, 2), m, vec3(1, 0, 0), vec3Zero, [roundHole(vec2(0, 0), 2)]);
34
+ expect(key(holed)).not.toBe(key(box(vec3(10, 10, 2), m)));
35
+ expect(local(holed, 0, 0, 0)).toEqual([1, 0, 0]);
36
+ expect(bounds(holed)).toEqual([-5, -5, -1, 5, 5, 1]);
37
+ expect(bounds(cylinder(vec3Zero, 2, 10, m, vec3Zero, false, [roundHole(vec2(0, 0), 1)]))).toEqual([-2, -5, -2, 2, 5, 2]);
38
+ });
39
+ });
40
+ describe("createSolidGeometry", () => {
41
+ it("closes partial cylinders with walls", () => {
42
+ const whole = createSolidGeometry(cylinder(vec3Zero, 1, 1, m).geometry);
43
+ const half = createSolidGeometry(cylinder(vec3Zero, 1, 1, m, vec3Zero, false, [], 0, Math.PI).geometry);
44
+ expect(half.getAttribute("position").count).toBeGreaterThan(whole.getAttribute("position").count / 2);
45
+ });
46
+ it("draws 4-point polygons as a quad and other polygons as a triangle list", () => {
47
+ expect(createSolidGeometry(polygon([vec3(0, 0, 0), vec3(1, 0, 0), vec3(1, 1, 0), vec3(0, 1, 0)], m).geometry).index.count).toBe(6);
48
+ expect(createSolidGeometry(polygon([vec3(0, 0, 0), vec3(1, 0, 0), vec3(1, 1, 0)], m).geometry).index.count).toBe(3);
49
+ });
50
+ it("gives every geometry an index, normals and uvs, so they can share a batch", () => {
51
+ const meshes = [
52
+ box(vec3(1, 1, 1), m),
53
+ box(vec3(1, 1, 1), m, vec3Zero, vec3Zero, [roundHole(vec2(0, 0), 0.1)]),
54
+ polygon([vec3(0, 0, 0), vec3(1, 0, 0), vec3(1, 1, 0)], m),
55
+ cylinder(vec3Zero, 1, 1, m, vec3Zero, false, [], 0, Math.PI),
56
+ shape([vec2(0, 0), vec2(1, 0), vec2(0, 1)], vec3Zero, m, 1),
57
+ tube(circleCurve(10, 0, Math.PI), 1, m),
58
+ ];
59
+ meshes.forEach((mesh) => {
60
+ const geometry = createSolidGeometry(mesh.geometry);
61
+ expect(geometry.index.count).toBeGreaterThan(0);
62
+ expect(Object.keys(geometry.attributes).toSorted()).toEqual(["normal", "position", "uv"]);
63
+ });
64
+ });
65
+ });
66
+ describe("keepGeometries", () => {
67
+ it("disposes the geometries a build no longer uses", () => {
68
+ const [kept, unused] = [createSolidGeometry(box(vec3(1, 1, 1), m).geometry), createSolidGeometry(sphere(1, m).geometry)];
69
+ const cache = new Map([
70
+ ["Box", kept],
71
+ ["Sphere", unused],
72
+ ]);
73
+ const disposed = [];
74
+ unused.addEventListener("dispose", () => disposed.push("Sphere"));
75
+ keepGeometries(cache, new Set(["Box"]));
76
+ expect(disposed).toEqual(["Sphere"]);
77
+ expect([...cache.keys()]).toEqual(["Box"]);
78
+ });
79
+ });
80
+ //# sourceMappingURL=geometry.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geometry.test.js","sourceRoot":"","sources":["../../../../src/renderers/three/geometry/geometry.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,OAAO,EAAE,MAAM,OAAO,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACjJ,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEnF,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;AACnC,MAAM,KAAK,GAAG,CAAC,IAAU,EAAE,CAAS,EAAE,CAAS,EAAE,CAAS,EAAyB,EAAE,CACnF,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;KACjB,YAAY,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAE,CAAC,KAAK,CAAC;KACjD,OAAO,EAAE;KACT,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC;AACjD,MAAM,GAAG,GAAG,CAAC,IAAU,EAAU,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAE,CAAC,GAAG,CAAC;AACtE,MAAM,MAAM,GAAG,CAAC,IAAU,EAAyB,EAAE;IACnD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpD,QAAQ,CAAC,kBAAkB,EAAE,CAAC;IAC9B,OAAO,CAAC,GAAG,QAAQ,CAAC,WAAY,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,GAAG,QAAQ,CAAC,WAAY,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC;AACtI,CAAC,CAAC;AAEF,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,mFAAmF,EAAE,GAAG,EAAE;QAC3F,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACxF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9E,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACvE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;QACpF,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAChF,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5H,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACpH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC5B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACtH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3F,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1D,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACjD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3H,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,KAAK,GAAG,mBAAmB,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QACxE,MAAM,IAAI,GAAG,mBAAmB,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;QACxG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IACxG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;QAChF,MAAM,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpI,MAAM,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2EAA2E,EAAE,GAAG,EAAE;QACnF,MAAM,MAAM,GAAG;YACb,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YACrB,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YACvE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACzD,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC;YAC5D,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;YAC3D,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;SACxC,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YACtB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACpD,MAAM,CAAC,QAAQ,CAAC,KAAM,CAAC,KAAK,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YACjD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC;QAC5F,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzH,MAAM,KAAK,GAAG,IAAI,GAAG,CAAyB;YAC5C,CAAC,KAAK,EAAE,IAAI,CAAC;YACb,CAAC,QAAQ,EAAE,MAAM,CAAC;SACnB,CAAC,CAAC;QACH,MAAM,QAAQ,GAAkB,EAAE,CAAC;QACnC,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QAClE,cAAc,CAAC,KAAK,EAAE,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACrC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { type BufferGeometry, Matrix4 } from "three";
2
+ import type { Mesh } from "../../abstract-3d.js";
3
+ /** Solid geometries by key, so identical shapes share one geometry; primitives are unit geometries scaled by their local matrix */
4
+ export type SolidShape = {
5
+ readonly key: string;
6
+ readonly create: () => BufferGeometry;
7
+ /** Position, rotation and, for unit geometries, scale, relative to the item's matrix */
8
+ readonly local: Matrix4;
9
+ };
10
+ /** The shape of a solid geometry, undefined for text, lines and images; it creates indexed geometries with position, normal and uv */
11
+ export declare function getSolidShape(geometry: Mesh["geometry"]): SolidShape | undefined;
12
+ export type GeometryCache = {
13
+ /** The shape's geometry, created on first use */
14
+ readonly get: (shape: SolidShape) => BufferGeometry;
15
+ /** Disposes the geometries whose keys aren't in `keys` */
16
+ readonly keepOnly: (keys: ReadonlySet<string>) => void;
17
+ readonly dispose: () => void;
18
+ };
19
+ export declare function createGeometryCache(): GeometryCache;
20
+ //# sourceMappingURL=geometry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../../../src/renderers/three/geometry.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EAOnB,OAAO,EAMR,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAiB,IAAI,EAAe,MAAM,sBAAsB,CAAC;AAK7E,mIAAmI;AAEnI,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,cAAc,CAAC;IACtC,wFAAwF;IACxF,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,sIAAsI;AACtI,wBAAgB,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,GAAG,UAAU,GAAG,SAAS,CAGhF;AAkED,MAAM,MAAM,aAAa,GAAG;IAC1B,iDAAiD;IACjD,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,cAAc,CAAC;IACpD,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IACvD,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B,CAAC;AAEF,wBAAgB,mBAAmB,IAAI,aAAa,CAsBnD"}
@@ -0,0 +1,164 @@
1
+ import { BoxGeometry, BufferGeometry as ThreeBufferGeometry, CatmullRomCurve3, ConeGeometry, CylinderGeometry, ExtrudeGeometry, Float32BufferAttribute, Matrix4, PlaneGeometry, Shape, SphereGeometry, TubeGeometry, Vector3, } from "three";
2
+ import { mergeGeometries } from "three/addons/utils/BufferGeometryUtils.js";
3
+ import { isZero, vec2Scale, vec3, vec3Zero } from "../../abstract-3d.js";
4
+ import { addHoles, CircleCurve, CYLINDER_SEGMENTS, cylinderCutPositions, nonZeroHoles } from "../shared/three-geometry.js";
5
+ import { transform } from "./compile.js";
6
+ /** The shape of a solid geometry, undefined for text, lines and images; it creates indexed geometries with position, normal and uv */
7
+ export function getSolidShape(geometry) {
8
+ const shape = getShape(geometry);
9
+ return shape && { ...shape, create: () => normalized(shape.create()) };
10
+ }
11
+ function getShape(geometry) {
12
+ switch (geometry.type) {
13
+ case "Box": {
14
+ const { pos, rot, size } = geometry;
15
+ return nonZeroHoles(geometry.holes).length === 0
16
+ ? { key: "box", create: () => new BoxGeometry(), local: transform(pos, rot, new Matrix4(), size) }
17
+ : extrudedRectangle("box", geometry, size.z);
18
+ }
19
+ case "Plane": {
20
+ const { pos, rot, size } = geometry;
21
+ return nonZeroHoles(geometry.holes).length === 0
22
+ ? { key: "plane", create: () => new PlaneGeometry(), local: transform(pos, rot, new Matrix4(), vec3(size.x, size.y, 1)) }
23
+ : extrudedRectangle("plane", geometry, 0);
24
+ }
25
+ case "Sphere":
26
+ return {
27
+ key: "sphere",
28
+ create: () => new SphereGeometry(1, 12, 12),
29
+ local: transform(geometry.pos, vec3Zero, new Matrix4(), vec3(geometry.radius, geometry.radius, geometry.radius)),
30
+ };
31
+ case "Cone": {
32
+ const { pos, rot, radius, length } = geometry;
33
+ return { key: "cone", create: () => new ConeGeometry(1, 1, 16, 1), local: transform(pos, rot, new Matrix4(), vec3(radius, length, radius)) };
34
+ }
35
+ case "Cylinder":
36
+ return cylinderShape(geometry);
37
+ case "Shape": {
38
+ const { points, holes, thickness, pos, rot } = geometry;
39
+ return {
40
+ key: `shape:${JSON.stringify([points, nonZeroHoles(holes), thickness])}`,
41
+ create: () => {
42
+ const shape = new Shape();
43
+ points.forEach((p, i) => (i === 0 ? shape.moveTo(p.x, p.y) : shape.lineTo(p.x, p.y)));
44
+ shape.closePath();
45
+ addHoles(holes, shape);
46
+ return new ExtrudeGeometry(shape, { depth: thickness, bevelEnabled: false }).translate(0, 0, -thickness / 2);
47
+ },
48
+ local: transform(pos, rot),
49
+ };
50
+ }
51
+ case "Polygon": {
52
+ const { points, pos, rot } = geometry;
53
+ return { key: `polygon:${JSON.stringify(points)}`, create: () => polygonGeometry(points), local: transform(pos, rot) };
54
+ }
55
+ case "Tube": {
56
+ const { curve, radius, pos, rot } = geometry;
57
+ return {
58
+ key: `tube:${JSON.stringify([curve, radius])}`,
59
+ create: () => new TubeGeometry(curve.type === "SplineCurve" ? new CatmullRomCurve3(curve.points.map((p) => new Vector3(p.x, p.y, p.z))) : new CircleCurve(curve), 9, radius, 9, false),
60
+ local: transform(pos, rot),
61
+ };
62
+ }
63
+ default:
64
+ return undefined;
65
+ }
66
+ }
67
+ export function createGeometryCache() {
68
+ const geometries = new Map();
69
+ const keepOnly = (keys) => geometries.forEach((geometry, key) => {
70
+ if (!keys.has(key)) {
71
+ geometry.dispose();
72
+ geometries.delete(key);
73
+ }
74
+ });
75
+ return {
76
+ get: (shape) => {
77
+ const cached = geometries.get(shape.key);
78
+ if (cached) {
79
+ return cached;
80
+ }
81
+ const geometry = shape.create();
82
+ geometries.set(shape.key, geometry);
83
+ return geometry;
84
+ },
85
+ keepOnly,
86
+ dispose: () => keepOnly(new Set()),
87
+ };
88
+ }
89
+ function cylinderShape(geometry) {
90
+ const { pos, rot, radius, radiusEnd = radius, length, holes, open = false, angleStart = 0, angleLength = Math.PI * 2 } = geometry;
91
+ const isWhole = isZero(Math.PI * 2 - angleLength);
92
+ // Holes are extruded along the length, which can't taper
93
+ if (isWhole && radiusEnd === radius && nonZeroHoles(holes).length > 0) {
94
+ return {
95
+ key: `cylinder-holes:${JSON.stringify([radius, length, nonZeroHoles(holes)])}`,
96
+ create: () => {
97
+ const shape = new Shape();
98
+ shape.moveTo(0, radius).absellipse(0, 0, radius, radius, 0, Math.PI * 2, true);
99
+ addHoles(holes, shape);
100
+ return new ExtrudeGeometry(shape, { depth: length, bevelEnabled: false }).rotateX(Math.PI / 2).translate(0, length / 2, 0);
101
+ },
102
+ local: transform(pos, rot),
103
+ };
104
+ }
105
+ // Unit geometry scaled by the largest radius, so only the radius ratio needs its own geometry
106
+ const maxRadius = Math.max(radius, radiusEnd);
107
+ const top = radiusEnd / (maxRadius || 1);
108
+ const bottom = radius / (maxRadius || 1);
109
+ const local = transform(pos, rot, new Matrix4(), vec3(maxRadius, length, maxRadius));
110
+ return isWhole
111
+ ? { key: `cylinder:${top}:${bottom}:${open}`, create: () => new CylinderGeometry(top, bottom, 1, CYLINDER_SEGMENTS, 1, open), local }
112
+ : {
113
+ key: `cylinder-part:${top}:${bottom}:${angleStart}:${angleLength}`,
114
+ create: () => {
115
+ const walls = new ThreeBufferGeometry();
116
+ walls.setAttribute("position", new Float32BufferAttribute(cylinderCutPositions(top, bottom, 1, angleStart, angleLength), 3));
117
+ walls.computeVertexNormals();
118
+ const mantle = new CylinderGeometry(top, bottom, 1, CYLINDER_SEGMENTS, 1, false, angleStart, angleLength);
119
+ return mergeGeometries([normalized(mantle), normalized(walls)]);
120
+ },
121
+ local,
122
+ };
123
+ }
124
+ function extrudedRectangle(kind, geometry, depth) {
125
+ const half = vec2Scale(geometry.size, 0.5);
126
+ return {
127
+ key: `${kind}-holes:${JSON.stringify([geometry.size, nonZeroHoles(geometry.holes)])}`,
128
+ create: () => {
129
+ const shape = new Shape();
130
+ shape.moveTo(-half.x, -half.y).lineTo(-half.x, half.y).lineTo(half.x, half.y).lineTo(half.x, -half.y).closePath();
131
+ addHoles(geometry.holes, shape);
132
+ return new ExtrudeGeometry(shape, { depth, bevelEnabled: false }).translate(0, 0, -depth / 2);
133
+ },
134
+ local: transform(geometry.pos, geometry.rot),
135
+ };
136
+ }
137
+ /** A quad for 4 points, else a list of triangles, as the points are given */
138
+ function polygonGeometry(points) {
139
+ const corners = points.length === 4 ? [0, 1, 2, 2, 3, 0] : points.slice(0, Math.floor(points.length / 3) * 3).map((_, i) => i);
140
+ const geometry = new ThreeBufferGeometry();
141
+ geometry.setAttribute("position", new Float32BufferAttribute(points.flatMap((p) => [p.x, p.y, p.z]), 3));
142
+ geometry.setIndex(corners);
143
+ geometry.computeVertexNormals();
144
+ return geometry;
145
+ }
146
+ /** Indexed, with exactly position, normal and uv attributes and no groups, as a BatchedMesh needs */
147
+ function normalized(geometry) {
148
+ const count = geometry.getAttribute("position").count;
149
+ if (!geometry.index) {
150
+ geometry.setIndex(Array.from({ length: count }, (_, i) => i));
151
+ }
152
+ if (!geometry.hasAttribute("normal")) {
153
+ geometry.computeVertexNormals();
154
+ }
155
+ if (!geometry.hasAttribute("uv")) {
156
+ geometry.setAttribute("uv", new Float32BufferAttribute(new Float32Array(count * 2), 2));
157
+ }
158
+ Object.keys(geometry.attributes)
159
+ .filter((name) => name !== "position" && name !== "normal" && name !== "uv")
160
+ .forEach((name) => geometry.deleteAttribute(name));
161
+ geometry.clearGroups();
162
+ return geometry;
163
+ }
164
+ //# sourceMappingURL=geometry.js.map