bool UsdGeomCollectionAPI::AppendTarget( const SdfPath &target, const VtIntArray &faceIndices /* =VtIntArray() */, const UsdTimeCode &time /* =UsdTimeCode::Default() */) const { if (target.IsEmpty()) { TF_CODING_ERROR("Cannot add empty target to collection '%s' on " "prim <%s>.", _name.GetText(), GetPath().GetText()); return false; } bool hasFaceCountsAtTime = true; if (time != UsdTimeCode::Default()) { UsdAttribute targetFaceCountsAttr = GetTargetFaceCountsAttr(); double lower=0., upper=0.; bool hasTimeSamples=false; if (targetFaceCountsAttr.GetBracketingTimeSamples(time.GetValue(), &lower, &upper, &hasTimeSamples)) { hasFaceCountsAtTime = (lower==upper && lower==time.GetValue()); } } VtIntArray targetFaceCounts, targetFaceIndices; if (hasFaceCountsAtTime) { GetTargetFaceCounts(&targetFaceCounts, time); GetTargetFaceIndices(&targetFaceIndices, time); } SdfPathVector targets; GetTargets(&targets); // If there are no existing face restrictions and no face-restriction is // specified on the current target, simly add the target and return. if (targetFaceCounts.empty() && targetFaceIndices.empty() && faceIndices.empty()) { // We can simply add the target here to the relationship here since // there are no companion non-list-edited integer arrays. return CreateTargetsRel().AppendTarget(target); } if (targetFaceCounts.empty() && !targetFaceIndices.empty()) { TF_CODING_ERROR("targetFaceCounts is empty, but targetFaceIndices " "is not, for the collection '%s' belonging to prim <%s>.", _name.GetText(), GetPath().GetText()); return false; } if (targetFaceCounts.empty() && !faceIndices.empty()) { for (size_t i = 0 ; i < targets.size(); i++) targetFaceCounts.push_back(0); } targetFaceCounts.push_back(faceIndices.size()); targetFaceIndices.reserve(targetFaceIndices.size() + faceIndices.size()); TF_FOR_ALL(it, faceIndices) { targetFaceIndices.push_back(*it); }
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; }
bool GusdUSD_XformCache::_GetLocalTransformation(const UsdPrim& prim, UsdTimeCode time, UT_Matrix4D& xform, const XformInfoHandle& info) { // See if we can remap the time to for unvarying xforms. if(!time.IsDefault() && !info->LocalXformIsMaybeTimeVarying()) { /* XXX: we know we're not time varying, but that doesn't mean that we can key default, since there might still be a single varying value that we'd miss. Key off of time=0 instead.*/ time = UsdTimeCode(0.0); } _VaryingKey key(GusdUSD_VaryingPropertyKey(prim, time)); if(auto item = _xforms.findItem(key)) { xform = UTverify_cast<const _CappedXformItem*>(item.get())->xform; return true; } /* XXX: Race is possible when setting computed value, but it's preferable to have multiple threads compute the same thing than to cause lock contention.*/ if(info->query.GetLocalTransformation(GusdUT_Gf::Cast(&xform), time)) { _xforms.addItem(key, UT_CappedItemHandle(new _CappedXformItem(xform))); return true; } return false; }
bool GusdUSD_XformCache::GetLocalToWorldTransform(const UsdPrim& prim, UsdTimeCode time, UT_Matrix4D& xform) { const auto info = GetXformInfo(prim); if(BOOST_UNLIKELY(!info)) return false; // See if we can remap the time to for unvarying xforms. if(!time.IsDefault() && !info->WorldXformIsMaybeTimeVarying()) { /* XXX: we know we're not time varying, but that doesn't mean that we can key default, since there might still be a single varying value that we'd miss. Key off of time=0 instead.*/ time = UsdTimeCode(0.0); } _VaryingKey key(GusdUSD_VaryingPropertyKey(prim, time)); if(auto item = _worldXforms.findItem(key)) { xform = UTverify_cast<const _CappedXformItem*>(item.get())->xform; return true; } /* XXX: Race is possible when setting computed value, but it's preferable to have multiple threads compute the same thing than to cause lock contention.*/ if(_GetLocalTransformation(prim, time, xform, info)) { if(BOOST_UNLIKELY(!info->HasParentXform())) { _worldXforms.addItem(key, UT_CappedItemHandle( new _CappedXformItem(xform))); return true; } UsdPrim parent = prim.GetParent(); UT_ASSERT_P(parent); UT_Matrix4D parentXf; if(GetLocalToWorldTransform(parent, time, parentXf)) { xform *= parentXf; _worldXforms.addItem( key, UT_CappedItemHandle(new _CappedXformItem(xform))); return true; } } return false; }
// virtual bool MayaNurbsCurveWriter::writeNurbsCurveAttrs(const UsdTimeCode &usdTime, UsdGeomNurbsCurves &primSchema) { MStatus status = MS::kSuccess; // Write parent class attrs writeTransformAttrs(usdTime, primSchema); // Return if usdTime does not match if shape is animated if (usdTime.IsDefault() == isShapeAnimated() ) { // skip shape as the usdTime does not match if shape isAnimated value return true; } MFnDependencyNode fnDepNode(getDagPath().node(), &status); MString name = fnDepNode.name(); MFnNurbsCurve curveFn( getDagPath(), &status ); if (!status) { MGlobal::displayError("MFnNurbsCurve() failed for MayaNurbsCurveWriter"); return false; } // Get curve attrs ====== unsigned int numCurves = 1; // Assuming only 1 curve for now VtArray<int> curveOrder(numCurves); VtArray<int> curveVertexCounts(numCurves); VtArray<float> curveWidths(numCurves); VtArray<GfVec2d> ranges(numCurves); curveOrder[0] = curveFn.degree()+1; curveVertexCounts[0] = curveFn.numCVs(); TF_AXIOM(curveOrder[0] <= curveVertexCounts[0] ); curveWidths[0] = 1.0; // TODO: Retrieve from custom attr double mayaKnotDomainMin; double mayaKnotDomainMax; status = curveFn.getKnotDomain(mayaKnotDomainMin, mayaKnotDomainMax); TF_AXIOM(status == MS::kSuccess); ranges[0][0] = mayaKnotDomainMin; ranges[0][1] = mayaKnotDomainMax; MPointArray mayaCurveCVs; status = curveFn.getCVs(mayaCurveCVs, MSpace::kObject); TF_AXIOM(status == MS::kSuccess); VtArray<GfVec3f> points(mayaCurveCVs.length()); // all CVs batched together for (unsigned int i=0; i < mayaCurveCVs.length(); i++) { points[i].Set(mayaCurveCVs[i].x, mayaCurveCVs[i].y, mayaCurveCVs[i].z); } MDoubleArray mayaCurveKnots; status = curveFn.getKnots(mayaCurveKnots); TF_AXIOM(status == MS::kSuccess); VtArray<double> curveKnots(mayaCurveKnots.length()); // all knots batched together for (unsigned int i=0; i < mayaCurveKnots.length(); i++) { curveKnots[i] = mayaCurveKnots[i]; } // Gprim VtArray<GfVec3f> extent(2); UsdGeomCurves::ComputeExtent(points, curveWidths, &extent); primSchema.CreateExtentAttr().Set(extent, usdTime); // Curve primSchema.GetOrderAttr().Set(curveOrder); // not animatable primSchema.GetCurveVertexCountsAttr().Set(curveVertexCounts); // not animatable primSchema.GetWidthsAttr().Set(curveWidths); // not animatable primSchema.GetKnotsAttr().Set(curveKnots); // not animatable primSchema.GetRangesAttr().Set(ranges); // not animatable primSchema.GetPointsAttr().Set(points, usdTime); // CVs // TODO: Handle periodic and non-periodic cases return true; }
// virtual bool MayaMeshWriter::writeMeshAttrs(const UsdTimeCode &usdTime, UsdGeomMesh &primSchema) { MStatus status = MS::kSuccess; // Write parent class attrs writeTransformAttrs(usdTime, primSchema); // Return if usdTime does not match if shape is animated if (usdTime.IsDefault() == isShapeAnimated() ) { // skip shape as the usdTime does not match if shape isAnimated value return true; } MFnMesh lMesh( getDagPath(), &status ); if ( !status ) { MGlobal::displayError( "MFnMesh() failed for MayaMeshWriter" ); return false; } unsigned int numVertices = lMesh.numVertices(); unsigned int numPolygons = lMesh.numPolygons(); // Set mesh attrs ========== // Get points // TODO: Use memcpy() const float* mayaRawPoints = lMesh.getRawPoints(&status); VtArray<GfVec3f> points(numVertices); for (unsigned int i = 0; i < numVertices; i++) { unsigned int floatIndex = i*3; points[i].Set(mayaRawPoints[floatIndex], mayaRawPoints[floatIndex+1], mayaRawPoints[floatIndex+2]); } primSchema.GetPointsAttr().Set(points, usdTime); // ANIMATED // Compute the extent using the raw points VtArray<GfVec3f> extent(2); UsdGeomPointBased::ComputeExtent(points, &extent); primSchema.CreateExtentAttr().Set(extent, usdTime); // Get faceVertexIndices unsigned int numFaceVertices = lMesh.numFaceVertices(&status); VtArray<int> faceVertexCounts(numPolygons); VtArray<int> faceVertexIndices(numFaceVertices); MIntArray mayaFaceVertexIndices; // used in loop below unsigned int curFaceVertexIndex = 0; for (unsigned int i = 0; i < numPolygons; i++) { lMesh.getPolygonVertices(i, mayaFaceVertexIndices); faceVertexCounts[i] = mayaFaceVertexIndices.length(); for (unsigned int j=0; j < mayaFaceVertexIndices.length(); j++) { faceVertexIndices[ curFaceVertexIndex ] = mayaFaceVertexIndices[j]; // push_back curFaceVertexIndex++; } } primSchema.GetFaceVertexCountsAttr().Set(faceVertexCounts); // not animatable primSchema.GetFaceVertexIndicesAttr().Set(faceVertexIndices); // not animatable // Read usdSdScheme attribute. If not set, we default to defaultMeshScheme // flag that can be user defined and initialized to catmullClark TfToken sdScheme = PxrUsdMayaMeshUtil::getSubdivScheme(lMesh, getArgs().defaultMeshScheme); primSchema.CreateSubdivisionSchemeAttr(VtValue(sdScheme), true); // Polygonal Mesh Case if (sdScheme==UsdGeomTokens->none) { // Support for standard USD bool and with Mojito bool tag TfToken normalInterp=PxrUsdMayaMeshUtil::getEmitNormals(lMesh, UsdGeomTokens->none); if (normalInterp==UsdGeomTokens->faceVarying) { // Get References to members of meshData object MFloatVectorArray normalArray; MFloatVectorArray vertexNormalArray; lMesh.getNormals(normalArray, MSpace::kObject); // Iterate through each face in the mesh. vertexNormalArray.setLength(lMesh.numFaceVertices()); VtArray<GfVec3f> meshNormals(lMesh.numFaceVertices()); size_t faceVertIdx = 0; for (MItMeshPolygon faceIter(getDagPath()); !faceIter.isDone(); faceIter.next()) { // Iterate through each face-vertex. for (size_t locVertIdx = 0; locVertIdx < faceIter.polygonVertexCount(); ++locVertIdx, ++faceVertIdx) { int index=faceIter.normalIndex(locVertIdx); for (int j=0;j<3;j++) { meshNormals[faceVertIdx][j]=normalArray[index][j]; } } } primSchema.GetNormalsAttr().Set(meshNormals, usdTime); primSchema.SetNormalsInterpolation(normalInterp); } } else { TfToken sdInterpBound = PxrUsdMayaMeshUtil::getSubdivInterpBoundary( lMesh, UsdGeomTokens->edgeAndCorner); primSchema.CreateInterpolateBoundaryAttr(VtValue(sdInterpBound), true); TfToken sdFVInterpBound = PxrUsdMayaMeshUtil::getSubdivFVInterpBoundary( lMesh); primSchema.CreateFaceVaryingLinearInterpolationAttr( VtValue(sdFVInterpBound), true); assignSubDivTagsToUSDPrim( lMesh, primSchema); } // Holes - we treat InvisibleFaces as holes MUintArray mayaHoles = lMesh.getInvisibleFaces(); if (mayaHoles.length() > 0) { VtArray<int> subdHoles(mayaHoles.length()); for (unsigned int i=0; i < mayaHoles.length(); i++) { subdHoles[i] = mayaHoles[i]; } // not animatable in Maya, so we'll set default only primSchema.GetHoleIndicesAttr().Set(subdHoles); } // == Write UVSets as Vec2f Primvars MStringArray uvSetNames; if (getArgs().exportMeshUVs) { status = lMesh.getUVSetNames(uvSetNames); } for (unsigned int i=0; i < uvSetNames.length(); i++) { // Initialize the VtArray to the max possible size (facevarying) VtArray<GfVec2f> uvValues(numFaceVertices); TfToken interpolation=TfToken(); // Gather UV data and interpolation into a Vec2f VtArray and try to compress if possible if (_GetMeshUVSetData(lMesh, uvSetNames[i], &uvValues, &interpolation) == MS::kSuccess) { // XXX:bug 118447 // We should be able to configure the UV map name that triggers this // behavior, and the name to which it exports. // The UV Set "map1" is renamed st. This is a Pixar/USD convention TfToken setName(uvSetNames[i].asChar()); if (setName == "map1") setName=UsdUtilsGetPrimaryUVSetName(); // Create the primvar and set the values UsdGeomPrimvar uvSet = primSchema.CreatePrimvar(setName, SdfValueTypeNames->Float2Array, interpolation); uvSet.Set( uvValues ); // not animatable } } // == Gather ColorSets MStringArray colorSetNames; if (getArgs().exportColorSets) { status = lMesh.getColorSetNames(colorSetNames); } // shaderColor is used in our pipeline as displayColor. // shaderColor is used to fill faces where the colorset is not assigned MColorArray shaderColors; MObjectArray shaderObjs; VtArray<GfVec3f> shadersRGBData; TfToken shadersRGBInterp; VtArray<float> shadersAlphaData; TfToken shadersAlphaInterp; // If exportDisplayColor is set to true or we have color sets, // gather color & opacity from the shader including per face // assignment. Color set require this to initialize unauthored/unpainted faces if (getArgs().exportDisplayColor or colorSetNames.length()>0) { PxrUsdMayaUtil::GetLinearShaderColor(lMesh, numPolygons, &shadersRGBData, &shadersRGBInterp, &shadersAlphaData, &shadersAlphaInterp); } for (unsigned int i=0; i < colorSetNames.length(); i++) { bool isDisplayColor=false; if (colorSetNames[i]=="displayColor") { if (not getArgs().exportDisplayColor) continue; isDisplayColor=true; } if (colorSetNames[i]=="displayOpacity") { MGlobal::displayWarning("displayOpacity on mesh:" + lMesh.fullPathName() + " is a reserved PrimVar name in USD. Skipping..."); continue; } VtArray<GfVec3f> RGBData; TfToken RGBInterp; VtArray<GfVec4f> RGBAData; TfToken RGBAInterp; VtArray<float> AlphaData; TfToken AlphaInterp; MFnMesh::MColorRepresentation colorSetRep; bool clamped=false; // If displayColor uses shaderValues for non authored areas // and allow RGB and Alpha to have different interpolation // For all other colorSets the non authored values are set // to (1,1,1,1) and RGB and Alpha will have the same interplation // since they will be emitted as a Vec4f if (not _GetMeshColorSetData( lMesh, colorSetNames[i], isDisplayColor, shadersRGBData, shadersAlphaData, &RGBData, &RGBInterp, &RGBAData, &RGBAInterp, &AlphaData, &AlphaInterp, &colorSetRep, &clamped)) { MGlobal::displayWarning("Unable to retrieve colorSet data: " + colorSetNames[i] + " on mesh: "+ lMesh.fullPathName() + ". Skipping..."); continue; } if (isDisplayColor) { // We tag the resulting displayColor/displayOpacity primvar as // authored to make sure we reconstruct the colorset on import // The RGB is also convererted From DisplayToLinear _setDisplayPrimVar( primSchema, colorSetRep, RGBData, RGBInterp, AlphaData, AlphaInterp, clamped, true); } else { TfToken colorSetNameToken = TfToken( PxrUsdMayaUtil::SanitizeColorSetName( std::string(colorSetNames[i].asChar()))); if (colorSetRep == MFnMesh::kAlpha) { _createAlphaPrimVar(primSchema, colorSetNameToken, AlphaData, AlphaInterp, clamped); } else if (colorSetRep == MFnMesh::kRGB) { _createRGBPrimVar(primSchema, colorSetNameToken, RGBData, RGBInterp, clamped); } else if (colorSetRep == MFnMesh::kRGBA) { _createRGBAPrimVar(primSchema, colorSetNameToken, RGBAData, RGBAInterp, clamped); } } } // Set displayColor and displayOpacity only if they are NOT authored already // Since this primvar will come from the shader and not a colorset, // we are not adding the clamp attribute as custom data // If a displayColor/displayOpacity is added, it's not considered authored // we don't need to reconstruct this as a colorset since it orgininated // from bound shader[s], so the authored flag is set to false // Given that this RGB is for display, we do DisplayToLinear conversion if (getArgs().exportDisplayColor) { _setDisplayPrimVar( primSchema, MFnMesh::kRGBA, shadersRGBData, shadersRGBInterp, shadersAlphaData, shadersAlphaInterp, false, false); } return true; }
bool PxrUsdTranslators_InstancerWriter::writeInstancerAttrs( const UsdTimeCode& usdTime, const UsdGeomPointInstancer& instancer) { MStatus status = MS::kSuccess; MFnDagNode dagNode(GetDagPath(), &status); CHECK_MSTATUS_AND_RETURN(status, false); // Note: In this function, we don't read instances using the provided // MFnInstancer API. One reason is that it breaks up prototypes into their // constituent shapes, and there's no way to figure out which hierarchy // they came from. Another reason is that it only provides computed matrices // and not separate position, rotation, scale attrs. const SdfPath prototypesGroupPath = instancer.GetPrim().GetPath().AppendChild(_tokens->Prototypes); // At the default time, setup all the prototype instances. if (usdTime.IsDefault()) { const MPlug inputHierarchy = dagNode.findPlug("inputHierarchy", true, &status); CHECK_MSTATUS_AND_RETURN(status, false); // Note that the "Prototypes" prim needs to be a model group to ensure // contiguous model hierarchy. const UsdPrim prototypesGroupPrim = GetUsdStage()->DefinePrim( prototypesGroupPath); UsdModelAPI(prototypesGroupPrim).SetKind(KindTokens->group); _modelPaths.push_back(prototypesGroupPath); UsdRelationship prototypesRel = instancer.CreatePrototypesRel(); const unsigned int numElements = inputHierarchy.numElements(); for (unsigned int i = 0; i < numElements; ++i) { const MPlug plug = inputHierarchy[i]; const MPlug source(UsdMayaUtil::GetConnected(plug)); if (source.isNull()) { TF_WARN("Cannot read prototype: the source plug %s was null", plug.name().asChar()); return false; } MFnDagNode sourceNode(source.node(), &status); CHECK_MSTATUS_AND_RETURN(status, false); MDagPath prototypeDagPath; sourceNode.getPath(prototypeDagPath); // Prototype names are guaranteed unique by virtue of having a // unique numerical suffix _# indicating the prototype index. const TfToken prototypeName( TfStringPrintf("%s_%d", sourceNode.name().asChar(), i)); const SdfPath prototypeUsdPath = prototypesGroupPrim.GetPath() .AppendChild(prototypeName); UsdPrim prototypePrim = GetUsdStage()->DefinePrim( prototypeUsdPath); _modelPaths.push_back(prototypeUsdPath); // Try to be conservative and only create an intermediary xformOp // with the instancerTranslate if we can ensure that we don't need // to compensate for the translation on the prototype root. // // XXX: instancerTranslate does not behave well when added to a // reference that has an existing transform on the far side of the // reference. However, its behavior at least matches the // behavior in UsdMayaTranslatorModelAssembly. If we fix the // behavior there, we need to make sure that this is also // fixed to match. bool instancerTranslateAnimated = false; if (_NeedsExtraInstancerTranslate( prototypeDagPath, &instancerTranslateAnimated)) { UsdGeomXformable xformable(prototypePrim); UsdGeomXformOp newOp = xformable.AddTranslateOp( UsdGeomXformOp::PrecisionDouble, _tokens->instancerTranslate); _instancerTranslateOps.push_back( {prototypeDagPath, newOp, instancerTranslateAnimated}); } // Two notes: // (1) We don't un-instance here, because it's OK for the prototype // to just be a reference to an instance master if the prototype // participates in Maya native instancing. // (2) The prototype root must be visible to match Maya's behavior, // which always vis'es the prototype root, even if it is marked // hidden. _writeJobCtx.CreatePrimWriterHierarchy( prototypeDagPath, prototypeUsdPath, /*forceUninstance*/ false, /*exportRootVisibility*/ false, &_prototypeWriters); prototypesRel.AddTarget(prototypeUsdPath); } _numPrototypes = numElements; } // If there aren't any prototypes, fail and don't export on subsequent // time-sampled exports. if (_numPrototypes == 0) { return false; } // Actual write of prototypes (@ both default time and animated time). for (UsdMayaPrimWriterSharedPtr& writer : _prototypeWriters) { writer->Write(usdTime); if (usdTime.IsDefault()) { // Prototype roots should have kind component or derived. // Calling Write() above may have populated kinds, so don't stomp // over existing component-derived kinds. // (Note that ModelKindWriter's fix-up stage might change this.) if (writer->GetUsdPath().GetParentPath() == prototypesGroupPath) { if (const UsdPrim writerPrim = writer->GetUsdPrim()) { UsdModelAPI primModelAPI(writerPrim); TfToken kind; primModelAPI.GetKind(&kind); if (!KindRegistry::IsA(kind, KindTokens->component)) { primModelAPI.SetKind(KindTokens->component); } } } } } // Write the instancerTranslate xformOp for all prims that need it. // (This should happen @ default time or animated time depending on whether // the xform is animated.) for (const _TranslateOpData& opData : _instancerTranslateOps) { if (opData.isAnimated != usdTime.IsDefault()) { GfVec3d origin; if (_GetTransformedOriginInLocalSpace(opData.mayaPath, &origin)) { UsdGeomXformOp translateOp = opData.op; _SetAttribute(translateOp.GetAttr(), -origin, usdTime); } } } // Grab the inputPoints data from the source plug. // (This attribute's value must come from a source plug; it isn't // directly writeable. Thus reading it directly may not give the right // value depending on Maya's execution behavior.) MPlug inputPointsDest = dagNode.findPlug("inputPoints", true, &status); CHECK_MSTATUS_AND_RETURN(status, false); MPlug inputPointsSrc = UsdMayaUtil::GetConnected(inputPointsDest); if (inputPointsSrc.isNull()) { TF_WARN("inputPoints not connected on instancer '%s'", GetDagPath().fullPathName().asChar()); return false; } auto holder = UsdMayaUtil::GetPlugDataHandle(inputPointsSrc); if (!holder) { TF_WARN("Unable to read inputPoints data handle for instancer '%s'", GetDagPath().fullPathName().asChar()); return false; } MFnArrayAttrsData inputPointsData(holder->GetDataHandle().data(), &status); CHECK_MSTATUS_AND_RETURN(status, false); if (!UsdMayaWriteUtil::WriteArrayAttrsToInstancer( inputPointsData, instancer, _numPrototypes, usdTime, _GetSparseValueWriter())) { return false; } // Load the completed point instancer to compute and set its extent. instancer.GetPrim().GetStage()->Load(instancer.GetPath()); VtArray<GfVec3f> extent(2); if (instancer.ComputeExtentAtTime(&extent, usdTime, usdTime)) { _SetAttribute(instancer.CreateExtentAttr(), &extent, usdTime); } return true; }
bool PxrUsdMayaWriteUtil::SetUsdAttr( const MPlug& attrPlug, const UsdAttribute& usdAttr, const UsdTimeCode& usdTime, const bool translateMayaDoubleToUsdSinglePrecision) { if (!usdAttr || attrPlug.isNull()) { return false; } bool isAnimated = attrPlug.isDestination(); if (usdTime.IsDefault() == isAnimated) { return true; } // We perform a similar set of type-infererence acrobatics here as we do up // above in GetUsdTypeName(). See the comments there for more detail on a // few type-related oddities. MObject attrObj(attrPlug.attribute()); if (attrObj.hasFn(MFn::kEnumAttribute)) { MFnEnumAttribute enumAttrFn(attrObj); const short enumIndex = attrPlug.asShort(); const TfToken enumToken(enumAttrFn.fieldName(enumIndex).asChar()); return usdAttr.Set(enumToken, usdTime); } MFnNumericData::Type numericDataType; MFnData::Type typedDataType; MFnUnitAttribute::Type unitDataType; _GetMayaAttributeNumericTypedAndUnitDataTypes(attrPlug, numericDataType, typedDataType, unitDataType); if (attrObj.hasFn(MFn::kMatrixAttribute)) { typedDataType = MFnData::kMatrix; } switch (typedDataType) { case MFnData::kString: { MFnStringData stringDataFn(attrPlug.asMObject()); const std::string usdVal(stringDataFn.string().asChar()); return usdAttr.Set(usdVal, usdTime); break; } case MFnData::kMatrix: { MFnMatrixData matrixDataFn(attrPlug.asMObject()); const GfMatrix4d usdVal(matrixDataFn.matrix().matrix); return usdAttr.Set(usdVal, usdTime); break; } case MFnData::kStringArray: { MFnStringArrayData stringArrayDataFn(attrPlug.asMObject()); VtStringArray usdVal(stringArrayDataFn.length()); for (unsigned int i = 0; i < stringArrayDataFn.length(); ++i) { usdVal[i] = std::string(stringArrayDataFn[i].asChar()); } return usdAttr.Set(usdVal, usdTime); break; } case MFnData::kDoubleArray: { MFnDoubleArrayData doubleArrayDataFn(attrPlug.asMObject()); if (translateMayaDoubleToUsdSinglePrecision) { VtFloatArray usdVal(doubleArrayDataFn.length()); for (unsigned int i = 0; i < doubleArrayDataFn.length(); ++i) { usdVal[i] = (float)doubleArrayDataFn[i]; } return usdAttr.Set(usdVal, usdTime); } else { VtDoubleArray usdVal(doubleArrayDataFn.length()); for (unsigned int i = 0; i < doubleArrayDataFn.length(); ++i) { usdVal[i] = doubleArrayDataFn[i]; } return usdAttr.Set(usdVal, usdTime); } break; } case MFnData::kFloatArray: { MFnFloatArrayData floatArrayDataFn(attrPlug.asMObject()); VtFloatArray usdVal(floatArrayDataFn.length()); for (unsigned int i = 0; i < floatArrayDataFn.length(); ++i) { usdVal[i] = floatArrayDataFn[i]; } return usdAttr.Set(usdVal, usdTime); break; } case MFnData::kIntArray: { MFnIntArrayData intArrayDataFn(attrPlug.asMObject()); VtIntArray usdVal(intArrayDataFn.length()); for (unsigned int i = 0; i < intArrayDataFn.length(); ++i) { usdVal[i] = intArrayDataFn[i]; } return usdAttr.Set(usdVal, usdTime); break; } case MFnData::kPointArray: { MFnPointArrayData pointArrayDataFn(attrPlug.asMObject()); if (translateMayaDoubleToUsdSinglePrecision) { VtVec3fArray usdVal(pointArrayDataFn.length()); for (unsigned int i = 0; i < pointArrayDataFn.length(); ++i) { MPoint tmpMayaVal = pointArrayDataFn[i]; if (tmpMayaVal.w != 0) { tmpMayaVal.cartesianize(); } usdVal[i] = GfVec3f((float)tmpMayaVal[0], (float)tmpMayaVal[1], (float)tmpMayaVal[2]); } return usdAttr.Set(usdVal, usdTime); } else { VtVec3dArray usdVal(pointArrayDataFn.length()); for (unsigned int i = 0; i < pointArrayDataFn.length(); ++i) { MPoint tmpMayaVal = pointArrayDataFn[i]; if (tmpMayaVal.w != 0) { tmpMayaVal.cartesianize(); } usdVal[i] = GfVec3d(tmpMayaVal[0], tmpMayaVal[1], tmpMayaVal[2]); } return usdAttr.Set(usdVal, usdTime); } break; } case MFnData::kVectorArray: { MFnVectorArrayData vectorArrayDataFn(attrPlug.asMObject()); if (translateMayaDoubleToUsdSinglePrecision) { VtVec3fArray usdVal(vectorArrayDataFn.length()); for (unsigned int i = 0; i < vectorArrayDataFn.length(); ++i) { MVector tmpMayaVal = vectorArrayDataFn[i]; usdVal[i] = GfVec3f((float)tmpMayaVal[0], (float)tmpMayaVal[1], (float)tmpMayaVal[2]); } return usdAttr.Set(usdVal, usdTime); } else { VtVec3dArray usdVal(vectorArrayDataFn.length()); for (unsigned int i = 0; i < vectorArrayDataFn.length(); ++i) { MVector tmpMayaVal = vectorArrayDataFn[i]; usdVal[i] = GfVec3d(tmpMayaVal[0], tmpMayaVal[1], tmpMayaVal[2]); } return usdAttr.Set(usdVal, usdTime); } break; } default: break; } switch (numericDataType) { case MFnNumericData::kBoolean: { const bool usdVal(attrPlug.asBool()); return usdAttr.Set(usdVal, usdTime); break; } case MFnNumericData::kByte: case MFnNumericData::kChar: { const int usdVal(attrPlug.asChar()); return usdAttr.Set(usdVal, usdTime); break; } case MFnNumericData::kShort: { const int usdVal(attrPlug.asShort()); return usdAttr.Set(usdVal, usdTime); break; } case MFnNumericData::kInt: { const int usdVal(attrPlug.asInt()); return usdAttr.Set(usdVal, usdTime); break; } case MFnNumericData::k2Short: { short tmp1, tmp2; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2); return usdAttr.Set(GfVec2i(tmp1, tmp2), usdTime); break; } case MFnNumericData::k2Int: { int tmp1, tmp2; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2); return usdAttr.Set(GfVec2i(tmp1, tmp2), usdTime); break; } case MFnNumericData::k3Short: { short tmp1, tmp2, tmp3; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2, tmp3); return usdAttr.Set(GfVec3i(tmp1, tmp2, tmp3), usdTime); break; } case MFnNumericData::k3Int: { int tmp1, tmp2, tmp3; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2, tmp3); return usdAttr.Set(GfVec3i(tmp1, tmp2, tmp3), usdTime); break; } case MFnNumericData::kFloat: { const float usdVal(attrPlug.asFloat()); return usdAttr.Set(usdVal, usdTime); break; } case MFnNumericData::k2Float: { float tmp1, tmp2; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2); return usdAttr.Set(GfVec2f(tmp1, tmp2), usdTime); break; } case MFnNumericData::k3Float: { float tmp1, tmp2, tmp3; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2, tmp3); return _SetVec(usdAttr, GfVec3f(tmp1, tmp2, tmp3), usdTime); break; } case MFnNumericData::kDouble: { const double usdVal(attrPlug.asDouble()); if (translateMayaDoubleToUsdSinglePrecision) { return usdAttr.Set((float)usdVal, usdTime); } else { return usdAttr.Set(usdVal, usdTime); } break; } case MFnNumericData::k2Double: { double tmp1, tmp2; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2); if (translateMayaDoubleToUsdSinglePrecision) { return usdAttr.Set(GfVec2f((float)tmp1, (float)tmp2), usdTime); } else { return usdAttr.Set(GfVec2d(tmp1, tmp2), usdTime); } break; } case MFnNumericData::k3Double: { double tmp1, tmp2, tmp3; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2, tmp3); if (translateMayaDoubleToUsdSinglePrecision) { return _SetVec(usdAttr, GfVec3f((float)tmp1, (float)tmp2, (float)tmp3), usdTime); } else { return _SetVec(usdAttr, GfVec3d(tmp1, tmp2, tmp3), usdTime); } break; } case MFnNumericData::k4Double: { double tmp1, tmp2, tmp3, tmp4; MFnNumericData numericDataFn(attrPlug.asMObject()); numericDataFn.getData(tmp1, tmp2, tmp3, tmp4); if (translateMayaDoubleToUsdSinglePrecision) { return _SetVec(usdAttr, GfVec4f((float)tmp1, (float)tmp2, (float)tmp3, (float)tmp4), usdTime); } else { return _SetVec(usdAttr, GfVec4d(tmp1, tmp2, tmp3, tmp4), usdTime); } break; } default: break; } switch (unitDataType) { case MFnUnitAttribute::kAngle: case MFnUnitAttribute::kDistance: if (translateMayaDoubleToUsdSinglePrecision) { const float usdVal(attrPlug.asFloat()); return usdAttr.Set(usdVal, usdTime); } else { const double usdVal(attrPlug.asDouble()); return usdAttr.Set(usdVal, usdTime); } break; default: break; } return false; }
bool PxrUsdMayaWriteUtil::SetUsdAttr( const MPlug &plg, const UsdAttribute& usdAttr, const UsdTimeCode &usdTime) { MStatus status; if (!usdAttr || plg.isNull() ) { return false; } bool isAnimated = plg.isDestination(); if (usdTime.IsDefault() == isAnimated ) { return true; } // Set UsdAttr MObject attrObj = plg.attribute(); if (attrObj.hasFn(MFn::kNumericAttribute)) { MFnNumericAttribute attrNumericFn(attrObj); switch (attrNumericFn.unitType()) { case MFnNumericData::kBoolean: usdAttr.Set(plg.asBool(), usdTime); break; case MFnNumericData::kByte: case MFnNumericData::kChar: usdAttr.Set((int)plg.asChar(), usdTime); break; case MFnNumericData::kShort: usdAttr.Set(int(plg.asShort()), usdTime); break; case MFnNumericData::kInt: usdAttr.Set(int(plg.asInt()), usdTime); break; //case MFnNumericData::kLong: //case MFnNumericData::kAddr: // usdAttr.Set(plg.asInt(), usdTime); // break; case MFnNumericData::kFloat: usdAttr.Set(plg.asFloat(), usdTime); break; case MFnNumericData::kDouble: usdAttr.Set(plg.asDouble(), usdTime); break; case MFnNumericData::k2Short: { short tmp1, tmp2; MFnNumericData attrNumericDataFn(plg.asMObject()); attrNumericDataFn.getData(tmp1, tmp2); usdAttr.Set(GfVec2i(tmp1, tmp2), usdTime); break; } case MFnNumericData::k2Int: { int tmp1, tmp2; MFnNumericData attrNumericDataFn(plg.asMObject()); attrNumericDataFn.getData(tmp1, tmp2); usdAttr.Set(GfVec2i(tmp1, tmp2), usdTime); break; } //case MFnNumericData::k2Long: case MFnNumericData::k3Short: { short tmp1, tmp2, tmp3; MFnNumericData attrNumericDataFn(plg.asMObject()); attrNumericDataFn.getData(tmp1, tmp2, tmp3); usdAttr.Set(GfVec3i(tmp1, tmp2, tmp3), usdTime); break; } case MFnNumericData::k3Int: { int tmp1, tmp2, tmp3; MFnNumericData attrNumericDataFn(plg.asMObject()); attrNumericDataFn.getData(tmp1, tmp2, tmp3); usdAttr.Set(GfVec3i(tmp1, tmp2, tmp3), usdTime); break; } //case MFnNumericData::k3Long: case MFnNumericData::k2Float: { float tmp1, tmp2; MFnNumericData attrNumericDataFn(plg.asMObject()); attrNumericDataFn.getData(tmp1, tmp2); usdAttr.Set(GfVec2f(tmp1, tmp2), usdTime); break; } case MFnNumericData::k3Float: { float tmp1, tmp2, tmp3; MFnNumericData attrNumericDataFn(plg.asMObject()); attrNumericDataFn.getData(tmp1, tmp2, tmp3); _SetVec(usdAttr, GfVec3f(tmp1, tmp2, tmp3), usdTime); break; } case MFnNumericData::k2Double: { double tmp1, tmp2; MFnNumericData attrNumericDataFn(plg.asMObject()); attrNumericDataFn.getData(tmp1, tmp2); usdAttr.Set(GfVec2d(tmp1, tmp2), usdTime); break; } case MFnNumericData::k3Double: { double tmp1, tmp2, tmp3; MFnNumericData attrNumericDataFn(plg.asMObject()); attrNumericDataFn.getData(tmp1, tmp2, tmp3); _SetVec(usdAttr, GfVec3d(tmp1, tmp2, tmp3), usdTime); break; } case MFnNumericData::k4Double: { double tmp1, tmp2, tmp3, tmp4; MFnNumericData attrNumericDataFn(plg.asMObject()); attrNumericDataFn.getData(tmp1, tmp2, tmp3, tmp4); _SetVec(usdAttr, GfVec4d(tmp1, tmp2, tmp3, tmp4), usdTime); break; } default: return false; } } else if (attrObj.hasFn(MFn::kTypedAttribute)) { MFnTypedAttribute attrTypedFn(attrObj); switch (attrTypedFn.attrType()) { case MFnData::kString: usdAttr.Set(std::string(plg.asString().asChar()), usdTime); break; case MFnData::kMatrix: { MFnMatrixData attrMatrixDataFn(plg.asMObject()); MMatrix mat1 = attrMatrixDataFn.matrix(); usdAttr.Set(GfMatrix4d(mat1.matrix), usdTime); break; } case MFnData::kStringArray: { MFnStringArrayData attrDataFn(plg.asMObject()); VtArray<std::string> usdVal(attrDataFn.length()); for (unsigned int i=0; i < attrDataFn.length(); i++) { usdVal[i] = std::string(attrDataFn[i].asChar()); } usdAttr.Set(usdVal, usdTime); break; } case MFnData::kIntArray: { MFnIntArrayData attrDataFn(plg.asMObject()); VtArray<int> usdVal(attrDataFn.length()); for (unsigned int i=0; i < attrDataFn.length(); i++) { usdVal[i] = attrDataFn[i]; } usdAttr.Set(usdVal, usdTime); break; } case MFnData::kFloatArray: { MFnFloatArrayData attrDataFn(plg.asMObject()); VtArray<float> usdVal(attrDataFn.length()); for (unsigned int i=0; i < attrDataFn.length(); i++) { usdVal[i] = attrDataFn[i]; } usdAttr.Set(usdVal, usdTime); break; } case MFnData::kDoubleArray: { MFnDoubleArrayData attrDataFn(plg.asMObject()); VtArray<double> usdVal(attrDataFn.length()); for (unsigned int i=0; i < attrDataFn.length(); i++) { usdVal[i] = attrDataFn[i]; } usdAttr.Set(usdVal, usdTime); break; } case MFnData::kVectorArray: { MFnVectorArrayData attrDataFn(plg.asMObject()); VtArray<GfVec3d> usdVal(attrDataFn.length()); for (unsigned int i=0; i < attrDataFn.length(); i++) { MVector tmpMayaVal = attrDataFn[i]; usdVal[i] = GfVec3d(tmpMayaVal[0], tmpMayaVal[1], tmpMayaVal[2]); } usdAttr.Set(usdVal, usdTime); break; } case MFnData::kPointArray: { MFnPointArrayData attrDataFn(plg.asMObject()); VtArray<GfVec4d> usdVal(attrDataFn.length()); for (unsigned int i=0; i < attrDataFn.length(); i++) { MPoint tmpMayaVal = attrDataFn[i]; usdVal[i] = GfVec4d(tmpMayaVal[0], tmpMayaVal[1], tmpMayaVal[2], tmpMayaVal[3]); } usdAttr.Set(usdVal, usdTime); break; } default: return false; } } else if (attrObj.hasFn(MFn::kUnitAttribute)) { //MFnUnitAttribute attrUnitFn(attrObj); return false; } else if (attrObj.hasFn(MFn::kEnumAttribute)) { MFnEnumAttribute attrEnumFn(attrObj); short enumIndex = plg.asShort(); TfToken enumToken( std::string(attrEnumFn.fieldName(enumIndex, &status).asChar()) ); usdAttr.Set(enumToken, usdTime); return false; } return true; }
/* virtual */ bool MayaCameraWriter::writeCameraAttrs(const UsdTimeCode &usdTime, UsdGeomCamera &primSchema) { // Since write() above will take care of any animation on the camera's // transform, we only want to proceed here if: // - We are at the default time and NO attributes on the shape are animated. // OR // - We are at a non-default time and some attribute on the shape IS animated. if (usdTime.IsDefault() == isShapeAnimated()) { return true; } MStatus status; MFnCamera camFn(getDagPath(), &status); CHECK_MSTATUS_AND_RETURN(status, false); // NOTE: We do not use a GfCamera and then call SetFromCamera() below // because we want the xformOps populated by the parent class to survive. // Using SetFromCamera() would stomp them with a single "transform" xformOp. // Set the type of projection. if (camFn.isOrtho()) { primSchema.GetProjectionAttr().Set(UsdGeomTokens->orthographic, usdTime); } else { primSchema.GetProjectionAttr().Set(UsdGeomTokens->perspective, usdTime); } // Setup the aperture. primSchema.GetHorizontalApertureAttr().Set( float(PxrUsdMayaUtil::ConvertInchesToMM( camFn.horizontalFilmAperture() * camFn.lensSqueezeRatio())), usdTime); primSchema.GetVerticalApertureAttr().Set( float(PxrUsdMayaUtil::ConvertInchesToMM( camFn.verticalFilmAperture() * camFn.lensSqueezeRatio())), usdTime); primSchema.GetHorizontalApertureOffsetAttr().Set( float(camFn.horizontalFilmOffset()), usdTime); primSchema.GetVerticalApertureOffsetAttr().Set( float(camFn.verticalFilmOffset()), usdTime); // Set the lens parameters. primSchema.GetFocalLengthAttr().Set( float(camFn.focalLength()), usdTime); // Always export focus distance and fStop regardless of what // camFn.isDepthOfField() says. Downstream tools can choose to ignore or // override them. primSchema.GetFocusDistanceAttr().Set( float(camFn.focusDistance()), usdTime); primSchema.GetFStopAttr().Set( float(camFn.fStop()), usdTime); // Set the clipping planes. GfVec2f clippingRange(camFn.nearClippingPlane(), camFn.farClippingPlane()); primSchema.GetClippingRangeAttr().Set(clippingRange, usdTime); return true; }