babylon-box3d 0.7.0 → 0.8.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/README.md +29 -4
- package/dist/box3dPlugin.d.ts +22 -0
- package/dist/box3dPlugin.d.ts.map +1 -1
- package/dist/box3dPlugin.js +33 -2
- package/dist/box3dPlugin.js.map +1 -1
- package/lib/esm/box3d.d.ts +8 -0
- package/lib/esm/box3d.js +2 -2
- package/lib/esm/box3d.wasm +0 -0
- package/lib/esm-f64/box3d.d.ts +8 -0
- package/lib/esm-f64/box3d.js +2 -2
- package/lib/esm-f64/box3d.wasm +0 -0
- package/lib/esm-f64-threads/box3d.d.ts +8 -0
- package/lib/esm-f64-threads/box3d.js +2 -2
- package/lib/esm-f64-threads/box3d.wasm +0 -0
- package/lib/esm-threads/box3d.d.ts +8 -0
- package/lib/esm-threads/box3d.js +2 -2
- package/lib/esm-threads/box3d.wasm +0 -0
- package/lib/node/box3d.d.ts +8 -0
- package/lib/node/box3d.mjs +2 -2
- package/lib/node/box3d.wasm +0 -0
- package/lib/node-f64/box3d.d.ts +8 -0
- package/lib/node-f64/box3d.mjs +2 -2
- package/lib/node-f64/box3d.wasm +0 -0
- package/lib/node-f64-threads/box3d.d.ts +8 -0
- package/lib/node-f64-threads/box3d.mjs +2 -2
- package/lib/node-f64-threads/box3d.wasm +0 -0
- package/lib/node-threads/box3d.d.ts +8 -0
- package/lib/node-threads/box3d.mjs +2 -2
- package/lib/node-threads/box3d.wasm +0 -0
- package/lib/umd/box3d.umd.js +2 -2
- package/lib/umd/box3d.umd.wasm +0 -0
- package/package.json +1 -1
- package/umd/babylon.box3d.js +47 -1
- package/umd/babylon.box3d.js.map +3 -3
- package/umd/babylon.box3d.min.js +2 -2
- package/umd/babylon.box3d.min.js.map +4 -4
- package/wasm/box3d_shim.c +136 -0
package/wasm/box3d_shim.c
CHANGED
|
@@ -157,6 +157,12 @@ typedef struct bxBody
|
|
|
157
157
|
// The body's feature key: each of its shapes gets (featureKey << BX_FEATURE_INDEX_BITS) | its index in the body as
|
|
158
158
|
// Box3D's b3ShapeDef::featureKey, which orders new contacts, continuous collision and cast ties. 0 until it is set.
|
|
159
159
|
uint64_t featureKey;
|
|
160
|
+
// A clip plane (wasm/patches/0006): contact points on its positive side, where n.p + d > 0 like Babylon's clip
|
|
161
|
+
// planes, or within twice the linear slop of it, are dropped from this body's contacts with shapes whose category
|
|
162
|
+
// bits meet clipMask. Off while clipEnabled is 0.
|
|
163
|
+
int clipEnabled;
|
|
164
|
+
double clipPlane[4];
|
|
165
|
+
uint64_t clipMask;
|
|
160
166
|
} bxBody;
|
|
161
167
|
|
|
162
168
|
#define BX_FEATURE_INDEX_BITS 20
|
|
@@ -603,6 +609,129 @@ static void bxResetTasks( void )
|
|
|
603
609
|
// World
|
|
604
610
|
// ---------------------------------------------------------------------------------------------
|
|
605
611
|
|
|
612
|
+
// ---------------------------------------------------------------------------------------------
|
|
613
|
+
// Clip planes (wasm/patches/0006)
|
|
614
|
+
// ---------------------------------------------------------------------------------------------
|
|
615
|
+
|
|
616
|
+
// Called from Box3D's workers during a step: only reads.
|
|
617
|
+
static const bxBody* bxClipBody( b3ShapeId shapeId, b3ShapeId otherId )
|
|
618
|
+
{
|
|
619
|
+
int slot = (int)(intptr_t)b3Body_GetUserData( b3Shape_GetBody( shapeId ) );
|
|
620
|
+
const bxBody* body = s_bodies + slot;
|
|
621
|
+
if ( slot <= 0 || slot >= s_bodyCount || body->clipEnabled == 0 )
|
|
622
|
+
{
|
|
623
|
+
return NULL;
|
|
624
|
+
}
|
|
625
|
+
return ( b3Shape_GetFilter( otherId ).categoryBits & body->clipMask ) != 0 ? body : NULL;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
static int bxIsClipped( const bxBody* body, b3Pos point )
|
|
629
|
+
{
|
|
630
|
+
if ( body == NULL )
|
|
631
|
+
{
|
|
632
|
+
return 0;
|
|
633
|
+
}
|
|
634
|
+
// A surface lying in the plane, such as the wall a portal is on, is clipped too: points within twice the linear
|
|
635
|
+
// slop in front of the plane count as past it, which covers a resting contact's point between the surfaces and the
|
|
636
|
+
// 5 mm skin mesh and height field contacts carry.
|
|
637
|
+
const double* n = body->clipPlane;
|
|
638
|
+
return n[0] * point.x + n[1] * point.y + n[2] * point.z + n[3] > -2.0 * B3_LINEAR_SLOP;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// Drops the points either body's clip plane clips; Box3D drops the manifolds left empty.
|
|
642
|
+
static int bxClipManifolds( b3ShapeId shapeIdA, b3ShapeId shapeIdB, b3Pos originA, b3Manifold* manifolds, int manifoldCount,
|
|
643
|
+
void* context )
|
|
644
|
+
{
|
|
645
|
+
(void)context;
|
|
646
|
+
const bxBody* a = bxClipBody( shapeIdA, shapeIdB );
|
|
647
|
+
const bxBody* b = bxClipBody( shapeIdB, shapeIdA );
|
|
648
|
+
if ( a == NULL && b == NULL )
|
|
649
|
+
{
|
|
650
|
+
return manifoldCount;
|
|
651
|
+
}
|
|
652
|
+
for ( int i = 0; i < manifoldCount; ++i )
|
|
653
|
+
{
|
|
654
|
+
b3Manifold* manifold = manifolds + i;
|
|
655
|
+
int kept = 0;
|
|
656
|
+
for ( int j = 0; j < manifold->pointCount; ++j )
|
|
657
|
+
{
|
|
658
|
+
// A speculative point is made while the surfaces are still apart, by up to the distance the body covers in
|
|
659
|
+
// the step against a mesh, and it lies midway between them (convex shapes) or on shape B (meshes and height
|
|
660
|
+
// fields). Either way it can sit in front of the plane while the surface it would push on lies in it, and a
|
|
661
|
+
// body falling into a portal would stop dead on the surface the portal is on. So each body also tests the
|
|
662
|
+
// point moved one separation toward the other shape, along the normal, which points from A to B: on or past
|
|
663
|
+
// that shape's surface.
|
|
664
|
+
const b3ManifoldPoint* mp = manifold->points + j;
|
|
665
|
+
b3Pos point = b3OffsetPos( originA, mp->anchorA );
|
|
666
|
+
b3Vec3 gap = b3MulSV( mp->separation, manifold->normal );
|
|
667
|
+
int clipped = bxIsClipped( a, point ) || bxIsClipped( a, b3OffsetPos( point, gap ) ) || bxIsClipped( b, point ) ||
|
|
668
|
+
bxIsClipped( b, b3OffsetPos( point, b3Neg( gap ) ) );
|
|
669
|
+
if ( clipped == 0 )
|
|
670
|
+
{
|
|
671
|
+
manifold->points[kept] = manifold->points[j];
|
|
672
|
+
kept += 1;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
manifold->pointCount = kept;
|
|
676
|
+
}
|
|
677
|
+
return manifoldCount;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// Continuous collision has only its time of impact point.
|
|
681
|
+
static bool bxClipPreSolve( b3ShapeId shapeIdA, b3ShapeId shapeIdB, b3Pos point, b3Vec3 normal, void* context )
|
|
682
|
+
{
|
|
683
|
+
(void)normal;
|
|
684
|
+
(void)context;
|
|
685
|
+
return bxIsClipped( bxClipBody( shapeIdA, shapeIdB ), point ) == 0 && bxIsClipped( bxClipBody( shapeIdB, shapeIdA ), point ) == 0;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/// Clips the body's contacts with a plane, see bxBody::clipPlane; enabled 0 removes it. The plane is normalized, so
|
|
689
|
+
/// its normal need not be unit length. Wakes the body so its contacts are made again.
|
|
690
|
+
BX_EXPORT void bx_Body_SetClipPlane( int slot, int enabled, double nx, double ny, double nz, double d, unsigned int mask )
|
|
691
|
+
{
|
|
692
|
+
bxBody* body = bxGetBody( slot );
|
|
693
|
+
if ( body == NULL || b3Body_IsValid( body->id ) == false )
|
|
694
|
+
{
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
double length = sqrt( nx * nx + ny * ny + nz * nz );
|
|
698
|
+
body->clipEnabled = enabled != 0 && length > 0.0;
|
|
699
|
+
length = length > 0.0 ? length : 1.0;
|
|
700
|
+
body->clipPlane[0] = nx / length;
|
|
701
|
+
body->clipPlane[1] = ny / length;
|
|
702
|
+
body->clipPlane[2] = nz / length;
|
|
703
|
+
body->clipPlane[3] = d / length;
|
|
704
|
+
body->clipMask = (uint64_t)mask;
|
|
705
|
+
for ( int i = 0; i < body->shapeCount; ++i )
|
|
706
|
+
{
|
|
707
|
+
if ( b3Shape_IsValid( body->shapes[i] ) )
|
|
708
|
+
{
|
|
709
|
+
b3Shape_EnablePreSolveEvents( body->shapes[i], body->clipEnabled != 0 );
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
if ( b3Body_GetType( body->id ) != b3_staticBody )
|
|
713
|
+
{
|
|
714
|
+
b3Body_SetAwake( body->id, true );
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
/// scratchF64: [enabled, nx, ny, nz, d, mask]
|
|
719
|
+
BX_EXPORT void bx_Body_GetClipPlane( int slot )
|
|
720
|
+
{
|
|
721
|
+
memset( s_scratchF64, 0, 6 * sizeof( double ) );
|
|
722
|
+
bxBody* body = bxGetBody( slot );
|
|
723
|
+
if ( body == NULL || b3Body_IsValid( body->id ) == false )
|
|
724
|
+
{
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
s_scratchF64[0] = body->clipEnabled;
|
|
728
|
+
for ( int i = 0; i < 4; ++i )
|
|
729
|
+
{
|
|
730
|
+
s_scratchF64[1 + i] = body->clipPlane[i];
|
|
731
|
+
}
|
|
732
|
+
s_scratchF64[5] = (double)( body->clipMask & 0xffffffffu );
|
|
733
|
+
}
|
|
734
|
+
|
|
606
735
|
BX_EXPORT int bx_GetMaxWorkers( void )
|
|
607
736
|
{
|
|
608
737
|
return BX_MAX_WORKERS;
|
|
@@ -639,6 +768,9 @@ BX_EXPORT int bx_CreateWorld( float gx, float gy, float gz, int workerCount )
|
|
|
639
768
|
}
|
|
640
769
|
#endif
|
|
641
770
|
s_worlds[i] = b3CreateWorld( &def );
|
|
771
|
+
// both only run for shapes with pre-solve events, which only clip planes turn on
|
|
772
|
+
b3World_SetManifoldCallback( s_worlds[i], bxClipManifolds, NULL );
|
|
773
|
+
b3World_SetPreSolveCallback( s_worlds[i], bxClipPreSolve, NULL );
|
|
642
774
|
return i + 1;
|
|
643
775
|
}
|
|
644
776
|
}
|
|
@@ -2394,6 +2526,10 @@ static void bxBodyPushShape( bxBody* body, b3ShapeId shapeId, int descSlot, int
|
|
|
2394
2526
|
body->shapeDescs[body->shapeCount] = descSlot;
|
|
2395
2527
|
body->geomDescs[body->shapeCount] = geomSlot;
|
|
2396
2528
|
body->shapeCount += 1;
|
|
2529
|
+
if ( body->clipEnabled )
|
|
2530
|
+
{
|
|
2531
|
+
b3Shape_EnablePreSolveEvents( shapeId, true );
|
|
2532
|
+
}
|
|
2397
2533
|
bxShapeDesc* geom = bxGetDesc( geomSlot );
|
|
2398
2534
|
if ( geom != NULL && ( geom->kind == bx_meshDesc || geom->kind == bx_heightFieldDesc ) )
|
|
2399
2535
|
{
|