@woosh/meep-engine 3.36.0 → 3.38.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/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +2 -0
- package/src/engine/ecs/transform/TRANSFORM64_EVENT_PLACED.d.ts +11 -0
- package/src/engine/ecs/transform/TRANSFORM64_EVENT_PLACED.d.ts.map +1 -0
- package/src/engine/ecs/transform/TRANSFORM64_EVENT_PLACED.js +10 -0
- package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.d.ts.map +1 -1
- package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +16 -0
- package/src/engine/graphics/ecs/water/Water.d.ts +30 -0
- package/src/engine/graphics/ecs/water/Water.d.ts.map +1 -1
- package/src/engine/graphics/ecs/water/Water.js +125 -104
- package/src/engine/graphics/ecs/water/WaterSerializationAdapter.d.ts.map +1 -1
- package/src/engine/graphics/ecs/water/WaterSerializationAdapter.js +13 -1
- package/src/engine/graphics/ecs/water/WaterSerializationUpgrader_1_2.d.ts +6 -0
- package/src/engine/graphics/ecs/water/WaterSerializationUpgrader_1_2.d.ts.map +1 -0
- package/src/engine/graphics/ecs/water/WaterSerializationUpgrader_1_2.js +18 -0
- package/src/engine/graphics3/WaterSystem.d.ts +22 -6
- package/src/engine/graphics3/WaterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/WaterSystem.js +314 -293
- package/src/engine/input/devices/XRInputDevice.d.ts +51 -23
- package/src/engine/input/devices/XRInputDevice.d.ts.map +1 -1
- package/src/engine/input/devices/XRInputDevice.js +145 -52
- package/src/engine/input/devices/xr/XRGamepadMapping.d.ts +14 -0
- package/src/engine/input/devices/xr/XRGamepadMapping.d.ts.map +1 -0
- package/src/engine/input/devices/xr/XRGamepadMapping.js +9 -0
- package/src/engine/input/devices/xr/XRHandedness.d.ts +15 -0
- package/src/engine/input/devices/xr/XRHandedness.d.ts.map +1 -0
- package/src/engine/input/devices/xr/XRHandedness.js +10 -0
- package/src/engine/input/devices/xr/XRInputAction.d.ts +24 -11
- package/src/engine/input/devices/xr/XRInputAction.d.ts.map +1 -1
- package/src/engine/input/devices/xr/XRInputAction.js +55 -24
- package/src/engine/input/devices/xr/XRInputButton.d.ts +7 -9
- package/src/engine/input/devices/xr/XRInputButton.d.ts.map +1 -1
- package/src/engine/input/devices/xr/XRInputButton.js +18 -8
- package/src/engine/input/devices/xr/XRInputCoordinates.d.ts +11 -3
- package/src/engine/input/devices/xr/XRInputCoordinates.d.ts.map +1 -1
- package/src/engine/input/devices/xr/XRInputCoordinates.js +17 -3
- package/src/engine/input/devices/xr/XRInputHandle.d.ts +41 -11
- package/src/engine/input/devices/xr/XRInputHandle.d.ts.map +1 -1
- package/src/engine/input/devices/xr/XRInputHandle.js +129 -32
- package/src/engine/input/devices/xr/XRInputPose.d.ts +41 -5
- package/src/engine/input/devices/xr/XRInputPose.d.ts.map +1 -1
- package/src/engine/input/devices/xr/XRInputPose.js +57 -16
- package/src/engine/input/devices/xr/XRInputTypes.d.ts +18 -18
- package/src/engine/input/devices/xr/XRInputTypes.js +3 -3
- package/src/engine/input/devices/xr/XRTargetRayMode.d.ts +17 -0
- package/src/engine/input/devices/xr/XRTargetRayMode.d.ts.map +1 -0
- package/src/engine/input/devices/xr/XRTargetRayMode.js +12 -0
- package/src/engine/input/devices/xr/XRVisibilityState.d.ts +15 -0
- package/src/engine/input/devices/xr/XRVisibilityState.d.ts.map +1 -0
- package/src/engine/input/devices/xr/XRVisibilityState.js +10 -0
- package/src/engine/input/ecs/ism/coordinate/InputCoordinateDevice.d.ts +3 -1
- package/src/engine/input/ecs/ism/coordinate/InputCoordinateDevice.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/coordinate/InputCoordinateDevice.js +5 -1
- package/src/engine/input/ecs/ism/device/XRInputDeviceAdapter.d.ts +19 -5
- package/src/engine/input/ecs/ism/device/XRInputDeviceAdapter.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/device/XRInputDeviceAdapter.js +42 -9
- package/src/engine/input/ecs/ism/device/XR_INPUT_DEVICE_IDS.d.ts +8 -2
- package/src/engine/input/ecs/ism/device/XR_INPUT_DEVICE_IDS.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/device/XR_INPUT_DEVICE_IDS.js +19 -9
- package/src/engine/input/ecs/ism/trigger/InputTriggerXRButton.d.ts +10 -2
- package/src/engine/input/ecs/ism/trigger/InputTriggerXRButton.d.ts.map +1 -1
- package/src/engine/input/ecs/ism/trigger/InputTriggerXRButton.js +12 -2
- package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts +13 -14
- package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts.map +1 -1
- package/src/engine/physics/cloth/collider/ClothColliderIndex.js +137 -36
- package/src/engine/physics/cloth/collider/cloth_collider_bounds.d.ts +30 -0
- package/src/engine/physics/cloth/collider/cloth_collider_bounds.d.ts.map +1 -1
- package/src/engine/physics/cloth/collider/cloth_collider_bounds.js +33 -0
- package/src/engine/physics/cloth/ecs/ClothColliderFlags.js +2 -1
- package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts +10 -1
- package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothColliderSystem.js +36 -14
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +15 -2
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothInstance.js +17 -2
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothWorld.js +19 -6
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +18 -20
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +139 -89
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +32 -16
- package/src/shade/playground/water_refraction/README.md +149 -0
- package/src/shade/playground/water_refraction/index.html +42 -0
- package/src/shade/playground/water_refraction/main.d.ts +2 -0
- package/src/shade/playground/water_refraction/main.d.ts.map +1 -0
- package/src/shade/playground/water_refraction/main.js +201 -0
- package/src/shade/playground/water_refraction/world.d.ts +37 -0
- package/src/shade/playground/water_refraction/world.d.ts.map +1 -0
- package/src/shade/playground/water_refraction/world.js +137 -0
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +4 -0
- package/src/shade/renderer/animation/chunk_pose_accumulator.d.ts +2 -3
- package/src/shade/renderer/animation/chunk_pose_accumulator.d.ts.map +1 -1
- package/src/shade/renderer/animation/chunk_pose_accumulator.js +14 -24
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_reduce.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/bounds_refresh/shader_meshlet_bounds_reduce.js +16 -15
- package/src/shade/renderer/deferred/indirect/chunk_lpv_sample_light.js +1 -1
- package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +1123 -1122
- package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +202 -201
- package/src/shade/renderer/light/environment/chunk_roughness_to_mip_ratio.d.ts +8 -0
- package/src/shade/renderer/light/environment/chunk_roughness_to_mip_ratio.d.ts.map +1 -0
- package/src/shade/renderer/light/environment/chunk_roughness_to_mip_ratio.js +24 -0
- package/src/shade/renderer/light/environment/chunk_sphere_probe_roughness_to_lod.d.ts +0 -6
- package/src/shade/renderer/light/environment/chunk_sphere_probe_roughness_to_lod.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/chunk_sphere_probe_roughness_to_lod.js +2 -25
- package/src/shade/renderer/light/environment/shader_project_environment_sh.d.ts +2 -2
- package/src/shade/renderer/light/environment/shader_project_environment_sh.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/shader_project_environment_sh.js +50 -19
- package/src/shade/renderer/particles/DESIGN.md +1 -1
- package/src/shade/renderer/particles/bounds/chunk_particle_bounds.d.ts +1 -1
- package/src/shade/renderer/particles/bounds/chunk_particle_bounds.d.ts.map +1 -1
- package/src/shade/renderer/particles/bounds/chunk_particle_bounds.js +10 -9
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts +17 -0
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.js +7 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_renormalization.d.ts +4 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_renormalization.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_renormalization.js +11 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_rgb_contribution.d.ts +4 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_rgb_contribution.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_rgb_contribution.js +19 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_splat_slice.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_splat_slice.js +5 -3
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_split_counts.d.ts +4 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_split_counts.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_split_counts.js +8 -0
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts +1 -1
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +21 -2
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_resolve.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/shader_avboit_resolve.js +4 -8
- package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.d.ts.map +1 -1
- package/src/shade/renderer/scene/shader_bvh_extract_instance_leaves.js +10 -8
- package/src/shade/renderer/shader/chunk/atomic/chunk_atomic_add_f32_storage.d.ts +12 -0
- package/src/shade/renderer/shader/chunk/atomic/chunk_atomic_add_f32_storage.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/atomic/chunk_atomic_add_f32_storage.js +25 -0
- package/src/shade/renderer/shader/chunk/atomic/chunk_atomic_max_f32_storage.d.ts +12 -0
- package/src/shade/renderer/shader/chunk/atomic/chunk_atomic_max_f32_storage.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/atomic/chunk_atomic_max_f32_storage.js +28 -0
- package/src/shade/renderer/shader/chunk/atomic/chunk_atomic_min_f32_storage.d.ts +12 -0
- package/src/shade/renderer/shader/chunk/atomic/chunk_atomic_min_f32_storage.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/atomic/chunk_atomic_min_f32_storage.js +28 -0
- package/src/shade/renderer/shader/chunk/geometry/plane/{plane_ray_raycast.d.ts → chunk_plane_ray_raycast.d.ts} +2 -2
- package/src/shade/renderer/shader/chunk/geometry/plane/chunk_plane_ray_raycast.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/plane/{plane_ray_raycast.js → chunk_plane_ray_raycast.js} +1 -1
- package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_space_newton_ray.d.ts +4 -0
- package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_space_newton_ray.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_space_newton_ray.js +101 -0
- package/src/shade/renderer/shadow/map/csm/shader/shader_csm_caster_range.js +3 -3
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts +62 -29
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
- package/src/shade/renderer/water/GPUWaterRenderer.js +235 -147
- package/src/shade/renderer/water/chunk_water_transport.d.ts +5 -0
- package/src/shade/renderer/water/chunk_water_transport.d.ts.map +1 -0
- package/src/shade/renderer/water/chunk_water_transport.js +94 -0
- package/src/shade/renderer/water/shader_water.d.ts +9 -26
- package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
- package/src/shade/renderer/water/shader_water.js +384 -246
- package/src/shade/renderer/water/shader_water_avboit.d.ts +12 -0
- package/src/shade/renderer/water/shader_water_avboit.d.ts.map +1 -0
- package/src/shade/renderer/water/shader_water_avboit.js +258 -0
- package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.js +13 -0
- package/src/shade/renderer/animation/skinning/bounds_refresh/chunk_aabb_atomic_f32.d.ts +0 -29
- package/src/shade/renderer/animation/skinning/bounds_refresh/chunk_aabb_atomic_f32.d.ts.map +0 -1
- package/src/shade/renderer/animation/skinning/bounds_refresh/chunk_aabb_atomic_f32.js +0 -59
- package/src/shade/renderer/shader/chunk/geometry/plane/plane_ray_raycast.d.ts.map +0 -1
|
@@ -104,25 +104,16 @@ export class ClothColliderIndex {
|
|
|
104
104
|
/**
|
|
105
105
|
* The widest {@link CCR_INFLATION} any live record carries, metres.
|
|
106
106
|
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* each particle. The gather cannot know which colliders it is about to find,
|
|
110
|
-
* so it takes the widest in the index — which is why this is here rather
|
|
111
|
-
* than derived per query.
|
|
112
|
-
*
|
|
113
|
-
* Exact after {@link advance}, and only ever raised between advances by
|
|
114
|
-
* {@link add} and {@link setSurface}. Stale-high is a wider margin; the
|
|
115
|
-
* other direction is a missed contact, so the maximum is never lowered
|
|
116
|
-
* inside a step.
|
|
107
|
+
* Diagnostic upper bound, exact after {@link advance} and only raised
|
|
108
|
+
* between advances. Contact queries use each collider's own reach instead.
|
|
117
109
|
* @type {number}
|
|
118
110
|
*/
|
|
119
111
|
max_inflation: number;
|
|
120
112
|
/**
|
|
121
113
|
* The furthest any live collider has moved since {@link advance}, metres.
|
|
122
114
|
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
* the set it hands over is smaller than the set the rows are drawn from.
|
|
115
|
+
* Diagnostic upper bound. Contact queries carry travel on each collider's
|
|
116
|
+
* leaf, so a remote outlier cannot widen every cloth's query.
|
|
126
117
|
* @type {number}
|
|
127
118
|
*/
|
|
128
119
|
max_collider_travel: number;
|
|
@@ -154,6 +145,11 @@ export class ClothColliderIndex {
|
|
|
154
145
|
* @returns {boolean}
|
|
155
146
|
*/
|
|
156
147
|
isLive(handle: number): boolean;
|
|
148
|
+
/**
|
|
149
|
+
* @param {number} handle
|
|
150
|
+
* @returns {number} revision of the live record
|
|
151
|
+
*/
|
|
152
|
+
revisionOf(handle: number): number;
|
|
157
153
|
/**
|
|
158
154
|
* Roll every live record's current pose into its previous one. Called once
|
|
159
155
|
* per fixed step, before any pose for this step is written.
|
|
@@ -235,9 +231,12 @@ export class ClothColliderIndex {
|
|
|
235
231
|
* @param {number} max_z
|
|
236
232
|
* @param {number} layer the querier's layer
|
|
237
233
|
* @param {number} mask the querier's mask
|
|
234
|
+
* @param {boolean} [contact] include each collider's own travel and contact
|
|
235
|
+
* inflation and conversion allowance; the caller supplies particle radius,
|
|
236
|
+
* travel and its local-coordinate conversion allowance in the query box
|
|
238
237
|
* @returns {number} how many handles were written
|
|
239
238
|
*/
|
|
240
|
-
query(out: number[], min_x: number, min_y: number, min_z: number, max_x: number, max_y: number, max_z: number, layer: number, mask: number): number;
|
|
239
|
+
query(out: number[], min_x: number, min_y: number, min_z: number, max_x: number, max_y: number, max_z: number, layer: number, mask: number, contact?: boolean): number;
|
|
241
240
|
#private;
|
|
242
241
|
}
|
|
243
242
|
//# sourceMappingURL=ClothColliderIndex.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClothColliderIndex.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/collider/ClothColliderIndex.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ClothColliderIndex.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/collider/ClothColliderIndex.js"],"names":[],"mappings":"AA2CA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH;IAEI;;;;;;OAMG;IACH,OAFU,YAAY,CAEM;IAE5B;;;;;OAKG;IACH,MAFU,UAAU,CAEK;IAEzB;;;;OAIG;IACH,OAFU,MAAM,CAEN;IAEV;;;;;;OAMG;IACH,eAFU,MAAM,CAEE;IAElB;;;;;;OAMG;IACH,qBAFU,MAAM,CAEQ;IAoFxB;;;;;;;;;;;OAWG;IACH,sCAPW,MAAM,aACN,MAAM,SACN,MAAM,QACN,MAAM,UACN,MAAM,GACJ,MAAM,CA8DlB;IAED;;;;;;;OAOG;IACH,eAHW,MAAM,GACJ,IAAI,CAoChB;IAED;;;;OAIG;IACH,eAHW,MAAM,GACJ,OAAO,CAInB;IAED;;;OAGG;IACH,mBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;;OAIG;IACH,WAFa,IAAI,CAuDhB;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,gBAVW,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,GACJ,IAAI,CA2BhB;IAwID;;;;;;;;;;;;;;;OAeG;IACH,kBAVW,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,GACJ,IAAI,CAiBhB;IAED;;;;;;;;OAQG;IACH,mBALW,MAAM,YACN,MAAM,aACN,MAAM,GACJ,IAAI,CAoBhB;IAED;;;;;OAKG;IACH,kBALW,MAAM,SACN,MAAM,QACN,MAAM,GACJ,IAAI,CAWhB;IAED;;;OAGG;IACH,iBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,WAdW,MAAM,EAAE,SACR,MAAM,SACN,MAAM,SACN,MAAM,SACN,MAAM,SACN,MAAM,SACN,MAAM,SACN,MAAM,QACN,MAAM,YACN,OAAO,GAGL,MAAM,CA6DlB;;CA6GJ"}
|
|
@@ -17,6 +17,9 @@ import {
|
|
|
17
17
|
CCR_META_MASK,
|
|
18
18
|
CCR_META_STRIDE,
|
|
19
19
|
CCR_KIND,
|
|
20
|
+
CCR_PARAM_0,
|
|
21
|
+
CCR_PARAM_1,
|
|
22
|
+
CCR_PARAM_2,
|
|
20
23
|
CCR_PREV_QW,
|
|
21
24
|
CCR_PREV_QX,
|
|
22
25
|
CCR_PREV_QY,
|
|
@@ -33,9 +36,10 @@ import {
|
|
|
33
36
|
CCR_TY,
|
|
34
37
|
CCR_TZ
|
|
35
38
|
} from "./ClothColliderRecord.js";
|
|
36
|
-
import { cloth_collider_refit_bounds } from "./cloth_collider_bounds.js";
|
|
39
|
+
import { cloth_collider_refit_bounds, cloth_contact_rounding } from "./cloth_collider_bounds.js";
|
|
37
40
|
import { cloth_collider_pack } from "./cloth_collider_pack.js";
|
|
38
41
|
import { ClothColliderKind } from "./ClothColliderKind.js";
|
|
42
|
+
import { CLOTH_CONTACT_MARGIN } from "../solver/cloth_contact_find.js";
|
|
39
43
|
|
|
40
44
|
/**
|
|
41
45
|
* # The index of live cloth colliders
|
|
@@ -147,16 +151,8 @@ export class ClothColliderIndex {
|
|
|
147
151
|
/**
|
|
148
152
|
* The widest {@link CCR_INFLATION} any live record carries, metres.
|
|
149
153
|
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
* each particle. The gather cannot know which colliders it is about to find,
|
|
153
|
-
* so it takes the widest in the index — which is why this is here rather
|
|
154
|
-
* than derived per query.
|
|
155
|
-
*
|
|
156
|
-
* Exact after {@link advance}, and only ever raised between advances by
|
|
157
|
-
* {@link add} and {@link setSurface}. Stale-high is a wider margin; the
|
|
158
|
-
* other direction is a missed contact, so the maximum is never lowered
|
|
159
|
-
* inside a step.
|
|
154
|
+
* Diagnostic upper bound, exact after {@link advance} and only raised
|
|
155
|
+
* between advances. Contact queries use each collider's own reach instead.
|
|
160
156
|
* @type {number}
|
|
161
157
|
*/
|
|
162
158
|
max_inflation = 0;
|
|
@@ -164,9 +160,8 @@ export class ClothColliderIndex {
|
|
|
164
160
|
/**
|
|
165
161
|
* The furthest any live collider has moved since {@link advance}, metres.
|
|
166
162
|
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
* the set it hands over is smaller than the set the rows are drawn from.
|
|
163
|
+
* Diagnostic upper bound. Contact queries carry travel on each collider's
|
|
164
|
+
* leaf, so a remote outlier cannot widen every cloth's query.
|
|
170
165
|
* @type {number}
|
|
171
166
|
*/
|
|
172
167
|
max_collider_travel = 0;
|
|
@@ -214,6 +209,23 @@ export class ClothColliderIndex {
|
|
|
214
209
|
*/
|
|
215
210
|
#node = new Uint32Array(0);
|
|
216
211
|
|
|
212
|
+
/**
|
|
213
|
+
* Each collider's speculative contact reach: its own translation travel
|
|
214
|
+
* plus inflation. Stored on the leaf instead of widening every cloth's
|
|
215
|
+
* query by the largest motion anywhere in the world.
|
|
216
|
+
* @type {Float64Array}
|
|
217
|
+
* @private
|
|
218
|
+
*/
|
|
219
|
+
#reach = new Float64Array(0);
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Changes to a handle's identity, pose, surface or filter. A placement has
|
|
223
|
+
* equal previous/current poses but must still wake cloth resting against it.
|
|
224
|
+
* @type {Uint32Array}
|
|
225
|
+
* @private
|
|
226
|
+
*/
|
|
227
|
+
#revision = new Uint32Array(0);
|
|
228
|
+
|
|
217
229
|
/**
|
|
218
230
|
* Handles of live half-spaces, which cannot go in the tree. Empty in every
|
|
219
231
|
* scene this engine has; see the class docblock.
|
|
@@ -277,6 +289,7 @@ export class ClothColliderIndex {
|
|
|
277
289
|
this.meta[m + CCR_META_ENTITY] = entity;
|
|
278
290
|
|
|
279
291
|
this.#live[handle] = 1;
|
|
292
|
+
this.#revision[handle]++;
|
|
280
293
|
|
|
281
294
|
// No pose yet, and a record with an uninitialised rotation is a
|
|
282
295
|
// quaternion of all zeros — which normalises to nothing and poses
|
|
@@ -362,6 +375,14 @@ export class ClothColliderIndex {
|
|
|
362
375
|
return handle >= 0 && handle < this.count && this.#live[handle] === 1;
|
|
363
376
|
}
|
|
364
377
|
|
|
378
|
+
/**
|
|
379
|
+
* @param {number} handle
|
|
380
|
+
* @returns {number} revision of the live record
|
|
381
|
+
*/
|
|
382
|
+
revisionOf(handle) {
|
|
383
|
+
return this.#revision[handle];
|
|
384
|
+
}
|
|
385
|
+
|
|
365
386
|
/**
|
|
366
387
|
* Roll every live record's current pose into its previous one. Called once
|
|
367
388
|
* per fixed step, before any pose for this step is written.
|
|
@@ -398,6 +419,14 @@ export class ClothColliderIndex {
|
|
|
398
419
|
this.max_inflation = table[r + CCR_INFLATION];
|
|
399
420
|
}
|
|
400
421
|
|
|
422
|
+
const moved = table[r + CCR_PREV_TX] !== table[r + CCR_TX]
|
|
423
|
+
|| table[r + CCR_PREV_TY] !== table[r + CCR_TY]
|
|
424
|
+
|| table[r + CCR_PREV_TZ] !== table[r + CCR_TZ]
|
|
425
|
+
|| table[r + CCR_PREV_QX] !== table[r + CCR_QX]
|
|
426
|
+
|| table[r + CCR_PREV_QY] !== table[r + CCR_QY]
|
|
427
|
+
|| table[r + CCR_PREV_QZ] !== table[r + CCR_QZ]
|
|
428
|
+
|| table[r + CCR_PREV_QW] !== table[r + CCR_QW];
|
|
429
|
+
|
|
401
430
|
table[r + CCR_PREV_TX] = table[r + CCR_TX];
|
|
402
431
|
table[r + CCR_PREV_TY] = table[r + CCR_TY];
|
|
403
432
|
table[r + CCR_PREV_TZ] = table[r + CCR_TZ];
|
|
@@ -406,6 +435,11 @@ export class ClothColliderIndex {
|
|
|
406
435
|
table[r + CCR_PREV_QY] = table[r + CCR_QY];
|
|
407
436
|
table[r + CCR_PREV_QZ] = table[r + CCR_QZ];
|
|
408
437
|
table[r + CCR_PREV_QW] = table[r + CCR_QW];
|
|
438
|
+
|
|
439
|
+
if (moved) {
|
|
440
|
+
cloth_collider_refit_bounds(table, handle, CCR_STRIDE);
|
|
441
|
+
this.#refit(handle);
|
|
442
|
+
}
|
|
409
443
|
}
|
|
410
444
|
}
|
|
411
445
|
|
|
@@ -434,6 +468,12 @@ export class ClothColliderIndex {
|
|
|
434
468
|
|
|
435
469
|
const r = handle * CCR_STRIDE;
|
|
436
470
|
|
|
471
|
+
if (table[r + CCR_TX] !== tx || table[r + CCR_TY] !== ty || table[r + CCR_TZ] !== tz
|
|
472
|
+
|| table[r + CCR_QX] !== qx || table[r + CCR_QY] !== qy
|
|
473
|
+
|| table[r + CCR_QZ] !== qz || table[r + CCR_QW] !== qw) {
|
|
474
|
+
this.#revision[handle]++;
|
|
475
|
+
}
|
|
476
|
+
|
|
437
477
|
table[r + CCR_TX] = tx;
|
|
438
478
|
table[r + CCR_TY] = ty;
|
|
439
479
|
table[r + CCR_TZ] = tz;
|
|
@@ -445,12 +485,37 @@ export class ClothColliderIndex {
|
|
|
445
485
|
|
|
446
486
|
cloth_collider_refit_bounds(this.table, handle, CCR_STRIDE);
|
|
447
487
|
|
|
488
|
+
this.#refit(handle);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* @param {number} handle
|
|
493
|
+
* @private
|
|
494
|
+
*/
|
|
495
|
+
#refit(handle) {
|
|
496
|
+
const table = this.table;
|
|
497
|
+
const r = handle * CCR_STRIDE;
|
|
498
|
+
|
|
448
499
|
const travel = Math.hypot(
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
500
|
+
table[r + CCR_TX] - table[r + CCR_PREV_TX],
|
|
501
|
+
table[r + CCR_TY] - table[r + CCR_PREV_TY],
|
|
502
|
+
table[r + CCR_TZ] - table[r + CCR_PREV_TZ]
|
|
452
503
|
);
|
|
453
504
|
|
|
505
|
+
const contact_reach = travel + Math.max(0, table[r + CCR_INFLATION]) * (1 + CLOTH_CONTACT_MARGIN);
|
|
506
|
+
// The sum of the bounded primitive's dimensions bounds its radius.
|
|
507
|
+
// Include conversion error in BOTH the tree leaf and the final test;
|
|
508
|
+
// the BVH's storage slack alone is discarded by the latter.
|
|
509
|
+
const geometry = table[r + CCR_KIND] === ClothColliderKind.Plane ? 0
|
|
510
|
+
: Math.abs(table[r + CCR_PARAM_0]) + Math.abs(table[r + CCR_PARAM_1])
|
|
511
|
+
+ Math.abs(table[r + CCR_PARAM_2]);
|
|
512
|
+
const local_scale = geometry + contact_reach;
|
|
513
|
+
const world_scale = local_scale
|
|
514
|
+
+ Math.abs(table[r + CCR_TX]) + Math.abs(table[r + CCR_TY]) + Math.abs(table[r + CCR_TZ])
|
|
515
|
+
+ Math.abs(table[r + CCR_PREV_TX]) + Math.abs(table[r + CCR_PREV_TY]) + Math.abs(table[r + CCR_PREV_TZ]);
|
|
516
|
+
const reach = contact_reach + cloth_contact_rounding(local_scale, world_scale);
|
|
517
|
+
this.#reach[handle] = reach;
|
|
518
|
+
|
|
454
519
|
if (travel > this.max_collider_travel) {
|
|
455
520
|
this.max_collider_travel = travel;
|
|
456
521
|
}
|
|
@@ -485,12 +550,20 @@ export class ClothColliderIndex {
|
|
|
485
550
|
// tree.
|
|
486
551
|
this.#bvh.node_get_aabb(node, STORED_AABB);
|
|
487
552
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
553
|
+
let contained = true;
|
|
554
|
+
let oversized = false;
|
|
555
|
+
for (let axis = 0; axis < 3; axis++) {
|
|
556
|
+
const lower = table[r + CCR_AABB_MIN_X + axis] - reach;
|
|
557
|
+
const upper = table[r + CCR_AABB_MAX_X + axis] + reach;
|
|
558
|
+
if (lower < STORED_AABB[axis] || upper > STORED_AABB[axis + 3]) contained = false;
|
|
559
|
+
// A one-step outlier must not leave a scene-sized leaf behind once
|
|
560
|
+
// motion stops. Allow ordinary jitter to keep spending the slack.
|
|
561
|
+
if (STORED_AABB[axis + 3] - STORED_AABB[axis]
|
|
562
|
+
> 2 * (upper - lower + 2 * BVH_LEAF_SLACK
|
|
563
|
+
+ (Math.abs(lower) + Math.abs(upper)) * FLOAT32_ROUNDING)) oversized = true;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
if (contained && !oversized) {
|
|
494
567
|
return;
|
|
495
568
|
}
|
|
496
569
|
|
|
@@ -510,8 +583,8 @@ export class ClothColliderIndex {
|
|
|
510
583
|
}
|
|
511
584
|
|
|
512
585
|
/**
|
|
513
|
-
* Write a record's swept bounds into {@link FAT_AABB}
|
|
514
|
-
* refit skip spends, and store them on the leaf.
|
|
586
|
+
* Write a record's swept bounds plus its contact reach into {@link FAT_AABB}
|
|
587
|
+
* with the slack the refit skip spends, and store them on the leaf.
|
|
515
588
|
*
|
|
516
589
|
* The slack is also what makes the tree's `Float32` nodes safe to hold a
|
|
517
590
|
* `Float64` world, and it has two terms because one is not enough. The
|
|
@@ -536,10 +609,11 @@ export class ClothColliderIndex {
|
|
|
536
609
|
*/
|
|
537
610
|
#store_fat_aabb(node, r) {
|
|
538
611
|
const table = this.table;
|
|
612
|
+
const reach = this.#reach[r / CCR_STRIDE];
|
|
539
613
|
|
|
540
614
|
for (let axis = 0; axis < 3; axis++) {
|
|
541
|
-
const lower = table[r + CCR_AABB_MIN_X + axis];
|
|
542
|
-
const upper = table[r + CCR_AABB_MAX_X + axis];
|
|
615
|
+
const lower = table[r + CCR_AABB_MIN_X + axis] - reach;
|
|
616
|
+
const upper = table[r + CCR_AABB_MAX_X + axis] + reach;
|
|
543
617
|
|
|
544
618
|
FAT_AABB[axis] = lower - BVH_LEAF_SLACK - Math.abs(lower) * FLOAT32_ROUNDING;
|
|
545
619
|
FAT_AABB[axis + 3] = upper + BVH_LEAF_SLACK + Math.abs(upper) * FLOAT32_ROUNDING;
|
|
@@ -593,6 +667,10 @@ export class ClothColliderIndex {
|
|
|
593
667
|
setSurface(handle, friction, inflation) {
|
|
594
668
|
const r = handle * CCR_STRIDE;
|
|
595
669
|
|
|
670
|
+
if (this.table[r + CCR_FRICTION] !== friction || this.table[r + CCR_INFLATION] !== inflation) {
|
|
671
|
+
this.#revision[handle]++;
|
|
672
|
+
}
|
|
673
|
+
|
|
596
674
|
this.table[r + CCR_FRICTION] = friction;
|
|
597
675
|
this.table[r + CCR_INFLATION] = inflation;
|
|
598
676
|
|
|
@@ -602,6 +680,8 @@ export class ClothColliderIndex {
|
|
|
602
680
|
if (inflation > this.max_inflation) {
|
|
603
681
|
this.max_inflation = inflation;
|
|
604
682
|
}
|
|
683
|
+
|
|
684
|
+
this.#refit(handle);
|
|
605
685
|
}
|
|
606
686
|
|
|
607
687
|
/**
|
|
@@ -613,6 +693,10 @@ export class ClothColliderIndex {
|
|
|
613
693
|
setFilter(handle, layer, mask) {
|
|
614
694
|
const m = handle * CCR_META_STRIDE;
|
|
615
695
|
|
|
696
|
+
if (this.meta[m + CCR_META_LAYER] !== (layer | 0) || this.meta[m + CCR_META_MASK] !== (mask | 0)) {
|
|
697
|
+
this.#revision[handle]++;
|
|
698
|
+
}
|
|
699
|
+
|
|
616
700
|
this.meta[m + CCR_META_LAYER] = layer;
|
|
617
701
|
this.meta[m + CCR_META_MASK] = mask;
|
|
618
702
|
}
|
|
@@ -642,9 +726,12 @@ export class ClothColliderIndex {
|
|
|
642
726
|
* @param {number} max_z
|
|
643
727
|
* @param {number} layer the querier's layer
|
|
644
728
|
* @param {number} mask the querier's mask
|
|
729
|
+
* @param {boolean} [contact] include each collider's own travel and contact
|
|
730
|
+
* inflation and conversion allowance; the caller supplies particle radius,
|
|
731
|
+
* travel and its local-coordinate conversion allowance in the query box
|
|
645
732
|
* @returns {number} how many handles were written
|
|
646
733
|
*/
|
|
647
|
-
query(out, min_x, min_y, min_z, max_x, max_y, max_z, layer, mask) {
|
|
734
|
+
query(out, min_x, min_y, min_z, max_x, max_y, max_z, layer, mask, contact = false) {
|
|
648
735
|
QUERY_AABB[0] = min_x;
|
|
649
736
|
QUERY_AABB[1] = min_y;
|
|
650
737
|
QUERY_AABB[2] = min_z;
|
|
@@ -676,9 +763,9 @@ export class ClothColliderIndex {
|
|
|
676
763
|
for (let i = 0; i < candidate_count; i++) {
|
|
677
764
|
const handle = candidates[i];
|
|
678
765
|
|
|
679
|
-
//
|
|
680
|
-
//
|
|
681
|
-
if (this.#overlaps(handle, min_x, min_y, min_z, max_x, max_y, max_z, layer, mask)) {
|
|
766
|
+
// Raw queries use the exact record. Contact queries retain the
|
|
767
|
+
// conversion allowance needed by the solver's Float32 table.
|
|
768
|
+
if (this.#overlaps(handle, min_x, min_y, min_z, max_x, max_y, max_z, layer, mask, contact)) {
|
|
682
769
|
answer.push(handle);
|
|
683
770
|
}
|
|
684
771
|
}
|
|
@@ -688,7 +775,7 @@ export class ClothColliderIndex {
|
|
|
688
775
|
for (let i = 0; i < planes.length; i++) {
|
|
689
776
|
const handle = planes[i];
|
|
690
777
|
|
|
691
|
-
if (this.#overlaps(handle, min_x, min_y, min_z, max_x, max_y, max_z, layer, mask)) {
|
|
778
|
+
if (this.#overlaps(handle, min_x, min_y, min_z, max_x, max_y, max_z, layer, mask, contact)) {
|
|
692
779
|
answer.push(handle);
|
|
693
780
|
}
|
|
694
781
|
}
|
|
@@ -718,10 +805,11 @@ export class ClothColliderIndex {
|
|
|
718
805
|
* @param {number} max_z
|
|
719
806
|
* @param {number} layer
|
|
720
807
|
* @param {number} mask
|
|
808
|
+
* @param {boolean} contact
|
|
721
809
|
* @returns {boolean}
|
|
722
810
|
* @private
|
|
723
811
|
*/
|
|
724
|
-
#overlaps(handle, min_x, min_y, min_z, max_x, max_y, max_z, layer, mask) {
|
|
812
|
+
#overlaps(handle, min_x, min_y, min_z, max_x, max_y, max_z, layer, mask, contact) {
|
|
725
813
|
if (this.#live[handle] === 0) {
|
|
726
814
|
return false;
|
|
727
815
|
}
|
|
@@ -742,15 +830,22 @@ export class ClothColliderIndex {
|
|
|
742
830
|
|
|
743
831
|
const r = handle * CCR_STRIDE;
|
|
744
832
|
|
|
745
|
-
|
|
833
|
+
// A plane has no finite radius with which to bound a rounded normal's
|
|
834
|
+
// displacement. Keep every filtered half-space; the gather can reject
|
|
835
|
+
// it using the solver's actual local bounds before applying its cap.
|
|
836
|
+
if (contact && table[r + CCR_KIND] === ClothColliderKind.Plane) return true;
|
|
837
|
+
|
|
838
|
+
const reach = contact ? this.#reach[handle] : 0;
|
|
839
|
+
|
|
840
|
+
if (table[r + CCR_AABB_MIN_X] - reach > max_x || table[r + CCR_AABB_MAX_X] + reach < min_x) {
|
|
746
841
|
return false;
|
|
747
842
|
}
|
|
748
843
|
|
|
749
|
-
if (table[r + CCR_AABB_MIN_Y] > max_y || table[r + CCR_AABB_MAX_Y] < min_y) {
|
|
844
|
+
if (table[r + CCR_AABB_MIN_Y] - reach > max_y || table[r + CCR_AABB_MAX_Y] + reach < min_y) {
|
|
750
845
|
return false;
|
|
751
846
|
}
|
|
752
847
|
|
|
753
|
-
if (table[r + CCR_AABB_MIN_Z] > max_z || table[r + CCR_AABB_MAX_Z] < min_z) {
|
|
848
|
+
if (table[r + CCR_AABB_MIN_Z] - reach > max_z || table[r + CCR_AABB_MAX_Z] + reach < min_z) {
|
|
754
849
|
return false;
|
|
755
850
|
}
|
|
756
851
|
|
|
@@ -784,11 +879,15 @@ export class ClothColliderIndex {
|
|
|
784
879
|
const meta = new Int32Array(capacity * CCR_META_STRIDE);
|
|
785
880
|
const live = new Uint8Array(capacity);
|
|
786
881
|
const node = new Uint32Array(capacity);
|
|
882
|
+
const reach = new Float64Array(capacity);
|
|
883
|
+
const revision = new Uint32Array(capacity);
|
|
787
884
|
|
|
788
885
|
table.set(this.table);
|
|
789
886
|
meta.set(this.meta);
|
|
790
887
|
live.set(this.#live);
|
|
791
888
|
node.set(this.#node);
|
|
889
|
+
reach.set(this.#reach);
|
|
890
|
+
revision.set(this.#revision);
|
|
792
891
|
|
|
793
892
|
node.fill(NULL_NODE, this.#node.length);
|
|
794
893
|
|
|
@@ -796,6 +895,8 @@ export class ClothColliderIndex {
|
|
|
796
895
|
this.meta = meta;
|
|
797
896
|
this.#live = live;
|
|
798
897
|
this.#node = node;
|
|
898
|
+
this.#reach = reach;
|
|
899
|
+
this.#revision = revision;
|
|
799
900
|
}
|
|
800
901
|
|
|
801
902
|
}
|
|
@@ -1,3 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Outward error allowance when a world-space query precedes the solver's
|
|
3
|
+
* Float32 conversion. Shared by the cloth query and the collider leaf: their
|
|
4
|
+
* allowances add, just as their speculative contact reaches do.
|
|
5
|
+
*
|
|
6
|
+
* Let u = 2^-24, P bound the particle's local distance from the anchor, G the
|
|
7
|
+
* shape radius, and L the sum of the contact and motion reaches. Rounding a
|
|
8
|
+
* localized translation contributes at most u times its length; rounding both
|
|
9
|
+
* swept translations adds at most u(2|t| + travel) to the measured travel.
|
|
10
|
+
* The relative quaternion is rounded, normalized and rounded again. Its
|
|
11
|
+
* error is less than 4u, so its inverse rotation/scale displaces a point by
|
|
12
|
+
* less than 9u times its radius. Shape parameters and inflation round once.
|
|
13
|
+
* Together these are bounded by 4u|t| + 16u(G + L). For an accepted contact,
|
|
14
|
+
* |t| <= P + G + L + error; substituting bounds that error by 32u(P + G + L).
|
|
15
|
+
* We spend 64u, including outward arithmetic rounding. P and the particle
|
|
16
|
+
* reach are paid by the query, G and collider reach by the index. No world
|
|
17
|
+
* coordinate is multiplied by a Float32 epsilon.
|
|
18
|
+
*
|
|
19
|
+
* World transforms/bounds use doubles: the separate world term covers their
|
|
20
|
+
* subtraction and rotation arithmetic, including cancellation far from the
|
|
21
|
+
* origin. The absolute term covers Float32 subnormals. Assumes finite solver
|
|
22
|
+
* values and rigid unit-quaternion input poses, as the collider API does.
|
|
23
|
+
* Unbounded planes cannot use a shape-radius bound and are always candidates
|
|
24
|
+
* for a contact query (their layer/mask still applies).
|
|
25
|
+
*
|
|
26
|
+
* @param {number} local_scale nonnegative local length bound
|
|
27
|
+
* @param {number} world_scale nonnegative world arithmetic magnitude bound
|
|
28
|
+
* @returns {number} metres of outward padding
|
|
29
|
+
*/
|
|
30
|
+
export function cloth_contact_rounding(local_scale: number, world_scale: number): number;
|
|
1
31
|
/**
|
|
2
32
|
* # The swept bounds of a packed collider
|
|
3
33
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloth_collider_bounds.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/collider/cloth_collider_bounds.js"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;GAOG;AACH,mDALW,YAAY,GAAC,YAAY,UACzB,MAAM,UACN,MAAM,GACJ,IAAI,CAoBhB"}
|
|
1
|
+
{"version":3,"file":"cloth_collider_bounds.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/collider/cloth_collider_bounds.js"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,oDAJW,MAAM,eACN,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;GAOG;AACH,mDALW,YAAY,GAAC,YAAY,UACzB,MAAM,UACN,MAAM,GACJ,IAAI,CAoBhB"}
|
|
@@ -19,6 +19,39 @@ import {
|
|
|
19
19
|
} from "./ClothColliderRecord.js";
|
|
20
20
|
import { cloth_collider_local_bounds } from "./cloth_collider_pack.js";
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Outward error allowance when a world-space query precedes the solver's
|
|
24
|
+
* Float32 conversion. Shared by the cloth query and the collider leaf: their
|
|
25
|
+
* allowances add, just as their speculative contact reaches do.
|
|
26
|
+
*
|
|
27
|
+
* Let u = 2^-24, P bound the particle's local distance from the anchor, G the
|
|
28
|
+
* shape radius, and L the sum of the contact and motion reaches. Rounding a
|
|
29
|
+
* localized translation contributes at most u times its length; rounding both
|
|
30
|
+
* swept translations adds at most u(2|t| + travel) to the measured travel.
|
|
31
|
+
* The relative quaternion is rounded, normalized and rounded again. Its
|
|
32
|
+
* error is less than 4u, so its inverse rotation/scale displaces a point by
|
|
33
|
+
* less than 9u times its radius. Shape parameters and inflation round once.
|
|
34
|
+
* Together these are bounded by 4u|t| + 16u(G + L). For an accepted contact,
|
|
35
|
+
* |t| <= P + G + L + error; substituting bounds that error by 32u(P + G + L).
|
|
36
|
+
* We spend 64u, including outward arithmetic rounding. P and the particle
|
|
37
|
+
* reach are paid by the query, G and collider reach by the index. No world
|
|
38
|
+
* coordinate is multiplied by a Float32 epsilon.
|
|
39
|
+
*
|
|
40
|
+
* World transforms/bounds use doubles: the separate world term covers their
|
|
41
|
+
* subtraction and rotation arithmetic, including cancellation far from the
|
|
42
|
+
* origin. The absolute term covers Float32 subnormals. Assumes finite solver
|
|
43
|
+
* values and rigid unit-quaternion input poses, as the collider API does.
|
|
44
|
+
* Unbounded planes cannot use a shape-radius bound and are always candidates
|
|
45
|
+
* for a contact query (their layer/mask still applies).
|
|
46
|
+
*
|
|
47
|
+
* @param {number} local_scale nonnegative local length bound
|
|
48
|
+
* @param {number} world_scale nonnegative world arithmetic magnitude bound
|
|
49
|
+
* @returns {number} metres of outward padding
|
|
50
|
+
*/
|
|
51
|
+
export function cloth_contact_rounding(local_scale, world_scale) {
|
|
52
|
+
return 64 * (2 ** -24 * local_scale + Number.EPSILON * world_scale + 2 ** -149);
|
|
53
|
+
}
|
|
54
|
+
|
|
22
55
|
/**
|
|
23
56
|
* # The swept bounds of a packed collider
|
|
24
57
|
*
|
|
@@ -24,7 +24,8 @@ export const ClothColliderFlags = {
|
|
|
24
24
|
* the sweep degenerates to the pose it already had. Move the entity anyway
|
|
25
25
|
* and the cloth will not notice: that is the trade, and it is why this is
|
|
26
26
|
* an author's assertion rather than something derived from a pose that
|
|
27
|
-
* happens not to have changed yet.
|
|
27
|
+
* happens not to have changed yet. An explicit TRANSFORM64_EVENT_PLACED
|
|
28
|
+
* (including PhysicsSystem.setPose) does re-place a static proxy.
|
|
28
29
|
*/
|
|
29
30
|
Static: 1
|
|
30
31
|
};
|
|
@@ -63,7 +63,8 @@ export class ClothColliderSystem extends System<any> {
|
|
|
63
63
|
* they were linked. Held rather than looked up per step for the same reason
|
|
64
64
|
* `ClothInstance` holds its transforms: a refresh is a loop over live
|
|
65
65
|
* colliders, not a query.
|
|
66
|
-
* @type {{collider: ClothCollider, transform: Transform64, entity: number, handle: number
|
|
66
|
+
* @type {{collider: ClothCollider, transform: Transform64, entity: number, handle: number,
|
|
67
|
+
* linked: boolean, onPlaced: function(): void}[]}
|
|
67
68
|
* @private
|
|
68
69
|
*/
|
|
69
70
|
private __linked;
|
|
@@ -99,6 +100,14 @@ export class ClothColliderSystem extends System<any> {
|
|
|
99
100
|
* @returns {void}
|
|
100
101
|
*/
|
|
101
102
|
refreshSurface(entity: number): void;
|
|
103
|
+
/**
|
|
104
|
+
* Reset motion history at an explicitly published placement, including
|
|
105
|
+
* static proxies. The next refresh can still sweep any subsequent motion.
|
|
106
|
+
* @param {number} handle
|
|
107
|
+
* @param {Transform64} transform
|
|
108
|
+
* @private
|
|
109
|
+
*/
|
|
110
|
+
private __place;
|
|
102
111
|
/**
|
|
103
112
|
* @param {number} entity
|
|
104
113
|
* @returns {number} the index handle, or `undefined` if the entity is not indexed
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClothColliderSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/ClothColliderSystem.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ClothColliderSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/ClothColliderSystem.js"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH;;IAEI,8EAAsD;IAEtD,wKAIE;IAEF;;OAEG;IACH,OAFU,kBAAkB,CAEK;IAEjC;;;;;;OAMG;IACH,kBAAsB;IAEtB;;;;;;;;OAQG;IACH,iBAAc;IAEd;;;;;OAKG;IACH,qBALW,aAAa,YACb,QAAQ,aACR,WAAW,UACX,MAAM,QAoChB;IAED;;;;;OAKG;IACH,uBALW,aAAa,YACb,QAAQ,aACR,WAAW,UACX,MAAM,QAqBhB;IAED;;;;;;OAMG;IACH,WAFa,IAAI,CAkChB;IAED;;;;;;;;OAQG;IACH,uBAHW,MAAM,GACJ,IAAI,CAyBhB;IAED;;;;;;OAMG;IACH,gBAWC;IAED;;;OAGG;IACH,iBAHW,MAAM,GACJ,MAAM,CAIlB;CACJ;uBAtQsB,wBAAwB;4BAMxC,uCAAuC;yBACrB,uBAAuB;8BAElB,oBAAoB;4CAVN,uDAAuD;mCAShE,mCAAmC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ResourceAccessKind } from "../../../../core/model/ResourceAccessKind.js";
|
|
2
2
|
import { ResourceAccessSpecification } from "../../../../core/model/ResourceAccessSpecification.js";
|
|
3
3
|
import { System } from "../../../ecs/System.js";
|
|
4
|
+
import { TRANSFORM64_EVENT_PLACED } from "../../../ecs/transform/TRANSFORM64_EVENT_PLACED.js";
|
|
4
5
|
import {
|
|
5
6
|
TRANSFORM64_ROTATION_OFFSET,
|
|
6
7
|
TRANSFORM64_TRANSLATION_OFFSET,
|
|
@@ -84,7 +85,8 @@ export class ClothColliderSystem extends System {
|
|
|
84
85
|
* they were linked. Held rather than looked up per step for the same reason
|
|
85
86
|
* `ClothInstance` holds its transforms: a refresh is a loop over live
|
|
86
87
|
* colliders, not a query.
|
|
87
|
-
* @type {{collider: ClothCollider, transform: Transform64, entity: number, handle: number
|
|
88
|
+
* @type {{collider: ClothCollider, transform: Transform64, entity: number, handle: number,
|
|
89
|
+
* linked: boolean, onPlaced: function(): void}[]}
|
|
88
90
|
* @private
|
|
89
91
|
*/
|
|
90
92
|
__linked = [];
|
|
@@ -117,20 +119,18 @@ export class ClothColliderSystem extends System {
|
|
|
117
119
|
|
|
118
120
|
this.__handles.set(entity, handle);
|
|
119
121
|
|
|
120
|
-
|
|
122
|
+
const entry = { collider: cloth_collider, transform, entity, handle, linked: true, onPlaced: () => {
|
|
123
|
+
// Dispatch snapshots can retain this listener after unlink, even
|
|
124
|
+
// after both its entity id and index slot have been reused.
|
|
125
|
+
if (entry.linked) this.__place(handle, transform);
|
|
126
|
+
} };
|
|
127
|
+
this.__linked.push(entry);
|
|
128
|
+
|
|
129
|
+
this.entityManager.dataset.addEntityEventListener(entity, TRANSFORM64_EVENT_PLACED, entry.onPlaced);
|
|
121
130
|
|
|
122
131
|
// Placed rather than posed, so its first step sweeps nothing. A
|
|
123
132
|
// collider that has just appeared did not move.
|
|
124
|
-
this.
|
|
125
|
-
handle,
|
|
126
|
-
transform[TRANSFORM64_TRANSLATION_OFFSET],
|
|
127
|
-
transform[TRANSFORM64_TRANSLATION_OFFSET + 1],
|
|
128
|
-
transform[TRANSFORM64_TRANSLATION_OFFSET + 2],
|
|
129
|
-
transform[TRANSFORM64_ROTATION_OFFSET],
|
|
130
|
-
transform[TRANSFORM64_ROTATION_OFFSET + 1],
|
|
131
|
-
transform[TRANSFORM64_ROTATION_OFFSET + 2],
|
|
132
|
-
transform[TRANSFORM64_ROTATION_OFFSET + 3]
|
|
133
|
-
);
|
|
133
|
+
this.__place(handle, transform);
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
/**
|
|
@@ -148,9 +148,11 @@ export class ClothColliderSystem extends System {
|
|
|
148
148
|
|
|
149
149
|
this.__handles.delete(entity);
|
|
150
150
|
this.index.remove(handle);
|
|
151
|
-
|
|
152
151
|
for (let i = 0; i < this.__linked.length; i++) {
|
|
153
|
-
|
|
152
|
+
const entry = this.__linked[i];
|
|
153
|
+
if (entry.entity === entity) {
|
|
154
|
+
entry.linked = false;
|
|
155
|
+
this.entityManager.dataset.removeEntityEventListener(entity, TRANSFORM64_EVENT_PLACED, entry.onPlaced);
|
|
154
156
|
this.__linked.splice(i, 1);
|
|
155
157
|
|
|
156
158
|
break;
|
|
@@ -233,6 +235,26 @@ export class ClothColliderSystem extends System {
|
|
|
233
235
|
this.index.setFilter(handle, cloth_collider.layer, cloth_collider.mask);
|
|
234
236
|
}
|
|
235
237
|
|
|
238
|
+
/**
|
|
239
|
+
* Reset motion history at an explicitly published placement, including
|
|
240
|
+
* static proxies. The next refresh can still sweep any subsequent motion.
|
|
241
|
+
* @param {number} handle
|
|
242
|
+
* @param {Transform64} transform
|
|
243
|
+
* @private
|
|
244
|
+
*/
|
|
245
|
+
__place(handle, transform) {
|
|
246
|
+
this.index.placePose(
|
|
247
|
+
handle,
|
|
248
|
+
transform[TRANSFORM64_TRANSLATION_OFFSET],
|
|
249
|
+
transform[TRANSFORM64_TRANSLATION_OFFSET + 1],
|
|
250
|
+
transform[TRANSFORM64_TRANSLATION_OFFSET + 2],
|
|
251
|
+
transform[TRANSFORM64_ROTATION_OFFSET],
|
|
252
|
+
transform[TRANSFORM64_ROTATION_OFFSET + 1],
|
|
253
|
+
transform[TRANSFORM64_ROTATION_OFFSET + 2],
|
|
254
|
+
transform[TRANSFORM64_ROTATION_OFFSET + 3]
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
236
258
|
/**
|
|
237
259
|
* @param {number} entity
|
|
238
260
|
* @returns {number} the index handle, or `undefined` if the entity is not indexed
|