static bool _TranslateUsdAttributeToPlug( const UsdAttribute& usdAttr, const MFnCamera& cameraFn, TfToken plugName, const PxrUsdMayaPrimReaderArgs& args, PxrUsdMayaPrimReaderContext* context, bool millimetersToInches=false) { MStatus status; MPlug plug = cameraFn.findPlug(plugName.GetText(), true, &status); CHECK_MSTATUS_AND_RETURN(status, false); // First check for and translate animation if there is any. if (!_TranslateAnimatedUsdAttributeToPlug(usdAttr, plug, args, context, millimetersToInches)) { // If that fails, then try just setting a static value. UsdTimeCode timeCode = UsdTimeCode::EarliestTime(); float attrValue; usdAttr.Get(&attrValue, timeCode); if (millimetersToInches) { attrValue = PxrUsdMayaUtil::ConvertMMToInches(attrValue); } status = plug.setFloat(attrValue); CHECK_MSTATUS_AND_RETURN(status, false); } return true; }
/* static */ bool UsdMayaTranslatorCamera::Read( const UsdGeomCamera& usdCamera, MObject parentNode, const UsdMayaPrimReaderArgs& args, UsdMayaPrimReaderContext* context) { if (!usdCamera) { return false; } const UsdPrim& prim = usdCamera.GetPrim(); const SdfPath primPath = prim.GetPath(); MStatus status; // Create the transform node for the camera. MObject transformObj; if (!UsdMayaTranslatorUtil::CreateTransformNode(prim, parentNode, args, context, &status, &transformObj)) { return false; } // Create the camera shape node. MDagModifier dagMod; MObject cameraObj = dagMod.createNode(_tokens->MayaCameraTypeName.GetText(), transformObj, &status); CHECK_MSTATUS_AND_RETURN(status, false); status = dagMod.doIt(); CHECK_MSTATUS_AND_RETURN(status, false); TF_VERIFY(!cameraObj.isNull()); MFnCamera cameraFn(cameraObj, &status); CHECK_MSTATUS_AND_RETURN(status, false); const std::string cameraShapeName = prim.GetName().GetString() + _tokens->MayaCameraShapeNameSuffix.GetString(); cameraFn.setName(cameraShapeName.c_str(), &status); CHECK_MSTATUS_AND_RETURN(status, false); if (context) { const SdfPath shapePrimPath = primPath.AppendChild(TfToken(cameraShapeName)); context->RegisterNewMayaNode(shapePrimPath.GetString(), cameraObj); } return _ReadToCamera(usdCamera, cameraFn, args, context); }
MSyntax RadiosityRenderer::newSyntax() { MStatus status; MSyntax syntax; syntax.addFlag( kDoNotClearBackground, kDoNotClearBackgroundLong ); CHECK_MSTATUS_AND_RETURN(status, syntax); return syntax; }
MSyntax renderViewRenderRegion::newSyntax() { MStatus status; MSyntax syntax; syntax.addFlag( kDoNotClearBackground, kDoNotClearBackgroundLong ); CHECK_MSTATUS_AND_RETURN(status, syntax); return syntax; }
// // Add additionnal flags for this command. The default setting of the // syntax is done in the base class. /////////////////////////////////////////////////////////////////////////////// MSyntax flipUVCmd::newSyntax () { MStatus status; // Get the base class syntax, and append to it. MSyntax syntax = MPxPolyTweakUVCommand::newSyntax(); status = syntax.addFlag(horizFlag, horizFlagLong, MSyntax::kBoolean); CHECK_MSTATUS_AND_RETURN(status, syntax); status = syntax.addFlag(globalFlag, globalFlagLong, MSyntax::kBoolean); CHECK_MSTATUS_AND_RETURN(status, syntax); status = syntax.addFlag(extendFlag, extendFlagLong, MSyntax::kBoolean); CHECK_MSTATUS_AND_RETURN(status, syntax); return syntax; }
static bool _TranslateUsdAttributeToPlug( const UsdAttribute& usdAttr, const MFnCamera& cameraFn, const TfToken& plugName, const UsdMayaPrimReaderArgs& args, UsdMayaPrimReaderContext* context, const MDistance::Unit convertToUnit = MDistance::kMillimeters) { MStatus status; MPlug plug = cameraFn.findPlug(plugName.GetText(), true, &status); CHECK_MSTATUS_AND_RETURN(status, false); // First check for and translate animation if there is any. if (!_TranslateAnimatedUsdAttributeToPlug(usdAttr, plug, args, context, convertToUnit)) { // If that fails, then try just setting a static value. UsdTimeCode timeCode = UsdTimeCode::EarliestTime(); float attrValue; usdAttr.Get(&attrValue, timeCode); switch (convertToUnit) { case MDistance::kInches: attrValue = UsdMayaUtil::ConvertMMToInches(attrValue); break; case MDistance::kCentimeters: attrValue = UsdMayaUtil::ConvertMMToCM(attrValue); break; default: // The input is expected to be in millimeters. break; } status = plug.setFloat(attrValue); CHECK_MSTATUS_AND_RETURN(status, false); } return true; }
MLL_EXPORT MStatus uninitializePlugin( MObject object ) { MStatus status; MFnPlugin plugin( object ); status = plugin.deregisterFileTranslator( MeshExport::m_name ); CHECK_MSTATUS_AND_RETURN( status, status ); return status; }
MSyntax TransferUV::newSyntax() { MSyntax syntax; MStatus status; status = syntax.addFlag(sourceUvSetFlag, sourceUvSetFlagLong, MSyntax::kString); CHECK_MSTATUS_AND_RETURN(status, syntax); status = syntax.addFlag(targetUvSetFlag, targetUvSetFlagLong, MSyntax::kString); CHECK_MSTATUS_AND_RETURN(status, syntax); status = syntax.addFlag(sourceMeshFlag, sourceMeshFlagLong, MSyntax::kString); CHECK_MSTATUS_AND_RETURN(status, syntax); status = syntax.addFlag(targetMeshFlag, targetMeshFlagLong, MSyntax::kString); CHECK_MSTATUS_AND_RETURN(status, syntax); return syntax; }
static bool _CreateAnimCurveForPlug( MPlug& plug, MTimeArray& timeArray, MDoubleArray& valueArray, UsdMayaPrimReaderContext* context) { MFnAnimCurve animFn; MStatus status; MObject animObj = animFn.create(plug, nullptr, &status); CHECK_MSTATUS_AND_RETURN(status, false); status = animFn.addKeys(&timeArray, &valueArray); CHECK_MSTATUS_AND_RETURN(status, false); if (context) { // used for undo/redo context->RegisterNewMayaNode(animFn.name().asChar(), animObj); } return true; }
MSyntax renderViewInteractiveRender::newSyntax() { MStatus status; MSyntax syntax; syntax.addFlag(kDoNotClearBackground, kDoNotClearBackgroundLong); CHECK_MSTATUS_AND_RETURN(status, syntax); syntax.addFlag(kVerbose, kVerboseLong); CHECK_MSTATUS_AND_RETURN(status, syntax); syntax.addFlag(kImmediateRefresh, kImmediateRefreshLong); CHECK_MSTATUS_AND_RETURN(status, syntax); syntax.addFlag(kFullRefresh, kFullRefreshLong); CHECK_MSTATUS_AND_RETURN(status, syntax); syntax.addFlag(kRadius, kRadiusLong, MSyntax::kDouble); CHECK_MSTATUS_AND_RETURN(status, syntax); syntax.addFlag(kSizeX, kSizeXLong, MSyntax::kLong); CHECK_MSTATUS_AND_RETURN(status, syntax); syntax.addFlag(kSizeY, kSizeYLong, MSyntax::kLong); CHECK_MSTATUS_AND_RETURN(status, syntax); syntax.addFlag(kSizeTileX, kSizeTileXLong, MSyntax::kLong); CHECK_MSTATUS_AND_RETURN(status, syntax); syntax.addFlag(kSizeTileY, kSizeTileYLong, MSyntax::kLong); CHECK_MSTATUS_AND_RETURN(status, syntax); syntax.addFlag(kNumberLoops, kNumberLoopsLong, MSyntax::kLong); CHECK_MSTATUS_AND_RETURN(status, syntax); return syntax; }
bool _ReadToCamera( const UsdGeomCamera& usdCamera, MFnCamera& cameraFn, const UsdMayaPrimReaderArgs& args, UsdMayaPrimReaderContext* context) { MStatus status; // Now translate all of the USD camera attributes over to plugs on the // Maya cameraFn. UsdTimeCode timeCode = UsdTimeCode::EarliestTime(); UsdAttribute usdAttr; TfToken plugName; // Set the type of projection. This is NOT keyable in Maya. TfToken projection; usdCamera.GetProjectionAttr().Get(&projection, timeCode); const bool isOrthographic = (projection == UsdGeomTokens->orthographic); status = cameraFn.setIsOrtho(isOrthographic); CHECK_MSTATUS_AND_RETURN(status, false); // Setup the aperture. usdAttr = usdCamera.GetHorizontalApertureAttr(); plugName = _tokens->MayaCameraAttrNameHorizontalAperture; if (!_TranslateUsdAttributeToPlug(usdAttr, cameraFn, plugName, args, context, /* convertToUnit = */ MDistance::kInches)) { return false; } if (isOrthographic) { // For orthographic cameras, we'll re-use the horizontal aperture value // to fill in Maya's orthographicWidth. The film aperture and film // aperture offset plugs in Maya have no effect on orthographic cameras, // but we author them anyway so that the data is preserved. Note also // that Maya stores the orthographicWidth as centimeters. plugName = _tokens->MayaCameraAttrNameOrthographicWidth; if (!_TranslateUsdAttributeToPlug(usdAttr, cameraFn, plugName, args, context, /* convertToUnit = */ MDistance::kCentimeters)) { return false; } } usdAttr = usdCamera.GetVerticalApertureAttr(); plugName = _tokens->MayaCameraAttrNameVerticalAperture; if (!_TranslateUsdAttributeToPlug(usdAttr, cameraFn, plugName, args, context, /* convertToUnit = */ MDistance::kInches)) { return false; } // XXX: // Lens Squeeze Ratio is DEPRECATED on USD schema. // Writing it out here for backwards compatibility (see bug 123124). cameraFn.setLensSqueezeRatio(1.0); usdAttr = usdCamera.GetHorizontalApertureOffsetAttr(); plugName = _tokens->MayaCameraAttrNameHorizontalApertureOffset; if (!_TranslateUsdAttributeToPlug(usdAttr, cameraFn, plugName, args, context, /* convertToUnit = */ MDistance::kInches)) { return false; } usdAttr = usdCamera.GetVerticalApertureOffsetAttr(); plugName = _tokens->MayaCameraAttrNameVerticalApertureOffset; if (!_TranslateUsdAttributeToPlug(usdAttr, cameraFn, plugName, args, context, /* convertToUnit = */ MDistance::kInches)) { return false; } // Set the lens parameters. usdAttr = usdCamera.GetFocalLengthAttr(); plugName = _tokens->MayaCameraAttrNameFocalLength; if (!_TranslateUsdAttributeToPlug(usdAttr, cameraFn, plugName, args, context)) { return false; } usdAttr = usdCamera.GetFocusDistanceAttr(); plugName = _tokens->MayaCameraAttrNameFocusDistance; if (!_TranslateUsdAttributeToPlug(usdAttr, cameraFn, plugName, args, context)) { return false; } usdAttr = usdCamera.GetFStopAttr(); plugName = _tokens->MayaCameraAttrNameFStop; if (!_TranslateUsdAttributeToPlug(usdAttr, cameraFn, plugName, args, context)) { return false; } // Set the clipping planes. This one is a little different from the others // because it is stored in USD as a single GfVec2f value but in Maya as // separate nearClipPlane and farClipPlane attributes. usdAttr = usdCamera.GetClippingRangeAttr(); MPlug nearClipPlug = cameraFn.findPlug( _tokens->MayaCameraAttrNameNearClippingPlane.GetText(), true, &status); CHECK_MSTATUS_AND_RETURN(status, false); MPlug farClipPlug = cameraFn.findPlug( _tokens->MayaCameraAttrNameFarClippingPlane.GetText(), true, &status); CHECK_MSTATUS_AND_RETURN(status, false); if (!_TranslateAnimatedUsdAttributeToPlugs(usdAttr, nearClipPlug, farClipPlug, args, context)) { GfVec2f clippingRange; usdCamera.GetClippingRangeAttr().Get(&clippingRange, timeCode); status = cameraFn.setNearClippingPlane(clippingRange[0]); CHECK_MSTATUS_AND_RETURN(status, false); status = cameraFn.setFarClippingPlane(clippingRange[1]); CHECK_MSTATUS_AND_RETURN(status, 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 preFrame( const MObject hairSystem, const double curTime, void **privateData ) { MStatus status; // If you need want to perform any preprocessing on your collision // objects pre-frame, do it here. One option for storing the pre- // processed data is on a typed attribute on the hairSystem node. // That data could be fetched and updated here. // // In our example, we'll just compute a bounding box here and NOT use // attribute storage. That is an exercise for the reader. // MFnDependencyNode fnHairSystem( hairSystem, &status ); CHECK_MSTATUS_AND_RETURN( status, false ); fprintf( stderr, "preFrame: calling hairSystem node=`%s', time=%g\n", fnHairSystem.name().asChar(), curTime ); MObjectArray cols; MIntArray logIdxs; CHECK_MSTATUS_AND_RETURN( MHairSystem::getCollisionObject( hairSystem, cols, logIdxs ), false ); int nobj = cols.length(); // Allocate private data. // This allows us to pre-process data on a pre-frame basis to avoid // calculating it per hair inside the collide() call. As noted earlier // we could allocate this in preFrame() and hang it off the hairSystem // node via a dynamic attribute. // Instead we'll allocate it here. // COLLISION_INFO *collisionInfo = (COLLISION_INFO *) malloc( sizeof( COLLISION_INFO ) ); collisionInfo->objs = (COLLISION_OBJ *) malloc( nobj * sizeof( COLLISION_OBJ ) ); collisionInfo->numObjs = nobj; // Create the private data that we'll make available to the collide // method. The data should actually be stored in a way that it can // be cleaned up (such as storing the pointer on the hairSystem node // using a dynamic attribute). As it stands right now, there is a // memory leak with this plug-in because the memory we're allocating // for the private data is never cleaned up. // // Note that when using the dynamic attribute approach, it is still // wise to set *privateData because this avoids the need to look up // the plug inside the collide() routine which is a high-traffic // method. // *privateData = (void *) collisionInfo; // Loop through the collision objects and pre-process, storing the // results in the collisionInfo structure. // int obj; for ( obj = 0; obj < nobj; ++obj ) { // Get the ith collision geometry we are connected to. // MObject colObj = cols[obj]; // Get the DAG path for the collision object so we can transform // the vertices to world space. // MFnDagNode fnDagNode( colObj, &status ); CHECK_MSTATUS_AND_RETURN( status, false ); MDagPath path; status = fnDagNode.getPath( path ); CHECK_MSTATUS_AND_RETURN( status, false ); MFnMesh fnMesh( path, &status ); if ( MS::kSuccess != status ) { fprintf( stderr, "%s:%d: collide was not passed a valid mesh shape\n", __FILE__, __LINE__ ); return( false ); } // Get the vertices of the object transformed to world space. // MFloatPointArray verts; status = fnMesh.getPoints( verts, MSpace::kWorld ); CHECK_MSTATUS_AND_RETURN( status, false ); // Compute the bounding box for the collision object. // As this is a quick and dirty demo, we'll just support collisions // between hair and the bbox. // double minx, miny, minz, maxx, maxy, maxz, x, y, z; minx = maxx = verts[0].x; miny = maxy = verts[0].y; minz = maxz = verts[0].z; int nv = verts.length(); int i; for ( i = 1; i < nv; ++i ) { x = verts[i].x; y = verts[i].y; z = verts[i].z; if ( x < minx ) { minx = x; } if ( y < miny ) { miny = y; } if ( z < minz ) { minz = z; } if ( x > maxx ) { maxx = x; } if ( y > maxy ) { maxy = y; } if ( z > maxz ) { maxz = z; } } // Store this precomputed informantion into our private data // structure. // collisionInfo->objs[obj].numVerts = nv; collisionInfo->objs[obj].minx = minx; collisionInfo->objs[obj].miny = miny; collisionInfo->objs[obj].minz = minz; collisionInfo->objs[obj].maxx = maxx; collisionInfo->objs[obj].maxy = maxy; collisionInfo->objs[obj].maxz = maxz; fprintf( stderr, "Inside preFrameInit, bbox=%g %g %g %g %g %g\n", minx,miny,minz,maxx,maxy,maxz); } 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; }