Ejemplo n.º 1
0
// virtual
void SkeletonModel::renderJointCollisionShapes(float alpha) { 
    if (!_ragdoll) {
        return;
    }
    glPushMatrix();
    Application::getInstance()->loadTranslatedViewMatrix(_translation);
    glm::vec3 simulationTranslation = _ragdoll->getTranslationInSimulationFrame();
    for (int i = 0; i < _shapes.size(); i++) { 
        Shape* shape = _shapes[i];
        if (!shape) { 
            continue;
        } 

        auto geometryCache = DependencyManager::get<GeometryCache>();

        glPushMatrix();
        // shapes are stored in simulation-frame but we want position to be model-relative
        if (shape->getType() == SPHERE_SHAPE) { 
            glm::vec3 position = shape->getTranslation() - simulationTranslation;
            glTranslatef(position.x, position.y, position.z);
            // draw a grey sphere at shape position
            geometryCache->renderSphere(shape->getBoundingRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS, glm::vec4(0.75f, 0.75f, 0.75f, alpha));
        } else if (shape->getType() == CAPSULE_SHAPE) {
            CapsuleShape* capsule = static_cast<CapsuleShape*>(shape);

            // draw a blue sphere at the capsule endpoint                                         
            glm::vec3 endPoint;
            capsule->getEndPoint(endPoint);
            endPoint = endPoint - simulationTranslation;
            glTranslatef(endPoint.x, endPoint.y, endPoint.z);                                     
            geometryCache->renderSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS, glm::vec4(0.6f, 0.6f, 0.8f, alpha));

            // draw a yellow sphere at the capsule startpoint
            glm::vec3 startPoint;
            capsule->getStartPoint(startPoint);
            startPoint = startPoint - simulationTranslation;
            glm::vec3 axis = endPoint - startPoint;
            glTranslatef(-axis.x, -axis.y, -axis.z);
            geometryCache->renderSphere(capsule->getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS, glm::vec4(0.8f, 0.8f, 0.6f, alpha));

            // draw a green cylinder between the two points
            glm::vec3 origin(0.0f);
            Avatar::renderJointConnectingCone( origin, axis, capsule->getRadius(), capsule->getRadius(), glm::vec4(0.6f, 0.8f, 0.6f, alpha));
        }
        glPopMatrix();
    }
    glPopMatrix();
}
Ejemplo n.º 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);
}
Ejemplo n.º 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);
}