コード例 #1
0
ファイル: frustum.cpp プロジェクト: JT-a/USD
bool
GfFrustum::Intersects(const GfBBox3d &bbox) const
{
    if (bbox.GetBox().IsEmpty())
        return false;
    
    // Recalculate frustum planes if necessary
    _CalculateFrustumPlanes();

    // Get the bbox in its local space and the matrix that converts
    // world space to that local space.
    const GfRange3d  &localBBox    = bbox.GetRange();
    const GfMatrix4d &worldToLocal = bbox.GetInverseMatrix();

    // Test the bbox against each of the frustum planes, transforming
    // the plane by the inverse of the matrix to bring it into the
    // bbox's local space.
    for (size_t i = 0; i < _planes.size(); i++) {

        GfPlane localPlane = _planes[i];
        localPlane.Transform(worldToLocal);

        if (! localPlane.IntersectsPositiveHalfSpace(localBBox))
            return false;
    }

    return true;
}
コード例 #2
0
ファイル: frustum.cpp プロジェクト: JT-a/USD
bool
GfFrustum::IntersectsViewVolume(const GfBBox3d &bbox,
                                const GfMatrix4d &viewProjMat)
{
    // This implementation is a standard technique employed in frustum
    // culling during rendering.  It correctly culls the box even from
    // view volumes that are not representable by a GfFrustum because of
    // skewed near/far planes, such as the ones produced by
    // presto shadowmap cameras.
    //
    // Its principle of operation:  If all 8 points of
    // the box, when transformed into clip coordinates,
    // are on one side or the other of each dimension's
    // clipping interval, then the entire
    // box volume must lie outside the view volume.

    // Compute the 8 points of the bbox in
    // bbox local space.
    GfVec4d points[8];
    const GfVec3d &localMin = bbox.GetRange().GetMin();
    const GfVec3d &localMax = bbox.GetRange().GetMax();
    points[0] = GfVec4d(localMin[0], localMin[1], localMin[2], 1);
    points[1] = GfVec4d(localMin[0], localMin[1], localMax[2], 1);
    points[2] = GfVec4d(localMin[0], localMax[1], localMin[2], 1);
    points[3] = GfVec4d(localMin[0], localMax[1], localMax[2], 1);
    points[4] = GfVec4d(localMax[0], localMin[1], localMin[2], 1);
    points[5] = GfVec4d(localMax[0], localMin[1], localMax[2], 1);
    points[6] = GfVec4d(localMax[0], localMax[1], localMin[2], 1);
    points[7] = GfVec4d(localMax[0], localMax[1], localMax[2], 1);

    // Transform bbox local space points into clip space
    for (int i = 0; i < 8; ++i) {
        points[i] = points[i] * bbox.GetMatrix() * viewProjMat;
    }

    // clipFlags is a 6-bit field with one bit per +/- per x,y,z,
    // or one per frustum plane.  If the points overlap the
    // clip volume in any axis, then clipFlags will be 0x3f (0b111111).
    int clipFlags = 0;
    for (int i = 0; i < 8; ++i) {
        GfVec4d clipPos = points[i];

        // flag is used as a 6-bit shift register, as we append
        // results of plane-side testing.  OR-ing all the flags
        // combines all the records of what plane-side the points
        // have been on.
        int flag = 0;
        for (int j = 0; j < 3; ++j) {
            // We use +/-clipPos[3] as the interval bound instead of 
            // 1,-1 because these coordinates are not normalized.
            flag = (flag << 1) | (clipPos[j] <  clipPos[3]);
            flag = (flag << 1) | (clipPos[j] > -clipPos[3]);
        }
        clipFlags |= flag;
    }

    return clipFlags == 0x3f;
}
コード例 #3
0
ファイル: boundsCache.cpp プロジェクト: JT-a/USD
bool 
GusdBoundsCache::_ComputeBound(
    const UsdPrim &prim,
    UsdTimeCode time,
    const TfTokenVector &includedPurposes,
    ComputeFunc boundFunc,
    UT_BoundingBox &bounds )
{
    if( !prim.IsValid() )
        return false;

    TfToken stageId( prim.GetStage()->GetRootLayer()->GetRealPath() );

    MapType::accessor accessor;
    if( !m_map.find( accessor, Key( stageId, includedPurposes ))) {
        m_map.insert( accessor, Key( stageId, includedPurposes ) );
        accessor->second = new Item( time, includedPurposes );
    }
    std::lock_guard<std::mutex> lock(accessor->second->lock);
    UsdGeomBBoxCache& cache = accessor->second->bboxCache;

    cache.SetTime( time );

    // boundFunc is either ComputeWorldBound or ComputeLocalBound
    GfBBox3d primBBox = (cache.*boundFunc)(prim);

    if( !primBBox.GetRange().IsEmpty() ) 
    {
        const GfRange3d rng = primBBox.ComputeAlignedRange();

        bounds = 
            UT_BoundingBox( 
                rng.GetMin()[0],
                rng.GetMin()[1],
                rng.GetMin()[2],
                rng.GetMax()[0],
                rng.GetMax()[1],
                rng.GetMax()[2]);
        return true;
    }

    return false;
}