1 #ifndef CSCPHYSICSSIMULATOR_H
2 #define CSCPHYSICSSIMULATOR_H
32 #define FORCE_MEMBER_VALUES_DEFAULT_MAX_ITERATION_NUMBER 1000
33 #define FORCE_MEMBER_VALUES_DEFAULT_MAX_LOOP_DURATION_MILLIS 50
34 using std::runtime_error, std::recursive_mutex, std::vector, std::string, std::runtime_error, std::function, std::optional, std::thread, std::isnan;
39 #pragma region forwardDefs
40 class btTypedConstraint;
41 class btHingeConstraint;
42 class btSliderConstraint;
44 class btBroadphaseInterface;
45 class btCollisionDispatcher;
46 class btDiscreteDynamicsWorld;
48 class btDefaultCollisionConfiguration;
49 class btSequentialImpulseConstraintSolver;
50 class btFixedConstraint;
51 class btCollisionShape;
53 #pragma endregion forwardDefs
57 #define BIT(x) (1 << (x))
86 double rotationQuaternion[4];
95 const double *
const getRotationQuaternionArray()
const;
98 const CscPoint3d *getRotationEulerAsPoint()
const;
103 const unsigned long long id;
115 objectiveValue(objectiveValue),
139 bulletConstraint(bulletConstraint),
140 limitMin(pivot->initialLimitMin),
141 limitMax(pivot->initialLimitMax),
142 rotationX(pivot->axeRotationX),
143 rotationY(pivot->axeRotationY),
144 rotationZ(pivot->axeRotationZ),
145 softness(pivot->softness),
147 relaxation(pivot->relaxation),
148 isMotorDisabled(pivot->free),
149 percentSpeedMax(pivot->percentSpeedMax),
150 maxImpulse(pivot->maxImpulse),
151 speedToReachTarget(pivot->speedMax * pivot->percentSpeedMax / 100.0
f) {
155 return bulletConstraint;
163 bulletConstraint(bulletConstraint) {
167 return bulletConstraint;
175 bulletConstraint(bulletConstraint) {
179 return bulletConstraint;
187 bulletConstraint(bulletConstraint) {
191 return bulletConstraint;
198 unsigned long long nanCountsPosition = 0;
199 unsigned long long nanCountsRotation = 0;
200 unsigned long long nanCountsAcceleration = 0;
205 btCollisionShape *getShape()
const;
207 void updatePosition(
double x,
double y,
double z);
208 void updateRotationEuler(
double x,
double y,
double z);
209 void updateAcceleration(
double x,
double y,
double z);
210 void updateRotationQuaternion(
double w,
double x,
double y,
double z);
221 float localGravity = -9.81;
222 bool initDone =
false;
224 unsigned long long refreshModelFromPhysicsSimulatorCount = 0;
228 map<EntityOutputId, PivotPhysicsState *>
pivots;
229 map<EntityOutputId, WheelPhysicsState *>
wheels;
238 template <
class TOutputState>
239 map<EntityOutputId, float> toValues(
const map<EntityOutputId, TOutputState> &statesMap)
const {
240 map<EntityOutputId, float> values;
241 for (
auto it = statesMap.begin(); it != statesMap.end(); it++) {
242 values[it->first] = it->second->value;
250 void initObjectShapesAndBodiesHullConcave(
CscWorldObject *
object);
253 void initDynamicWorld();
254 void physicsThreadInit();
256 void initEntityShapesAndBodies(CscEntityPhysicsState *entityPhysicsState,
const CscPoint3dOriented *customPositionAndOrientation =
nullptr);
257 void initEntityPivot(CscEntityPhysicsState *entityPhysicsState,
const CscMemberJoint *currentJoint,
int index);
258 void initEntityPivots(CscEntityPhysicsState *entityPhysicsState);
259 void initEntityTranslation(CscEntityPhysicsState *entityPhysicsState,
const CscTranslation *currentTranslation,
int index);
260 void initEntityTranslations(CscEntityPhysicsState *entityPhysicsState);
261 void initEntityWheels(CscEntityPhysicsState *entityPhysicsState);
262 void initEntityWheel(CscEntityPhysicsState *entityPhysicsState,
const CscMemberWheel *currentWheel,
int index);
263 void initEntityPropellers(CscEntityPhysicsState *entityPhysicsState);
264 void initEntityPropeller(CscEntityPhysicsState *entityPhysicsState,
const CscPropeller *currentPropeller,
int index);
265 void initEntityLense(CscEntityPhysicsState *entityPhysicsState);
270 void applyOutputs(
const CscWorldElementId &entityId,
const CscState *outputsValues,
bool pivots,
bool propellers,
bool wheels);
279 MemberPhysicsState *getMemberPhysicsState(
const CscWorldElementId &entityId,
int memberIndex)
const {
280 bool memberHasState = entities.find(entityId) != entities.end() && entities.at(entityId)->membersByIndex.find(memberIndex) != entities.at(entityId)->membersByIndex.end();
281 ASSERT(entityId +
" member state not found for index " +
to_string(memberIndex), memberHasState);
282 if (!memberHasState) {
283 throw runtime_error(
"member state not found for index " +
to_string(memberIndex));
285 return entities.at(entityId)->membersByIndex.at(memberIndex);
288 inline btRigidBody *getMemberBody(
const CscWorldElementId &entityId,
int memberIndex) {
289 auto result = getMemberPhysicsState(entityId, memberIndex)->body;
293 inline PivotPhysicsState *getMutablePivotState(
const CscWorldElementId &entityId,
int id)
const {
294 bool pivotHasState = entities.find(entityId) != entities.end() && entities.at(entityId)->pivots.find(
id) != entities.at(entityId)->pivots.end();
295 ASSERT(
"pivot state not found for id " +
to_string(
id), pivotHasState);
296 if (!pivotHasState) {
297 throw runtime_error(
"pivot state not found for id " +
to_string(
id));
299 return entities.at(entityId)->pivots.at(
id);
302 inline TranslationPhysicsState *getMutableTranslationState(
const CscWorldElementId &entityId,
int id)
const {
303 bool translationHasState = entities.find(entityId) != entities.end() && entities.at(entityId)->translations.find(
id) != entities.at(entityId)->translations.end();
304 ASSERT(
"translation state not found for id " +
to_string(
id), translationHasState);
305 if (!translationHasState) {
306 throw runtime_error(
"translation state not found for id " +
to_string(
id));
308 return entities.at(entityId)->translations.at(
id);
311 inline WheelPhysicsState *getMutableWheelState(
const CscWorldElementId &entityId,
int id)
const {
312 bool wheelHasState = entities.find(entityId) != entities.end() && entities.at(entityId)->wheels.find(
id) != entities.at(entityId)->wheels.end();
313 ASSERT(
"wheel state not found for id " +
to_string(
id), wheelHasState);
314 if (!wheelHasState) {
315 throw runtime_error(
"wheel state not found for id " +
to_string(
id));
317 return entities.at(entityId)->wheels.at(
id);
320 inline PropellerPhysicsState *getMutablePropellerState(
const CscWorldElementId &entityId,
int id)
const {
321 bool propellerHasState = entities.find(entityId) != entities.end() && entities.at(entityId)->propellers.find(
id) != entities.at(entityId)->propellers.end();
322 ASSERT(
"propeller state not found for id " +
to_string(
id), propellerHasState);
323 if (!propellerHasState) {
324 throw runtime_error(
"propeller state not found for id " +
to_string(
id));
326 return entities.at(entityId)->propellers.at(
id);
332 void refreshModelFromPhysicsSimulator();
337 void dividedStepSimulationFutureVision(
unsigned umpteenthState,
CscSequence *sequence,
unsigned nbStateSubstep);
339 inline CscEntityPhysicsState *getEntityState(
const CscWorldElementId &entityId,
bool assertFound =
false)
const {
340 auto entityMatch = entities.find(entityId);
341 if (entityMatch == entities.end()) {
343 ASSERT(
"entity not found for id " + entityId,
false);
344 logger->warn(
"entity not found for id " + entityId);
348 return entityMatch->second;
352 CscEntityPhysicsState *state = getEntityState(entityId, assertFound);
353 if (state ==
nullptr) {
360 float floorWidth = 6000.0;
361 float floorHeight = 25.4;
362 float floorLength = 6000.0;
363 float globalGravity = -9.81;
370 thread *simulatorPhysicsThread =
nullptr;
371 bool simulatorPhysicsThreadRunning =
false;
372 bool simulatorPhysicsThreadStopped =
true;
375 btRigidBody *floorBody =
nullptr;
378 map<CscWorldElementId, CscEntityPhysicsState *>
entities;
388 btRigidBody *focusSphereBody =
nullptr;
389 btRigidBody *focusBarBody =
nullptr;
391 float speedFactor = 1.0;
393 void setMemberKinematicMode(
const CscWorldElementId &entityId,
int memberId,
bool kinematicMode);
394 void memberApplyAcceleration(
const CscWorldElementId &entityId,
int bodyIndex,
float accX,
float accY,
float accZ);
397 bool samePosition(
float x1,
float y1,
float z1,
float x2,
float y2,
float z2,
float epsilon);
398 bool sameEuler(
float yaw1,
float pitch1,
float roll1,
float yaw2,
float pitch2,
float roll2,
float epsilon);
401 map<int, float> getCurrentPropellers();
402 map<int, float> getCurrentWheels();
403 map<int, float> getCurrentTranslations();
404 map<int, float> getCurrentJoints();
409 optional<PlayStateListener> onStatePlayedListener = {};
411 string toDebugLogMemberInputs(
const CscWorldElementId &entityId,
int memberIndex);
416 static void buildConcaveHull(
CscWorldElement *
object,
float alphaShapeValue);
418 void removeAndDeleteBody(btRigidBody *);
419 void removeObjectByIndex(
int index);
421 void fireStatePlayed(
const CscWorldElementId &entityId,
const CscState *state,
int duration = 0,
int delay = 0,
bool relativeValues =
false);
424 const PivotPhysicsState *getPivotState(
const CscWorldElementId &entityId,
int id)
const;
425 const PropellerPhysicsState *getPropellerState(
const CscWorldElementId &entityId,
int id)
const;
426 const WheelPhysicsState *getWheelState(
const CscWorldElementId &entityId,
int id)
const;
427 const TranslationPhysicsState *getTranslationState(
const CscWorldElementId &entityId,
int id)
const;
429 btDiscreteDynamicsWorld *m_dynamicsWorld =
nullptr;
437 void setFloorRotation(
float yaw,
float pitch,
float roll);
438 void setFloorFriction(
float val);
450 btClock *clock =
nullptr;
451 const float fixedTimeStep = 1.0 / 100.0;
452 const float minFPS = 16.6666666666f;
468 void importObjectsIntoPhysicsSimulator(vector<CscWorldObject *> *objects);
470 void updateTranslation(
const CscWorldElementId &entityId,
int translationId,
float val,
bool relativeValues =
false);
471 void updateWheel(
const CscWorldElementId &entityId,
int wheelId,
float val,
float cst = 1000.0,
float speedCoef = 1.0);
473 void updatePropeller(
const CscWorldElementId &entityId,
int propellerId,
float val,
float cst = 1000.0);
474 void updatePivot(
const CscWorldElementId &entityId,
int pivotId,
float newValPercent,
bool relativeValues =
false);
479 void forceMemberValuesAndVerifyState(
const CscWorldElementId &entityId,
const CscMemberInputStatus *inputsValues,
const bool applyPosition[3],
const bool applyEuler[3],
const bool applyAcceleration[3], optional<int> nbMaxIteration = {}, optional<int> maxLoopDurationMillis = {},
const CscState *verifyState =
nullptr);
484 int moveMemberToStateFromMember(
const CscWorldElementId &entityId,
const CscMemberInputStatus *inputsValues,
const bool applyPosition[3],
const bool applyEuler[3],
const bool applyAcceleration[3], optional<int> nbMaxIteration = {}, optional<int> maxLoopDurationMillis = {},
int tryNumber = 0);
485 void moveMember(
const CscWorldElementId &entityId,
float *vals,
int bodyIndex,
int isTranslate);
486 void memberTeleportToOrigin(
const CscWorldElementId &entityId,
int bodyIndex,
float posX,
float posY,
float posZ);
487 void memberTeleportToRotation(
const CscWorldElementId &entityId,
int bodyIndex,
float yaw,
float pitch,
float roll);
495 bool resetOutputsToInitialVals =
false, optional<int> nbMaxIteration = {}, optional<int> maxLoopDurationMillis = {},
bool callPlayStateListener =
false);
507 void forceState(
const CscWorldElementId &entityId,
const CscState *appliedState,
int memberIdForInputs,
const bool applyPos[3],
const bool applyRot[3],
const bool applyAcc[3], optional<int> nbMaxIteration = {}, optional<int> maxLoopDurationMillis = {},
bool callPlayStateListener =
false);
515 void playSequence(
const CscWorldElementId &entityId,
CscState *init,
CscSequence *sequence,
const map<int, CscPivotMovementType> &pivotMovementByPivotId,
bool geneticAi =
false,
bool extrapolationRealTime =
false);
516 void updateMemberPhysics(
const CscWorldElementId &entityId,
int itemId,
float mass,
float friction,
float restitution,
float linearDamping,
float angularDamping);
517 void updatePivotPhysics(
const CscWorldElementId &entityId,
int id,
float min,
float max,
float softness,
float bias,
float relaxation,
float speedMax,
float percentSpeedMax);
518 void updatePropellerPhysics(
const CscWorldElementId &entityId,
int id,
float speedMax);
519 void updateWheelMaxSpeed(
const CscWorldElementId &entityId,
int wheelId,
float newSpeedMax);
520 void updateTranslationPhysics(
const CscWorldElementId &entityId,
int translationId,
float newMaxSpped);
521 void updateBehaviorMode(
const CscWorldElementId &entityId,
int modeId,
int memberId);
522 void updateMemberEulers(
const CscWorldElementId &entityId,
int memberId,
double eulerX,
double eulerY,
double eulerZ);
523 void updateMemberPosition(
const CscWorldElementId &entityId,
int memberId,
float posX,
float posY,
float posZ);
524 void updatePivotSpeedMax(
const CscWorldElementId &entityId,
int id,
float speedMax);
531 float getJointHingeAngle(
const CscWorldElementId &entityId,
int jointIdIn)
const;
532 vector<const CscMemberInputStatus *> *getCurrentInputs(
const CscWorldElementId &entityId);
544 void stepSimulationRealTime();
545 void stepSimulationFutureVision(
int millisecondsFromNow,
int nbSubSteps = 55);
546 void setGravity(
float xIn,
float yIn,
float zIn);
547 void setEntityGravity(
const CscWorldElementId &entityId,
float xIn,
float yIn,
float zIn);
550 return environmentObjects.size() >
index ? environmentObjects.at(
index) :
nullptr;
554 this->onStatePlayedListener = onStatePlayedListener;
558 this->simulatorSpeed = speed;
570 void playState(
const CscWorldElementId &entityId,
CscState *state,
int duration = 0,
int delay = 0,
bool relativeValues =
false);
584 void removeConscienceMemberFrontFocus();
587 btFixedConstraint *visionCnt1 = NULL;
588 btHingeConstraint *visionCnt2 = NULL;
590 void focusVisionIntoPosition(
float posX,
float posY,
float posZ);
595 void unitUpdatePivots();
596 void unitUpdateTranslations();
599 void removeObjectByName(
string name);
600 void removePlaceById(
string placeId);
613 string getPivotOtherMember(
const CscWorldElementId &entityId,
const string &memberName);
639 vector<CscState *> dividingOneStateIntoSubStates(
CscState *stateToDivide,
CscState *currentState,
int durationStateToDivide,
int nbStateToDivide,
float durationLastSubStep,
const map<int, CscPivotMovementType> &pivotMovementByPivotId);
661 CscSequence *dividingAllStatesOfOneSequenceIntoSubStates(
CscSequence *sequenceToDivide,
CscState *initialState,
const map<int, CscPivotMovementType> &pivotMovementByPivotId);
663 map<int, CscPoint3d *> getCenterOfMassOfAllMemberByMemberId(
const CscWorldElementId &entityId);
682 CscPoint3d *findCenterOfMass(
const CscEntityModel *entityModel, map<int, CscPoint3d *> centerOfMassOfAllMemberByMemberId);