void _WritePrefixedAttrs( const UsdTimeCode &usdTime, const _PrimEntry& entry) { MStatus status; MFnDependencyNode depFn(entry.mayaDagPath.node()); for (const auto& attrEntry : entry.attrs) { MPlug plg = depFn.findPlug(attrEntry.mayaAttributeName.c_str(), true); UsdAttribute usdAttr; if (attrEntry.isPrimvar) { // Treat as custom primvar. TfToken interpolation = _GetPrimvarInterpolation( depFn, attrEntry.mayaAttributeName); UsdGeomImageable imageable(entry.usdPrim); if (!imageable) { TF_RUNTIME_ERROR( "Cannot create primvar for non-UsdGeomImageable " "USD prim <%s>", entry.usdPrim.GetPath().GetText()); continue; } UsdGeomPrimvar primvar = UsdMayaWriteUtil::GetOrCreatePrimvar( plg, imageable, attrEntry.usdAttributeName, interpolation, -1, false); if (primvar) { usdAttr = primvar.GetAttr(); } } else { // Treat as custom attribute. usdAttr = UsdMayaWriteUtil::GetOrCreateUsdAttr( plg, entry.usdPrim, attrEntry.usdAttributeName, true); } if (usdAttr) { UsdMayaWriteUtil::SetUsdAttr(plg, usdAttr, usdTime); } else { TF_RUNTIME_ERROR( "Could not create attribute '%s' for " "USD prim <%s>", attrEntry.usdAttributeName.c_str(), entry.usdPrim.GetPath().GetText()); continue; } } }
NdrNodeDiscoveryResultVec UsdHydraDiscoveryPlugin::DiscoverNodes(const Context &context) { NdrNodeDiscoveryResultVec result; static std::string shaderDefsFile = _GetShaderResourcePath( "shaderDefs.usda"); if (shaderDefsFile.empty()) return result; auto resolverContext = ArGetResolver().CreateDefaultContextForAsset( shaderDefsFile); const UsdStageRefPtr stage = UsdStage::Open(shaderDefsFile, resolverContext); if (!stage) { TF_RUNTIME_ERROR("Could not open file '%s' on a USD stage.", shaderDefsFile.c_str()); return result; } ArResolverContextBinder binder(resolverContext); const TfToken discoveryType(ArGetResolver().GetExtension( shaderDefsFile)); auto rootPrims = stage->GetPseudoRoot().GetChildren(); for (const auto &shaderDef : rootPrims) { UsdShadeShader shader(shaderDef); if (!shader) { continue; } auto discoveryResults = UsdShadeShaderDefUtils::GetNodeDiscoveryResults( shader, shaderDefsFile); result.insert(result.end(), discoveryResults.begin(), discoveryResults.end()); if (discoveryResults.empty()) { TF_RUNTIME_ERROR("Found shader definition <%s> with no valid " "discovery results. This is likely because there are no " "resolvable info:sourceAsset values.", shaderDef.GetPath().GetText()); } } return result; }
void Hd_VtExtractor::Extract(const VtValue &value) { // Type dispatch to _Extractor. // // Iterate over each acceptable type T, calling typeChecker<T>(), which // internally calls value.IsHolding<T>(); if the VtValue IS holding a T, // then pass the held value to _Extractor::Extract<T>(value). _Extractor e; boost::mpl::for_each<_AcceptedTypes>(_TypeChecker<_Extractor>(value, e)); // Guarantee that the _Extractor::Extract method was called exactly once // and issue a runtime error otherwise. (The only case where Extract wont // be called is when the VtValue is holding an unacceptable type). if (e.GetNumComponents() == 0) { TF_RUNTIME_ERROR("Trying to extract a VtValue holding " "unacceptable type: %s", value.GetType().GetTypeName().c_str()); return; } const _GLDataType &glDataType = e.GetGLDataType(); _glComponentType = glDataType.componentType; _glElementType = glDataType.elementType; _size = e.GetSize(); _numComponents = e.GetNumComponents(); _data = e.GetData(); }
void HdxIntersector::SetResolution(GfVec2i const& widthHeight) { TRACE_FUNCTION(); // Make sure we're in a sane GL state before attempting anything. if (GlfHasLegacyGraphics()) { TF_RUNTIME_ERROR("framebuffer object not supported"); return; } if (!_drawTarget) { // Initialize the shared draw target late to ensure there is a valid GL // context, which may not be the case at constructon time. _Init(widthHeight); return; } if (widthHeight == _drawTarget->GetSize()){ return; } // Make sure master draw target is always modified on the shared context, // so we access it consistently. GlfSharedGLContextScopeHolder sharedContextHolder; { _drawTarget->Bind(); _drawTarget->SetSize(widthHeight); _drawTarget->Unbind(); } }
static bool _GetMetadataUnchecked( const MFnDependencyNode& node, const TfToken& key, VtValue* value) { VtValue fallback = SdfSchema::GetInstance().GetFallback(key); if (fallback.IsEmpty()) { return false; } std::string mayaAttrName = _GetMayaAttrNameForMetadataKey(key); MPlug plug = node.findPlug(mayaAttrName.c_str()); if (plug.isNull()) { return false; } TfType ty = fallback.GetType(); VtValue result = UsdMayaWriteUtil::GetVtValue(plug, ty, TfToken()); if (result.IsEmpty()) { TF_RUNTIME_ERROR( "Cannot convert plug '%s' into metadata '%s' (%s)", plug.name().asChar(), key.GetText(), ty.GetTypeName().c_str()); return false; } *value = result; return true; }
void KindRegistry::_RegisterDefaults() { // Initialize builtin kind hierarchy. _Register(KindTokens->subcomponent); _Register(KindTokens->model); _Register(KindTokens->component, KindTokens->model); _Register(KindTokens->group, KindTokens->model); _Register(KindTokens->assembly, KindTokens->group); // Check plugInfo for extensions to the kind hierarchy. // // XXX We only do this once, and do not re-build the kind hierarchy // if someone manages to add more plugins while the app is running. // This allows the KindRegistry to be threadsafe without locking. const PlugPluginPtrVector& plugins = PlugRegistry::GetInstance().GetAllPlugins(); TF_FOR_ALL(plug, plugins){ JsObject kinds; const JsObject &metadata = (*plug)->GetMetadata(); if (!_GetKey(metadata, _tokens->PluginKindsKey, &kinds)) continue; TF_FOR_ALL(kindEntry, kinds){ // Each entry is a map from kind -> metadata dict. TfToken kind(kindEntry->first); JsObject kindDict; if (!_GetKey(kinds, kind, &kindDict)){ TF_RUNTIME_ERROR("Expected dict for kind '%s'", kind.GetText()); continue; } // Check for baseKind. TfToken baseKind; JsObject::const_iterator i = kindDict.find("baseKind"); if (i != kindDict.end()) { if (i->second.IsString()) { baseKind = TfToken(i->second.GetString()); } else { TF_RUNTIME_ERROR("Expected string for baseKind"); continue; } } _Register(kind, baseKind); }
void _TestGusdTfErrorScope() { std::cout << "Test GusdTfErrorScope" << std::endl; // Severity is user-configured. Test each severity level. for(int i = UT_ERROR_MESSAGE; i < UT_NUM_ERROR_SEVERITIES; ++i) { auto sev = static_cast<UT_ErrorSeverity>(i); UT_ErrorManager::Scope scope; { GusdTfErrorScope tfErrScope(sev); TF_CODING_ERROR("(coding error)"); TF_RUNTIME_ERROR("(runtime error)"); } TF_AXIOM(scope.getErrorManager().getNumErrors() == 2); TF_AXIOM(scope.getSeverity() == sev); TF_AXIOM(TfStringContains(GusdGetErrors(), "(coding error)")); TF_AXIOM(TfStringContains(GusdGetErrors(), "(runtime error)")); } // Setting severity of NONE means errors are ignored. { UT_ErrorManager::Scope scope; { GusdTfErrorScope tfErrScope(UT_ERROR_NONE); TF_CODING_ERROR("(coding error)"); TF_RUNTIME_ERROR("(runtime error)"); } TF_AXIOM(scope.getErrorManager().getNumErrors() == 0); TF_AXIOM(scope.getSeverity() == UT_ERROR_NONE); } // Test workaround for errors containing '<>' chars, which normally // won't display in node MMB menus due to HTML formatting. { UT_ErrorManager::Scope scope; { GusdTfErrorScope tfErrScope; TF_CODING_ERROR("<foo>"); } TF_AXIOM(TfStringContains(GusdGetErrors(), "[foo]")); } }
void UsdImagingMaterialAdapter::_GetMaterialNetworkMap(UsdPrim const &usdPrim, HdMaterialNetworkMap *materialNetworkMap) const { UsdShadeMaterial material(usdPrim); if (!material) { TF_RUNTIME_ERROR("Expected material prim at <%s> to be of type " "'UsdShadeMaterial', not type '%s'; ignoring", usdPrim.GetPath().GetText(), usdPrim.GetTypeName().GetText()); return; } const TfToken context = _GetMaterialNetworkSelector(); if (UsdShadeShader s = material.ComputeSurfaceSource(context)) { _WalkGraph(s, &materialNetworkMap->map[UsdImagingTokens->bxdf], _GetShaderSourceTypes()); } if (UsdShadeShader d = material.ComputeDisplacementSource(context)) { _WalkGraph(d, &materialNetworkMap->map[UsdImagingTokens->displacement], _GetShaderSourceTypes()); } }
static bool _AssignMaterialFaceSet( const MObject& shadingEngine, const MDagPath& shapeDagPath, const VtIntArray& faceIndices) { MStatus status; // Create component object using single indexed // components, i.e. face indices. MFnSingleIndexedComponent compFn; MObject faceComp = compFn.create(MFn::kMeshPolygonComponent, &status); if (!status) { TF_RUNTIME_ERROR("Failed to create face component."); return false; } MIntArray mFaces; TF_FOR_ALL(fIdxIt, faceIndices) { mFaces.append(*fIdxIt); }
bool HdxIntersector::Query(HdxIntersector::Params const& params, HdRprimCollection const& col, HdEngine* engine, HdxIntersector::Result* result) { TRACE_FUNCTION(); // Make sure we're in a sane GL state before attempting anything. if (GlfHasLegacyGraphics()) { TF_RUNTIME_ERROR("framebuffer object not supported"); return false; } GlfGLContextSharedPtr context = GlfGLContext::GetCurrentGLContext(); if (!TF_VERIFY(context)) { TF_RUNTIME_ERROR("Invalid GL context"); return false; } if (!_drawTarget) { // Initialize the shared draw target late to ensure there is a valid GL // context, which may not be the case at constructon time. _Init(GfVec2i(128,128)); } GfVec2i size(_drawTarget->GetSize()); GfVec4i viewport(0, 0, size[0], size[1]); if (!TF_VERIFY(_renderPass)) { return false; } _renderPass->SetRprimCollection(col); // Setup state based on incoming params. _renderPassState->SetAlphaThreshold(params.alphaThreshold); _renderPassState->SetClipPlanes(params.clipPlanes); _renderPassState->SetCullStyle(params.cullStyle); _renderPassState->SetCamera(params.viewMatrix, params.projectionMatrix, viewport); _renderPassState->SetLightingEnabled(false); // Use a separate drawTarget (framebuffer object) for each GL context // that uses this renderer, but the drawTargets share attachments/textures. GlfDrawTargetRefPtr drawTarget = GlfDrawTarget::New(size); // Clone attachments into this context. Note that this will do a // light-weight copy of the textures, it does not produce a full copy of the // underlying images. drawTarget->Bind(); drawTarget->CloneAttachments(_drawTarget); // // Setup GL raster state // GLenum drawBuffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; glDrawBuffers(3, drawBuffers); glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); glDepthFunc(GL_LEQUAL); glClearColor(0,0,0,0); glClearStencil(0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); GLF_POST_PENDING_GL_ERRORS(); // // Execute the picking pass // { GLuint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); // Setup stencil state and prevent writes to color buffer. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 1, 1); glStencilOp(GL_KEEP, // stencil failed GL_KEEP, // stencil passed, depth failed GL_REPLACE); // stencil passed, depth passed // // Condition the stencil buffer. // params.depthMaskCallback(); // we expect any GL state changes are restored. // Disable stencil updates and setup the stencil test. glStencilFunc(GL_LESS, 0, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // Clear depth incase the depthMaskCallback pollutes the depth buffer. glClear(GL_DEPTH_BUFFER_BIT); // Restore color outputs & setup state for rendering glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDisable(GL_CULL_FACE); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glFrontFace(GL_CCW); // // Enable conservative rasterization, if available. // // XXX: This wont work until it's in the Glew build. bool convRstr = glewIsSupported("GL_NV_conservative_raster"); if (convRstr) { // XXX: this should come from Glew #define GL_CONSERVATIVE_RASTERIZATION_NV 0x9346 glEnable(GL_CONSERVATIVE_RASTERIZATION_NV); } // // Execute // // XXX: make intersector a Task HdTaskSharedPtrVector tasks; tasks.push_back(boost::make_shared<HdxIntersector_DrawTask>(_renderPass, _renderPassState, params.renderTags)); engine->Execute(*_index, tasks); glDisable(GL_STENCIL_TEST); if (convRstr) { // XXX: this should come from Glew #define GL_CONSERVATIVE_RASTERIZATION_NV 0x9346 glDisable(GL_CONSERVATIVE_RASTERIZATION_NV); } // Restore glBindVertexArray(0); glDeleteVertexArrays(1, &vao); } GLF_POST_PENDING_GL_ERRORS(); // // Capture the result buffers to be resolved later. // size_t len = size[0] * size[1]; std::unique_ptr<unsigned char[]> primId(new unsigned char[len*4]); std::unique_ptr<unsigned char[]> instanceId(new unsigned char[len*4]); std::unique_ptr<unsigned char[]> elementId(new unsigned char[len*4]); std::unique_ptr<float[]> depths(new float[len]); glBindTexture(GL_TEXTURE_2D, drawTarget->GetAttachments().at("primId")->GetGlTextureName()); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &primId[0]); glBindTexture(GL_TEXTURE_2D, drawTarget->GetAttachments().at("instanceId")->GetGlTextureName()); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &instanceId[0]); glBindTexture(GL_TEXTURE_2D, drawTarget->GetAttachments().at("elementId")->GetGlTextureName()); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &elementId[0]); glBindTexture(GL_TEXTURE_2D, drawTarget->GetAttachments().at("depth")->GetGlTextureName()); glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_FLOAT, &depths[0]); glBindTexture(GL_TEXTURE_2D, 0); GLF_POST_PENDING_GL_ERRORS(); if (result) { *result = HdxIntersector::Result( std::move(primId), std::move(instanceId), std::move(elementId), std::move(depths), _index, params, viewport); } drawTarget->Unbind(); GLF_POST_PENDING_GL_ERRORS(); return true; }
/// Finds the existing SkelRoot which is shared by all \p paths. /// If no SkelRoot is found, and \p config is "auto", then attempts to /// find a common ancestor of \p paths which can be converted to SkelRoot. /// \p outMadeSkelRoot must be non-null; it will be set to indicate whether /// any auto-typename change actually occurred (true) or whether there was /// already a SkelRoot, so no renaming was necessary (false). /// If an existing, common SkelRoot cannot be found for all paths, and if /// it's not possible to create one, returns an empty SdfPath. static SdfPath _VerifyOrMakeSkelRoot(const UsdStagePtr& stage, const SdfPath& path, const TfToken& config) { if (config != UsdMayaJobExportArgsTokens->auto_ && config != UsdMayaJobExportArgsTokens->explicit_) { return SdfPath(); } // Only try to auto-rename to SkelRoot if we're not already a // descendant of one. Otherwise, verify that the user tagged it in a sane // way. if (UsdSkelRoot root = UsdSkelRoot::Find(stage->GetPrimAtPath(path))) { // Verify that the SkelRoot isn't nested in another SkelRoot. // This is necessary because UsdSkel doesn't handle nested skel roots // very well currently; this restriction may be loosened in the future. if (UsdSkelRoot root2 = UsdSkelRoot::Find(root.GetPrim().GetParent())) { TF_RUNTIME_ERROR("The SkelRoot <%s> is nested inside another " "SkelRoot <%s>. This might cause unexpected behavior.", root.GetPath().GetText(), root2.GetPath().GetText()); return SdfPath(); } else { return root.GetPath(); } } else if(config == UsdMayaJobExportArgsTokens->auto_) { // If auto-generating the SkelRoot, find the rootmost // UsdGeomXform and turn it into a SkelRoot. // XXX: It might be good to also consider model hierarchy here, and not // go past our ancestor component when trying to generate the SkelRoot. // (Example: in a scene with /World, /World/Char_1, /World/Char_2, we // might want SkelRoots to stop at Char_1 and Char_2.) Unfortunately, // the current structure precludes us from accessing model hierarchy // here. if (UsdPrim root = _FindRootmostXformOrSkelRoot(stage, path)) { UsdSkelRoot::Define(stage, root.GetPath()); return root.GetPath(); } else { if (path.IsRootPrimPath()) { // This is the most common problem when we can't obtain a // SkelRoot. // Show a nice error with useful information about root prims. TF_RUNTIME_ERROR("The prim <%s> is a root prim, so it has no " "ancestors that can be converted to a SkelRoot. (USD " "requires that skinned meshes and skeletons be " "encapsulated under a SkelRoot.) Try grouping this " "prim under a parent group.", path.GetText()); } else { // Show generic error as a last resort if we don't know exactly // what went wrong. TF_RUNTIME_ERROR("Could not find an ancestor of the prim <%s> " "that can be converted to a SkelRoot. (USD requires " "that skinned meshes and skeletons be encapsulated " "under a SkelRoot.)", path.GetText()); } return SdfPath(); } } return SdfPath(); }
/* static */ std::vector<UsdMayaUserTaggedAttribute> UsdMayaUserTaggedAttribute::GetUserTaggedAttributesForNode( const MObject& mayaNode) { std::vector<UsdMayaUserTaggedAttribute> result; MStatus status; const MFnDependencyNode depNodeFn(mayaNode, &status); if (status != MS::kSuccess) { return result; } const MPlug exportedAttrsJsonPlug = depNodeFn.findPlug( _tokens->USD_UserExportedAttributesJson.GetText(), true, &status); if (status != MS::kSuccess || exportedAttrsJsonPlug.isNull()) { // No attributes specified for export on this node. return result; } const std::string exportedAttrsJsonString( exportedAttrsJsonPlug.asString().asChar()); if (exportedAttrsJsonString.empty()) { return result; } JsParseError jsError; const JsValue jsValue = JsParseString(exportedAttrsJsonString, &jsError); if (!jsValue) { TF_RUNTIME_ERROR( "Failed to parse USD exported attributes JSON on node '%s' " "at line %d, column %d: %s", UsdMayaUtil::GetMayaNodeName(mayaNode).c_str(), jsError.line, jsError.column, jsError.reason.c_str()); return result; } // If an attribute is multiply-defined, we'll use the first tag encountered // and issue warnings for the subsequent definitions. JsObject is really // just a std::map, so we'll be considering attributes in sorted order. std::set<std::string> processedAttributeNames; const JsObject& exportedAttrs = jsValue.GetJsObject(); for (const auto& exportedAttr : exportedAttrs) { const std::string mayaAttrName = exportedAttr.first; const MPlug attrPlug = depNodeFn.findPlug(mayaAttrName.c_str(), true, &status); if (status != MS::kSuccess || attrPlug.isNull()) { TF_RUNTIME_ERROR( "Could not find attribute '%s' for USD export on node '%s'", mayaAttrName.c_str(), UsdMayaUtil::GetMayaNodeName(mayaNode).c_str()); continue; } const JsObject& attrMetadata = exportedAttr.second.GetJsObject(); // Check if this is a particular type of attribute (e.g. primvar or // usdRi attribute). If we don't recognize the type specified, we'll // fall back to a regular USD attribute. const TfToken usdAttrType( _GetExportAttributeMetadata(attrMetadata, _tokens->usdAttrType)); // Check whether an interpolation type was specified. This is only // relevant for primvars. const TfToken interpolation( _GetExportAttributeMetadata(attrMetadata, UsdGeomTokens->interpolation)); // Check whether it was specified that the double precision Maya // attribute type should be mapped to a single precision USD type. // If it wasn't specified, use the fallback value. const bool translateMayaDoubleToUsdSinglePrecision( _GetExportAttributeMetadata( attrMetadata, _tokens->translateMayaDoubleToUsdSinglePrecision, GetFallbackTranslateMayaDoubleToUsdSinglePrecision())); // Check whether the USD attribute name should be different than the // Maya attribute name. std::string usdAttrName = _GetExportAttributeMetadata(attrMetadata, _tokens->usdAttrName); if (usdAttrName.empty()) { const auto& tokens = UsdMayaUserTaggedAttributeTokens; if (usdAttrType == tokens->USDAttrTypePrimvar || usdAttrType == tokens->USDAttrTypeUsdRi) { // Primvars and UsdRi attributes will be given a type-specific // namespace, so just use the Maya attribute name. usdAttrName = mayaAttrName; } else { // For regular USD attributes, when no name was specified we // prepend the userProperties namespace to the Maya attribute // name to get the USD attribute name. usdAttrName = _tokens->UserPropertiesNamespace.GetString() + mayaAttrName; } } const auto& insertIter = processedAttributeNames.emplace(usdAttrName); if (!insertIter.second) { TF_RUNTIME_ERROR( "Ignoring duplicate USD export tag for attribute '%s' " "on node '%s'", usdAttrName.c_str(), UsdMayaUtil::GetMayaNodeName(mayaNode).c_str()); continue; } result.emplace_back(attrPlug, usdAttrName, usdAttrType, interpolation, translateMayaDoubleToUsdSinglePrecision); } return result; }