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