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

This commit is contained in:
Andrzej Kapolka 2014-06-09 11:55:30 -07:00
commit 32cf08ce65
11 changed files with 106 additions and 30 deletions

View file

@ -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,

View file

@ -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";

View file

@ -23,7 +23,10 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar) :
void SkeletonModel::setJointStates(QVector<JointState> 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<const Shape*>& 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;

View file

@ -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

View file

@ -140,7 +140,7 @@ public:
void clearShapes();
void rebuildShapes();
void resetShapePositions();
void updateShapePositions();
virtual void updateShapePositions();
void renderJointCollisionShapes(float alpha);
void renderBoundingCollisionShapes(float alpha);

View file

@ -15,13 +15,15 @@
#include <CollisionInfo.h>
#include <SharedUtil.h>
#include <CapsuleShape.h>
#include <SphereShape.h>
#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<SphereShape*>(shape);
sphere->setPosition(translation + rotation * (*_points[1]));
}
break;
case Shape::CAPSULE_SHAPE: {
// capsule collides from startPoint to endPoint
CapsuleShape* capsule = static_cast<CapsuleShape*>(shape);
capsule->setEndPoints(translation + rotation * (*_points[0]), translation + rotation * (*_points[1]));
}
break;
default:
break;
}
}
// ----------------------------------------------------------------------------
// RagDoll
// ----------------------------------------------------------------------------
@ -90,12 +114,16 @@ void RagDoll::init(const QVector<JointState>& 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<Shape*>& 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);
}
}

View file

@ -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<glm::vec3>& 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<Shape*>& shapes, const glm::quat& rotation, const glm::vec3& translation) const;
private:
QVector<Constraint*> _constraints;
QVector<glm::vec3> _points;

View file

@ -894,14 +894,15 @@ FBXBlendshape extractBlendshape(const FBXNode& object) {
}
void setTangents(FBXMesh& mesh, int firstIndex, int secondIndex) {
glm::vec3 normal = glm::normalize(mesh.normals.at(firstIndex));
const glm::vec3& normal = mesh.normals.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);
mesh.tangents[firstIndex] += glm::cross(glm::angleAxis(
- atan2f(-texCoordDelta.t, texCoordDelta.s), normal) * glm::normalize(bitangent), normal);
glm::vec3 normalizedNormal = glm::normalize(normal);
mesh.tangents[firstIndex] += glm::cross(glm::angleAxis(-atan2f(-texCoordDelta.t, texCoordDelta.s), normalizedNormal) *
glm::normalize(bitangent), normalizedNormal);
}
QVector<int> getIndices(const QVector<QString> ids, QVector<QString> modelIDs) {

View file

@ -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);

View file

@ -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();
}

View file

@ -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; }