js call to ray-pick against avatars

This commit is contained in:
Seth Alves 2016-06-28 09:55:49 -07:00
parent cecd871c66
commit 4e70e8ed42
7 changed files with 101 additions and 0 deletions

View file

@ -1085,6 +1085,15 @@ void Avatar::computeShapeInfo(ShapeInfo& shapeInfo) {
shapeInfo.setOffset(uniformScale * _skeletonModel->getBoundingCapsuleOffset());
}
void Avatar::getCapsule(glm::vec3& start, glm::vec3& end, float& radius) {
ShapeInfo shapeInfo;
computeShapeInfo(shapeInfo);
glm::vec3 halfExtents = shapeInfo.getHalfExtents(); // x = radius, y = halfHeight
start = getPosition() - glm::vec3(0, halfExtents.y, 0);
end = getPosition() + glm::vec3(0, halfExtents.y, 0);
radius = halfExtents.x;
}
void Avatar::setMotionState(AvatarMotionState* motionState) {
_motionState = motionState;
}

View file

@ -154,6 +154,7 @@ public:
virtual void rebuildCollisionShape();
virtual void computeShapeInfo(ShapeInfo& shapeInfo);
void getCapsule(glm::vec3& start, glm::vec3& end, float& radius);
AvatarMotionState* getMotionState() { return _motionState; }

View file

@ -398,3 +398,51 @@ AvatarSharedPointer AvatarManager::getAvatarBySessionID(const QUuid& sessionID)
return findAvatar(sessionID);
}
RayToAvatarIntersectionResult AvatarManager::findRayIntersection(const PickRay& ray,
const QScriptValue& avatarIdsToInclude,
const QScriptValue& avatarIdsToDiscard) {
if (QThread::currentThread() != thread()) {
RayToAvatarIntersectionResult result;
QMetaObject::invokeMethod(const_cast<AvatarManager*>(this), "findRayIntersection", Qt::BlockingQueuedConnection,
Q_ARG(const QScriptValue&, avatarIdsToInclude),
Q_ARG(const QScriptValue&, avatarIdsToDiscard),
Q_RETURN_ARG(RayToAvatarIntersectionResult, result));
return result;
}
RayToAvatarIntersectionResult result;
QVector<EntityItemID> avatarsToInclude = qVectorEntityItemIDFromScriptValue(avatarIdsToInclude);
QVector<EntityItemID> avatarsToDiscard = qVectorEntityItemIDFromScriptValue(avatarIdsToDiscard);
glm::vec3 normDirection = glm::normalize(ray.direction);
for (auto avatarData : _avatarHash) {
auto avatar = std::static_pointer_cast<Avatar>(avatarData);
if ((avatarsToInclude.size() > 0 && !avatarsToInclude.contains(avatar->getID())) ||
(avatarsToDiscard.size() > 0 && avatarsToDiscard.contains(avatar->getID()))) {
continue;
}
float distance;
glm::vec3 start;
glm::vec3 end;
float radius;
avatar->getCapsule(start, end, radius);
bool intersects = findRayCapsuleIntersection(ray.origin, normDirection, start, end, radius, distance);
if (intersects && (!result.intersects || distance < result.distance)) {
result.intersects = true;
result.avatarID = avatar->getID();
result.distance = distance;
}
}
if (result.intersects) {
result.intersection = ray.origin + normDirection * result.distance;
}
return result;
}

View file

@ -70,6 +70,10 @@ public:
void addAvatarToSimulation(Avatar* avatar);
Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersection(const PickRay& ray,
const QScriptValue& avatarIdsToInclude = QScriptValue(),
const QScriptValue& avatarIdsToDiscard = QScriptValue());
public slots:
void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; }
void updateAvatarRenderStatus(bool shouldRenderAvatars);

View file

@ -34,6 +34,7 @@
#include <StreamUtils.h>
#include <UUID.h>
#include <shared/JSONHelpers.h>
#include <ShapeInfo.h>
#include "AvatarLogging.h"
@ -1681,3 +1682,25 @@ AvatarEntityIDs AvatarData::getAndClearRecentlyDetachedIDs() {
});
return result;
}
QScriptValue RayToAvatarIntersectionResultToScriptValue(QScriptEngine* engine, const RayToAvatarIntersectionResult& value) {
QScriptValue obj = engine->newObject();
obj.setProperty("intersects", value.intersects);
QScriptValue avatarIDValue = quuidToScriptValue(engine, value.avatarID);
obj.setProperty("avatarID", avatarIDValue);
obj.setProperty("distance", value.distance);
QScriptValue intersection = vec3toScriptValue(engine, value.intersection);
obj.setProperty("intersection", intersection);
return obj;
}
void RayToAvatarIntersectionResultFromScriptValue(const QScriptValue& object, RayToAvatarIntersectionResult& value) {
value.intersects = object.property("intersects").toVariant().toBool();
QScriptValue avatarIDValue = object.property("avatarID");
quuidFromScriptValue(avatarIDValue, value.avatarID);
value.distance = object.property("distance").toVariant().toFloat();
QScriptValue intersection = object.property("intersection");
if (intersection.isValid()) {
vec3FromScriptValue(intersection, value.intersection);
}
}

View file

@ -495,4 +495,19 @@ public:
void registerAvatarTypes(QScriptEngine* engine);
class RayToAvatarIntersectionResult {
public:
RayToAvatarIntersectionResult() : intersects(false), avatarID(), distance(0) {}
bool intersects;
QUuid avatarID;
float distance;
glm::vec3 intersection;
};
Q_DECLARE_METATYPE(RayToAvatarIntersectionResult)
QScriptValue RayToAvatarIntersectionResultToScriptValue(QScriptEngine* engine, const RayToAvatarIntersectionResult& results);
void RayToAvatarIntersectionResultFromScriptValue(const QScriptValue& object, RayToAvatarIntersectionResult& results);
#endif // hifi_AvatarData_h

View file

@ -465,6 +465,7 @@ void ScriptEngine::init() {
qScriptRegisterMetaType(this, EntityItemPropertiesToScriptValue, EntityItemPropertiesFromScriptValueHonorReadOnly);
qScriptRegisterMetaType(this, EntityItemIDtoScriptValue, EntityItemIDfromScriptValue);
qScriptRegisterMetaType(this, RayToEntityIntersectionResultToScriptValue, RayToEntityIntersectionResultFromScriptValue);
qScriptRegisterMetaType(this, RayToAvatarIntersectionResultToScriptValue, RayToAvatarIntersectionResultFromScriptValue);
qScriptRegisterSequenceMetaType<QVector<QUuid>>(this);
qScriptRegisterSequenceMetaType<QVector<EntityItemID>>(this);