// // Created by Sam Gondelman 7/2/2018 // Copyright 2018 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "ParabolaPick.h" #include "Application.h" #include "EntityScriptingInterface.h" #include "PickScriptingInterface.h" #include "avatar/AvatarManager.h" #include "scripting/HMDScriptingInterface.h" #include "DependencyManager.h" #include "PickManager.h" ParabolaPick::ParabolaPick(const glm::vec3& position, const glm::vec3& direction, float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, bool rotateAccelerationWithParent, bool scaleWithParent, const PickFilter& filter, float maxDistance, bool enabled) : Pick(PickParabola(position, speed * direction, accelerationAxis), filter, maxDistance, enabled), _rotateAccelerationWithAvatar(rotateAccelerationWithAvatar), _rotateAccelerationWithParent(rotateAccelerationWithParent), _scaleWithParent(scaleWithParent), _speed(speed) { } PickParabola ParabolaPick::getMathematicalPick() const { if (!parentTransform) { PickParabola mathPick = _mathPick; if (_rotateAccelerationWithAvatar) { mathPick.acceleration = DependencyManager::get()->getMyAvatar()->getWorldOrientation() * mathPick.acceleration; } return mathPick; } Transform currentParentTransform = parentTransform->getTransform(); glm::vec3 position = currentParentTransform.transform(_mathPick.origin); glm::vec3 velocity = _mathPick.velocity; if (_scaleWithParent) { velocity = currentParentTransform.transformDirection(velocity); } else { glm::vec3 transformedVelocity = currentParentTransform.transformDirection(velocity); velocity = glm::normalize(transformedVelocity) * _speed; } glm::vec3 acceleration = _mathPick.acceleration; if (_scaleWithParent) { acceleration *= currentParentTransform.getScale(); } if (_rotateAccelerationWithAvatar) { acceleration = DependencyManager::get()->getMyAvatar()->getWorldOrientation() * acceleration; } else if (_rotateAccelerationWithParent) { acceleration = currentParentTransform.getRotation() * acceleration; } return PickParabola(position, velocity, acceleration); } PickResultPointer ParabolaPick::getEntityIntersection(const PickParabola& pick) { if (glm::length2(pick.acceleration) > EPSILON && glm::length2(pick.velocity) > EPSILON) { PickFilter searchFilter = getFilter(); if (DependencyManager::get()->getForceCoarsePicking()) { searchFilter.setFlag(PickFilter::COARSE, true); searchFilter.setFlag(PickFilter::PRECISE, false); } ParabolaToEntityIntersectionResult entityRes = DependencyManager::get()->evalParabolaIntersectionVector(pick, searchFilter, getIncludeItemsAs(), getIgnoreItemsAs()); if (entityRes.intersects) { IntersectionType type = IntersectionType::ENTITY; if (getFilter().doesPickLocalEntities()) { EntityPropertyFlags desiredProperties; desiredProperties += PROP_ENTITY_HOST_TYPE; if (DependencyManager::get()->getEntityPropertiesInternal(entityRes.entityID, desiredProperties, false).getEntityHostType() == entity::HostType::LOCAL) { type = IntersectionType::LOCAL_ENTITY; } } return std::make_shared(type, entityRes.entityID, entityRes.distance, entityRes.parabolicDistance, entityRes.intersection, pick, entityRes.surfaceNormal, entityRes.extraInfo); } } return std::make_shared(pick.toVariantMap()); } PickResultPointer ParabolaPick::getAvatarIntersection(const PickParabola& pick) { if (glm::length2(pick.acceleration) > EPSILON && glm::length2(pick.velocity) > EPSILON) { ParabolaToAvatarIntersectionResult avatarRes = DependencyManager::get()->findParabolaIntersectionVector(pick, getIncludeItemsAs(), getIgnoreItemsAs()); if (avatarRes.intersects) { return std::make_shared(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.parabolicDistance, avatarRes.intersection, pick, avatarRes.surfaceNormal, avatarRes.extraInfo); } } return std::make_shared(pick.toVariantMap()); } PickResultPointer ParabolaPick::getHUDIntersection(const PickParabola& pick) { if (glm::length2(pick.acceleration) > EPSILON && glm::length2(pick.velocity) > EPSILON) { float parabolicDistance; glm::vec3 hudRes = DependencyManager::get()->calculateParabolaUICollisionPoint(pick.origin, pick.velocity, pick.acceleration, parabolicDistance); return std::make_shared(IntersectionType::HUD, QUuid(), glm::distance(pick.origin, hudRes), parabolicDistance, hudRes, pick); } return std::make_shared(pick.toVariantMap()); } Transform ParabolaPick::getResultTransform() const { PickResultPointer result = getPrevPickResult(); if (!result) { return Transform(); } auto parabolaResult = std::static_pointer_cast(result); Transform transform; transform.setTranslation(parabolaResult->intersection); return transform; }