mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 23:33:48 +02:00
Skeleton now creates VerletShape
This commit is contained in:
parent
715cc3467d
commit
d4b5550cda
10 changed files with 117 additions and 189 deletions
|
@ -218,9 +218,6 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
|
|||
bool renderSkeleton = Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionShapes);
|
||||
bool renderHead = Menu::getInstance()->isOptionChecked(MenuOption::RenderHeadCollisionShapes);
|
||||
bool renderBounding = Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes);
|
||||
if (renderSkeleton || renderHead || renderBounding) {
|
||||
updateShapePositions();
|
||||
}
|
||||
|
||||
if (renderSkeleton) {
|
||||
_skeletonModel.renderJointCollisionShapes(0.7f);
|
||||
|
@ -590,18 +587,6 @@ bool Avatar::findPlaneCollisions(const glm::vec4& plane, CollisionList& collisio
|
|||
getHead()->getFaceModel().findPlaneCollisions(plane, collisions);
|
||||
}
|
||||
|
||||
void Avatar::updateShapePositions() {
|
||||
_skeletonModel.updateShapePositions();
|
||||
Model& headModel = getHead()->getFaceModel();
|
||||
headModel.updateShapePositions();
|
||||
/* KEEP FOR DEBUG: use this in rather than code above to see shapes
|
||||
* in their default positions where the bounding shape is computed.
|
||||
_skeletonModel.resetShapePositions();
|
||||
Model& headModel = getHead()->getFaceModel();
|
||||
headModel.resetShapePositions();
|
||||
*/
|
||||
}
|
||||
|
||||
bool Avatar::findCollisions(const QVector<const Shape*>& shapes, CollisionList& collisions) {
|
||||
// TODO: Andrew to fix: also collide against _skeleton
|
||||
//bool collided = _skeletonModel.findCollisions(shapes, collisions);
|
||||
|
|
|
@ -136,7 +136,6 @@ public:
|
|||
|
||||
/// \return bounding radius of avatar
|
||||
virtual float getBoundingRadius() const;
|
||||
void updateShapePositions();
|
||||
|
||||
quint32 getCollisionGroups() const { return _collisionGroups; }
|
||||
virtual void setCollisionGroups(quint32 collisionGroups) { _collisionGroups = (collisionGroups & VALID_COLLISION_GROUPS); }
|
||||
|
|
|
@ -210,7 +210,6 @@ void MyAvatar::simulate(float deltaTime) {
|
|||
radius = myCamera->getAspectRatio() * (myCamera->getNearClip() / cos(myCamera->getFieldOfView() / 2.0f));
|
||||
radius *= COLLISION_RADIUS_SCALAR;
|
||||
}
|
||||
updateShapePositions();
|
||||
if (_collisionGroups & COLLISION_GROUP_ENVIRONMENT) {
|
||||
PerformanceTimer perfTimer("MyAvatar::simulate/updateCollisionWithEnvironment");
|
||||
updateCollisionWithEnvironment(deltaTime, radius);
|
||||
|
@ -1447,7 +1446,6 @@ void MyAvatar::updateCollisionWithAvatars(float deltaTime) {
|
|||
// don't collide with ourselves
|
||||
continue;
|
||||
}
|
||||
avatar->updateShapePositions();
|
||||
float distance = glm::length(_position - avatar->getPosition());
|
||||
if (_distanceToNearestAvatar > distance) {
|
||||
_distanceToNearestAvatar = distance;
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
||||
#include <CapsuleShape.h>
|
||||
#include <SphereShape.h>
|
||||
#include <VerletCapsuleShape.h>
|
||||
#include <VerletSphereShape.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Avatar.h"
|
||||
|
@ -31,20 +31,10 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) :
|
|||
void SkeletonModel::setJointStates(QVector<JointState> states) {
|
||||
Model::setJointStates(states);
|
||||
|
||||
if (isActive() && _owningAvatar->isMyAvatar()) {
|
||||
// extract lists of parentIndex and position from _jointStates...
|
||||
QVector<int> parentIndices;
|
||||
QVector<glm::vec3> points;
|
||||
int numJoints = _jointStates.size();
|
||||
parentIndices.reserve(numJoints);
|
||||
points.reserve(numJoints);
|
||||
for (int i = 0; i < numJoints; ++i) {
|
||||
JointState& state = _jointStates[i];
|
||||
parentIndices.push_back(state.getFBXJoint().parentIndex);
|
||||
points.push_back(state.getPosition());
|
||||
}
|
||||
// ... and feed the results to Ragdoll
|
||||
initShapesAndPoints(&_shapes, parentIndices, points);
|
||||
clearShapes();
|
||||
clearRagdollConstraintsAndPoints();
|
||||
if (_enableShapes) {
|
||||
buildShapes();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,14 +100,11 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
|
|||
}
|
||||
|
||||
void SkeletonModel::simulateRagdoll(float deltaTime) {
|
||||
// move ragdoll _points toward joints
|
||||
// move _ragdollPoints toward joints
|
||||
const int numStates = _jointStates.size();
|
||||
assert(numStates == _points.size());
|
||||
assert(numStates == _ragdollPoints.size());
|
||||
float fraction = 0.1f; // fraction = 0.1f left intentionally low for demo purposes
|
||||
float oneMinusFraction = 1.0f - fraction;
|
||||
for (int i = 0; i < numStates; ++i) {
|
||||
_points[i] = oneMinusFraction * _points[i] + fraction * _jointStates[i].getPosition();
|
||||
}
|
||||
moveShapesTowardJoints(fraction);
|
||||
|
||||
// enforce the constraints
|
||||
float MIN_CONSTRAINT_ERROR = 0.005f; // 5mm
|
||||
|
@ -125,7 +112,7 @@ void SkeletonModel::simulateRagdoll(float deltaTime) {
|
|||
int iterations = 0;
|
||||
float delta = 0.0f;
|
||||
do {
|
||||
delta = enforceConstraints();
|
||||
delta = enforceRagdollConstraints();
|
||||
++iterations;
|
||||
} while (delta > MIN_CONSTRAINT_ERROR && iterations < MAX_ITERATIONS);
|
||||
}
|
||||
|
@ -274,16 +261,6 @@ void SkeletonModel::updateJointState(int index) {
|
|||
}
|
||||
}
|
||||
|
||||
void SkeletonModel::updateShapePositions() {
|
||||
if (isActive() && _owningAvatar->isMyAvatar() &&
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::CollideAsRagdoll)) {
|
||||
// TODO: Andrew to move shape updates to SimulationEngine
|
||||
//updateShapes(_rotation, _translation);
|
||||
} else {
|
||||
Model::updateShapePositions();
|
||||
}
|
||||
}
|
||||
|
||||
void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
|
||||
if (!_owningAvatar->isMyAvatar() || Application::getInstance()->getPrioVR()->isActive()) {
|
||||
return;
|
||||
|
@ -516,14 +493,14 @@ void SkeletonModel::renderRagdoll() {
|
|||
glPushMatrix();
|
||||
|
||||
Application::getInstance()->loadTranslatedViewMatrix(_translation);
|
||||
int numPoints = _points.size();
|
||||
int numPoints = _ragdollPoints.size();
|
||||
float alpha = 0.3f;
|
||||
float radius1 = 0.008f;
|
||||
float radius2 = 0.01f;
|
||||
for (int i = 0; i < numPoints; ++i) {
|
||||
glPushMatrix();
|
||||
// draw each point as a yellow hexagon with black border
|
||||
glm::vec3 position = _rotation * _points[i];
|
||||
glm::vec3 position = _rotation * _ragdollPoints[i];
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glColor4f(0.0f, 0.0f, 0.0f, alpha);
|
||||
glutSolidSphere(radius2, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS);
|
||||
|
@ -536,6 +513,22 @@ void SkeletonModel::renderRagdoll() {
|
|||
glEnable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
// virtual
|
||||
void SkeletonModel::initRagdollPoints() {
|
||||
assert(_ragdollPoints.size() == 0);
|
||||
// one point for each joint
|
||||
int numJoints = _jointStates.size();
|
||||
_ragdollPoints.reserve(numJoints);
|
||||
for (int i = 0; i < numJoints; ++i) {
|
||||
const JointState& state = _jointStates.at(i);
|
||||
_ragdollPoints.push_back(state.getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
void SkeletonModel::stepRagdollForward(float deltaTime) {
|
||||
}
|
||||
|
||||
// virtual
|
||||
void SkeletonModel::buildShapes() {
|
||||
if (!_geometry || _rootIndex == -1) {
|
||||
|
@ -546,42 +539,53 @@ void SkeletonModel::buildShapes() {
|
|||
if (geometry.joints.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// We create the shapes with proper dimensions, but we set their transforms later.
|
||||
float uniformScale = extractUniformScale(_scale);
|
||||
for (int i = 0; i < _jointStates.size(); i++) {
|
||||
const FBXJoint& joint = geometry.joints[i];
|
||||
|
||||
initRagdollPoints();
|
||||
|
||||
float uniformScale = extractUniformScale(_scale);
|
||||
const int numStates = _jointStates.size();
|
||||
for (int i = 0; i < numStates; i++) {
|
||||
const FBXJoint& joint = geometry.joints[i];
|
||||
float radius = uniformScale * joint.boneRadius;
|
||||
float halfHeight = 0.5f * uniformScale * joint.distanceToParent;
|
||||
Shape::Type type = joint.shapeType;
|
||||
if (type == Shape::CAPSULE_SHAPE && halfHeight < EPSILON) {
|
||||
// this capsule is effectively a sphere
|
||||
if (i == 0 || (type == Shape::CAPSULE_SHAPE && halfHeight < EPSILON)) {
|
||||
// this shape is forced to be a sphere
|
||||
type = Shape::SPHERE_SHAPE;
|
||||
}
|
||||
if (type == Shape::CAPSULE_SHAPE) {
|
||||
CapsuleShape* capsule = new CapsuleShape(radius, halfHeight);
|
||||
capsule->setEntity(this);
|
||||
_shapes.push_back(capsule);
|
||||
} else if (type == Shape::SPHERE_SHAPE) {
|
||||
SphereShape* sphere = new SphereShape(radius, glm::vec3(0.0f));
|
||||
_shapes.push_back(sphere);
|
||||
sphere->setEntity(this);
|
||||
} else {
|
||||
// this shape type is not handled and the joint shouldn't collide,
|
||||
// however we must have a Shape* for each joint, so we push NULL
|
||||
_shapes.push_back(NULL);
|
||||
}
|
||||
Shape* shape = NULL;
|
||||
if (type == Shape::SPHERE_SHAPE) {
|
||||
shape = new VerletSphereShape(radius, &(_ragdollPoints[i]));
|
||||
shape->setEntity(this);
|
||||
} else if (type == Shape::CAPSULE_SHAPE) {
|
||||
int parentIndex = joint.parentIndex;
|
||||
assert(parentIndex != -1);
|
||||
shape = new VerletCapsuleShape(radius, &(_ragdollPoints[parentIndex]), &(_ragdollPoints[i]));
|
||||
shape->setEntity(this);
|
||||
}
|
||||
_shapes.push_back(shape);
|
||||
}
|
||||
|
||||
// This method moves the shapes to their default positions in Model frame
|
||||
// which is where we compute the bounding shape's parameters.
|
||||
computeBoundingShape(geometry);
|
||||
|
||||
// finally sync shapes to joint positions
|
||||
_shapesAreDirty = true;
|
||||
updateShapePositions();
|
||||
// move shapes to joint positions
|
||||
moveShapesTowardJoints(1.0f);
|
||||
}
|
||||
|
||||
void SkeletonModel::moveShapesTowardJoints(float fraction) {
|
||||
assert(fraction >= 0.0f && fraction <= 1.0f);
|
||||
if (_ragdollPoints.size() == _jointStates.size()) {
|
||||
float oneMinusFraction = 1.0f - fraction;
|
||||
int numJoints = _jointStates.size();
|
||||
for (int i = 0; i < numJoints; ++i) {
|
||||
_ragdollPoints[i] = oneMinusFraction * _ragdollPoints[i] + fraction * _jointStates.at(i).getPosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Andrew to remove this when done with ragdoll work.
|
||||
void SkeletonModel::updateShapePositionsLegacy() {
|
||||
if (_shapesAreDirty && _shapes.size() == _jointStates.size()) {
|
||||
glm::vec3 rootPosition(0.0f);
|
||||
|
@ -612,65 +616,28 @@ void SkeletonModel::updateShapePositionsLegacy() {
|
|||
_boundingShape.setRotation(_rotation);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
|
||||
// compute default joint transforms and rotations
|
||||
// (in local frame, ignoring Model translation and rotation)
|
||||
// compute default joint transforms
|
||||
int numJoints = geometry.joints.size();
|
||||
if (numJoints != _ragdollPoints.size()) {
|
||||
return;
|
||||
}
|
||||
QVector<glm::mat4> transforms;
|
||||
transforms.fill(glm::mat4(), numJoints);
|
||||
QVector<glm::quat> finalRotations;
|
||||
finalRotations.fill(glm::quat(), numJoints);
|
||||
|
||||
QVector<bool> shapeIsSet;
|
||||
shapeIsSet.fill(false, numJoints);
|
||||
int numShapesSet = 0;
|
||||
int lastNumShapesSet = -1;
|
||||
while (numShapesSet < numJoints && numShapesSet != lastNumShapesSet) {
|
||||
lastNumShapesSet = numShapesSet;
|
||||
for (int i = 0; i < numJoints; i++) {
|
||||
const FBXJoint& joint = geometry.joints.at(i);
|
||||
int parentIndex = joint.parentIndex;
|
||||
|
||||
if (parentIndex == -1) {
|
||||
glm::mat4 baseTransform = glm::scale(_scale) * glm::translate(_offset);
|
||||
glm::quat combinedRotation = joint.preRotation * joint.rotation * joint.postRotation;
|
||||
glm::mat4 rootTransform = baseTransform * geometry.offset * glm::translate(joint.translation)
|
||||
* joint.preTransform * glm::mat4_cast(combinedRotation) * joint.postTransform;
|
||||
// remove the tranlsation part before we save the root transform
|
||||
transforms[i] = glm::translate(- extractTranslation(rootTransform)) * rootTransform;
|
||||
|
||||
finalRotations[i] = combinedRotation;
|
||||
++numShapesSet;
|
||||
shapeIsSet[i] = true;
|
||||
} else if (shapeIsSet[parentIndex]) {
|
||||
glm::quat combinedRotation = joint.preRotation * joint.rotation * joint.postRotation;
|
||||
transforms[i] = transforms[parentIndex] * glm::translate(joint.translation)
|
||||
* joint.preTransform * glm::mat4_cast(combinedRotation) * joint.postTransform;
|
||||
finalRotations[i] = finalRotations[parentIndex] * combinedRotation;
|
||||
++numShapesSet;
|
||||
shapeIsSet[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sync shapes to joints
|
||||
_boundingRadius = 0.0f;
|
||||
float uniformScale = extractUniformScale(_scale);
|
||||
for (int i = 0; i < _shapes.size(); i++) {
|
||||
Shape* shape = _shapes[i];
|
||||
if (!shape) {
|
||||
continue;
|
||||
}
|
||||
const FBXJoint& joint = geometry.joints[i];
|
||||
glm::vec3 jointToShapeOffset = uniformScale * (finalRotations[i] * joint.shapePosition);
|
||||
glm::vec3 localPosition = extractTranslation(transforms[i]) + jointToShapeOffset;
|
||||
shape->setTranslation(localPosition);
|
||||
shape->setRotation(finalRotations[i] * joint.shapeRotation);
|
||||
float distance = glm::length(localPosition) + shape->getBoundingRadius();
|
||||
if (distance > _boundingRadius) {
|
||||
_boundingRadius = distance;
|
||||
}
|
||||
transforms[0] = glm::scale(_scale);
|
||||
for (int i = 1; i < numJoints; i++) {
|
||||
const FBXJoint& joint = geometry.joints.at(i);
|
||||
int parentIndex = joint.parentIndex;
|
||||
assert(parentIndex != -1);
|
||||
|
||||
glm::quat modifiedRotation = joint.preRotation * joint.rotation * joint.postRotation;
|
||||
transforms[i] = transforms[parentIndex] * glm::translate(joint.translation)
|
||||
* joint.preTransform * glm::mat4_cast(modifiedRotation) * joint.postTransform;
|
||||
// setting the ragdollPoints here slams the VerletShapes into their default positions
|
||||
_ragdollPoints[i] = extractTranslation(transforms[i]);
|
||||
}
|
||||
|
||||
// compute bounding box
|
||||
|
@ -682,6 +649,7 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
|
|||
if (!shape) {
|
||||
continue;
|
||||
}
|
||||
// TODO: skip hand and arm joints when computing bounding dimensions
|
||||
Extents shapeExtents;
|
||||
shapeExtents.reset();
|
||||
glm::vec3 localPosition = shape->getTranslation();
|
||||
|
@ -715,6 +683,7 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
|
|||
_boundingShape.setRadius(capsuleRadius);
|
||||
_boundingShape.setHalfHeight(0.5f * diagonal.y - capsuleRadius);
|
||||
_boundingShapeLocalOffset = 0.5f * (totalExtents.maximum + totalExtents.minimum);
|
||||
_boundingRadius = 0.5f * glm::length(diagonal);
|
||||
}
|
||||
|
||||
void SkeletonModel::resetShapePositions() {
|
||||
|
|
|
@ -95,9 +95,12 @@ public:
|
|||
/// \return whether or not both eye meshes were found
|
||||
bool getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const;
|
||||
|
||||
virtual void initRagdollPoints();
|
||||
virtual void stepRagdollForward(float deltaTime);
|
||||
|
||||
void buildShapes();
|
||||
void updateShapePositions();
|
||||
void updateShapePositionsLegacy();
|
||||
void moveShapesTowardJoints(float fraction);
|
||||
//void updateShapePositionsLegacy(); // TODO: Andrew to remove this when done with ragdoll work
|
||||
|
||||
void computeBoundingShape(const FBXGeometry& geometry);
|
||||
void renderBoundingCollisionShapes(float alpha);
|
||||
|
|
|
@ -551,9 +551,6 @@ bool Model::updateGeometry() {
|
|||
model->setURL(attachment.url);
|
||||
_attachments.append(model);
|
||||
}
|
||||
if (_enableShapes) {
|
||||
buildShapes();
|
||||
}
|
||||
needFullUpdate = true;
|
||||
}
|
||||
return needFullUpdate;
|
||||
|
|
|
@ -92,7 +92,7 @@ bool PhysicalEntity::findCollisions(const QVector<const Shape*> shapes, Collisio
|
|||
}
|
||||
int numOurShapes = _shapes.size();
|
||||
for (int j = 0; j < numOurShapes; ++j) {
|
||||
const Shape* ourShape = _shapes[j];
|
||||
const Shape* ourShape = _shapes.at(j);
|
||||
if (ourShape && ShapeCollider::collideShapes(theirShape, ourShape, collisions)) {
|
||||
collided = true;
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ bool PhysicalEntity::findPlaneCollisions(const glm::vec4& plane, CollisionList&
|
|||
bool collided = false;
|
||||
PlaneShape planeShape(plane);
|
||||
for (int i = 0; i < _shapes.size(); i++) {
|
||||
if (_shapes[i] && ShapeCollider::collideShapes(&planeShape, _shapes[i], collisions)) {
|
||||
if (_shapes.at(i) && ShapeCollider::collideShapes(&planeShape, _shapes.at(i), collisions)) {
|
||||
CollisionInfo* collision = collisions.getLastCollision();
|
||||
collision->_data = (void*)(this);
|
||||
collision->_intData = i;
|
||||
|
|
|
@ -94,66 +94,55 @@ void DistanceConstraint::updateProxyShape(Shape* shape, const glm::quat& rotatio
|
|||
// Ragdoll
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
Ragdoll::Ragdoll() : _verletShapes(NULL) {
|
||||
Ragdoll::Ragdoll() {
|
||||
}
|
||||
|
||||
Ragdoll::~Ragdoll() {
|
||||
clear();
|
||||
clearRagdollConstraintsAndPoints();
|
||||
}
|
||||
|
||||
void Ragdoll::initShapesAndPoints(QVector<Shape*>* shapes, const QVector<int>& parentIndices, const QVector<glm::vec3>& points) {
|
||||
/*
|
||||
void Ragdoll::useShapesAndCopyPoints(QVector<Shape*>* shapes, const QVector<int>& parentIndices, const QVector<glm::vec3>& points) {
|
||||
clear();
|
||||
_verletShapes = shapes;
|
||||
const int numPoints = points.size();
|
||||
assert(numPoints == parentIndices.size());
|
||||
_points.reserve(numPoints);
|
||||
_ragdollPoints.reserve(numPoints);
|
||||
for (int i = 0; i < numPoints; ++i) {
|
||||
glm::vec3 position = points[i];
|
||||
_points.push_back(position);
|
||||
_ragdollPoints.push_back(position);
|
||||
|
||||
int parentIndex = parentIndices[i];
|
||||
assert(parentIndex < i && parentIndex >= -1);
|
||||
if (parentIndex == -1) {
|
||||
FixedConstraint* anchor = new FixedConstraint(&(_points[i]), glm::vec3(0.0f));
|
||||
_constraints.push_back(anchor);
|
||||
FixedConstraint* anchor = new FixedConstraint(&(_ragdollPoints[i]), glm::vec3(0.0f));
|
||||
_ragdollConstraints.push_back(anchor);
|
||||
} else {
|
||||
DistanceConstraint* stick = new DistanceConstraint(&(_points[i]), &(_points[parentIndex]));
|
||||
_constraints.push_back(stick);
|
||||
DistanceConstraint* stick = new DistanceConstraint(&(_ragdollPoints[i]), &(_ragdollPoints[parentIndex]));
|
||||
_ragdollConstraints.push_back(stick);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/// Delete all data.
|
||||
void Ragdoll::clear() {
|
||||
int numConstraints = _constraints.size();
|
||||
void Ragdoll::clearRagdollConstraintsAndPoints() {
|
||||
int numConstraints = _ragdollConstraints.size();
|
||||
for (int i = 0; i < numConstraints; ++i) {
|
||||
delete _constraints[i];
|
||||
delete _ragdollConstraints[i];
|
||||
}
|
||||
_constraints.clear();
|
||||
_points.clear();
|
||||
_verletShapes = NULL;
|
||||
_ragdollConstraints.clear();
|
||||
_ragdollPoints.clear();
|
||||
}
|
||||
|
||||
float Ragdoll::enforceConstraints() {
|
||||
float Ragdoll::enforceRagdollConstraints() {
|
||||
float maxDistance = 0.0f;
|
||||
const int numConstraints = _constraints.size();
|
||||
const int numConstraints = _ragdollConstraints.size();
|
||||
for (int i = 0; i < numConstraints; ++i) {
|
||||
DistanceConstraint* c = static_cast<DistanceConstraint*>(_constraints[i]);
|
||||
//maxDistance = glm::max(maxDistance, _constraints[i]->enforce());
|
||||
DistanceConstraint* c = static_cast<DistanceConstraint*>(_ragdollConstraints[i]);
|
||||
//maxDistance = glm::max(maxDistance, _ragdollConstraints[i]->enforce());
|
||||
maxDistance = glm::max(maxDistance, c->enforce());
|
||||
}
|
||||
return maxDistance;
|
||||
}
|
||||
|
||||
void Ragdoll::updateShapes(const glm::quat& rotation, const glm::vec3& translation) const {
|
||||
if (!_verletShapes) {
|
||||
return;
|
||||
}
|
||||
int numShapes = _verletShapes->size();
|
||||
int numConstraints = _constraints.size();
|
||||
|
||||
// NOTE: we assume a one-to-one relationship between shapes and constraints
|
||||
for (int i = 0; i < numShapes && i < numConstraints; ++i) {
|
||||
_constraints[i]->updateProxyShape((*_verletShapes)[i], rotation, translation);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,38 +66,24 @@ public:
|
|||
|
||||
Ragdoll();
|
||||
virtual ~Ragdoll();
|
||||
|
||||
/// Create points and constraints based on topology of collection of joints
|
||||
/// \param joints list of connected joint states
|
||||
void initShapesAndPoints(QVector<Shape*>* shapes, const QVector<int>& parentIndices, const QVector<glm::vec3>& points);
|
||||
|
||||
/// Delete all data.
|
||||
void clear();
|
||||
void clearRagdollConstraintsAndPoints();
|
||||
|
||||
// TODO: Andrew to implement this
|
||||
void stepForward(float deltaTime) {}
|
||||
virtual void initRagdollPoints() = 0;
|
||||
virtual void stepRagdollForward(float deltaTime) = 0;
|
||||
|
||||
/// Enforce contraints.
|
||||
/// \return max distance of point movement
|
||||
float enforceConstraints();
|
||||
float enforceRagdollConstraints();
|
||||
|
||||
// both const and non-const getPoints()
|
||||
const QVector<glm::vec3>& getPoints() const { return _points; }
|
||||
QVector<glm::vec3>& getPoints() { return _points; }
|
||||
|
||||
/// \param rotation rotation into shapes' collision frame
|
||||
/// \param translation translation into shapes' collision frame
|
||||
/// Moves and modifies elements of _verletShapes to agree with state of _points
|
||||
void updateShapes(const glm::quat& rotation, const glm::vec3& translation) const;
|
||||
|
||||
const QVector<Shape*>* getShapes() const { return _verletShapes; }
|
||||
const QVector<glm::vec3>& getRagdollPoints() const { return _ragdollPoints; }
|
||||
QVector<glm::vec3>& getRagdollPoints() { return _ragdollPoints; }
|
||||
|
||||
protected:
|
||||
QVector<glm::vec3> _points;
|
||||
QVector<Constraint*> _constraints;
|
||||
|
||||
// the Ragdoll does NOT own the data in _verletShapes.
|
||||
QVector<Shape*>* _verletShapes;
|
||||
QVector<glm::vec3> _ragdollPoints;
|
||||
QVector<Constraint*> _ragdollConstraints;
|
||||
};
|
||||
|
||||
#endif // hifi_Ragdoll_h
|
||||
|
|
|
@ -67,6 +67,7 @@ void SimulationEngine::removeRagdoll(Ragdoll* doll) {
|
|||
}
|
||||
|
||||
void SimulationEngine::stepForward(float deltaTime, float minError, int maxIterations, quint64 maxUsec) {
|
||||
/* TODO: Andrew to make this work
|
||||
int iterations = 0;
|
||||
float delta = 0.0f;
|
||||
quint64 now = usecTimestampNow();
|
||||
|
@ -82,7 +83,7 @@ void SimulationEngine::stepForward(float deltaTime, float minError, int maxItera
|
|||
// (4) collisions move points (SpecialCapsuleShape would help solve this)
|
||||
// (5) enforce constraints
|
||||
// (6) add and enforce angular contraints for joints
|
||||
_dolls.at(i)->stepForward(deltaTime);
|
||||
//_dolls.at(i)->stepForward(deltaTime);
|
||||
}
|
||||
|
||||
|
||||
|
@ -128,6 +129,7 @@ void SimulationEngine::stepForward(float deltaTime, float minError, int maxItera
|
|||
_enforcementIterations = iterations;
|
||||
_enforcementError = delta;
|
||||
_enforcementTime = now - startTime;
|
||||
*/
|
||||
}
|
||||
|
||||
int SimulationEngine::computeCollisions() {
|
||||
|
|
Loading…
Reference in a new issue