Exemple #1
0
void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
    // compute default joint transforms
    int numStates = _rig->getJointStateCount();
    QVector<glm::mat4> transforms;
    transforms.fill(glm::mat4(), numStates);

    // compute bounding box that encloses all shapes
    Extents totalExtents;
    totalExtents.reset();
    totalExtents.addPoint(glm::vec3(0.0f));
    for (int i = 0; i < numStates; i++) {
        // compute the default transform of this joint
        const JointState& state = _rig->getJointState(i);
        int parentIndex = state.getParentIndex();
        if (parentIndex == -1) {
            transforms[i] = _rig->getJointTransform(i);
        } else {
            glm::quat modifiedRotation = state.getPreRotation() * state.getDefaultRotation() * state.getPostRotation();
            transforms[i] = transforms[parentIndex] * glm::translate(state.getTranslation())
                * state.getPreTransform() * glm::mat4_cast(modifiedRotation) * state.getPostTransform();
        }

        // Each joint contributes a sphere at its position
        glm::vec3 axis(state.getBoneRadius());
        glm::vec3 jointPosition = extractTranslation(transforms[i]);
        totalExtents.addPoint(jointPosition + axis);
        totalExtents.addPoint(jointPosition - axis);
    }

    // compute bounding shape parameters
    // NOTE: we assume that the longest side of totalExtents is the yAxis...
    glm::vec3 diagonal = totalExtents.maximum - totalExtents.minimum;
    // ... and assume the radius is half the RMS of the X and Z sides:
    _boundingCapsuleRadius = 0.5f * sqrtf(0.5f * (diagonal.x * diagonal.x + diagonal.z * diagonal.z));
    _boundingCapsuleHeight = diagonal.y - 2.0f * _boundingCapsuleRadius;

    glm::vec3 rootPosition = _rig->getJointState(geometry.rootJointIndex).getPosition();
    _boundingCapsuleLocalOffset = 0.5f * (totalExtents.maximum + totalExtents.minimum) - rootPosition;
    _boundingRadius = 0.5f * glm::length(diagonal);
}
Exemple #2
0
void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
    // compute default joint transforms
    int numStates = _jointStates.size();
    assert(numStates == _shapes.size());
    QVector<glm::mat4> transforms;
    transforms.fill(glm::mat4(), numStates);

    // compute bounding box that encloses all shapes
    Extents totalExtents;
    totalExtents.reset();
    totalExtents.addPoint(glm::vec3(0.0f));
    for (int i = 0; i < numStates; i++) {
        // compute the default transform of this joint
        JointState& state = _jointStates[i];
        const FBXJoint& joint = state.getFBXJoint();
        int parentIndex = joint.parentIndex;
        if (parentIndex == -1) {
            transforms[i] = _jointStates[i].getTransform();
        } else {
            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;
        }

        // Each joint contributes its point to the bounding box
        glm::vec3 jointPosition = extractTranslation(transforms[i]);
        totalExtents.addPoint(jointPosition);

        Shape* shape = _shapes[i];
        if (!shape) {
            continue;
        }

        // Each joint with a shape contributes to the totalExtents: a box 
        // that contains the sphere centered at the end of the joint with radius of the bone.

        // TODO: skip hand and arm shapes for bounding box calculation
        int type = shape->getType();
        if (type == CAPSULE_SHAPE) {
            // add the two furthest surface points of the capsule
            CapsuleShape* capsule = static_cast<CapsuleShape*>(shape);
            float radius = capsule->getRadius();
            glm::vec3 axis(radius);
            Extents shapeExtents;
            shapeExtents.reset();
            shapeExtents.addPoint(jointPosition + axis);
            shapeExtents.addPoint(jointPosition - axis);
            totalExtents.addExtents(shapeExtents);
        } else if (type == SPHERE_SHAPE) {
            float radius = shape->getBoundingRadius();
            glm::vec3 axis(radius);
            Extents shapeExtents;
            shapeExtents.reset();
            shapeExtents.addPoint(jointPosition + axis);
            shapeExtents.addPoint(jointPosition - axis);
            totalExtents.addExtents(shapeExtents);
        }
    }

    // compute bounding shape parameters
    // NOTE: we assume that the longest side of totalExtents is the yAxis...
    glm::vec3 diagonal = totalExtents.maximum - totalExtents.minimum;
    // ... and assume the radius is half the RMS of the X and Z sides:
    float capsuleRadius = 0.5f * sqrtf(0.5f * (diagonal.x * diagonal.x + diagonal.z * diagonal.z));
    _boundingShape.setRadius(capsuleRadius);
    _boundingShape.setHalfHeight(0.5f * diagonal.y - capsuleRadius);

    glm::vec3 rootPosition = _jointStates[geometry.rootJointIndex].getPosition();
    _boundingShapeLocalOffset = 0.5f * (totalExtents.maximum + totalExtents.minimum) - rootPosition;
    _boundingRadius = 0.5f * glm::length(diagonal);
}
Exemple #3
0
void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
    // compute default joint transforms
    int numStates = _jointStates.size();
    QVector<glm::mat4> transforms;
    transforms.fill(glm::mat4(), numStates);

    QVector<VerletPoint>& ragdollPoints = _ragdoll->getPoints();

    // compute the default transforms and slam the ragdoll positions accordingly
    // (which puts the shapes where we want them)
    for (int i = 0; i < numStates; i++) {
        JointState& state = _jointStates[i];
        const FBXJoint& joint = state.getFBXJoint();
        int parentIndex = joint.parentIndex;
        if (parentIndex == -1) {
            transforms[i] = _jointStates[i].getTransform();
            ragdollPoints[i].initPosition(extractTranslation(transforms[i]));
            continue;
        }
        
        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].initPosition(extractTranslation(transforms[i]));
    }

    // compute bounding box that encloses all shapes
    Extents totalExtents;
    totalExtents.reset();
    totalExtents.addPoint(glm::vec3(0.0f));
    for (int i = 0; i < _shapes.size(); i++) {
        Shape* shape = _shapes[i];
        if (!shape) {
            continue;
        }
        // TODO: skip hand and arm shapes for bounding box calculation
        Extents shapeExtents;
        shapeExtents.reset();
        glm::vec3 localPosition = shape->getTranslation();
        int type = shape->getType();
        if (type == CAPSULE_SHAPE) {
            // add the two furthest surface points of the capsule
            CapsuleShape* capsule = static_cast<CapsuleShape*>(shape);
            glm::vec3 axis;
            capsule->computeNormalizedAxis(axis);
            float radius = capsule->getRadius();
            float halfHeight = capsule->getHalfHeight();
            axis = halfHeight * axis + glm::vec3(radius);

            shapeExtents.addPoint(localPosition + axis);
            shapeExtents.addPoint(localPosition - axis);
            totalExtents.addExtents(shapeExtents);
        } else if (type == SPHERE_SHAPE) {
            float radius = shape->getBoundingRadius();
            glm::vec3 axis = glm::vec3(radius);
            shapeExtents.addPoint(localPosition + axis);
            shapeExtents.addPoint(localPosition - axis);
            totalExtents.addExtents(shapeExtents);
        }
    }

    // compute bounding shape parameters
    // NOTE: we assume that the longest side of totalExtents is the yAxis...
    glm::vec3 diagonal = totalExtents.maximum - totalExtents.minimum;
    // ... and assume the radius is half the RMS of the X and Z sides:
    float capsuleRadius = 0.5f * sqrtf(0.5f * (diagonal.x * diagonal.x + diagonal.z * diagonal.z));
    _boundingShape.setRadius(capsuleRadius);
    _boundingShape.setHalfHeight(0.5f * diagonal.y - capsuleRadius);

    glm::vec3 rootPosition = _jointStates[geometry.rootJointIndex].getPosition();
    _boundingShapeLocalOffset = 0.5f * (totalExtents.maximum + totalExtents.minimum) - rootPosition;
    _boundingRadius = 0.5f * glm::length(diagonal);
}