12 using namespace bicameral::physics;
13 using namespace bicameral::fx;
16 return value == 0 ? 0 : FxMsbU64(FxAbsU64(value)) + 1;
25 body.massOverH2 = PxMassOverStepSquared(source.
massMilligrams, rate);
27 const PxVec3 h = body.halfExtent;
28 body.inertiaOverH2 = PxMakeVec3(PxBoxInertiaOverStepSquared(body.massMilligrams, h.y, h.z, rate),
29 PxBoxInertiaOverStepSquared(body.massMilligrams, h.x, h.z, rate),
30 PxBoxInertiaOverStepSquared(body.massMilligrams, h.x, h.y, rate));
31 body.boundingRadius = (int64_t)PxLength(h);
35 body.rotation = PxQuatNormalize(
37 body.color = PX_NO_COLOR;
68 for (uint32_t iteration = 0; iteration <= iterations; ++iteration) {
72 const int64_t alphaQ16 = iteration < iterations ? PX_ALPHA_ONE_Q16 : 0;
76 if (iteration < iterations)
79 if (iteration + 1 == iterations)
88 body.active = PxIsActiveAt(body,
m_tick);
94 const auto count = (uint32_t)
m_bodies.size();
95 for (uint32_t a = 0; a < count; ++a) {
96 for (uint32_t b = a + 1; b < count; ++b) {
103 const PxContactGeometry geometry = PxCollideBoxes(PxShapeOf(bodyA), PxShapeOf(bodyB), margin);
104 if (geometry.count == 0)
111 m_stats.maxPenetration = std::max(
m_stats.maxPenetration, PxMaxPenetration(geometry));
112 m_stats.contactCount += manifold.count;
113 next.emplace(std::pair{a, b}, manifold);
131 std::vector<uint64_t> touchingMass(
m_bodies.size());
132 for (uint32_t i = 0; i <
m_bodies.size(); ++i)
133 touchingMass[i] = PxTouchMass(
m_bodies[i]);
136 touchingMass[manifold.bodyA] = std::max(touchingMass[manifold.bodyA],
137 PxTouchMass(
m_bodies[manifold.bodyB]));
138 touchingMass[manifold.bodyB] = std::max(touchingMass[manifold.bodyB],
139 PxTouchMass(
m_bodies[manifold.bodyA]));
143 const uint64_t mass = std::max(touchingMass[manifold.bodyA], touchingMass[manifold.bodyB]);
150 manifold = PxWarmStartManifold(manifold,
m_parameters.gammaQ16);
155 body = PxInitializeBody(body,
m_rate);
160 manifold = PxLinearizeManifold(manifold,
m_bodies[manifold.bodyA],
m_bodies[manifold.bodyB]);
173 for (uint32_t i : chosen)
185 std::vector<std::vector<uint32_t>> neighbors(
m_bodies.size());
187 if (!PxIsDynamic(
m_bodies[manifold.bodyA]) || !PxIsDynamic(
m_bodies[manifold.bodyB]))
190 neighbors[manifold.bodyA].push_back(manifold.bodyB);
191 neighbors[manifold.bodyB].push_back(manifold.bodyA);
199 std::vector<uint32_t> chosen;
200 for (uint32_t i = 0; i <
m_bodies.size(); ++i) {
202 if (!PxIsDynamic(body) || body.active == 0 || body.color >= 0)
205 const auto isBelow = [&](uint32_t j) {
206 return m_bodies[j].color >= 0 || PxColorPriorityBelow(j, i);
208 if (std::ranges::all_of(neighbors[i], isBelow))
218 while (std::ranges::any_of(neighbors, [&](uint32_t j) {
return m_bodies[j].color == color; }))
228 const uint32_t before = manifold.count;
230 m_stats.contactCount += manifold.count - before;
236 for (uint32_t i = 0; i <
m_bodies.size(); ++i) {
244 PxBodySystem system = PxBeginSystemOf(body);
248 for (uint32_t k = 0; k < manifold->count; ++k) {
249 system = PxAddPointRows(system, manifold->points[k], manifold->frictionQ16, isA, alphaQ16,
250 m_parameters.gapSlop, a.deltaLinear, a.deltaAngular, b.deltaLinear,
256 const PxSolveResult solved = PxSolveSymmetric6(system.lhs, system.rhs, PX_SOLVE_GAIN_SHIFT);
258 m_stats.solveFailures += solved.ok ? 0 : 1;
260 body = PxApplySolution(body, solved.x);
261 for (uint32_t i = 0; i < 3; ++i) {
262 m_stats.deltaBits = std::max(
m_stats.deltaBits, BitsOf(PxGet(body.deltaLinear, i)));
263 m_stats.deltaBits = std::max(
m_stats.deltaBits, BitsOf(PxGet(body.deltaAngular, i)));
268 for (int64_t value : system.lhs.m)
271 for (int64_t value : system.rhs.v)
279 for (uint32_t k = 0; k < manifold.count; ++k) {
281 contactPoint = PxUpdatePointDuals(contactPoint, manifold.frictionQ16, manifold.beta,
282 manifold.maxPenalty, alphaQ16,
m_parameters, a.deltaLinear,
283 a.deltaAngular, b.deltaLinear, b.deltaAngular);
290 for (
const PxRow& row : contactPoint.rows) {
291 m_stats.penaltyBits = std::max(
m_stats.penaltyBits, BitsOf(row.penalty));
292 m_stats.lambdaBits = std::max(
m_stats.lambdaBits, BitsOf(row.lambda));
298 body = PxUpdateVelocity(body,
m_rate);
303 body = PxFinishBody(body);
307 uint32_t
PhysicsWorld::Push(
const PxVec3& origin,
const PxVec3& direction, uint32_t impulseMillinewtonSeconds) {
308 int64_t best = PX_RAY_MISS;
309 uint32_t hit = UINT32_MAX;
310 for (uint32_t index = 0; index <
m_bodies.size(); ++index) {
311 const int64_t distance = PxRayEntryDistance(
m_bodies[index], origin, direction);
312 if (PxRayHitCloser(distance, best)) {
318 if (hit == UINT32_MAX || !PxIsDynamic(
m_bodies[hit]))
322 const PxVec3 offset = PxSub(PxRayPoint(origin, direction, best), body.position);
323 body = PxApplyImpulse(body, offset, PxPushImpulse(direction, impulseMillinewtonSeconds),
m_rate);
329 uint64_t hash = FxMix64(
m_tick);
331 hash = PxHashBody(hash, body);
std::vector< uint32_t > ChooseLocalMaxima(const std::vector< std::vector< uint32_t > > &neighbors) const
void UpdateDuals(int64_t alphaQ16)
std::vector< std::vector< uint32_t > > DynamicNeighbors() const
void SolveBody(uint32_t index, int64_t alphaQ16)
void AssignSmallestColor(uint32_t index, const std::vector< uint32_t > &neighbors)
uint64_t StateHash() const
uint32_t Push(const physics::PxVec3 &origin, const physics::PxVec3 &direction, uint32_t impulseMillinewtonSeconds)
void SolveColor(int32_t color, int64_t alphaQ16)
PhysicsWorld(const PhysicsScene &scene, const physics::PxParameters ¶meters)
void RecordPointBits(const PhysicsContactPoint &point)
physics::PxParameters m_parameters
std::map< std::pair< uint32_t, uint32_t >, PhysicsManifold > m_manifolds
void RecordSystemBits(const physics::PxBodySystem &system)
std::vector< std::vector< std::pair< const PhysicsManifold *, bool > > > m_bodyManifolds
std::vector< PhysicsBody > m_bodies
uint32_t BitsOf(int64_t value)
physics::PxContactPoint PhysicsContactPoint
PhysicsBody MakePhysicsBody(const PhysicsSceneBody &source, int64_t rate)
physics::PxManifold PhysicsManifold
physics::PxBody PhysicsBody
std::array< int64_t, 3 > halfExtent
std::array< int64_t, 3 > position
std::array< int32_t, 4 > rotation
std::vector< PhysicsSceneBody > bodies