mirror of
https://github.com/lubosz/overte.git
synced 2025-04-14 01:46:18 +02:00
set useFlow function
This commit is contained in:
parent
05d50f32ba
commit
3e66bce112
6 changed files with 161 additions and 31 deletions
|
@ -5320,3 +5320,58 @@ void MyAvatar::addAvatarHandsToFlow(const std::shared_ptr<Avatar>& otherAvatar)
|
|||
flow.setOthersCollision(otherAvatar->getID(), jointIndex, position);
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::useFlow(const QVariantMap& physicsConfig, const QVariantMap& collisionsConfig) {
|
||||
if (_skeletonModel->isLoaded()) {
|
||||
auto &flow = _skeletonModel->getRig().getFlow();
|
||||
flow.init();
|
||||
auto physicsGroups = physicsConfig.keys();
|
||||
if (physicsGroups.size() > 0) {
|
||||
for (auto &groupName : physicsGroups) {
|
||||
auto &settings = physicsConfig[groupName].toMap();
|
||||
FlowPhysicsSettings physicsSettings = flow.getPhysicsSettingsForGroup(groupName);
|
||||
if (settings.contains("active")) {
|
||||
physicsSettings._active = settings["active"].toBool();
|
||||
}
|
||||
if (settings.contains("damping")) {
|
||||
physicsSettings._damping = settings["damping"].toFloat();
|
||||
}
|
||||
if (settings.contains("delta")) {
|
||||
physicsSettings._delta = settings["delta"].toFloat();
|
||||
}
|
||||
if (settings.contains("gravity")) {
|
||||
physicsSettings._gravity = settings["gravity"].toFloat();
|
||||
}
|
||||
if (settings.contains("inertia")) {
|
||||
physicsSettings._inertia = settings["inertia"].toFloat();
|
||||
}
|
||||
if (settings.contains("radius")) {
|
||||
physicsSettings._radius = settings["radius"].toFloat();
|
||||
}
|
||||
if (settings.contains("stiffness")) {
|
||||
physicsSettings._stiffness = settings["stiffness"].toFloat();
|
||||
}
|
||||
flow.setPhysicsSettingsForGroup(groupName, physicsSettings);
|
||||
}
|
||||
}
|
||||
auto collisionJoints = collisionsConfig.keys();
|
||||
if (collisionJoints.size() > 0) {
|
||||
auto &collisionSystem = flow.getCollisionSystem();
|
||||
collisionSystem.resetCollisions();
|
||||
for (auto &jointName : collisionJoints) {
|
||||
int jointIndex = getJointIndex(jointName);
|
||||
FlowCollisionSettings collisionsSettings;
|
||||
auto &settings = collisionsConfig[jointName].toMap();
|
||||
collisionsSettings._entityID = getID();
|
||||
if (settings.contains("radius")) {
|
||||
collisionsSettings._radius = settings["radius"].toFloat();
|
||||
}
|
||||
if (settings.contains("offset")) {
|
||||
collisionsSettings._offset = vec3FromVariant(settings["offset"]);
|
||||
}
|
||||
collisionSystem.addCollisionSphere(jointIndex, collisionsSettings);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1185,6 +1185,16 @@ public:
|
|||
|
||||
void addAvatarHandsToFlow(const std::shared_ptr<Avatar>& otherAvatar);
|
||||
|
||||
/**jsdoc
|
||||
* Init flow simulation on avatar.
|
||||
* @function MyAvatar.useFlow
|
||||
* @param {Object} physicsConfig - object with the customized physic parameters
|
||||
* i.e. {"hair": {"active": true, "stiffness": 0.0, "radius": 0.04, "gravity": -0.035, "damping": 0.8, "inertia": 0.8, "delta": 0.35}}
|
||||
* @param {Object} collisionsConfig - object with the customized collision parameters
|
||||
* i.e. {"Spine2": {"type": "sphere", "radius": 0.14, "offset": {"x": 0.0, "y": 0.2, "z": 0.0}}}
|
||||
*/
|
||||
Q_INVOKABLE void useFlow(const QVariantMap& flowConfig = QVariantMap(), const QVariantMap& collisionsConfig = QVariantMap());
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
|
|
|
@ -176,7 +176,7 @@ void FlowCollisionSystem::modifySelfCollisionRadius(int jointIndex, float radius
|
|||
int collisionIndex = findSelfCollisionWithJoint(jointIndex);
|
||||
if (collisionIndex > -1) {
|
||||
_selfCollisions[collisionIndex]._initialRadius = radius;
|
||||
_selfCollisions[collisionIndex]._radius = _scale * radius;
|
||||
//_selfCollisions[collisionIndex]._radius = _scale * radius;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -185,7 +185,7 @@ void FlowCollisionSystem::modifySelfCollisionYOffset(int jointIndex, float offse
|
|||
if (collisionIndex > -1) {
|
||||
auto currentOffset = _selfCollisions[collisionIndex]._offset;
|
||||
_selfCollisions[collisionIndex]._initialOffset = glm::vec3(currentOffset.x, offset, currentOffset.z);
|
||||
_selfCollisions[collisionIndex]._offset = _selfCollisions[collisionIndex]._initialOffset * _scale;
|
||||
//_selfCollisions[collisionIndex]._offset = _selfCollisions[collisionIndex]._initialOffset * _scale;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -193,11 +193,27 @@ void FlowCollisionSystem::modifySelfCollisionOffset(int jointIndex, const glm::v
|
|||
int collisionIndex = findSelfCollisionWithJoint(jointIndex);
|
||||
if (collisionIndex > -1) {
|
||||
_selfCollisions[collisionIndex]._initialOffset = offset;
|
||||
_selfCollisions[collisionIndex]._offset = _selfCollisions[collisionIndex]._initialOffset * _scale;
|
||||
//_selfCollisions[collisionIndex]._offset = _selfCollisions[collisionIndex]._initialOffset * _scale;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
FlowCollisionSettings FlowCollisionSystem::getCollisionSettingsByJoint(int jointIndex) {
|
||||
for (auto &collision : _selfCollisions) {
|
||||
if (collision._jointIndex == jointIndex) {
|
||||
return FlowCollisionSettings(collision._entityID, FlowCollisionType::CollisionSphere, collision._initialOffset, collision._initialRadius);
|
||||
}
|
||||
}
|
||||
return FlowCollisionSettings();
|
||||
}
|
||||
void FlowCollisionSystem::setCollisionSettingsByJoint(int jointIndex, const FlowCollisionSettings& settings) {
|
||||
for (auto &collision : _selfCollisions) {
|
||||
if (collision._jointIndex == jointIndex) {
|
||||
collision._initialRadius = settings._radius;
|
||||
collision._initialOffset = settings._offset;
|
||||
collision._radius = _scale * settings._radius;
|
||||
collision._offset = _scale * settings._offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
void FlowCollisionSystem::prepareCollisions() {
|
||||
_allCollisions.clear();
|
||||
_allCollisions.resize(_selfCollisions.size() + _othersCollisions.size());
|
||||
|
@ -206,6 +222,11 @@ void FlowCollisionSystem::prepareCollisions() {
|
|||
_othersCollisions.clear();
|
||||
}
|
||||
|
||||
FlowNode::FlowNode(const glm::vec3& initialPosition, FlowPhysicsSettings settings) {
|
||||
_initialPosition = _previousPosition = _currentPosition = initialPosition;
|
||||
_initialRadius = settings._radius;
|
||||
}
|
||||
|
||||
void FlowNode::update(float deltaTime, const glm::vec3& accelerationOffset) {
|
||||
_acceleration = glm::vec3(0.0f, _settings._gravity, 0.0f);
|
||||
_previousVelocity = _currentVelocity;
|
||||
|
@ -215,15 +236,16 @@ void FlowNode::update(float deltaTime, const glm::vec3& accelerationOffset) {
|
|||
// Add inertia
|
||||
const float FPS = 60.0f;
|
||||
float timeRatio = (FPS * deltaTime);
|
||||
|
||||
float invertedTimeRatio = timeRatio > 0.0f ? 1.0f / timeRatio : 1.0f;
|
||||
auto deltaVelocity = _previousVelocity - _currentVelocity;
|
||||
auto centrifugeVector = glm::length(deltaVelocity) != 0.0f ? glm::normalize(deltaVelocity) : glm::vec3();
|
||||
_acceleration = _acceleration + centrifugeVector * _settings._inertia * glm::length(_currentVelocity) * (1 / timeRatio);
|
||||
_acceleration = _acceleration + centrifugeVector * _settings._inertia * glm::length(_currentVelocity) * invertedTimeRatio;
|
||||
|
||||
// Add offset
|
||||
_acceleration += accelerationOffset;
|
||||
|
||||
glm::vec3 deltaAcceleration = timeRatio * _acceleration * glm::pow(_settings._delta * _scale, 2);
|
||||
//glm::vec3 deltaAcceleration = timeRatio * _acceleration * glm::pow(_settings._delta * _scale, 2);
|
||||
glm::vec3 deltaAcceleration = timeRatio * _acceleration * glm::pow(_settings._delta, 2);
|
||||
// Calculate new position
|
||||
_currentPosition = (_currentPosition + _currentVelocity * _settings._damping) + deltaAcceleration;
|
||||
}
|
||||
|
@ -257,11 +279,10 @@ void FlowNode::solveCollisions(const FlowCollisionResult& collision) {
|
|||
}
|
||||
};
|
||||
|
||||
FlowJoint::FlowJoint(int jointIndex, int parentIndex, int childIndex, const QString& name, const QString& group, float scale, const FlowPhysicsSettings& settings) {
|
||||
FlowJoint::FlowJoint(int jointIndex, int parentIndex, int childIndex, const QString& name, const QString& group, const FlowPhysicsSettings& settings) {
|
||||
_index = jointIndex;
|
||||
_name = name;
|
||||
_group = group;
|
||||
_scale = scale;
|
||||
_childIndex = childIndex;
|
||||
_parentIndex = parentIndex;
|
||||
_node = FlowNode(glm::vec3(), settings);
|
||||
|
@ -276,8 +297,7 @@ void FlowJoint::setInitialData(const glm::vec3& initialPosition, const glm::vec3
|
|||
_initialRotation = initialRotation;
|
||||
_translationDirection = glm::normalize(_initialTranslation);
|
||||
_parentPosition = parentPosition;
|
||||
_length = glm::length(_initialPosition - parentPosition);
|
||||
_originalLength = _length / _scale;
|
||||
_initialLength = _length = glm::length(_initialPosition - parentPosition);
|
||||
}
|
||||
|
||||
void FlowJoint::setUpdatedData(const glm::vec3& updatedPosition, const glm::vec3& updatedTranslation, const glm::quat& updatedRotation, const glm::vec3& parentPosition, const glm::quat& parentWorldRotation) {
|
||||
|
@ -313,8 +333,8 @@ void FlowJoint::solve(const FlowCollisionResult& collision) {
|
|||
_node.solve(_parentPosition, _length, collision);
|
||||
};
|
||||
|
||||
FlowDummyJoint::FlowDummyJoint(const glm::vec3& initialPosition, int index, int parentIndex, int childIndex, float scale, FlowPhysicsSettings settings) :
|
||||
FlowJoint(index, parentIndex, childIndex, DUMMY_KEYWORD + "_" + index, DUMMY_KEYWORD, scale, settings) {
|
||||
FlowDummyJoint::FlowDummyJoint(const glm::vec3& initialPosition, int index, int parentIndex, int childIndex, FlowPhysicsSettings settings) :
|
||||
FlowJoint(index, parentIndex, childIndex, DUMMY_KEYWORD + "_" + index, DUMMY_KEYWORD, settings) {
|
||||
_isDummy = true;
|
||||
_initialPosition = initialPosition;
|
||||
_node = FlowNode(_initialPosition, settings);
|
||||
|
@ -451,6 +471,12 @@ bool FlowThread::getActive() {
|
|||
return _jointsPointer->at(_joints[0])._node._active;
|
||||
};
|
||||
|
||||
void Flow::init() {
|
||||
if (!_initialized) {
|
||||
calculateConstraints();
|
||||
}
|
||||
}
|
||||
|
||||
void Flow::calculateConstraints() {
|
||||
cleanUp();
|
||||
if (!_rig) {
|
||||
|
@ -507,7 +533,7 @@ void Flow::calculateConstraints() {
|
|||
jointSettings = DEFAULT_JOINT_SETTINGS;
|
||||
}
|
||||
if (_flowJointData.find(i) == _flowJointData.end()) {
|
||||
auto flowJoint = FlowJoint(i, parentIndex, -1, name, group, _scale, jointSettings);
|
||||
auto flowJoint = FlowJoint(i, parentIndex, -1, name, group, jointSettings);
|
||||
_flowJointData.insert(std::pair<int, FlowJoint>(i, flowJoint));
|
||||
}
|
||||
}
|
||||
|
@ -553,7 +579,7 @@ void Flow::calculateConstraints() {
|
|||
auto newSettings = FlowPhysicsSettings(joint._node._settings);
|
||||
newSettings._stiffness = ISOLATED_JOINT_STIFFNESS;
|
||||
int extraIndex = (int)_flowJointData.size();
|
||||
auto newJoint = FlowDummyJoint(jointPosition, extraIndex, jointIndex, -1, _scale, newSettings);
|
||||
auto newJoint = FlowDummyJoint(jointPosition, extraIndex, jointIndex, -1, newSettings);
|
||||
newJoint._isDummy = false;
|
||||
newJoint._length = ISOLATED_JOINT_LENGTH;
|
||||
newJoint._childIndex = extraIndex;
|
||||
|
@ -575,7 +601,7 @@ void Flow::calculateConstraints() {
|
|||
int parentIndex = rightHandIndex;
|
||||
for (int i = 0; i < DUMMY_JOINT_COUNT; i++) {
|
||||
int childIndex = (i == (DUMMY_JOINT_COUNT - 1)) ? -1 : extraIndex + 1;
|
||||
auto newJoint = FlowDummyJoint(rightHandPosition, extraIndex, parentIndex, childIndex, _scale, DEFAULT_JOINT_SETTINGS);
|
||||
auto newJoint = FlowDummyJoint(rightHandPosition, extraIndex, parentIndex, childIndex, DEFAULT_JOINT_SETTINGS);
|
||||
_flowJointData.insert(std::pair<int, FlowJoint>(extraIndex, newJoint));
|
||||
parentIndex = extraIndex;
|
||||
extraIndex++;
|
||||
|
@ -601,24 +627,39 @@ void Flow::cleanUp() {
|
|||
_flowJointKeywords.clear();
|
||||
_collisionSystem.resetCollisions();
|
||||
_initialized = false;
|
||||
_isScaleSet = false;
|
||||
_active = false;
|
||||
}
|
||||
|
||||
void Flow::setTransform(float scale, const glm::vec3& position, const glm::quat& rotation) {
|
||||
_scale = scale;
|
||||
for (auto &joint : _flowJointData) {
|
||||
joint.second._scale = scale;
|
||||
joint.second._node._scale = scale;
|
||||
}
|
||||
_entityPosition = position;
|
||||
_entityRotation = rotation;
|
||||
_active = true;
|
||||
_active = _initialized;
|
||||
}
|
||||
|
||||
void Flow::update(float deltaTime) {
|
||||
if (_initialized && _active) {
|
||||
QElapsedTimer _timer;
|
||||
_timer.start();
|
||||
if (_scale != _lastScale) {
|
||||
if (!_isScaleSet) {
|
||||
for (auto &joint: _flowJointData) {
|
||||
joint.second._initialLength = joint.second._length / _scale;
|
||||
}
|
||||
_isScaleSet = true;
|
||||
}
|
||||
_lastScale = _scale;
|
||||
_collisionSystem.setScale(_scale);
|
||||
for (int i = 0; i < _jointThreads.size(); i++) {
|
||||
for (int j = 0; j < _jointThreads[i]._joints.size(); j++) {
|
||||
auto &joint = _flowJointData[_jointThreads[i]._joints[j]];
|
||||
joint._node._settings._radius = joint._node._initialRadius * _scale;
|
||||
joint._length = joint._initialLength * _scale;
|
||||
}
|
||||
_jointThreads[i].resetLength();
|
||||
}
|
||||
}
|
||||
updateJoints();
|
||||
for (size_t i = 0; i < _jointThreads.size(); i++) {
|
||||
size_t index = _invertThreadLoop ? _jointThreads.size() - 1 - i : i;
|
||||
|
@ -710,4 +751,21 @@ void Flow::setOthersCollision(const QUuid& otherId, int jointIndex, const glm::v
|
|||
settings._entityID = otherId;
|
||||
settings._radius = HAND_COLLISION_RADIUS;
|
||||
_collisionSystem.addCollisionSphere(jointIndex, settings, position, false, true);
|
||||
}
|
||||
|
||||
FlowPhysicsSettings Flow::getPhysicsSettingsForGroup(const QString& group) {
|
||||
for (auto &joint : _flowJointData) {
|
||||
if (joint.second._group.toUpper() == group.toUpper()) {
|
||||
return joint.second._node._settings;
|
||||
}
|
||||
}
|
||||
return FlowPhysicsSettings();
|
||||
}
|
||||
|
||||
void Flow::setPhysicsSettingsForGroup(const QString& group, const FlowPhysicsSettings& settings) {
|
||||
for (auto &joint : _flowJointData) {
|
||||
if (joint.second._group.toUpper() == group.toUpper()) {
|
||||
joint.second._node._settings = settings;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -155,7 +155,6 @@ public:
|
|||
FlowCollisionSystem() {};
|
||||
void addCollisionSphere(int jointIndex, const FlowCollisionSettings& settings, const glm::vec3& position = { 0.0f, 0.0f, 0.0f }, bool isSelfCollision = true, bool isTouch = false);
|
||||
FlowCollisionResult computeCollision(const std::vector<FlowCollisionResult> collisions);
|
||||
void setScale(float scale);
|
||||
|
||||
std::vector<FlowCollisionResult> checkFlowThreadCollisions(FlowThread* flowThread);
|
||||
|
||||
|
@ -169,6 +168,9 @@ public:
|
|||
void prepareCollisions();
|
||||
void resetCollisions();
|
||||
void resetOthersCollisions() { _othersCollisions.clear(); }
|
||||
void setScale(float scale);
|
||||
FlowCollisionSettings getCollisionSettingsByJoint(int jointIndex);
|
||||
void setCollisionSettingsByJoint(int jointIndex, const FlowCollisionSettings& settings);
|
||||
protected:
|
||||
std::vector<FlowCollisionSphere> _selfCollisions;
|
||||
std::vector<FlowCollisionSphere> _othersCollisions;
|
||||
|
@ -179,8 +181,7 @@ protected:
|
|||
class FlowNode {
|
||||
public:
|
||||
FlowNode() {};
|
||||
FlowNode(const glm::vec3& initialPosition, FlowPhysicsSettings settings) :
|
||||
_initialPosition(initialPosition), _previousPosition(initialPosition), _currentPosition(initialPosition){};
|
||||
FlowNode(const glm::vec3& initialPosition, FlowPhysicsSettings settings);
|
||||
|
||||
FlowPhysicsSettings _settings;
|
||||
glm::vec3 _initialPosition;
|
||||
|
@ -195,7 +196,6 @@ public:
|
|||
FlowCollisionResult _previousCollision;
|
||||
|
||||
float _initialRadius { 0.0f };
|
||||
float _scale{ 1.0f };
|
||||
|
||||
bool _anchored { false };
|
||||
bool _colliding { false };
|
||||
|
@ -210,7 +210,7 @@ public:
|
|||
class FlowJoint {
|
||||
public:
|
||||
FlowJoint() {};
|
||||
FlowJoint(int jointIndex, int parentIndex, int childIndex, const QString& name, const QString& group, float scale, const FlowPhysicsSettings& settings);
|
||||
FlowJoint(int jointIndex, int parentIndex, int childIndex, const QString& name, const QString& group, const FlowPhysicsSettings& settings);
|
||||
void setInitialData(const glm::vec3& initialPosition, const glm::vec3& initialTranslation, const glm::quat& initialRotation, const glm::vec3& parentPosition);
|
||||
void setUpdatedData(const glm::vec3& updatedPosition, const glm::vec3& updatedTranslation, const glm::quat& updatedRotation, const glm::vec3& parentPosition, const glm::quat& parentWorldRotation);
|
||||
void setRecoveryPosition(const glm::vec3& recoveryPosition);
|
||||
|
@ -241,13 +241,13 @@ public:
|
|||
glm::vec3 _translationDirection;
|
||||
float _scale { 1.0f };
|
||||
float _length { 0.0f };
|
||||
float _originalLength { 0.0f };
|
||||
float _initialLength { 0.0f };
|
||||
bool _applyRecovery { false };
|
||||
};
|
||||
|
||||
class FlowDummyJoint : public FlowJoint {
|
||||
public:
|
||||
FlowDummyJoint(const glm::vec3& initialPosition, int index, int parentIndex, int childIndex, float scale, FlowPhysicsSettings settings);
|
||||
FlowDummyJoint(const glm::vec3& initialPosition, int index, int parentIndex, int childIndex, FlowPhysicsSettings settings);
|
||||
};
|
||||
|
||||
|
||||
|
@ -277,6 +277,8 @@ public:
|
|||
class Flow {
|
||||
public:
|
||||
Flow(Rig* rig) { _rig = rig; };
|
||||
void init();
|
||||
bool isActive() { return _active; }
|
||||
void calculateConstraints();
|
||||
void update(float deltaTime);
|
||||
void setTransform(float scale, const glm::vec3& position, const glm::quat& rotation);
|
||||
|
@ -284,6 +286,8 @@ public:
|
|||
const std::vector<FlowThread>& getThreads() const { return _jointThreads; }
|
||||
void setOthersCollision(const QUuid& otherId, int jointIndex, const glm::vec3& position);
|
||||
FlowCollisionSystem& getCollisionSystem() { return _collisionSystem; }
|
||||
FlowPhysicsSettings getPhysicsSettingsForGroup(const QString& group);
|
||||
void setPhysicsSettingsForGroup(const QString& group, const FlowPhysicsSettings& settings);
|
||||
private:
|
||||
void setJoints();
|
||||
void cleanUp();
|
||||
|
@ -292,6 +296,7 @@ private:
|
|||
bool worldToJointPoint(const glm::vec3& position, const int jointIndex, glm::vec3& jointSpacePosition) const;
|
||||
Rig* _rig;
|
||||
float _scale { 1.0f };
|
||||
float _lastScale{ 1.0f };
|
||||
glm::vec3 _entityPosition;
|
||||
glm::quat _entityRotation;
|
||||
std::map<int, FlowJoint> _flowJointData;
|
||||
|
@ -300,6 +305,7 @@ private:
|
|||
FlowCollisionSystem _collisionSystem;
|
||||
bool _initialized { false };
|
||||
bool _active { false };
|
||||
bool _isScaleSet { false };
|
||||
int _deltaTime { 0 };
|
||||
int _deltaTimeLimit { 4000000 };
|
||||
int _updates { 0 };
|
||||
|
|
|
@ -1905,7 +1905,9 @@ void Rig::initAnimGraph(const QUrl& url) {
|
|||
qCritical(animation) << "Error loading: code = " << error << "str =" << str;
|
||||
});
|
||||
connect(this, &Rig::onLoadComplete, [&]() {
|
||||
_flow.calculateConstraints();
|
||||
if (_flow.isActive()) {
|
||||
_flow.calculateConstraints();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -736,7 +736,6 @@ void Avatar::postUpdate(float deltaTime, const render::ScenePointer& scene) {
|
|||
// glm::vec3 pos2 = joints.find(joint.second._parentIndex) != joints.end() ? joints[joint.second._parentIndex]._node._currentPosition : getJointPosition(joint.second._parentIndex);
|
||||
// DebugDraw::getInstance().drawRay(pos1, pos2, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
DebugDraw::getInstance().drawRay(joints[index1]._node._currentPosition, joints[index2]._node._currentPosition, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue