/* * Return a FloatAttribute for points. There are 4 floats per * point, where the first 3 floats are the point's position, * and the 4th float is the weight of the point. */ static FnKat::FloatAttribute _GetPwAttr( const UsdGeomNurbsPatch &nurbsPatch, double currentTime, const std::vector<double>& motionSampleTimes, const bool isMotionBackward) { UsdAttribute weightsAttr = nurbsPatch.GetPointWeightsAttr(); UsdAttribute pointsAttr = nurbsPatch.GetPointsAttr(); if (!pointsAttr) { return FnKat::FloatAttribute(); } FnKat::FloatBuilder pwBuilder(/* tupleSize = */ 4); TF_FOR_ALL(iter, motionSampleTimes) { double relSampleTime = *iter; double time = currentTime + relSampleTime; // Eval points at this motion sample time VtVec3fArray ptArray; pointsAttr.Get(&ptArray, time); // Eval Weights at this motion sample time VtDoubleArray wtArray; weightsAttr.Get(&wtArray, currentTime); bool hasWeights = false; if (ptArray.size() == wtArray.size()) { hasWeights = true; } else if (wtArray.size() > 0) { FnLogWarn("Nurbs Patch " << nurbsPatch.GetPath().GetText() << " has mismatched weights array. Skipping."); return FnKat::FloatAttribute(); } // set the points data in katana at the give motion sample time std::vector<float> &ptVec = pwBuilder.get(isMotionBackward ? PxrUsdKatanaUtils::ReverseTimeSample(relSampleTime) : relSampleTime); ptVec.resize(ptArray.size() * 4); size_t count = 0; for (size_t i = 0; i != ptArray.size(); ++i) { float weight = hasWeights ? wtArray[i] : 1.0f; ptVec[count++] = ptArray[i][0]*weight; ptVec[count++] = ptArray[i][1]*weight; ptVec[count++] = ptArray[i][2]*weight; // the 4th float is the weight of the point ptVec[count++] = weight ; } }
/* static */ bool PxrUsdKatanaUsdInPluginRegistry::_DoFindKind( const TfToken& kind, std::string* opName, const _KindRegistry& reg) { // can cache this if it becomes an issue. TfToken currKind = kind; while (!currKind.IsEmpty()) { if (TfMapLookup(reg, currKind, opName)) { return true; } if (KindRegistry::HasKind(currKind)) { currKind = KindRegistry::GetBaseKind(currKind); } else { FnLogWarn(TfStringPrintf("Unknown kind: '%s'", currKind.GetText())); return false; } } return false; }
static FnKat::Attribute _GetMaterialAssignAttr( const UsdPrim& prim, const PxrUsdKatanaUsdInPrivateData& data) { if (not prim or prim.GetPath() == SdfPath::AbsoluteRootPath()) { // Special-case to pre-empt coding errors. return FnKat::Attribute(); } UsdRelationship usdRel = UsdShadeLook::GetBindingRel(prim); if (usdRel) { // USD shading binding SdfPathVector targetPaths; usdRel.GetForwardedTargets(&targetPaths); if (targetPaths.size() > 0) { if (not targetPaths[0].IsPrimPath()) { FnLogWarn("Target path " << prim.GetPath().GetString() << " is not a prim"); return FnKat::Attribute(); } // This is a copy as it could be modified below. SdfPath targetPath = targetPaths[0]; UsdPrim targetPrim = data.GetUsdInArgs()->GetStage()->GetPrimAtPath(targetPath); // If the target is inside a master, then it needs to be re-targeted // to the instance. // // XXX remove this special awareness once GetMasterWithContext is // is available as the provided prim will automatically // retarget (or provide enough context to retarget without // tracking manually). if (targetPrim and targetPrim.IsInMaster()) { if (not data.GetInstancePath().IsEmpty() and not data.GetMasterPath().IsEmpty()) { // Check if the source and the target of the relationship // belong to the same master. // If they do, we have the context necessary to do the // re-mapping. if (data.GetMasterPath().GetCommonPrefix(targetPath). GetPathElementCount() > 0) { targetPath = data.GetInstancePath().AppendPath( targetPath.ReplacePrefix(targetPath.GetPrefixes()[0], SdfPath::ReflexiveRelativePath())); } else { // Warn saying the target of relationship isn't within // the same master as the source. FnLogWarn("Target path " << prim.GetPath().GetString() << " isn't within the master " << data.GetMasterPath()); return FnKat::Attribute(); } } else { // XXX // When loading beneath a master via an isolatePath // opArg, we can encounter targets which are within masters // but not within the context of a material. // While that would be an error according to the below // warning, it produces the expected results. // This case can occur when expanding pointinstancers as // the sources are made via execution of PxrUsdIn again // at the sub-trees. // Warn saying target of relationship is in a master, // but the associated instance path is unknown! // FnLogWarn("Target path " << prim.GetPath().GetString() // << " is within a master, but the associated " // "instancePath is unknown."); // return FnKat::Attribute(); } } // Convert the target path to the equivalent katana location. // XXX: Looks may have an atypical USD->Katana // path mapping std::string location = PxrUsdKatanaUtils::ConvertUsdLookPathToKatLocation(targetPath, data); // XXX Looks containing only display terminals are causing issues // with katana material manipulation workflows. // For now: exclude any material assign which doesn't include // /Looks/ in the path if (location.find(UsdKatanaTokens->katanaLooksScopePathSubstring) == std::string::npos) { return FnKat::Attribute(); } // location = TfStringReplace(location, "/Looks/", "/Materials/"); // XXX handle multiple assignments return FnKat::StringAttribute(location); } } return FnKat::Attribute(); }
void USDVMP::setup(FnKat::ViewerModifierInput& input) { TF_DEBUG(KATANA_DEBUG_VMP_USD).Msg("%s @ %p : %s\n", TF_FUNC_NAME().c_str(), this, input.getFullName().c_str()); // The multi-threaded Usd Op may be loading or unloading models on the stage // we need, so we grab the global lock in reader mode. boost::shared_lock<boost::upgrade_mutex> readerLock(UsdKatanaGetStageLock()); // Open stage if necessary. if (not _stage) { // Get usd file, node path, and current time, // needed to call TidSceneRenderer FnKat::StringAttribute usdFileAttr = input.getAttribute("fileName"); FnKat::StringAttribute usdRootLocationAttr = input.getAttribute("rootLocation"); FnKat::StringAttribute usdReferencePathAttr = input.getAttribute("referencePath"); FnKat::StringAttribute variantStringAttr = input.getAttribute("variants"); FnKat::StringAttribute ignoreLayerAttr= input.getAttribute("ignoreLayerRegex"); FnKat::FloatAttribute forcePopulateAttr = input.getAttribute("forcePopulateUsdStage"); std::string usdFile = usdFileAttr.getValue("", false); std::string usdRootLocation = usdRootLocationAttr.getValue("", false); std::string usdReferencePath = usdReferencePathAttr.getValue("",false); std::string variantString = variantStringAttr.getValue("",false); std::string ignoreLayerRegex = ignoreLayerAttr.getValue("$^", false); bool forcePopulate = forcePopulateAttr.getValue((float)true,false); if (usdFile.empty()) return; _stage = UsdKatanaCache::GetInstance().GetStage(usdFile, variantString, ignoreLayerRegex, forcePopulate); if (not _stage) { TF_DEBUG(KATANA_DEBUG_VMP_USD).Msg( "Cannot resolve path %s", usdFile.c_str()); return; } if (usdReferencePath == "") _prim = _stage->GetPseudoRoot(); else _prim = _stage->GetPrimAtPath(SdfPath(usdReferencePath)); if (not _prim) FnLogWarn(std::string("Cannot compose ") + _prim.GetPath().GetString()); _params.cullStyle = UsdImagingEngine::CULL_STYLE_BACK_UNLESS_DOUBLE_SIDED; _renderer = UsdKatanaCache::GetInstance() .GetRenderer(_stage, _prim, variantString); } // always update frame time FnKat::DoubleAttribute currentTimeAttr = input.getAttribute("currentTime"); double currentTime = currentTimeAttr.getValue(0.0, false); _params.frame = currentTime; }