mirror of
https://github.com/overte-org/overte.git
synced 2025-08-05 17:37:22 +02:00
Use capsules for some joints and render them.
This commit is contained in:
parent
1a8c10e132
commit
4ef2067421
3 changed files with 75 additions and 27 deletions
|
@ -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
|
// 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) {
|
for (int i = 0; i < geometry.joints.size(); ++i) {
|
||||||
FBXJoint& joint = geometry.joints[i];
|
FBXJoint& joint = geometry.joints[i];
|
||||||
JointShapeInfo& jointShapeInfo = jointShapeInfos[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
|
// AND its boneRadius is not too close to zero
|
||||||
bool collideLikeCapsule = jointShapeInfo.numProjectedVertices > 0
|
bool collideLikeCapsule = jointShapeInfo.numProjectedVertices > 0
|
||||||
&& glm::length(jointShapeInfo.boneBegin) > EPSILON;
|
&& glm::length(jointShapeInfo.boneBegin) > EPSILON;
|
||||||
|
|
||||||
if (collideLikeCapsule) {
|
if (collideLikeCapsule) {
|
||||||
joint.shapeRotation = rotationBetween(yAxis, jointShapeInfo.boneBegin);
|
joint.shapeRotation = rotationBetween(defaultCapsuleAxis, jointShapeInfo.boneBegin);
|
||||||
joint.shapePosition = 0.5f * jointShapeInfo.boneBegin;
|
joint.shapePosition = 0.5f * jointShapeInfo.boneBegin;
|
||||||
//joint.shapePosition = glm::vec3(0.f);
|
//joint.shapePosition = glm::vec3(0.f);
|
||||||
joint.shapeType = Shape::CAPSULE_SHAPE;
|
joint.shapeType = Shape::CAPSULE_SHAPE;
|
||||||
|
|
|
@ -26,10 +26,17 @@ extern const char* FACESHIFT_BLENDSHAPES[];
|
||||||
|
|
||||||
class Extents {
|
class Extents {
|
||||||
public:
|
public:
|
||||||
//Extents() : minimum(FLT_MAX), maximum(-FLT_MAX) {}
|
/// set minimum and maximum to FLT_MAX and -FLT_MAX respectively
|
||||||
void reset();
|
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);
|
void addPoint(const glm::vec3& point);
|
||||||
|
|
||||||
|
/// \param point
|
||||||
|
/// \return true if point is within current limits
|
||||||
bool containsPoint(const glm::vec3& point) const;
|
bool containsPoint(const glm::vec3& point) const;
|
||||||
|
|
||||||
glm::vec3 minimum;
|
glm::vec3 minimum;
|
||||||
glm::vec3 maximum;
|
glm::vec3 maximum;
|
||||||
};
|
};
|
||||||
|
@ -73,11 +80,9 @@ public:
|
||||||
glm::quat inverseDefaultRotation;
|
glm::quat inverseDefaultRotation;
|
||||||
glm::quat inverseBindRotation;
|
glm::quat inverseBindRotation;
|
||||||
glm::mat4 bindTransform;
|
glm::mat4 bindTransform;
|
||||||
// TODO: add some comments to these data members
|
QString name; // temp field for debugging
|
||||||
// Trying to provide enough info so that the proper shape can be generated in Model
|
glm::vec3 shapePosition; // in joint frame
|
||||||
QString name;
|
glm::quat shapeRotation; // in joint frame
|
||||||
glm::vec3 shapePosition; // in joint frame (where boneEnd = origin)
|
|
||||||
glm::quat shapeRotation;
|
|
||||||
int shapeType;
|
int shapeType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -142,8 +142,15 @@ void Model::createCollisionShapes() {
|
||||||
glm::vec3 position = _rotation * (extractTranslation(_jointStates[i].transform) + uniformScale * meshCenter) + _translation;
|
glm::vec3 position = _rotation * (extractTranslation(_jointStates[i].transform) + uniformScale * meshCenter) + _translation;
|
||||||
|
|
||||||
float radius = uniformScale * joint.boneRadius;
|
float radius = uniformScale * joint.boneRadius;
|
||||||
SphereShape* shape = new SphereShape(radius, position);
|
if (joint.shapeType == Shape::CAPSULE_SHAPE) {
|
||||||
_shapes.push_back(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()) {
|
if (_shapesAreDirty && _shapes.size() == _jointStates.size()) {
|
||||||
for (int i = 0; i < _jointStates.size(); i++) {
|
for (int i = 0; i < _jointStates.size(); i++) {
|
||||||
const FBXJoint& joint = geometry.joints[i];
|
const FBXJoint& joint = geometry.joints[i];
|
||||||
// shape positions are stored in world-frame
|
|
||||||
glm::vec3 meshCenter = _jointStates[i].combinedRotation * joint.shapePosition;
|
// shape position and rotation are stored in world-frame
|
||||||
_shapes[i]->setPosition(_rotation * (extractTranslation(_jointStates[i].transform) + uniformScale * meshCenter) + _translation);
|
glm::vec3 localPosition = uniformScale * (_jointStates[i].combinedRotation * joint.shapePosition);
|
||||||
_shapes[i]->setRotation(_jointStates[i].combinedRotation);
|
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;
|
_shapesAreDirty = false;
|
||||||
}
|
}
|
||||||
|
@ -743,24 +754,56 @@ void Model::renderCollisionProxies(float alpha) {
|
||||||
Application::getInstance()->loadTranslatedViewMatrix(_translation);
|
Application::getInstance()->loadTranslatedViewMatrix(_translation);
|
||||||
updateShapePositions();
|
updateShapePositions();
|
||||||
float uniformScale = extractUniformScale(_scale);
|
float uniformScale = extractUniformScale(_scale);
|
||||||
|
const int BALL_SUBDIVISIONS = 10;
|
||||||
glm::quat inverseRotation = glm::inverse(_rotation);
|
glm::quat inverseRotation = glm::inverse(_rotation);
|
||||||
for (int i = 0; i < _shapes.size(); i++) {
|
for (int i = 0; i < _shapes.size(); i++) {
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
|
||||||
Shape* shape = _shapes[i];
|
Shape* shape = _shapes[i];
|
||||||
|
|
||||||
// shapes are stored in world-frame, so we have to transform into local frame
|
if (shape->getType() == Shape::SPHERE_SHAPE) {
|
||||||
glm::vec3 position = inverseRotation * (shape->getPosition() - _translation);
|
// shapes are stored in world-frame, so we have to transform into model frame
|
||||||
glTranslatef(position.x, position.y, position.z);
|
glm::vec3 position = inverseRotation * (shape->getPosition() - _translation);
|
||||||
|
glTranslatef(position.x, position.y, position.z);
|
||||||
const glm::quat& rotation = shape->getRotation();
|
const glm::quat& rotation = inverseRotation;
|
||||||
glm::vec3 axis = glm::axis(rotation);
|
glm::vec3 axis = glm::axis(rotation);
|
||||||
glRotatef(glm::angle(rotation), axis.x, axis.y, axis.z);
|
glRotatef(glm::angle(rotation), axis.x, axis.y, axis.z);
|
||||||
|
|
||||||
glColor4f(0.75f, 0.75f, 0.75f, alpha);
|
// draw a grey sphere at shape position
|
||||||
const int BALL_SUBDIVISIONS = 10;
|
glColor4f(0.75f, 0.75f, 0.75f, alpha);
|
||||||
glutSolidSphere(shape->getBoundingRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS);
|
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();
|
||||||
}
|
}
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
Loading…
Reference in a new issue