Beispiel #1
0
GT_PrimitiveHandle GusdPrimWrapper::
defineForRead( const GusdUSD_StageProxyHandle&  stage, 
               const UsdGeomImageable&          sourcePrim, 
               const UsdTimeCode&               time,
               const GusdPurposeSet&            purposes )
{
    GT_PrimitiveHandle gtUsdPrimHandle;

    GusdUSD_ImageableHolder::ScopedLock lock;

    GusdUSD_ImageableHolder holder( sourcePrim, stage->GetLock() );
    lock.Acquire( holder, /*write*/false);

    UsdGeomImageable sourceImageable = *lock;

    // Find the function registered for the source prim's type
    // to define the prim from read and call that function.
    if(sourcePrim) {
        USDTypeToDefineFuncMap::const_iterator mapIt
            = s_usdTypeToFuncMap.find(sourceImageable.GetPrim().GetTypeName());
        if(mapIt != s_usdTypeToFuncMap.end()) {
            gtUsdPrimHandle = mapIt->second(stage,sourcePrim,time,purposes);
        }
    }
    return gtUsdPrimHandle;
}
Beispiel #2
0
bool
MayaPrimWriter::writePrimAttrs(const MDagPath &dagT, const UsdTimeCode &usdTime, UsdGeomImageable &primSchema) 
{
    MStatus status;
    MFnDependencyNode depFn(getDagPath().node());
    MFnDependencyNode depFn2(dagT.node()); // optionally also scan a shape's transform if merging transforms

    if (getArgs().exportVisibility) {
        bool isVisible  = true;   // if BOTH shape or xform is animated, then visible
        bool isAnimated = false;  // if either shape or xform is animated, then animated

        PxrUsdMayaUtil::getPlugValue(depFn, "visibility", &isVisible, &isAnimated);

        if ( dagT.isValid() ) {
            bool isVis, isAnim;
            if (PxrUsdMayaUtil::getPlugValue(depFn2, "visibility", &isVis, &isAnim)){
                isVisible = isVisible and isVis;
                isAnimated = isAnimated or isAnim;
            }
        }

        TfToken const &visibilityTok = (isVisible ? UsdGeomTokens->inherited : 
                                        UsdGeomTokens->invisible);
        if (usdTime.IsDefault() != isAnimated ) {
            if (usdTime.IsDefault())
                primSchema.CreateVisibilityAttr(VtValue(visibilityTok), true);
            else
                primSchema.CreateVisibilityAttr().Set(visibilityTok, usdTime);
        }
    }

    UsdPrim usdPrim = primSchema.GetPrim();

    // There is no Gprim abstraction in this module, so process the few
    // gprim attrs here.
    UsdGeomGprim gprim = UsdGeomGprim(usdPrim);
    if (gprim and usdTime.IsDefault()){

        PxrUsdMayaPrimWriterContext* unused = NULL;
        PxrUsdMayaTranslatorGprim::Write(
                getDagPath().node(),
                gprim,
                unused);

    }

    _writeUsdInfo(dagT, usdTime, usdPrim);
    
    // Write user-tagged export attributes. Write attributes on the transform
    // first, and then attributes on the shape node. This means that attribute
    // name collisions will always be handled by taking the shape node's value
    // if we're merging transforms and shapes.
    if (dagT.isValid() and !(dagT == getDagPath())) {
        PxrUsdMayaWriteUtil::WriteUserExportedAttributes(dagT, usdPrim, usdTime);
    }
    PxrUsdMayaWriteUtil::WriteUserExportedAttributes(getDagPath(), usdPrim, usdTime);

    return true;
}
Beispiel #3
0
/* static */
UsdGeomPrimvar PxrUsdMayaWriteUtil::GetOrCreatePrimvar(
        const MPlug& attrPlug,
        UsdGeomImageable& imageable,
        const std::string& primvarName,
        const TfToken& interpolation,
        const int elementSize,
        const bool custom,
        const bool translateMayaDoubleToUsdSinglePrecision)
{
    UsdGeomPrimvar primvar;

    if (!imageable) {
        return primvar;
    }

    MObject attrObj(attrPlug.attribute());

    TfToken primvarNameToken(primvarName);
    if (primvarNameToken.IsEmpty()) {
        MGlobal::displayError(
            TfStringPrintf("Invalid primvar name '%s' for Maya plug '%s'",
                           primvarName.c_str(),
                           attrPlug.name().asChar()).c_str());
        return primvar;
    }

    // See if the primvar already exists. If so, return it.
    primvar = imageable.GetPrimvar(primvarNameToken);
    if (primvar) {
        return primvar;
    }

    const SdfValueTypeName& typeName =
        PxrUsdMayaWriteUtil::GetUsdTypeName(attrPlug,
                                            translateMayaDoubleToUsdSinglePrecision);
    if (typeName) {
        primvar = imageable.CreatePrimvar(primvarNameToken,
                                          typeName,
                                          interpolation,
                                          elementSize,
                                          custom);
    }

    return primvar;
}
Beispiel #4
0
GT_PrimitiveHandle GusdPrimWrapper::
defineForRead( const UsdGeomImageable&  sourcePrim, 
               UsdTimeCode              time,
               GusdPurposeSet           purposes )
{
    GT_PrimitiveHandle gtUsdPrimHandle;

    // Find the function registered for the source prim's type
    // to define the prim from read and call that function.
    if(sourcePrim) {
        const TfToken& typeName = sourcePrim.GetPrim().GetTypeName();
        USDTypeToDefineFuncMap::const_accessor caccessor;
        if(s_usdTypeToFuncMap.find(caccessor, typeName)) {
            gtUsdPrimHandle = caccessor->second(sourcePrim,time,purposes);
        }
        else {
            // If no function is registered for the prim's type, try to
            // find a supported base type.
            const TfType& baseType = TfType::Find<UsdSchemaBase>();
            const TfType& derivedType
                = baseType.FindDerivedByName(typeName.GetText());

            vector<TfType> ancestorTypes;
            derivedType.GetAllAncestorTypes(&ancestorTypes);

            for(size_t i=1; i<ancestorTypes.size(); ++i) {
                const TfType& ancestorType = ancestorTypes[i];
                vector<string> typeAliases = baseType.GetAliases(ancestorType);
                typeAliases.push_back(ancestorType.GetTypeName());

                for(auto const& typeAlias : typeAliases) {
                    if(s_usdTypeToFuncMap.find(caccessor, TfToken(typeAlias))) {
                        gtUsdPrimHandle = caccessor->second(sourcePrim,time,purposes);
                        USDTypeToDefineFuncMap::accessor accessor;
                        s_usdTypeToFuncMap.insert(accessor, typeName);
                        accessor->second = caccessor->second;
                        TF_WARN("Type \"%s\" not registered, using base type \"%s\".",
                                typeName.GetText(), typeAlias.c_str());
                        break;
                    }
                }
                if(gtUsdPrimHandle) break;
            }

            if(!gtUsdPrimHandle) {
                // If we couldn't find a function for the prim's type or any 
                // of it's base types, register a function which returns an
                // empty prim handle.
                registerPrimDefinitionFuncForRead(typeName, _nullPrimReadFunc);
                TF_WARN("Couldn't read unsupported USD prim type \"%s\".",
                        typeName.GetText());
            }
        }
    }
    return gtUsdPrimHandle;
}
Beispiel #5
0
GT_PrimitiveHandle GusdXformWrapper::
defineForRead(
        const UsdGeomImageable& sourcePrim, 
        UsdTimeCode             time,
        GusdPurposeSet          purposes )
{
    return new GusdXformWrapper( 
                    UsdGeomXform( sourcePrim.GetPrim() ),
                    time,
                    purposes );
}
Beispiel #6
0
GT_PrimitiveHandle GusdScopeWrapper::
defineForRead(
        const GusdUSD_StageProxyHandle& stage,
        const UsdGeomImageable&         sourcePrim, 
        const UsdTimeCode&              time,
        const GusdPurposeSet&           purposes )
{
    return new GusdScopeWrapper( 
                    stage, 
                    UsdGeomScope( sourcePrim.GetPrim() ),
                    time,
                    purposes );
}
Beispiel #7
0
void
GusdPrimWrapper::loadPrimvars( 
    UsdTimeCode               time,
    const GT_RefineParms*     rparms,
    int                       minUniform,
    int                       minPoint,
    int                       minVertex,
    const string&             primPath,
    GT_AttributeListHandle*   vertex,
    GT_AttributeListHandle*   point,
    GT_AttributeListHandle*   primitive,
    GT_AttributeListHandle*   constant,
    const GT_DataArrayHandle& remapIndicies ) const
{
    // Primvars will be loaded if they match a provided pattern.
    // By default, set the pattern to match only "Cd". Then write
    // over this pattern if there is one provided in rparms.
    const char* Cd = "Cd";
    UT_String primvarPattern(Cd);

    if (rparms) {
        rparms->import("usd:primvarPattern", primvarPattern);
    }

    std::vector<UsdGeomPrimvar> authoredPrimvars;
    bool hasCdPrimvar = false;

    {
        UsdGeomImageable prim = getUsdPrimForRead();

        UsdGeomPrimvar colorPrimvar = prim.GetPrimvar(GusdTokens->Cd);
        if (colorPrimvar && colorPrimvar.GetAttr().HasAuthoredValueOpinion()) {
            hasCdPrimvar = true;
        }

        // It's common for "Cd" to be the only primvar to load.
        // In this case, avoid getting all other authored primvars.
        if (primvarPattern == Cd) {
            if (hasCdPrimvar) {
                authoredPrimvars.push_back(colorPrimvar);
            } else {
                // There is no authored "Cd" primvar.
                // Try to find "displayColor" instead.
                colorPrimvar = prim.GetPrimvar(UsdGeomTokens->primvarsDisplayColor);
                if (colorPrimvar &&
                    colorPrimvar.GetAttr().HasAuthoredValueOpinion()) {
                    authoredPrimvars.push_back(colorPrimvar);
                }
            }
        } else if (primvarPattern != "") {
            authoredPrimvars = prim.GetAuthoredPrimvars();
        }
    }    

    // Is it better to sort the attributes and build the attributes all at once.

    for( const UsdGeomPrimvar &primvar : authoredPrimvars )
    {
        DBG(cerr << "loadPrimvar " << primvar.GetPrimvarName() << "\t" << primvar.GetTypeName() << "\t" << primvar.GetInterpolation() << endl);

        UT_String name(primvar.GetPrimvarName());

        // One special case we always handle here is to change
        // the name of the USD "displayColor" primvar to "Cd",
        // as long as there is not already a "Cd" primvar.
        if (!hasCdPrimvar && 
            primvar.GetName() == UsdGeomTokens->primvarsDisplayColor) {
            name = Cd;
        }

        // If the name of this primvar doesn't
        // match the primvarPattern, skip it.
        if (!name.multiMatch(primvarPattern, 1, " ")) {
            continue;
        }

        GT_DataArrayHandle gtData = convertPrimvarData( primvar, time );

        if( !gtData )
        {
            TF_WARN( "Failed to convert primvar %s:%s %s.", 
                        primPath.c_str(),
                        primvar.GetPrimvarName().GetText(),
                        primvar.GetTypeName().GetAsToken().GetText() );
            continue;
        }

        // usd vertex primvars are assigned to points
        if( primvar.GetInterpolation() == UsdGeomTokens->vertex )
        {
            if( gtData->entries() < minPoint ) {
                TF_WARN( "Not enough values found for primvar: %s:%s. "
                         "%zd values given for %d points.",
                         primPath.c_str(),
                         primvar.GetPrimvarName().GetText(),
                         gtData->entries(), minPoint );
            }
            else {
                if (remapIndicies) {
                    gtData = new GT_DAIndirect( remapIndicies, gtData );
                }
                if( point ) {
                    *point = (*point)->addAttribute( name.c_str(), gtData, true );
                }
            }
        }
        else if( primvar.GetInterpolation() == UsdGeomTokens->faceVarying )
        {
            if( gtData->entries() < minVertex ) {
                TF_WARN( "Not enough values found for primvar: %s:%s. "
                         "%zd values given for %d verticies.", 
                         primPath.c_str(),
                         primvar.GetPrimvarName().GetText(), 
                         gtData->entries(), minVertex );
            }
            else if( vertex ) {           
                *vertex = (*vertex)->addAttribute( name.c_str(), gtData, true );
            }
        }
        else if( primvar.GetInterpolation() == UsdGeomTokens->uniform )
        {
            if( gtData->entries() < minUniform ) {
                TF_WARN( "Not enough values found for primvar: %s:%s. "
                         "%zd values given for %d faces.", 
                         primPath.c_str(),
                         primvar.GetPrimvarName().GetText(),
                         gtData->entries(), minUniform );
            }
            else if( primitive ) {
                *primitive = (*primitive)->addAttribute( name.c_str(), gtData, true );
            }
        }
        else if( primvar.GetInterpolation() == UsdGeomTokens->constant )
        {
            if( constant ) {
                *constant = (*constant)->addAttribute( name.c_str(), gtData, true );
            }
        }
    }
}
Beispiel #8
0
void
GusdPrimWrapper::updateTransformFromGTPrim( const GfMatrix4d &xform, 
                                            UsdTimeCode time, bool force )
{
    UsdGeomImageable usdGeom = getUsdPrimForWrite();
    UsdGeomXformable prim( usdGeom );

    // Determine if we need to clear previous transformations from a stronger
    // opinion on the stage before authoring ours.
    UsdStagePtr stage = usdGeom.GetPrim().GetStage();
    UsdEditTarget currEditTarget = stage->GetEditTarget();

    // If the edit target does no mapping, it is most likely the session
    // layer which means it is in the local layer stack and can overlay
    // any xformOps.
    if ( !currEditTarget.GetMapFunction().IsNull() && 
         !currEditTarget.GetMapFunction().IsIdentity() ) {
        bool reset;
        std::vector<UsdGeomXformOp> xformVec = prim.GetOrderedXformOps(&reset);

        // The xformOps attribute is static so we only check if we haven't
        // changed anything yet. In addition nothing needs to be cleared if it
        // was previously empty.
        if (m_lastXformSet.IsDefault() && (int)xformVec.size() > 0) {
            // Load the root layer for temp, stronger opinion changes.
            stage->GetRootLayer()->SetPermissionToSave(false);
            stage->SetEditTarget(stage->GetRootLayer());
            UsdGeomXformable stagePrim( getUsdPrimForWrite() );

            // Clear the xformOps on the stronger layer, so our weaker edit
            // target (with mapping across a reference) can write out clean,
            // new transforms.
            stagePrim.ClearXformOpOrder();
            stage->SetEditTarget(currEditTarget);
        }
    }

    if( !prim )
        return;

    // Try to avoid setting the transform when we can.
    // If force it true, always write the transform (used when writting per frame)
    bool setKnot = true;
    if( !force ) {
        
        // Has the transform has been set at least once
        if( !m_lastXformSet.IsDefault() ) {

            // Is the transform at this frame the same as the last frame
            if( isClose(xform,m_xformCache) ) {
                setKnot = false;
                m_lastXformCompared = time;
            }
            else {
                // If the transform has been held for more than one frame, 
                // set a knot on the last frame
                if( m_lastXformCompared != m_lastXformSet ) {
                    prim.MakeMatrixXform().Set( m_xformCache, m_lastXformCompared );
                }
            }
        }
        else {
            // If the transform is an identity, don't set it
            if( isClose(xform,GfMatrix4d( 1.0 ))) {

                setKnot = false;
                m_lastXformCompared = time;
            }
            else {

                // If the transform was identity and now isn't, set a knot on the last frame
                if( !m_lastXformCompared.IsDefault() ) {
                    prim.MakeMatrixXform().Set( GfMatrix4d(1.0), m_lastXformCompared );
                }
            }
        }
    }

    if( setKnot ) {
        prim.MakeMatrixXform().Set( xform, time );
        m_xformCache = xform;
        m_lastXformSet = time;
        m_lastXformCompared = time;
    }
}
bool
GusdGU_PackedUSD::unpackPrim( 
    GU_Detail&              destgdp,
    UsdGeomImageable        prim, 
    const SdfPath&          primPath,
    const UT_Matrix4D&      xform,
    const GT_RefineParms&   rparms,
    bool                    addPathAttributes ) const
{
    GT_PrimitiveHandle gtPrim = 
        GusdPrimWrapper::defineForRead( 
                    prim,
                    m_frame,
                    m_purposes );

    if( !gtPrim ) {
        const TfToken &type = prim.GetPrim().GetTypeName();
        if( type != "PxHairman" && type != "PxProcArgs" )
            TF_WARN( "Can't convert prim for unpack. %s. Type = %s.", 
                      prim.GetPrim().GetPath().GetText(),
                      type.GetText() );
        return false;
    }
    GusdPrimWrapper* wrapper = UTverify_cast<GusdPrimWrapper*>(gtPrim.get());

    if( !wrapper->unpack( 
            destgdp,
            fileName(),
            primPath,
            xform,
            intrinsicFrame(),
#if SYS_VERSION_FULL_INT < 0x10050000
	    intrinsicViewportLOD(),
#else
	    intrinsicViewportLOD( getPrim() ),
#endif
            m_purposes )) {

        // If the wrapper prim does not do the unpack, do it here.
        UT_Array<GU_Detail *>   details;

        if( prim.GetPrim().IsInMaster() ) {

            gtPrim->setPrimitiveTransform( new GT_Transform( &xform, 1 ) );
        }    


        GA_Size startIndex = destgdp.getNumPrimitives();

        GT_Util::makeGEO(details, gtPrim, &rparms);

        for (exint i = 0; i < details.entries(); ++i)
        {
            copyPrimitiveGroups(*details(i), false);
#if SYS_VERSION_FULL_INT < 0x11000000
            unpackToDetail(destgdp, details(i), true);
#else
            unpackToDetail(destgdp, details(i), &xform);
#endif
            delete details(i);
        }

        if( addPathAttributes ) { 
            // Add usdpath and usdprimpath attributes to unpacked geometry.
            GA_Size endIndex = destgdp.getNumPrimitives();

            const char *path = prim.GetPrim().GetPath().GetString().c_str();

            if( endIndex > startIndex )
            {
                GA_RWHandleS primPathAttr( 
                    destgdp.addStringTuple( GA_ATTRIB_PRIMITIVE, GUSD_PRIMPATH_ATTR, 1 ));
                GA_RWHandleS pathAttr( 
                    destgdp.addStringTuple( GA_ATTRIB_PRIMITIVE, GUSD_PATH_ATTR, 1 ));

                for( GA_Size i = startIndex; i < endIndex; ++i )
                {
                    primPathAttr.set( destgdp.primitiveOffset( i ), 0, path );
                    pathAttr.set( destgdp.primitiveOffset( i ), 0, fileName().c_str() );
                }
            }
        }
    }
    return true;
}
/* static */
GU_PrimPacked* 
GusdGU_PackedUSD::Build( 
    GU_Detail&              detail, 
    const UT_StringHolder&  fileName, 
    const SdfPath&          primPath, 
    UsdTimeCode             frame, 
    const char*             lod,
    GusdPurposeSet          purposes,
    const UsdPrim&          prim,
    const UT_Matrix4D*      xform )
{   
    auto packedPrim = GU_PrimPacked::build( detail, k_typeName );
    auto impl = UTverify_cast<GusdGU_PackedUSD *>(packedPrim->implementation());
    impl->m_fileName = fileName;
    impl->m_primPath = primPath;
    impl->m_frame = frame;

    if( prim && !prim.IsA<UsdGeomBoundable>() )
    {
        UsdGeomImageable geom = UsdGeomImageable(prim);
        std::vector<UsdGeomPrimvar> authoredPrimvars = geom.GetAuthoredPrimvars();
        GT_DataArrayHandle buffer;

        for( const UsdGeomPrimvar &primvar : authoredPrimvars ) {
            // XXX This is temporary code, we need to factor the usd read code into GT_Utils.cpp
            // to avoid duplicates and read for types GfHalf,double,int,string ...
            GT_DataArrayHandle gtData = GusdPrimWrapper::convertPrimvarData( primvar, frame );
	    if (!gtData)
		continue;

            const UT_String  name(primvar.GetPrimvarName());
            const GT_Storage gtStorage = gtData->getStorage();
            const GT_Size    gtTupleSize = gtData->getTupleSize();

            GA_Attribute *anAttr = detail.addTuple(GT_Util::getGAStorage(gtStorage), GA_ATTRIB_PRIMITIVE, name,
                                                   gtTupleSize);

            if( !anAttr ) {
                // addTuple could fail for various reasons, like if there's a
                // non-alphanumeric character in the primvar name.
                continue;
            }

            if( const GA_AIFTuple *aIFTuple = anAttr->getAIFTuple()) {

                const float* flatArray = gtData->getF32Array( buffer );
                aIFTuple->set( anAttr, packedPrim->getMapOffset(), flatArray, gtTupleSize );

            }  else {

                //TF_WARN( "Unsupported primvar type: %s, %s, tupleSize = %zd", 
                //         GT_String( name ), GTstorage( gtStorage ), gtTupleSize );
            }
        }
    }

    if( lod )
    {
#if SYS_VERSION_FULL_INT < 0x10050000
        impl->intrinsicSetViewportLOD( lod );
#else
        impl->intrinsicSetViewportLOD( packedPrim, lod );
#endif
    }
    impl->setPurposes( purposes );

    // It seems that Houdini may reuse memory for packed implementations with
    // out calling the constructor to initialize data. 
    impl->resetCaches();

    // If a UsdPrim was passed in, make sure it is used.
    impl->m_usdPrim = prim;

    if (xform) {
        impl->setTransform(*xform);
    } else {
        impl->updateTransform();    
    }
    return packedPrim;
}