@woosh/meep-engine 2.143.0 → 2.145.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/package.json +1 -1
- package/src/core/bvh2/bvh3/BVH.d.ts.map +1 -1
- package/src/core/bvh2/bvh3/BVH.js +158 -4
- package/src/core/geom/3d/shape/CylinderShape3D.d.ts +56 -0
- package/src/core/geom/3d/shape/CylinderShape3D.d.ts.map +1 -0
- package/src/core/geom/3d/shape/CylinderShape3D.js +223 -0
- package/src/core/geom/3d/shape/PointShape3D.d.ts +1 -0
- package/src/core/geom/3d/shape/PointShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/PointShape3D.js +11 -0
- package/src/core/geom/3d/shape/SphereShape3D.d.ts +1 -0
- package/src/core/geom/3d/shape/SphereShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/SphereShape3D.js +4 -0
- package/src/core/geom/3d/shape/json/shape_to_type.d.ts.map +1 -1
- package/src/core/geom/3d/shape/json/shape_to_type.js +3 -0
- package/src/core/geom/3d/shape/json/type_adapters.d.ts +15 -0
- package/src/core/geom/3d/shape/json/type_adapters.d.ts.map +1 -1
- package/src/core/geom/3d/shape/json/type_adapters.js +16 -0
- package/src/engine/control/first-person/DESIGN_COLLISION.md +314 -217
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts +104 -58
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts.map +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +1828 -1789
- package/src/engine/control/first-person/TODO.md +17 -32
- package/src/engine/control/first-person/abilities/WallRun.d.ts.map +1 -1
- package/src/engine/control/first-person/abilities/WallRun.js +18 -35
- package/src/engine/control/first-person/collision/KinematicMover.d.ts +206 -0
- package/src/engine/control/first-person/collision/KinematicMover.d.ts.map +1 -0
- package/src/engine/control/first-person/collision/KinematicMover.js +592 -0
- package/src/engine/control/first-person/prototype_first_person_controller.js +65 -0
- package/src/engine/graphics/render/buffer/simple-fx/ao/SAOShader.js +18 -9
- package/src/engine/physics/PLAN.md +145 -41
- package/src/engine/physics/contact/ManifoldStore.d.ts +28 -2
- package/src/engine/physics/contact/ManifoldStore.d.ts.map +1 -1
- package/src/engine/physics/contact/ManifoldStore.js +37 -3
- package/src/engine/physics/contact/combine_material.d.ts +30 -0
- package/src/engine/physics/contact/combine_material.d.ts.map +1 -0
- package/src/engine/physics/contact/combine_material.js +35 -0
- package/src/engine/physics/ecs/Collider.d.ts +15 -0
- package/src/engine/physics/ecs/Collider.d.ts.map +1 -1
- package/src/engine/physics/ecs/Collider.js +34 -0
- package/src/engine/physics/ecs/Joint.d.ts +18 -0
- package/src/engine/physics/ecs/Joint.d.ts.map +1 -1
- package/src/engine/physics/ecs/Joint.js +70 -0
- package/src/engine/physics/ecs/PhysicsSystem.d.ts +9 -4
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +9 -4
- package/src/engine/physics/ecs/RigidBody.d.ts +15 -0
- package/src/engine/physics/ecs/RigidBody.d.ts.map +1 -1
- package/src/engine/physics/ecs/RigidBody.js +46 -0
- package/src/engine/physics/narrowphase/compute_penetration.d.ts +41 -41
- package/src/engine/physics/narrowphase/compute_penetration.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/compute_penetration.js +96 -169
- package/src/engine/physics/narrowphase/narrowphase_step.d.ts +52 -0
- package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/narrowphase_step.js +130 -3
- package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -1
- package/src/engine/physics/solver/solve_contacts.js +10 -21
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"description": "Pure JavaScript game engine. Fully featured and production ready.",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"author": "Alexander Goldring",
|
|
9
|
-
"version": "2.
|
|
9
|
+
"version": "2.145.0",
|
|
10
10
|
"main": "build/meep.module.js",
|
|
11
11
|
"module": "build/meep.module.js",
|
|
12
12
|
"exports": {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BVH.d.ts","sourceRoot":"","sources":["../../../../../src/core/bvh2/bvh3/BVH.js"],"names":[],"mappings":"AASA,8BAA+B;AAC/B,+BAAgC;AAChC,+BAAgC;AAChC,8BAA+B;AAE/B;;;;;GAKG;AACH,+BAFU,MAAM,CAE+B;AAE/C;;;GAGG;AACH,wBAFU,MAAM,CAEoB;AAcpC;;;;;GAKG;AACH,iCAFU,MAAM,CAEqB;AAiBrC;;;;;;;;GAQG;AACH;IAEI;;;;OAIG;IACH,sBAAuE;IAYvE;;;;;OAKG;IACH,kCAUC;IA1BD;;;;;OAKG;IACH,+BAEC;IAoBD;;;;OAIG;IACH,uBAAsD;IAUtD;;;;OAIG;IACH,sBAAoD;IAsEpD;;;OAGG;IACH,+BAMC;IAlBD;;;OAGG;IACH,4BAEC;IAjFD;;;OAGG;IACH,iCAEC;IASD;;;;OAIG;IACH,mBAA8B;IAE9B;;;;OAIG;IACH,eAAW;IAEX;;;;OAIG;IACH,eAAY;IAEZ;;;;OAIG;IACH,uBAAmB;IAEnB;;;;OAIG;IACH,eAAmB;IAUnB;;;OAGG;IACH,sBAEC;IAdD;;;OAGG;IACH,mBAEC;IAUD;;;;OAIG;IACH,mBAEC;IAsBD,wBAgBC;IAED;;;;OAIG;IACH,uBA6BC;IAED;;OAEG;IACH,aAIC;IAED;;;;;;;OAOG;IACH,4BAFW,MAAM,QAQhB;IAED;;;OAGG;IACH,iBAFa,MAAM,CAqDlB;IAED;;;;OAIG;IACH,iBAFW,MAAM,QAMhB;IAED;;;;OAIG;IACH,iBAHW,MAAM,GACJ,OAAO,CAOnB;IAED;;;;OAIG;IACH,uBAHW,MAAM,GACJ,MAAM,CAKlB;IAED;;;;OAIG;IACH,uBAHW,MAAM,SACN,MAAM,QAOhB;IAED;;;;OAIG;IACH,oBAHW,MAAM,GACJ,MAAM,CAKlB;IAED;;;;OAIG;IACH,sBAHW,MAAM,UACN,MAAM,QAIhB;IAED;;;;OAIG;IACH,oBAHW,MAAM,GACJ,MAAM,CAKlB;IAED;;;;OAIG;IACH,sBAHW,MAAM,UACN,MAAM,QAIhB;IAED;;;;OAIG;IACH,oBAHW,MAAM,GACJ,MAAM,CAKlB;IAED;;;;OAIG;IACH,sBAHW,MAAM,UACN,MAAM,QAIhB;IAGD;;;;OAIG;IACH,oBAHW,MAAM,GACJ,MAAM,CAKlB;IAED;;;;OAIG;IACH,oBAHW,MAAM,UACN,MAAM,QAKhB;IAED;;;;OAIG;IACH,kBAHW,MAAM,UACN,MAAM,EAAE,GAAC,YAAY,QAe/B;IAED;;;;OAIG;IACH,kBAHW,MAAM,QACN,MAAM,EAAE,GAAC,UAAU,MAAM,CAAC,QAAM,QAsB1C;IAED;;;;OAIG;IACH,mBAHW,MAAM,QACN,MAAM,EAAE,QAWlB;IAED;;;;;;;;;OASG;IACH,4BARW,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,QAmBhB;IAED;;;;OAIG;IACH,0BAHW,MAAM,GACJ,MAAM,CAoBlB;IAED;;;;;OAKG;IACH,wCAJW,MAAM,WACN,MAAM,GACJ,MAAM,CAoClB;IAED;;;;;OAKG;IACH,oCAJW,MAAM,WACN,MAAM,WACN,MAAM,QAgBhB;IAED;;;;OAIG;IACH,kBAHW,MAAM,GACJ,IAAI,CA0GhB;IAED;;;;;OAKG;IACH,wBAqBC;IAED;;;;OAIG;IACH,
|
|
1
|
+
{"version":3,"file":"BVH.d.ts","sourceRoot":"","sources":["../../../../../src/core/bvh2/bvh3/BVH.js"],"names":[],"mappings":"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"}
|
|
@@ -800,7 +800,14 @@ export class BVH {
|
|
|
800
800
|
const uint32 = this.__data_uint32;
|
|
801
801
|
|
|
802
802
|
while (index !== NULL_NODE) {
|
|
803
|
-
|
|
803
|
+
// SAH-reducing rotation (Box2D v3 style) — keeps query cost near the
|
|
804
|
+
// SAH optimum. {@link balance_height} (pure height-AVL) is kept as
|
|
805
|
+
// the alternative. The tree shape this produces differs from the
|
|
806
|
+
// height-balanced one, which (because the contact solver's order
|
|
807
|
+
// follows broadphase traversal order) shifts Gauss-Seidel
|
|
808
|
+
// convergence on near-aligned stacks — see the BVH balance note in
|
|
809
|
+
// engine/physics/PLAN.md.
|
|
810
|
+
index = this.balance_rotate(index);
|
|
804
811
|
|
|
805
812
|
const node_address = index * ELEMENT_WORD_COUNT;
|
|
806
813
|
|
|
@@ -875,13 +882,18 @@ export class BVH {
|
|
|
875
882
|
}
|
|
876
883
|
|
|
877
884
|
/**
|
|
878
|
-
*
|
|
879
|
-
*
|
|
885
|
+
* **Height-balancing** rotation (Box2D v2 `b2DynamicTree::Balance`): if the
|
|
886
|
+
* two subtrees of node A differ in height by more than one, rotate the
|
|
887
|
+
* taller grandchild up. Keeps the tree height ≤ O(log N) but is chosen
|
|
888
|
+
* purely on *height* — it does not consider surface area, so the result is
|
|
889
|
+
* height-balanced yet not SAH-balanced (query cost can stay 1.3–2× above an
|
|
890
|
+
* SAH-optimal tree). See {@link balance_rotate} for the SAH-driven variant.
|
|
891
|
+
* Returns the (possibly new) subtree-root index.
|
|
880
892
|
* @param {number} iA
|
|
881
893
|
* @returns {number}
|
|
882
894
|
* @private
|
|
883
895
|
*/
|
|
884
|
-
|
|
896
|
+
balance_height(iA) {
|
|
885
897
|
assert.notEqual(iA, NULL_NODE, 'input is a null node');
|
|
886
898
|
|
|
887
899
|
//b2TreeNode* A = m_nodes + iA;
|
|
@@ -1079,6 +1091,148 @@ export class BVH {
|
|
|
1079
1091
|
return iA;
|
|
1080
1092
|
}
|
|
1081
1093
|
|
|
1094
|
+
/**
|
|
1095
|
+
* **SAH-reducing** rotation (Kensler 2008 / Box2D v3 `b2RotateNodes`). For
|
|
1096
|
+
* node A with children B, C, consider the four ways to swap a child of A
|
|
1097
|
+
* with a grandchild (a child of the other child); each rotation re-forms
|
|
1098
|
+
* exactly one internal node and changes the tree's total surface-area
|
|
1099
|
+
* (SAH) cost by `area(old child) − area(new child)`. Apply the swap with
|
|
1100
|
+
* the largest positive reduction, or none if no swap helps.
|
|
1101
|
+
*
|
|
1102
|
+
* Unlike {@link balance_height} the subtree root A never moves (so the
|
|
1103
|
+
* return value is always `iA`), and the criterion is *surface area*, not
|
|
1104
|
+
* height — keeping query cost near the SAH optimum. Height is not an
|
|
1105
|
+
* explicit invariant here, but SAH-good trees stay well-shaped for
|
|
1106
|
+
* spatially-distributed data (this is what modern Box2D ships).
|
|
1107
|
+
*
|
|
1108
|
+
* Deterministic: a pure function of the current tree state.
|
|
1109
|
+
*
|
|
1110
|
+
* @param {number} iA
|
|
1111
|
+
* @returns {number} always `iA` (the subtree root is unchanged)
|
|
1112
|
+
* @private
|
|
1113
|
+
*/
|
|
1114
|
+
balance_rotate(iA) {
|
|
1115
|
+
assert.notEqual(iA, NULL_NODE, 'input is a null node');
|
|
1116
|
+
|
|
1117
|
+
const uint32 = this.__data_uint32;
|
|
1118
|
+
const a_addr = iA * ELEMENT_WORD_COUNT;
|
|
1119
|
+
|
|
1120
|
+
if (this.node_is_leaf(iA) || uint32[a_addr + COLUMN_HEIGHT] < 2) {
|
|
1121
|
+
return iA;
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
const iB = uint32[a_addr + COLUMN_CHILD_1];
|
|
1125
|
+
const iC = uint32[a_addr + COLUMN_CHILD_2];
|
|
1126
|
+
|
|
1127
|
+
const b_leaf = this.node_is_leaf(iB);
|
|
1128
|
+
const c_leaf = this.node_is_leaf(iC);
|
|
1129
|
+
|
|
1130
|
+
// Largest beneficial SAH reduction found so far. Strictly positive, so a
|
|
1131
|
+
// zero-improvement (or worse) configuration leaves the tree untouched —
|
|
1132
|
+
// no churn, and deterministic.
|
|
1133
|
+
let best_improvement = 0;
|
|
1134
|
+
let best_rotation = 0; // 1..4, 0 = keep as-is
|
|
1135
|
+
|
|
1136
|
+
let iD = NULL_NODE, iE = NULL_NODE, iF = NULL_NODE, iG = NULL_NODE;
|
|
1137
|
+
|
|
1138
|
+
if (!b_leaf) {
|
|
1139
|
+
// B is internal with children D, E. Moving C down into B (and a
|
|
1140
|
+
// grandchild D/E up to A) re-forms B; the only changed area is B's.
|
|
1141
|
+
const area_b = this.node_get_surface_area(iB);
|
|
1142
|
+
iD = uint32[iB * ELEMENT_WORD_COUNT + COLUMN_CHILD_1];
|
|
1143
|
+
iE = uint32[iB * ELEMENT_WORD_COUNT + COLUMN_CHILD_2];
|
|
1144
|
+
|
|
1145
|
+
// Rotation 1 — swap C and D → B = (C, E), A = (B, D).
|
|
1146
|
+
const imp1 = area_b - this.node_get_combined_surface_area(iC, iE);
|
|
1147
|
+
if (imp1 > best_improvement) { best_improvement = imp1; best_rotation = 1; }
|
|
1148
|
+
|
|
1149
|
+
// Rotation 2 — swap C and E → B = (D, C), A = (B, E).
|
|
1150
|
+
const imp2 = area_b - this.node_get_combined_surface_area(iD, iC);
|
|
1151
|
+
if (imp2 > best_improvement) { best_improvement = imp2; best_rotation = 2; }
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
if (!c_leaf) {
|
|
1155
|
+
// C is internal with children F, G. Symmetric: re-forms C.
|
|
1156
|
+
const area_c = this.node_get_surface_area(iC);
|
|
1157
|
+
iF = uint32[iC * ELEMENT_WORD_COUNT + COLUMN_CHILD_1];
|
|
1158
|
+
iG = uint32[iC * ELEMENT_WORD_COUNT + COLUMN_CHILD_2];
|
|
1159
|
+
|
|
1160
|
+
// Rotation 3 — swap B and F → C = (B, G), A = (F, C).
|
|
1161
|
+
const imp3 = area_c - this.node_get_combined_surface_area(iB, iG);
|
|
1162
|
+
if (imp3 > best_improvement) { best_improvement = imp3; best_rotation = 3; }
|
|
1163
|
+
|
|
1164
|
+
// Rotation 4 — swap B and G → C = (F, B), A = (G, C).
|
|
1165
|
+
const imp4 = area_c - this.node_get_combined_surface_area(iF, iB);
|
|
1166
|
+
if (imp4 > best_improvement) { best_improvement = imp4; best_rotation = 4; }
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
if (best_rotation === 0) {
|
|
1170
|
+
return iA; // no beneficial rotation
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
// Apply the chosen rotation: re-wire one child↔grandchild pair, then
|
|
1174
|
+
// refresh the re-formed internal node's AABB + height. A's AABB / height
|
|
1175
|
+
// are recomputed by the caller (bubble_up_update) after we return, but
|
|
1176
|
+
// we also set A's height here so the subtree is self-consistent.
|
|
1177
|
+
switch (best_rotation) {
|
|
1178
|
+
case 1: { // swap C and D: B = (C, E), A = (B, D)
|
|
1179
|
+
uint32[a_addr + COLUMN_CHILD_2] = iD;
|
|
1180
|
+
uint32[iB * ELEMENT_WORD_COUNT + COLUMN_CHILD_1] = iC;
|
|
1181
|
+
uint32[iD * ELEMENT_WORD_COUNT + COLUMN_PARENT] = iA;
|
|
1182
|
+
uint32[iC * ELEMENT_WORD_COUNT + COLUMN_PARENT] = iB;
|
|
1183
|
+
this.node_set_combined_aabb(iB, iC, iE);
|
|
1184
|
+
uint32[iB * ELEMENT_WORD_COUNT + COLUMN_HEIGHT] = 1 + max2(
|
|
1185
|
+
uint32[iC * ELEMENT_WORD_COUNT + COLUMN_HEIGHT],
|
|
1186
|
+
uint32[iE * ELEMENT_WORD_COUNT + COLUMN_HEIGHT]
|
|
1187
|
+
);
|
|
1188
|
+
break;
|
|
1189
|
+
}
|
|
1190
|
+
case 2: { // swap C and E: B = (D, C), A = (B, E)
|
|
1191
|
+
uint32[a_addr + COLUMN_CHILD_2] = iE;
|
|
1192
|
+
uint32[iB * ELEMENT_WORD_COUNT + COLUMN_CHILD_2] = iC;
|
|
1193
|
+
uint32[iE * ELEMENT_WORD_COUNT + COLUMN_PARENT] = iA;
|
|
1194
|
+
uint32[iC * ELEMENT_WORD_COUNT + COLUMN_PARENT] = iB;
|
|
1195
|
+
this.node_set_combined_aabb(iB, iD, iC);
|
|
1196
|
+
uint32[iB * ELEMENT_WORD_COUNT + COLUMN_HEIGHT] = 1 + max2(
|
|
1197
|
+
uint32[iD * ELEMENT_WORD_COUNT + COLUMN_HEIGHT],
|
|
1198
|
+
uint32[iC * ELEMENT_WORD_COUNT + COLUMN_HEIGHT]
|
|
1199
|
+
);
|
|
1200
|
+
break;
|
|
1201
|
+
}
|
|
1202
|
+
case 3: { // swap B and F: C = (B, G), A = (F, C)
|
|
1203
|
+
uint32[a_addr + COLUMN_CHILD_1] = iF;
|
|
1204
|
+
uint32[iC * ELEMENT_WORD_COUNT + COLUMN_CHILD_1] = iB;
|
|
1205
|
+
uint32[iF * ELEMENT_WORD_COUNT + COLUMN_PARENT] = iA;
|
|
1206
|
+
uint32[iB * ELEMENT_WORD_COUNT + COLUMN_PARENT] = iC;
|
|
1207
|
+
this.node_set_combined_aabb(iC, iB, iG);
|
|
1208
|
+
uint32[iC * ELEMENT_WORD_COUNT + COLUMN_HEIGHT] = 1 + max2(
|
|
1209
|
+
uint32[iB * ELEMENT_WORD_COUNT + COLUMN_HEIGHT],
|
|
1210
|
+
uint32[iG * ELEMENT_WORD_COUNT + COLUMN_HEIGHT]
|
|
1211
|
+
);
|
|
1212
|
+
break;
|
|
1213
|
+
}
|
|
1214
|
+
case 4: { // swap B and G: C = (F, B), A = (G, C)
|
|
1215
|
+
uint32[a_addr + COLUMN_CHILD_1] = iG;
|
|
1216
|
+
uint32[iC * ELEMENT_WORD_COUNT + COLUMN_CHILD_2] = iB;
|
|
1217
|
+
uint32[iG * ELEMENT_WORD_COUNT + COLUMN_PARENT] = iA;
|
|
1218
|
+
uint32[iB * ELEMENT_WORD_COUNT + COLUMN_PARENT] = iC;
|
|
1219
|
+
this.node_set_combined_aabb(iC, iF, iB);
|
|
1220
|
+
uint32[iC * ELEMENT_WORD_COUNT + COLUMN_HEIGHT] = 1 + max2(
|
|
1221
|
+
uint32[iF * ELEMENT_WORD_COUNT + COLUMN_HEIGHT],
|
|
1222
|
+
uint32[iB * ELEMENT_WORD_COUNT + COLUMN_HEIGHT]
|
|
1223
|
+
);
|
|
1224
|
+
break;
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
uint32[a_addr + COLUMN_HEIGHT] = 1 + max2(
|
|
1229
|
+
uint32[uint32[a_addr + COLUMN_CHILD_1] * ELEMENT_WORD_COUNT + COLUMN_HEIGHT],
|
|
1230
|
+
uint32[uint32[a_addr + COLUMN_CHILD_2] * ELEMENT_WORD_COUNT + COLUMN_HEIGHT]
|
|
1231
|
+
);
|
|
1232
|
+
|
|
1233
|
+
return iA;
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1082
1236
|
/**
|
|
1083
1237
|
* Utility method for assigning both children at once
|
|
1084
1238
|
* Children must be valid nodes (non-null)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A solid right circular cylinder aligned with the Y axis, centred at the local
|
|
3
|
+
* origin. A disk of {@link radius} extruded along Y for {@link height}, so it
|
|
4
|
+
* spans `y ∈ [-height/2, +height/2]` with **flat** circular caps (the capsule's
|
|
5
|
+
* flat-cap sibling — same radius/height parametrisation, hemispherical caps
|
|
6
|
+
* replaced by disks).
|
|
7
|
+
*
|
|
8
|
+
* Convex, so the physics narrowphase handles it through the GJK + EPA fallback
|
|
9
|
+
* via {@link support} — there is no closed-form cylinder-vs-X contact path yet
|
|
10
|
+
* (a future refinement; the curved side is the usual smooth-support EPA case).
|
|
11
|
+
*
|
|
12
|
+
* @author Alex Goldring
|
|
13
|
+
* @copyright Company Named Limited (c) 2026
|
|
14
|
+
*/
|
|
15
|
+
export class CylinderShape3D extends AbstractShape3D {
|
|
16
|
+
/**
|
|
17
|
+
* @param {number} radius
|
|
18
|
+
* @param {number} height
|
|
19
|
+
* @returns {CylinderShape3D}
|
|
20
|
+
*/
|
|
21
|
+
static from(radius: number, height: number): CylinderShape3D;
|
|
22
|
+
/**
|
|
23
|
+
* Radius of the circular cross-section.
|
|
24
|
+
* @type {number}
|
|
25
|
+
*/
|
|
26
|
+
radius: number;
|
|
27
|
+
/**
|
|
28
|
+
* Full height along the Y axis (total extent — the cylinder spans
|
|
29
|
+
* `[-height/2, +height/2]`).
|
|
30
|
+
* @type {number}
|
|
31
|
+
*/
|
|
32
|
+
height: number;
|
|
33
|
+
compute_bounding_box(result: any): void;
|
|
34
|
+
support(result: any, result_offset: any, direction_x: any, direction_y: any, direction_z: any): void;
|
|
35
|
+
signed_distance_at_point(point: any): number;
|
|
36
|
+
signed_distance_gradient_at_point(result: any, point: any): number;
|
|
37
|
+
contains_point(point: any): boolean;
|
|
38
|
+
nearest_point_on_surface(result: any, reference: any): void;
|
|
39
|
+
sample_random_point_in_volume(result: any, result_offset: any, random: any): void;
|
|
40
|
+
/**
|
|
41
|
+
* @param {CylinderShape3D} other
|
|
42
|
+
* @returns {boolean}
|
|
43
|
+
*/
|
|
44
|
+
equals(other: CylinderShape3D): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Fast type-check marker, mirroring `isSphereShape3D` / `isBoxShape3D` /
|
|
47
|
+
* `isCapsuleShape3D`. Reserved for a future closed-form cylinder narrowphase
|
|
48
|
+
* dispatch; until then the cylinder routes through GJK + EPA like any other
|
|
49
|
+
* convex shape (no marker check needed for that path).
|
|
50
|
+
* @readonly
|
|
51
|
+
* @type {boolean}
|
|
52
|
+
*/
|
|
53
|
+
readonly isCylinderShape3D: boolean;
|
|
54
|
+
}
|
|
55
|
+
import { AbstractShape3D } from "./AbstractShape3D.js";
|
|
56
|
+
//# sourceMappingURL=CylinderShape3D.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CylinderShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/CylinderShape3D.js"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;GAaG;AACH;IAkBI;;;;OAIG;IACH,oBAJW,MAAM,UACN,MAAM,GACJ,eAAe,CAa3B;IA9BG;;;OAGG;IACH,QAFU,MAAM,CAEC;IAEjB;;;;OAIG;IACH,QAFU,MAAM,CAED;IAgCnB,wCAUC;IAED,qGAqBC;IAED,6CAoBC;IAED,mEAEC;IAED,oCASC;IAED,4DA0CC;IAED,kFAOC;IAED;;;OAGG;IACH,cAHW,eAAe,GACb,OAAO,CAMnB;IAUL;;;;;;;OAOG;IACH,4BAFU,OAAO,CAE0B;CAV1C;gCA/M+B,sBAAsB"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { assert } from "../../../assert.js";
|
|
2
|
+
import { clamp } from "../../../math/clamp.js";
|
|
3
|
+
import { sign_not_zero } from "../../../math/sign_not_zero.js";
|
|
4
|
+
import { computeHashFloat } from "../../../primitives/numbers/computeHashFloat.js";
|
|
5
|
+
import { randomPointInCircle } from "../../random/randomPointInCircle.js";
|
|
6
|
+
import { AbstractShape3D } from "./AbstractShape3D.js";
|
|
7
|
+
import { compute_signed_distance_gradient_by_sampling } from "./util/compute_signed_distance_gradient_by_sampling.js";
|
|
8
|
+
|
|
9
|
+
const scratch_v3 = [0, 0, 0];
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A solid right circular cylinder aligned with the Y axis, centred at the local
|
|
13
|
+
* origin. A disk of {@link radius} extruded along Y for {@link height}, so it
|
|
14
|
+
* spans `y ∈ [-height/2, +height/2]` with **flat** circular caps (the capsule's
|
|
15
|
+
* flat-cap sibling — same radius/height parametrisation, hemispherical caps
|
|
16
|
+
* replaced by disks).
|
|
17
|
+
*
|
|
18
|
+
* Convex, so the physics narrowphase handles it through the GJK + EPA fallback
|
|
19
|
+
* via {@link support} — there is no closed-form cylinder-vs-X contact path yet
|
|
20
|
+
* (a future refinement; the curved side is the usual smooth-support EPA case).
|
|
21
|
+
*
|
|
22
|
+
* @author Alex Goldring
|
|
23
|
+
* @copyright Company Named Limited (c) 2026
|
|
24
|
+
*/
|
|
25
|
+
export class CylinderShape3D extends AbstractShape3D {
|
|
26
|
+
constructor() {
|
|
27
|
+
super();
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Radius of the circular cross-section.
|
|
31
|
+
* @type {number}
|
|
32
|
+
*/
|
|
33
|
+
this.radius = 0.5;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Full height along the Y axis (total extent — the cylinder spans
|
|
37
|
+
* `[-height/2, +height/2]`).
|
|
38
|
+
* @type {number}
|
|
39
|
+
*/
|
|
40
|
+
this.height = 1;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param {number} radius
|
|
45
|
+
* @param {number} height
|
|
46
|
+
* @returns {CylinderShape3D}
|
|
47
|
+
*/
|
|
48
|
+
static from(radius, height) {
|
|
49
|
+
assert.isNumber(radius, 'radius');
|
|
50
|
+
assert.isNumber(height, 'height');
|
|
51
|
+
assert.greaterThanOrEqual(radius, 0, 'radius');
|
|
52
|
+
assert.greaterThanOrEqual(height, 0, 'height');
|
|
53
|
+
|
|
54
|
+
const r = new CylinderShape3D();
|
|
55
|
+
r.radius = radius;
|
|
56
|
+
r.height = height;
|
|
57
|
+
|
|
58
|
+
return r;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get volume() {
|
|
62
|
+
const r = this.radius;
|
|
63
|
+
return Math.PI * r * r * this.height;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
get surface_area() {
|
|
67
|
+
const r = this.radius;
|
|
68
|
+
// two circular caps + the lateral (side) surface
|
|
69
|
+
return 2 * Math.PI * r * r + 2 * Math.PI * r * this.height;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
compute_bounding_box(result) {
|
|
73
|
+
const r = this.radius;
|
|
74
|
+
const half_h = this.height / 2;
|
|
75
|
+
|
|
76
|
+
result[0] = -r;
|
|
77
|
+
result[1] = -half_h;
|
|
78
|
+
result[2] = -r;
|
|
79
|
+
result[3] = r;
|
|
80
|
+
result[4] = half_h;
|
|
81
|
+
result[5] = r;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
support(result, result_offset, direction_x, direction_y, direction_z) {
|
|
85
|
+
const r = this.radius;
|
|
86
|
+
const half_h = this.height / 2;
|
|
87
|
+
|
|
88
|
+
// Radial: farthest point on the cross-section disk along (dx, dz). For a
|
|
89
|
+
// purely axial query (rl ≈ 0) any point on the cap face is extremal —
|
|
90
|
+
// the cap centre (0,0) is on the (flat) surface, so it's a valid support.
|
|
91
|
+
const rl = Math.sqrt(direction_x * direction_x + direction_z * direction_z);
|
|
92
|
+
let sx = 0, sz = 0;
|
|
93
|
+
if (rl > 0) {
|
|
94
|
+
const inv = r / rl;
|
|
95
|
+
sx = direction_x * inv;
|
|
96
|
+
sz = direction_z * inv;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Axial: the cap on the +direction.y side.
|
|
100
|
+
const sy = sign_not_zero(direction_y) * half_h;
|
|
101
|
+
|
|
102
|
+
result[result_offset] = sx;
|
|
103
|
+
result[result_offset + 1] = sy;
|
|
104
|
+
result[result_offset + 2] = sz;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
signed_distance_at_point(point) {
|
|
108
|
+
const px = point[0];
|
|
109
|
+
const py = point[1];
|
|
110
|
+
const pz = point[2];
|
|
111
|
+
|
|
112
|
+
const half_h = this.height / 2;
|
|
113
|
+
|
|
114
|
+
// Inigo Quilez capped-cylinder SDF, axis = Y. `d_radial` / `d_axial` are
|
|
115
|
+
// the signed distances outside the infinite cylinder and the slab.
|
|
116
|
+
const d_radial = Math.sqrt(px * px + pz * pz) - this.radius;
|
|
117
|
+
const d_axial = Math.abs(py) - half_h;
|
|
118
|
+
|
|
119
|
+
const ext_r = d_radial > 0 ? d_radial : 0;
|
|
120
|
+
const ext_a = d_axial > 0 ? d_axial : 0;
|
|
121
|
+
const outside = Math.sqrt(ext_r * ext_r + ext_a * ext_a);
|
|
122
|
+
|
|
123
|
+
const m = d_radial > d_axial ? d_radial : d_axial;
|
|
124
|
+
const inside = m < 0 ? m : 0;
|
|
125
|
+
|
|
126
|
+
return outside + inside;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
signed_distance_gradient_at_point(result, point) {
|
|
130
|
+
return compute_signed_distance_gradient_by_sampling(result, this, point);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
contains_point(point) {
|
|
134
|
+
const px = point[0];
|
|
135
|
+
const py = point[1];
|
|
136
|
+
const pz = point[2];
|
|
137
|
+
|
|
138
|
+
const half_h = this.height / 2;
|
|
139
|
+
const r = this.radius;
|
|
140
|
+
|
|
141
|
+
return (px * px + pz * pz) < r * r && (py < half_h) && (py > -half_h);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
nearest_point_on_surface(result, reference) {
|
|
145
|
+
const rx = reference[0];
|
|
146
|
+
const ry = reference[1];
|
|
147
|
+
const rz = reference[2];
|
|
148
|
+
|
|
149
|
+
const r = this.radius;
|
|
150
|
+
const half_h = this.height / 2;
|
|
151
|
+
|
|
152
|
+
const rho = Math.sqrt(rx * rx + rz * rz);
|
|
153
|
+
let dirx, dirz;
|
|
154
|
+
if (rho > 0) {
|
|
155
|
+
dirx = rx / rho;
|
|
156
|
+
dirz = rz / rho;
|
|
157
|
+
} else {
|
|
158
|
+
// On the axis — radial direction is undefined; pick +X.
|
|
159
|
+
dirx = 1;
|
|
160
|
+
dirz = 0;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Three candidate projections; the nearest to the reference is the
|
|
164
|
+
// closest surface point (correct for points inside and outside).
|
|
165
|
+
// 1. side — radial clamped to r, y clamped to the band
|
|
166
|
+
// 2. top cap — y = +half_h, radial clamped to r
|
|
167
|
+
// 3. bot cap — y = -half_h, radial clamped to r
|
|
168
|
+
const cy = clamp(ry, -half_h, half_h);
|
|
169
|
+
const s1x = r * dirx, s1y = cy, s1z = r * dirz;
|
|
170
|
+
|
|
171
|
+
const rc = rho < r ? rho : r;
|
|
172
|
+
const s2x = rc * dirx, s2y = half_h, s2z = rc * dirz;
|
|
173
|
+
const s3x = rc * dirx, s3y = -half_h, s3z = rc * dirz;
|
|
174
|
+
|
|
175
|
+
const d1 = (s1x - rx) * (s1x - rx) + (s1y - ry) * (s1y - ry) + (s1z - rz) * (s1z - rz);
|
|
176
|
+
const d2 = (s2x - rx) * (s2x - rx) + (s2y - ry) * (s2y - ry) + (s2z - rz) * (s2z - rz);
|
|
177
|
+
const d3 = (s3x - rx) * (s3x - rx) + (s3y - ry) * (s3y - ry) + (s3z - rz) * (s3z - rz);
|
|
178
|
+
|
|
179
|
+
if (d1 <= d2 && d1 <= d3) {
|
|
180
|
+
result[0] = s1x; result[1] = s1y; result[2] = s1z;
|
|
181
|
+
} else if (d2 <= d3) {
|
|
182
|
+
result[0] = s2x; result[1] = s2y; result[2] = s2z;
|
|
183
|
+
} else {
|
|
184
|
+
result[0] = s3x; result[1] = s3y; result[2] = s3z;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
sample_random_point_in_volume(result, result_offset, random) {
|
|
189
|
+
// Uniform in the disk (sqrt-weighted radius) × uniform in y.
|
|
190
|
+
randomPointInCircle(random, scratch_v3, 0);
|
|
191
|
+
|
|
192
|
+
result[result_offset] = scratch_v3[0] * this.radius;
|
|
193
|
+
result[result_offset + 1] = (random() - 0.5) * this.height;
|
|
194
|
+
result[result_offset + 2] = scratch_v3[1] * this.radius;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* @param {CylinderShape3D} other
|
|
199
|
+
* @returns {boolean}
|
|
200
|
+
*/
|
|
201
|
+
equals(other) {
|
|
202
|
+
return super.equals(other)
|
|
203
|
+
&& this.radius === other.radius
|
|
204
|
+
&& this.height === other.height;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
hash() {
|
|
208
|
+
const a = computeHashFloat(this.radius);
|
|
209
|
+
const b = computeHashFloat(this.height);
|
|
210
|
+
|
|
211
|
+
return ((a << 5) - a + b) | 0;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Fast type-check marker, mirroring `isSphereShape3D` / `isBoxShape3D` /
|
|
217
|
+
* `isCapsuleShape3D`. Reserved for a future closed-form cylinder narrowphase
|
|
218
|
+
* dispatch; until then the cylinder routes through GJK + EPA like any other
|
|
219
|
+
* convex shape (no marker check needed for that path).
|
|
220
|
+
* @readonly
|
|
221
|
+
* @type {boolean}
|
|
222
|
+
*/
|
|
223
|
+
CylinderShape3D.prototype.isCylinderShape3D = true;
|
|
@@ -9,6 +9,7 @@ export class PointShape3D extends AbstractShape3D {
|
|
|
9
9
|
nearest_point_on_surface(result: any, reference: any): void;
|
|
10
10
|
sample_random_point_in_volume(result: any, result_offset: any, random: any): void;
|
|
11
11
|
support(result: any, result_offset: any, direction_x: any, direction_y: any, direction_z: any): void;
|
|
12
|
+
equals(other: any): boolean;
|
|
12
13
|
}
|
|
13
14
|
import { AbstractShape3D } from "./AbstractShape3D.js";
|
|
14
15
|
//# sourceMappingURL=PointShape3D.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PointShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/PointShape3D.js"],"names":[],"mappings":"AAGA;;GAEG;AACH;
|
|
1
|
+
{"version":3,"file":"PointShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/PointShape3D.js"],"names":[],"mappings":"AAGA;;GAEG;AACH;IAuDI,8BAAqC;IA9CrC,wCAOC;IAED,6CAEC;IAED,oCAEC;IAED,4DAIC;IAED,kFAIC;IAED,qGAIC;IAED,4BAGC;CASJ;gCA7D+B,sBAAsB"}
|
|
@@ -48,5 +48,16 @@ export class PointShape3D extends AbstractShape3D {
|
|
|
48
48
|
result[result_offset + 2] = 0;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
equals(other) {
|
|
52
|
+
// Parameterless: identity is the type alone (a point has no fields).
|
|
53
|
+
return super.equals(other);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
hash() {
|
|
57
|
+
// Constant — every PointShape3D is identical. Distinct from the
|
|
58
|
+
// base-class 0 so it doesn't collide with a hypothetical default shape.
|
|
59
|
+
return 0x504f494e; // "POIN"
|
|
60
|
+
}
|
|
61
|
+
|
|
51
62
|
static INSTANCE = new PointShape3D();
|
|
52
63
|
}
|
|
@@ -32,6 +32,7 @@ export class SphereShape3D extends AbstractShape3D {
|
|
|
32
32
|
signed_distance_at_point(point: any): number;
|
|
33
33
|
contains_point(point: any): boolean;
|
|
34
34
|
sample_random_point_in_volume(result: any, result_offset: any, random: any): void;
|
|
35
|
+
equals(other: any): boolean;
|
|
35
36
|
/**
|
|
36
37
|
* Fast type-check marker. Lets the physics narrowphase short-circuit
|
|
37
38
|
* sphere-involved pairs to closed-form solvers (reading `radius`) rather than
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SphereShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/SphereShape3D.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;GAcG;AACH;IAUI;;;;OAIG;IACH,oBAHW,MAAM,GACJ,aAAa,CAMzB;IAhBG;;;OAGG;IACH,QAFU,MAAM,CAED;IAwBnB,qGAQC;IAED,wCAQC;IAED,4DAaC;IAED,mEAEC;IAED,6CAEC;IAED,oCAOC;IAED,kFAMC;IAOL;;;;;;;;OAQG;IACH,0BAFU,OAAO,CAEsB;CAXtC;
|
|
1
|
+
{"version":3,"file":"SphereShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/SphereShape3D.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;GAcG;AACH;IAUI;;;;OAIG;IACH,oBAHW,MAAM,GACJ,aAAa,CAMzB;IAhBG;;;OAGG;IACH,QAFU,MAAM,CAED;IAwBnB,qGAQC;IAED,wCAQC;IAED,4DAaC;IAED,mEAEC;IAED,6CAEC;IAED,oCAOC;IAED,kFAMC;IAED,4BAEC;IAOL;;;;;;;;OAQG;IACH,0BAFU,OAAO,CAEsB;CAXtC;gCApH+B,sBAAsB"}
|
|
@@ -110,6 +110,10 @@ export class SphereShape3D extends AbstractShape3D {
|
|
|
110
110
|
result[result_offset + 2] *= r;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
equals(other) {
|
|
114
|
+
return super.equals(other) && this.radius === other.radius;
|
|
115
|
+
}
|
|
116
|
+
|
|
113
117
|
hash() {
|
|
114
118
|
return computeHashFloat(this.radius);
|
|
115
119
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shape_to_type.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/shape/json/shape_to_type.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"shape_to_type.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/shape/json/shape_to_type.js"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,uDAFa,MAAM,CAoBlB"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CapsuleShape3D } from "../CapsuleShape3D.js";
|
|
2
|
+
import { CylinderShape3D } from "../CylinderShape3D.js";
|
|
2
3
|
import { SphereShape3D } from "../SphereShape3D.js";
|
|
3
4
|
import { TransformedShape3D } from "../TransformedShape3D.js";
|
|
4
5
|
import { UnionShape3D } from "../UnionShape3D.js";
|
|
@@ -22,6 +23,8 @@ export function shape_to_type(shape) {
|
|
|
22
23
|
return 'transform';
|
|
23
24
|
} else if (shape instanceof CapsuleShape3D) {
|
|
24
25
|
return 'capsule';
|
|
26
|
+
} else if (shape instanceof CylinderShape3D) {
|
|
27
|
+
return 'cylinder';
|
|
25
28
|
} else {
|
|
26
29
|
throw new Error('Unsupported shape');
|
|
27
30
|
}
|
|
@@ -30,6 +30,20 @@ export namespace type_adapters {
|
|
|
30
30
|
height: number;
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
|
+
namespace cylinder {
|
|
34
|
+
function read({ radius, height }: {
|
|
35
|
+
radius: any;
|
|
36
|
+
height: any;
|
|
37
|
+
}): CylinderShape3D;
|
|
38
|
+
/**
|
|
39
|
+
*
|
|
40
|
+
* @param {CylinderShape3D} object
|
|
41
|
+
*/
|
|
42
|
+
function write(object: CylinderShape3D): {
|
|
43
|
+
radius: number;
|
|
44
|
+
height: number;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
33
47
|
namespace transform {
|
|
34
48
|
function read({ transform, subject }: {
|
|
35
49
|
transform: any;
|
|
@@ -60,6 +74,7 @@ export namespace type_adapters {
|
|
|
60
74
|
import { UnitCubeShape3D } from "../UnitCubeShape3D.js";
|
|
61
75
|
import { SphereShape3D } from "../SphereShape3D.js";
|
|
62
76
|
import { CapsuleShape3D } from "../CapsuleShape3D.js";
|
|
77
|
+
import { CylinderShape3D } from "../CylinderShape3D.js";
|
|
63
78
|
import { TransformedShape3D } from "../TransformedShape3D.js";
|
|
64
79
|
import { UnionShape3D } from "../UnionShape3D.js";
|
|
65
80
|
//# sourceMappingURL=type_adapters.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type_adapters.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/shape/json/type_adapters.js"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"type_adapters.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/shape/json/type_adapters.js"],"names":[],"mappings":";;QAYQ,iCAEC;QACD,qBAEC;;;QAGD;;0BAQC;QACD;;WAEG;QACH;;;;UAIC;;;QAGD;;;2BAEC;QACD;;;WAGG;QACH;;;UAKC;;;QAGD;;;4BAEC;QACD;;;WAGG;QACH;;;UAKC;;;QAGD;;;+BAIC;QACD;;;WAGG;QACH;;;UAKC;;;QAGD;;yBAIC;QACD;;;WAGG;QACH;;UAIC;;;gCA9FuB,uBAAuB;8BAHzB,qBAAqB;+BAFpB,sBAAsB;gCACrB,uBAAuB;mCAEpB,0BAA0B;6BAChC,oBAAoB"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CapsuleShape3D } from "../CapsuleShape3D.js";
|
|
2
|
+
import { CylinderShape3D } from "../CylinderShape3D.js";
|
|
2
3
|
import { SphereShape3D } from "../SphereShape3D.js";
|
|
3
4
|
import { TransformedShape3D } from "../TransformedShape3D.js";
|
|
4
5
|
import { UnionShape3D } from "../UnionShape3D.js";
|
|
@@ -50,6 +51,21 @@ export const type_adapters = {
|
|
|
50
51
|
};
|
|
51
52
|
}
|
|
52
53
|
},
|
|
54
|
+
'cylinder': {
|
|
55
|
+
read({ radius, height }) {
|
|
56
|
+
return CylinderShape3D.from(radius, height);
|
|
57
|
+
},
|
|
58
|
+
/**
|
|
59
|
+
*
|
|
60
|
+
* @param {CylinderShape3D} object
|
|
61
|
+
*/
|
|
62
|
+
write(object) {
|
|
63
|
+
return {
|
|
64
|
+
radius: object.radius,
|
|
65
|
+
height: object.height
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
},
|
|
53
69
|
'transform': {
|
|
54
70
|
read({ transform, subject }) {
|
|
55
71
|
const subject_shape = shape_from_json(subject);
|