improve model picking performance, scale parabola v/a with avatar, improve followNormal behavior, turn off followNormal on teleport, remove 1 m no teleport spot

This commit is contained in:
SamGondelman 2018-07-25 15:19:25 -07:00
parent fbcddf1445
commit 9b41cb5554
18 changed files with 94 additions and 88 deletions

View file

@ -10,8 +10,8 @@
#include "avatar/AvatarManager.h" #include "avatar/AvatarManager.h"
JointParabolaPick::JointParabolaPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, JointParabolaPick::JointParabolaPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset,
float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, PickFilter& filter, float maxDistance, bool enabled) : float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, bool scaleWithAvatar, PickFilter& filter, float maxDistance, bool enabled) :
ParabolaPick(speed, accelerationAxis, rotateAccelerationWithAvatar, filter, maxDistance, enabled), ParabolaPick(speed, accelerationAxis, rotateAccelerationWithAvatar, scaleWithAvatar, filter, maxDistance, enabled),
_jointName(jointName), _jointName(jointName),
_posOffset(posOffset), _posOffset(posOffset),
_dirOffset(dirOffset) _dirOffset(dirOffset)
@ -36,7 +36,7 @@ PickParabola JointParabolaPick::getMathematicalPick() const {
pos = pos + (rot * (myAvatar->getSensorToWorldScale() * _posOffset)); pos = pos + (rot * (myAvatar->getSensorToWorldScale() * _posOffset));
glm::vec3 dir = rot * glm::normalize(_dirOffset); glm::vec3 dir = rot * glm::normalize(_dirOffset);
return PickParabola(pos, _speed * dir, getAcceleration()); return PickParabola(pos, getSpeed() * dir, getAcceleration());
} }
return PickParabola(); return PickParabola();

View file

@ -14,7 +14,8 @@ class JointParabolaPick : public ParabolaPick {
public: public:
JointParabolaPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, JointParabolaPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset,
float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, PickFilter& filter, float maxDistance = 0.0f, bool enabled = false); float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, bool scaleWithAvatar,
PickFilter& filter, float maxDistance = 0.0f, bool enabled = false);
PickParabola getMathematicalPick() const override; PickParabola getMathematicalPick() const override;

View file

@ -105,8 +105,8 @@ void LaserPointer::RenderState::disable() {
} }
void LaserPointer::RenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY, void LaserPointer::RenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
bool faceAvatar, bool followNormal, float distance, const PickResultPointer& pickResult) { bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) {
StartEndRenderState::update(origin, end, surfaceNormal, scaleWithAvatar, distanceScaleEnd, centerEndY, faceAvatar, followNormal, distance, pickResult); StartEndRenderState::update(origin, end, surfaceNormal, scaleWithAvatar, distanceScaleEnd, centerEndY, faceAvatar, followNormal, followNormalStrength, distance, pickResult);
QVariant endVariant = vec3toVariant(end); QVariant endVariant = vec3toVariant(end);
if (!getPathID().isNull()) { if (!getPathID().isNull()) {
QVariantMap pathProps; QVariantMap pathProps;

View file

@ -30,7 +30,7 @@ public:
void cleanup() override; void cleanup() override;
void disable() override; void disable() override;
void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY, void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
bool faceAvatar, bool followNormal, float distance, const PickResultPointer& pickResult) override; bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) override;
private: private:
OverlayID _pathID; OverlayID _pathID;

View file

@ -10,8 +10,9 @@
#include "Application.h" #include "Application.h"
#include "display-plugins/CompositorHelper.h" #include "display-plugins/CompositorHelper.h"
MouseParabolaPick::MouseParabolaPick(float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, const PickFilter& filter, float maxDistance, bool enabled) : MouseParabolaPick::MouseParabolaPick(float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar,
ParabolaPick(speed, accelerationAxis, rotateAccelerationWithAvatar, filter, maxDistance, enabled) bool scaleWithAvatar, const PickFilter& filter, float maxDistance, bool enabled) :
ParabolaPick(speed, accelerationAxis, rotateAccelerationWithAvatar, scaleWithAvatar, filter, maxDistance, enabled)
{ {
} }
@ -20,7 +21,7 @@ PickParabola MouseParabolaPick::getMathematicalPick() const {
if (position.isValid()) { if (position.isValid()) {
QVariantMap posMap = position.toMap(); QVariantMap posMap = position.toMap();
PickRay pickRay = qApp->getCamera().computePickRay(posMap["x"].toFloat(), posMap["y"].toFloat()); PickRay pickRay = qApp->getCamera().computePickRay(posMap["x"].toFloat(), posMap["y"].toFloat());
return PickParabola(pickRay.origin, _speed * pickRay.direction, getAcceleration()); return PickParabola(pickRay.origin, getSpeed() * pickRay.direction, getAcceleration());
} }
return PickParabola(); return PickParabola();

View file

@ -13,7 +13,8 @@
class MouseParabolaPick : public ParabolaPick { class MouseParabolaPick : public ParabolaPick {
public: public:
MouseParabolaPick(float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, const PickFilter& filter, float maxDistance = 0.0f, bool enabled = false); MouseParabolaPick(float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, bool scaleWithAvatar,
const PickFilter& filter, float maxDistance = 0.0f, bool enabled = false);
PickParabola getMathematicalPick() const override; PickParabola getMathematicalPick() const override;

View file

@ -51,9 +51,14 @@ PickResultPointer ParabolaPick::getHUDIntersection(const PickParabola& pick) {
return std::make_shared<ParabolaPickResult>(IntersectionType::HUD, QUuid(), glm::distance(pick.origin, hudRes), parabolicDistance, hudRes, pick); return std::make_shared<ParabolaPickResult>(IntersectionType::HUD, QUuid(), glm::distance(pick.origin, hudRes), parabolicDistance, hudRes, pick);
} }
float ParabolaPick::getSpeed() const {
return _scaleWithAvatar ? DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale() * _speed : _speed;
}
glm::vec3 ParabolaPick::getAcceleration() const { glm::vec3 ParabolaPick::getAcceleration() const {
float scale = _scaleWithAvatar ? DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale() : 1.0f;
if (_rotateAccelerationWithAvatar) { if (_rotateAccelerationWithAvatar) {
return DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * _accelerationAxis; return scale * DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * _accelerationAxis;
} }
return _accelerationAxis; return scale * _accelerationAxis;
} }

View file

@ -74,8 +74,9 @@ public:
class ParabolaPick : public Pick<PickParabola> { class ParabolaPick : public Pick<PickParabola> {
public: public:
ParabolaPick(float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, const PickFilter& filter, float maxDistance, bool enabled) : ParabolaPick(float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, bool scaleWithAvatar, const PickFilter& filter, float maxDistance, bool enabled) :
Pick(filter, maxDistance, enabled), _speed(speed), _accelerationAxis(accelerationAxis), _rotateAccelerationWithAvatar(rotateAccelerationWithAvatar) {} Pick(filter, maxDistance, enabled), _speed(speed), _accelerationAxis(accelerationAxis), _rotateAccelerationWithAvatar(rotateAccelerationWithAvatar),
_scaleWithAvatar(scaleWithAvatar) {}
PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override { return std::make_shared<ParabolaPickResult>(pickVariant); } PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override { return std::make_shared<ParabolaPickResult>(pickVariant); }
PickResultPointer getEntityIntersection(const PickParabola& pick) override; PickResultPointer getEntityIntersection(const PickParabola& pick) override;
@ -87,7 +88,9 @@ protected:
float _speed; float _speed;
glm::vec3 _accelerationAxis; glm::vec3 _accelerationAxis;
bool _rotateAccelerationWithAvatar; bool _rotateAccelerationWithAvatar;
bool _scaleWithAvatar;
float getSpeed() const;
glm::vec3 getAcceleration() const; glm::vec3 getAcceleration() const;
}; };

View file

@ -163,8 +163,8 @@ void ParabolaPointer::RenderState::editParabola(const glm::vec3& color, float al
} }
void ParabolaPointer::RenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY, void ParabolaPointer::RenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
bool faceAvatar, bool followNormal, float distance, const PickResultPointer& pickResult) { bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) {
StartEndRenderState::update(origin, end, surfaceNormal, scaleWithAvatar, distanceScaleEnd, centerEndY, faceAvatar, followNormal, distance, pickResult); StartEndRenderState::update(origin, end, surfaceNormal, scaleWithAvatar, distanceScaleEnd, centerEndY, faceAvatar, followNormal, followNormalStrength, distance, pickResult);
auto parabolaPickResult = std::static_pointer_cast<ParabolaPickResult>(pickResult); auto parabolaPickResult = std::static_pointer_cast<ParabolaPickResult>(pickResult);
if (parabolaPickResult && render::Item::isValidID(_pathID)) { if (parabolaPickResult && render::Item::isValidID(_pathID)) {
render::Transaction transaction; render::Transaction transaction;

View file

@ -84,7 +84,7 @@ public:
void cleanup() override; void cleanup() override;
void disable() override; void disable() override;
void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY, void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
bool faceAvatar, bool followNormal, float distance, const PickResultPointer& pickResult) override; bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) override;
void editParabola(const glm::vec3& color, float alpha, float width, bool isVisibleInSecondaryCamera, bool enabled); void editParabola(const glm::vec3& color, float alpha, float width, bool isVisibleInSecondaryCamera, bool enabled);

View file

@ -149,18 +149,8 @@ void PathPointer::updateVisuals(const PickResultPointer& pickResult) {
glm::vec3 origin = getPickOrigin(pickResult); glm::vec3 origin = getPickOrigin(pickResult);
glm::vec3 end = getPickEnd(pickResult, _pathLength); glm::vec3 end = getPickEnd(pickResult, _pathLength);
glm::vec3 surfaceNormal = getPickedObjectNormal(pickResult); glm::vec3 surfaceNormal = getPickedObjectNormal(pickResult);
if (_followNormal && _followNormalStrength > 0.0f && _followNormalStrength < 1.0f) {
if (glm::any(glm::isnan(_avgNormal))) {
_avgNormal = surfaceNormal;
} else {
glm::quat a = Quat().lookAtSimple(glm::vec3(0.0f), _avgNormal);
glm::quat b = Quat().lookAtSimple(glm::vec3(0.0f), surfaceNormal);
surfaceNormal = glm::normalize(glm::slerp(a, b, _followNormalStrength) * Vectors::FRONT);
_avgNormal = surfaceNormal;
}
}
_renderStates[_currentRenderState]->update(origin, end, surfaceNormal, _scaleWithAvatar, _distanceScaleEnd, _centerEndY, _faceAvatar, _renderStates[_currentRenderState]->update(origin, end, surfaceNormal, _scaleWithAvatar, _distanceScaleEnd, _centerEndY, _faceAvatar,
_followNormal, _pathLength, pickResult); _followNormal, _followNormalStrength, _pathLength, pickResult);
if (_defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) { if (_defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
_defaultRenderStates[_currentRenderState].second->disable(); _defaultRenderStates[_currentRenderState].second->disable();
} }
@ -171,7 +161,7 @@ void PathPointer::updateVisuals(const PickResultPointer& pickResult) {
glm::vec3 origin = getPickOrigin(pickResult); glm::vec3 origin = getPickOrigin(pickResult);
glm::vec3 end = getPickEnd(pickResult, _defaultRenderStates[_currentRenderState].first); glm::vec3 end = getPickEnd(pickResult, _defaultRenderStates[_currentRenderState].first);
_defaultRenderStates[_currentRenderState].second->update(origin, end, Vectors::UP, _scaleWithAvatar, _distanceScaleEnd, _centerEndY, _defaultRenderStates[_currentRenderState].second->update(origin, end, Vectors::UP, _scaleWithAvatar, _distanceScaleEnd, _centerEndY,
_faceAvatar, _followNormal, _defaultRenderStates[_currentRenderState].first, pickResult); _faceAvatar, _followNormal, _followNormalStrength, _defaultRenderStates[_currentRenderState].first, pickResult);
} else if (!_currentRenderState.empty()) { } else if (!_currentRenderState.empty()) {
if (_renderStates.find(_currentRenderState) != _renderStates.end()) { if (_renderStates.find(_currentRenderState) != _renderStates.end()) {
_renderStates[_currentRenderState]->disable(); _renderStates[_currentRenderState]->disable();
@ -286,7 +276,7 @@ void StartEndRenderState::disable() {
} }
void StartEndRenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY, void StartEndRenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
bool faceAvatar, bool followNormal, float distance, const PickResultPointer& pickResult) { bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) {
if (!getStartID().isNull()) { if (!getStartID().isNull()) {
QVariantMap startProps; QVariantMap startProps;
startProps.insert("position", vec3toVariant(origin)); startProps.insert("position", vec3toVariant(origin));
@ -321,22 +311,29 @@ void StartEndRenderState::update(const glm::vec3& origin, const glm::vec3& end,
position = end + 0.5f * dim.y * avatarUp; position = end + 0.5f * dim.y * avatarUp;
} }
} }
endProps.insert("position", vec3toVariant(position));
if (faceAvatar) { if (faceAvatar) {
if (followNormal) { glm::quat orientation = followNormal ? normalQuat : DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation();
glm::quat lookAtWorld = Quat().lookAt(position, DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldPosition(), surfaceNormal); glm::quat lookAtWorld = Quat().lookAt(position, DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldPosition(), surfaceNormal);
glm::quat lookAtModel = glm::inverse(normalQuat) * lookAtWorld; glm::quat lookAtModel = glm::inverse(orientation) * lookAtWorld;
glm::quat lookAtFlatModel = Quat().cancelOutRollAndPitch(lookAtModel); glm::quat lookAtFlatModel = Quat().cancelOutRollAndPitch(lookAtModel);
glm::quat lookAtFlatWorld = normalQuat * lookAtFlatModel; glm::quat lookAtFlatWorld = orientation * lookAtFlatModel;
rotation = lookAtFlatWorld; rotation = lookAtFlatWorld;
} else if (followNormal) {
rotation = normalQuat;
}
if (followNormal && followNormalStrength > 0.0f && followNormalStrength < 1.0f) {
if (!_avgEndRotInitialized) {
_avgEndRot = rotation;
_avgEndRotInitialized = true;
} else { } else {
glm::quat lookAtWorld = Quat().lookAt(position, DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldPosition(), surfaceNormal); rotation = glm::slerp(_avgEndRot, rotation, followNormalStrength);
glm::quat lookAtModel = glm::inverse(DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation()) * lookAtWorld; if (!centerEndY) {
glm::quat lookAtFlatModel = Quat().cancelOutRollAndPitch(lookAtModel); position = end + 0.5f * dim.y * (rotation * Vectors::UP);
glm::quat lookAtFlatWorld = DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * lookAtFlatModel; }
rotation = lookAtFlatWorld; _avgEndRot = rotation;
} }
} }
endProps.insert("position", vec3toVariant(position));
endProps.insert("rotation", quatToVariant(rotation)); endProps.insert("rotation", quatToVariant(rotation));
endProps.insert("visible", true); endProps.insert("visible", true);
endProps.insert("ignoreRayIntersection", doesEndIgnoreRays()); endProps.insert("ignoreRayIntersection", doesEndIgnoreRays());

View file

@ -45,7 +45,7 @@ public:
virtual void cleanup(); virtual void cleanup();
virtual void disable(); virtual void disable();
virtual void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY, virtual void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
bool faceAvatar, bool followNormal, float distance, const PickResultPointer& pickResult); bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult);
protected: protected:
OverlayID _startID; OverlayID _startID;
@ -56,6 +56,9 @@ protected:
glm::vec3 _startDim; glm::vec3 _startDim;
glm::vec3 _endDim; glm::vec3 _endDim;
glm::quat _endRot; glm::quat _endRot;
glm::quat _avgEndRot;
bool _avgEndRotInitialized { false };
}; };
typedef std::unordered_map<std::string, std::shared_ptr<StartEndRenderState>> RenderStateMap; typedef std::unordered_map<std::string, std::shared_ptr<StartEndRenderState>> RenderStateMap;
@ -87,7 +90,6 @@ protected:
bool _faceAvatar; bool _faceAvatar;
bool _followNormal; bool _followNormal;
float _followNormalStrength; float _followNormalStrength;
glm::vec3 _avgNormal { NAN };
bool _centerEndY; bool _centerEndY;
bool _lockEnd; bool _lockEnd;
bool _distanceScaleEnd; bool _distanceScaleEnd;

View file

@ -154,7 +154,8 @@ unsigned int PickScriptingInterface::createStylusPick(const QVariant& properties
* @property {Vec3} [direction=-Vec3.FRONT] Only for Static Parabola Picks. The world-space direction of the parabola segment. * @property {Vec3} [direction=-Vec3.FRONT] Only for Static Parabola Picks. The world-space direction of the parabola segment.
* @property {number} [speed=1] The initial speed of the parabola, i.e. the initial speed of the projectile whose trajectory defines the parabola. * @property {number} [speed=1] The initial speed of the parabola, i.e. the initial speed of the projectile whose trajectory defines the parabola.
* @property {Vec3} [accelerationAxis=-Vec3.UP] The acceleration of the parabola, i.e. the acceleration of the projectile whose trajectory defines the parabola, both magnitude and direction. * @property {Vec3} [accelerationAxis=-Vec3.UP] The acceleration of the parabola, i.e. the acceleration of the projectile whose trajectory defines the parabola, both magnitude and direction.
* @property {boolean} [rotateWithAvatar=true] Whether or not the acceleration axis should rotate with your avatar's local Y axis. * @property {boolean} [rotateAccelerationWithAvatar=true] Whether or not the acceleration axis should rotate with your avatar's local Y axis.
* @property {boolean} [scaleWithAvatar=false] If true, the velocity and acceleration of the Pick will scale linearly with your avatar.
*/ */
unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properties) { unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properties) {
QVariantMap propMap = properties.toMap(); QVariantMap propMap = properties.toMap();
@ -189,6 +190,11 @@ unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properti
rotateAccelerationWithAvatar = propMap["rotateAccelerationWithAvatar"].toBool(); rotateAccelerationWithAvatar = propMap["rotateAccelerationWithAvatar"].toBool();
} }
bool scaleWithAvatar = false;
if (propMap["scaleWithAvatar"].isValid()) {
scaleWithAvatar = propMap["scaleWithAvatar"].toBool();
}
if (propMap["joint"].isValid()) { if (propMap["joint"].isValid()) {
std::string jointName = propMap["joint"].toString().toStdString(); std::string jointName = propMap["joint"].toString().toStdString();
@ -205,10 +211,12 @@ unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properti
} }
return DependencyManager::get<PickManager>()->addPick(PickQuery::Parabola, std::make_shared<JointParabolaPick>(jointName, posOffset, dirOffset, return DependencyManager::get<PickManager>()->addPick(PickQuery::Parabola, std::make_shared<JointParabolaPick>(jointName, posOffset, dirOffset,
speed, accelerationAxis, rotateAccelerationWithAvatar, filter, maxDistance, enabled)); speed, accelerationAxis, rotateAccelerationWithAvatar,
scaleWithAvatar, filter, maxDistance, enabled));
} else { } else {
return DependencyManager::get<PickManager>()->addPick(PickQuery::Parabola, std::make_shared<MouseParabolaPick>(speed, accelerationAxis, rotateAccelerationWithAvatar, filter, maxDistance, enabled)); return DependencyManager::get<PickManager>()->addPick(PickQuery::Parabola, std::make_shared<MouseParabolaPick>(speed, accelerationAxis, rotateAccelerationWithAvatar,
scaleWithAvatar, filter, maxDistance, enabled));
} }
} else if (propMap["position"].isValid()) { } else if (propMap["position"].isValid()) {
glm::vec3 position = vec3FromVariant(propMap["position"]); glm::vec3 position = vec3FromVariant(propMap["position"]);
@ -218,7 +226,9 @@ unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properti
direction = vec3FromVariant(propMap["direction"]); direction = vec3FromVariant(propMap["direction"]);
} }
return DependencyManager::get<PickManager>()->addPick(PickQuery::Parabola, std::make_shared<StaticParabolaPick>(position, direction, speed, accelerationAxis, rotateAccelerationWithAvatar, filter, maxDistance, enabled)); return DependencyManager::get<PickManager>()->addPick(PickQuery::Parabola, std::make_shared<StaticParabolaPick>(position, direction, speed, accelerationAxis,
rotateAccelerationWithAvatar, scaleWithAvatar,
filter, maxDistance, enabled));
} }
return PickManager::INVALID_PICK_ID; return PickManager::INVALID_PICK_ID;

View file

@ -132,7 +132,7 @@ unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& prope
scaleWithAvatar = propertyMap["scaleWithAvatar"].toBool(); scaleWithAvatar = propertyMap["scaleWithAvatar"].toBool();
} }
bool followNormal = true; bool followNormal = false;
if (propertyMap["followNormal"].isValid()) { if (propertyMap["followNormal"].isValid()) {
followNormal = propertyMap["followNormal"].toBool(); followNormal = propertyMap["followNormal"].toBool();
} }
@ -275,7 +275,7 @@ unsigned int PointerScriptingInterface::createParabolaPointer(const QVariant& pr
scaleWithAvatar = propertyMap["scaleWithAvatar"].toBool(); scaleWithAvatar = propertyMap["scaleWithAvatar"].toBool();
} }
bool followNormal = true; bool followNormal = false;
if (propertyMap["followNormal"].isValid()) { if (propertyMap["followNormal"].isValid()) {
followNormal = propertyMap["followNormal"].toBool(); followNormal = propertyMap["followNormal"].toBool();
} }

View file

@ -7,13 +7,13 @@
// //
#include "StaticParabolaPick.h" #include "StaticParabolaPick.h"
StaticParabolaPick::StaticParabolaPick(const glm::vec3& position, const glm::vec3& direction, float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, StaticParabolaPick::StaticParabolaPick(const glm::vec3& position, const glm::vec3& direction, float speed, const glm::vec3& accelerationAxis,
const PickFilter& filter, float maxDistance, bool enabled) : bool scaleWithAvatar, bool rotateAccelerationWithAvatar, const PickFilter& filter, float maxDistance, bool enabled) :
ParabolaPick(speed, accelerationAxis, rotateAccelerationWithAvatar, filter, maxDistance, enabled), ParabolaPick(speed, accelerationAxis, rotateAccelerationWithAvatar, scaleWithAvatar, filter, maxDistance, enabled),
_position(position), _velocity(speed * direction) _position(position), _velocity(direction)
{ {
} }
PickParabola StaticParabolaPick::getMathematicalPick() const { PickParabola StaticParabolaPick::getMathematicalPick() const {
return PickParabola(_position, _velocity, getAcceleration()); return PickParabola(_position, getSpeed() * _velocity, getAcceleration());
} }

View file

@ -14,7 +14,7 @@ class StaticParabolaPick : public ParabolaPick {
public: public:
StaticParabolaPick(const glm::vec3& position, const glm::vec3& direction, float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, StaticParabolaPick(const glm::vec3& position, const glm::vec3& direction, float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar,
const PickFilter& filter, float maxDistance = 0.0f, bool enabled = false); bool scaleWithAvatar, const PickFilter& filter, float maxDistance = 0.0f, bool enabled = false);
PickParabola getMathematicalPick() const override; PickParabola getMathematicalPick() const override;

View file

@ -135,7 +135,6 @@ bool TriangleSet::TriangleOctreeCell::findRayIntersectionInternal(const glm::vec
} }
} else { } else {
intersectedSomething = true; intersectedSomething = true;
// FIXME: this needs to set triangle to something or it will carry the previous value
bestDistance = distance; bestDistance = distance;
} }
@ -168,7 +167,6 @@ bool TriangleSet::TriangleOctreeCell::findParabolaIntersectionInternal(const glm
} }
} else { } else {
intersectedSomething = true; intersectedSomething = true;
// FIXME: this needs to set triangle to something or it will carry the previous value
bestDistance = parabolicDistance; bestDistance = parabolicDistance;
} }
@ -263,29 +261,28 @@ bool TriangleSet::TriangleOctreeCell::findRayIntersection(const glm::vec3& origi
bool intersects = false; bool intersects = false;
float boxDistance = FLT_MAX; float boxDistance = FLT_MAX;
// if the ray intersects our bounding box, then continue // if the pick intersects our bounding box, then continue
if (getBounds().findRayIntersection(origin, direction, boxDistance, bestLocalFace, bestLocalNormal)) { if (getBounds().findRayIntersection(origin, direction, boxDistance, bestLocalFace, bestLocalNormal)) {
// if the intersection with our bounding box, is greater than the current best distance (the distance passed in) // if the intersection with our bounding box, is greater than the current best distance (the distance passed in)
// then we know that none of our triangles can represent a better intersection and we can return // then we know that none of our triangles can represent a better intersection and we can return
if (bestLocalDistance > distance) { if (boxDistance > distance) {
return false; return false;
} }
bestLocalDistance = distance;
float childDistance = distance;
BoxFace childFace;
Triangle childTriangle;
// if we're not yet at the max depth, then check which child the triangle fits in // if we're not yet at the max depth, then check which child the triangle fits in
if (_depth < MAX_DEPTH) { if (_depth < MAX_DEPTH) {
float bestChildDistance = FLT_MAX;
for (auto& child : _children) { for (auto& child : _children) {
// check each child, if there's an intersection, it will return some distance that we need // check each child, if there's an intersection, it will return some distance that we need
// to compare against the other results, because there might be multiple intersections and // to compare against the other results, because there might be multiple intersections and
// we will always choose the best (shortest) intersection // we will always choose the best (shortest) intersection
float childDistance = bestChildDistance;
BoxFace childFace;
Triangle childTriangle;
if (child.second.findRayIntersection(origin, direction, childDistance, childFace, childTriangle, precision, trianglesTouched)) { if (child.second.findRayIntersection(origin, direction, childDistance, childFace, childTriangle, precision, trianglesTouched)) {
if (childDistance < bestLocalDistance) { if (childDistance < bestLocalDistance) {
bestLocalDistance = childDistance; bestLocalDistance = childDistance;
bestChildDistance = childDistance;
bestLocalFace = childFace; bestLocalFace = childFace;
bestLocalTriangle = childTriangle; bestLocalTriangle = childTriangle;
intersects = true; intersects = true;
@ -298,7 +295,7 @@ bool TriangleSet::TriangleOctreeCell::findRayIntersection(const glm::vec3& origi
BoxFace internalFace; BoxFace internalFace;
Triangle internalTriangle; Triangle internalTriangle;
if (findRayIntersectionInternal(origin, direction, internalDistance, internalFace, internalTriangle, precision, trianglesTouched, allowBackface)) { if (findRayIntersectionInternal(origin, direction, internalDistance, internalFace, internalTriangle, precision, trianglesTouched, allowBackface)) {
if (internalDistance < childDistance) { if (internalDistance < bestLocalDistance) {
bestLocalDistance = internalDistance; bestLocalDistance = internalDistance;
bestLocalFace = internalFace; bestLocalFace = internalFace;
bestLocalTriangle = internalTriangle; bestLocalTriangle = internalTriangle;
@ -329,29 +326,28 @@ bool TriangleSet::TriangleOctreeCell::findParabolaIntersection(const glm::vec3&
bool intersects = false; bool intersects = false;
float boxDistance = FLT_MAX; float boxDistance = FLT_MAX;
// if the ray intersects our bounding box, then continue // if the pick intersects our bounding box, then continue
if (getBounds().findParabolaIntersection(origin, velocity, acceleration, boxDistance, bestLocalFace, bestLocalNormal)) { if (getBounds().findParabolaIntersection(origin, velocity, acceleration, boxDistance, bestLocalFace, bestLocalNormal)) {
// if the intersection with our bounding box, is greater than the current best distance (the distance passed in) // if the intersection with our bounding box, is greater than the current best distance (the distance passed in)
// then we know that none of our triangles can represent a better intersection and we can return // then we know that none of our triangles can represent a better intersection and we can return
if (bestLocalDistance > parabolicDistance) { if (boxDistance > parabolicDistance) {
return false; return false;
} }
bestLocalDistance = parabolicDistance;
float childDistance = parabolicDistance;
BoxFace childFace;
Triangle childTriangle;
// if we're not yet at the max depth, then check which child the triangle fits in // if we're not yet at the max depth, then check which child the triangle fits in
if (_depth < MAX_DEPTH) { if (_depth < MAX_DEPTH) {
float bestChildDistance = FLT_MAX;
for (auto& child : _children) { for (auto& child : _children) {
// check each child, if there's an intersection, it will return some distance that we need // check each child, if there's an intersection, it will return some distance that we need
// to compare against the other results, because there might be multiple intersections and // to compare against the other results, because there might be multiple intersections and
// we will always choose the best (shortest) intersection // we will always choose the best (shortest) intersection
float childDistance = bestChildDistance;
BoxFace childFace;
Triangle childTriangle;
if (child.second.findParabolaIntersection(origin, velocity, acceleration, childDistance, childFace, childTriangle, precision, trianglesTouched)) { if (child.second.findParabolaIntersection(origin, velocity, acceleration, childDistance, childFace, childTriangle, precision, trianglesTouched)) {
if (childDistance < bestLocalDistance) { if (childDistance < bestLocalDistance) {
bestLocalDistance = childDistance; bestLocalDistance = childDistance;
bestChildDistance = childDistance;
bestLocalFace = childFace; bestLocalFace = childFace;
bestLocalTriangle = childTriangle; bestLocalTriangle = childTriangle;
intersects = true; intersects = true;
@ -364,7 +360,7 @@ bool TriangleSet::TriangleOctreeCell::findParabolaIntersection(const glm::vec3&
BoxFace internalFace; BoxFace internalFace;
Triangle internalTriangle; Triangle internalTriangle;
if (findParabolaIntersectionInternal(origin, velocity, acceleration, internalDistance, internalFace, internalTriangle, precision, trianglesTouched, allowBackface)) { if (findParabolaIntersectionInternal(origin, velocity, acceleration, internalDistance, internalFace, internalTriangle, precision, trianglesTouched, allowBackface)) {
if (internalDistance < childDistance) { if (internalDistance < bestLocalDistance) {
bestLocalDistance = internalDistance; bestLocalDistance = internalDistance;
bestLocalFace = internalFace; bestLocalFace = internalFace;
bestLocalTriangle = internalTriangle; bestLocalTriangle = internalTriangle;

View file

@ -49,7 +49,6 @@ Script.include("/~/system/libraries/controllers.js");
blue: 73 blue: 73
}; };
var TELEPORT_CANCEL_RANGE = 1;
var COOL_IN_DURATION = 300; var COOL_IN_DURATION = 300;
var handInfo = { var handInfo = {
@ -146,8 +145,6 @@ Script.include("/~/system/libraries/controllers.js");
faceAvatar: true, faceAvatar: true,
scaleWithAvatar: true, scaleWithAvatar: true,
centerEndY: false, centerEndY: false,
followNormal: true,
followNormalStrength: 0.1,
speed: speed, speed: speed,
accelerationAxis: accelerationAxis, accelerationAxis: accelerationAxis,
rotateAccelerationWithAvatar: true, rotateAccelerationWithAvatar: true,
@ -161,8 +158,6 @@ Script.include("/~/system/libraries/controllers.js");
faceAvatar: true, faceAvatar: true,
scaleWithAvatar: true, scaleWithAvatar: true,
centerEndY: false, centerEndY: false,
followNormal: true,
followNormalStrength: 0.1,
speed: speed, speed: speed,
accelerationAxis: accelerationAxis, accelerationAxis: accelerationAxis,
rotateAccelerationWithAvatar: true, rotateAccelerationWithAvatar: true,
@ -175,8 +170,6 @@ Script.include("/~/system/libraries/controllers.js");
faceAvatar: true, faceAvatar: true,
scaleWithAvatar: true, scaleWithAvatar: true,
centerEndY: false, centerEndY: false,
followNormal: true,
followNormalStrength: 0.1,
speed: speed, speed: speed,
accelerationAxis: accelerationAxis, accelerationAxis: accelerationAxis,
rotateAccelerationWithAvatar: true, rotateAccelerationWithAvatar: true,
@ -190,8 +183,6 @@ Script.include("/~/system/libraries/controllers.js");
faceAvatar: true, faceAvatar: true,
scaleWithAvatar: true, scaleWithAvatar: true,
centerEndY: false, centerEndY: false,
followNormal: true,
followNormalStrength: 0.1,
speed: speed, speed: speed,
accelerationAxis: accelerationAxis, accelerationAxis: accelerationAxis,
rotateAccelerationWithAvatar: true, rotateAccelerationWithAvatar: true,
@ -440,8 +431,7 @@ Script.include("/~/system/libraries/controllers.js");
var surfaceNormal = result.surfaceNormal; var surfaceNormal = result.surfaceNormal;
var angle = Math.acos(Vec3.dot(surfaceNormal, Quat.getUp(MyAvatar.orientation))) * (180.0 / Math.PI); var angle = Math.acos(Vec3.dot(surfaceNormal, Quat.getUp(MyAvatar.orientation))) * (180.0 / Math.PI);
if (angle > MAX_ANGLE_FROM_UP_TO_TELEPORT || if (angle > MAX_ANGLE_FROM_UP_TO_TELEPORT) {
Vec3.distance(MyAvatar.position, result.intersection) <= TELEPORT_CANCEL_RANGE * MyAvatar.sensorToWorldScale) {
return TARGET.INVALID; return TARGET.INVALID;
} else { } else {
return TARGET.SURFACE; return TARGET.SURFACE;