Use capsules for some joints and render them.

This commit is contained in:
Andrew Meadows 2014-03-03 17:49:24 -08:00
parent 1a8c10e132
commit 4ef2067421
3 changed files with 75 additions and 27 deletions
interface/src/renderer

View file

@ -1620,18 +1620,18 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
}
// now that all joints have been scanned, compute a collision shape for each joint
glm::vec3 yAxis(0.f, 1.f, 0.f);
glm::vec3 defaultCapsuleAxis(0.f, 1.f, 0.f);
for (int i = 0; i < geometry.joints.size(); ++i) {
FBXJoint& joint = geometry.joints[i];
JointShapeInfo& jointShapeInfo = jointShapeInfos[i];
// we use a capsule if the joint ANY mesh vertices that successfully projected onto the bone
// we use a capsule if the joint ANY mesh vertices successfully projected onto the bone
// AND its boneRadius is not too close to zero
bool collideLikeCapsule = jointShapeInfo.numProjectedVertices > 0
&& glm::length(jointShapeInfo.boneBegin) > EPSILON;
if (collideLikeCapsule) {
joint.shapeRotation = rotationBetween(yAxis, jointShapeInfo.boneBegin);
joint.shapeRotation = rotationBetween(defaultCapsuleAxis, jointShapeInfo.boneBegin);
joint.shapePosition = 0.5f * jointShapeInfo.boneBegin;
//joint.shapePosition = glm::vec3(0.f);
joint.shapeType = Shape::CAPSULE_SHAPE;

View file

@ -26,10 +26,17 @@ extern const char* FACESHIFT_BLENDSHAPES[];
class Extents {
public:
//Extents() : minimum(FLT_MAX), maximum(-FLT_MAX) {}
/// set minimum and maximum to FLT_MAX and -FLT_MAX respectively
void reset();
/// \param point new point to compare against existing limits
/// compare point to current limits and expand them if necessary to contain point
void addPoint(const glm::vec3& point);
/// \param point
/// \return true if point is within current limits
bool containsPoint(const glm::vec3& point) const;
glm::vec3 minimum;
glm::vec3 maximum;
};
@ -73,11 +80,9 @@ public:
glm::quat inverseDefaultRotation;
glm::quat inverseBindRotation;
glm::mat4 bindTransform;
// TODO: add some comments to these data members
// Trying to provide enough info so that the proper shape can be generated in Model
QString name;
glm::vec3 shapePosition; // in joint frame (where boneEnd = origin)
glm::quat shapeRotation;
QString name; // temp field for debugging
glm::vec3 shapePosition; // in joint frame
glm::quat shapeRotation; // in joint frame
int shapeType;
};

View file

@ -142,8 +142,15 @@ void Model::createCollisionShapes() {
glm::vec3 position = _rotation * (extractTranslation(_jointStates[i].transform) + uniformScale * meshCenter) + _translation;
float radius = uniformScale * joint.boneRadius;
SphereShape* shape = new SphereShape(radius, position);
_shapes.push_back(shape);
if (joint.shapeType == Shape::CAPSULE_SHAPE) {
float halfHeight = 0.5f * uniformScale * joint.distanceToParent;
CapsuleShape* shape = new CapsuleShape(radius, halfHeight);
shape->setPosition(position);
_shapes.push_back(shape);
} else {
SphereShape* shape = new SphereShape(radius, position);
_shapes.push_back(shape);
}
}
}
@ -153,10 +160,14 @@ void Model::updateShapePositions() {
if (_shapesAreDirty && _shapes.size() == _jointStates.size()) {
for (int i = 0; i < _jointStates.size(); i++) {
const FBXJoint& joint = geometry.joints[i];
// shape positions are stored in world-frame
glm::vec3 meshCenter = _jointStates[i].combinedRotation * joint.shapePosition;
_shapes[i]->setPosition(_rotation * (extractTranslation(_jointStates[i].transform) + uniformScale * meshCenter) + _translation);
_shapes[i]->setRotation(_jointStates[i].combinedRotation);
// shape position and rotation are stored in world-frame
glm::vec3 localPosition = uniformScale * (_jointStates[i].combinedRotation * joint.shapePosition);
glm::vec3 worldPosition = _rotation * (extractTranslation(_jointStates[i].transform) + localPosition) + _translation;
_shapes[i]->setPosition(worldPosition);
glm::quat localRotation = _jointStates[i].combinedRotation * joint.shapeRotation;
glm::quat worldRotation = _rotation * localRotation;
_shapes[i]->setRotation(worldRotation);
}
_shapesAreDirty = false;
}
@ -743,24 +754,56 @@ void Model::renderCollisionProxies(float alpha) {
Application::getInstance()->loadTranslatedViewMatrix(_translation);
updateShapePositions();
float uniformScale = extractUniformScale(_scale);
const int BALL_SUBDIVISIONS = 10;
glm::quat inverseRotation = glm::inverse(_rotation);
for (int i = 0; i < _shapes.size(); i++) {
glPushMatrix();
Shape* shape = _shapes[i];
// shapes are stored in world-frame, so we have to transform into local frame
glm::vec3 position = inverseRotation * (shape->getPosition() - _translation);
glTranslatef(position.x, position.y, position.z);
const glm::quat& rotation = shape->getRotation();
glm::vec3 axis = glm::axis(rotation);
glRotatef(glm::angle(rotation), axis.x, axis.y, axis.z);
glColor4f(0.75f, 0.75f, 0.75f, alpha);
const int BALL_SUBDIVISIONS = 10;
glutSolidSphere(shape->getBoundingRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS);
if (shape->getType() == Shape::SPHERE_SHAPE) {
// shapes are stored in world-frame, so we have to transform into model frame
glm::vec3 position = inverseRotation * (shape->getPosition() - _translation);
glTranslatef(position.x, position.y, position.z);
const glm::quat& rotation = inverseRotation;
glm::vec3 axis = glm::axis(rotation);
glRotatef(glm::angle(rotation), axis.x, axis.y, axis.z);
// draw a grey sphere at shape position
glColor4f(0.75f, 0.75f, 0.75f, alpha);
glutSolidSphere(shape->getBoundingRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS);
} else if (shape->getType() == Shape::CAPSULE_SHAPE) {
CapsuleShape* capsule = static_cast<CapsuleShape*>(shape);
// translate to capsule center
glm::vec3 point = inverseRotation * (capsule->getPosition() - _translation);
// draw a blue sphere at the capsule endpoint
glm::vec3 endPoint;
capsule->getEndPoint(endPoint);
endPoint = inverseRotation * (endPoint - _translation);
glTranslatef(endPoint.x, endPoint.y, endPoint.z);
glColor4f(0.65f, 0.65f, 0.95f, alpha);
glutSolidSphere(0.95f * capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS);
// draw a red sphere at the capsule startpoint
glm::vec3 startPoint;
capsule->getStartPoint(startPoint);
startPoint = inverseRotation * (startPoint - _translation);
glm::vec3 axis = endPoint - startPoint;
glTranslatef(-axis.x, -axis.y, -axis.z);
glColor4f(0.95f, 0.65f, 0.65f, alpha);
glutSolidSphere(0.95f * capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS);
// draw a green cylinder between the two points
glm::vec3 origin(0.f);
glColor4f(0.05f, 0.95f, 0.65f, alpha);
Avatar::renderJointConnectingCone(
origin,
axis,
1.05f * capsule->getRadius(),
1.05f * capsule->getRadius());
}
glPopMatrix();
}
glPopMatrix();