Overte C++ Documentation
Rig.h
1 //
2 // Rig.h
3 // libraries/animation/src/
4 //
5 // Produces animation data and hip placement for the current timestamp.
6 //
7 // Created by Howard Stearns, Seth Alves, Anthony Thibault, Andrew Meadows on 7/15/15.
8 // Copyright (c) 2015 High Fidelity, Inc. All rights reserved.
9 // Copyright 2023 Overte e.V.
10 //
11 // Distributed under the Apache License, Version 2.0.
12 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
13 // SPDX-License-Identifier: Apache-2.0
14 //
15 
16 #ifndef __hifi__Rig__
17 #define __hifi__Rig__
18 
19 #include <QObject>
20 #include <QMutex>
21 #include <vector>
22 #include <JointData.h>
23 #include <QReadWriteLock>
24 #include <ScriptValue.h>
25 
26 #include "AnimNode.h"
27 #include "AnimNodeLoader.h"
28 #include "SimpleMovingAverage.h"
29 #include "AnimUtil.h"
30 #include "Flow.h"
31 #include "AvatarConstants.h"
32 
33 class Rig;
34 class AnimInverseKinematics;
35 
36 // Rig instances are reentrant.
37 // However only specific methods thread-safe. Noted below.
38 
39 class Rig : public QObject {
40  Q_OBJECT
41 public:
42  struct StateHandler {
43  AnimVariantMap results;
44  QStringList propertyNames;
45  std::shared_ptr<ScriptValue> function;
46  bool useNames;
47  };
48 
49  enum PrimaryControllerType {
50  PrimaryControllerType_Head = 0,
51  PrimaryControllerType_LeftHand,
52  PrimaryControllerType_RightHand,
53  PrimaryControllerType_Hips,
54  PrimaryControllerType_LeftFoot,
55  PrimaryControllerType_RightFoot,
56  PrimaryControllerType_Spine2,
57  NumPrimaryControllerTypes
58  };
59 
60  // NOTE: These should ordered such that joint parents appear before their children.
61  enum SecondaryControllerType {
62  SecondaryControllerType_LeftShoulder = 0,
63  SecondaryControllerType_RightShoulder,
64  SecondaryControllerType_LeftArm,
65  SecondaryControllerType_RightArm,
66  SecondaryControllerType_LeftForeArm,
67  SecondaryControllerType_RightForeArm,
68  SecondaryControllerType_LeftUpLeg,
69  SecondaryControllerType_RightUpLeg,
70  SecondaryControllerType_LeftLeg,
71  SecondaryControllerType_RightLeg,
72  SecondaryControllerType_LeftToeBase,
73  SecondaryControllerType_RightToeBase,
74  NumSecondaryControllerTypes
75  };
76 
77  enum class ControllerFlags : uint8_t {
78  Enabled = 0x01,
79  Estimated = 0x02
80  };
81 
82  struct ControllerParameters {
83  ControllerParameters() {
84  memset(primaryControllerFlags, 0, NumPrimaryControllerTypes);
85  memset(secondaryControllerFlags, 0, NumPrimaryControllerTypes);
86  }
87  glm::mat4 rigToSensorMatrix;
88  AnimPose primaryControllerPoses[NumPrimaryControllerTypes]; // rig space
89  uint8_t primaryControllerFlags[NumPrimaryControllerTypes];
90  AnimPose secondaryControllerPoses[NumSecondaryControllerTypes]; // rig space
91  uint8_t secondaryControllerFlags[NumSecondaryControllerTypes];
92  bool isTalking;
93  float inputX = 0.0f;
94  float inputZ = 0.0f;
95  bool reactionEnabledFlags[NUM_AVATAR_BEGIN_END_REACTIONS];
96  bool reactionTriggers[NUM_AVATAR_TRIGGER_REACTIONS];
97  HFMJointShapeInfo hipsShapeInfo;
98  HFMJointShapeInfo spineShapeInfo;
99  HFMJointShapeInfo spine1ShapeInfo;
100  HFMJointShapeInfo spine2ShapeInfo;
101  };
102 
103  struct EyeParameters {
104  glm::vec3 eyeLookAt = glm::vec3(); // world space
105  glm::vec3 eyeSaccade = glm::vec3(); // world space
106  glm::vec3 modelTranslation = glm::vec3();
107  glm::quat modelRotation = glm::quat();
108  int leftEyeJointIndex = -1;
109  int rightEyeJointIndex = -1;
110  };
111 
112  enum class CharacterControllerState {
113  Ground = 0,
114  Takeoff,
115  InAir,
116  Hover,
117  Seated
118  };
119 
120  Rig();
121  virtual ~Rig();
122 
123  void destroyAnimGraph();
124 
125  void overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
126  bool isPlayingOverrideAnimation() const { return _userAnimState.clipNodeEnum != UserAnimState::None; };
127  void restoreAnimation();
128 
129  void overrideHandAnimation(bool isLeft, const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
130  void restoreHandAnimation(bool isLeft);
131 
132  void overrideNetworkAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
133  void triggerNetworkRole(const QString& role);
134  void restoreNetworkAnimation();
135 
136  QStringList getAnimationRoles() const;
137  void overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
138  void restoreRoleAnimation(const QString& role);
139 
140  void initJointStates(const HFMModel& hfmModel, const glm::mat4& modelOffset);
141  void reset(const HFMModel& hfmModel);
142  bool jointStatesEmpty() const;
143  int getJointStateCount() const;
144  int indexOfJoint(const QString& jointName) const;
145  QString nameOfJoint(int jointIndex) const;
146 
147  void setModelOffset(const glm::mat4& modelOffsetMat);
148 
149  void clearJointState(int index);
150  void clearJointStates();
151  void clearJointAnimationPriority(int index);
152 
153  std::shared_ptr<AnimInverseKinematics> getAnimInverseKinematicsNode() const;
154 
155  void clearIKJointLimitHistory();
156  void setMaxHipsOffsetLength(float maxLength);
157  float getMaxHipsOffsetLength() const;
158 
159  float getIKErrorOnLastSolve() const;
160 
161  int getJointParentIndex(int childIndex) const;
162 
163  // geometry space
164  void setJointState(int index, bool valid, const glm::quat& rotation, const glm::vec3& translation, float priority);
165 
166  // geometry space
167  void setJointTranslation(int index, bool valid, const glm::vec3& translation, float priority);
168  void setJointRotation(int index, bool valid, const glm::quat& rotation, float priority);
169 
170  bool getIsJointOverridden(int jointIndex) const;
171 
172  // if translation and rotation is identity, position will be in rig space
173  bool getJointPositionInWorldFrame(int jointIndex, glm::vec3& position,
174  glm::vec3 translation, glm::quat rotation) const;
175 
176  // rig space
177  bool getJointPosition(int jointIndex, glm::vec3& position) const;
178 
179  // if rotation is identity, result will be in rig space
180  bool getJointRotationInWorldFrame(int jointIndex, glm::quat& result, const glm::quat& rotation) const;
181 
182  // geometry space (thread-safe)
183  bool getJointRotation(int jointIndex, glm::quat& rotation) const;
184  bool getJointTranslation(int jointIndex, glm::vec3& translation) const;
185 
186  // rig space (thread-safe)
187  bool getAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation) const;
188  bool getAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translation) const;
189  bool getAbsoluteJointPoseInRigFrame(int jointIndex, AnimPose& returnPose) const;
190 
191  // rig space
192  glm::mat4 getJointTransform(int jointIndex) const;
193  AnimPose getJointPose(int jointIndex) const;
194 
195  // Start or stop animations as needed.
196  void computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity,
197  const glm::quat& worldRotation, CharacterControllerState ccState, float sensorToWorldScale);
198 
199  // Regardless of who started the animations or how many, update the joints.
200  void updateAnimations(float deltaTime, const glm::mat4& rootTransform, const glm::mat4& rigToWorldTransform);
201 
202  void updateFromControllerParameters(const ControllerParameters& params, float dt);
203  void updateFromEyeParameters(const EyeParameters& params);
204 
205  void initAnimGraph(const QUrl& url);
206 
207  AnimNode::ConstPointer getAnimNode() const { return _animNode; }
208  AnimNode::ConstPointer findAnimNodeByName(const QString& name) const;
209  AnimSkeleton::ConstPointer getAnimSkeleton() const { return _animSkeleton; }
210  ScriptValue addAnimationStateHandler(const ScriptValue& handler, const ScriptValue& propertiesList);
211  void removeAnimationStateHandler(const ScriptValue& handler);
212  void animationStateHandlerResult(int identifier, const ScriptValue& result);
213 
214  // rig space
215  bool getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const;
216 
217  // rig space
218  AnimPose getAbsoluteDefaultPose(int index) const;
219 
220  // rig space
221  const AnimPoseVec& getAbsoluteDefaultPoses() const;
222 
223  // geometry space
224  bool getRelativeDefaultJointRotation(int index, glm::quat& rotationOut) const;
225  bool getRelativeDefaultJointTranslation(int index, glm::vec3& translationOut) const;
226 
227  void copyJointsIntoJointData(QVector<JointData>& jointDataVec) const;
228  void copyJointsFromJointData(const QVector<JointData>& jointDataVec);
229  void computeExternalPoses(const glm::mat4& modelOffsetMat);
230 
231  void computeAvatarBoundingCapsule(const HFMModel& hfmModel, float& radiusOut, float& heightOut, glm::vec3& offsetOut) const;
232 
233  void setEnableInverseKinematics(bool enable);
234  void setEnableAnimations(bool enable);
235 
236  const glm::mat4& getGeometryToRigTransform() const { return _geometryToRigTransform; }
237 
238  const AnimPose& getModelOffsetPose() const { return _modelOffset; }
239  const AnimPose& getGeometryOffsetPose() const { return _geometryOffset; }
240 
241  void setEnableDebugDrawIKTargets(bool enableDebugDrawIKTargets) { _enableDebugDrawIKTargets = enableDebugDrawIKTargets; }
242  void setEnableDebugDrawIKConstraints(bool enableDebugDrawIKConstraints) { _enableDebugDrawIKConstraints = enableDebugDrawIKConstraints; }
243  void setEnableDebugDrawIKChains(bool enableDebugDrawIKChains) { _enableDebugDrawIKChains = enableDebugDrawIKChains; }
244 
245  // input assumed to be in rig space
246  void computeHeadFromHMD(const AnimPose& hmdPose, glm::vec3& headPositionOut, glm::quat& headOrientationOut) const;
247 
248  // used to debug animation playback
249  const AnimContext::DebugAlphaMap& getDebugAlphaMap() const { return _lastContext.getDebugAlphaMap(); }
250  const AnimVariantMap& getAnimVars() const { return _lastAnimVars; }
251  const AnimContext::DebugStateMachineMap& getStateMachineMap() const { return _lastContext.getStateMachineMap(); }
252  void initFlow(bool isActive);
253  Flow& getFlow() { return _internalFlow; }
254 
255  float getUnscaledEyeHeight() const;
256  float getUnscaledHipsHeight() const;
257  void buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) const;
258 
259  int getOverrideJointCount() const;
260  bool getFlowActive() const;
261  bool getNetworkGraphActive() const;
262  void setDirectionalBlending(const QString& targetName, const glm::vec3& blendingTarget, const QString& alphaName, float alpha);
263 
264  // Get the scale factor to convert distances in the geometry frame into the unscaled rig frame.
265  float GetScaleFactorGeometryToUnscaledRig() const;
266 
267 signals:
268  void onLoadComplete();
269  void onLoadFailed();
270 
271 protected:
272  bool isIndexValid(int index) const { return _animSkeleton && index >= 0 && index < _animSkeleton->getNumJoints(); }
273  void updateAnimationStateHandlers();
274  void applyOverridePoses();
275 
276  void updateHead(bool headEnabled, bool hipsEnabled, const AnimPose& headMatrix);
277  void updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool hipsEstimated,
278  bool leftArmEnabled, bool rightArmEnabled, bool headEnabled, float dt,
279  const AnimPose& leftHandPose, const AnimPose& rightHandPose,
280  const HFMJointShapeInfo& hipsShapeInfo, const HFMJointShapeInfo& spineShapeInfo,
281  const HFMJointShapeInfo& spine1ShapeInfo, const HFMJointShapeInfo& spine2ShapeInfo,
282  const glm::mat4& rigToSensorMatrix, const glm::mat4& sensorToRigMatrix);
283  void updateFeet(bool leftFootEnabled, bool rightFootEnabled, bool headEnabled,
284  const AnimPose& leftFootPose, const AnimPose& rightFootPose,
285  const glm::mat4& rigToSensorMatrix, const glm::mat4& sensorToRigMatrix);
286  void updateReactions(const ControllerParameters& params);
287 
288  void updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm::quat& modelRotation, const glm::vec3& lookAt, const glm::vec3& saccade);
289  void calcAnimAlpha(float speed, const std::vector<float>& referenceSpeeds, float* alphaOut) const;
290 
291  bool calculateElbowPoleVector(int handIndex, int elbowIndex, int armIndex, int oppositeArmIndex, glm::vec3& poleVector) const;
292  glm::vec3 calculateKneePoleVector(int footJointIndex, int kneeJoint, int upLegIndex, int hipsIndex, const AnimPose& targetFootPose) const;
293  glm::vec3 deflectHandFromTorso(const glm::vec3& handPosition, const HFMJointShapeInfo& hipsShapeInfo, const HFMJointShapeInfo& spineShapeInfo,
294  const HFMJointShapeInfo& spine1ShapeInfo, const HFMJointShapeInfo& spine2ShapeInfo) const;
295 
296  // The ground plane Y position in geometry space.
297  static constexpr float GEOMETRY_GROUND_Y = 0.0f;
298 
299  AnimPose _modelOffset; // model to rig space
300  AnimPose _geometryOffset; // geometry to model space (includes unit offset & fst offsets)
301  AnimPose _invGeometryOffset;
302 
303  struct PoseSet {
304  AnimPoseVec _relativePoses; // geometry space relative to parent.
305  AnimPoseVec _absolutePoses; // rig space, not relative to parent.
306  AnimPoseVec _overridePoses; // geometry space relative to parent.
307  std::vector<bool> _overrideFlags;
308  };
309 
310  // Only accessed by the main thread
311  PoseSet _internalPoseSet;
312  PoseSet _networkPoseSet;
313 
314  // Copy of the _poseSet for external threads.
315  PoseSet _externalPoseSet;
316  mutable QReadWriteLock _externalPoseSetLock;
317 
318  AnimPoseVec _absoluteDefaultPoses; // rig space, not relative to parent.
319 
320  glm::mat4 _geometryToRigTransform;
321  glm::mat4 _rigToGeometryTransform;
322 
323  int _rootJointIndex { -1 };
324 
325  int _leftEyeJointIndex { -1 };
326  int _rightEyeJointIndex { -1 };
327  std::vector<int> _leftEyeJointChildren;
328  std::vector<int> _rightEyeJointChildren;
329 
330  int _leftHandJointIndex { -1 };
331  int _leftElbowJointIndex { -1 };
332  int _leftShoulderJointIndex { -1 };
333 
334  int _rightHandJointIndex { -1 };
335  int _rightElbowJointIndex { -1 };
336  int _rightShoulderJointIndex { -1 };
337 
338  glm::vec3 _lastForward;
339  glm::vec3 _lastPosition;
340  glm::vec3 _lastVelocity;
341  bool _isMovingWithMomentum{ false };
342 
343  QUrl _animGraphURL;
344  std::shared_ptr<AnimNode> _animNode;
345  std::shared_ptr<AnimNode> _networkNode;
346  std::shared_ptr<AnimSkeleton> _animSkeleton;
347  std::unique_ptr<AnimNodeLoader> _animLoader;
348  std::unique_ptr<AnimNodeLoader> _networkLoader;
349  AnimVariantMap _animVars;
350  AnimVariantMap _networkVars;
351 
352  enum class RigRole {
353  Idle = 0,
354  Turn,
355  Move,
356  Hover,
357  Takeoff,
358  InAir,
359  Seated
360  };
361  RigRole _state { RigRole::Idle };
362  RigRole _desiredState { RigRole::Idle };
363  float _desiredStateAge { 0.0f };
364 
365  struct NetworkAnimState {
366  enum ClipNodeEnum {
367  None = 0,
368  PreTransit,
369  Transit,
370  PostTransit,
371  A,
372  B
373  };
374  NetworkAnimState() : clipNodeEnum(NetworkAnimState::None), fps(30.0f), loop(false), firstFrame(0.0f), lastFrame(0.0f), blendTime(FLT_MAX) {}
375  NetworkAnimState(ClipNodeEnum clipNodeEnumIn, const QString& urlIn, float fpsIn, bool loopIn, float firstFrameIn, float lastFrameIn) :
376  clipNodeEnum(clipNodeEnumIn), url(urlIn), fps(fpsIn), loop(loopIn), firstFrame(firstFrameIn), lastFrame(lastFrameIn), blendTime(FLT_MAX) {}
377 
378  ClipNodeEnum clipNodeEnum;
379  QString url;
380  float fps;
381  bool loop;
382  float firstFrame;
383  float lastFrame;
384  float blendTime;
385  };
386 
387  struct HandAnimState {
388  enum ClipNodeEnum {
389  None = 0,
390  A,
391  B
392  };
393 
394  HandAnimState() : clipNodeEnum(HandAnimState::None) {}
395  HandAnimState(ClipNodeEnum clipNodeEnumIn, const QString& urlIn, float fpsIn, bool loopIn, float firstFrameIn, float lastFrameIn) :
396  clipNodeEnum(clipNodeEnumIn), url(urlIn), fps(fpsIn), loop(loopIn), firstFrame(firstFrameIn), lastFrame(lastFrameIn) {
397  }
398 
399 
400  ClipNodeEnum clipNodeEnum;
401  QString url;
402  float fps;
403  bool loop;
404  float firstFrame;
405  float lastFrame;
406  };
407 
408  struct UserAnimState {
409  enum ClipNodeEnum {
410  None = 0,
411  A,
412  B
413  };
414 
415  UserAnimState() : clipNodeEnum(UserAnimState::None) {}
416  UserAnimState(ClipNodeEnum clipNodeEnumIn, const QString& urlIn, float fpsIn, bool loopIn, float firstFrameIn, float lastFrameIn) :
417  clipNodeEnum(clipNodeEnumIn), url(urlIn), fps(fpsIn), loop(loopIn), firstFrame(firstFrameIn), lastFrame(lastFrameIn) {}
418 
419  ClipNodeEnum clipNodeEnum;
420  QString url;
421  float fps;
422  bool loop;
423  float firstFrame;
424  float lastFrame;
425  };
426 
427  struct RoleAnimState {
428  RoleAnimState() {}
429  RoleAnimState(const QString& roleId, const QString& urlIn, float fpsIn, bool loopIn, float firstFrameIn, float lastFrameIn) :
430  role(roleId), url(urlIn), fps(fpsIn), loop(loopIn), firstFrame(firstFrameIn), lastFrame(lastFrameIn) {}
431 
432  QString role;
433  QString url;
434  float fps;
435  bool loop;
436  float firstFrame;
437  float lastFrame;
438  };
439 
440  UserAnimState _userAnimState;
441  NetworkAnimState _networkAnimState;
442  HandAnimState _rightHandAnimState;
443  HandAnimState _leftHandAnimState;
444  std::map<QString, RoleAnimState> _roleAnimStates;
445  int _evaluationCount{ 0 };
446 
447  float _leftHandOverlayAlpha { 0.0f };
448  float _rightHandOverlayAlpha { 0.0f };
449  float _talkIdleInterpTime { 0.0f };
450  bool _previousIsTalking { false };
451 
452  SimpleMovingAverage _averageForwardSpeed { 10 };
453  SimpleMovingAverage _averageLateralSpeed { 10 };
454 
455  std::map<QString, AnimNode::Pointer> _origRoleAnimations;
456 
457  int32_t _numOverrides { 0 };
458  bool _lastEnableInverseKinematics { true };
459  bool _enableInverseKinematics { true };
460  bool _enabledAnimations { true };
461 
462  mutable uint32_t _jointNameWarningCount { 0 };
463 
464  bool _enableDebugDrawIKTargets { false };
465  bool _enableDebugDrawIKConstraints { false };
466  bool _enableDebugDrawIKChains { false };
467 
468  QMap<int, StateHandler> _stateHandlers;
469  int _nextStateHandlerId { 0 };
470  QMutex _stateMutex;
471 
472  glm::vec3 _prevRightFootPoleVector { Vectors::UNIT_Z }; // sensor space
473  bool _prevRightFootPoleVectorValid { false };
474 
475  glm::vec3 _prevLeftFootPoleVector { Vectors::UNIT_Z }; // sensor space
476  bool _prevLeftFootPoleVectorValid { false };
477 
478  int _rigId;
479  bool _headEnabled { false };
480  bool _computeNetworkAnimation { false };
481  bool _sendNetworkNode { false };
482 
483  AnimContext _lastContext;
484  AnimVariantMap _lastAnimVars;
485 
486  SnapshotBlendPoseHelper _hipsBlendHelper;
487  ControllerParameters _previousControllerParameters;
488  Flow _internalFlow;
489  Flow _networkFlow;
490 };
491 
492 #endif /* defined(__hifi__Rig__) */
[ScriptInterface] Provides an engine-independent interface for QScriptValue
Definition: ScriptValue.h:40
The runtime model format.
Definition: HFM.h:302