From c1d1a8de5c3bb0aaf23be67190e5cfabfe492836 Mon Sep 17 00:00:00 2001 From: Joseph Gilley Date: Thu, 5 Jun 2014 00:26:45 -0400 Subject: [PATCH 1/6] Fix for users with some special characters in their password not being able to log in using the login overlay in the Interface. --- libraries/networking/src/AccountManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 7d27332a57..b4aedbcb7c 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -313,7 +313,7 @@ void AccountManager::requestAccessToken(const QString& login, const QString& pas QByteArray postData; postData.append("grant_type=password&"); postData.append("username=" + login + "&"); - postData.append("password=" + password + "&"); + postData.append("password=" + QUrl::toPercentEncoding(password) + "&"); postData.append("scope=" + ACCOUNT_MANAGER_REQUESTED_SCOPE); request.setUrl(grantURL); From e8724b02f307e8f265cd08dc79d6a2cd17813d43 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 6 Jun 2014 08:50:57 -0700 Subject: [PATCH 2/6] add CapsuleShape::setEndPoints() --- libraries/shared/src/CapsuleShape.cpp | 32 +++++++++++++++------------ libraries/shared/src/CapsuleShape.h | 1 + 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/libraries/shared/src/CapsuleShape.cpp b/libraries/shared/src/CapsuleShape.cpp index 11bd70f8d2..8e887107dc 100644 --- a/libraries/shared/src/CapsuleShape.cpp +++ b/libraries/shared/src/CapsuleShape.cpp @@ -33,20 +33,7 @@ CapsuleShape::CapsuleShape(float radius, float halfHeight, const glm::vec3& posi CapsuleShape::CapsuleShape(float radius, const glm::vec3& startPoint, const glm::vec3& endPoint) : Shape(Shape::CAPSULE_SHAPE), _radius(radius), _halfHeight(0.0f) { - glm::vec3 axis = endPoint - startPoint; - _position = 0.5f * (endPoint + startPoint); - float height = glm::length(axis); - if (height > EPSILON) { - _halfHeight = 0.5f * height; - axis /= height; - glm::vec3 yAxis(0.0f, 1.0f, 0.0f); - float angle = glm::angle(axis, yAxis); - if (angle > EPSILON) { - axis = glm::normalize(glm::cross(yAxis, axis)); - _rotation = glm::angleAxis(angle, axis); - } - } - updateBoundingRadius(); + setEndPoints(startPoint, endPoint); } /// \param[out] startPoint is the center of start cap @@ -80,3 +67,20 @@ void CapsuleShape::setRadiusAndHalfHeight(float radius, float halfHeight) { updateBoundingRadius(); } +void CapsuleShape::setEndPoints(const glm::vec3& startPoint, const glm::vec3& endPoint) { + glm::vec3 axis = endPoint - startPoint; + _position = 0.5f * (endPoint + startPoint); + float height = glm::length(axis); + if (height > EPSILON) { + _halfHeight = 0.5f * height; + axis /= height; + glm::vec3 yAxis(0.0f, 1.0f, 0.0f); + float angle = glm::angle(axis, yAxis); + if (angle > EPSILON) { + axis = glm::normalize(glm::cross(yAxis, axis)); + _rotation = glm::angleAxis(angle, axis); + } + } + updateBoundingRadius(); +} + diff --git a/libraries/shared/src/CapsuleShape.h b/libraries/shared/src/CapsuleShape.h index 0889f6b2f3..756ae18911 100644 --- a/libraries/shared/src/CapsuleShape.h +++ b/libraries/shared/src/CapsuleShape.h @@ -37,6 +37,7 @@ public: void setRadius(float radius); void setHalfHeight(float height); void setRadiusAndHalfHeight(float radius, float height); + void setEndPoints(const glm::vec3& startPoint, const glm::vec3& endPoint); protected: void updateBoundingRadius() { _boundingRadius = _radius + _halfHeight; } From 551029c2f5e696f054f987d34b40fa6da56a8697 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 6 Jun 2014 08:51:22 -0700 Subject: [PATCH 3/6] slave SkeletonModel's collision shapes to RagDoll --- interface/src/Menu.cpp | 1 + interface/src/Menu.h | 1 + interface/src/avatar/SkeletonModel.cpp | 20 +++++++++-- interface/src/avatar/SkeletonModel.h | 1 + interface/src/renderer/Model.h | 2 +- interface/src/renderer/RagDoll.cpp | 46 +++++++++++++++++++++++--- interface/src/renderer/RagDoll.h | 23 +++++++++++-- 7 files changed, 82 insertions(+), 12 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 5d9cd1f1c4..e429a81fa2 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -353,6 +353,7 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderSkeletonCollisionShapes); addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderHeadCollisionShapes); addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderBoundingCollisionShapes); + addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::CollideAsRagDoll); addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::LookAtVectors, 0, false); addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 6bc9adef05..c7d3a94741 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -311,6 +311,7 @@ namespace MenuOption { const QString CascadedShadows = "Cascaded"; const QString Chat = "Chat..."; const QString ChatCircling = "Chat Circling"; + const QString CollideAsRagDoll = "Collide As RagDoll"; const QString CollideWithAvatars = "Collide With Avatars"; const QString CollideWithEnvironment = "Collide With World Boundaries"; const QString CollideWithParticles = "Collide With Particles"; diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index f5ca1ab218..ca40ba1d64 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -23,7 +23,10 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar) : void SkeletonModel::setJointStates(QVector states) { Model::setJointStates(states); - _ragDoll.init(_jointStates); + + if (isActive() && _owningAvatar->isMyAvatar()) { + _ragDoll.init(_jointStates); + } } const float PALM_PRIORITY = 3.0f; @@ -88,7 +91,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { } void SkeletonModel::simulateRagDoll(float deltaTime) { - _ragDoll.slaveToSkeleton(_jointStates, 0.5f); + _ragDoll.slaveToSkeleton(_jointStates, 0.1f); // fraction = 0.1f left intentionally low for demo purposes float MIN_CONSTRAINT_ERROR = 0.005f; // 5mm int MAX_ITERATIONS = 4; @@ -141,7 +144,9 @@ void SkeletonModel::getBodyShapes(QVector& shapes) const { void SkeletonModel::renderIKConstraints() { renderJointConstraints(getRightHandJointIndex()); renderJointConstraints(getLeftHandJointIndex()); - renderRagDoll(); + if (isActive() && _owningAvatar->isMyAvatar()) { + renderRagDoll(); + } } class IndexValue { @@ -254,6 +259,15 @@ void SkeletonModel::updateJointState(int index) { } } +void SkeletonModel::updateShapePositions() { + if (isActive() && _owningAvatar->isMyAvatar() && + Menu::getInstance()->isOptionChecked(MenuOption::CollideAsRagDoll)) { + _ragDoll.updateShapes(_jointShapes, _rotation, _translation); + } else { + Model::updateShapePositions(); + } +} + void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) { if (!_owningAvatar->isMyAvatar() || Application::getInstance()->getPrioVR()->isActive()) { return; diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index d733d937ee..086973807d 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -29,6 +29,7 @@ public: void simulate(float deltaTime, bool fullUpdate = true); void simulateRagDoll(float deltaTime); + void updateShapePositions(); /// \param jointIndex index of hand joint /// \param shapes[out] list in which is stored pointers to hand shapes diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 3bc261ed44..11e6861775 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -140,7 +140,7 @@ public: void clearShapes(); void rebuildShapes(); void resetShapePositions(); - void updateShapePositions(); + virtual void updateShapePositions(); void renderJointCollisionShapes(float alpha); void renderBoundingCollisionShapes(float alpha); diff --git a/interface/src/renderer/RagDoll.cpp b/interface/src/renderer/RagDoll.cpp index 54fb776552..e2654d737f 100644 --- a/interface/src/renderer/RagDoll.cpp +++ b/interface/src/renderer/RagDoll.cpp @@ -15,13 +15,15 @@ #include #include +#include +#include #include "RagDoll.h" // ---------------------------------------------------------------------------- // FixedConstraint // ---------------------------------------------------------------------------- -FixedConstraint::FixedConstraint() : _point(NULL), _anchor(0.0f, 0.0f, 0.0f) { +FixedConstraint::FixedConstraint(glm::vec3* point, const glm::vec3& anchor ) : _point(point), _anchor(anchor) { } float FixedConstraint::enforce() { @@ -42,9 +44,9 @@ void FixedConstraint::setAnchor(const glm::vec3& anchor) { // ---------------------------------------------------------------------------- // DistanceConstraint // ---------------------------------------------------------------------------- -DistanceConstraint::DistanceConstraint(glm::vec3* pointA, glm::vec3* pointB) : _distance(-1.0f) { - _points[0] = pointA; - _points[1] = pointB; +DistanceConstraint::DistanceConstraint(glm::vec3* startPoint, glm::vec3* endPoint) : _distance(-1.0f) { + _points[0] = startPoint; + _points[1] = endPoint; _distance = glm::distance(*(_points[0]), *(_points[1])); } @@ -70,6 +72,28 @@ float DistanceConstraint::enforce() { return glm::abs(newDistance - _distance); } +void DistanceConstraint::updateProxyShape(Shape* shape, const glm::quat& rotation, const glm::vec3& translation) const { + if (!shape) { + return; + } + switch (shape->getType()) { + case Shape::SPHERE_SHAPE: { + // sphere collides at endPoint + SphereShape* sphere = static_cast(shape); + sphere->setPosition(translation + rotation * (*_points[1])); + } + break; + case Shape::CAPSULE_SHAPE: { + // capsule collides from startPoint to endPoint + CapsuleShape* capsule = static_cast(shape); + capsule->setEndPoints(translation + rotation * (*_points[0]), translation + rotation * (*_points[1])); + } + break; + default: + break; + } +} + // ---------------------------------------------------------------------------- // RagDoll // ---------------------------------------------------------------------------- @@ -90,12 +114,16 @@ void RagDoll::init(const QVector& states) { _points.push_back(state.getPosition()); int parentIndex = state.getFBXJoint().parentIndex; assert(parentIndex < i); - if (parentIndex != -1) { + if (parentIndex == -1) { + FixedConstraint* anchor = new FixedConstraint(&(_points[i]), glm::vec3(0.0f)); + _constraints.push_back(anchor); + } else { DistanceConstraint* stick = new DistanceConstraint(&(_points[i]), &(_points[parentIndex])); _constraints.push_back(stick); } } } + /// Delete all data. void RagDoll::clear() { int numConstraints = _constraints.size(); @@ -129,3 +157,11 @@ float RagDoll::enforceConstraints() { } return maxDistance; } + +void RagDoll::updateShapes(const QVector& shapes, const glm::quat& rotation, const glm::vec3& translation) const { + int numShapes = shapes.size(); + int numConstraints = _constraints.size(); + for (int i = 0; i < numShapes && i < numConstraints; ++i) { + _constraints[i]->updateProxyShape(shapes[i], rotation, translation); + } +} diff --git a/interface/src/renderer/RagDoll.h b/interface/src/renderer/RagDoll.h index 1d23973827..60e242d19b 100644 --- a/interface/src/renderer/RagDoll.h +++ b/interface/src/renderer/RagDoll.h @@ -14,6 +14,8 @@ #include "renderer/Model.h" +class Shape; + class Constraint { public: Constraint() {} @@ -22,11 +24,20 @@ public: /// Enforce contraint by moving relevant points. /// \return max distance of point movement virtual float enforce() = 0; + + /// \param shape pointer to shape that will be this Constraint's collision proxy + /// \param rotation rotation into shape's collision frame + /// \param translation translation into shape's collision frame + /// Moves the shape such that it will collide at this constraint's position + virtual void updateProxyShape(Shape* shape, const glm::quat& rotation, const glm::vec3& translation) const {} + +protected: + int _type; }; class FixedConstraint : public Constraint { public: - FixedConstraint(); + FixedConstraint(glm::vec3* point, const glm::vec3& anchor); float enforce(); void setPoint(glm::vec3* point); void setAnchor(const glm::vec3& anchor); @@ -37,10 +48,11 @@ private: class DistanceConstraint : public Constraint { public: - DistanceConstraint(glm::vec3* pointA, glm::vec3* pointB); + DistanceConstraint(glm::vec3* startPoint, glm::vec3* endPoint); DistanceConstraint(const DistanceConstraint& other); float enforce(); void setDistance(float distance); + void updateProxyShape(Shape* shape, const glm::quat& rotation, const glm::vec3& translation) const; private: float _distance; glm::vec3* _points[2]; @@ -69,7 +81,12 @@ public: float enforceConstraints(); const QVector& getPoints() const { return _points; } - + + /// \param shapes list of shapes to be updated with new positions + /// \param rotation rotation into shapes' collision frame + /// \param translation translation into shapes' collision frame + void updateShapes(const QVector& shapes, const glm::quat& rotation, const glm::vec3& translation) const; + private: QVector _constraints; QVector _points; From 6eac0ee2aeb262feee7a192b17c786c933e1d8db Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 9 Jun 2014 10:58:56 -0700 Subject: [PATCH 4/6] Avoid crash on zero-length normals. --- libraries/fbx/src/FBXReader.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 60412cf0ce..d668349b96 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -894,14 +894,19 @@ FBXBlendshape extractBlendshape(const FBXNode& object) { } void setTangents(FBXMesh& mesh, int firstIndex, int secondIndex) { - glm::vec3 normal = glm::normalize(mesh.normals.at(firstIndex)); - glm::vec3 bitangent = glm::cross(normal, mesh.vertices.at(secondIndex) - mesh.vertices.at(firstIndex)); + const glm::vec3& normal = mesh.normals.at(firstIndex); + float normalLength = glm::length(normal); + if (normalLength < EPSILON) { + return; + } + glm::vec3 normalizedNormal = normal / normalLength; + glm::vec3 bitangent = glm::cross(normalizedNormal, mesh.vertices.at(secondIndex) - mesh.vertices.at(firstIndex)); if (glm::length(bitangent) < EPSILON) { return; } glm::vec2 texCoordDelta = mesh.texCoords.at(secondIndex) - mesh.texCoords.at(firstIndex); - mesh.tangents[firstIndex] += glm::cross(glm::angleAxis( - - atan2f(-texCoordDelta.t, texCoordDelta.s), normal) * glm::normalize(bitangent), normal); + mesh.tangents[firstIndex] += glm::cross(glm::angleAxis(-atan2f(-texCoordDelta.t, texCoordDelta.s), normalizedNormal) * + glm::normalize(bitangent), normalizedNormal); } QVector getIndices(const QVector ids, QVector modelIDs) { From a1e208ae3d3173ca4490a9d96941e860adf9e0b0 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 9 Jun 2014 11:03:50 -0700 Subject: [PATCH 5/6] Simplification. If the normal is zero, then the cross product will also be zero, so we can just have the one check and postpone normalization until afterwards. --- libraries/fbx/src/FBXReader.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index d668349b96..9aeb81a2a3 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -895,16 +895,12 @@ FBXBlendshape extractBlendshape(const FBXNode& object) { void setTangents(FBXMesh& mesh, int firstIndex, int secondIndex) { const glm::vec3& normal = mesh.normals.at(firstIndex); - float normalLength = glm::length(normal); - if (normalLength < EPSILON) { - return; - } - glm::vec3 normalizedNormal = normal / normalLength; - glm::vec3 bitangent = glm::cross(normalizedNormal, mesh.vertices.at(secondIndex) - mesh.vertices.at(firstIndex)); + glm::vec3 bitangent = glm::cross(normal, mesh.vertices.at(secondIndex) - mesh.vertices.at(firstIndex)); if (glm::length(bitangent) < EPSILON) { return; } glm::vec2 texCoordDelta = mesh.texCoords.at(secondIndex) - mesh.texCoords.at(firstIndex); + glm::vec3 normalizedNormal = glm::normalize(normal); mesh.tangents[firstIndex] += glm::cross(glm::angleAxis(-atan2f(-texCoordDelta.t, texCoordDelta.s), normalizedNormal) * glm::normalize(bitangent), normalizedNormal); } From 4f9da0cc3716dccf58ce25affc15cb1b9886040e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 9 Jun 2014 11:50:31 -0700 Subject: [PATCH 6/6] fix whitespace formatting --- interface/src/renderer/RagDoll.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/renderer/RagDoll.cpp b/interface/src/renderer/RagDoll.cpp index e2654d737f..305724d6e4 100644 --- a/interface/src/renderer/RagDoll.cpp +++ b/interface/src/renderer/RagDoll.cpp @@ -23,7 +23,7 @@ // ---------------------------------------------------------------------------- // FixedConstraint // ---------------------------------------------------------------------------- -FixedConstraint::FixedConstraint(glm::vec3* point, const glm::vec3& anchor ) : _point(point), _anchor(anchor) { +FixedConstraint::FixedConstraint(glm::vec3* point, const glm::vec3& anchor) : _point(point), _anchor(anchor) { } float FixedConstraint::enforce() { @@ -84,7 +84,7 @@ void DistanceConstraint::updateProxyShape(Shape* shape, const glm::quat& rotatio } break; case Shape::CAPSULE_SHAPE: { - // capsule collides from startPoint to endPoint + // capsule collides from startPoint to endPoint CapsuleShape* capsule = static_cast(shape); capsule->setEndPoints(translation + rotation * (*_points[0]), translation + rotation * (*_points[1])); }