Hand collisions working

This commit is contained in:
luiscuenca 2019-02-11 18:21:00 -07:00
parent 02646fb8a9
commit 942e9ccdfd
6 changed files with 162 additions and 164 deletions

View file

@ -271,6 +271,14 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
if (avatar->getSkeletonModel()->isLoaded()) {
// remove the orb if it is there
avatar->removeOrb();
if (avatar->getWorkloadRegion() == workload::Region::R1) {
auto &flow = _myAvatar->getSkeletonModel()->getRig().getFlow();
for (auto &handJointName : HAND_COLLISION_JOINTS) {
int jointIndex = avatar->getJointIndex(handJointName);
glm::vec3 position = avatar->getJointPosition(jointIndex);
flow.setOthersCollision(avatar->getID(), jointIndex, position);
}
}
if (avatar->needsPhysicsUpdate()) {
_avatarsToChangeInPhysics.insert(avatar);
}

View file

@ -365,7 +365,6 @@ void OtherAvatar::simulate(float deltaTime, bool inView) {
PROFILE_RANGE(simulation, "grabs");
applyGrabChanges();
}
updateFadingStatus();
}

View file

@ -50,6 +50,7 @@ public:
void rebuildCollisionShape() override;
void setWorkloadRegion(uint8_t region);
uint8_t getWorkloadRegion() { return _workloadRegion; }
bool shouldBeInPhysicsSimulation() const;
bool needsPhysicsUpdate() const;

View file

@ -12,11 +12,23 @@
#include "Rig.h"
#include "AnimSkeleton.h"
FlowCollisionSphere::FlowCollisionSphere(const int& jointIndex, const FlowCollisionSettings& settings) {
const std::map<QString, FlowPhysicsSettings> PRESET_FLOW_DATA = { { "hair", FlowPhysicsSettings() },
{ "skirt", FlowPhysicsSettings(true, 1.0f, DEFAULT_GRAVITY, 0.65f, 0.8f, 0.45f, 0.01f) },
{ "breast", FlowPhysicsSettings(true, 1.0f, DEFAULT_GRAVITY, 0.65f, 0.8f, 0.45f, 0.01f) } };
const std::map<QString, FlowCollisionSettings> PRESET_COLLISION_DATA = {
{ "Spine2", FlowCollisionSettings(QUuid(), FlowCollisionType::CollisionSphere, glm::vec3(0.0f, 0.2f, 0.0f), 0.14f) },
{ "LeftArm", FlowCollisionSettings(QUuid(), FlowCollisionType::CollisionSphere, glm::vec3(0.0f, 0.02f, 0.0f), 0.05f) },
{ "RightArm", FlowCollisionSettings(QUuid(), FlowCollisionType::CollisionSphere, glm::vec3(0.0f, 0.02f, 0.0f), 0.05f) },
{ "HeadTop_End", FlowCollisionSettings(QUuid(), FlowCollisionType::CollisionSphere, glm::vec3(0.0f, -0.15f, 0.0f), 0.09f) }
};
FlowCollisionSphere::FlowCollisionSphere(const int& jointIndex, const FlowCollisionSettings& settings, bool isTouch) {
_jointIndex = jointIndex;
_radius = _initialRadius = settings._radius;
_offset = _initialOffset = settings._offset;
_entityID = settings._entityID;
_isTouch = isTouch;
}
FlowCollisionResult FlowCollisionSphere::computeSphereCollision(const glm::vec3& point, float radius) const {
@ -51,53 +63,21 @@ FlowCollisionResult FlowCollisionSphere::checkSegmentCollision(const glm::vec3&
return result;
}
void FlowCollisionSphere::update() {
// TODO
// Fill this
void FlowCollisionSystem::addCollisionSphere(int jointIndex, const FlowCollisionSettings& settings, const glm::vec3& position, bool isSelfCollision, bool isTouch) {
auto collision = FlowCollisionSphere(jointIndex, settings, isTouch);
collision.setPosition(position);
if (isSelfCollision) {
_selfCollisions.push_back(collision);
} else {
_othersCollisions.push_back(collision);
}
};
void FlowCollisionSystem::resetCollisions() {
_allCollisions.clear();
_othersCollisions.clear();
_selfCollisions.clear();
}
void FlowCollisionSystem::addCollisionSphere(int jointIndex, const FlowCollisionSettings& settings) {
_collisionSpheres.push_back(FlowCollisionSphere(jointIndex, settings));
};
void FlowCollisionSystem::addCollisionShape(int jointIndex, const FlowCollisionSettings& settings) {
auto name = JOINT_COLLISION_PREFIX + jointIndex;
switch (settings._type) {
case FlowCollisionType::CollisionSphere:
addCollisionSphere(jointIndex, settings);
break;
default:
break;
}
};
bool FlowCollisionSystem::addCollisionToJoint(int jointIndex) {
if (_collisionSpheres.size() >= COLLISION_SHAPES_LIMIT) {
return false;
}
int collisionIndex = findCollisionWithJoint(jointIndex);
if (collisionIndex == -1) {
addCollisionShape(jointIndex, FlowCollisionSettings());
return true;
}
else {
return false;
}
};
void FlowCollisionSystem::removeCollisionFromJoint(int jointIndex) {
int collisionIndex = findCollisionWithJoint(jointIndex);
if (collisionIndex > -1) {
_collisionSpheres.erase(_collisionSpheres.begin() + collisionIndex);
}
};
void FlowCollisionSystem::update() {
for (size_t i = 0; i < _collisionSpheres.size(); i++) {
_collisionSpheres[i].update();
}
};
FlowCollisionResult FlowCollisionSystem::computeCollision(const std::vector<FlowCollisionResult> collisions) {
FlowCollisionResult result;
if (collisions.size() > 1) {
@ -123,50 +103,51 @@ FlowCollisionResult FlowCollisionSystem::computeCollision(const std::vector<Flow
void FlowCollisionSystem::setScale(float scale) {
_scale = scale;
for (size_t j = 0; j < _collisionSpheres.size(); j++) {
_collisionSpheres[j]._radius = _collisionSpheres[j]._initialRadius * scale;
_collisionSpheres[j]._offset = _collisionSpheres[j]._initialOffset * scale;
for (size_t j = 0; j < _selfCollisions.size(); j++) {
_selfCollisions[j]._radius = _selfCollisions[j]._initialRadius * scale;
_selfCollisions[j]._offset = _selfCollisions[j]._initialOffset * scale;
}
};
std::vector<FlowCollisionResult> FlowCollisionSystem::checkFlowThreadCollisions(FlowThread* flowThread, bool checkSegments) {
std::vector<FlowCollisionResult> FlowCollisionSystem::checkFlowThreadCollisions(FlowThread* flowThread) {
std::vector<std::vector<FlowCollisionResult>> FlowThreadResults;
FlowThreadResults.resize(flowThread->_joints.size());
for (size_t j = 0; j < _collisionSpheres.size(); j++) {
FlowCollisionSphere &sphere = _collisionSpheres[j];
for (size_t j = 0; j < _allCollisions.size(); j++) {
FlowCollisionSphere &sphere = _allCollisions[j];
FlowCollisionResult rootCollision = sphere.computeSphereCollision(flowThread->_positions[0], flowThread->_radius);
std::vector<FlowCollisionResult> collisionData = { rootCollision };
bool tooFar = rootCollision._distance >(flowThread->_length + rootCollision._radius);
FlowCollisionResult nextCollision;
if (!tooFar) {
if (checkSegments) {
if (sphere._isTouch) {
for (size_t i = 1; i < flowThread->_joints.size(); i++) {
auto prevCollision = collisionData[i - 1];
nextCollision = _collisionSpheres[j].computeSphereCollision(flowThread->_positions[i], flowThread->_radius);
nextCollision = _allCollisions[j].computeSphereCollision(flowThread->_positions[i], flowThread->_radius);
collisionData.push_back(nextCollision);
bool isTouching = false;
if (prevCollision._offset > 0.0f) {
if (i == 1) {
FlowThreadResults[i - 1].push_back(prevCollision);
isTouching = true;
}
}
else if (nextCollision._offset > 0.0f) {
} else if (nextCollision._offset > 0.0f) {
FlowThreadResults[i].push_back(nextCollision);
}
else {
FlowCollisionResult segmentCollision = _collisionSpheres[j].checkSegmentCollision(flowThread->_positions[i - 1], flowThread->_positions[i], prevCollision, nextCollision);
isTouching = true;
} else {
FlowCollisionResult segmentCollision = _allCollisions[j].checkSegmentCollision(flowThread->_positions[i - 1], flowThread->_positions[i], prevCollision, nextCollision);
if (segmentCollision._offset > 0) {
FlowThreadResults[i - 1].push_back(segmentCollision);
FlowThreadResults[i].push_back(segmentCollision);
isTouching = true;
}
}
}
}
else {
} else {
if (rootCollision._offset > 0.0f) {
FlowThreadResults[0].push_back(rootCollision);
}
for (size_t i = 1; i < flowThread->_joints.size(); i++) {
nextCollision = _collisionSpheres[j].computeSphereCollision(flowThread->_positions[i], flowThread->_radius);
nextCollision = _allCollisions[j].computeSphereCollision(flowThread->_positions[i], flowThread->_radius);
if (nextCollision._offset > 0.0f) {
FlowThreadResults[i].push_back(nextCollision);
}
@ -182,40 +163,49 @@ std::vector<FlowCollisionResult> FlowCollisionSystem::checkFlowThreadCollisions(
return results;
};
int FlowCollisionSystem::findCollisionWithJoint(int jointIndex) {
for (size_t i = 0; i < _collisionSpheres.size(); i++) {
if (_collisionSpheres[i]._jointIndex == jointIndex) {
int FlowCollisionSystem::findSelfCollisionWithJoint(int jointIndex) {
for (size_t i = 0; i < _selfCollisions.size(); i++) {
if (_selfCollisions[i]._jointIndex == jointIndex) {
return (int)i;
}
}
return -1;
};
void FlowCollisionSystem::modifyCollisionRadius(int jointIndex, float radius) {
int collisionIndex = findCollisionWithJoint(jointIndex);
void FlowCollisionSystem::modifySelfCollisionRadius(int jointIndex, float radius) {
int collisionIndex = findSelfCollisionWithJoint(jointIndex);
if (collisionIndex > -1) {
_collisionSpheres[collisionIndex]._initialRadius = radius;
_collisionSpheres[collisionIndex]._radius = _scale * radius;
_selfCollisions[collisionIndex]._initialRadius = radius;
_selfCollisions[collisionIndex]._radius = _scale * radius;
}
};
void FlowCollisionSystem::modifyCollisionYOffset(int jointIndex, float offset) {
int collisionIndex = findCollisionWithJoint(jointIndex);
void FlowCollisionSystem::modifySelfCollisionYOffset(int jointIndex, float offset) {
int collisionIndex = findSelfCollisionWithJoint(jointIndex);
if (collisionIndex > -1) {
auto currentOffset = _collisionSpheres[collisionIndex]._offset;
_collisionSpheres[collisionIndex]._initialOffset = glm::vec3(currentOffset.x, offset, currentOffset.z);
_collisionSpheres[collisionIndex]._offset = _collisionSpheres[collisionIndex]._initialOffset * _scale;
auto currentOffset = _selfCollisions[collisionIndex]._offset;
_selfCollisions[collisionIndex]._initialOffset = glm::vec3(currentOffset.x, offset, currentOffset.z);
_selfCollisions[collisionIndex]._offset = _selfCollisions[collisionIndex]._initialOffset * _scale;
}
};
void FlowCollisionSystem::modifyCollisionOffset(int jointIndex, const glm::vec3& offset) {
int collisionIndex = findCollisionWithJoint(jointIndex);
void FlowCollisionSystem::modifySelfCollisionOffset(int jointIndex, const glm::vec3& offset) {
int collisionIndex = findSelfCollisionWithJoint(jointIndex);
if (collisionIndex > -1) {
_collisionSpheres[collisionIndex]._initialOffset = offset;
_collisionSpheres[collisionIndex]._offset = _collisionSpheres[collisionIndex]._initialOffset * _scale;
_selfCollisions[collisionIndex]._initialOffset = offset;
_selfCollisions[collisionIndex]._offset = _selfCollisions[collisionIndex]._initialOffset * _scale;
}
};
void FlowCollisionSystem::prepareCollisions() {
_allCollisions.clear();
_allCollisions.resize(_selfCollisions.size() + _othersCollisions.size());
std::copy(_selfCollisions.begin(), _selfCollisions.begin() + _selfCollisions.size(), _allCollisions.begin());
std::copy(_othersCollisions.begin(), _othersCollisions.begin() + _othersCollisions.size(), _allCollisions.begin() + _selfCollisions.size());
_othersCollisions.clear();
}
void FlowNode::update(const glm::vec3& accelerationOffset) {
_acceleration = glm::vec3(0.0f, _settings._gravity, 0.0f);
_previousVelocity = _currentVelocity;
@ -263,16 +253,6 @@ void FlowNode::solveCollisions(const FlowCollisionResult& collision) {
}
};
void FlowNode::apply(const QString& name, bool forceRendering) {
// TODO
// Render here ??
/*
jointDebug.setDebugSphere(name, self.currentPosition, 2 * self.radius, { red: self.collision && self.collision.collisionCount > 1 ? 0 : 255,
green : self.colliding ? 0 : 255,
blue : 0 }, forceRendering);
*/
};
FlowJoint::FlowJoint(int jointIndex, int parentIndex, int childIndex, const QString& name, const QString& group, float scale, const FlowPhysicsSettings& settings) {
_index = jointIndex;
_name = name;
@ -347,7 +327,7 @@ void FlowThread::resetLength() {
_length = 0.0f;
for (size_t i = 1; i < _joints.size(); i++) {
int index = _joints[i];
_length += (*_jointsPointer)[index]._length;
_length += _jointsPointer->at(index)._length;
}
}
@ -356,12 +336,12 @@ void FlowThread::computeFlowThread(int rootIndex) {
if (_jointsPointer->size() == 0) {
return;
}
int childIndex = (*_jointsPointer)[parentIndex]._childIndex;
int childIndex = _jointsPointer->at(parentIndex)._childIndex;
std::vector<int> indexes = { parentIndex };
for (size_t i = 0; i < _jointsPointer->size(); i++) {
if (childIndex > -1) {
indexes.push_back(childIndex);
childIndex = (*_jointsPointer)[childIndex]._childIndex;
childIndex = _jointsPointer->at(childIndex)._childIndex;
} else {
break;
}
@ -370,20 +350,20 @@ void FlowThread::computeFlowThread(int rootIndex) {
int index = indexes[i];
_joints.push_back(index);
if (i > 0) {
_length += (*_jointsPointer)[index]._length;
_length += _jointsPointer->at(index)._length;
}
}
};
void FlowThread::computeRecovery() {
int parentIndex = _joints[0];
auto parentJoint = (*_jointsPointer)[parentIndex];
(*_jointsPointer)[parentIndex]._recoveryPosition = parentJoint._recoveryPosition = parentJoint._node._currentPosition;
auto parentJoint = _jointsPointer->at(parentIndex);
_jointsPointer->at(parentIndex)._recoveryPosition = parentJoint._recoveryPosition = parentJoint._node._currentPosition;
glm::quat parentRotation = parentJoint._parentWorldRotation * parentJoint._initialRotation;
for (size_t i = 1; i < _joints.size(); i++) {
auto joint = (*_jointsPointer)[_joints[i]];
auto joint = _jointsPointer->at(_joints[i]);
glm::quat rotation = i == 1 ? parentRotation : rotation * parentJoint._initialRotation;
(*_jointsPointer)[_joints[i]]._recoveryPosition = joint._recoveryPosition = parentJoint._recoveryPosition + (rotation * (joint._initialTranslation * 0.01f));
_jointsPointer->at(_joints[i])._recoveryPosition = joint._recoveryPosition = parentJoint._recoveryPosition + (rotation * (joint._initialTranslation * 0.01f));
parentJoint = joint;
}
};
@ -391,10 +371,10 @@ void FlowThread::computeRecovery() {
void FlowThread::update() {
if (getActive()) {
_positions.clear();
_radius = (*_jointsPointer)[_joints[0]]._node._settings._radius;
_radius = _jointsPointer->at(_joints[0])._node._settings._radius;
computeRecovery();
for (size_t i = 0; i < _joints.size(); i++) {
auto &joint = (*_jointsPointer)[_joints[i]];
auto &joint = _jointsPointer->at(_joints[i]);
joint.update();
_positions.push_back(joint._node._currentPosition);
}
@ -404,20 +384,16 @@ void FlowThread::update() {
void FlowThread::solve(bool useCollisions, FlowCollisionSystem& collisionSystem) {
if (getActive()) {
if (useCollisions) {
auto bodyCollisions = collisionSystem.checkFlowThreadCollisions(this, false);
auto bodyCollisions = collisionSystem.checkFlowThreadCollisions(this);
int handTouchedJoint = -1;
for (size_t i = 0; i < _joints.size(); i++) {
int index = _joints[i];
if (bodyCollisions[i]._offset > 0.0f) {
(*_jointsPointer)[index].solve(bodyCollisions[i]);
} else {
(*_jointsPointer)[index].solve(FlowCollisionResult());
}
_jointsPointer->at(index).solve(bodyCollisions[i]);
}
} else {
for (size_t i = 0; i < _joints.size(); i++) {
int index = _joints[i];
(*_jointsPointer)[index].solve(FlowCollisionResult());
_jointsPointer->at(index).solve(FlowCollisionResult());
}
}
}
@ -428,8 +404,8 @@ void FlowThread::computeJointRotations() {
auto pos0 = _rootFramePositions[0];
auto pos1 = _rootFramePositions[1];
auto joint0 = (*_jointsPointer)[_joints[0]];
auto joint1 = (*_jointsPointer)[_joints[1]];
auto joint0 = _jointsPointer->at(_joints[0]);
auto joint1 = _jointsPointer->at(_joints[1]);
auto initial_pos1 = pos0 + (joint0._initialRotation * (joint1._initialTranslation * 0.01f));
@ -438,10 +414,10 @@ void FlowThread::computeJointRotations() {
auto delta = rotationBetween(vec0, vec1);
joint0._currentRotation = (*_jointsPointer)[_joints[0]]._currentRotation = delta * joint0._initialRotation;
joint0._currentRotation = _jointsPointer->at(_joints[0])._currentRotation = delta * joint0._initialRotation;
for (size_t i = 1; i < _joints.size() - 1; i++) {
auto nextJoint = (*_jointsPointer)[_joints[i + 1]];
auto nextJoint = _jointsPointer->at(_joints[i + 1]);
for (size_t j = i; j < _joints.size(); j++) {
_rootFramePositions[j] = glm::inverse(joint0._currentRotation) * _rootFramePositions[j] - (joint0._initialTranslation * 0.01f);
}
@ -454,7 +430,7 @@ void FlowThread::computeJointRotations() {
delta = rotationBetween(vec0, vec1);
joint1._currentRotation = (*_jointsPointer)[joint1._index]._currentRotation = delta * joint1._initialRotation;
joint1._currentRotation = _jointsPointer->at(joint1._index)._currentRotation = delta * joint1._initialRotation;
joint0 = joint1;
joint1 = nextJoint;
}
@ -468,7 +444,7 @@ void FlowThread::apply() {
};
bool FlowThread::getActive() {
return (*_jointsPointer)[_joints[0]]._node._active;
return _jointsPointer->at(_joints[0])._node._active;
};
void Flow::setRig(Rig* rig) {
@ -484,12 +460,17 @@ void Flow::calculateConstraints() {
auto flowPrefix = FLOW_JOINT_PREFIX.toUpper();
auto simPrefix = SIM_JOINT_PREFIX.toUpper();
auto skeleton = _rig->getAnimSkeleton();
std::vector<int> handsIndices;
_collisionSystem.resetCollisions();
if (skeleton) {
for (int i = 0; i < skeleton->getNumJoints(); i++) {
auto name = skeleton->getJointName(i);
if (name == "RightHand") {
rightHandIndex = i;
}
if (std::find(HAND_COLLISION_JOINTS.begin(), HAND_COLLISION_JOINTS.end(), name) != HAND_COLLISION_JOINTS.end()) {
handsIndices.push_back(i);
}
auto parentIndex = skeleton->getParentIndex(i);
if (parentIndex == -1) {
continue;
@ -533,7 +514,7 @@ void Flow::calculateConstraints() {
}
} else {
if (PRESET_COLLISION_DATA.find(name) != PRESET_COLLISION_DATA.end()) {
_collisionSystem.addCollisionShape(i, PRESET_COLLISION_DATA.at(name));
_collisionSystem.addCollisionSphere(i, PRESET_COLLISION_DATA.at(name));
}
}
if (isFlowJoint || isSimJoint) {
@ -591,8 +572,6 @@ void Flow::calculateConstraints() {
if (_jointThreads.size() == 0) {
_rig->clearJointStates();
}
if (SHOW_DUMMY_JOINTS && rightHandIndex > -1) {
int jointCount = (int)_flowJointData.size();
int extraIndex = (int)_flowJointData.size();
@ -611,6 +590,13 @@ void Flow::calculateConstraints() {
auto extraThread = FlowThread(jointCount, &_flowJointData);
_jointThreads.push_back(extraThread);
}
if (handsIndices.size() > 0) {
FlowCollisionSettings handSettings;
handSettings._radius = HAND_COLLISION_RADIUS;
for (size_t i = 0; i < handsIndices.size(); i++) {
_collisionSystem.addCollisionSphere(handsIndices[i], handSettings, glm::vec3(), true, true);
}
}
_initialized = _jointThreads.size() > 0;
}
@ -633,12 +619,10 @@ void Flow::setTransform(float scale, const glm::vec3& position, const glm::quat&
}
void Flow::update() {
QElapsedTimer _timer;
_timer.start();
if (_initialized && _active) {
updateJoints();
if (USE_COLLISIONS) {
_collisionSystem.update();
}
int count = 0;
for (auto &thread : _jointThreads) {
thread.update();
@ -650,11 +634,12 @@ void Flow::update() {
}
setJoints();
}
_elapsedTime = ((1.0 - _tau) * _elapsedTime + _tau * _timer.nsecsElapsed());
_deltaTime += _elapsedTime;
_deltaTime += _timer.nsecsElapsed();
_updates++;
if (_deltaTime > _deltaTimeLimit) {
qDebug() << "Flow C++ update" << _elapsedTime;
_deltaTime = 0.0;
qDebug() << "Flow C++ update " << _deltaTime / _updates << " nanoSeconds";
_deltaTime = 0;
_updates = 0;
}
}
@ -697,10 +682,15 @@ void Flow::updateJoints() {
_rig->getJointRotationInWorldFrame(jointData.second._parentIndex, parentWorldRotation, _entityRotation);
jointData.second.setUpdatedData(jointPosition, jointTranslation, jointRotation, parentPosition, parentWorldRotation);
}
auto &collisions = _collisionSystem.getCollisions();
for (auto &collision : collisions) {
auto &selfCollisions = _collisionSystem.getSelfCollisions();
for (auto &collision : selfCollisions) {
glm::quat jointRotation;
_rig->getJointPositionInWorldFrame(collision._jointIndex, collision._position, _entityPosition, _entityRotation);
_rig->getJointRotationInWorldFrame(collision._jointIndex, jointRotation, _entityRotation);
glm::vec3 worldOffset = jointRotation * collision._offset;
collision._position = collision._position + worldOffset;
}
_collisionSystem.prepareCollisions();
}
void Flow::setJoints() {
@ -712,3 +702,10 @@ void Flow::setJoints() {
}
}
}
void Flow::setOthersCollision(const QUuid& otherId, int jointIndex, const glm::vec3& position) {
FlowCollisionSettings settings;
settings._entityID = otherId;
settings._radius = HAND_COLLISION_RADIUS;
_collisionSystem.addCollisionSphere(jointIndex, settings, position, false, true);
}

View file

@ -39,6 +39,8 @@ const float HAPTIC_THRESHOLD = 40.0f;
const QString FLOW_JOINT_PREFIX = "flow";
const QString SIM_JOINT_PREFIX = "sim";
const std::vector<QString> HAND_COLLISION_JOINTS = { "RightHandMiddle1", "RightHandThumb3", "LeftHandMiddle1", "LeftHandThumb3", "RightHandMiddle3", "LeftHandMiddle3" };
const QString JOINT_COLLISION_PREFIX = "joint_";
const QString HAND_COLLISION_PREFIX = "hand_";
const float HAND_COLLISION_RADIUS = 0.03f;
@ -100,18 +102,6 @@ struct FlowCollisionSettings {
const FlowPhysicsSettings DEFAULT_JOINT_SETTINGS;
const std::map<QString, FlowPhysicsSettings> PRESET_FLOW_DATA = { {"hair", FlowPhysicsSettings()},
{"skirt", FlowPhysicsSettings(true, 1.0f, DEFAULT_GRAVITY, 0.65f, 0.8f, 0.45f, 0.01f)},
{"breast", FlowPhysicsSettings(true, 1.0f, DEFAULT_GRAVITY, 0.65f, 0.8f, 0.45f, 0.01f)} };
const std::map<QString, FlowCollisionSettings> PRESET_COLLISION_DATA = {
{ "Head", FlowCollisionSettings(QUuid(), FlowCollisionType::CollisionSphere, glm::vec3(0.0f, 0.06f, 0.0f), 0.08f)},
{ "LeftArm", FlowCollisionSettings(QUuid(), FlowCollisionType::CollisionSphere, glm::vec3(0.0f, 0.02f, 0.0f), 0.05f) },
{ "Head", FlowCollisionSettings(QUuid(), FlowCollisionType::CollisionSphere, glm::vec3(0.0f, 0.04f, 0.0f), 0.0f) }
};
const std::vector<QString> HAND_COLLISION_JOINTS = { "RightHandMiddle1", "RightHandThumb3", "LeftHandMiddle1", "LeftHandThumb3", "RightHandMiddle3", "LeftHandMiddle3" };
struct FlowJointInfo {
FlowJointInfo() {};
FlowJointInfo(int index, int parentIndex, int childIndex, const QString& name) {
@ -138,19 +128,22 @@ struct FlowCollisionResult {
class FlowCollisionSphere {
public:
FlowCollisionSphere() {};
FlowCollisionSphere(const int& jointIndex, const FlowCollisionSettings& settings);
FlowCollisionSphere(const int& jointIndex, const FlowCollisionSettings& settings, bool isTouch = false);
void setPosition(const glm::vec3& position) { _position = position; }
FlowCollisionResult computeSphereCollision(const glm::vec3& point, float radius) const;
FlowCollisionResult checkSegmentCollision(const glm::vec3& point1, const glm::vec3& point2, const FlowCollisionResult& collisionResult1, const FlowCollisionResult& collisionResult2);
void update();
QUuid _entityID;
int _jointIndex { -1 };
float _radius { 0.0f };
float _initialRadius{ 0.0f };
glm::vec3 _offset;
glm::vec3 _initialOffset;
glm::vec3 _position;
bool _isTouch { false };
int _jointIndex { -1 };
int collisionIndex { -1 };
float _radius { 0.0f };
float _initialRadius{ 0.0f };
};
class FlowThread;
@ -158,24 +151,26 @@ class FlowThread;
class FlowCollisionSystem {
public:
FlowCollisionSystem() {};
void addCollisionSphere(int jointIndex, const FlowCollisionSettings& settings);
void addCollisionShape(int jointIndex, const FlowCollisionSettings& settings);
bool addCollisionToJoint(int jointIndex);
void removeCollisionFromJoint(int jointIndex);
void update();
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, bool checkSegments);
std::vector<FlowCollisionResult> checkFlowThreadCollisions(FlowThread* flowThread);
int findCollisionWithJoint(int jointIndex);
void modifyCollisionRadius(int jointIndex, float radius);
void modifyCollisionYOffset(int jointIndex, float offset);
void modifyCollisionOffset(int jointIndex, const glm::vec3& offset);
int findSelfCollisionWithJoint(int jointIndex);
void modifySelfCollisionRadius(int jointIndex, float radius);
void modifySelfCollisionYOffset(int jointIndex, float offset);
void modifySelfCollisionOffset(int jointIndex, const glm::vec3& offset);
std::vector<FlowCollisionSphere>& getCollisions() { return _collisionSpheres; };
private:
std::vector<FlowCollisionSphere> _collisionSpheres;
std::vector<FlowCollisionSphere>& getSelfCollisions() { return _selfCollisions; };
void setOthersCollisions(const std::vector<FlowCollisionSphere>& othersCollisions) { _othersCollisions = othersCollisions; }
void prepareCollisions();
void resetCollisions();
void resetOthersCollisions() { _othersCollisions.clear(); }
protected:
std::vector<FlowCollisionSphere> _selfCollisions;
std::vector<FlowCollisionSphere> _othersCollisions;
std::vector<FlowCollisionSphere> _allCollisions;
float _scale{ 1.0f };
};
@ -208,7 +203,6 @@ public:
void solve(const glm::vec3& constrainPoint, float maxDistance, const FlowCollisionResult& collision);
void solveConstraints(const glm::vec3& constrainPoint, float maxDistance);
void solveCollisions(const FlowCollisionResult& collision);
void apply(const QString& name, bool forceRendering);
};
class FlowJoint {
@ -268,7 +262,7 @@ public:
void computeJointRotations();
void apply();
bool getActive();
void setRootFramePositions(const std::vector<glm::vec3>& rootFramePositions) { _rootFramePositions = rootFramePositions; };
void setRootFramePositions(const std::vector<glm::vec3>& rootFramePositions) { _rootFramePositions = rootFramePositions; }
std::vector<int> _joints;
std::vector<glm::vec3> _positions;
@ -276,7 +270,6 @@ public:
float _length{ 0.0f };
std::map<int, FlowJoint>* _jointsPointer;
std::vector<glm::vec3> _rootFramePositions;
};
class Flow {
@ -288,6 +281,8 @@ public:
void setTransform(float scale, const glm::vec3& position, const glm::quat& rotation);
const std::map<int, FlowJoint>& getJoints() const { return _flowJointData; }
const std::vector<FlowThread>& getThreads() const { return _jointThreads; }
void setOthersCollision(const QUuid& otherId, int jointIndex, const glm::vec3& position);
FlowCollisionSystem& getCollisionSystem() { return _collisionSystem; }
private:
void setJoints();
void cleanUp();
@ -305,11 +300,9 @@ private:
FlowCollisionSystem _collisionSystem;
bool _initialized { false };
bool _active { false };
int _deltaTime{ 0 };
int _deltaTimeLimit{ 4000 };
int _elapsedTime{ 0 };
float _tau = 0.1f;
QElapsedTimer _timer;
int _deltaTime { 0 };
int _deltaTimeLimit { 4000000 };
int _updates { 0 };
};
#endif // hifi_Flow_h

View file

@ -235,7 +235,7 @@ public:
const AnimVariantMap& getAnimVars() const { return _lastAnimVars; }
const AnimContext::DebugStateMachineMap& getStateMachineMap() const { return _lastContext.getStateMachineMap(); }
void computeFlowSkeleton() { _flow.calculateConstraints(); }
const Flow& getFlow() const { return _flow; }
Flow& getFlow() { return _flow; }
signals:
void onLoadComplete();