mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-04 20:57:49 +00:00
381 lines
11 KiB
C++
381 lines
11 KiB
C++
#pragma once
|
|
|
|
#include "v8kernel/Body.h"
|
|
#include "V8Kernel/SimBody.h"
|
|
#include "V8Kernel/Point.h"
|
|
#include "V8Kernel/Connector.h"
|
|
#include "V8Kernel/ContactConnector.h"
|
|
#include "V8Kernel/BuoyancyConnector.h"
|
|
#include "V8kernel/Constants.h"
|
|
#include "V8datamodel/FastLogSettings.h"
|
|
|
|
|
|
namespace RBX {
|
|
|
|
class KernelData {
|
|
public:
|
|
// main object types
|
|
IndexArray<SimBody, &SimBody::getFreeFallBodyIndex> freeFallBodies; // bodies with no connectors
|
|
IndexArray<SimBody, &SimBody::getRealTimeBodyIndex> realTimeBodies; // humanoid bodies that are not throttle-able
|
|
IndexArray<SimBody, &SimBody::getJointBodyIndex> jointBodies; // bodies with joint connectors
|
|
IndexArray<SimBody, &SimBody::getContactBodyIndex> contactBodies; // bodies with contact connectors but no joint connectors
|
|
IndexArray<Body, &Body::getLeafBodyIndex> leafBodies; // need update PV every step, NOT in kernel!
|
|
IndexArray<Point, &Point::getKernelIndex> points;
|
|
IndexArray<Connector, &Connector::getHumanoidIndex> humanoidConnectors; // The humanoids
|
|
IndexArray<Connector, &Connector::getSecondPassIndex> secondPassConnectors; // kernel joints
|
|
IndexArray<Connector, &Connector::getRealTimeIndex> realTimeConnectors; // connectors on humanoid body parts
|
|
IndexArray<Connector, &Connector::getJointIndex> jointConnectors;
|
|
IndexArray<Connector, &Connector::getBuoyancyIndex> buoyancyConnectors;
|
|
IndexArray<Connector, &Connector::getContactIndex> contactConnectors;
|
|
|
|
KernelData()
|
|
{
|
|
}
|
|
|
|
~KernelData() {
|
|
RBXASSERT(freeFallBodies.size() == 0);
|
|
RBXASSERT(realTimeBodies.size() == 0);
|
|
RBXASSERT(jointBodies.size() == 0);
|
|
RBXASSERT(contactBodies.size() == 0);
|
|
RBXASSERT(leafBodies.size() == 0);
|
|
RBXASSERT(points.size() == 0);
|
|
RBXASSERT(humanoidConnectors.size() == 0);
|
|
RBXASSERT(secondPassConnectors.size() == 0);
|
|
RBXASSERT(realTimeConnectors.size() == 0);
|
|
RBXASSERT(jointConnectors.size() == 0);
|
|
RBXASSERT(buoyancyConnectors.size() == 0);
|
|
RBXASSERT(contactConnectors.size() == 0);
|
|
}
|
|
|
|
inline void addLeafBodies(Body* b)
|
|
{
|
|
for (int i = 0; i < b->numChildren(); ++i)
|
|
{
|
|
Body* child = b->getChild(i);
|
|
RBXASSERT(!child->isLeafBody());
|
|
RBXASSERT(child != child->getRoot());
|
|
if (child->connectorUseCount > 0)
|
|
{
|
|
addLeafBody(child);
|
|
}
|
|
addLeafBodies(child);
|
|
}
|
|
}
|
|
|
|
inline void insertBody(Body* b)
|
|
{
|
|
RBXASSERT(b->getRoot() == b);
|
|
SimBody* simBody = b->getSimBody();
|
|
RBXASSERT(!b->isLeafBody() && !simBody->isInKernel());
|
|
addBodyToNewList(simBody);
|
|
RBXASSERT(simBody->validateBodyLists());
|
|
}
|
|
|
|
inline void removeBody(Body* b)
|
|
{
|
|
RBXASSERT(b->getRoot() == b);
|
|
RBXASSERT(!b->isLeafBody());
|
|
|
|
SimBody* simBody = b->getSimBody();
|
|
removeBodyFromCurrentList(simBody);
|
|
simBody->clearSymStateAndAccummulator();
|
|
RBXASSERT(simBody->validateBodyLists());
|
|
}
|
|
|
|
inline void addConnector(Connector* c, bool pgsOn)
|
|
{
|
|
RBXASSERT(!c->isInKernel());
|
|
Body* body0 = c->getBody(Connector::body0);
|
|
Body* body1 = c->getBody(Connector::body1);
|
|
SimBody* simBody0 = body0 ? body0->getRootSimBody() : NULL;
|
|
SimBody* simBody1 = body1 ? body1->getRootSimBody() : NULL;
|
|
|
|
Connector::KernelType connectorType = c->getConnectorKernelType();
|
|
if ((simBody0 == NULL || !simBody0->isInKernel()) &&
|
|
(simBody1 == NULL || !simBody1->isInKernel()) &&
|
|
connectorType != Connector::HUMANOID &&
|
|
connectorType != Connector::JOINT &&
|
|
connectorType != Connector::KERNEL_JOINT)
|
|
return;
|
|
|
|
if (connectorType == Connector::HUMANOID)
|
|
{
|
|
humanoidConnectors.fastAppend(c);
|
|
if (simBody0)
|
|
simBody0->incrementHumanoidConnectorCount();
|
|
if (simBody1)
|
|
simBody1->incrementHumanoidConnectorCount();
|
|
}
|
|
else if (connectorType == Connector::KERNEL_JOINT)
|
|
{
|
|
secondPassConnectors.fastAppend(c);
|
|
if (simBody0)
|
|
simBody0->incrementSecondPassConnectorCount();
|
|
if (simBody1)
|
|
simBody1->incrementSecondPassConnectorCount();
|
|
}
|
|
else if (pgsOn && connectorType == Connector::JOINT)
|
|
{
|
|
jointConnectors.fastAppend(c);
|
|
if (simBody0)
|
|
simBody0->incrementJointConnetorCount();
|
|
if (simBody1)
|
|
simBody1->incrementJointConnetorCount();
|
|
}
|
|
else if (pgsOn && connectorType == Connector::BUOYANCY)
|
|
{
|
|
buoyancyConnectors.fastAppend(c);
|
|
if (simBody0)
|
|
simBody0->incrementBuoyancyConnectorCount();
|
|
if (simBody1)
|
|
simBody1->incrementBuoyancyConnectorCount();
|
|
}
|
|
else if ((simBody0 && !simBody0->getBody()->getCanThrottle()) ||
|
|
(simBody1 && !simBody1->getBody()->getCanThrottle()))
|
|
{
|
|
realTimeConnectors.fastAppend(c);
|
|
if (simBody0)
|
|
simBody0->incrementRealTimeConnectorCount();
|
|
if (simBody1)
|
|
simBody1->incrementRealTimeConnectorCount();
|
|
}
|
|
else if (!pgsOn &&
|
|
(connectorType == Connector::JOINT ||
|
|
connectorType == Connector::BUOYANCY ||
|
|
((simBody0 && simBody0->isJointBody()) || // Contact connectors in touch with joint bodies
|
|
(simBody1 && simBody1->isJointBody())))) // are considered joint connectors.
|
|
{
|
|
jointConnectors.fastAppend(c);
|
|
if (simBody0)
|
|
simBody0->incrementJointConnetorCount();
|
|
if (simBody1)
|
|
simBody1->incrementJointConnetorCount();
|
|
}
|
|
else
|
|
{
|
|
RBXASSERT(connectorType == Connector::CONTACT);
|
|
contactConnectors.fastAppend(c);
|
|
if (simBody0)
|
|
simBody0->incrementContactConnectorCount();
|
|
if (simBody1)
|
|
simBody1->incrementContactConnectorCount();
|
|
}
|
|
|
|
if (body0)
|
|
addConnectorToBody(c, body0);
|
|
if (body1)
|
|
addConnectorToBody(c, body1);
|
|
|
|
RBXASSERT(simBody0 == NULL || simBody0->validateBodyLists());
|
|
RBXASSERT(simBody1 == NULL || simBody1->validateBodyLists());
|
|
}
|
|
|
|
inline void removeConnector(Connector* c)
|
|
{
|
|
if (!c->isInKernel())
|
|
return;
|
|
|
|
Body* body0 = c->getBody(Connector::body0);
|
|
Body* body1 = c->getBody(Connector::body1);
|
|
SimBody* simBody0 = body0 ? body0->getRootSimBody() : NULL;
|
|
SimBody* simBody1 = body1 ? body1->getRootSimBody() : NULL;
|
|
|
|
if (c->isHumanoid())
|
|
{
|
|
humanoidConnectors.fastRemove(c);
|
|
if (simBody0)
|
|
simBody0->decrementHumanoidConnectorCount();
|
|
if (simBody1)
|
|
simBody1->decrementHumanoidConnectorCount();
|
|
}
|
|
else if (c->isSecondPass())
|
|
{
|
|
secondPassConnectors.fastRemove(c);
|
|
if (simBody0)
|
|
simBody0->decrementSecondPassConnectorCount();
|
|
if (simBody1)
|
|
simBody1->decrementSecondPassConnectorCount();
|
|
}
|
|
else if (c->isRealTime())
|
|
{
|
|
realTimeConnectors.fastRemove(c);
|
|
if (simBody0)
|
|
simBody0->decrementRealTimeConnectorCount();
|
|
if (simBody1)
|
|
simBody1->decrementRealTimeConnectorCount();
|
|
}
|
|
else if (c->isJoint())
|
|
{
|
|
jointConnectors.fastRemove(c);
|
|
if (simBody0)
|
|
simBody0->decrementJointConnetorCount();
|
|
if (simBody1)
|
|
simBody1->decrementJointConnetorCount();
|
|
}
|
|
else if (c->isBuoyancy())
|
|
{
|
|
buoyancyConnectors.fastRemove(c);
|
|
if (simBody0)
|
|
simBody0->decrementBuoyancyConnectorCount();
|
|
if (simBody1)
|
|
simBody1->decrementBuoyancyConnectorCount();
|
|
}
|
|
else
|
|
{
|
|
RBXASSERT(c->isContact());
|
|
contactConnectors.fastRemove(c);
|
|
if (simBody0)
|
|
simBody0->decrementContactConnectorCount();
|
|
if (simBody1)
|
|
simBody1->decrementContactConnectorCount();
|
|
|
|
ContactConnector* conn = static_cast<ContactConnector*>(c);
|
|
PairParams params = conn->getContactPoint();
|
|
if (conn->getReordedSimBody(simBody0, simBody1, params))
|
|
conn->applyContactPointForSymmetryDetection(simBody0, simBody1, params, -1.0f);
|
|
}
|
|
|
|
if (body0)
|
|
removeConnectorFromBody(c, body0);
|
|
if (body1)
|
|
removeConnectorFromBody(c, body1);
|
|
|
|
RBXASSERT(simBody0 == NULL || simBody0->validateBodyLists());
|
|
RBXASSERT(simBody1 == NULL || simBody1->validateBodyLists());
|
|
}
|
|
|
|
private:
|
|
|
|
inline void addLeafBody(Body* b)
|
|
{
|
|
RBXASSERT(!b->isLeafBody());
|
|
RBXASSERT(b->connectorUseCount > 0);
|
|
leafBodies.fastAppend(b);
|
|
RBXASSERT(b->isLeafBody());
|
|
}
|
|
|
|
inline void removeLeafBody(Body* b)
|
|
{
|
|
RBXASSERT(b->isLeafBody());
|
|
leafBodies.fastRemove(b);
|
|
RBXASSERT(!b->isLeafBody());
|
|
}
|
|
|
|
inline void removeLeafBodies(Body* b)
|
|
{
|
|
for (int i = 0; i < b->numChildren(); ++i)
|
|
{
|
|
Body* child = b->getChild(i);
|
|
if (child->isLeafBody())
|
|
{
|
|
removeLeafBody(child);
|
|
}
|
|
removeLeafBodies(child);
|
|
}
|
|
}
|
|
|
|
inline void removeBodyFromCurrentList(SimBody* simBody)
|
|
{
|
|
if (simBody->isRealTimeBody())
|
|
{
|
|
removeLeafBodies(simBody->getBody());
|
|
realTimeBodies.fastRemove(simBody);
|
|
} else if (simBody->isJointBody())
|
|
{
|
|
removeLeafBodies(simBody->getBody());
|
|
jointBodies.fastRemove(simBody);
|
|
} else if (simBody->isContactBody())
|
|
{
|
|
contactBodies.fastRemove(simBody);
|
|
} else if (simBody->isFreeFallBody())
|
|
{
|
|
freeFallBodies.fastRemove(simBody);
|
|
simBody->updateAngMomentum();
|
|
} else
|
|
return;
|
|
simBody->setDt(0.0f);
|
|
}
|
|
|
|
inline void addBodyToNewList(SimBody* simBody)
|
|
{
|
|
if (!simBody->getBody()->getCanThrottle())
|
|
{
|
|
if (!simBody->isRealTimeBody())
|
|
{
|
|
removeBodyFromCurrentList(simBody);
|
|
realTimeBodies.fastAppend(simBody);
|
|
simBody->setDt(Constants::kernelDt());
|
|
addLeafBodies(simBody->getBody());
|
|
}
|
|
} else if (simBody->getJointConnectorCount() > 0)
|
|
{
|
|
if (!simBody->isJointBody())
|
|
{
|
|
removeBodyFromCurrentList(simBody);
|
|
jointBodies.fastAppend(simBody);
|
|
simBody->setDt(Constants::kernelDt());
|
|
addLeafBodies(simBody->getBody());
|
|
}
|
|
} else if (simBody->getContactConnectorCount() > 0)
|
|
{
|
|
if (!simBody->isContactBody())
|
|
{
|
|
removeBodyFromCurrentList(simBody);
|
|
contactBodies.fastAppend(simBody);
|
|
simBody->setDt(Constants::freeFallDt());
|
|
}
|
|
} else
|
|
{
|
|
if (simBody->getConnectorCount() == 0)
|
|
{
|
|
if (!simBody->isFreeFallBody())
|
|
{
|
|
removeBodyFromCurrentList(simBody);
|
|
freeFallBodies.fastAppend(simBody);
|
|
simBody->setDt(Constants::freeFallDt());
|
|
simBody->clearSymStateAndAccummulator();
|
|
}
|
|
} else
|
|
{
|
|
if (!simBody->isJointBody())
|
|
{
|
|
removeBodyFromCurrentList(simBody);
|
|
jointBodies.fastAppend(simBody);
|
|
simBody->setDt(Constants::kernelDt());
|
|
addLeafBodies(simBody->getBody());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
inline void addConnectorToBody(Connector* c, Body* body)
|
|
{
|
|
body->connectorUseCount++;
|
|
SimBody* simBody = body->getRootSimBody();
|
|
|
|
if (!simBody->isInKernel())
|
|
return;
|
|
addBodyToNewList(simBody);
|
|
|
|
// adds leaf bodies if root is already here and it is subject to the spring solver
|
|
if (body != body->getRoot() && !body->isLeafBody() &&
|
|
(simBody->isJointBody() || simBody->isRealTimeBody()))
|
|
addLeafBody(body);
|
|
}
|
|
|
|
inline void removeConnectorFromBody(Connector* c, Body* body)
|
|
{
|
|
body->connectorUseCount--;
|
|
|
|
if (body->isLeafBody() && body->connectorUseCount == 0)
|
|
removeLeafBody(body);
|
|
|
|
SimBody* simBody = body->getRootSimBody();
|
|
if (!simBody->isInKernel())
|
|
return;
|
|
addBodyToNewList(simBody);
|
|
}
|
|
};
|
|
|
|
} // namespace
|