Merge branch 'dejitter-hold-action' of github.com:sethalves/hifi into near-grab-via-parenting

This commit is contained in:
Seth Alves 2015-12-16 15:56:31 -08:00
commit 9e5116bf4f
31 changed files with 306 additions and 169 deletions

View file

@ -1260,15 +1260,14 @@ void Application::paintGL() {
hmdOffset.x = -hmdOffset.x; hmdOffset.x = -hmdOffset.x;
_myCamera.setPosition(myAvatar->getDefaultEyePosition() _myCamera.setPosition(myAvatar->getDefaultEyePosition()
+ glm::vec3(0, _raiseMirror * myAvatar->getAvatarScale(), 0) + glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0)
+ mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror + mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror
+ mirrorBodyOrientation * hmdOffset); + mirrorBodyOrientation * hmdOffset);
} else { } else {
_myCamera.setRotation(myAvatar->getWorldAlignedOrientation() _myCamera.setRotation(myAvatar->getWorldAlignedOrientation()
* glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
_myCamera.setPosition(myAvatar->getDefaultEyePosition() _myCamera.setPosition(myAvatar->getDefaultEyePosition()
+ glm::vec3(0, _raiseMirror * myAvatar->getAvatarScale(), 0) + glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0)
+ (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) * + (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
} }
@ -2989,6 +2988,9 @@ void Application::update(float deltaTime) {
_physicsEngine->changeObjects(motionStates); _physicsEngine->changeObjects(motionStates);
myAvatar->prepareForPhysicsSimulation(); myAvatar->prepareForPhysicsSimulation();
_physicsEngine->forEachAction([&](EntityActionPointer action) {
action->prepareForPhysicsSimulation();
});
getEntities()->getTree()->withWriteLock([&] { getEntities()->getTree()->withWriteLock([&] {
_physicsEngine->stepSimulation(); _physicsEngine->stepSimulation();

View file

@ -99,7 +99,8 @@ Avatar::Avatar(RigPointer rig) :
// we may have been created in the network thread, but we live in the main thread // we may have been created in the network thread, but we live in the main thread
moveToThread(qApp->thread()); moveToThread(qApp->thread());
setAvatarScale(1.0f); setScale(glm::vec3(1.0f)); // avatar scale is uniform
// give the pointer to our head to inherited _headData variable from AvatarData // give the pointer to our head to inherited _headData variable from AvatarData
_headData = static_cast<HeadData*>(new Head(this)); _headData = static_cast<HeadData*>(new Head(this));
_handData = static_cast<HandData*>(new Hand(this)); _handData = static_cast<HandData*>(new Hand(this));
@ -143,15 +144,35 @@ AABox Avatar::getBounds() const {
float Avatar::getLODDistance() const { float Avatar::getLODDistance() const {
return DependencyManager::get<LODManager>()->getAvatarLODDistanceMultiplier() * return DependencyManager::get<LODManager>()->getAvatarLODDistanceMultiplier() *
glm::distance(qApp->getCamera()->getPosition(), getPosition()) / getAvatarScale(); glm::distance(qApp->getCamera()->getPosition(), getPosition()) / getUniformScale();
}
void Avatar::animateScaleChanges(float deltaTime) {
float currentScale = getUniformScale();
if (currentScale != _targetScale) {
// use exponential decay toward _targetScale
const float SCALE_ANIMATION_TIMESCALE = 0.5f;
float blendFactor = glm::clamp(deltaTime / SCALE_ANIMATION_TIMESCALE, 0.0f, 1.0f);
float animatedScale = (1.0f - blendFactor) * currentScale + blendFactor * _targetScale;
// snap to the end when we get close enough
const float MIN_RELATIVE_SCALE_ERROR = 0.03f;
if (fabsf(_targetScale - currentScale) / _targetScale < 0.03f) {
animatedScale = _targetScale;
}
setScale(glm::vec3(animatedScale)); // avatar scale is uniform
rebuildCollisionShape();
}
} }
void Avatar::simulate(float deltaTime) { void Avatar::simulate(float deltaTime) {
PerformanceTimer perfTimer("simulate"); PerformanceTimer perfTimer("simulate");
if (getAvatarScale() != _targetScale) { if (!isDead() && !_motionState) {
setAvatarScale(_targetScale); DependencyManager::get<AvatarManager>()->addAvatarToSimulation(this);
} }
animateScaleChanges(deltaTime);
// update the billboard render flag // update the billboard render flag
const float BILLBOARD_HYSTERESIS_PROPORTION = 0.1f; const float BILLBOARD_HYSTERESIS_PROPORTION = 0.1f;
@ -210,7 +231,7 @@ void Avatar::simulate(float deltaTime) {
_skeletonModel.getHeadPosition(headPosition); _skeletonModel.getHeadPosition(headPosition);
Head* head = getHead(); Head* head = getHead();
head->setPosition(headPosition); head->setPosition(headPosition);
head->setScale(getAvatarScale()); head->setScale(getUniformScale());
head->simulate(deltaTime, false, _shouldRenderBillboard); head->simulate(deltaTime, false, _shouldRenderBillboard);
} }
} }
@ -238,12 +259,12 @@ void Avatar::simulate(float deltaTime) {
measureMotionDerivatives(deltaTime); measureMotionDerivatives(deltaTime);
} }
bool Avatar::isLookingAtMe(AvatarSharedPointer avatar) { bool Avatar::isLookingAtMe(AvatarSharedPointer avatar) const {
const float HEAD_SPHERE_RADIUS = 0.1f; const float HEAD_SPHERE_RADIUS = 0.1f;
glm::vec3 theirLookAt = dynamic_pointer_cast<Avatar>(avatar)->getHead()->getLookAtPosition(); glm::vec3 theirLookAt = dynamic_pointer_cast<Avatar>(avatar)->getHead()->getLookAtPosition();
glm::vec3 myEyePosition = getHead()->getEyePosition(); glm::vec3 myEyePosition = getHead()->getEyePosition();
return glm::distance(theirLookAt, myEyePosition) <= (HEAD_SPHERE_RADIUS * getAvatarScale()); return glm::distance(theirLookAt, myEyePosition) <= (HEAD_SPHERE_RADIUS * getUniformScale());
} }
void Avatar::slamPosition(const glm::vec3& newPosition) { void Avatar::slamPosition(const glm::vec3& newPosition) {
@ -423,7 +444,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
const float BASE_LIGHT_DISTANCE = 2.0f; const float BASE_LIGHT_DISTANCE = 2.0f;
const float LIGHT_EXPONENT = 1.0f; const float LIGHT_EXPONENT = 1.0f;
const float LIGHT_CUTOFF = glm::radians(80.0f); const float LIGHT_CUTOFF = glm::radians(80.0f);
float distance = BASE_LIGHT_DISTANCE * getAvatarScale(); float distance = BASE_LIGHT_DISTANCE * getUniformScale();
glm::vec3 position = glm::mix(_skeletonModel.getTranslation(), getHead()->getFaceModel().getTranslation(), 0.9f); glm::vec3 position = glm::mix(_skeletonModel.getTranslation(), getHead()->getFaceModel().getTranslation(), 0.9f);
glm::quat orientation = getOrientation(); glm::quat orientation = getOrientation();
foreach (const AvatarManager::LocalLight& light, DependencyManager::get<AvatarManager>()->getLocalLights()) { foreach (const AvatarManager::LocalLight& light, DependencyManager::get<AvatarManager>()->getLocalLights()) {
@ -436,7 +457,8 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
bool renderBounding = Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes); bool renderBounding = Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes);
if (renderBounding && shouldRenderHead(renderArgs) && _skeletonModel.isRenderable()) { if (renderBounding && shouldRenderHead(renderArgs) && _skeletonModel.isRenderable()) {
PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes"); PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes");
_skeletonModel.renderBoundingCollisionShapes(*renderArgs->_batch, 0.7f); const float BOUNDING_SHAPE_ALPHA = 0.7f;
_skeletonModel.renderBoundingCollisionShapes(*renderArgs->_batch, getUniformScale(), BOUNDING_SHAPE_ALPHA);
} }
// If this is the avatar being looked at, render a little ball above their head // If this is the avatar being looked at, render a little ball above their head
@ -479,7 +501,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
} }
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch, DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch,
Transform(transform).postScale(eyeDiameter * getAvatarScale() / 2.0f + RADIUS_INCREMENT), Transform(transform).postScale(eyeDiameter * getUniformScale() / 2.0f + RADIUS_INCREMENT),
glm::vec4(LOOKING_AT_ME_COLOR, alpha)); glm::vec4(LOOKING_AT_ME_COLOR, alpha));
position = getHead()->getRightEyePosition(); position = getHead()->getRightEyePosition();
@ -489,7 +511,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
eyeDiameter = DEFAULT_EYE_DIAMETER; eyeDiameter = DEFAULT_EYE_DIAMETER;
} }
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch, DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch,
Transform(transform).postScale(eyeDiameter * getAvatarScale() / 2.0f + RADIUS_INCREMENT), Transform(transform).postScale(eyeDiameter * getUniformScale() / 2.0f + RADIUS_INCREMENT),
glm::vec4(LOOKING_AT_ME_COLOR, alpha)); glm::vec4(LOOKING_AT_ME_COLOR, alpha));
} }
@ -590,9 +612,9 @@ void Avatar::simulateAttachments(float deltaTime) {
glm::quat jointRotation; glm::quat jointRotation;
if (_skeletonModel.getJointPositionInWorldFrame(jointIndex, jointPosition) && if (_skeletonModel.getJointPositionInWorldFrame(jointIndex, jointPosition) &&
_skeletonModel.getJointRotationInWorldFrame(jointIndex, jointRotation)) { _skeletonModel.getJointRotationInWorldFrame(jointIndex, jointRotation)) {
model->setTranslation(jointPosition + jointRotation * attachment.translation * getAvatarScale()); model->setTranslation(jointPosition + jointRotation * attachment.translation * getUniformScale());
model->setRotation(jointRotation * attachment.rotation); model->setRotation(jointRotation * attachment.rotation);
model->setScaleToFit(true, getAvatarScale() * attachment.scale, true); // hack to force rescale model->setScaleToFit(true, getUniformScale() * attachment.scale, true); // hack to force rescale
model->setSnapModelToCenter(false); // hack to force resnap model->setSnapModelToCenter(false); // hack to force resnap
model->setSnapModelToCenter(true); model->setSnapModelToCenter(true);
model->simulate(deltaTime); model->simulate(deltaTime);
@ -647,7 +669,7 @@ void Avatar::renderBillboard(RenderArgs* renderArgs) {
} }
float Avatar::getBillboardSize() const { float Avatar::getBillboardSize() const {
return getAvatarScale() * BILLBOARD_DISTANCE * glm::tan(glm::radians(BILLBOARD_FIELD_OF_VIEW / 2.0f)); return getUniformScale() * BILLBOARD_DISTANCE * glm::tan(glm::radians(BILLBOARD_FIELD_OF_VIEW / 2.0f));
} }
#ifdef DEBUG #ifdef DEBUG
@ -796,7 +818,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, co
} }
void Avatar::setSkeletonOffset(const glm::vec3& offset) { void Avatar::setSkeletonOffset(const glm::vec3& offset) {
const float MAX_OFFSET_LENGTH = getAvatarScale() * 0.5f; const float MAX_OFFSET_LENGTH = getUniformScale() * 0.5f;
float offsetLength = glm::length(offset); float offsetLength = glm::length(offset);
if (offsetLength > MAX_OFFSET_LENGTH) { if (offsetLength > MAX_OFFSET_LENGTH) {
_skeletonOffset = (MAX_OFFSET_LENGTH / offsetLength) * offset; _skeletonOffset = (MAX_OFFSET_LENGTH / offsetLength) * offset;
@ -905,7 +927,7 @@ glm::vec3 Avatar::getJointPosition(const QString& name) const {
void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const { void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const {
//Scale a world space vector as if it was relative to the position //Scale a world space vector as if it was relative to the position
positionToScale = getPosition() + getAvatarScale() * (positionToScale - getPosition()); positionToScale = getPosition() + getUniformScale() * (positionToScale - getPosition());
} }
void Avatar::setFaceModelURL(const QUrl& faceModelURL) { void Avatar::setFaceModelURL(const QUrl& faceModelURL) {
@ -945,7 +967,7 @@ void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
for (int i = 0; i < attachmentData.size(); i++) { for (int i = 0; i < attachmentData.size(); i++) {
_attachmentModels[i]->setURL(attachmentData.at(i).modelURL); _attachmentModels[i]->setURL(attachmentData.at(i).modelURL);
_attachmentModels[i]->setSnapModelToCenter(true); _attachmentModels[i]->setSnapModelToCenter(true);
_attachmentModels[i]->setScaleToFit(true, getAvatarScale() * _attachmentData.at(i).scale); _attachmentModels[i]->setScaleToFit(true, getUniformScale() * _attachmentData.at(i).scale);
} }
} }
@ -1036,15 +1058,6 @@ void Avatar::renderJointConnectingCone(gpu::Batch& batch, glm::vec3 position1, g
} }
} }
void Avatar::setAvatarScale(float scale) {
if (_targetScale * (1.0f - RESCALING_TOLERANCE) < scale &&
scale < _targetScale * (1.0f + RESCALING_TOLERANCE)) {
setScale(glm::vec3(_targetScale));
} else {
setScale(glm::vec3(scale));
}
}
float Avatar::getSkeletonHeight() const { float Avatar::getSkeletonHeight() const {
Extents extents = _skeletonModel.getBindExtents(); Extents extents = _skeletonModel.getBindExtents();
return extents.maximum.y - extents.minimum.y; return extents.maximum.y - extents.minimum.y;
@ -1056,7 +1069,7 @@ float Avatar::getHeadHeight() const {
// HACK: We have a really odd case when fading out for some models where this value explodes // HACK: We have a really odd case when fading out for some models where this value explodes
float result = extents.maximum.y - extents.minimum.y; float result = extents.maximum.y - extents.minimum.y;
if (result >= 0.0f && result < 100.0f * getAvatarScale() ) { if (result >= 0.0f && result < 100.0f * getUniformScale() ) {
return result; return result;
} }
} }
@ -1099,13 +1112,21 @@ void Avatar::setShowDisplayName(bool showDisplayName) {
// virtual // virtual
void Avatar::computeShapeInfo(ShapeInfo& shapeInfo) { void Avatar::computeShapeInfo(ShapeInfo& shapeInfo) {
shapeInfo.setCapsuleY(_skeletonModel.getBoundingCapsuleRadius(), 0.5f * _skeletonModel.getBoundingCapsuleHeight()); float uniformScale = getUniformScale();
shapeInfo.setOffset(_skeletonModel.getBoundingCapsuleOffset()); shapeInfo.setCapsuleY(uniformScale * _skeletonModel.getBoundingCapsuleRadius(),
0.5f * uniformScale * _skeletonModel.getBoundingCapsuleHeight());
shapeInfo.setOffset(uniformScale * _skeletonModel.getBoundingCapsuleOffset());
}
void Avatar::setMotionState(AvatarMotionState* motionState) {
_motionState = motionState;
} }
// virtual // virtual
void Avatar::rebuildSkeletonBody() { void Avatar::rebuildCollisionShape() {
DependencyManager::get<AvatarManager>()->updateAvatarPhysicsShape(this); if (_motionState) {
_motionState->addDirtyFlags(Simulation::DIRTY_SHAPE);
}
} }
glm::vec3 Avatar::getLeftPalmPosition() { glm::vec3 Avatar::getLeftPalmPosition() {

View file

@ -36,7 +36,6 @@ namespace render {
static const float SCALING_RATIO = .05f; static const float SCALING_RATIO = .05f;
static const float SMOOTHING_RATIO = .05f; // 0 < ratio < 1 static const float SMOOTHING_RATIO = .05f; // 0 < ratio < 1
static const float RESCALING_TOLERANCE = .02f;
static const float BILLBOARD_FIELD_OF_VIEW = 30.0f; // degrees static const float BILLBOARD_FIELD_OF_VIEW = 30.0f; // degrees
static const float BILLBOARD_DISTANCE = 5.56f; // meters static const float BILLBOARD_DISTANCE = 5.56f; // meters
@ -89,7 +88,7 @@ public:
SkeletonModel& getSkeletonModel() { return _skeletonModel; } SkeletonModel& getSkeletonModel() { return _skeletonModel; }
const SkeletonModel& getSkeletonModel() const { return _skeletonModel; } const SkeletonModel& getSkeletonModel() const { return _skeletonModel; }
glm::vec3 getChestPosition() const; glm::vec3 getChestPosition() const;
float getAvatarScale() const { return getScale().y; } float getUniformScale() const { return getScale().y; }
const Head* getHead() const { return static_cast<const Head*>(_headData); } const Head* getHead() const { return static_cast<const Head*>(_headData); }
Head* getHead() { return static_cast<Head*>(_headData); } Head* getHead() { return static_cast<Head*>(_headData); }
Hand* getHand() { return static_cast<Hand*>(_handData); } Hand* getHand() { return static_cast<Hand*>(_handData); }
@ -154,11 +153,10 @@ public:
// (otherwise floating point error will cause problems at large positions). // (otherwise floating point error will cause problems at large positions).
void applyPositionDelta(const glm::vec3& delta); void applyPositionDelta(const glm::vec3& delta);
virtual void rebuildSkeletonBody(); virtual void rebuildCollisionShape();
virtual void computeShapeInfo(ShapeInfo& shapeInfo); virtual void computeShapeInfo(ShapeInfo& shapeInfo);
void setMotionState(AvatarMotionState* motionState) { _motionState = motionState; }
AvatarMotionState* getMotionState() { return _motionState; } AvatarMotionState* getMotionState() { return _motionState; }
using SpatiallyNestable::setPosition; using SpatiallyNestable::setPosition;
@ -175,6 +173,10 @@ public slots:
glm::quat getRightPalmRotation(); glm::quat getRightPalmRotation();
protected: protected:
friend class AvatarManager;
void setMotionState(AvatarMotionState* motionState);
SkeletonModel _skeletonModel; SkeletonModel _skeletonModel;
glm::vec3 _skeletonOffset; glm::vec3 _skeletonOffset;
QVector<Model*> _attachmentModels; QVector<Model*> _attachmentModels;
@ -201,14 +203,15 @@ protected:
float _stringLength; float _stringLength;
bool _moving; ///< set when position is changing bool _moving; ///< set when position is changing
bool isLookingAtMe(AvatarSharedPointer avatar);
// protected methods... // protected methods...
bool isLookingAtMe(AvatarSharedPointer avatar) const;
virtual void animateScaleChanges(float deltaTime);
glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; }
glm::vec3 getBodyUpDirection() const { return getOrientation() * IDENTITY_UP; } glm::vec3 getBodyUpDirection() const { return getOrientation() * IDENTITY_UP; }
glm::vec3 getBodyFrontDirection() const { return getOrientation() * IDENTITY_FRONT; } glm::vec3 getBodyFrontDirection() const { return getOrientation() * IDENTITY_FRONT; }
glm::quat computeRotationFromBodyToWorldUp(float proportion = 1.0f) const; glm::quat computeRotationFromBodyToWorldUp(float proportion = 1.0f) const;
void setAvatarScale(float scale);
void measureMotionDerivatives(float deltaTime); void measureMotionDerivatives(float deltaTime);
float getSkeletonHeight() const; float getSkeletonHeight() const;

View file

@ -14,6 +14,7 @@
#include <QVariantGLM.h> #include <QVariantGLM.h>
#include "avatar/AvatarManager.h" #include "avatar/AvatarManager.h"
#include "CharacterController.h"
const uint16_t AvatarActionHold::holdVersion = 1; const uint16_t AvatarActionHold::holdVersion = 1;
@ -32,6 +33,56 @@ AvatarActionHold::~AvatarActionHold() {
#endif #endif
} }
bool AvatarActionHold::getAvatarRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation) {
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
MyCharacterController* controller = myAvatar ? myAvatar->getCharacterController() : nullptr;
if (!controller) {
qDebug() << "AvatarActionHold::getAvatarRigidBodyLocation failed to get character controller";
return false;
}
controller->getRigidBodyLocation(avatarRigidBodyPosition, avatarRigidBodyRotation);
return true;
}
void AvatarActionHold::prepareForPhysicsSimulation() {
auto avatarManager = DependencyManager::get<AvatarManager>();
auto holdingAvatar = std::static_pointer_cast<Avatar>(avatarManager->getAvatarBySessionID(_holderID));
if (!holdingAvatar) {
return;
}
withWriteLock([&]{
if (_ignoreIK && holdingAvatar->isMyAvatar()) {
return;
}
if (holdingAvatar->isMyAvatar()) {
glm::vec3 palmPosition;
glm::quat palmRotation;
if (_hand == "right") {
palmPosition = holdingAvatar->getRightPalmPosition();
palmRotation = holdingAvatar->getRightPalmRotation();
} else {
palmPosition = holdingAvatar->getLeftPalmPosition();
palmRotation = holdingAvatar->getLeftPalmRotation();
}
glm::vec3 avatarRigidBodyPosition;
glm::quat avatarRigidBodyRotation;
getAvatarRigidBodyLocation(avatarRigidBodyPosition, avatarRigidBodyRotation);
// determine the difference in translation and rotation between the avatar's
// rigid body and the palm position. The avatar's rigid body will be moved by bullet
// between this call and the call to getTarget, below. A call to get*PalmPosition in
// getTarget would get the palm position of the previous location of the avatar (because
// bullet has moved the av's rigid body but the rigid body's location has not yet been
// copied out into the Avatar class.
_palmOffsetFromRigidBody = palmPosition - avatarRigidBodyPosition;
_palmRotationFromRigidBody = glm::inverse(avatarRigidBodyRotation) * palmRotation;
}
});
}
std::shared_ptr<Avatar> AvatarActionHold::getTarget(glm::quat& rotation, glm::vec3& position) { std::shared_ptr<Avatar> AvatarActionHold::getTarget(glm::quat& rotation, glm::vec3& position) {
auto avatarManager = DependencyManager::get<AvatarManager>(); auto avatarManager = DependencyManager::get<AvatarManager>();
auto holdingAvatar = std::static_pointer_cast<Avatar>(avatarManager->getAvatarBySessionID(_holderID)); auto holdingAvatar = std::static_pointer_cast<Avatar>(avatarManager->getAvatarBySessionID(_holderID));
@ -40,7 +91,7 @@ std::shared_ptr<Avatar> AvatarActionHold::getTarget(glm::quat& rotation, glm::ve
return holdingAvatar; return holdingAvatar;
} }
withTryReadLock([&]{ withReadLock([&]{
bool isRightHand = (_hand == "right"); bool isRightHand = (_hand == "right");
glm::vec3 palmPosition { Vectors::ZERO }; glm::vec3 palmPosition { Vectors::ZERO };
glm::quat palmRotation { Quaternions::IDENTITY }; glm::quat palmRotation { Quaternions::IDENTITY };
@ -55,6 +106,23 @@ std::shared_ptr<Avatar> AvatarActionHold::getTarget(glm::quat& rotation, glm::ve
palmPosition = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getPosition(); palmPosition = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getPosition();
palmRotation = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getRotation(); palmRotation = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getRotation();
} }
} else if (holdingAvatar->isMyAvatar()) {
glm::vec3 avatarRigidBodyPosition;
glm::quat avatarRigidBodyRotation;
getAvatarRigidBodyLocation(avatarRigidBodyPosition, avatarRigidBodyRotation);
// the offset and rotation between the avatar's rigid body and the palm were determined earlier
// in prepareForPhysicsSimulation. At this point, the avatar's rigid body has been moved by bullet
// and the data in the Avatar class is stale. This means that the result of get*PalmPosition will
// be stale. Instead, determine the current palm position with the current avatar's rigid body
// location and the saved offsets.
palmPosition = avatarRigidBodyPosition + _palmOffsetFromRigidBody;
palmRotation = avatarRigidBodyRotation * _palmRotationFromRigidBody;
if (isRightHand) {
palmRotation = holdingAvatar->getRightPalmRotation();
} else {
palmRotation = holdingAvatar->getLeftPalmRotation();
}
} else { } else {
if (isRightHand) { if (isRightHand) {
palmPosition = holdingAvatar->getRightPalmPosition(); palmPosition = holdingAvatar->getRightPalmPosition();
@ -103,14 +171,13 @@ void AvatarActionHold::updateActionWorker(float deltaTimeStep) {
if (valid && holdCount > 0) { if (valid && holdCount > 0) {
position /= holdCount; position /= holdCount;
bool gotLock = withTryWriteLock([&]{ withWriteLock([&]{
_positionalTarget = position; _positionalTarget = position;
_rotationalTarget = rotation; _rotationalTarget = rotation;
_positionalTargetSet = true; _positionalTargetSet = true;
_rotationalTargetSet = true; _rotationalTargetSet = true;
_active = true; _active = true;
}); });
if (gotLock) {
if (_kinematic) { if (_kinematic) {
doKinematicUpdate(deltaTimeStep); doKinematicUpdate(deltaTimeStep);
} else { } else {
@ -120,7 +187,6 @@ void AvatarActionHold::updateActionWorker(float deltaTimeStep) {
} }
} }
} }
}
void AvatarActionHold::doKinematicUpdate(float deltaTimeStep) { void AvatarActionHold::doKinematicUpdate(float deltaTimeStep) {
auto ownerEntity = _ownerEntity.lock(); auto ownerEntity = _ownerEntity.lock();

View file

@ -25,18 +25,21 @@ public:
AvatarActionHold(const QUuid& id, EntityItemPointer ownerEntity); AvatarActionHold(const QUuid& id, EntityItemPointer ownerEntity);
virtual ~AvatarActionHold(); virtual ~AvatarActionHold();
virtual bool updateArguments(QVariantMap arguments); virtual bool updateArguments(QVariantMap arguments) override;
virtual QVariantMap getArguments(); virtual QVariantMap getArguments() override;
virtual void updateActionWorker(float deltaTimeStep); virtual void updateActionWorker(float deltaTimeStep) override;
QByteArray serialize() const; QByteArray serialize() const;
virtual void deserialize(QByteArray serializedArguments); virtual void deserialize(QByteArray serializedArguments) override;
virtual bool shouldSuppressLocationEdits() { return _active && !_ownerEntity.expired(); } virtual bool shouldSuppressLocationEdits() override { return _active && !_ownerEntity.expired(); }
bool getAvatarRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation);
std::shared_ptr<Avatar> getTarget(glm::quat& rotation, glm::vec3& position); std::shared_ptr<Avatar> getTarget(glm::quat& rotation, glm::vec3& position);
virtual void prepareForPhysicsSimulation() override;
private: private:
void doKinematicUpdate(float deltaTimeStep); void doKinematicUpdate(float deltaTimeStep);
@ -56,6 +59,9 @@ private:
float _previousDeltaTimeStep = 0.0f; float _previousDeltaTimeStep = 0.0f;
glm::vec3 _previousPositionalDelta; glm::vec3 _previousPositionalDelta;
glm::vec3 _palmOffsetFromRigidBody;
glm::quat _palmRotationFromRigidBody;
}; };
#endif // hifi_AvatarActionHold_h #endif // hifi_AvatarActionHold_h

View file

@ -203,7 +203,7 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
while (fadingIterator != _avatarFades.end()) { while (fadingIterator != _avatarFades.end()) {
auto avatar = std::static_pointer_cast<Avatar>(*fadingIterator); auto avatar = std::static_pointer_cast<Avatar>(*fadingIterator);
avatar->startUpdate(); avatar->startUpdate();
avatar->setTargetScale(avatar->getAvatarScale() * SHRINK_RATE); avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE);
if (avatar->getTargetScale() <= MIN_FADE_SCALE) { if (avatar->getTargetScale() <= MIN_FADE_SCALE) {
avatar->removeFromScene(*fadingIterator, scene, pendingChanges); avatar->removeFromScene(*fadingIterator, scene, pendingChanges);
fadingIterator = _avatarFades.erase(fadingIterator); fadingIterator = _avatarFades.erase(fadingIterator);
@ -261,6 +261,7 @@ void AvatarManager::removeAvatar(const QUuid& sessionUUID) {
void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar) { void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar) {
AvatarHashMap::handleRemovedAvatar(removedAvatar); AvatarHashMap::handleRemovedAvatar(removedAvatar);
removedAvatar->die();
removeAvatarMotionState(removedAvatar); removeAvatarMotionState(removedAvatar);
_avatarFades.push_back(removedAvatar); _avatarFades.push_back(removedAvatar);
} }
@ -374,22 +375,20 @@ void AvatarManager::handleCollisionEvents(const CollisionEvents& collisionEvents
} }
} }
void AvatarManager::updateAvatarPhysicsShape(Avatar* avatar) { void AvatarManager::addAvatarToSimulation(Avatar* avatar) {
AvatarMotionState* motionState = avatar->getMotionState(); assert(!avatar->getMotionState());
if (motionState) {
motionState->addDirtyFlags(Simulation::DIRTY_SHAPE);
} else {
ShapeInfo shapeInfo; ShapeInfo shapeInfo;
avatar->computeShapeInfo(shapeInfo); avatar->computeShapeInfo(shapeInfo);
btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo); btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo);
if (shape) { if (shape) {
// we don't add to the simulation now, we put it on a list to be added later
AvatarMotionState* motionState = new AvatarMotionState(avatar, shape); AvatarMotionState* motionState = new AvatarMotionState(avatar, shape);
avatar->setMotionState(motionState); avatar->setMotionState(motionState);
_motionStatesToAdd.insert(motionState); _motionStatesToAdd.insert(motionState);
_avatarMotionStates.insert(motionState); _avatarMotionStates.insert(motionState);
} }
} }
}
void AvatarManager::updateAvatarRenderStatus(bool shouldRenderAvatars) { void AvatarManager::updateAvatarRenderStatus(bool shouldRenderAvatars) {
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderAvatars()) { if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderAvatars()) {

View file

@ -66,7 +66,7 @@ public:
void handleOutgoingChanges(const VectorOfMotionStates& motionStates); void handleOutgoingChanges(const VectorOfMotionStates& motionStates);
void handleCollisionEvents(const CollisionEvents& collisionEvents); void handleCollisionEvents(const CollisionEvents& collisionEvents);
void updateAvatarPhysicsShape(Avatar* avatar); void addAvatarToSimulation(Avatar* avatar);
// Expose results and parameter-tuning operations to other systems, such as stats and javascript. // Expose results and parameter-tuning operations to other systems, such as stats and javascript.
Q_INVOKABLE float getRenderDistance() { return _renderDistance; } Q_INVOKABLE float getRenderDistance() { return _renderDistance; }

View file

@ -37,7 +37,7 @@ void Hand::simulate(float deltaTime, bool isMine) {
void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) { void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) {
float avatarScale = 1.0f; float avatarScale = 1.0f;
if (_owningAvatar) { if (_owningAvatar) {
avatarScale = _owningAvatar->getAvatarScale(); avatarScale = _owningAvatar->getUniformScale();
} }
const float alpha = 1.0f; const float alpha = 1.0f;

View file

@ -287,10 +287,7 @@ extern void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avata
void MyAvatar::simulate(float deltaTime) { void MyAvatar::simulate(float deltaTime) {
PerformanceTimer perfTimer("simulate"); PerformanceTimer perfTimer("simulate");
if (getAvatarScale() != _targetScale) { animateScaleChanges(deltaTime);
float scale = (1.0f - SMOOTHING_RATIO) * getAvatarScale() + SMOOTHING_RATIO * _targetScale;
setAvatarScale(scale);
}
{ {
PerformanceTimer perfTimer("transform"); PerformanceTimer perfTimer("transform");
@ -337,7 +334,7 @@ void MyAvatar::simulate(float deltaTime) {
headPosition = getPosition(); headPosition = getPosition();
} }
head->setPosition(headPosition); head->setPosition(headPosition);
head->setScale(getAvatarScale()); head->setScale(getUniformScale());
head->simulate(deltaTime, true); head->simulate(deltaTime, true);
} }
@ -681,7 +678,7 @@ void MyAvatar::loadData() {
_leanScale = loadSetting(settings, "leanScale", 0.05f); _leanScale = loadSetting(settings, "leanScale", 0.05f);
_targetScale = loadSetting(settings, "scale", 1.0f); _targetScale = loadSetting(settings, "scale", 1.0f);
setAvatarScale(getAvatarScale()); setScale(glm::vec3(_targetScale));
_animGraphUrl = settings.value("animGraphURL", "").toString(); _animGraphUrl = settings.value("animGraphURL", "").toString();
_fullAvatarURLFromPreferences = settings.value("fullAvatarURL", AvatarData::defaultFullAvatarModelUrl()).toUrl(); _fullAvatarURLFromPreferences = settings.value("fullAvatarURL", AvatarData::defaultFullAvatarModelUrl()).toUrl();
@ -809,7 +806,7 @@ void MyAvatar::updateLookAtTargetAvatar() {
float distanceTo = glm::length(avatar->getHead()->getEyePosition() - cameraPosition); float distanceTo = glm::length(avatar->getHead()->getEyePosition() - cameraPosition);
avatar->setIsLookAtTarget(false); avatar->setIsLookAtTarget(false);
if (!avatar->isMyAvatar() && avatar->isInitialized() && if (!avatar->isMyAvatar() && avatar->isInitialized() &&
(distanceTo < GREATEST_LOOKING_AT_DISTANCE * getAvatarScale())) { (distanceTo < GREATEST_LOOKING_AT_DISTANCE * getUniformScale())) {
float angleTo = glm::angle(lookForward, glm::normalize(avatar->getHead()->getEyePosition() - cameraPosition)); float angleTo = glm::angle(lookForward, glm::normalize(avatar->getHead()->getEyePosition() - cameraPosition));
if (angleTo < (smallestAngleTo * (isCurrentTarget ? KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR : 1.0f))) { if (angleTo < (smallestAngleTo * (isCurrentTarget ? KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR : 1.0f))) {
_lookAtTargetAvatar = avatarPointer; _lookAtTargetAvatar = avatarPointer;
@ -1036,14 +1033,15 @@ glm::vec3 MyAvatar::getSkeletonPosition() const {
return Avatar::getPosition(); return Avatar::getPosition();
} }
void MyAvatar::rebuildSkeletonBody() { void MyAvatar::rebuildCollisionShape() {
// compute localAABox // compute localAABox
float radius = _skeletonModel.getBoundingCapsuleRadius(); float scale = getUniformScale();
float height = _skeletonModel.getBoundingCapsuleHeight() + 2.0f * radius; float radius = scale * _skeletonModel.getBoundingCapsuleRadius();
float height = scale * _skeletonModel.getBoundingCapsuleHeight() + 2.0f * radius;
glm::vec3 corner(-radius, -0.5f * height, -radius); glm::vec3 corner(-radius, -0.5f * height, -radius);
corner += _skeletonModel.getBoundingCapsuleOffset(); corner += scale * _skeletonModel.getBoundingCapsuleOffset();
glm::vec3 scale(2.0f * radius, height, 2.0f * radius); glm::vec3 diagonal(2.0f * radius, height, 2.0f * radius);
_characterController.setLocalBoundingBox(corner, scale); _characterController.setLocalBoundingBox(corner, diagonal);
} }
void MyAvatar::prepareForPhysicsSimulation() { void MyAvatar::prepareForPhysicsSimulation() {
@ -1331,7 +1329,7 @@ const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f;
bool MyAvatar::cameraInsideHead() const { bool MyAvatar::cameraInsideHead() const {
const Head* head = getHead(); const Head* head = getHead();
const glm::vec3 cameraPosition = qApp->getCamera()->getPosition(); const glm::vec3 cameraPosition = qApp->getCamera()->getPosition();
return glm::length(cameraPosition - head->getEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getAvatarScale()); return glm::length(cameraPosition - head->getEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getUniformScale());
} }
bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const { bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const {
@ -1455,11 +1453,11 @@ glm::vec3 MyAvatar::applyKeyboardMotor(float deltaTime, const glm::vec3& localVe
if (isHovering) { if (isHovering) {
// we're flying --> complex acceleration curve with high max speed // we're flying --> complex acceleration curve with high max speed
float motorSpeed = glm::length(_keyboardMotorVelocity); float motorSpeed = glm::length(_keyboardMotorVelocity);
float finalMaxMotorSpeed = getAvatarScale() * MAX_KEYBOARD_MOTOR_SPEED; float finalMaxMotorSpeed = getUniformScale() * MAX_KEYBOARD_MOTOR_SPEED;
float speedGrowthTimescale = 2.0f; float speedGrowthTimescale = 2.0f;
float speedIncreaseFactor = 1.8f; float speedIncreaseFactor = 1.8f;
motorSpeed *= 1.0f + glm::clamp(deltaTime / speedGrowthTimescale , 0.0f, 1.0f) * speedIncreaseFactor; motorSpeed *= 1.0f + glm::clamp(deltaTime / speedGrowthTimescale , 0.0f, 1.0f) * speedIncreaseFactor;
const float maxBoostSpeed = getAvatarScale() * MAX_BOOST_SPEED; const float maxBoostSpeed = getUniformScale() * MAX_BOOST_SPEED;
if (motorSpeed < maxBoostSpeed) { if (motorSpeed < maxBoostSpeed) {
// an active keyboard motor should never be slower than this // an active keyboard motor should never be slower than this
float boostCoefficient = (maxBoostSpeed - motorSpeed) / maxBoostSpeed; float boostCoefficient = (maxBoostSpeed - motorSpeed) / maxBoostSpeed;

View file

@ -249,7 +249,7 @@ public slots:
Q_INVOKABLE void updateMotionBehaviorFromMenu(); Q_INVOKABLE void updateMotionBehaviorFromMenu();
virtual void rebuildSkeletonBody() override; virtual void rebuildCollisionShape() override;
Q_INVOKABLE QUrl getAnimGraphUrl() const { return _animGraphUrl; } Q_INVOKABLE QUrl getAnimGraphUrl() const { return _animGraphUrl; }

View file

@ -69,7 +69,7 @@ void SkeletonModel::initJointStates() {
_headClipDistance = -(meshExtents.minimum.z / _scale.z - _defaultEyeModelPosition.z); _headClipDistance = -(meshExtents.minimum.z / _scale.z - _defaultEyeModelPosition.z);
_headClipDistance = std::max(_headClipDistance, DEFAULT_NEAR_CLIP); _headClipDistance = std::max(_headClipDistance, DEFAULT_NEAR_CLIP);
_owningAvatar->rebuildSkeletonBody(); _owningAvatar->rebuildCollisionShape();
emit skeletonLoaded(); emit skeletonLoaded();
} }
@ -338,35 +338,38 @@ void SkeletonModel::computeBoundingShape() {
return; return;
} }
_rig->computeAvatarBoundingCapsule(geometry, float radius, height;
_boundingCapsuleRadius, glm::vec3 offset;
_boundingCapsuleHeight, _rig->computeAvatarBoundingCapsule(geometry, radius, height, offset);
_boundingCapsuleLocalOffset); float invScale = 1.0f / _owningAvatar->getUniformScale();
_boundingCapsuleRadius = invScale * radius;
_boundingCapsuleHeight = invScale * height;
_boundingCapsuleLocalOffset = invScale * offset;
} }
void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float alpha) { void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float scale, float alpha) {
auto geometryCache = DependencyManager::get<GeometryCache>(); auto geometryCache = DependencyManager::get<GeometryCache>();
auto deferredLighting = DependencyManager::get<DeferredLightingEffect>(); auto deferredLighting = DependencyManager::get<DeferredLightingEffect>();
// draw a blue sphere at the capsule top point // draw a blue sphere at the capsule top point
glm::vec3 topPoint = _translation + getRotation() * (_boundingCapsuleLocalOffset + (0.5f * _boundingCapsuleHeight) * glm::vec3(0.0f, 1.0f, 0.0f)); glm::vec3 topPoint = _translation + getRotation() * (scale * (_boundingCapsuleLocalOffset + (0.5f * _boundingCapsuleHeight) * Vectors::UNIT_Y));
deferredLighting->renderSolidSphereInstance(batch, deferredLighting->renderSolidSphereInstance(batch,
Transform().setTranslation(topPoint).postScale(_boundingCapsuleRadius), Transform().setTranslation(topPoint).postScale(scale * _boundingCapsuleRadius),
glm::vec4(0.6f, 0.6f, 0.8f, alpha)); glm::vec4(0.6f, 0.6f, 0.8f, alpha));
// draw a yellow sphere at the capsule bottom point // draw a yellow sphere at the capsule bottom point
glm::vec3 bottomPoint = topPoint - glm::vec3(0.0f, _boundingCapsuleHeight, 0.0f); glm::vec3 bottomPoint = topPoint - glm::vec3(0.0f, scale * _boundingCapsuleHeight, 0.0f);
glm::vec3 axis = topPoint - bottomPoint; glm::vec3 axis = topPoint - bottomPoint;
deferredLighting->renderSolidSphereInstance(batch, deferredLighting->renderSolidSphereInstance(batch,
Transform().setTranslation(bottomPoint).postScale(_boundingCapsuleRadius), Transform().setTranslation(bottomPoint).postScale(scale * _boundingCapsuleRadius),
glm::vec4(0.8f, 0.8f, 0.6f, alpha)); glm::vec4(0.8f, 0.8f, 0.6f, alpha));
// draw a green cylinder between the two points // draw a green cylinder between the two points
glm::vec3 origin(0.0f); glm::vec3 origin(0.0f);
batch.setModelTransform(Transform().setTranslation(bottomPoint)); batch.setModelTransform(Transform().setTranslation(bottomPoint));
deferredLighting->bindSimpleProgram(batch); deferredLighting->bindSimpleProgram(batch);
Avatar::renderJointConnectingCone(batch, origin, axis, _boundingCapsuleRadius, _boundingCapsuleRadius, Avatar::renderJointConnectingCone(batch, origin, axis, scale * _boundingCapsuleRadius, scale * _boundingCapsuleRadius,
glm::vec4(0.6f, 0.8f, 0.6f, alpha)); glm::vec4(0.6f, 0.8f, 0.6f, alpha));
} }

View file

@ -89,7 +89,7 @@ public:
/// \return whether or not the head was found. /// \return whether or not the head was found.
glm::vec3 getDefaultEyeModelPosition() const; glm::vec3 getDefaultEyeModelPosition() const;
void renderBoundingCollisionShapes(gpu::Batch& batch, float alpha); void renderBoundingCollisionShapes(gpu::Batch& batch, float scale, float alpha);
float getBoundingCapsuleRadius() const { return _boundingCapsuleRadius; } float getBoundingCapsuleRadius() const { return _boundingCapsuleRadius; }
float getBoundingCapsuleHeight() const { return _boundingCapsuleHeight; } float getBoundingCapsuleHeight() const { return _boundingCapsuleHeight; }
const glm::vec3 getBoundingCapsuleOffset() const { return _boundingCapsuleLocalOffset; } const glm::vec3 getBoundingCapsuleOffset() const { return _boundingCapsuleLocalOffset; }

View file

@ -386,7 +386,7 @@ bool ApplicationCompositor::calculateRayUICollisionPoint(const glm::vec3& positi
glm::vec3 relativeDirection = glm::normalize(inverseOrientation * direction); glm::vec3 relativeDirection = glm::normalize(inverseOrientation * direction);
float t; float t;
if (raySphereIntersect(relativeDirection, relativePosition, _oculusUIRadius * myAvatar->getAvatarScale(), &t)){ if (raySphereIntersect(relativeDirection, relativePosition, _oculusUIRadius * myAvatar->getUniformScale(), &t)){
result = position + direction * t; result = position + direction * t;
return true; return true;
} }

View file

@ -199,7 +199,7 @@ void PreferencesDialog::loadPreferences() {
ui.leanScaleSpin->setValue(myAvatar->getLeanScale()); ui.leanScaleSpin->setValue(myAvatar->getLeanScale());
ui.avatarScaleSpin->setValue(myAvatar->getAvatarScale()); ui.avatarScaleSpin->setValue(myAvatar->getUniformScale());
ui.avatarAnimationEdit->setText(myAvatar->getAnimGraphUrl().toString()); ui.avatarAnimationEdit->setText(myAvatar->getAnimGraphUrl().toString());
ui.maxOctreePPSSpin->setValue(qApp->getMaxOctreePacketsPerSecond()); ui.maxOctreePPSSpin->setValue(qApp->getMaxOctreePacketsPerSecond());
@ -256,7 +256,7 @@ void PreferencesDialog::savePreferences() {
myAvatar->getHead()->setPupilDilation(ui.pupilDilationSlider->value() / (float)ui.pupilDilationSlider->maximum()); myAvatar->getHead()->setPupilDilation(ui.pupilDilationSlider->value() / (float)ui.pupilDilationSlider->maximum());
myAvatar->setLeanScale(ui.leanScaleSpin->value()); myAvatar->setLeanScale(ui.leanScaleSpin->value());
myAvatar->setClampedTargetScale(ui.avatarScaleSpin->value()); myAvatar->setTargetScaleVerbose(ui.avatarScaleSpin->value());
if (myAvatar->getAnimGraphUrl() != ui.avatarAnimationEdit->text()) { // If changed, destroy the old and start with the new if (myAvatar->getAnimGraphUrl() != ui.avatarAnimationEdit->text()) { // If changed, destroy the old and start with the new
myAvatar->setAnimGraphUrl(ui.avatarAnimationEdit->text()); myAvatar->setAnimGraphUrl(ui.avatarAnimationEdit->text());
} }

View file

@ -27,13 +27,15 @@ QString const Image3DOverlay::TYPE = "image3d";
Image3DOverlay::Image3DOverlay() { Image3DOverlay::Image3DOverlay() {
_isLoaded = false; _isLoaded = false;
_emissive = false;
} }
Image3DOverlay::Image3DOverlay(const Image3DOverlay* image3DOverlay) : Image3DOverlay::Image3DOverlay(const Image3DOverlay* image3DOverlay) :
Billboard3DOverlay(image3DOverlay), Billboard3DOverlay(image3DOverlay),
_url(image3DOverlay->_url), _url(image3DOverlay->_url),
_texture(image3DOverlay->_texture), _texture(image3DOverlay->_texture),
_fromImage(image3DOverlay->_fromImage) _fromImage(image3DOverlay->_fromImage),
_emissive(image3DOverlay->_emissive)
{ {
} }
@ -94,7 +96,7 @@ void Image3DOverlay::render(RenderArgs* args) {
batch->setModelTransform(transform); batch->setModelTransform(transform);
batch->setResourceTexture(0, _texture->getGPUTexture()); batch->setResourceTexture(0, _texture->getGPUTexture());
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(*batch, true, false, false, true); DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(*batch, true, false, _emissive, true);
DependencyManager::get<GeometryCache>()->renderQuad( DependencyManager::get<GeometryCache>()->renderQuad(
*batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, *batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha) glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha)
@ -144,6 +146,11 @@ void Image3DOverlay::setProperties(const QScriptValue &properties) {
setClipFromSource(subImageRect); setClipFromSource(subImageRect);
} }
} }
QScriptValue emissiveValue = properties.property("emissive");
if (emissiveValue.isValid()) {
_emissive = emissiveValue.toBool();
}
} }
QScriptValue Image3DOverlay::getProperty(const QString& property) { QScriptValue Image3DOverlay::getProperty(const QString& property) {
@ -156,6 +163,9 @@ QScriptValue Image3DOverlay::getProperty(const QString& property) {
if (property == "offsetPosition") { if (property == "offsetPosition") {
return vec3toScriptValue(_scriptEngine, getOffsetPosition()); return vec3toScriptValue(_scriptEngine, getOffsetPosition());
} }
if (property == "emissive") {
return _emissive;
}
return Billboard3DOverlay::getProperty(property); return Billboard3DOverlay::getProperty(property);
} }

View file

@ -46,6 +46,7 @@ public:
private: private:
QString _url; QString _url;
NetworkTexturePointer _texture; NetworkTexturePointer _texture;
bool _emissive;
QRect _fromImage; // where from in the image to sample QRect _fromImage; // where from in the image to sample
}; };

View file

@ -68,7 +68,7 @@ namespace render {
glm::vec3 myAvatarPosition = avatar->getPosition(); glm::vec3 myAvatarPosition = avatar->getPosition();
float angle = glm::degrees(glm::angle(myAvatarRotation)); float angle = glm::degrees(glm::angle(myAvatarRotation));
glm::vec3 axis = glm::axis(myAvatarRotation); glm::vec3 axis = glm::axis(myAvatarRotation);
float myAvatarScale = avatar->getAvatarScale(); float myAvatarScale = avatar->getUniformScale();
Transform transform = Transform(); Transform transform = Transform();
transform.setTranslation(myAvatarPosition); transform.setTranslation(myAvatarPosition);
transform.setRotation(glm::angleAxis(angle, axis)); transform.setRotation(glm::angleAxis(angle, axis));

View file

@ -90,7 +90,7 @@ const QUrl& AvatarData::defaultFullAvatarModelUrl() {
// There are a number of possible strategies for this set of tools through endRender, below. // There are a number of possible strategies for this set of tools through endRender, below.
void AvatarData::nextAttitude(glm::vec3 position, glm::quat orientation) { void AvatarData::nextAttitude(glm::vec3 position, glm::quat orientation) {
avatarLock.lock(); avatarLock.lock();
Transform trans; Transform trans = getTransform();
trans.setTranslation(position); trans.setTranslation(position);
trans.setRotation(orientation); trans.setRotation(orientation);
bool success; bool success;
@ -133,13 +133,10 @@ float AvatarData::getTargetScale() const {
} }
void AvatarData::setTargetScale(float targetScale) { void AvatarData::setTargetScale(float targetScale) {
_targetScale = std::max(MIN_AVATAR_SCALE, std::min(MAX_AVATAR_SCALE, targetScale)); _targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE);
} }
void AvatarData::setClampedTargetScale(float targetScale) { void AvatarData::setTargetScaleVerbose(float targetScale) {
targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE);
setTargetScale(targetScale); setTargetScale(targetScale);
qCDebug(avatars) << "Changed scale to " << _targetScale; qCDebug(avatars) << "Changed scale to " << _targetScale;
} }

View file

@ -239,7 +239,7 @@ public:
// Scale // Scale
float getTargetScale() const; float getTargetScale() const;
void setTargetScale(float targetScale); void setTargetScale(float targetScale);
void setClampedTargetScale(float targetScale); void setTargetScaleVerbose(float targetScale);
// Hand State // Hand State
Q_INVOKABLE void setHandState(char s) { _handState = s; } Q_INVOKABLE void setHandState(char s) { _handState = s; }
@ -344,6 +344,9 @@ public:
glm::vec3 getClientGlobalPosition() { return _globalPosition; } glm::vec3 getClientGlobalPosition() { return _globalPosition; }
void die() { _isDead = true; }
bool isDead() const { return _isDead; }
public slots: public slots:
void sendAvatarDataPacket(); void sendAvatarDataPacket();
void sendIdentityPacket(); void sendIdentityPacket();
@ -415,6 +418,8 @@ protected:
// updates about one avatar to another. // updates about one avatar to another.
glm::vec3 _globalPosition; glm::vec3 _globalPosition;
bool _isDead { false };
private: private:
friend void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar); friend void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar);
static QUrl _defaultFullAvatarModelUrl; static QUrl _defaultFullAvatarModelUrl;

View file

@ -58,6 +58,8 @@ public:
virtual bool shouldSuppressLocationEdits() { return false; } virtual bool shouldSuppressLocationEdits() { return false; }
virtual void prepareForPhysicsSimulation() { }
// these look in the arguments map for a named argument. if it's not found or isn't well formed, // these look in the arguments map for a named argument. if it's not found or isn't well formed,
// ok will be set to false (note that it's never set to true -- set it to true before calling these). // ok will be set to false (note that it's never set to true -- set it to true before calling these).
// if required is true, failure to extract an argument will cause a warning to be printed. // if required is true, failure to extract an argument will cause a warning to be printed.

View file

@ -15,6 +15,7 @@
#include "BulletUtil.h" #include "BulletUtil.h"
#include "PhysicsCollisionGroups.h" #include "PhysicsCollisionGroups.h"
#include "ObjectMotionState.h"
const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f); const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f);
const float JUMP_SPEED = 3.5f; const float JUMP_SPEED = 3.5f;
@ -379,3 +380,15 @@ void CharacterController::preSimulation() {
void CharacterController::postSimulation() { void CharacterController::postSimulation() {
// postSimulation() exists for symmetry and just in case we need to do something here later // postSimulation() exists for symmetry and just in case we need to do something here later
} }
bool CharacterController::getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation) {
if (!_rigidBody) {
return false;
}
const btTransform& worldTrans = _rigidBody->getCenterOfMassTransform();
avatarRigidBodyPosition = bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset();
avatarRigidBodyRotation = bulletToGLM(worldTrans.getRotation());
return true;
}

View file

@ -79,6 +79,8 @@ public:
void setEnabled(bool enabled); void setEnabled(bool enabled);
bool isEnabled() const { return _enabled && _dynamicsWorld; } bool isEnabled() const { return _enabled && _dynamicsWorld; }
bool getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation);
protected: protected:
void updateUpAxis(const glm::quat& rotation); void updateUpAxis(const glm::quat& rotation);

View file

@ -29,12 +29,12 @@ public:
ObjectAction(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity); ObjectAction(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity);
virtual ~ObjectAction(); virtual ~ObjectAction();
virtual void removeFromSimulation(EntitySimulation* simulation) const; virtual void removeFromSimulation(EntitySimulation* simulation) const override;
virtual EntityItemWeakPointer getOwnerEntity() const { return _ownerEntity; } virtual EntityItemWeakPointer getOwnerEntity() const override { return _ownerEntity; }
virtual void setOwnerEntity(const EntityItemPointer ownerEntity) { _ownerEntity = ownerEntity; } virtual void setOwnerEntity(const EntityItemPointer ownerEntity) override { _ownerEntity = ownerEntity; }
virtual bool updateArguments(QVariantMap arguments); virtual bool updateArguments(QVariantMap arguments) override;
virtual QVariantMap getArguments(); virtual QVariantMap getArguments() override;
// this is called from updateAction and should be overridden by subclasses // this is called from updateAction and should be overridden by subclasses
virtual void updateActionWorker(float deltaTimeStep) = 0; virtual void updateActionWorker(float deltaTimeStep) = 0;
@ -43,25 +43,25 @@ public:
virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep); virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep);
virtual void debugDraw(btIDebugDraw* debugDrawer); virtual void debugDraw(btIDebugDraw* debugDrawer);
virtual QByteArray serialize() const = 0; virtual QByteArray serialize() const override = 0;
virtual void deserialize(QByteArray serializedArguments) = 0; virtual void deserialize(QByteArray serializedArguments) override = 0;
virtual bool lifetimeIsOver(); virtual bool lifetimeIsOver() override;
virtual quint64 getExpires() { return _expires; } virtual quint64 getExpires() override { return _expires; }
protected: protected:
quint64 localTimeToServerTime(quint64 timeValue) const; quint64 localTimeToServerTime(quint64 timeValue) const;
quint64 serverTimeToLocalTime(quint64 timeValue) const; quint64 serverTimeToLocalTime(quint64 timeValue) const;
virtual btRigidBody* getRigidBody(); virtual btRigidBody* getRigidBody();
virtual glm::vec3 getPosition(); virtual glm::vec3 getPosition() override;
virtual void setPosition(glm::vec3 position); virtual void setPosition(glm::vec3 position) override;
virtual glm::quat getRotation(); virtual glm::quat getRotation() override;
virtual void setRotation(glm::quat rotation); virtual void setRotation(glm::quat rotation) override;
virtual glm::vec3 getLinearVelocity(); virtual glm::vec3 getLinearVelocity() override;
virtual void setLinearVelocity(glm::vec3 linearVelocity); virtual void setLinearVelocity(glm::vec3 linearVelocity) override;
virtual glm::vec3 getAngularVelocity(); virtual glm::vec3 getAngularVelocity() override;
virtual void setAngularVelocity(glm::vec3 angularVelocity); virtual void setAngularVelocity(glm::vec3 angularVelocity) override;
virtual void activateBody(); virtual void activateBody();
virtual void forceBodyNonStatic(); virtual void forceBodyNonStatic();

View file

@ -22,13 +22,13 @@ public:
ObjectActionOffset(const QUuid& id, EntityItemPointer ownerEntity); ObjectActionOffset(const QUuid& id, EntityItemPointer ownerEntity);
virtual ~ObjectActionOffset(); virtual ~ObjectActionOffset();
virtual bool updateArguments(QVariantMap arguments); virtual bool updateArguments(QVariantMap arguments) override;
virtual QVariantMap getArguments(); virtual QVariantMap getArguments() override;
virtual void updateActionWorker(float deltaTimeStep); virtual void updateActionWorker(float deltaTimeStep) override;
virtual QByteArray serialize() const; virtual QByteArray serialize() const override;
virtual void deserialize(QByteArray serializedArguments); virtual void deserialize(QByteArray serializedArguments) override;
private: private:
static const uint16_t offsetVersion; static const uint16_t offsetVersion;

View file

@ -19,13 +19,13 @@ public:
ObjectActionSpring(const QUuid& id, EntityItemPointer ownerEntity); ObjectActionSpring(const QUuid& id, EntityItemPointer ownerEntity);
virtual ~ObjectActionSpring(); virtual ~ObjectActionSpring();
virtual bool updateArguments(QVariantMap arguments); virtual bool updateArguments(QVariantMap arguments) override;
virtual QVariantMap getArguments(); virtual QVariantMap getArguments() override;
virtual void updateActionWorker(float deltaTimeStep); virtual void updateActionWorker(float deltaTimeStep) override;
virtual QByteArray serialize() const; virtual QByteArray serialize() const override;
virtual void deserialize(QByteArray serializedArguments); virtual void deserialize(QByteArray serializedArguments) override;
protected: protected:
static const uint16_t springVersion; static const uint16_t springVersion;

View file

@ -497,3 +497,11 @@ void PhysicsEngine::removeAction(const QUuid actionID) {
_objectActions.remove(actionID); _objectActions.remove(actionID);
} }
} }
void PhysicsEngine::forEachAction(std::function<void(EntityActionPointer)> actor) {
QHashIterator<QUuid, EntityActionPointer> iter(_objectActions);
while (iter.hasNext()) {
iter.next();
actor(iter.value());
}
}

View file

@ -97,6 +97,7 @@ public:
EntityActionPointer getActionByID(const QUuid& actionID) const; EntityActionPointer getActionByID(const QUuid& actionID) const;
void addAction(EntityActionPointer action); void addAction(EntityActionPointer action);
void removeAction(const QUuid actionID); void removeAction(const QUuid actionID);
void forEachAction(std::function<void(EntityActionPointer)> actor);
private: private:
void removeContacts(ObjectMotionState* motionState); void removeContacts(ObjectMotionState* motionState);

View file

@ -169,8 +169,8 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {
gpu::PipelinePointer DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled, gpu::PipelinePointer DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled,
bool emmisive, bool depthBias) { bool emissive, bool depthBias) {
SimpleProgramKey config{textured, culled, emmisive, depthBias}; SimpleProgramKey config{textured, culled, emissive, depthBias};
gpu::PipelinePointer pipeline = getPipeline(config); gpu::PipelinePointer pipeline = getPipeline(config);
batch.setPipeline(pipeline); batch.setPipeline(pipeline);

View file

@ -38,7 +38,7 @@ public:
/// Sets up the state necessary to render static untextured geometry with the simple program. /// Sets up the state necessary to render static untextured geometry with the simple program.
gpu::PipelinePointer bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true, gpu::PipelinePointer bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true,
bool emmisive = false, bool depthBias = false); bool emissive = false, bool depthBias = false);
void renderSolidSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec4& color); void renderSolidSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec4& color);
void renderSolidSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec3& color) { void renderSolidSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec3& color) {