set useFlow function

This commit is contained in:
luiscuenca 2019-02-14 18:30:37 -07:00
parent 05d50f32ba
commit 3e66bce112
6 changed files with 161 additions and 31 deletions

View file

@ -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);
}
}
}
}

View file

@ -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

View file

@ -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;
}
}
}

View file

@ -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 };

View file

@ -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();
}
});
}
}

View file

@ -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));
}
}
}