Merge branch 'master' of https://github.com/highfidelity/hifi into punk

This commit is contained in:
samcake 2018-03-09 16:32:37 -08:00
commit 10016756b7
38 changed files with 211 additions and 136 deletions

View file

@ -128,10 +128,10 @@ Rectangle {
AudioControls.CheckBox { AudioControls.CheckBox {
id: stereoMic id: stereoMic
spacing: muteMic.spacing; spacing: muteMic.spacing;
text: qsTr("use stereo for stereo devices"); text: qsTr("Enable stereo input");
checked: false; checked: AudioScriptingInterface.isStereoInput();
onClicked: { onClicked: {
var success = Audio.setIsStereoInput(checked); var success = AudioScriptingInterface.setStereoInput(checked);
if (!success) { if (!success) {
checked = !checked; checked = !checked;
} }
@ -219,7 +219,7 @@ Rectangle {
onPressed: { onPressed: {
if (!checked) { if (!checked) {
stereoMic.checked = false; stereoMic.checked = false;
Audio.setIsStereoInput(false); // the next selected audio device might not support stereo AudioScriptingInterface.setStereoInput(false); // the next selected audio device might not support stereo
AudioScriptingInterface.setInputDevice(info, bar.currentIndex === 1); AudioScriptingInterface.setInputDevice(info, bar.currentIndex === 1);
} }
} }

View file

@ -174,11 +174,12 @@ Rectangle {
WalletChoice { WalletChoice {
id: walletChoice; id: walletChoice;
proceedFunction: function (isReset) { proceedFunction: function (isReset) {
console.log(isReset ? "Reset wallet." : "Trying again with new wallet."); console.log("WalletChoice", isReset ? "Reset wallet." : "Trying again with new wallet.");
Commerce.setSoftReset(); Commerce.setSoftReset();
if (isReset) { if (isReset) {
walletResetSetup(); walletResetSetup();
} else { } else {
Commerce.clearWallet();
var msg = { referrer: walletChoice.referrer } var msg = { referrer: walletChoice.referrer }
followReferrer(msg); followReferrer(msg);
} }

View file

@ -138,6 +138,11 @@ void QmlCommerce::setSoftReset() {
wallet->setSoftReset(); wallet->setSoftReset();
} }
void QmlCommerce::clearWallet() {
auto wallet = DependencyManager::get<Wallet>();
wallet->clear();
}
void QmlCommerce::setPassphrase(const QString& passphrase) { void QmlCommerce::setPassphrase(const QString& passphrase) {
auto wallet = DependencyManager::get<Wallet>(); auto wallet = DependencyManager::get<Wallet>();
wallet->setPassphrase(passphrase); wallet->setPassphrase(passphrase);

View file

@ -67,6 +67,7 @@ protected:
Q_INVOKABLE void setPassphrase(const QString& passphrase); Q_INVOKABLE void setPassphrase(const QString& passphrase);
Q_INVOKABLE void changePassphrase(const QString& oldPassphrase, const QString& newPassphrase); Q_INVOKABLE void changePassphrase(const QString& oldPassphrase, const QString& newPassphrase);
Q_INVOKABLE void setSoftReset(); Q_INVOKABLE void setSoftReset();
Q_INVOKABLE void clearWallet();
Q_INVOKABLE void buy(const QString& assetId, int cost, const bool controlledFailure = false); Q_INVOKABLE void buy(const QString& assetId, int cost, const bool controlledFailure = false);
Q_INVOKABLE void balance(); Q_INVOKABLE void balance();

View file

@ -343,19 +343,23 @@ Wallet::Wallet() {
auto accountManager = DependencyManager::get<AccountManager>(); auto accountManager = DependencyManager::get<AccountManager>();
connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() { connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() {
getWalletStatus(); getWalletStatus();
_publicKeys.clear(); clear();
if (_securityImage) {
delete _securityImage;
}
_securityImage = nullptr;
// tell the provider we got nothing
updateImageProvider();
_passphrase->clear();
}); });
} }
void Wallet::clear() {
_publicKeys.clear();
if (_securityImage) {
delete _securityImage;
}
_securityImage = nullptr;
// tell the provider we got nothing
updateImageProvider();
_passphrase->clear();
}
Wallet::~Wallet() { Wallet::~Wallet() {
if (_securityImage) { if (_securityImage) {
delete _securityImage; delete _securityImage;

View file

@ -49,8 +49,9 @@ public:
bool getPassphraseIsCached() { return !(_passphrase->isEmpty()); } bool getPassphraseIsCached() { return !(_passphrase->isEmpty()); }
bool walletIsAuthenticatedWithPassphrase(); bool walletIsAuthenticatedWithPassphrase();
bool changePassphrase(const QString& newPassphrase); bool changePassphrase(const QString& newPassphrase);
void setSoftReset() { _isOverridingServer = true; } void setSoftReset() { _isOverridingServer = true; }
bool wasSoftReset() { bool was = _isOverridingServer; _isOverridingServer = false; return was; } bool wasSoftReset() { bool was = _isOverridingServer; _isOverridingServer = false; return was; }
void clear();
void getWalletStatus(); void getWalletStatus();
enum WalletStatus { enum WalletStatus {

View file

@ -175,3 +175,11 @@ void PickScriptingInterface::registerMetaTypes(QScriptEngine* engine) {
qScriptRegisterMetaType(engine, pickTypesToScriptValue, pickTypesFromScriptValue); qScriptRegisterMetaType(engine, pickTypesToScriptValue, pickTypesFromScriptValue);
} }
unsigned int PickScriptingInterface::getPerFrameTimeBudget() const {
return DependencyManager::get<PickManager>()->getPerFrameTimeBudget();
}
void PickScriptingInterface::setPerFrameTimeBudget(unsigned int numUsecs) {
DependencyManager::get<PickManager>()->setPerFrameTimeBudget(numUsecs);
}

View file

@ -185,6 +185,14 @@ public:
*/ */
Q_INVOKABLE bool isMouse(unsigned int uid); Q_INVOKABLE bool isMouse(unsigned int uid);
Q_PROPERTY(unsigned int perFrameTimeBudget READ getPerFrameTimeBudget WRITE setPerFrameTimeBudget)
/**jsdoc
* The max number of usec to spend per frame updating Pick results.
* @typedef {number} Picks.perFrameTimeBudget
*/
unsigned int getPerFrameTimeBudget() const;
void setPerFrameTimeBudget(unsigned int numUsecs);
public slots: public slots:
static constexpr unsigned int PICK_NOTHING() { return 0; } static constexpr unsigned int PICK_NOTHING() { return 0; }
static constexpr unsigned int PICK_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ENTITIES); } static constexpr unsigned int PICK_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ENTITIES); }

View file

@ -193,6 +193,7 @@ public slots:
bool isMuted() { return _muted; } bool isMuted() { return _muted; }
virtual bool setIsStereoInput(bool stereo) override; virtual bool setIsStereoInput(bool stereo) override;
virtual bool isStereoInput() override { return _isStereoInput; }
void setNoiseReduction(bool isNoiseGateEnabled); void setNoiseReduction(bool isNoiseGateEnabled);
bool isNoiseReductionEnabled() const { return _isNoiseGateEnabled; } bool isNoiseReductionEnabled() const { return _isNoiseGateEnabled; }

View file

@ -42,6 +42,8 @@ public slots:
virtual bool shouldLoopbackInjectors() { return false; } virtual bool shouldLoopbackInjectors() { return false; }
virtual bool setIsStereoInput(bool stereo) = 0; virtual bool setIsStereoInput(bool stereo) = 0;
virtual bool isStereoInput() = 0;
}; };
Q_DECLARE_METATYPE(AbstractAudioInterface*) Q_DECLARE_METATYPE(AbstractAudioInterface*)

View file

@ -286,7 +286,7 @@ bool RenderableModelEntityItem::supportsDetailedRayIntersection() const {
} }
bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, OctreeElementPointer& element, float& distance, BoxFace& face,
glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const {
auto model = getModel(); auto model = getModel();
if (!model) { if (!model) {

View file

@ -68,7 +68,7 @@ public:
virtual bool supportsDetailedRayIntersection() const override; virtual bool supportsDetailedRayIntersection() const override;
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const override; QVariantMap& extraInfo, bool precisionPicking) const override;

View file

@ -565,7 +565,7 @@ public:
#endif #endif
bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, OctreeElementPointer& element,
float& distance, BoxFace& face, glm::vec3& surfaceNormal, float& distance, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const QVariantMap& extraInfo, bool precisionPicking) const
{ {

View file

@ -53,7 +53,7 @@ public:
virtual bool supportsDetailedRayIntersection() const override { return true; } virtual bool supportsDetailedRayIntersection() const override { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const override; QVariantMap& extraInfo, bool precisionPicking) const override;

View file

@ -159,7 +159,7 @@ public:
virtual bool supportsDetailedRayIntersection() const { return false; } virtual bool supportsDetailedRayIntersection() const { return false; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const { return true; } QVariantMap& extraInfo, bool precisionPicking) const { return true; }

View file

@ -594,17 +594,15 @@ EntityItemID EntityTreeElement::findRayIntersection(const glm::vec3& origin, con
const QVector<EntityItemID>& entityIdsToDiscard, bool visibleOnly, bool collidableOnly, const QVector<EntityItemID>& entityIdsToDiscard, bool visibleOnly, bool collidableOnly,
QVariantMap& extraInfo, bool precisionPicking) { QVariantMap& extraInfo, bool precisionPicking) {
keepSearching = true; // assume that we will continue searching after this.
EntityItemID result; EntityItemID result;
float distanceToElementCube = std::numeric_limits<float>::max(); float distanceToElementCube = std::numeric_limits<float>::max();
float distanceToElementDetails = distance;
BoxFace localFace; BoxFace localFace;
glm::vec3 localSurfaceNormal; glm::vec3 localSurfaceNormal;
QVariantMap localExtraInfo;
// if the ray doesn't intersect with our cube, we can stop searching! // if the ray doesn't intersect with our cube OR the distance to element is less than current best distance
if (!_cube.findRayIntersection(origin, direction, distanceToElementCube, localFace, localSurfaceNormal)) { // we can stop searching!
bool hit = _cube.findRayIntersection(origin, direction, distanceToElementCube, localFace, localSurfaceNormal);
if (!hit || (!_cube.contains(origin) && distanceToElementCube > distance)) {
keepSearching = false; // no point in continuing to search keepSearching = false; // no point in continuing to search
return result; // we did not intersect return result; // we did not intersect
} }
@ -616,52 +614,46 @@ EntityItemID EntityTreeElement::findRayIntersection(const glm::vec3& origin, con
// if the distance to the element cube is not less than the current best distance, then it's not possible // if the distance to the element cube is not less than the current best distance, then it's not possible
// for any details inside the cube to be closer so we don't need to consider them. // for any details inside the cube to be closer so we don't need to consider them.
if (_cube.contains(origin) || distanceToElementCube < distance) { QVariantMap localExtraInfo;
float distanceToElementDetails = distance;
EntityItemID entityID = findDetailedRayIntersection(origin, direction, keepSearching, element, distanceToElementDetails, EntityItemID entityID = findDetailedRayIntersection(origin, direction, element, distanceToElementDetails,
face, localSurfaceNormal, entityIdsToInclude, entityIdsToDiscard, visibleOnly, collidableOnly, face, localSurfaceNormal, entityIdsToInclude, entityIdsToDiscard, visibleOnly, collidableOnly,
localExtraInfo, precisionPicking, distanceToElementCube); localExtraInfo, precisionPicking);
if (!entityID.isNull()) { if (!entityID.isNull() && distanceToElementDetails < distance) {
if (distanceToElementDetails < distance) { distance = distanceToElementDetails;
distance = distanceToElementDetails; face = localFace;
face = localFace; surfaceNormal = localSurfaceNormal;
surfaceNormal = localSurfaceNormal; extraInfo = localExtraInfo;
extraInfo = localExtraInfo; result = entityID;
result = entityID;
}
}
} }
return result; return result;
} }
EntityItemID EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, EntityItemID EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal,
const QVector<EntityItemID>& entityIdsToInclude, const QVector<EntityItemID>& entityIDsToDiscard, const QVector<EntityItemID>& entityIdsToInclude, const QVector<EntityItemID>& entityIDsToDiscard,
bool visibleOnly, bool collidableOnly, QVariantMap& extraInfo, bool precisionPicking, float distanceToElementCube) { bool visibleOnly, bool collidableOnly, QVariantMap& extraInfo, bool precisionPicking) {
// only called if we do intersect our bounding cube, but find if we actually intersect with entities... // only called if we do intersect our bounding cube, but find if we actually intersect with entities...
int entityNumber = 0; int entityNumber = 0;
EntityItemID entityID; EntityItemID entityID;
forEachEntity([&](EntityItemPointer entity) { forEachEntity([&](EntityItemPointer entity) {
if ( (visibleOnly && !entity->isVisible()) || (collidableOnly && (entity->getCollisionless() || entity->getShapeType() == SHAPE_TYPE_NONE)) // use simple line-sphere for broadphase check
|| (entityIdsToInclude.size() > 0 && !entityIdsToInclude.contains(entity->getID())) // (this is faster and more likely to cull results than the filter check below so we do it first)
|| (entityIDsToDiscard.size() > 0 && entityIDsToDiscard.contains(entity->getID())) ) {
return;
}
bool success; bool success;
AABox entityBox = entity->getAABox(success); AABox entityBox = entity->getAABox(success);
if (!success) { if (!success) {
return; return;
} }
if (!entityBox.rayHitsBoundingSphere(origin, direction)) {
return;
}
float localDistance; // check RayPick filter settings
BoxFace localFace; if ((visibleOnly && !entity->isVisible())
glm::vec3 localSurfaceNormal; || (collidableOnly && (entity->getCollisionless() || entity->getShapeType() == SHAPE_TYPE_NONE))
QVariantMap localExtraInfo; || (entityIdsToInclude.size() > 0 && !entityIdsToInclude.contains(entity->getID()))
|| (entityIDsToDiscard.size() > 0 && entityIDsToDiscard.contains(entity->getID())) ) {
// if the ray doesn't intersect with our cube, we can stop searching!
if (!entityBox.findRayIntersection(origin, direction, localDistance, localFace, localSurfaceNormal)) {
return; return;
} }
@ -682,14 +674,17 @@ EntityItemID EntityTreeElement::findDetailedRayIntersection(const glm::vec3& ori
// we can use the AABox's ray intersection by mapping our origin and direction into the entity frame // we can use the AABox's ray intersection by mapping our origin and direction into the entity frame
// and testing intersection there. // and testing intersection there.
float localDistance;
BoxFace localFace;
glm::vec3 localSurfaceNormal;
if (entityFrameBox.findRayIntersection(entityFrameOrigin, entityFrameDirection, localDistance, if (entityFrameBox.findRayIntersection(entityFrameOrigin, entityFrameDirection, localDistance,
localFace, localSurfaceNormal)) { localFace, localSurfaceNormal)) {
if (entityFrameBox.contains(entityFrameOrigin) || localDistance < distance) { if (entityFrameBox.contains(entityFrameOrigin) || localDistance < distance) {
// now ask the entity if we actually intersect // now ask the entity if we actually intersect
if (entity->supportsDetailedRayIntersection()) { if (entity->supportsDetailedRayIntersection()) {
if (entity->findDetailedRayIntersection(origin, direction, keepSearching, element, localDistance, QVariantMap localExtraInfo;
localFace, localSurfaceNormal, localExtraInfo, precisionPicking)) { if (entity->findDetailedRayIntersection(origin, direction, element, localDistance,
localFace, localSurfaceNormal, localExtraInfo, precisionPicking)) {
if (localDistance < distance) { if (localDistance < distance) {
distance = localDistance; distance = localDistance;
face = localFace; face = localFace;

View file

@ -152,10 +152,10 @@ public:
const QVector<EntityItemID>& entityIdsToDiscard, bool visibleOnly, bool collidableOnly, const QVector<EntityItemID>& entityIdsToDiscard, bool visibleOnly, bool collidableOnly,
QVariantMap& extraInfo, bool precisionPicking = false); QVariantMap& extraInfo, bool precisionPicking = false);
virtual EntityItemID findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, virtual EntityItemID findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, const QVector<EntityItemID>& entityIdsToInclude, BoxFace& face, glm::vec3& surfaceNormal, const QVector<EntityItemID>& entityIdsToInclude,
const QVector<EntityItemID>& entityIdsToDiscard, bool visibleOnly, bool collidableOnly, const QVector<EntityItemID>& entityIdsToDiscard, bool visibleOnly, bool collidableOnly,
QVariantMap& extraInfo, bool precisionPicking, float distanceToElementCube); QVariantMap& extraInfo, bool precisionPicking);
virtual bool findSpherePenetration(const glm::vec3& center, float radius, virtual bool findSpherePenetration(const glm::vec3& center, float radius,
glm::vec3& penetration, void** penetratedObject) const override; glm::vec3& penetration, void** penetratedObject) const override;

View file

@ -298,7 +298,7 @@ void LightEntityItem::resetLightPropertiesChanged() {
} }
bool LightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool LightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const { QVariantMap& extraInfo, bool precisionPicking) const {

View file

@ -86,7 +86,7 @@ public:
virtual bool supportsDetailedRayIntersection() const override { return true; } virtual bool supportsDetailedRayIntersection() const override { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const override; QVariantMap& extraInfo, bool precisionPicking) const override;

View file

@ -61,7 +61,7 @@ class LineEntityItem : public EntityItem {
// never have a ray intersection pick a LineEntityItem. // never have a ray intersection pick a LineEntityItem.
virtual bool supportsDetailedRayIntersection() const override { return true; } virtual bool supportsDetailedRayIntersection() const override { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, QVariantMap& extraInfo,
bool precisionPicking) const override { return false; } bool precisionPicking) const override { return false; }

View file

@ -94,7 +94,7 @@ class PolyLineEntityItem : public EntityItem {
// never have a ray intersection pick a PolyLineEntityItem. // never have a ray intersection pick a PolyLineEntityItem.
virtual bool supportsDetailedRayIntersection() const override { return true; } virtual bool supportsDetailedRayIntersection() const override { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const override { return false; } QVariantMap& extraInfo, bool precisionPicking) const override { return false; }

View file

@ -45,7 +45,7 @@ class PolyVoxEntityItem : public EntityItem {
// never have a ray intersection pick a PolyVoxEntityItem. // never have a ray intersection pick a PolyVoxEntityItem.
virtual bool supportsDetailedRayIntersection() const override { return true; } virtual bool supportsDetailedRayIntersection() const override { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const override { return false; } QVariantMap& extraInfo, bool precisionPicking) const override { return false; }

View file

@ -228,7 +228,7 @@ bool ShapeEntityItem::supportsDetailedRayIntersection() const {
} }
bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, OctreeElementPointer& element,
float& distance, BoxFace& face, glm::vec3& surfaceNormal, float& distance, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const { QVariantMap& extraInfo, bool precisionPicking) const {
// determine the ray in the frame of the entity transformed from a unit sphere // determine the ray in the frame of the entity transformed from a unit sphere

View file

@ -92,7 +92,7 @@ public:
bool supportsDetailedRayIntersection() const override; bool supportsDetailedRayIntersection() const override;
bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const override; QVariantMap& extraInfo, bool precisionPicking) const override;

View file

@ -129,7 +129,7 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
} }
bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const { QVariantMap& extraInfo, bool precisionPicking) const {
glm::vec3 dimensions = getScaledDimensions(); glm::vec3 dimensions = getScaledDimensions();

View file

@ -48,7 +48,7 @@ public:
virtual bool supportsDetailedRayIntersection() const override { return true; } virtual bool supportsDetailedRayIntersection() const override { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const override; QVariantMap& extraInfo, bool precisionPicking) const override;

View file

@ -106,7 +106,7 @@ void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst
} }
bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const { QVariantMap& extraInfo, bool precisionPicking) const {
glm::vec3 dimensions = getScaledDimensions(); glm::vec3 dimensions = getScaledDimensions();

View file

@ -47,7 +47,7 @@ public:
virtual bool supportsDetailedRayIntersection() const override { return true; } virtual bool supportsDetailedRayIntersection() const override { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const override; QVariantMap& extraInfo, bool precisionPicking) const override;

View file

@ -296,7 +296,7 @@ void ZoneEntityItem::setCompoundShapeURL(const QString& url) {
} }
bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const { QVariantMap& extraInfo, bool precisionPicking) const {

View file

@ -105,7 +105,7 @@ public:
virtual bool supportsDetailedRayIntersection() const override { return true; } virtual bool supportsDetailedRayIntersection() const override { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, BoxFace& face, glm::vec3& surfaceNormal,
QVariantMap& extraInfo, bool precisionPicking) const override; QVariantMap& extraInfo, bool precisionPicking) const override;

View file

@ -37,7 +37,7 @@ template<typename T>
class PickCacheOptimizer { class PickCacheOptimizer {
public: public:
void update(std::unordered_map<unsigned int, std::shared_ptr<PickQuery>>& picks, bool shouldPickHUD); void update(std::unordered_map<uint32_t, std::shared_ptr<PickQuery>>& picks, uint32_t& nextToUpdate, uint64_t expiry, bool shouldPickHUD);
protected: protected:
typedef std::unordered_map<T, std::unordered_map<PickCacheKey, PickResultPointer>> PickCache; typedef std::unordered_map<T, std::unordered_map<PickCacheKey, PickResultPointer>> PickCache;
@ -67,64 +67,82 @@ void PickCacheOptimizer<T>::cacheResult(const bool intersects, const PickResultP
} }
template<typename T> template<typename T>
void PickCacheOptimizer<T>::update(std::unordered_map<unsigned int, std::shared_ptr<PickQuery>>& picks, bool shouldPickHUD) { void PickCacheOptimizer<T>::update(std::unordered_map<uint32_t, std::shared_ptr<PickQuery>>& picks,
uint32_t& nextToUpdate, uint64_t expiry, bool shouldPickHUD) {
PickCache results; PickCache results;
for (const auto& pickPair : picks) { const uint32_t INVALID_PICK_ID = 0;
std::shared_ptr<Pick<T>> pick = std::static_pointer_cast<Pick<T>>(pickPair.second); auto itr = picks.begin();
if (nextToUpdate != INVALID_PICK_ID) {
itr = picks.find(nextToUpdate);
if (itr == picks.end()) {
itr = picks.begin();
}
}
uint32_t numUpdates = 0;
while(numUpdates < picks.size()) {
std::shared_ptr<Pick<T>> pick = std::static_pointer_cast<Pick<T>>(itr->second);
T mathematicalPick = pick->getMathematicalPick(); T mathematicalPick = pick->getMathematicalPick();
PickResultPointer res = pick->getDefaultResult(mathematicalPick.toVariantMap()); PickResultPointer res = pick->getDefaultResult(mathematicalPick.toVariantMap());
if (!pick->isEnabled() || pick->getFilter().doesPickNothing() || pick->getMaxDistance() < 0.0f || !mathematicalPick) { if (!pick->isEnabled() || pick->getFilter().doesPickNothing() || pick->getMaxDistance() < 0.0f || !mathematicalPick) {
pick->setPickResult(res); pick->setPickResult(res);
continue;
}
if (pick->getFilter().doesPickEntities()) {
PickCacheKey entityKey = { pick->getFilter().getEntityFlags(), pick->getIncludeItems(), pick->getIgnoreItems() };
if (!checkAndCompareCachedResults(mathematicalPick, results, res, entityKey)) {
PickResultPointer entityRes = pick->getEntityIntersection(mathematicalPick);
if (entityRes) {
cacheResult(entityRes->doesIntersect(), entityRes, entityKey, res, mathematicalPick, results, pick);
}
}
}
if (pick->getFilter().doesPickOverlays()) {
PickCacheKey overlayKey = { pick->getFilter().getOverlayFlags(), pick->getIncludeItems(), pick->getIgnoreItems() };
if (!checkAndCompareCachedResults(mathematicalPick, results, res, overlayKey)) {
PickResultPointer overlayRes = pick->getOverlayIntersection(mathematicalPick);
if (overlayRes) {
cacheResult(overlayRes->doesIntersect(), overlayRes, overlayKey, res, mathematicalPick, results, pick);
}
}
}
if (pick->getFilter().doesPickAvatars()) {
PickCacheKey avatarKey = { pick->getFilter().getAvatarFlags(), pick->getIncludeItems(), pick->getIgnoreItems() };
if (!checkAndCompareCachedResults(mathematicalPick, results, res, avatarKey)) {
PickResultPointer avatarRes = pick->getAvatarIntersection(mathematicalPick);
if (avatarRes) {
cacheResult(avatarRes->doesIntersect(), avatarRes, avatarKey, res, mathematicalPick, results, pick);
}
}
}
// Can't intersect with HUD in desktop mode
if (pick->getFilter().doesPickHUD() && shouldPickHUD) {
PickCacheKey hudKey = { pick->getFilter().getHUDFlags(), QVector<QUuid>(), QVector<QUuid>() };
if (!checkAndCompareCachedResults(mathematicalPick, results, res, hudKey)) {
PickResultPointer hudRes = pick->getHUDIntersection(mathematicalPick);
if (hudRes) {
cacheResult(true, hudRes, hudKey, res, mathematicalPick, results, pick);
}
}
}
if (pick->getMaxDistance() == 0.0f || (pick->getMaxDistance() > 0.0f && res->checkOrFilterAgainstMaxDistance(pick->getMaxDistance()))) {
pick->setPickResult(res);
} else { } else {
pick->setPickResult(pick->getDefaultResult(mathematicalPick.toVariantMap())); if (pick->getFilter().doesPickEntities()) {
PickCacheKey entityKey = { pick->getFilter().getEntityFlags(), pick->getIncludeItems(), pick->getIgnoreItems() };
if (!checkAndCompareCachedResults(mathematicalPick, results, res, entityKey)) {
PickResultPointer entityRes = pick->getEntityIntersection(mathematicalPick);
if (entityRes) {
cacheResult(entityRes->doesIntersect(), entityRes, entityKey, res, mathematicalPick, results, pick);
}
}
}
if (pick->getFilter().doesPickOverlays()) {
PickCacheKey overlayKey = { pick->getFilter().getOverlayFlags(), pick->getIncludeItems(), pick->getIgnoreItems() };
if (!checkAndCompareCachedResults(mathematicalPick, results, res, overlayKey)) {
PickResultPointer overlayRes = pick->getOverlayIntersection(mathematicalPick);
if (overlayRes) {
cacheResult(overlayRes->doesIntersect(), overlayRes, overlayKey, res, mathematicalPick, results, pick);
}
}
}
if (pick->getFilter().doesPickAvatars()) {
PickCacheKey avatarKey = { pick->getFilter().getAvatarFlags(), pick->getIncludeItems(), pick->getIgnoreItems() };
if (!checkAndCompareCachedResults(mathematicalPick, results, res, avatarKey)) {
PickResultPointer avatarRes = pick->getAvatarIntersection(mathematicalPick);
if (avatarRes) {
cacheResult(avatarRes->doesIntersect(), avatarRes, avatarKey, res, mathematicalPick, results, pick);
}
}
}
// Can't intersect with HUD in desktop mode
if (pick->getFilter().doesPickHUD() && shouldPickHUD) {
PickCacheKey hudKey = { pick->getFilter().getHUDFlags(), QVector<QUuid>(), QVector<QUuid>() };
if (!checkAndCompareCachedResults(mathematicalPick, results, res, hudKey)) {
PickResultPointer hudRes = pick->getHUDIntersection(mathematicalPick);
if (hudRes) {
cacheResult(true, hudRes, hudKey, res, mathematicalPick, results, pick);
}
}
}
if (pick->getMaxDistance() == 0.0f || (pick->getMaxDistance() > 0.0f && res->checkOrFilterAgainstMaxDistance(pick->getMaxDistance()))) {
pick->setPickResult(res);
} else {
pick->setPickResult(pick->getDefaultResult(mathematicalPick.toVariantMap()));
}
}
++itr;
if (itr == picks.end()) {
itr = picks.begin();
}
nextToUpdate = itr->first;
++numUpdates;
if (usecTimestampNow() > expiry) {
break;
} }
} }
} }

View file

@ -89,14 +89,17 @@ void PickManager::setIncludeItems(unsigned int uid, const QVector<QUuid>& includ
} }
void PickManager::update() { void PickManager::update() {
uint64_t expiry = usecTimestampNow() + _perFrameTimeBudget;
std::unordered_map<PickQuery::PickType, std::unordered_map<unsigned int, std::shared_ptr<PickQuery>>> cachedPicks; std::unordered_map<PickQuery::PickType, std::unordered_map<unsigned int, std::shared_ptr<PickQuery>>> cachedPicks;
withReadLock([&] { withReadLock([&] {
cachedPicks = _picks; cachedPicks = _picks;
}); });
bool shouldPickHUD = _shouldPickHUDOperator(); bool shouldPickHUD = _shouldPickHUDOperator();
_rayPickCacheOptimizer.update(cachedPicks[PickQuery::Ray], shouldPickHUD); // we pass the same expiry to both updates, but the stylus updates are relatively cheap
_stylusPickCacheOptimizer.update(cachedPicks[PickQuery::Stylus], false); // and the rayPicks updae will ALWAYS update at least one ray even when there is no budget
_stylusPickCacheOptimizer.update(cachedPicks[PickQuery::Stylus], _nextPickToUpdate[PickQuery::Stylus], expiry, false);
_rayPickCacheOptimizer.update(cachedPicks[PickQuery::Ray], _nextPickToUpdate[PickQuery::Ray], expiry, shouldPickHUD);
} }
bool PickManager::isLeftHand(unsigned int uid) { bool PickManager::isLeftHand(unsigned int uid) {

View file

@ -14,6 +14,8 @@
#include "Pick.h" #include "Pick.h"
#include "PickCacheOptimizer.h" #include "PickCacheOptimizer.h"
#include <NumericalConstants.h>
class PickManager : public Dependency, protected ReadWriteLockable { class PickManager : public Dependency, protected ReadWriteLockable {
SINGLETON_DEPENDENCY SINGLETON_DEPENDENCY
@ -48,17 +50,24 @@ public:
static const unsigned int INVALID_PICK_ID { 0 }; static const unsigned int INVALID_PICK_ID { 0 };
unsigned int getPerFrameTimeBudget() const { return _perFrameTimeBudget; }
void setPerFrameTimeBudget(unsigned int numUsecs) { _perFrameTimeBudget = numUsecs; }
protected: protected:
std::function<bool()> _shouldPickHUDOperator; std::function<bool()> _shouldPickHUDOperator;
std::function<glm::vec2(const glm::vec3&)> _calculatePos2DFromHUDOperator; std::function<glm::vec2(const glm::vec3&)> _calculatePos2DFromHUDOperator;
std::shared_ptr<PickQuery> findPick(unsigned int uid) const; std::shared_ptr<PickQuery> findPick(unsigned int uid) const;
std::unordered_map<PickQuery::PickType, std::unordered_map<unsigned int, std::shared_ptr<PickQuery>>> _picks; std::unordered_map<PickQuery::PickType, std::unordered_map<unsigned int, std::shared_ptr<PickQuery>>> _picks;
unsigned int _nextPickToUpdate[PickQuery::NUM_PICK_TYPES] { 0, 0 };
std::unordered_map<unsigned int, PickQuery::PickType> _typeMap; std::unordered_map<unsigned int, PickQuery::PickType> _typeMap;
unsigned int _nextPickID { INVALID_PICK_ID + 1 }; unsigned int _nextPickID { INVALID_PICK_ID + 1 };
PickCacheOptimizer<PickRay> _rayPickCacheOptimizer; PickCacheOptimizer<PickRay> _rayPickCacheOptimizer;
PickCacheOptimizer<StylusTip> _stylusPickCacheOptimizer; PickCacheOptimizer<StylusTip> _stylusPickCacheOptimizer;
static const unsigned int DEFAULT_PER_FRAME_TIME_BUDGET = 2 * USECS_PER_MSEC;
unsigned int _perFrameTimeBudget { DEFAULT_PER_FRAME_TIME_BUDGET };
}; };
#endif // hifi_PickManager_h #endif // hifi_PickManager_h

View file

@ -67,3 +67,11 @@ bool AudioScriptingInterface::setStereoInput(bool stereo) {
} }
return stereoInputChanged; return stereoInputChanged;
} }
bool AudioScriptingInterface::isStereoInput() {
bool stereoEnabled = false;
if (_localAudioInterface) {
stereoEnabled = _localAudioInterface->isStereoInput();
}
return stereoEnabled;
}

View file

@ -36,6 +36,7 @@ protected:
Q_INVOKABLE ScriptAudioInjector* playSystemSound(SharedSoundPointer sound, const QVector3D& position); Q_INVOKABLE ScriptAudioInjector* playSystemSound(SharedSoundPointer sound, const QVector3D& position);
Q_INVOKABLE bool setStereoInput(bool stereo); Q_INVOKABLE bool setStereoInput(bool stereo);
Q_INVOKABLE bool isStereoInput();
signals: signals:
void mutedByMixer(); /// the client has been muted by the mixer void mutedByMixer(); /// the client has been muted by the mixer

View file

@ -287,6 +287,15 @@ bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct
return false; return false;
} }
bool AABox::rayHitsBoundingSphere(const glm::vec3& origin, const glm::vec3& direction) const {
glm::vec3 localCenter = calcCenter() - origin;
float distance = glm::dot(localCenter, direction);
const float ONE_OVER_TWO_SQUARED = 0.25f;
float radiusSquared = ONE_OVER_TWO_SQUARED * glm::length2(_scale);
return (glm::length2(localCenter) < radiusSquared
|| (glm::abs(distance) > 0.0f && glm::distance2(distance * direction, localCenter) < radiusSquared));
}
bool AABox::touchesSphere(const glm::vec3& center, float radius) const { bool AABox::touchesSphere(const glm::vec3& center, float radius) const {
// Avro's algorithm from this paper: http://www.mrtc.mdh.se/projects/3Dgraphics/paperF.pdf // Avro's algorithm from this paper: http://www.mrtc.mdh.se/projects/3Dgraphics/paperF.pdf
glm::vec3 e = glm::max(_corner - center, Vectors::ZERO) + glm::max(center - _corner - _scale, Vectors::ZERO); glm::vec3 e = glm::max(_corner - center, Vectors::ZERO) + glm::max(center - _corner - _scale, Vectors::ZERO);

View file

@ -71,6 +71,7 @@ public:
bool expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, float expansion) const; bool expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, float expansion) const;
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
BoxFace& face, glm::vec3& surfaceNormal) const; BoxFace& face, glm::vec3& surfaceNormal) const;
bool rayHitsBoundingSphere(const glm::vec3& origin, const glm::vec3& direction) const;
bool touchesSphere(const glm::vec3& center, float radius) const; // fast but may generate false positives bool touchesSphere(const glm::vec3& center, float radius) const; // fast but may generate false positives
bool touchesAAEllipsoid(const glm::vec3& center, const glm::vec3& radials) const; bool touchesAAEllipsoid(const glm::vec3& center, const glm::vec3& radials) const;
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const; bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const;