Beispiel #1
0
Datei: ray.cpp Projekt: JT-a/USD
bool
GfRay::Intersect(const GfRange3d &box,
		 double *enterDistance, double *exitDistance) const
{
    if (box.IsEmpty())
	return false;

    // Compute the intersection distance of all 6 planes of the
    // box. Save the largest near-plane intersection and the smallest
    // far-plane intersection.
    double maxNearest = -DBL_MAX, minFarthest = DBL_MAX;
    for (size_t i = 0; i < 3; i++) {

        // Skip dimensions almost parallel to the ray.
        double d = GetDirection()[i];
        if (GfAbs(d) < GF_MIN_VECTOR_LENGTH) {
            // ray is parallel to this set of planes.
            // If origin is not between them, no intersection.
            if (GetStartPoint()[i] < box.GetMin()[i] ||
                GetStartPoint()[i] > box.GetMax()[i]) {
                return false;
            } else {
                continue;
            }
        }

        d = 1.0 / d;
        double t1 = d * (box.GetMin()[i] - GetStartPoint()[i]);
        double t2 = d * (box.GetMax()[i] - GetStartPoint()[i]);

        // Make sure t1 is the nearer one
        if (t1 > t2) {
            double tmp = t1;
            t1 = t2;
            t2 = tmp;
        }

        // Update the min and max
        if (t1 > maxNearest)
            maxNearest = t1;
        if (t2 < minFarthest)
            minFarthest = t2;
    }

    // If the largest near-plane intersection is after the smallest
    // far-plane intersection, the ray's line misses the box. Also
    // check if both intersections are completely outside the near/far
    // bounds.
    if (maxNearest  >  minFarthest ||
        minFarthest < 0.0)
        return false;
        
    if (enterDistance)
	*enterDistance = maxNearest;
    if (exitDistance)
        *exitDistance = minFarthest;
    return true;
}
Beispiel #2
0
bool
UsdGeomPointBased::ComputeExtent(const VtVec3fArray& points, 
    VtVec3fArray* extent)  
{
    // Create Sized Extent
    extent->resize(2);

    // Calculate bounds
    GfRange3d bbox;
    TF_FOR_ALL(pointsItr, points) {
        bbox.UnionWith(GfVec3f(*pointsItr));
    }
Beispiel #3
0
VtVec3fArray
UsdGeomModelAPI::ComputeExtentsHint(
        UsdGeomBBoxCache& bboxCache) const
{
    static const TfTokenVector &purposeTokens =
        UsdGeomImageable::GetOrderedPurposeTokens();

    VtVec3fArray extents(purposeTokens.size() * 2);
    size_t lastNonEmptyBbox = std::numeric_limits<size_t>::max();

    // We should be able execute this loop in parallel since the
    // bounding box computation can be multi-threaded. However, most 
    // conversion processes are run on the farm and are limited to one
    // CPU, so there may not be a huge benefit from doing this. Also, 
    // we expect purpose 'default' to be the most common purpose value 
    // and in some cases the only purpose value. Computing bounds for 
    // the rest of the purpose values should be very fast.
    for(size_t bboxType = purposeTokens.size(); bboxType-- != 0; ) {

        // Set the gprim purpose that we are interested in computing the 
        // bbox for. This doesn't cause the cache to be blown.
        bboxCache.SetIncludedPurposes(
            std::vector<TfToken>(1, purposeTokens[bboxType]));

        GfBBox3d bbox = bboxCache.
            ComputeUntransformedBound(GetPrim());

        const GfRange3d range = bbox.ComputeAlignedBox();

        if (!range.IsEmpty() && lastNonEmptyBbox == std::numeric_limits<size_t>::max())
            lastNonEmptyBbox = bboxType;
        
        const GfVec3d &min = range.GetMin();
        const GfVec3d &max = range.GetMax();

        size_t index = bboxType * 2;
        extents[index] = GfVec3f(min[0], min[1], min[2]);
        extents[index + 1] = GfVec3f(max[0], max[1], max[2]);
    }

    // If all the extents are empty. Author a single empty range.
    if (lastNonEmptyBbox == std::numeric_limits<size_t>::max())
        lastNonEmptyBbox = 0;

    // Shrink the array to only include non-empty bounds. 
    // If all the bounds are empty, we still need to author one empty 
    // bound.
    extents.resize(2 * (lastNonEmptyBbox + 1));
    return extents;
}
Beispiel #4
0
bool
GfPlane::IntersectsPositiveHalfSpace(const GfRange3d &box) const
{
    if (box.IsEmpty())
	return false;
    
    // Test each vertex of the box against the positive half
    // space. Since the box is aligned with the coordinate axes, we
    // can test for a quick accept/reject at each stage.

// This macro tests one corner using the given inequality operators.
#define _GF_CORNER_TEST(X, Y, Z, XOP, YOP, ZOP)                               \
    if (X + Y + Z >= _distance)                                               \
        return true;                                                          \
    else if (_normal[0] XOP 0.0 && _normal[1] YOP 0.0 && _normal[2] ZOP 0.0)  \
        return false

    // The sum of these values is GfDot(box.GetMin(), _normal)
    double xmin = _normal[0] * box.GetMin()[0];
    double ymin = _normal[1] * box.GetMin()[1];
    double zmin = _normal[2] * box.GetMin()[2];

    // We can do the all-min corner test right now.
    _GF_CORNER_TEST(xmin, ymin, zmin, <=, <=, <=);

    // The sum of these values is GfDot(box.GetMax(), _normal)
    double xmax = _normal[0] * box.GetMax()[0];
    double ymax = _normal[1] * box.GetMax()[1];
    double zmax = _normal[2] * box.GetMax()[2];

    // Do the other 7 corner tests.
    _GF_CORNER_TEST(xmax, ymax, zmax, >=, >=, >=);
    _GF_CORNER_TEST(xmin, ymin, zmax, <=, <=, >=);
    _GF_CORNER_TEST(xmin, ymax, zmin, <=, >=, <=);
    _GF_CORNER_TEST(xmin, ymax, zmax, <=, >=, >=);
    _GF_CORNER_TEST(xmax, ymin, zmin, >=, <=, <=);
    _GF_CORNER_TEST(xmax, ymin, zmax, >=, <=, >=);
    _GF_CORNER_TEST(xmax, ymax, zmin, >=, >=, <=);

    // CODE_COVERAGE_OFF - We should never get here, but just in case...
    return false;
    // CODE_COVERAGE_ON

#undef _GF_CORNER_TEST
}
Beispiel #5
0
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;
}
Beispiel #6
0
bool
UsdGeomCylinder::ComputeExtent(double height, double radius,
    const TfToken& axis, const GfMatrix4d& transform, VtVec3fArray* extent)
{
    // Create Sized Extent
    extent->resize(2);

    GfVec3f max;
    if (!_ComputeExtentMax(height, radius, axis, &max)) {
        return false;
    }

    GfBBox3d bbox = GfBBox3d(GfRange3d(-max, max), transform);
    GfRange3d range = bbox.ComputeAlignedRange();
    (*extent)[0] = GfVec3f(range.GetMin());
    (*extent)[1] = GfVec3f(range.GetMax());

    return true;
}
Beispiel #7
0
bool
UsdGeomPointInstancer::ComputeExtentAtTime(
    VtVec3fArray* extent,
    const UsdTimeCode time,
    const UsdTimeCode baseTime) const
{
    if (!extent) {
        TF_WARN("%s -- null container passed to ComputeExtentAtTime()",
                GetPrim().GetPath().GetText());
        return false;
    }

    VtIntArray protoIndices;
    if (!GetProtoIndicesAttr().Get(&protoIndices, time)) {
        TF_WARN("%s -- no prototype indices",
                GetPrim().GetPath().GetText());
        return false;
    }

    const std::vector<bool> mask = ComputeMaskAtTime(time);
    if (!mask.empty() && mask.size() != protoIndices.size()) {
        TF_WARN("%s -- mask.size() [%zu] != protoIndices.size() [%zu]",
                GetPrim().GetPath().GetText(),
                mask.size(),
                protoIndices.size());
        return false;
    }

    const UsdRelationship prototypes = GetPrototypesRel();
    SdfPathVector protoPaths;
    if (!prototypes.GetTargets(&protoPaths) || protoPaths.empty()) {
        TF_WARN("%s -- no prototypes",
                GetPrim().GetPath().GetText());
        return false;
    }

    // verify that all the protoIndices are in bounds.
    TF_FOR_ALL(iter, protoIndices) {
        const int protoIndex = *iter;
        if (protoIndex < 0 || 
            static_cast<size_t>(protoIndex) >= protoPaths.size()) {
            TF_WARN("%s -- invalid prototype index: %d. Should be in [0, %zu)",
                    GetPrim().GetPath().GetText(),
                    protoIndex,
                    protoPaths.size());
            return false;
        }
    }

    // Note that we do NOT apply any masking when computing the instance
    // transforms. This is so that for a particular instance we can determine
    // both its transform and its prototype. Otherwise, the instanceTransforms
    // array would have masked instances culled out and we would lose the
    // mapping to the prototypes.
    // Masked instances will be culled before being applied to the extent below.
    VtMatrix4dArray instanceTransforms;
    if (!ComputeInstanceTransformsAtTime(&instanceTransforms,
                                         time,
                                         baseTime,
                                         IncludeProtoXform,
                                         IgnoreMask)) {
        TF_WARN("%s -- could not compute instance transforms",
                GetPrim().GetPath().GetText());
        return false;
    }

    UsdStageWeakPtr stage = GetPrim().GetStage();
    const TfTokenVector purposes {
        UsdGeomTokens->default_,
        UsdGeomTokens->proxy,
        UsdGeomTokens->render
    };
    UsdGeomBBoxCache bboxCache(time, purposes);
    bboxCache.SetTime(time);

    GfRange3d extentRange;

    for (size_t instanceId = 0; instanceId < protoIndices.size(); ++instanceId) {
        if (!mask.empty() && !mask[instanceId]) {
            continue;
        }

        const int protoIndex = protoIndices[instanceId];
        const SdfPath& protoPath = protoPaths[protoIndex];
        const UsdPrim& protoPrim = stage->GetPrimAtPath(protoPath);

        // Get the prototype bounding box.
        GfBBox3d thisBounds = bboxCache.ComputeUntransformedBound(protoPrim);

        // Apply the instance transform.
        thisBounds.Transform(instanceTransforms[instanceId]);
        extentRange.UnionWith(thisBounds.ComputeAlignedRange());
    }

    const GfVec3d extentMin = extentRange.GetMin();
    const GfVec3d extentMax = extentRange.GetMax();

    *extent = VtVec3fArray(2);
    (*extent)[0] = GfVec3f(extentMin[0], extentMin[1], extentMin[2]);
    (*extent)[1] = GfVec3f(extentMax[0], extentMax[1], extentMax[2]);

    return true;
}
void
My_TestGLDrawing::InitTest()
{
    std::cout << "My_TestGLDrawing::InitTest()\n";
    _stage = UsdStage::Open(GetStageFilePath());
    SdfPathVector excludedPaths;

    if (UsdImagingGLEngine::IsHydraEnabled()) {
        std::cout << "Using HD Renderer.\n";
        _engine.reset(new UsdImagingGLEngine(
            _stage->GetPseudoRoot().GetPath(), excludedPaths));
        if (!_GetRenderer().IsEmpty()) {
            if (!_engine->SetRendererPlugin(_GetRenderer())) {
                std::cerr << "Couldn't set renderer plugin: " <<
                    _GetRenderer().GetText() << std::endl;
                exit(-1);
            } else {
                std::cout << "Renderer plugin: " << _GetRenderer().GetText()
                    << std::endl;
            }
        }
    } else{
        std::cout << "Using Reference Renderer.\n"; 
        _engine.reset(
            new UsdImagingGLEngine(_stage->GetPseudoRoot().GetPath(), 
                    excludedPaths));
    }

    std::cout << glGetString(GL_VENDOR) << "\n";
    std::cout << glGetString(GL_RENDERER) << "\n";
    std::cout << glGetString(GL_VERSION) << "\n";

    if (_ShouldFrameAll()) {
        TfTokenVector purposes;
        purposes.push_back(UsdGeomTokens->default_);
        purposes.push_back(UsdGeomTokens->proxy);

        // Extent hints are sometimes authored as an optimization to avoid
        // computing bounds, they are particularly useful for some tests where
        // there is no bound on the first frame.
        bool useExtentHints = true;
        UsdGeomBBoxCache bboxCache(UsdTimeCode::Default(), purposes, useExtentHints);

        GfBBox3d bbox = bboxCache.ComputeWorldBound(_stage->GetPseudoRoot());
        GfRange3d world = bbox.ComputeAlignedRange();

        GfVec3d worldCenter = (world.GetMin() + world.GetMax()) / 2.0;
        double worldSize = world.GetSize().GetLength();

        std::cerr << "worldCenter: " << worldCenter << "\n";
        std::cerr << "worldSize: " << worldSize << "\n";
        if (UsdGeomGetStageUpAxis(_stage) == UsdGeomTokens->z) {
            // transpose y and z centering translation
            _translate[0] = -worldCenter[0];
            _translate[1] = -worldCenter[2];
            _translate[2] = -worldCenter[1] - worldSize;
        } else {
            _translate[0] = -worldCenter[0];
            _translate[1] = -worldCenter[1];
            _translate[2] = -worldCenter[2] - worldSize;
        }
    } else {
        _translate[0] = GetTranslate()[0];
        _translate[1] = GetTranslate()[1];
        _translate[2] = GetTranslate()[2];
    }

    if(IsEnabledTestLighting()) {
        if(UsdImagingGLEngine::IsHydraEnabled()) {
            // set same parameter as GlfSimpleLightingContext::SetStateFromOpenGL
            // OpenGL defaults
            _lightingContext = GlfSimpleLightingContext::New();
            GlfSimpleLight light;
            if (IsEnabledCameraLight()) {
                light.SetPosition(GfVec4f(_translate[0], _translate[2], _translate[1], 0));
            } else {
                light.SetPosition(GfVec4f(0, -.5, .5, 0));
            }
            light.SetDiffuse(GfVec4f(1,1,1,1));
            light.SetAmbient(GfVec4f(0,0,0,1));
            light.SetSpecular(GfVec4f(1,1,1,1));
            GlfSimpleLightVector lights;
            lights.push_back(light);
            _lightingContext->SetLights(lights);

            GlfSimpleMaterial material;
            material.SetAmbient(GfVec4f(0.2, 0.2, 0.2, 1.0));
            material.SetDiffuse(GfVec4f(0.8, 0.8, 0.8, 1.0));
            material.SetSpecular(GfVec4f(0,0,0,1));
            material.SetShininess(0.0001f);
            _lightingContext->SetMaterial(material);
            _lightingContext->SetSceneAmbient(GfVec4f(0.2,0.2,0.2,1.0));
        } else {
            glEnable(GL_LIGHTING);
            glEnable(GL_LIGHT0);
            if (IsEnabledCameraLight()) {
                float position[4] = {_translate[0], _translate[2], _translate[1], 0};
                glLightfv(GL_LIGHT0, GL_POSITION, position);
            } else {
                float position[4] = {0,-.5,.5,0};
                glLightfv(GL_LIGHT0, GL_POSITION, position);
            }
        }
    }
}