Use NULL Shape* for non-colliding joints in Models

This commit is contained in:
Andrew Meadows 2014-06-09 09:35:27 -07:00
parent 90c55ad06c
commit 8e536ebd9a
3 changed files with 48 additions and 28 deletions

View file

@ -135,18 +135,21 @@ void SkeletonModel::getHandShapes(int jointIndex, QVector<const Shape*>& shapes)
for (int i = 0; i < _jointStates.size(); i++) {
const FBXJoint& joint = geometry.joints[i];
int parentIndex = joint.parentIndex;
Shape* shape = _jointShapes[i];
if (i == jointIndex) {
// this shape is the hand
shapes.push_back(_jointShapes[i]);
if (parentIndex != -1) {
if (shape) {
shapes.push_back(shape);
}
if (parentIndex != -1 && _jointShapes[parentIndex]) {
// also add the forearm
shapes.push_back(_jointShapes[parentIndex]);
}
} else {
} else if (shape) {
while (parentIndex != -1) {
if (parentIndex == jointIndex) {
// this shape is a child of the hand
shapes.push_back(_jointShapes[i]);
shapes.push_back(shape);
break;
}
parentIndex = geometry.joints[parentIndex].parentIndex;

View file

@ -813,11 +813,8 @@ void Model::rebuildShapes() {
_jointShapes.push_back(sphere);
} else {
// this shape type is not handled and the joint shouldn't collide,
// however we must have a shape for each joint,
// so we make a bogus sphere with zero radius.
// TODO: implement collision groups for more control over what collides with what
SphereShape* sphere = new SphereShape(0.0f, glm::vec3(0.0f));
_jointShapes.push_back(sphere);
// however we must have a Shape* for each joint, so we push NULL
_jointShapes.push_back(NULL);
}
}
@ -875,10 +872,13 @@ void Model::computeBoundingShape(const FBXGeometry& geometry) {
_boundingRadius = 0.0f;
float uniformScale = extractUniformScale(_scale);
for (int i = 0; i < _jointShapes.size(); i++) {
Shape* shape = _jointShapes[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* shape = _jointShapes[i];
shape->setPosition(localPosition);
shape->setRotation(finalRotations[i] * joint.shapeRotation);
float distance = glm::length(localPosition) + shape->getBoundingRadius();
@ -890,11 +890,14 @@ void Model::computeBoundingShape(const FBXGeometry& geometry) {
// compute bounding box
Extents totalExtents;
totalExtents.reset();
totalExtents.addPoint(glm::vec3(0.0f));
for (int i = 0; i < _jointShapes.size(); i++) {
Shape* shape = _jointShapes[i];
if (!shape) {
continue;
}
Extents shapeExtents;
shapeExtents.reset();
Shape* shape = _jointShapes[i];
glm::vec3 localPosition = shape->getPosition();
int type = shape->getType();
if (type == Shape::CAPSULE_SHAPE) {
@ -949,8 +952,10 @@ void Model::resetShapePositions() {
// Then we move them into world frame for rendering at the Model's location.
for (int i = 0; i < _jointShapes.size(); i++) {
Shape* shape = _jointShapes[i];
shape->setPosition(_translation + _rotation * shape->getPosition());
shape->setRotation(_rotation * shape->getRotation());
if (shape) {
shape->setPosition(_translation + _rotation * shape->getPosition());
shape->setRotation(_rotation * shape->getRotation());
}
}
_boundingShape.setPosition(_translation + _rotation * _boundingShapeLocalOffset);
_boundingShape.setRotation(_rotation);
@ -969,11 +974,13 @@ void Model::updateShapePositions() {
glm::vec3 shapeOffset = uniformScale * (stateRotation * joint.shapePosition);
glm::vec3 worldPosition = _translation + _rotation * (state.getPosition() + shapeOffset);
Shape* shape = _jointShapes[i];
shape->setPosition(worldPosition);
shape->setRotation(_rotation * stateRotation * joint.shapeRotation);
float distance = glm::distance(worldPosition, _translation) + shape->getBoundingRadius();
if (distance > _boundingRadius) {
_boundingRadius = distance;
if (shape) {
shape->setPosition(worldPosition);
shape->setRotation(_rotation * stateRotation * joint.shapeRotation);
float distance = glm::distance(worldPosition, _translation) + shape->getBoundingRadius();
if (distance > _boundingRadius) {
_boundingRadius = distance;
}
}
if (joint.parentIndex == -1) {
rootPosition = worldPosition;
@ -1018,9 +1025,12 @@ bool Model::findCollisions(const QVector<const Shape*> shapes, CollisionList& co
bool collided = false;
for (int i = 0; i < shapes.size(); ++i) {
const Shape* theirShape = shapes[i];
if (!theirShape) {
continue;
}
for (int j = 0; j < _jointShapes.size(); ++j) {
const Shape* ourShape = _jointShapes[j];
if (ShapeCollider::collideShapes(theirShape, ourShape, collisions)) {
if (ourShape && ShapeCollider::collideShapes(theirShape, ourShape, collisions)) {
collided = true;
}
}
@ -1034,6 +1044,10 @@ bool Model::findSphereCollisions(const glm::vec3& sphereCenter, float sphereRadi
SphereShape sphere(sphereRadius, sphereCenter);
const FBXGeometry& geometry = _geometry->getFBXGeometry();
for (int i = 0; i < _jointShapes.size(); i++) {
Shape* shape = _jointShapes[i];
if (!shape) {
continue;
}
const FBXJoint& joint = geometry.joints[i];
if (joint.parentIndex != -1) {
if (skipIndex != -1) {
@ -1047,7 +1061,7 @@ bool Model::findSphereCollisions(const glm::vec3& sphereCenter, float sphereRadi
} while (ancestorIndex != -1);
}
}
if (ShapeCollider::collideShapes(&sphere, _jointShapes[i], collisions)) {
if (ShapeCollider::collideShapes(&sphere, shape, collisions)) {
CollisionInfo* collision = collisions.getLastCollision();
collision->_data = (void*)(this);
collision->_intData = i;
@ -1062,7 +1076,7 @@ bool Model::findPlaneCollisions(const glm::vec4& plane, CollisionList& collision
bool collided = false;
PlaneShape planeShape(plane);
for (int i = 0; i < _jointShapes.size(); i++) {
if (ShapeCollider::collideShapes(&planeShape, _jointShapes[i], collisions)) {
if (_jointShapes[i] && ShapeCollider::collideShapes(&planeShape, _jointShapes[i], collisions)) {
CollisionInfo* collision = collisions.getLastCollision();
collision->_data = (void*)(this);
collision->_intData = i;
@ -1369,10 +1383,12 @@ void Model::renderJointCollisionShapes(float alpha) {
glPushMatrix();
Application::getInstance()->loadTranslatedViewMatrix(_translation);
for (int i = 0; i < _jointShapes.size(); i++) {
glPushMatrix();
Shape* shape = _jointShapes[i];
if (!shape) {
continue;
}
glPushMatrix();
if (shape->getType() == Shape::SPHERE_SHAPE) {
// shapes are stored in world-frame, so we have to transform into model frame
glm::vec3 position = shape->getPosition() - _translation;

View file

@ -137,10 +137,11 @@ public:
const QList<AnimationHandlePointer>& getRunningAnimations() const { return _runningAnimations; }
void clearShapes();
void rebuildShapes();
void resetShapePositions();
virtual void clearShapes();
virtual void rebuildShapes();
void resetShapePositions(); // DEBUG method
virtual void updateShapePositions();
void renderJointCollisionShapes(float alpha);
void renderBoundingCollisionShapes(float alpha);