mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 17:24:24 +02:00
Add avatar joints filter to intersection calculation
This commit is contained in:
parent
67cc5bd7f2
commit
2158e084d4
6 changed files with 94 additions and 51 deletions
|
@ -640,23 +640,27 @@ AvatarSharedPointer AvatarManager::getAvatarBySessionID(const QUuid& sessionID)
|
||||||
|
|
||||||
RayToAvatarIntersectionResult AvatarManager::findRayIntersection(const PickRay& ray,
|
RayToAvatarIntersectionResult AvatarManager::findRayIntersection(const PickRay& ray,
|
||||||
const QScriptValue& avatarIdsToInclude,
|
const QScriptValue& avatarIdsToInclude,
|
||||||
const QScriptValue& avatarIdsToDiscard) {
|
const QScriptValue& avatarIdsToDiscard,
|
||||||
|
const QScriptValue& jointIndicesToFilter) {
|
||||||
QVector<EntityItemID> avatarsToInclude = qVectorEntityItemIDFromScriptValue(avatarIdsToInclude);
|
QVector<EntityItemID> avatarsToInclude = qVectorEntityItemIDFromScriptValue(avatarIdsToInclude);
|
||||||
QVector<EntityItemID> avatarsToDiscard = qVectorEntityItemIDFromScriptValue(avatarIdsToDiscard);
|
QVector<EntityItemID> avatarsToDiscard = qVectorEntityItemIDFromScriptValue(avatarIdsToDiscard);
|
||||||
|
QVector<uint> jointsToFilter;
|
||||||
return findRayIntersectionVector(ray, avatarsToInclude, avatarsToDiscard);
|
qVectorIntFromScriptValue(jointIndicesToFilter, jointsToFilter);
|
||||||
|
return findRayIntersectionVector(ray, avatarsToInclude, avatarsToDiscard, jointsToFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const PickRay& ray,
|
RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const PickRay& ray,
|
||||||
const QVector<EntityItemID>& avatarsToInclude,
|
const QVector<EntityItemID>& avatarsToInclude,
|
||||||
const QVector<EntityItemID>& avatarsToDiscard) {
|
const QVector<EntityItemID>& avatarsToDiscard,
|
||||||
|
const QVector<uint>& jointIndicesToFilter) {
|
||||||
RayToAvatarIntersectionResult result;
|
RayToAvatarIntersectionResult result;
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
BLOCKING_INVOKE_METHOD(const_cast<AvatarManager*>(this), "findRayIntersectionVector",
|
BLOCKING_INVOKE_METHOD(const_cast<AvatarManager*>(this), "findRayIntersectionVector",
|
||||||
Q_RETURN_ARG(RayToAvatarIntersectionResult, result),
|
Q_RETURN_ARG(RayToAvatarIntersectionResult, result),
|
||||||
Q_ARG(const PickRay&, ray),
|
Q_ARG(const PickRay&, ray),
|
||||||
Q_ARG(const QVector<EntityItemID>&, avatarsToInclude),
|
Q_ARG(const QVector<EntityItemID>&, avatarsToInclude),
|
||||||
Q_ARG(const QVector<EntityItemID>&, avatarsToDiscard));
|
Q_ARG(const QVector<EntityItemID>&, avatarsToDiscard),
|
||||||
|
Q_ARG(const QVector<uint>&, jointIndicesToFilter));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -672,55 +676,80 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const Pic
|
||||||
|
|
||||||
if (physicsResults.size() > 0) {
|
if (physicsResults.size() > 0) {
|
||||||
MyCharacterController::RayAvatarResult rayAvatarResult;
|
MyCharacterController::RayAvatarResult rayAvatarResult;
|
||||||
|
AvatarPointer avatar = nullptr;
|
||||||
for (auto &hit : physicsResults) {
|
for (auto &hit : physicsResults) {
|
||||||
if ((avatarsToInclude.size() > 0 && !avatarsToInclude.contains(hit._intersectWithAvatar)) ||
|
auto avatarID = hit._intersectWithAvatar;
|
||||||
(avatarsToDiscard.size() > 0 && avatarsToDiscard.contains(hit._intersectWithAvatar))) {
|
bool skipThisAvatar = (avatarsToInclude.size() > 0 && !avatarsToInclude.contains(avatarID)) ||
|
||||||
|
(avatarsToDiscard.size() > 0 && avatarsToDiscard.contains(avatarID)) && jointIndicesToFilter.size() == 0;
|
||||||
|
if (skipThisAvatar) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!hit._isBound) {
|
if (!(_myAvatar->getSessionUUID() == avatarID)) {
|
||||||
rayAvatarResult = hit;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
auto avatarMap = getHashCopy();
|
auto avatarMap = getHashCopy();
|
||||||
auto avatarID = hit._intersectWithAvatar;
|
|
||||||
AvatarHash::iterator itr = avatarMap.find(avatarID);
|
AvatarHash::iterator itr = avatarMap.find(avatarID);
|
||||||
if (itr != avatarMap.end()) {
|
if (itr != avatarMap.end()) {
|
||||||
const auto& avatar = std::static_pointer_cast<Avatar>(*itr);
|
avatar = std::static_pointer_cast<Avatar>(*itr);
|
||||||
auto &multiSpheres = avatar->getMultiSphereShapes();
|
}
|
||||||
if (multiSpheres.size() > 0) {
|
} else {
|
||||||
std::vector<MyCharacterController::RayAvatarResult> boxHits;
|
avatar = _myAvatar;
|
||||||
for (size_t i = 0; i < hit._boundJoints.size(); i++) {
|
}
|
||||||
assert(hit._boundJoints[i] < multiSpheres.size());
|
QVector<int> jointsToDiscard;
|
||||||
auto &mSphere = multiSpheres[hit._boundJoints[i]];
|
if (avatar && jointIndicesToFilter.size() > 0) {
|
||||||
if (mSphere.isValid()) {
|
int jointCount = avatar->getJointCount();
|
||||||
float boundDistance = FLT_MAX;
|
if (avatarsToInclude.size() > 0 && avatarsToInclude.contains(avatarID)) {
|
||||||
BoxFace face;
|
for (int i = 0; i < jointCount; i++) {
|
||||||
glm::vec3 surfaceNormal;
|
if (!jointIndicesToFilter.contains(i)) {
|
||||||
auto &bbox = mSphere.getBoundingBox();
|
jointsToDiscard.push_back(i);
|
||||||
if (bbox.findRayIntersection(ray.origin, ray.direction, rayDirectionInv, boundDistance, face, surfaceNormal)) {
|
|
||||||
MyCharacterController::RayAvatarResult boxHit;
|
|
||||||
boxHit._distance = boundDistance;
|
|
||||||
boxHit._intersect = true;
|
|
||||||
boxHit._intersectionNormal = surfaceNormal;
|
|
||||||
boxHit._intersectionPoint = ray.origin + boundDistance * glm::normalize(ray.direction);
|
|
||||||
boxHit._intersectWithAvatar = avatarID;
|
|
||||||
boxHit._intersectWithJoint = mSphere.getJointIndex();
|
|
||||||
boxHits.push_back(boxHit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (boxHits.size() > 0) {
|
|
||||||
if (boxHits.size() > 1) {
|
|
||||||
std::sort(boxHits.begin(), boxHits.end(), [](const MyCharacterController::RayAvatarResult& hitA,
|
|
||||||
const MyCharacterController::RayAvatarResult& hitB) {
|
|
||||||
return hitA._distance < hitB._distance;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
rayAvatarResult = boxHits[0];
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (avatarsToDiscard.size() > 0 && avatarsToDiscard.contains(avatarID)) {
|
||||||
|
for (int i = 0; i < jointCount; i++) {
|
||||||
|
if (jointIndicesToFilter.contains(i)) {
|
||||||
|
jointsToDiscard.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hit._isBound) {
|
||||||
|
if (!jointsToDiscard.contains(hit._intersectWithJoint)) {
|
||||||
|
rayAvatarResult = hit;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (avatar) {
|
||||||
|
auto &multiSpheres = avatar->getMultiSphereShapes();
|
||||||
|
if (multiSpheres.size() > 0) {
|
||||||
|
std::vector<MyCharacterController::RayAvatarResult> boxHits;
|
||||||
|
for (size_t i = 0; i < hit._boundJoints.size(); i++) {
|
||||||
|
assert(hit._boundJoints[i] < multiSpheres.size());
|
||||||
|
auto &mSphere = multiSpheres[hit._boundJoints[i]];
|
||||||
|
if (mSphere.isValid() && !jointsToDiscard.contains(hit._boundJoints[i])) {
|
||||||
|
float boundDistance = FLT_MAX;
|
||||||
|
BoxFace face;
|
||||||
|
glm::vec3 surfaceNormal;
|
||||||
|
auto &bbox = mSphere.getBoundingBox();
|
||||||
|
if (bbox.findRayIntersection(ray.origin, ray.direction, rayDirectionInv, boundDistance, face, surfaceNormal)) {
|
||||||
|
MyCharacterController::RayAvatarResult boxHit;
|
||||||
|
boxHit._distance = boundDistance;
|
||||||
|
boxHit._intersect = true;
|
||||||
|
boxHit._intersectionNormal = surfaceNormal;
|
||||||
|
boxHit._intersectionPoint = ray.origin + boundDistance * glm::normalize(ray.direction);
|
||||||
|
boxHit._intersectWithAvatar = avatarID;
|
||||||
|
boxHit._intersectWithJoint = hit._intersectWithJoint;
|
||||||
|
boxHits.push_back(boxHit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (boxHits.size() > 0) {
|
||||||
|
if (boxHits.size() > 1) {
|
||||||
|
std::sort(boxHits.begin(), boxHits.end(), [](const MyCharacterController::RayAvatarResult& hitA,
|
||||||
|
const MyCharacterController::RayAvatarResult& hitB) {
|
||||||
|
return hitA._distance < hitB._distance;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
rayAvatarResult = boxHits[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rayAvatarResult._intersect) {
|
if (rayAvatarResult._intersect) {
|
||||||
|
|
|
@ -138,21 +138,25 @@ public:
|
||||||
* @param {PickRay} ray
|
* @param {PickRay} ray
|
||||||
* @param {Uuid[]} [avatarsToInclude=[]]
|
* @param {Uuid[]} [avatarsToInclude=[]]
|
||||||
* @param {Uuid[]} [avatarsToDiscard=[]]
|
* @param {Uuid[]} [avatarsToDiscard=[]]
|
||||||
|
* @param {uint[]} [jointIndicesToFilter=[] - If included/discarded avatars are provided only this joints corresponding to those avatars would be included/discarded. ]
|
||||||
* @returns {RayToAvatarIntersectionResult}
|
* @returns {RayToAvatarIntersectionResult}
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersection(const PickRay& ray,
|
Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersection(const PickRay& ray,
|
||||||
const QScriptValue& avatarIdsToInclude = QScriptValue(),
|
const QScriptValue& avatarIdsToInclude = QScriptValue(),
|
||||||
const QScriptValue& avatarIdsToDiscard = QScriptValue());
|
const QScriptValue& avatarIdsToDiscard = QScriptValue(),
|
||||||
|
const QScriptValue& jointIndicesToFilter = QScriptValue());
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function AvatarManager.findRayIntersectionVector
|
* @function AvatarManager.findRayIntersectionVector
|
||||||
* @param {PickRay} ray
|
* @param {PickRay} ray
|
||||||
* @param {Uuid[]} avatarsToInclude
|
* @param {Uuid[]} avatarsToInclude
|
||||||
* @param {Uuid[]} avatarsToDiscard
|
* @param {Uuid[]} avatarsToDiscard
|
||||||
|
* @param {uint[]} [jointIndicesToFilter=[] - If included/discarded avatars are provided only this joints corresponding to those avatars would be included/discarded. ]
|
||||||
* @returns {RayToAvatarIntersectionResult}
|
* @returns {RayToAvatarIntersectionResult}
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersectionVector(const PickRay& ray,
|
Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersectionVector(const PickRay& ray,
|
||||||
const QVector<EntityItemID>& avatarsToInclude,
|
const QVector<EntityItemID>& avatarsToInclude,
|
||||||
const QVector<EntityItemID>& avatarsToDiscard);
|
const QVector<EntityItemID>& avatarsToDiscard,
|
||||||
|
const QVector<uint>& jointIndicesToFilter);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @function AvatarManager.findParabolaIntersectionVector
|
* @function AvatarManager.findParabolaIntersectionVector
|
||||||
|
|
|
@ -182,7 +182,7 @@ void DetailedMotionState::setShape(const btCollisionShape* shape) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DetailedMotionState::forceActive() {
|
void DetailedMotionState::forceActive() {
|
||||||
if (_body) {
|
if (_body && !_body->isActive()) {
|
||||||
_body->setActivationState(ACTIVE_TAG);
|
_body->setActivationState(ACTIVE_TAG);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -360,6 +360,9 @@ btCollisionShape* MyCharacterController::createDetailedCollisionShapeForJoint(in
|
||||||
_avatar->computeDetailedShapeInfo(shapeInfo, jointIndex);
|
_avatar->computeDetailedShapeInfo(shapeInfo, jointIndex);
|
||||||
if (shapeInfo.getType() != SHAPE_TYPE_NONE) {
|
if (shapeInfo.getType() != SHAPE_TYPE_NONE) {
|
||||||
btCollisionShape* shape = const_cast<btCollisionShape*>(ObjectMotionState::getShapeManager()->getShape(shapeInfo));
|
btCollisionShape* shape = const_cast<btCollisionShape*>(ObjectMotionState::getShapeManager()->getShape(shapeInfo));
|
||||||
|
if (shape) {
|
||||||
|
shape->setMargin(0.001f);
|
||||||
|
}
|
||||||
return shape;
|
return shape;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -114,6 +114,9 @@ void OtherAvatar::updateSpaceProxy(workload::Transaction& transaction) const {
|
||||||
|
|
||||||
int OtherAvatar::parseDataFromBuffer(const QByteArray& buffer) {
|
int OtherAvatar::parseDataFromBuffer(const QByteArray& buffer) {
|
||||||
int32_t bytesRead = Avatar::parseDataFromBuffer(buffer);
|
int32_t bytesRead = Avatar::parseDataFromBuffer(buffer);
|
||||||
|
for (size_t i = 0; i < _detailedMotionStates.size(); i++) {
|
||||||
|
_detailedMotionStates[i]->forceActive();
|
||||||
|
}
|
||||||
if (_moving && _motionState) {
|
if (_moving && _motionState) {
|
||||||
_motionState->addDirtyFlags(Simulation::DIRTY_POSITION);
|
_motionState->addDirtyFlags(Simulation::DIRTY_POSITION);
|
||||||
}
|
}
|
||||||
|
@ -166,7 +169,11 @@ btCollisionShape* OtherAvatar::createCollisionShape(int jointIndex, bool& isBoun
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (shapeInfo.getType() != SHAPE_TYPE_NONE) {
|
if (shapeInfo.getType() != SHAPE_TYPE_NONE) {
|
||||||
return const_cast<btCollisionShape*>(ObjectMotionState::getShapeManager()->getShape(shapeInfo));
|
auto shape = const_cast<btCollisionShape*>(ObjectMotionState::getShapeManager()->getShape(shapeInfo));
|
||||||
|
if (shape) {
|
||||||
|
shape->setMargin(0.001f);
|
||||||
|
}
|
||||||
|
return shape;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ PickResultPointer RayPick::getOverlayIntersection(const PickRay& pick) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PickResultPointer RayPick::getAvatarIntersection(const PickRay& pick) {
|
PickResultPointer RayPick::getAvatarIntersection(const PickRay& pick) {
|
||||||
RayToAvatarIntersectionResult avatarRes = DependencyManager::get<AvatarManager>()->findRayIntersectionVector(pick, getIncludeItemsAs<EntityItemID>(), getIgnoreItemsAs<EntityItemID>());
|
RayToAvatarIntersectionResult avatarRes = DependencyManager::get<AvatarManager>()->findRayIntersectionVector(pick, getIncludeItemsAs<EntityItemID>(), getIgnoreItemsAs<EntityItemID>(), QVector<uint>());
|
||||||
if (avatarRes.intersects) {
|
if (avatarRes.intersects) {
|
||||||
return std::make_shared<RayPickResult>(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, pick, avatarRes.surfaceNormal, avatarRes.extraInfo);
|
return std::make_shared<RayPickResult>(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, pick, avatarRes.surfaceNormal, avatarRes.extraInfo);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue