Example #1
0
bool
UsdSkelSkeletonQuery::_ComputeSkinningTransforms(VtMatrix4dArray* xforms,
                                                 UsdTimeCode time) const
{
    if (ComputeJointSkelTransforms(xforms, time)) {

        // XXX: Since this is a fairly frequent computation request,
        // skel-space inverse rest transforms are cached on-demand
        // on the definition
        
        VtMatrix4dArray inverseBindXforms;
        if (!_definition->GetJointWorldInverseBindTransforms(
                &inverseBindXforms)) {
            TF_WARN("%s -- Failed fetching bind transforms. The "
                    "'bindTransforms' attribute may be unauthored, "
                    "or may not match the number of joints.",
                    GetSkeleton().GetPrim().GetPath().GetText());
            return false;
        }

        if(xforms->size() == inverseBindXforms.size()) {
            // xforms = inverseBindXforms * xforms
            _PreMultXforms(inverseBindXforms, xforms);
            return true;
        } else {
            TF_WARN("%s -- Size of computed joints transforms [%zu] does not "
                    "match the number of elements in the 'bindTransforms' "
                    "attr [%zu].", GetSkeleton().GetPrim().GetPath().GetText(),
                    xforms->size(), inverseBindXforms.size());
        }
    }
    return false;
}
Example #2
0
static 
bool _GetMayaDictValue(const UsdAttribute& attr, const TfToken& key, T* outVal)
{
    VtValue data = attr.GetCustomDataByKey(_tokens->Maya);
    if (!data.IsEmpty()) {
        if (data.IsHolding<VtDictionary>()) {
            VtValue val;
            if (TfMapLookup(data.UncheckedGet<VtDictionary>(), key, &val)) {
                if (val.IsHolding<T>()) {
                    *outVal = val.UncheckedGet<T>();
                    return true;
                }
                else {
                    TF_WARN("Unexpected type for %s[%s] on <%s>.",
                            _tokens->Maya.GetText(),
                            key.GetText(),
                            attr.GetPath().GetText());
                }
            }
        }
        else {
            TF_WARN("Expected to get %s on <%s> to be a dictionary.",
                    _tokens->Maya.GetText(),
                    attr.GetPath().GetText());
        }
    }
    return false;
}
Example #3
0
void UsdMayaJobExportArgs::AddFilteredTypeName(const MString& typeName)
{
    MNodeClass cls(typeName);
    unsigned int id = cls.typeId().id();
    if (id == 0) {
        TF_WARN("Given excluded node type '%s' does not exist; ignoring",
                typeName.asChar());
        return;
    }
    _filteredTypeIds.insert(id);
    // We also insert all inherited types - only way to query this is through mel,
    // which is slower, but this should be ok, as these queries are only done
    // "up front" when the export starts, not per-node
    MString queryCommand("nodeType -isTypeName -derived ");
    queryCommand += typeName;
    MStringArray inheritedTypes;
    MStatus status = MGlobal::executeCommand(queryCommand, inheritedTypes, false, false);
    if (!status) {
        TF_WARN("Error querying derived types for '%s': %s",
                typeName.asChar(), status.errorString().asChar());
        return;
    }

    for (unsigned int i=0; i < inheritedTypes.length(); ++i) {
        if (inheritedTypes[i].length() == 0) continue;
        id = MNodeClass(inheritedTypes[i]).typeId().id();
        if (id == 0) {
            // Unfortunately, the returned list will often include weird garbage, like
            // "THconstraint" for "constraint", which cannot be converted to a MNodeClass,
            // so just ignore these...
            continue;
        }
        _filteredTypeIds.insert(id);
    }
}
Example #4
0
GlfQGLPlatformDebugContextPrivate::GlfQGLPlatformDebugContextPrivate(
        int majorVersion, int minorVersion,
        bool coreProfile, bool directRendering)
    : _dpy(NULL)
    , _ctx(NULL)
{
    Display *shareDisplay = glXGetCurrentDisplay();
    GLXContext shareContext = glXGetCurrentContext();

    int fbConfigId = 0;
    glXQueryContext(shareDisplay, shareContext, GLX_FBCONFIG_ID, &fbConfigId);
    int screen = 0;
    glXQueryContext(shareDisplay, shareContext, GLX_SCREEN, &screen);

    int configSpec[] = {
        GLX_FBCONFIG_ID, fbConfigId,
        None, 
    };
    GLXFBConfig *configs = NULL;
    int configCount = 0;
    configs = glXChooseFBConfig(shareDisplay, screen, configSpec, &configCount);
    if (not TF_VERIFY(configCount > 0)) {
        return;
    }

    const int profile =
        coreProfile
            ? GLX_CONTEXT_CORE_PROFILE_BIT_ARB
            : GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;

    int attribs[] = {
        GLX_CONTEXT_MAJOR_VERSION_ARB, majorVersion,
        GLX_CONTEXT_MINOR_VERSION_ARB, minorVersion,
        GLX_CONTEXT_PROFILE_MASK_ARB, profile,
        GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
        0,
    };

    // Extension entry points must be resolved at run-time.
    PFNGLXCREATECONTEXTATTRIBSARBPROC createContextAttribs =
        (PFNGLXCREATECONTEXTATTRIBSARBPROC)
            glXGetProcAddressARB((const GLubyte*)"glXCreateContextAttribsARB");

    // Create a GL context with the requested capabilities.
    if (createContextAttribs) {
        _ctx = (*createContextAttribs)(shareDisplay, configs[0],
                                       shareContext, directRendering,
                                       attribs);
    } else {
        TF_WARN("Unable to create GL debug context.");
        XVisualInfo *vis = glXGetVisualFromFBConfig(shareDisplay, configs[0]);
        _ctx = glXCreateContext(shareDisplay, vis,
                                shareContext, directRendering);
    }
    if (not TF_VERIFY(_ctx)) {
        return;
    }

    _dpy = shareDisplay;
}
Example #5
0
GfMatrix4d
UsdGeomConstraintTarget::ComputeInWorldSpace(
    UsdTimeCode time,
    UsdGeomXformCache *xfCache) const
{
    if (not IsDefined()) {
        TF_CODING_ERROR("Invalid constraint target.");
        return GfMatrix4d(1);
    }

    const UsdPrim &modelPrim = GetAttr().GetPrim();

    GfMatrix4d localToWorld(1);
    if (xfCache) {
        xfCache->SetTime(time);
        localToWorld = xfCache->GetLocalToWorldTransform(modelPrim);
    } else {
        UsdGeomXformCache cache;
        cache.SetTime(time);
        localToWorld = cache.GetLocalToWorldTransform(modelPrim);
    }

    GfMatrix4d localConstraintSpace(1.);
    if (not Get(&localConstraintSpace, time)) {
        TF_WARN("Failed to get value of constraint target '%s' at path <%s>.",
                GetIdentifier().GetText(), GetAttr().GetPath().GetText());
        return localConstraintSpace;
    }

    return localConstraintSpace * localToWorld;
}
Example #6
0
/*
 * Make the matrix orthonormal in place using an iterative method.
 * It is potentially slower if the matrix is far from orthonormal (i.e. if
 * the row basis vectors are close to colinear) but in the common case
 * of near-orthonormality it should be just as fast.
 *
 * The translation part is left intact.  If the translation is represented as
 * a homogenous coordinate (i.e. a non-unity lower right corner), it is divided
 * out.
 */
bool
GfMatrix4f::Orthonormalize(bool issueWarning)
{
    // orthogonalize and normalize row vectors
    GfVec3d r0(_mtx[0][0],_mtx[0][1],_mtx[0][2]);
    GfVec3d r1(_mtx[1][0],_mtx[1][1],_mtx[1][2]);
    GfVec3d r2(_mtx[2][0],_mtx[2][1],_mtx[2][2]);
    bool result = GfVec3d::OrthogonalizeBasis(&r0, &r1, &r2, true);
    _mtx[0][0] = r0[0];
    _mtx[0][1] = r0[1];
    _mtx[0][2] = r0[2];
    _mtx[1][0] = r1[0];
    _mtx[1][1] = r1[1];
    _mtx[1][2] = r1[2];
    _mtx[2][0] = r2[0];
    _mtx[2][1] = r2[1];
    _mtx[2][2] = r2[2];

    // divide out any homogeneous coordinate - unless it's zero
    if (_mtx[3][3] != 1.0 && !GfIsClose(_mtx[3][3], 0.0, GF_MIN_VECTOR_LENGTH))
    {
	_mtx[3][0] /= _mtx[3][3];
	_mtx[3][1] /= _mtx[3][3];
	_mtx[3][2] /= _mtx[3][3];
	_mtx[3][3] = 1.0;
    }

    if (!result && issueWarning)
	TF_WARN("OrthogonalizeBasis did not converge, matrix may not be "
                "orthonormal.");

    return result;
}
Example #7
0
GlfTextureHandleRefPtr
GlfTextureRegistry::GetTextureHandle(const TfTokenVector &textures)
{
    if (textures.empty()) {
        TF_WARN("Attempting to register arrayTexture with empty token vector.");
        return GlfTextureHandlePtr();
    }

    const size_t numTextures = textures.size();
    // We register an array texture with the
    // path of the first texture in the array
    TfToken texture = textures[0];
    GlfTextureHandleRefPtr textureHandle;

    _TextureMetadata md(textures);

    // look into exisiting textures
    std::map<TfToken, _TextureMetadata>::iterator it =
        _textureRegistry.find(texture);
    
    if (it != _textureRegistry.end() && it->second.IsMetadataEqual(md)) {
        textureHandle = it->second.GetHandle();
    } else {
        // if not exists, create it
        textureHandle = _CreateTexture(textures, numTextures);
        md.SetHandle(textureHandle);
        _textureRegistry[texture] = md;
    }

    return textureHandle;
}
Example #8
0
File: mesh.cpp Project: mplanck/USD
// For now, this is only used by the mesh op.  If this logic needs to be
// accessed elsewhere, it should move down into usdKatana.
static void 
_CreateFaceSetsFromFaceSetAPI(
        const UsdPrim& prim,
        const PxrUsdKatanaUsdInPrivateData &data,
        FnKat::GeolibCookInterface& interface)
{
    UsdGeomFaceSetAPI faceSet = UsdShadeMaterial::GetMaterialFaceSet(prim);
    bool isPartition = faceSet.GetIsPartition();;
    if (!isPartition) {
        TF_WARN("Found face set on prim <%s> that is not a partition.", 
                prim.GetPath().GetText());
        // continue here?
    }

    const double currentTime = data.GetCurrentTime();

    VtIntArray faceCounts, faceIndices;
    faceSet.GetFaceCounts(&faceCounts, currentTime);
    faceSet.GetFaceIndices(&faceIndices, currentTime);

    SdfPathVector bindingTargets;
    faceSet.GetBindingTargets(&bindingTargets);

    size_t faceSetIdxStart = 0;
    for(size_t faceSetIdx = 0; faceSetIdx < faceCounts.size(); ++faceSetIdx) {
        size_t faceCount = faceCounts[faceSetIdx];

        FnKat::GroupBuilder faceSetAttrs;

        faceSetAttrs.set("type", FnKat::StringAttribute("faceset"));
        faceSetAttrs.set("materialAssign", FnKat::StringAttribute(
            PxrUsdKatanaUtils::ConvertUsdMaterialPathToKatLocation(
                bindingTargets[faceSetIdx], data)));

        FnKat::IntBuilder facesBuilder;
        {
            std::vector<int> faceIndicesVec(faceCount);
            for (size_t faceIndicesIdx = 0; faceIndicesIdx < faceCount; ++faceIndicesIdx)
            {
                faceIndicesVec[faceIndicesIdx] = 
                    faceIndices[faceSetIdxStart + faceIndicesIdx];
            }
            faceSetIdxStart += faceCount;
            facesBuilder.set(faceIndicesVec);
        }
        faceSetAttrs.set("geometry.faces", facesBuilder.build());

        std::string faceSetName = TfStringPrintf("faceset_%zu", faceSetIdx);

        FnKat::GroupBuilder staticSceneCreateAttrs;
        staticSceneCreateAttrs.set("a", faceSetAttrs.build());
        interface.createChild(
            faceSetName,
            "StaticSceneCreate",
            staticSceneCreateAttrs.build());
    }
}
static TfToken HdSt_BasisToShaderKey(const TfToken& basis){
    if (basis == HdTokens->bezier)
        return _tokens->curvesBezier;
    else if (basis == HdTokens->catmullRom)
        return _tokens->curvesCatmullRom;
    else if (basis == HdTokens->bSpline)
        return _tokens->curvesBspline;
    TF_WARN("Unknown basis");
    return _tokens->curvesFallback;
}
Example #10
0
static TfToken 
_GetProxyOverlayMode()
{
    TfToken overlay(TfGetEnvSetting(USDVMP_PROXY_OVERLAY));
    if (overlay != _tokens->ghosted
        and overlay != _tokens->none
        and overlay != _tokens->wireframe)
    {
        TF_WARN("Invalid proxy USDVMP_PROXY_OVERLAY mode: %s\n", overlay.GetText());
        return _tokens->ghosted;
    }
    return overlay;
}
Example #11
0
File: primvar.cpp Project: JT-a/USD
bool 
UsdGeomPrimvar::ComputeFlattened(VtValue *value, UsdTimeCode time) const
{
    VtValue attrVal;
    if (!Get(&attrVal, time)) {
        return false;
    }

    // If the primvar attr value is not an array or if the primvar isn't 
    // indexed, simply return the attribute value.
    if (!attrVal.IsArrayValued() || !IsIndexed()) {
        *value = VtValue::Take(attrVal);
        return true;
    }

    VtIntArray indices;
    if (!GetIndices(&indices, time)) {
        TF_CODING_ERROR("No indices authored for indexed primvar <%s>.", 
                        _attr.GetPath().GetText());
        return false;
    }

    // Handle all known supported array value types.
    bool foundSupportedType =
        _ComputeFlattenedArray<VtVec2fArray>(attrVal, indices, value)       || 
        _ComputeFlattenedArray<VtVec2dArray>(attrVal, indices, value)       || 
        _ComputeFlattenedArray<VtVec2iArray>(attrVal, indices, value)       || 
        _ComputeFlattenedArray<VtVec2hArray>(attrVal, indices, value)       || 
        _ComputeFlattenedArray<VtVec3fArray>(attrVal, indices, value)       || 
        _ComputeFlattenedArray<VtVec3dArray>(attrVal, indices, value)       || 
        _ComputeFlattenedArray<VtVec3iArray>(attrVal, indices, value)       || 
        _ComputeFlattenedArray<VtVec3hArray>(attrVal, indices, value)       || 
        _ComputeFlattenedArray<VtVec4fArray>(attrVal, indices, value)       || 
        _ComputeFlattenedArray<VtVec4dArray>(attrVal, indices, value)       || 
        _ComputeFlattenedArray<VtVec4iArray>(attrVal, indices, value)       || 
        _ComputeFlattenedArray<VtVec4hArray>(attrVal, indices, value)       ||
        _ComputeFlattenedArray<VtMatrix3dArray>(attrVal, indices, value)    || 
        _ComputeFlattenedArray<VtMatrix4dArray>(attrVal, indices, value)    ||
        _ComputeFlattenedArray<VtStringArray>(attrVal, indices, value)      ||
        _ComputeFlattenedArray<VtDoubleArray>(attrVal, indices, value)      ||
        _ComputeFlattenedArray<VtIntArray>(attrVal, indices, value)         ||
        _ComputeFlattenedArray<VtFloatArray>(attrVal, indices, value)       ||
        _ComputeFlattenedArray<VtHalfArray>(attrVal, indices, value);

    if (!foundSupportedType) {
        TF_WARN("Unsupported indexed primvar value type %s.", 
                attrVal.GetTypeName().c_str());
    }

    return !value->IsEmpty();
}
Example #12
0
PXR_NAMESPACE_OPEN_SCOPE


// TODO: We should centralize this logic in a UsdImaging ShaderAdapter.

/*static*/
UsdPrim
UsdImaging_MaterialStrategy::GetTargetedShader(UsdPrim const& materialPrim,
                                        UsdRelationship const& materialRel)
{
    SdfPathVector targets;
    if (!materialRel.GetForwardedTargets(&targets))
        return UsdPrim();

    if (targets.size() != 1) {
        // XXX: This should really be a validation error once USD gets that
        // feature.
        TF_WARN("We expect only one target on relationship %s of prim <%s>, "
                "but got %zu.",
                materialRel.GetName().GetText(),
                materialPrim.GetPath().GetText(),
                targets.size());
        return UsdPrim();
    }

    if (!targets[0].IsPrimPath()) {
        // XXX: This should really be a validation error once USD gets that
        // feature.
        TF_WARN("We expect the target of the relationship %s of prim <%s> "
                "to be a prim, instead it is <%s>.",
                materialRel.GetName().GetText(),
                materialPrim.GetPath().GetText(),
                targets[0].GetText());
        return UsdPrim();
    }

    return materialPrim.GetStage()->GetPrimAtPath(targets[0]);
}
static void
_MatrixToVectorsWithPivotInvariant(
    const GfMatrix4d &m,
    const GfVec3d pivotPosition,
    const GfVec3d pivotOrientation,
    GfVec3d *translation, 
    GfVec3d *rotation, 
    GfVec3d *scale, 
    GfVec3d *scaleOrientation) 
{

    GfMatrix3d pivotOrientMat = _EulerXYZToMatrix3d(pivotOrientation);

    GfMatrix4d pp    = GfMatrix4d(1.0).SetTranslate( pivotPosition);
    GfMatrix4d ppInv = GfMatrix4d(1.0).SetTranslate(-pivotPosition);
    GfMatrix4d po    = GfMatrix4d(1.0).SetRotate(pivotOrientMat);
    GfMatrix4d poInv = GfMatrix4d(1.0).SetRotate(pivotOrientMat.GetInverse());

    GfMatrix4d factorMe = po * pp * m * ppInv;

    GfMatrix4d scaleOrientMat, factoredRotMat, perspMat;

    factorMe.Factor(&scaleOrientMat, scale, &factoredRotMat, 
                    translation, &perspMat);

    GfMatrix4d rotMat = factoredRotMat * poInv;

    if(not rotMat.Orthonormalize(/* issueWarning */ false))
        TF_WARN("Failed to orthonormalize rotMat.");

    _RotMatToRotTriplet(rotMat, rotation);

    if(not scaleOrientMat.Orthonormalize(/* issueWarning */ false))
        TF_WARN("Failed to orthonormalize scaleOrientMat.");

    _RotMatToRotTriplet(scaleOrientMat, scaleOrientation);
}
bool
HdExtCompPrimvarBufferSource::Resolve()
{
    bool sourceValid = _source->IsValid();
    if (sourceValid) {
        if (!_source->IsResolved()) {
            return false;
        }
    }

    if (!_TryLock()) return false;

    if (!sourceValid || _source->HasResolveError()) {
        _SetResolveError();
        return true;
    }

    HdVtBufferSource output(_primvarName,
                            _source->GetOutputByIndex(_sourceOutputIdx));

    // Validate output type and count matches what is expected.
    if (output.GetTupleType() != _tupleType) {
        TF_WARN("Output type mismatch on %s. ", _primvarName.GetText());
        _SetResolveError();
        return true;
    }
    if (output.GetNumElements() != _source->GetNumElements()) {
        TF_WARN("Output elements mismatch on %s. ", _primvarName.GetText());
        _SetResolveError();
        return true;
    }

    _rawDataPtr = output.GetData();

    _SetResolved();
    return true;
}
Example #15
0
bool
UsdSkelSkeletonQuery::ComputeJointRestRelativeTransforms(
    VtMatrix4dArray* xforms, UsdTimeCode time) const
{
    TRACE_FUNCTION();

    if (!xforms) {
        TF_CODING_ERROR("'xforms' pointer is null.");
        return false;
    }

    if(TF_VERIFY(IsValid(), "invalid skeleton query.")) {
        if (_HasMappableAnim()) {
            // jointLocalXf = restRelativeXf * restXf
            // restRelativeXf = jointLocalXf * inv(restXf)

            // Pull inverse rest transforms first
            // They are cached on the definition.
            VtMatrix4dArray invRestXforms;
            if (_definition->GetJointLocalInverseRestTransforms(
                    &invRestXforms)) {

                VtMatrix4dArray localXforms;
                if (_ComputeJointLocalTransforms(
                        &localXforms, time, /*atRest*/ false)) {
                    if (TF_VERIFY(localXforms.size() == invRestXforms.size())) {
                        
                        xforms->resize(localXforms.size());

                        _MultTransforms(localXforms.cdata(),
                                        invRestXforms.cdata(),
                                        xforms->data(), xforms->size());
                        return true;
                    }
                }
            } else {
                TF_WARN("%s -- Failed computing rest-relative transforms: "
                        "the 'restTransforms' of the Skeleton are either unset, "
                        "or do not have a matching number of joints.",
                        GetSkeleton().GetPrim().GetPath().GetText());
            }
        } else {
            // No bound animation, so rest relative transforms are identity.
            xforms->assign(GetTopology().GetNumJoints(), GfMatrix4d(1));
            return true;
        }
    }
    return false;
}
HdBasisCurvesTopology::HdBasisCurvesTopology(const TfToken &curveType,
                                             const TfToken &curveBasis,
                                             const TfToken &curveWrap,
                                             const VtIntArray &curveVertexCounts,
                                             const VtIntArray &curveIndices)
  : HdTopology()
  , _curveType(curveType)
  , _curveBasis(curveBasis)
  , _curveWrap(curveWrap)
  , _curveVertexCounts(curveVertexCounts)
  , _curveIndices(curveIndices)
{
    if (_curveType != HdTokens->linear && _curveType != HdTokens->cubic){
        TF_WARN("Curve type must be 'linear' or 'cubic'.  Got: '%s'", _curveType.GetText());
        _curveType = HdTokens->linear;
        _curveBasis = TfToken();
    }
    if (curveBasis == HdTokens->linear && curveType == HdTokens->cubic){
        TF_WARN("Basis 'linear' passed in to 'cubic' curveType.  Converting 'curveType' to 'linear'.");
        _curveType = HdTokens->linear;
        _curveBasis = TfToken();
    }
    HD_PERF_COUNTER_INCR(HdPerfTokens->basisCurvesTopology);
}
Example #17
0
void
PxOsdMeshTopology::SetHoleIndices(VtIntArray const &holeIndices)
{
    if (TfDebug::IsEnabled(0)) {
        // make sure faceIndices is given in ascending order.
        int nFaceIndices = holeIndices.size();
        for (int i = 1; i < nFaceIndices; ++i) {
            if (holeIndices[i] <= holeIndices[i-1]) {
                // XXX: would be better to print the prim name.
                TF_WARN("hole face indices are not in ascending order.");
                return;
            }
        }
    }
    _holeIndices = holeIndices;
}
Example #18
0
bool
TfUnsetenv(const std::string & name)
{
#ifdef PXR_PYTHON_SUPPORT_ENABLED
    if (TfPyIsInitialized()) {
        return TfPyUnsetenv(name);
    }
#endif // PXR_PYTHON_SUPPORT_ENABLED

    if (ArchRemoveEnv(name.c_str())) {
        return true;
    }

    TF_WARN("Error unsetting '%s': %s", name.c_str(), ArchStrerror().c_str());
    return false;
}
/* static */
void
UsdMayaUndoHelperCommand::ExecuteWithUndo(const UndoableFunction& func)
{
    int cmdExists = 0;
    MGlobal::executeCommand("exists usdUndoHelperCmd", cmdExists);
    if (!cmdExists) {
        TF_WARN("usdUndoHelperCmd is unavailable; "
                "function will run without undo support");
        MDGModifier modifier;
        func(modifier);
        return;
    }

    // Run function through command if it is available to get undo support!
    _dgModifierFunc = &func;
    MGlobal::executeCommand("usdUndoHelperCmd", false, true);
}
PXR_NAMESPACE_USING_DIRECTIVE

// Here we emit some warnings on the same line, so they 
// will get coalesced, and others on different lines, so they wont
// We expect to get 4 results when coalesced, 6 uncoalesced
static void 
EmitWarnings() {
    TF_WARN("aaaaaaaaaaaaaa"); TF_WARN("bbbbbbbbbbbbbb"); 
    TF_WARN("cccccccccccccc");               
    TF_WARN("dddddddddddddd");               
    TF_WARN("eeeeeeeeeeeeee"); TF_WARN("ffffffffffffff");
}
Example #21
0
File: prim.cpp Project: lvxejay/USD
SdfPrimSpecHandle
UsdPrim::GetPrimDefinition() const
{
    const TfToken &typeName = GetTypeName();
    SdfPrimSpecHandle definition;

    if (!typeName.IsEmpty()) {
        // Look up definition from prim type name.
        definition = UsdSchemaRegistry::GetPrimDefinition(typeName);

        if (!definition) {
            // Issue a diagnostic for unknown prim types.
            TF_WARN("No definition for prim type '%s', <%s>",
                    typeName.GetText(), GetPath().GetText());
        }
    }
    return definition;
}
Example #22
0
PXR_NAMESPACE_OPEN_SCOPE

bool
TfSetenv(const std::string & name, const std::string & value)
{
#ifdef PXR_PYTHON_SUPPORT_ENABLED
    if (TfPyIsInitialized()) {
        return TfPySetenv(name, value);
    }
#endif // PXR_PYTHON_SUPPORT_ENABLED

    if (ArchSetEnv(name.c_str(), value.c_str(), /* overwrite */ true)) {
        return true;
    }

    TF_WARN("Error setting '%s': %s", name.c_str(), ArchStrerror().c_str());
    return false;
}
Example #23
0
static 
void _SetMayaDictValue(const UsdAttribute& attr, const TfToken& flagName, const T& val)
{
    VtValue data = attr.GetCustomDataByKey(_tokens->Maya);

    VtDictionary newDict;
    if (!data.IsEmpty()) {
        if (data.IsHolding<VtDictionary>()) {
            newDict = data.UncheckedGet<VtDictionary>();
        }
        else {
            TF_WARN("Expected to get %s on <%s> to be a dictionary.",
                    _tokens->Maya.GetText(),
                    attr.GetPath().GetText());
            return;
        }
    }
    newDict[flagName] = VtValue(val);
    attr.SetCustomDataByKey(_tokens->Maya, VtValue(newDict));
}
Example #24
0
/* Make the matrix orthonormal in place using an iterative method.
 * It is potentially slower if the matrix is far from orthonormal (i.e. if
 * the row basis vectors are close to colinear) but in the common case
 * of near-orthonormality it should be just as fast. */
bool
GfMatrix3d::Orthonormalize(bool issueWarning)
{
    // orthogonalize and normalize row vectors
    GfVec3d r0(_mtx[0][0],_mtx[0][1],_mtx[0][2]);
    GfVec3d r1(_mtx[1][0],_mtx[1][1],_mtx[1][2]);
    GfVec3d r2(_mtx[2][0],_mtx[2][1],_mtx[2][2]);
    bool result = GfVec3d::OrthogonalizeBasis(&r0, &r1, &r2, true);
    _mtx[0][0] = r0[0];
    _mtx[0][1] = r0[1];
    _mtx[0][2] = r0[2];
    _mtx[1][0] = r1[0];
    _mtx[1][1] = r1[1];
    _mtx[1][2] = r1[2];
    _mtx[2][0] = r2[0];
    _mtx[2][1] = r2[1];
    _mtx[2][2] = r2[2];
    if (!result && issueWarning)
	TF_WARN("OrthogonalizeBasis did not converge, matrix may not be "
                "orthonormal.");
    return result;
}
Example #25
0
/// Extracts a token at \p key from \p userArgs.
/// If the token value is not either \p defaultToken or one of the
/// \p otherTokens, then returns \p defaultToken instead.
static TfToken
_Token(
    const VtDictionary& userArgs,
    const TfToken& key,
    const TfToken& defaultToken,
    const std::vector<TfToken>& otherTokens)
{
    const TfToken tok(_String(userArgs, key));
    for (const TfToken& allowedTok : otherTokens) {
        if (tok == allowedTok) {
            return tok;
        }
    }

    // Empty token will silently be promoted to default value.
    // Warning for non-empty tokens that don't match.
    if (tok != defaultToken && !tok.IsEmpty()) {
        TF_WARN("Value '%s' is not allowed for flag '%s'; using fallback '%s' "
                "instead",
                tok.GetText(), key.GetText(), defaultToken.GetText());
    }
    return defaultToken;
}
Example #26
0
bool
UsdSkelSkeletonQuery::_ComputeJointLocalTransforms(VtMatrix4dArray* xforms,
                                                   UsdTimeCode time,
                                                   bool atRest) const
{
    if(atRest) {
        return _definition->GetJointLocalRestTransforms(xforms);
    }

    if(_animToSkelMapper.IsSparse()) {
        // Animation does not override all values;
        // Need to first fill in bind transforms.
        if (!_definition->GetJointLocalRestTransforms(xforms)) {
            TF_WARN("%s -- Failed computing local space transforms: "
                    "the the animation source (<%s>) is sparse, but the "
                    "'restTransforms' of the Skeleton are either unset, "
                    "or do not match the number of joints.",
                    GetSkeleton().GetPrim().GetPath().GetText(),
                    GetAnimQuery().GetPrim().GetPath().GetText());
            return false;
        }
    }

    VtMatrix4dArray animXforms;
    if(_animQuery.ComputeJointLocalTransforms(&animXforms, time)) {
        return _animToSkelMapper.RemapTransforms(animXforms, xforms);
    } else {
        // Failed to compute anim xforms.
        // Fall back to our rest transforms.
        // These will have already been initialized above,
        // unless we have a non-sparse mapping.
        if (!_animToSkelMapper.IsSparse()) {
            return _definition->GetJointLocalRestTransforms(xforms);
        }
    }
    return true;
}
/* static */
bool
UsdMayaTranslatorMesh::_AssignColorSetPrimvarToMesh(
        const UsdGeomMesh& primSchema,
        const UsdGeomPrimvar& primvar,
        MFnMesh& meshFn)
{
    const TfToken& primvarName = primvar.GetPrimvarName();
    const SdfValueTypeName& typeName = primvar.GetTypeName();

    MString colorSetName(primvarName.GetText());

    // If the primvar is displayOpacity and it is a FloatArray, check if
    // displayColor is authored. If not, we'll import this 'displayOpacity'
    // primvar as a 'displayColor' color set. This supports cases where the
    // user created a single channel value for displayColor.
    // Note that if BOTH displayColor and displayOpacity are authored, they will
    // be imported as separate color sets. We do not attempt to combine them
    // into a single color set.
    if (primvarName == UsdMayaMeshColorSetTokens->DisplayOpacityColorSetName &&
            typeName == SdfValueTypeNames->FloatArray) {
        if (!UsdMayaRoundTripUtil::IsAttributeUserAuthored(primSchema.GetDisplayColorPrimvar())) {
            colorSetName = UsdMayaMeshColorSetTokens->DisplayColorColorSetName.GetText();
        }
    }

    // We'll need to convert colors from linear to display if this color set is
    // for display colors.
    const bool isDisplayColor =
        (colorSetName == UsdMayaMeshColorSetTokens->DisplayColorColorSetName.GetText());

    // Get the raw data before applying any indexing. We'll only populate one
    // of these arrays based on the primvar's typeName, and we'll also set the
    // color representation so we know which array to use later.
    VtFloatArray alphaArray;
    VtVec3fArray rgbArray;
    VtVec4fArray rgbaArray;
    MFnMesh::MColorRepresentation colorRep;
    size_t numValues = 0;

    MStatus status = MS::kSuccess;

    if (typeName == SdfValueTypeNames->FloatArray) {
        colorRep = MFnMesh::kAlpha;
        if (!primvar.Get(&alphaArray) || alphaArray.empty()) {
            status = MS::kFailure;
        } else {
            numValues = alphaArray.size();
        }
    } else if (typeName == SdfValueTypeNames->Float3Array ||
               typeName == SdfValueTypeNames->Color3fArray) {
        colorRep = MFnMesh::kRGB;
        if (!primvar.Get(&rgbArray) || rgbArray.empty()) {
            status = MS::kFailure;
        } else {
            numValues = rgbArray.size();
        }
    } else if (typeName == SdfValueTypeNames->Float4Array ||
               typeName == SdfValueTypeNames->Color4fArray) {
        colorRep = MFnMesh::kRGBA;
        if (!primvar.Get(&rgbaArray) || rgbaArray.empty()) {
            status = MS::kFailure;
        } else {
            numValues = rgbaArray.size();
        }
    } else {
        TF_WARN("Unsupported color set primvar type '%s' for primvar '%s' on "
                "mesh: %s",
                typeName.GetAsToken().GetText(),
                primvarName.GetText(),
                primvar.GetAttr().GetPrimPath().GetText());
        return false;
    }

    if (status != MS::kSuccess || numValues == 0) {
        TF_WARN("Could not read color set values from primvar '%s' on mesh: %s",
                primvarName.GetText(),
                primvar.GetAttr().GetPrimPath().GetText());
        return false;
    }

    VtIntArray assignmentIndices;
    int unauthoredValuesIndex = -1;
    if (primvar.GetIndices(&assignmentIndices)) {
        // The primvar IS indexed, so the indices array is what determines the
        // number of color values.
        numValues = assignmentIndices.size();
        unauthoredValuesIndex = primvar.GetUnauthoredValuesIndex();
    }

    // Go through the color data and translate the values into MColors in the
    // colorArray, taking into consideration that indexed data may have been
    // authored sparsely. If the assignmentIndices array is empty then the data
    // is NOT indexed.
    // Note that with indexed data, the data is added to the arrays in ascending
    // component ID order according to the primvar's interpolation (ascending
    // face ID for uniform interpolation, ascending vertex ID for vertex
    // interpolation, etc.). This ordering may be different from the way the
    // values are ordered in the primvar. Because of this, we recycle the
    // assignmentIndices array as we go to store the new mapping from component
    // index to color index.
    MColorArray colorArray;
    for (size_t i = 0; i < numValues; ++i) {
        int valueIndex = i;

        if (i < assignmentIndices.size()) {
            // The data is indexed, so consult the indices array for the
            // correct index into the data.
            valueIndex = assignmentIndices[i];

            if (valueIndex == unauthoredValuesIndex) {
                // This component is unauthored, so just update the
                // mapping in assignmentIndices and then skip the value.
                // We don't actually use the value at the unassigned index.
                assignmentIndices[i] = -1;
                continue;
            }

            // We'll be appending a new value, so the current length of the
            // array gives us the new value's index.
            assignmentIndices[i] = colorArray.length();
        }

        GfVec4f colorValue(1.0);

        switch(colorRep) {
            case MFnMesh::kAlpha:
                colorValue[3] = alphaArray[valueIndex];
                break;
            case MFnMesh::kRGB:
                colorValue[0] = rgbArray[valueIndex][0];
                colorValue[1] = rgbArray[valueIndex][1];
                colorValue[2] = rgbArray[valueIndex][2];
                break;
            case MFnMesh::kRGBA:
                colorValue[0] = rgbaArray[valueIndex][0];
                colorValue[1] = rgbaArray[valueIndex][1];
                colorValue[2] = rgbaArray[valueIndex][2];
                colorValue[3] = rgbaArray[valueIndex][3];
                break;
            default:
                break;
        }

        if (isDisplayColor) {
            colorValue = UsdMayaColorSpace::ConvertLinearToMaya(colorValue);
        }

        MColor mColor(colorValue[0], colorValue[1], colorValue[2], colorValue[3]);
        colorArray.append(mColor);
    }

    // colorArray now stores all of the values and any unassigned components
    // have had their indices set to -1, so update the unauthored values index.
    unauthoredValuesIndex = -1;

    const bool clamped = UsdMayaRoundTripUtil::IsPrimvarClamped(primvar);

    status = meshFn.createColorSet(colorSetName, nullptr, clamped, colorRep);
    if (status != MS::kSuccess) {
        TF_WARN("Unable to create color set '%s' for mesh: %s",
                colorSetName.asChar(),
                meshFn.fullPathName().asChar());
        return false;
    }

    // Create colors on the mesh from the values we collected out of the
    // primvar. We'll assign mesh components to these values below.
    status = meshFn.setColors(colorArray, &colorSetName, colorRep);
    if (status != MS::kSuccess) {
        TF_WARN("Unable to set color data on color set '%s' for mesh: %s",
                colorSetName.asChar(),
                meshFn.fullPathName().asChar());
        return false;
    }

    const TfToken& interpolation = primvar.GetInterpolation();

    // Build an array of value assignments for each face vertex in the mesh.
    // Any assignments left as -1 will not be assigned a value.
    MIntArray colorIds = _GetMayaFaceVertexAssignmentIds(meshFn,
                                                         interpolation,
                                                         assignmentIndices,
                                                         unauthoredValuesIndex);

    status = meshFn.assignColors(colorIds, &colorSetName);
    if (status != MS::kSuccess) {
        TF_WARN("Could not assign color values to color set '%s' on mesh: %s",
                colorSetName.asChar(),
                meshFn.fullPathName().asChar());
        return false;
    }

    return true;
}
/* static */
bool
UsdMayaTranslatorMesh::_AssignUVSetPrimvarToMesh(
        const UsdGeomPrimvar& primvar,
        MFnMesh& meshFn)
{
    const TfToken& primvarName = primvar.GetPrimvarName();

    // Get the raw data before applying any indexing.
    VtVec2fArray uvValues;
    if (!primvar.Get(&uvValues) || uvValues.empty()) {
        TF_WARN("Could not read UV values from primvar '%s' on mesh: %s",
                primvarName.GetText(),
                primvar.GetAttr().GetPrimPath().GetText());
        return false;
    }

    // This is the number of UV values assuming the primvar is NOT indexed.
    VtIntArray assignmentIndices;
    if (primvar.GetIndices(&assignmentIndices)) {
        // The primvar IS indexed, so the indices array is what determines the
        // number of UV values.
        int unauthoredValuesIndex = primvar.GetUnauthoredValuesIndex();

        // Replace any index equal to unauthoredValuesIndex with -1.
        if (unauthoredValuesIndex != -1) {
            for (int& index : assignmentIndices) {
                if (index == unauthoredValuesIndex) {
                    index = -1;
                }
            }
        }

        // Furthermore, if unauthoredValuesIndex is valid for uvValues, then
        // remove it from uvValues and shift the indices (we don't want to
        // import the unauthored value into Maya, where it has no meaning).
        if (unauthoredValuesIndex >= 0 &&
                static_cast<size_t>(unauthoredValuesIndex) < uvValues.size()) {
            // This moves [unauthoredValuesIndex + 1, end) to
            // [unauthoredValuesIndex, end - 1), erasing the
            // unauthoredValuesIndex.
            std::move(
                    uvValues.begin() + unauthoredValuesIndex + 1,
                    uvValues.end(),
                    uvValues.begin() + unauthoredValuesIndex);
            uvValues.pop_back();

            for (int& index : assignmentIndices) {
                if (index > unauthoredValuesIndex) {
                    index = index - 1;
                }
            }
        }
    }

    // Go through the UV data and add the U and V values to separate
    // MFloatArrays.
    MFloatArray uCoords;
    MFloatArray vCoords;
    for (const GfVec2f& v : uvValues) {
        uCoords.append(v[0]);
        vCoords.append(v[1]);
    }

    MStatus status;
    MString uvSetName(primvarName.GetText());
    if (primvarName == UsdUtilsGetPrimaryUVSetName()) {
        // We assume that the primary USD UV set maps to Maya's default 'map1'
        // set which always exists, so we shouldn't try to create it.
        uvSetName = "map1";
    } else {
        status = meshFn.createUVSet(uvSetName);
        if (status != MS::kSuccess) {
            TF_WARN("Unable to create UV set '%s' for mesh: %s",
                    uvSetName.asChar(),
                    meshFn.fullPathName().asChar());
            return false;
        }
    }

    // The following two lines should have no effect on user-visible state but
    // prevent a Maya crash in MFnMesh.setUVs after creating a crease set.
    // XXX this workaround is needed pending a fix by Autodesk.
    MString currentSet = meshFn.currentUVSetName();
    meshFn.setCurrentUVSetName(currentSet);

    // Create UVs on the mesh from the values we collected out of the primvar.
    // We'll assign mesh components to these values below.
    status = meshFn.setUVs(uCoords, vCoords, &uvSetName);
    if (status != MS::kSuccess) {
        TF_WARN("Unable to set UV data on UV set '%s' for mesh: %s",
                uvSetName.asChar(),
                meshFn.fullPathName().asChar());
        return false;
    }

    const TfToken& interpolation = primvar.GetInterpolation();

    // Build an array of value assignments for each face vertex in the mesh.
    // Any assignments left as -1 will not be assigned a value.
    MIntArray uvIds = _GetMayaFaceVertexAssignmentIds(meshFn,
                                                      interpolation,
                                                      assignmentIndices,
                                                      -1);

    MIntArray vertexCounts;
    MIntArray vertexList;
    status = meshFn.getVertices(vertexCounts, vertexList);
    if (status != MS::kSuccess) {
        TF_WARN("Could not get vertex counts for UV set '%s' on mesh: %s",
                uvSetName.asChar(),
                meshFn.fullPathName().asChar());
        return false;
    }

    status = meshFn.assignUVs(vertexCounts, uvIds, &uvSetName);
    if (status != MS::kSuccess) {
        TF_WARN("Could not assign UV values to UV set '%s' on mesh: %s",
                uvSetName.asChar(),
                meshFn.fullPathName().asChar());
        return false;
    }

    return true;
}
Example #29
0
static void
_AddClipsFromNode(const PcpPrimIndex& primIndex, Usd_ClipCache::Clips* clips)
{
    Usd_ResolvedClipInfo clipInfo;
    auto node = Usd_ResolveClipInfo(primIndex, &clipInfo);

    // If we haven't found all of the required clip metadata we can just 
    // bail out. Note that clipTimes and clipManifestAssetPath are *not* 
    // required.
    if (!clipInfo.clipAssetPaths 
        || !clipInfo.clipPrimPath 
        || !clipInfo.clipActive) {
        return;
    }

    // The clip manifest is currently optional but can greatly improve
    // performance if specified. For debugging performance problems,
    // issue a message indicating if one hasn't been specified.
    if (!clipInfo.clipManifestAssetPath) {
        TF_DEBUG(USD_CLIPS).Msg(
            "No clip manifest specified for prim <%s>. " 
            "Performance may be improved if a manifest is specified.",
            primIndex.GetPath().GetString().c_str());
    }

    // XXX: Possibly want a better way to inform consumers of the error
    //      message..
    std::string error;
    if (!_ValidateClipFields(
            *clipInfo.clipAssetPaths, *clipInfo.clipPrimPath, 
            *clipInfo.clipActive, &error)) {

        TF_WARN(
            "Invalid clips specified for prim <%s> in LayerStack %s: %s",
            node.GetPath().GetString().c_str(),
            TfStringify(node.GetLayerStack()).c_str(),
            error.c_str());
        return;
    }

    // If a clip manifest has been specified, create a clip for it.
    if (clipInfo.clipManifestAssetPath) {
        const Usd_ClipRefPtr clip(new Usd_Clip(
            /* clipSourceNode       = */ node,
            /* clipSourceLayerIndex = */ 
                clipInfo.indexOfLayerWhereAssetPathsFound,
            /* clipAssetPath        = */ *clipInfo.clipManifestAssetPath,
            /* clipPrimPath         = */ SdfPath(*clipInfo.clipPrimPath),
            /* clipStartTime        = */ Usd_ClipTimesEarliest,
            /* clipEndTime          = */ Usd_ClipTimesLatest,
            /* clipTimes            = */ Usd_Clip::TimeMappings()));
        clips->manifestClip = clip;
    }

    // Generate a mapping of startTime -> clip entry. This allows us to
    // quickly determine the (startTime, endTime) for a given clip.
    typedef std::map<double, Usd_ClipEntry> _TimeToClipMap;
    _TimeToClipMap startTimeToClip;

    for (const auto& startFrameAndClipIndex : *clipInfo.clipActive) {
        const double startFrame = startFrameAndClipIndex[0];
        const int clipIndex = (int)(startFrameAndClipIndex[1]);
        const SdfAssetPath& assetPath = (*clipInfo.clipAssetPaths)[clipIndex];

        Usd_ClipEntry entry;
        entry.startTime = startFrame;
        entry.clipAssetPath = assetPath;
        entry.clipPrimPath = SdfPath(*clipInfo.clipPrimPath);

        // Validation should have caused us to bail out if there were any
        // conflicting clip activations set.
        TF_VERIFY(startTimeToClip.insert(
                std::make_pair(entry.startTime, entry)).second);
    }

    // Build up the final vector of clips.
    const _TimeToClipMap::const_iterator itBegin = startTimeToClip.begin();
    const _TimeToClipMap::const_iterator itEnd = startTimeToClip.end();

    _TimeToClipMap::const_iterator it = startTimeToClip.begin();
    while (it != itEnd) {
        const Usd_ClipEntry clipEntry = it->second;

        const Usd_Clip::ExternalTime clipStartTime = 
            (it == itBegin ? Usd_ClipTimesEarliest : it->first);
        ++it;
        const Usd_Clip::ExternalTime clipEndTime = 
            (it == itEnd ? Usd_ClipTimesLatest : it->first);

        // Generate the clip time mapping that applies to this clip.
        Usd_Clip::TimeMappings timeMapping;
        if (clipInfo.clipTimes) {
            for (const auto& clipTime : *clipInfo.clipTimes) {
                const Usd_Clip::ExternalTime extTime = clipTime[0];
                const Usd_Clip::InternalTime intTime = clipTime[1];
                
                if (clipStartTime <= extTime && extTime < clipEndTime) {
                    timeMapping.push_back(
                        Usd_Clip::TimeMapping(extTime, intTime));
                }
            }
        }

        const Usd_ClipRefPtr clip(new Usd_Clip(
            /* clipSourceNode = */ node,
            /* clipSourceLayerIndex = */ 
                clipInfo.indexOfLayerWhereAssetPathsFound,
            /* clipAssetPath = */ clipEntry.clipAssetPath,
            /* clipPrimPath = */ clipEntry.clipPrimPath,
            /* clipStartTime = */ clipStartTime,
            /* clipEndTime = */ clipEndTime,
            /* clipTimes = */ timeMapping));

        clips->valueClips.push_back(clip);
    }

    clips->sourceNode = node;
    clips->sourceLayerIndex = clipInfo.indexOfLayerWhereAssetPathsFound;    
}
Example #30
0
bool
Hd_TriangleIndexBuilderComputation::Resolve()
{
    if (not _TryLock()) return false;

    HD_TRACE_FUNCTION();

    // generate triangle index buffer

    int const * numVertsPtr = _topology->GetFaceVertexCounts().cdata();
    int const * vertsPtr = _topology->GetFaceVertexIndices().cdata();
    int const * holeFacesPtr = _topology->GetHoleIndices().cdata();
    int numFaces = _topology->GetFaceVertexCounts().size();
    int numVertIndices = _topology->GetFaceVertexIndices().size();
    int numTris = 0;
    int numHoleFaces = _topology->GetHoleIndices().size();
    bool invalidTopology = false;
    int holeIndex = 0;
    for (int i=0; i<numFaces; ++i) {
        int nv = numVertsPtr[i]-2;
        if (nv < 1) {
            // skip degenerated face
            invalidTopology = true;
        } else if (holeIndex < numHoleFaces and holeFacesPtr[holeIndex] == i) {
            // skip hole face
            ++holeIndex;
        } else {
            numTris += nv;
        }
    }
    if (invalidTopology) {
        TF_WARN("degenerated face found [%s]", _id.GetText());
        invalidTopology = false;
    }

    VtVec3iArray trianglesFaceVertexIndices(numTris);
    VtIntArray primitiveParam(numTris);
    bool flip = (_topology->GetOrientation() != HdTokens->rightHanded);

    // reset holeIndex
    holeIndex = 0;

    for (int i=0,tv=0,v=0; i<numFaces; ++i) {
        int nv = numVertsPtr[i];
        if (nv < 3) {
            // Skip degenerate faces.
        } else if (holeIndex < numHoleFaces and holeFacesPtr[holeIndex] == i) {
            // Skip hole faces.
            ++holeIndex;
        } else {
            // edgeFlag is used for inner-line removal of non-triangle
            // faces on wireframe shading.
            //
            //          0__                0  0   0__
            //        _/|\ \_            _/.  ..   . \_
            //      _/  | \  \_   ->   _/  .  . .   .  \_
            //     /  A |C \ B \_     /  A .  .C .   . B \_
            //    1-----2---3----4   1-----2  1---2   1----2
            //
            //  Type   EdgeFlag    Draw
            //    -       0        show all edges
            //    A       1        hide [2-0]
            //    B       2        hide [0-1]
            //    C       3        hide [0-1] and [2-0]
            //
            int edgeFlag = 0;
            for (int j=0; j < nv-2; ++j) {
                if (nv > 3) {
                    if (j == 0) edgeFlag = flip ? 2 : 1;
                    else if (j == nv-3) edgeFlag = flip ? 1 : 2;
                    else edgeFlag = 3;
                }

                if (not _FanTriangulate(
                        trianglesFaceVertexIndices[tv],
                        vertsPtr, v, j, numVertIndices, flip)) {
                    invalidTopology = true;
                }

                // note that ptex indexing isn't available along with
                // triangulation.
                int coarseFaceParam =
                    HdMeshTopology::EncodeCoarseFaceParam(i, edgeFlag);
                primitiveParam[tv] = coarseFaceParam;
                ++tv;
            }
        }
        // When the face is degenerate and nv > 0, we need to increment the v
        // pointer to walk past the degenerate verts.
        v += nv;
    }
    if (invalidTopology) {
        TF_WARN("numVerts and verts are incosistent [%s]",
                _id.GetText());
    }

    _SetResult(HdBufferSourceSharedPtr(
                   new HdVtBufferSource(
                       HdTokens->indices,
                       VtValue(trianglesFaceVertexIndices))));

    _primitiveParam.reset(new HdVtBufferSource(
                              HdTokens->primitiveParam,
                              VtValue(primitiveParam)));

    _SetResolved();
    return true;
}