diff --git a/src/experimental/usd/plugins/mjcf/mjcf_file_format.cc b/src/experimental/usd/plugins/mjcf/mjcf_file_format.cc index f9c78252..4fcdc505 100644 --- a/src/experimental/usd/plugins/mjcf/mjcf_file_format.cc +++ b/src/experimental/usd/plugins/mjcf/mjcf_file_format.cc @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -236,13 +237,15 @@ bool UsdMjcfFileFormat::ReadImpl(pxr::SdfLayer *layer, mjSpec *spec) const { auto args = layer->GetFileFormatArguments(); auto data = InitData(args); - auto success = mujoco::usd::WriteSpecToData(spec, data); + pxr::SdfChangeBlock block; + pxr::SdfLayerRefPtr spec_layer = pxr::SdfLayer::CreateAnonymous(); + auto success = mujoco::usd::WriteSpecToData(spec, spec_layer); mj_deleteSpec(spec); if (!success) { return false; } - _SetLayerData(layer, data); + layer->TransferContent(spec_layer); return true; } diff --git a/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc b/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc index 4a444914..8c268618 100644 --- a/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc +++ b/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -153,7 +154,6 @@ using mujoco::usd::SetAttributeMetadata; using mujoco::usd::SetAttributeTimeSample; using mujoco::usd::SetLayerMetadata; using mujoco::usd::SetPrimKind; -using mujoco::usd::SetPrimMetadata; using mujoco::usd::SetPrimPurpose; pxr::GfMatrix4d MujocoPosQuatToTransform(double *pos, double *quat) { @@ -174,8 +174,8 @@ pxr::GfMatrix4d MujocoPosQuatToTransform(double *pos, double *quat) { class ModelWriter { public: - ModelWriter(mjSpec *spec, mjModel *model, pxr::SdfAbstractDataRefPtr &data) - : spec_(spec), model_(model), data_(data), class_path_("/Bad_Path") { + ModelWriter(mjSpec *spec, mjModel *model, pxr::SdfLayerRefPtr layer) + : spec_(spec), model_(model), layer_(layer), class_path_("/Bad_Path") { body_paths_ = std::vector(model->nbody); site_paths_ = std::vector(model->nsite); joint_paths_ = std::vector(model->njnt); @@ -184,23 +184,20 @@ class ModelWriter { void Write() { // Create top level class holder. - class_path_ = CreateClassSpec(data_, pxr::SdfPath::AbsoluteRootPath(), - pxr::TfToken("__class__")); + class_path_ = CreateClassSpec(layer_, pxr::SdfPath::AbsoluteRootPath(), + pxr::TfToken("__class__"))->GetPath(); // Create the world body. - body_paths_[kWorldIndex] = WriteWorldBody(kWorldIndex); - - SetLayerMetadata(data_, pxr::SdfFieldKeys->Documentation, - "Generated by mujoco model writer."); - // Mujoco is Z up by default. - SetLayerMetadata(data_, pxr::UsdGeomTokens->upAxis, pxr::UsdGeomTokens->z); - // Mujoco is authored in meters by default. - SetLayerMetadata(data_, pxr::UsdGeomTokens->metersPerUnit, - pxr::UsdGeomLinearUnits::meters); + body_paths_[kWorldIndex] = WriteWorldBody(kWorldIndex)->GetPath(); + layer_->SetDocumentation("Generated by mujoco model writer."); // Set the world body to be the default prim for referencing/payloads. - SetLayerMetadata(data_, pxr::SdfFieldKeys->DefaultPrim, - body_paths_[kWorldIndex].GetNameToken()); + layer_->SetDefaultPrim(body_paths_[kWorldIndex].GetNameToken()); + // Mujoco is Z up by default. + SetLayerMetadata(layer_, pxr::UsdGeomTokens->upAxis, pxr::UsdGeomTokens->z); + // Mujoco is authored in meters by default. + SetLayerMetadata(layer_, pxr::UsdGeomTokens->metersPerUnit, + pxr::UsdGeomLinearUnits::meters); WritePhysicsScene(); @@ -215,10 +212,8 @@ class ModelWriter { private: mjSpec *spec_; mjModel *model_; + pxr::SdfLayerRefPtr layer_; - // This is a handle to the Sdf data to be written into the generated USD - // layer. - pxr::SdfAbstractDataRefPtr &data_; // Path to top level class spec that all classes should be children of. pxr::SdfPath class_path_; // Mapping from Mujoco body id to SdfPath. @@ -257,8 +252,8 @@ class ModelWriter { std::string name = valid_base_name; pxr::SdfPath test_path = parent_path.AppendChild(pxr::TfToken(name)); int count = 1; - while (data_->HasSpec(test_path) && - data_->GetSpecType(test_path) == pxr::SdfSpecType::SdfSpecTypePrim) { + while (layer_->HasSpec(test_path) && + layer_->GetSpecType(test_path) == pxr::SdfSpecType::SdfSpecTypePrim) { name = pxr::TfStringPrintf("%s_%d", valid_base_name.c_str(), count++); test_path = parent_path.AppendChild(pxr::TfToken(name)); } @@ -277,41 +272,41 @@ class ModelWriter { pxr::TfToken body_name; }; - void WriteScaleXformOp(const pxr::SdfPath &prim_path, + void WriteScaleXformOp(const pxr::SdfPrimSpecHandle prim_spec, const pxr::GfVec3f &scale) { - pxr::SdfPath scale_attr_path = - CreateAttributeSpec(data_, prim_path, kTokens->xformOpScale, + auto scale_attr_spec = + CreateAttributeSpec(layer_, prim_spec, kTokens->xformOpScale, pxr::SdfValueTypeNames->Float3); - SetAttributeDefault(data_, scale_attr_path, scale); + SetAttributeDefault(layer_, scale_attr_spec, scale); } - void WriteTransformXformOp(const pxr::SdfPath &prim_path, + void WriteTransformXformOp(const pxr::SdfPrimSpecHandle prim_spec, const pxr::GfMatrix4d &transform) { - pxr::SdfPath transform_op_path = - CreateAttributeSpec(data_, prim_path, kTokens->xformOpTransform, + auto transform_op_spec = + CreateAttributeSpec(layer_, prim_spec, kTokens->xformOpTransform, pxr::SdfValueTypeNames->Matrix4d); - SetAttributeDefault(data_, transform_op_path, transform); + SetAttributeDefault(layer_, transform_op_spec, transform); } - void WriteXformOpOrder(const pxr::SdfPath &prim_path, + void WriteXformOpOrder(const pxr::SdfPrimSpecHandle prim_spec, const pxr::VtArray &order) { - pxr::SdfPath xform_op_order_path = - CreateAttributeSpec(data_, prim_path, pxr::UsdGeomTokens->xformOpOrder, + auto xform_op_order_spec = + CreateAttributeSpec(layer_, prim_spec, pxr::UsdGeomTokens->xformOpOrder, pxr::SdfValueTypeNames->TokenArray); - SetAttributeDefault(data_, xform_op_order_path, order); + SetAttributeDefault(layer_, xform_op_order_spec, order); } template - void WriteUniformAttribute(const pxr::SdfPath &prim_path, + void WriteUniformAttribute(const pxr::SdfPrimSpecHandle prim_spec, const pxr::SdfValueTypeName &value_type_name, const pxr::TfToken &token, const T &value) { - pxr::SdfPath attr_path = CreateAttributeSpec( - data_, prim_path, token, value_type_name, pxr::SdfVariabilityUniform); - SetAttributeDefault(data_, attr_path, value); + auto attr_spec = CreateAttributeSpec( + layer_, prim_spec, token, value_type_name, pxr::SdfVariabilityUniform); + SetAttributeDefault(layer_, attr_spec, value); } template - void WriteColorAndOpacityAttributes(const pxr::SdfPath &prim_path, + void WriteColorAndOpacityAttributes(const pxr::SdfPrimSpecHandle prim_spec, const T &element) { // If rgba is not the default (0.5, 0.5, 0.5, 1), then set the // displayColor attribute. @@ -320,56 +315,56 @@ class ModelWriter { if (element->rgba[0] != 0.5f || element->rgba[1] != 0.5f || element->rgba[2] != 0.5f || element->rgba[3] != 1.0f) { // Set the displayColor attribute. - pxr::SdfPath display_color_attr = CreateAttributeSpec( - data_, prim_path, pxr::UsdGeomTokens->primvarsDisplayColor, + auto display_color_attr = CreateAttributeSpec( + layer_, prim_spec, pxr::UsdGeomTokens->primvarsDisplayColor, pxr::SdfValueTypeNames->Color3fArray); SetAttributeDefault( - data_, display_color_attr, + layer_, display_color_attr, pxr::VtArray{ {element->rgba[0], element->rgba[1], element->rgba[2]}}); // Set the displayOpacity attribute, only if the opacity is not 1. if (element->rgba[3] != 1.0f) { - pxr::SdfPath display_opacity_attr = CreateAttributeSpec( - data_, prim_path, pxr::UsdGeomTokens->primvarsDisplayOpacity, + auto display_opacity_attr = CreateAttributeSpec( + layer_, prim_spec, pxr::UsdGeomTokens->primvarsDisplayOpacity, pxr::SdfValueTypeNames->FloatArray); - SetAttributeDefault(data_, display_opacity_attr, + SetAttributeDefault(layer_, display_opacity_attr, pxr::VtArray{element->rgba[3]}); } } } - void PrependToXformOpOrder(const pxr::SdfPath &prim_path, + void PrependToXformOpOrder(const pxr::SdfPrimSpecHandle prim_spec, const pxr::VtArray &order) { auto xform_op_order_path = - prim_path.AppendProperty(pxr::UsdGeomTokens->xformOpOrder); - if (!data_->HasSpec(xform_op_order_path)) { - WriteXformOpOrder(prim_path, order); + prim_spec->GetPath().AppendProperty(pxr::UsdGeomTokens->xformOpOrder); + if (!prim_spec->HasField(pxr::UsdGeomTokens->xformOpOrder)) { + WriteXformOpOrder(prim_spec, order); return; } auto existing_order = - data_->Get(xform_op_order_path, pxr::SdfFieldKeys->Default) - .UncheckedGet>(); + prim_spec->GetField(pxr::UsdGeomTokens->xformOpOrder).UncheckedGet>(); + prim_spec->GetField(pxr::UsdGeomTokens->xformOpOrder).Get>(); pxr::VtArray new_order(order.size() + existing_order.size()); std::copy(order.begin(), order.end(), new_order.begin()); std::copy(existing_order.begin(), existing_order.end(), new_order.begin() + order.size()); - SetAttributeDefault(data_, xform_op_order_path, new_order); + SetAttributeDefault(layer_, layer_->GetAttributeAtPath(xform_op_order_path), new_order); } void WriteMesh(const mjsMesh *mesh, const pxr::SdfPath &parent_path) { auto name = GetAvailablePrimName(*mjs_getName(mesh->element), pxr::UsdGeomTokens->Mesh, parent_path); - pxr::SdfPath subcomponent_path = - CreatePrimSpec(data_, parent_path, name, pxr::UsdGeomTokens->Xform); - pxr::SdfPath mesh_path = - CreatePrimSpec(data_, subcomponent_path, kTokens->sourceMesh, + auto subcomponent_spec = + CreatePrimSpec(layer_, parent_path, name, pxr::UsdGeomTokens->Xform); + auto mesh_spec = + CreatePrimSpec(layer_, subcomponent_spec->GetPath(), kTokens->sourceMesh, pxr::UsdGeomTokens->Mesh); - mesh_paths_[*mjs_getName(mesh->element)] = subcomponent_path; + mesh_paths_[*mjs_getName(mesh->element)] = subcomponent_spec->GetPath(); - ApplyApiSchema(data_, mesh_path, MjcPhysicsTokens->MjcMeshCollisionAPI); + ApplyApiSchema(layer_, mesh_spec, MjcPhysicsTokens->MjcMeshCollisionAPI); pxr::TfToken inertia = MjcPhysicsTokens->legacy; if (mesh->inertia == mjtMeshInertia::mjMESH_INERTIA_EXACT) { @@ -380,10 +375,10 @@ class ModelWriter { inertia = MjcPhysicsTokens->shell; } - WriteUniformAttribute(mesh_path, pxr::SdfValueTypeNames->Token, + WriteUniformAttribute(mesh_spec, pxr::SdfValueTypeNames->Token, MjcPhysicsTokens->mjcInertia, inertia); - WriteUniformAttribute(mesh_path, pxr::SdfValueTypeNames->Int, + WriteUniformAttribute(mesh_spec, pxr::SdfValueTypeNames->Int, MjcPhysicsTokens->mjcMaxhullvert, mesh->maxhullvert); // NOTE: The geometry data taken from the spec is the post-compilation @@ -399,10 +394,10 @@ class ModelWriter { points.emplace_back(&model_->mesh_vert[i]); } - pxr::SdfPath points_attr_path = - CreateAttributeSpec(data_, mesh_path, pxr::UsdGeomTokens->points, + auto points_attr = + CreateAttributeSpec(layer_, mesh_spec, pxr::UsdGeomTokens->points, pxr::SdfValueTypeNames->Vector3fArray); - SetAttributeDefault(data_, points_attr_path, points); + SetAttributeDefault(layer_, points_attr, points); // NOTE: nface is never 0. int nface = model_->mesh_facenum[mesh_id]; @@ -414,20 +409,20 @@ class ModelWriter { faces.push_back(model_->mesh_face[i + 1]); faces.push_back(model_->mesh_face[i + 2]); } - pxr::SdfPath face_vertex_idx_attr_path = CreateAttributeSpec( - data_, mesh_path, pxr::UsdGeomTokens->faceVertexIndices, + auto face_vertex_idx_attr= CreateAttributeSpec( + layer_, mesh_spec, pxr::UsdGeomTokens->faceVertexIndices, pxr::SdfValueTypeNames->IntArray); - SetAttributeDefault(data_, face_vertex_idx_attr_path, faces); + SetAttributeDefault(layer_, face_vertex_idx_attr, faces); pxr::VtArray vertex_counts; for (int i = 0; i < nface; ++i) { // Mujoco is always triangles. vertex_counts.push_back(3); } - pxr::SdfPath face_vertex_counts_attr_path = CreateAttributeSpec( - data_, mesh_path, pxr::UsdGeomTokens->faceVertexCounts, + auto face_vertex_counts_attr= CreateAttributeSpec( + layer_, mesh_spec, pxr::UsdGeomTokens->faceVertexCounts, pxr::SdfValueTypeNames->IntArray); - SetAttributeDefault(data_, face_vertex_counts_attr_path, vertex_counts); + SetAttributeDefault(layer_, face_vertex_counts_attr, vertex_counts); if (model_->mesh_normalnum[mesh_id]) { // We have to convert from Mujoco's indexed normals to USD's faceVarying @@ -440,12 +435,11 @@ class ModelWriter { int normal_adr = normal_start_adr + model_->mesh_facenormal[i]; normals.emplace_back(&model_->mesh_normal[normal_adr * 3]); } - pxr::SdfPath normals_attr_path = - CreateAttributeSpec(data_, mesh_path, pxr::UsdGeomTokens->normals, + auto normals_attr= + CreateAttributeSpec(layer_, mesh_spec, pxr::UsdGeomTokens->normals, pxr::SdfValueTypeNames->Vector3fArray); - SetAttributeDefault(data_, normals_attr_path, normals); - SetAttributeMetadata(data_, normals_attr_path, - pxr::UsdGeomTokens->interpolation, + SetAttributeDefault(layer_, normals_attr, normals); + normals_attr->SetField(pxr::UsdGeomTokens->interpolation, pxr::UsdGeomTokens->faceVarying); } @@ -465,30 +459,29 @@ class ModelWriter { texcoords.push_back(uv); } - pxr::SdfPath texcoords_attr_path = - CreateAttributeSpec(data_, mesh_path, kTokens->primvarsSt, + auto texcoords_attr= + CreateAttributeSpec(layer_, mesh_spec, kTokens->primvarsSt, pxr::SdfValueTypeNames->TexCoord2fArray); - SetAttributeDefault(data_, texcoords_attr_path, texcoords); - SetAttributeMetadata(data_, texcoords_attr_path, - pxr::UsdGeomTokens->interpolation, + SetAttributeDefault(layer_, texcoords_attr, texcoords); + texcoords_attr->SetField(pxr::UsdGeomTokens->interpolation, pxr::UsdGeomTokens->faceVarying); } // Default subdivision scheme is catmull clark so explicitly set it // to none here. - pxr::SdfPath subdivision_scheme_path = CreateAttributeSpec( - data_, mesh_path, pxr::UsdGeomTokens->subdivisionScheme, + auto subdivision_scheme= CreateAttributeSpec( + layer_, mesh_spec, pxr::UsdGeomTokens->subdivisionScheme, pxr::SdfValueTypeNames->Token); - SetAttributeDefault(data_, subdivision_scheme_path, + SetAttributeDefault(layer_, subdivision_scheme, pxr::UsdGeomTokens->none); } void WritePhysicsScene() { - pxr::SdfPath physics_scene_path = CreatePrimSpec( - data_, body_paths_[kWorldIndex], pxr::UsdPhysicsTokens->PhysicsScene, + auto physics_scene_spec = CreatePrimSpec( + layer_, body_paths_[kWorldIndex], pxr::UsdPhysicsTokens->PhysicsScene, pxr::UsdPhysicsTokens->PhysicsScene); - ApplyApiSchema(data_, physics_scene_path, MjcPhysicsTokens->MjcSceneAPI); + ApplyApiSchema(layer_, physics_scene_spec, MjcPhysicsTokens->MjcSceneAPI); const std::vector> option_double_attributes = { @@ -506,7 +499,7 @@ class ModelWriter { {MjcPhysicsTokens->mjcOptionO_margin, spec_->option.o_margin}, }; for (const auto &[token, value] : option_double_attributes) { - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Double, token, value); } @@ -523,55 +516,55 @@ class ModelWriter { spec_->option.sdf_initpoints}, }; for (const auto &[token, value] : option_int_attributes) { - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Int, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Int, token, value); } - pxr::SdfPath cone_attr = CreateAttributeSpec( - data_, physics_scene_path, MjcPhysicsTokens->mjcOptionCone, + auto cone_attr = CreateAttributeSpec( + layer_, physics_scene_spec, MjcPhysicsTokens->mjcOptionCone, pxr::SdfValueTypeNames->Token, pxr::SdfVariabilityUniform); switch (spec_->option.cone) { case mjCONE_PYRAMIDAL: - SetAttributeDefault(data_, cone_attr, MjcPhysicsTokens->pyramidal); + SetAttributeDefault(layer_, cone_attr, MjcPhysicsTokens->pyramidal); break; case mjCONE_ELLIPTIC: - SetAttributeDefault(data_, cone_attr, MjcPhysicsTokens->elliptic); + SetAttributeDefault(layer_, cone_attr, MjcPhysicsTokens->elliptic); break; default: break; } - pxr::SdfPath jacobian_attr = CreateAttributeSpec( - data_, physics_scene_path, MjcPhysicsTokens->mjcOptionJacobian, + auto jacobian_attr = CreateAttributeSpec( + layer_, physics_scene_spec, MjcPhysicsTokens->mjcOptionJacobian, pxr::SdfValueTypeNames->Token, pxr::SdfVariabilityUniform); switch (spec_->option.jacobian) { case mjJAC_AUTO: - SetAttributeDefault(data_, jacobian_attr, MjcPhysicsTokens->auto_); + SetAttributeDefault(layer_, jacobian_attr, MjcPhysicsTokens->auto_); break; case mjJAC_DENSE: - SetAttributeDefault(data_, jacobian_attr, MjcPhysicsTokens->dense); + SetAttributeDefault(layer_, jacobian_attr, MjcPhysicsTokens->dense); break; case mjJAC_SPARSE: - SetAttributeDefault(data_, jacobian_attr, MjcPhysicsTokens->sparse); + SetAttributeDefault(layer_, jacobian_attr, MjcPhysicsTokens->sparse); break; default: break; } - pxr::SdfPath solver_attr = CreateAttributeSpec( - data_, physics_scene_path, MjcPhysicsTokens->mjcOptionSolver, + auto solver_attr = CreateAttributeSpec( + layer_, physics_scene_spec, MjcPhysicsTokens->mjcOptionSolver, pxr::SdfValueTypeNames->Token, pxr::SdfVariabilityUniform); switch (spec_->option.solver) { case mjSOL_NEWTON: - SetAttributeDefault(data_, solver_attr, MjcPhysicsTokens->newton); + SetAttributeDefault(layer_, solver_attr, MjcPhysicsTokens->newton); break; case mjSOL_PGS: - SetAttributeDefault(data_, solver_attr, MjcPhysicsTokens->pgs); + SetAttributeDefault(layer_, solver_attr, MjcPhysicsTokens->pgs); break; case mjSOL_CG: - SetAttributeDefault(data_, solver_attr, MjcPhysicsTokens->cg); + SetAttributeDefault(layer_, solver_attr, MjcPhysicsTokens->cg); break; default: break; @@ -583,50 +576,50 @@ class ModelWriter { // normalization. float gravity_magnitude = gravity.Normalize(); - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Float, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Float, pxr::UsdPhysicsTokens->physicsGravityMagnitude, gravity_magnitude); - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Vector3f, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Vector3f, pxr::UsdPhysicsTokens->physicsGravityDirection, gravity); pxr::GfVec3d wind(spec_->option.wind[0], spec_->option.wind[1], spec_->option.wind[2]); - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Double3, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Double3, MjcPhysicsTokens->mjcOptionWind, wind); pxr::GfVec3d magnetic(spec_->option.magnetic[0], spec_->option.magnetic[1], spec_->option.magnetic[2]); - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Double3, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Double3, MjcPhysicsTokens->mjcOptionMagnetic, magnetic); pxr::VtArray o_solref(spec_->option.o_solref, spec_->option.o_solref + mjNREF); - WriteUniformAttribute(physics_scene_path, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->DoubleArray, MjcPhysicsTokens->mjcOptionO_solref, o_solref); pxr::VtArray o_solimp(spec_->option.o_solimp, spec_->option.o_solimp + mjNIMP); - WriteUniformAttribute(physics_scene_path, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->DoubleArray, MjcPhysicsTokens->mjcOptionO_solimp, o_solimp); pxr::VtArray o_friction(spec_->option.o_friction, spec_->option.o_friction + 5); - WriteUniformAttribute(physics_scene_path, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->DoubleArray, MjcPhysicsTokens->mjcOptionO_friction, o_friction); - pxr::SdfPath integrator_attr = CreateAttributeSpec( - data_, physics_scene_path, MjcPhysicsTokens->mjcOptionIntegrator, + auto integrator_attr = CreateAttributeSpec( + layer_, physics_scene_spec, MjcPhysicsTokens->mjcOptionIntegrator, pxr::SdfValueTypeNames->Token, pxr::SdfVariabilityUniform); switch (spec_->option.integrator) { case mjINT_EULER: - SetAttributeDefault(data_, integrator_attr, MjcPhysicsTokens->euler); + SetAttributeDefault(layer_, integrator_attr, MjcPhysicsTokens->euler); break; case mjINT_RK4: - SetAttributeDefault(data_, integrator_attr, MjcPhysicsTokens->rk4); + SetAttributeDefault(layer_, integrator_attr, MjcPhysicsTokens->rk4); break; default: break; @@ -636,7 +629,7 @@ class ModelWriter { int flags = enable ? spec_->option.enableflags : spec_->option.disableflags; bool value = enable ? (flags & flag) : !(flags & flag); - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Bool, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Bool, token, value); }; @@ -675,40 +668,40 @@ class ModelWriter { } // Compiler attributes - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Bool, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Bool, MjcPhysicsTokens->mjcCompilerAutoLimits, (bool)spec_->compiler.autolimits); - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcCompilerBoundMass, spec_->compiler.boundmass); - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcCompilerBoundInertia, spec_->compiler.boundinertia); - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcCompilerSetTotalMass, spec_->compiler.settotalmass); - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Bool, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Bool, MjcPhysicsTokens->mjcCompilerUseThread, (bool)spec_->compiler.usethread); - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Bool, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Bool, MjcPhysicsTokens->mjcCompilerBalanceInertia, (bool)spec_->compiler.balanceinertia); - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Token, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Token, MjcPhysicsTokens->mjcCompilerAngle, spec_->compiler.degree ? MjcPhysicsTokens->degree : MjcPhysicsTokens->radian); - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Bool, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Bool, MjcPhysicsTokens->mjcCompilerFitAABB, (bool)spec_->compiler.fitaabb); - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Bool, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Bool, MjcPhysicsTokens->mjcCompilerFuseStatic, (bool)spec_->compiler.fusestatic); @@ -720,101 +713,102 @@ class ModelWriter { mjINERTIAFROMGEOM_FALSE) { // mjINERTIA_FALSE inertiafromgeom_token = MjcPhysicsTokens->false_; } - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Token, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Token, MjcPhysicsTokens->mjcCompilerInertiaFromGeom, inertiafromgeom_token); - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Bool, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Bool, MjcPhysicsTokens->mjcCompilerAlignFree, (bool)spec_->compiler.alignfree); - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Int, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Int, MjcPhysicsTokens->mjcCompilerInertiaGroupRangeMin, spec_->compiler.inertiagrouprange[0]); - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Int, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Int, MjcPhysicsTokens->mjcCompilerInertiaGroupRangeMax, spec_->compiler.inertiagrouprange[1]); - WriteUniformAttribute(physics_scene_path, pxr::SdfValueTypeNames->Bool, + WriteUniformAttribute(physics_scene_spec, pxr::SdfValueTypeNames->Bool, MjcPhysicsTokens->mjcCompilerSaveInertial, (bool)spec_->compiler.saveinertial); } void WriteMeshes() { // Create a scope for the meshes to keep things organized - pxr::SdfPath scope_path = - CreatePrimSpec(data_, body_paths_[kWorldIndex], kTokens->meshScope, + auto scope = + CreatePrimSpec(layer_, body_paths_[kWorldIndex], kTokens->meshScope, pxr::UsdGeomTokens->Scope); // Make the mesh scope invisible since they will be referenced by the bits // that should be visible. - SetPrimMetadata(data_, scope_path, pxr::SdfFieldKeys->Active, false); + scope->SetField(pxr::SdfFieldKeys->Active, false); mjsMesh *mesh = mjs_asMesh(mjs_firstElement(spec_, mjOBJ_MESH)); while (mesh) { - WriteMesh(mesh, scope_path); + WriteMesh(mesh, scope->GetPath()); mesh = mjs_asMesh(mjs_nextElement(spec_, mesh->element)); } } - pxr::SdfPath AddUVTextureShader(const pxr::SdfPath &material_path, - const pxr::TfToken &name) { - pxr::SdfPath uvmap_shader_path = - CreatePrimSpec(data_, material_path, name, pxr::UsdShadeTokens->Shader); + pxr::SdfAttributeSpecHandle AddUVTextureShader( + const pxr::SdfPrimSpecHandle material_spec, const pxr::TfToken &name) { + auto uvmap_shader_spec = + CreatePrimSpec(layer_, material_spec->GetPath(), name, pxr::UsdShadeTokens->Shader); - pxr::SdfPath uvmap_info_id_attr = CreateAttributeSpec( - data_, uvmap_shader_path, pxr::UsdShadeTokens->infoId, + auto uvmap_info_id_attr = CreateAttributeSpec( + layer_, uvmap_shader_spec, pxr::UsdShadeTokens->infoId, pxr::SdfValueTypeNames->Token, pxr::SdfVariabilityUniform); - SetAttributeDefault(data_, uvmap_info_id_attr, + SetAttributeDefault(layer_, uvmap_info_id_attr, pxr::UsdImagingTokens->UsdPrimvarReader_float2); - pxr::SdfPath uvmap_varname_attr = - CreateAttributeSpec(data_, uvmap_shader_path, kTokens->inputsVarname, + auto uvmap_varname_attr = + CreateAttributeSpec(layer_, uvmap_shader_spec, kTokens->inputsVarname, pxr::SdfValueTypeNames->Token); - SetAttributeDefault(data_, uvmap_varname_attr, kTokens->st); + SetAttributeDefault(layer_, uvmap_varname_attr, kTokens->st); - pxr::SdfPath uvmap_st_output_attr = - CreateAttributeSpec(data_, uvmap_shader_path, kTokens->outputsSt, + auto uvmap_st_output_attr = + CreateAttributeSpec(layer_, uvmap_shader_spec, kTokens->outputsSt, pxr::SdfValueTypeNames->Float2); return uvmap_st_output_attr; } - std::vector AddTextureShader( - const pxr::SdfPath &material_path, const char *texture_file, - const pxr::TfToken &name, const pxr::SdfPath &uvmap_st_output_attr, + std::vector AddTextureShader( + const pxr::SdfPrimSpecHandle material_spec, const char *texture_file, + const pxr::TfToken &name, + const pxr::SdfAttributeSpecHandle uvmap_st_output_attr, const std::vector &output_channels) { - pxr::SdfPath texture_shader_path = - CreatePrimSpec(data_, material_path, name, pxr::UsdShadeTokens->Shader); - pxr::SdfPath texture_info_id_attr = CreateAttributeSpec( - data_, texture_shader_path, pxr::UsdShadeTokens->infoId, + auto texture_shader_spec = + CreatePrimSpec(layer_, material_spec->GetPath(), name, pxr::UsdShadeTokens->Shader); + auto texture_info_id_attr = CreateAttributeSpec( + layer_, texture_shader_spec, pxr::UsdShadeTokens->infoId, pxr::SdfValueTypeNames->Token, pxr::SdfVariabilityUniform); - SetAttributeDefault(data_, texture_info_id_attr, + SetAttributeDefault(layer_, texture_info_id_attr, pxr::UsdImagingTokens->UsdUVTexture); - pxr::SdfPath texture_file_attr = - CreateAttributeSpec(data_, texture_shader_path, kTokens->inputsFile, + auto texture_file_attr = + CreateAttributeSpec(layer_, texture_shader_spec, kTokens->inputsFile, pxr::SdfValueTypeNames->Asset); - SetAttributeDefault(data_, texture_file_attr, + SetAttributeDefault(layer_, texture_file_attr, pxr::SdfAssetPath(texture_file)); - pxr::SdfPath texture_st_input_attr = - CreateAttributeSpec(data_, texture_shader_path, kTokens->inputsSt, + auto texture_st_input_attr = + CreateAttributeSpec(layer_, texture_shader_spec, kTokens->inputsSt, pxr::SdfValueTypeNames->Float2); - AddAttributeConnection(data_, texture_st_input_attr, uvmap_st_output_attr); + AddAttributeConnection(layer_, texture_st_input_attr, uvmap_st_output_attr); - pxr::SdfPath texture_wrap_s_attr = - CreateAttributeSpec(data_, texture_shader_path, kTokens->inputsWrapS, + auto texture_wrap_s_attr = + CreateAttributeSpec(layer_, texture_shader_spec, kTokens->inputsWrapS, pxr::SdfValueTypeNames->Token); - SetAttributeDefault(data_, texture_wrap_s_attr, kTokens->repeat); + SetAttributeDefault(layer_, texture_wrap_s_attr, kTokens->repeat); - pxr::SdfPath texture_wrap_t_attr = - CreateAttributeSpec(data_, texture_shader_path, kTokens->inputsWrapT, + auto texture_wrap_t_attr = + CreateAttributeSpec(layer_, texture_shader_spec, kTokens->inputsWrapT, pxr::SdfValueTypeNames->Token); - SetAttributeDefault(data_, texture_wrap_t_attr, kTokens->repeat); + SetAttributeDefault(layer_, texture_wrap_t_attr, kTokens->repeat); - std::vector texture_output_attrs; + std::vector texture_output_attrs; for (const auto &output_channel : output_channels) { pxr::SdfValueTypeName value_type; if (output_channel == kTokens->outputsRgb) { @@ -824,49 +818,51 @@ class ModelWriter { value_type = pxr::SdfValueTypeNames->Float; } texture_output_attrs.push_back(CreateAttributeSpec( - data_, texture_shader_path, output_channel, value_type)); + layer_, texture_shader_spec, output_channel, value_type)); } return texture_output_attrs; } - pxr::SdfPath WritePhysicsMaterial(mjsGeom *geom) { + pxr::SdfPrimSpecHandle WritePhysicsMaterial(mjsGeom *geom) { pxr::SdfPath scope_path = body_paths_[kWorldIndex].AppendChild(kTokens->physicsMaterialsScope); - if (!data_->HasSpec(scope_path)) { - CreatePrimSpec(data_, body_paths_[kWorldIndex], - kTokens->physicsMaterialsScope, pxr::UsdGeomTokens->Scope); + pxr::SdfPrimSpecHandle scope_spec = layer_->GetPrimAtPath(scope_path); + if (!scope_spec) { + scope_spec = CreatePrimSpec(layer_, body_paths_[kWorldIndex], + kTokens->physicsMaterialsScope, + pxr::UsdGeomTokens->Scope); } auto name = GetAvailablePrimName(*mjs_getName(geom->element), pxr::UsdShadeTokens->Material, scope_path); - pxr::SdfPath material_path = - CreatePrimSpec(data_, scope_path, name, pxr::UsdShadeTokens->Material); + auto material_spec = + CreatePrimSpec(layer_, scope_spec->GetPath(), name, pxr::UsdShadeTokens->Material); - ApplyApiSchema(data_, material_path, + ApplyApiSchema(layer_, material_spec, pxr::UsdPhysicsTokens->PhysicsMaterialAPI); - ApplyApiSchema(data_, material_path, MjcPhysicsTokens->MjcMaterialAPI); + ApplyApiSchema(layer_, material_spec, MjcPhysicsTokens->MjcMaterialAPI); mjsGeom *geom_default = mjs_getDefault(geom->element)->geom; if (geom->friction[0] != geom_default->friction[0]) { // Since MuJoCo has no concept of static friction, only write dynamic // friction to remain truthful to how MuJoCo perceives the data. - WriteUniformAttribute(material_path, pxr::SdfValueTypeNames->Float, + WriteUniformAttribute(material_spec, pxr::SdfValueTypeNames->Float, pxr::UsdPhysicsTokens->physicsDynamicFriction, (float)geom->friction[0]); } if (geom->friction[1] != geom_default->friction[1]) { - WriteUniformAttribute(material_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(material_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcTorsionalfriction, geom->friction[1]); } if (geom->friction[2] != geom_default->friction[2]) { - WriteUniformAttribute(material_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(material_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcRollingfriction, geom->friction[2]); } - return material_path; + return material_spec; } void WriteMaterial(mjsMaterial *material, const pxr::SdfPath &parent_path) { @@ -874,58 +870,58 @@ class ModelWriter { auto name = GetAvailablePrimName(*mjs_getName(material->element), pxr::UsdShadeTokens->Material, parent_path); - pxr::SdfPath material_path = - CreatePrimSpec(data_, parent_path, name, pxr::UsdShadeTokens->Material); + auto material_spec = + CreatePrimSpec(layer_, parent_path, name, pxr::UsdShadeTokens->Material); // Create a Shader prim "PreviewSurface" under the Material prim. - pxr::SdfPath preview_surface_shader_path = - CreatePrimSpec(data_, material_path, kTokens->previewSurface, + auto preview_surface_shader_spec = + CreatePrimSpec(layer_, material_spec->GetPath(), kTokens->previewSurface, pxr::UsdShadeTokens->Shader); // Set the Shader'sinfoId attribute to UsdPreviewSurface, a standard surface // shader. - pxr::SdfPath info_id_attr = CreateAttributeSpec( - data_, preview_surface_shader_path, pxr::UsdShadeTokens->infoId, + auto info_id_attr = CreateAttributeSpec( + layer_, preview_surface_shader_spec, pxr::UsdShadeTokens->infoId, pxr::SdfValueTypeNames->Token, pxr::SdfVariabilityUniform); - SetAttributeDefault(data_, info_id_attr, + SetAttributeDefault(layer_, info_id_attr, pxr::UsdImagingTokens->UsdPreviewSurface); // Connect material's surface output to the preview surface's surface // output. - pxr::SdfPath surface_output_attr = CreateAttributeSpec( - data_, preview_surface_shader_path, pxr::UsdShadeTokens->outputsSurface, + auto surface_output_attr = CreateAttributeSpec( + layer_, preview_surface_shader_spec, pxr::UsdShadeTokens->outputsSurface, pxr::SdfValueTypeNames->Token); - pxr::SdfPath material_surface_output_attr = CreateAttributeSpec( - data_, material_path, pxr::UsdShadeTokens->outputsSurface, + auto material_surface_output_attr = CreateAttributeSpec( + layer_, material_spec, pxr::UsdShadeTokens->outputsSurface, pxr::SdfValueTypeNames->Token); - AddAttributeConnection(data_, material_surface_output_attr, + AddAttributeConnection(layer_, material_surface_output_attr, surface_output_attr); // Connect material's displacement output to the preview surface's // displacement output. - pxr::SdfPath displacement_output_attr = - CreateAttributeSpec(data_, preview_surface_shader_path, + auto displacement_output_attr = + CreateAttributeSpec(layer_, preview_surface_shader_spec, pxr::UsdShadeTokens->outputsDisplacement, pxr::SdfValueTypeNames->Token); - pxr::SdfPath material_displacement_output_attr = CreateAttributeSpec( - data_, material_path, pxr::UsdShadeTokens->outputsDisplacement, + auto material_displacement_output_attr = CreateAttributeSpec( + layer_, material_spec, pxr::UsdShadeTokens->outputsDisplacement, pxr::SdfValueTypeNames->Token); - AddAttributeConnection(data_, material_displacement_output_attr, + AddAttributeConnection(layer_, material_displacement_output_attr, displacement_output_attr); // Add an st (uv) Shader, a prim var reader for the UV coordinates. - const pxr::SdfPath &uvmap_st_output_attr = - AddUVTextureShader(material_path, pxr::TfToken("uvmap")); + const pxr::SdfAttributeSpecHandle &uvmap_st_output_attr = + AddUVTextureShader(material_spec, pxr::TfToken("uvmap")); const mjStringVec &textures = *(material->textures); // Set the values of metallic, roughness and occlusion. These can come from // an ORM packed texture, as individual textures, or as a values defined in // mjsMaterial_ (with the exception of occlusion). - pxr::SdfPath metallic_attr = CreateAttributeSpec( - data_, preview_surface_shader_path, kTokens->inputsMetallic, + auto metallic_attr = CreateAttributeSpec( + layer_, preview_surface_shader_spec, kTokens->inputsMetallic, pxr::SdfValueTypeNames->Float); - pxr::SdfPath roughness_attr = CreateAttributeSpec( - data_, preview_surface_shader_path, kTokens->inputsRoughness, + auto roughness_attr = CreateAttributeSpec( + layer_, preview_surface_shader_spec, kTokens->inputsRoughness, pxr::SdfValueTypeNames->Float); // Find the occlusion, roughness, and metallic textures. if (mjTEXROLE_ORM < textures.size()) { @@ -944,53 +940,54 @@ class ModelWriter { if (orm_texture) { // Create the ORM shader and connect its output to the preview // surface ORM attrs. - const std::vector orm_output_attrs = AddTextureShader( - material_path, orm_texture->file->c_str(), - pxr::TfToken("orm_packed"), uvmap_st_output_attr, - {kTokens->outputsR, kTokens->outputsG, kTokens->outputsB}); + const std::vector orm_output_attrs = + AddTextureShader( + material_spec, orm_texture->file->c_str(), + pxr::TfToken("orm_packed"), uvmap_st_output_attr, + {kTokens->outputsR, kTokens->outputsG, kTokens->outputsB}); if (orm_output_attrs.size() == 3) { - pxr::SdfPath occlusion_attr = CreateAttributeSpec( - data_, preview_surface_shader_path, kTokens->inputsOcclusion, + auto occlusion_attr = CreateAttributeSpec( + layer_, preview_surface_shader_spec, kTokens->inputsOcclusion, pxr::SdfValueTypeNames->Float); - AddAttributeConnection(data_, occlusion_attr, orm_output_attrs[0]); - AddAttributeConnection(data_, roughness_attr, orm_output_attrs[1]); - AddAttributeConnection(data_, metallic_attr, orm_output_attrs[2]); + AddAttributeConnection(layer_, occlusion_attr, orm_output_attrs[0]); + AddAttributeConnection(layer_, roughness_attr, orm_output_attrs[1]); + AddAttributeConnection(layer_, metallic_attr, orm_output_attrs[2]); } } else { if (metallic_texture) { - const std::vector metallic_output_attrs = - AddTextureShader(material_path, metallic_texture->file->c_str(), + const std::vector metallic_output_attrs = + AddTextureShader(material_spec, metallic_texture->file->c_str(), pxr::TfToken("metallic"), uvmap_st_output_attr, {kTokens->outputsRgb}); if (metallic_output_attrs.size() == 1) { - AddAttributeConnection(data_, metallic_attr, + AddAttributeConnection(layer_, metallic_attr, metallic_output_attrs[0]); } } else { - SetAttributeDefault(data_, metallic_attr, material->metallic); + SetAttributeDefault(layer_, metallic_attr, material->metallic); } if (roughness_texture) { - const std::vector roughness_output_attrs = - AddTextureShader(material_path, roughness_texture->file->c_str(), + const std::vector roughness_output_attrs = + AddTextureShader(material_spec, roughness_texture->file->c_str(), pxr::TfToken("roughness"), uvmap_st_output_attr, {kTokens->outputsRgb}); if (roughness_output_attrs.size() == 1) { - AddAttributeConnection(data_, roughness_attr, + AddAttributeConnection(layer_, roughness_attr, roughness_output_attrs[0]); } } else { - SetAttributeDefault(data_, roughness_attr, material->roughness); + SetAttributeDefault(layer_, roughness_attr, material->roughness); } if (occlusion_texture) { - pxr::SdfPath occlusion_attr = CreateAttributeSpec( - data_, preview_surface_shader_path, kTokens->inputsOcclusion, + auto occlusion_attr = CreateAttributeSpec( + layer_, preview_surface_shader_spec, kTokens->inputsOcclusion, pxr::SdfValueTypeNames->Float); - const std::vector occlusion_output_attrs = - AddTextureShader(material_path, occlusion_texture->file->c_str(), + const std::vector occlusion_output_attrs = + AddTextureShader(material_spec, occlusion_texture->file->c_str(), pxr::TfToken("occlusion"), uvmap_st_output_attr, {kTokens->outputsRgb}); if (occlusion_output_attrs.size() == 1) { - AddAttributeConnection(data_, occlusion_attr, + AddAttributeConnection(layer_, occlusion_attr, occlusion_output_attrs[0]); } } @@ -1002,17 +999,17 @@ class ModelWriter { mjsTexture *normal_texture = mjs_asTexture( mjs_findElement(spec_, mjOBJ_TEXTURE, normal_texture_name.c_str())); if (normal_texture) { - pxr::SdfPath normal_attr = CreateAttributeSpec( - data_, preview_surface_shader_path, kTokens->inputsNormal, + auto normal_attr = CreateAttributeSpec( + layer_, preview_surface_shader_spec, kTokens->inputsNormal, pxr::SdfValueTypeNames->Normal3f); // Create the normal map shader and connect its output to the preview // surface normal attr. - const std::vector normal_map_output_attrs = - AddTextureShader(material_path, normal_texture->file->c_str(), + const std::vector normal_map_output_attrs = + AddTextureShader(material_spec, normal_texture->file->c_str(), pxr::TfToken("normal"), uvmap_st_output_attr, {kTokens->outputsRgb}); if (normal_map_output_attrs.size() == 1) { - AddAttributeConnection(data_, normal_attr, + AddAttributeConnection(layer_, normal_attr, normal_map_output_attrs[0]); } } @@ -1024,15 +1021,15 @@ class ModelWriter { mjsTexture *emissive_texture = mjs_asTexture( mjs_findElement(spec_, mjOBJ_TEXTURE, emissive_texture_name.c_str())); if (emissive_texture) { - pxr::SdfPath emissive_attr = CreateAttributeSpec( - data_, preview_surface_shader_path, kTokens->inputsEmissiveColor, + auto emissive_attr = CreateAttributeSpec( + layer_, preview_surface_shader_spec, kTokens->inputsEmissiveColor, pxr::SdfValueTypeNames->Color3f); - const std::vector emissive_map_output_attrs = - AddTextureShader(material_path, emissive_texture->file->c_str(), + const std::vector emissive_map_output_attrs = + AddTextureShader(material_spec, emissive_texture->file->c_str(), pxr::TfToken("emissive"), uvmap_st_output_attr, {kTokens->outputsRgb}); if (emissive_map_output_attrs.size() == 1) { - AddAttributeConnection(data_, emissive_attr, + AddAttributeConnection(layer_, emissive_attr, emissive_map_output_attrs[0]); } } @@ -1040,8 +1037,8 @@ class ModelWriter { // Set the value of diffuse color. This can come from a diffuse texture // or as a value defined in mjsMaterial_. - pxr::SdfPath diffuse_color_attr = CreateAttributeSpec( - data_, preview_surface_shader_path, kTokens->inputsDiffuseColor, + auto diffuse_color_attr = CreateAttributeSpec( + layer_, preview_surface_shader_spec, kTokens->inputsDiffuseColor, pxr::SdfValueTypeNames->Color3f); // Find the main texture if specified. @@ -1051,17 +1048,18 @@ class ModelWriter { if (main_texture) { // Create the texture shader and connect it to the diffuse color // attribute. - const std::vector texture_diffuse_output_attrs = - AddTextureShader(material_path, main_texture->file->c_str(), - pxr::TfToken("diffuse"), uvmap_st_output_attr, - {kTokens->outputsRgb}); + const std::vector + texture_diffuse_output_attrs = + AddTextureShader(material_spec, main_texture->file->c_str(), + pxr::TfToken("diffuse"), uvmap_st_output_attr, + {kTokens->outputsRgb}); if (texture_diffuse_output_attrs.size() == 1) { - AddAttributeConnection(data_, diffuse_color_attr, + AddAttributeConnection(layer_, diffuse_color_attr, texture_diffuse_output_attrs[0]); } } else { // If no texture is specified, use the rgba diffuse color. - SetAttributeDefault(data_, diffuse_color_attr, + SetAttributeDefault(layer_, diffuse_color_attr, pxr::GfVec3f(material->rgba[0], material->rgba[1], material->rgba[2])); } @@ -1069,14 +1067,14 @@ class ModelWriter { void WriteMaterials() { // Create a scope for the meshes to keep things organized - pxr::SdfPath scope_path = - CreatePrimSpec(data_, body_paths_[kWorldIndex], kTokens->materialsScope, + auto scope = + CreatePrimSpec(layer_, body_paths_[kWorldIndex], kTokens->materialsScope, pxr::UsdGeomTokens->Scope); mjsMaterial *material = mjs_asMaterial(mjs_firstElement(spec_, mjOBJ_MATERIAL)); while (material) { - WriteMaterial(material, scope_path); + WriteMaterial(material, scope->GetPath()); material = mjs_asMaterial(mjs_nextElement(spec_, material->element)); } } @@ -1090,65 +1088,67 @@ class ModelWriter { const auto keyframe_name = pxr::TfToken(pxr::TfMakeValidIdentifier( name.empty() ? MjcPhysicsTokens->MjcKeyframe : name)); pxr::SdfPath keyframe_path = parent_path.AppendChild(keyframe_name); - if (!data_->HasSpec(keyframe_path)) { - CreatePrimSpec(data_, parent_path, keyframe_name, - pxr::MjcPhysicsTokens->MjcKeyframe); - } - auto set_attribute_data = [&](const pxr::SdfPath &attr_path, + auto keyframe_spec = + layer_->HasSpec(keyframe_path) + ? layer_->GetPrimAtPath(keyframe_path) + : CreatePrimSpec(layer_, parent_path, keyframe_name, + pxr::MjcPhysicsTokens->MjcKeyframe); + + auto set_attribute_data = [&](const pxr::SdfAttributeSpecHandle &attr_spec, const pxr::VtDoubleArray &value, mjsKey *keyframe) { // If the keyframe time is the default, and there are no other keyframes // set the attribute at the default time code. if (keyframe->time == 0 && keyframes.size() == 1) { - SetAttributeDefault(data_, attr_path, value); + SetAttributeDefault(layer_, attr_spec, value); } else { - SetAttributeTimeSample(data_, attr_path, keyframe->time, value); + SetAttributeTimeSample(layer_, attr_spec, keyframe->time, value); } }; for (auto *keyframe : keyframes) { - pxr::SdfPath qpos_attr_path = - CreateAttributeSpec(data_, keyframe_path, MjcPhysicsTokens->mjcQpos, + auto qpos_attr = + CreateAttributeSpec(layer_, keyframe_spec, MjcPhysicsTokens->mjcQpos, pxr::SdfValueTypeNames->DoubleArray); set_attribute_data( - qpos_attr_path, + qpos_attr, pxr::VtDoubleArray(keyframe->qpos->begin(), keyframe->qpos->end()), keyframe); - pxr::SdfPath qvel_attr_path = - CreateAttributeSpec(data_, keyframe_path, MjcPhysicsTokens->mjcQvel, + auto qvel_attr = + CreateAttributeSpec(layer_, keyframe_spec, MjcPhysicsTokens->mjcQvel, pxr::SdfValueTypeNames->DoubleArray); set_attribute_data( - qvel_attr_path, + qvel_attr, pxr::VtDoubleArray(keyframe->qvel->begin(), keyframe->qvel->end()), keyframe); - pxr::SdfPath act_attr_path = - CreateAttributeSpec(data_, keyframe_path, MjcPhysicsTokens->mjcAct, + auto act_attr = + CreateAttributeSpec(layer_, keyframe_spec, MjcPhysicsTokens->mjcAct, pxr::SdfValueTypeNames->DoubleArray); set_attribute_data( - act_attr_path, + act_attr, pxr::VtDoubleArray(keyframe->act->begin(), keyframe->act->end()), keyframe); - pxr::SdfPath ctrl_attr_path = - CreateAttributeSpec(data_, keyframe_path, MjcPhysicsTokens->mjcCtrl, + auto ctrl_attr = + CreateAttributeSpec(layer_, keyframe_spec, MjcPhysicsTokens->mjcCtrl, pxr::SdfValueTypeNames->DoubleArray); set_attribute_data( - ctrl_attr_path, + ctrl_attr, pxr::VtDoubleArray(keyframe->ctrl->begin(), keyframe->ctrl->end()), keyframe); - pxr::SdfPath mpos_attr_path = - CreateAttributeSpec(data_, keyframe_path, MjcPhysicsTokens->mjcMpos, + auto mpos_attr = + CreateAttributeSpec(layer_, keyframe_spec, MjcPhysicsTokens->mjcMpos, pxr::SdfValueTypeNames->DoubleArray); set_attribute_data( - mpos_attr_path, + mpos_attr, pxr::VtDoubleArray(keyframe->mpos->begin(), keyframe->mpos->end()), keyframe); - pxr::SdfPath mquat_attr_path = - CreateAttributeSpec(data_, keyframe_path, MjcPhysicsTokens->mjcMquat, + auto mquat_attr_path = + CreateAttributeSpec(layer_, keyframe_spec, MjcPhysicsTokens->mjcMquat, pxr::SdfValueTypeNames->DoubleArray); set_attribute_data( mquat_attr_path, @@ -1168,19 +1168,22 @@ class ModelWriter { keyframe = mjs_asKey(mjs_nextElement(spec_, keyframe->element)); } - pxr::SdfPath scope_path = - CreatePrimSpec(data_, body_paths_[kWorldIndex], kTokens->keyframesScope, + auto scope = + CreatePrimSpec(layer_, body_paths_[kWorldIndex], kTokens->keyframesScope, pxr::UsdGeomTokens->Scope); for (const auto &[keyframe_name, keyframes] : keyframes_map) { - WriteKeyframesWithName(keyframe_name, keyframes, scope_path); + WriteKeyframesWithName(keyframe_name, keyframes, scope->GetPath()); } } void WriteActuator(mjsActuator *actuator, const pxr::SdfPath &parent_path) { - pxr::TfToken valid_name = GetValidPrimName(*mjs_getName(actuator->element)); - pxr::SdfPath actuator_path = parent_path.AppendChild(valid_name); - if (!data_->HasSpec(actuator_path)) { - CreatePrimSpec(data_, parent_path, valid_name, + const pxr::TfToken valid_name = GetValidPrimName(*mjs_getName(actuator->element)); + const pxr::SdfPath actuator_path = parent_path.AppendChild(valid_name); + pxr::SdfPrimSpecHandle actuator_spec; + if (layer_->HasSpec(actuator_path)) { + actuator_spec = layer_->GetPrimAtPath(actuator_path); + } else { + actuator_spec = CreatePrimSpec(layer_, parent_path, valid_name, pxr::MjcPhysicsTokens->MjcActuator); } @@ -1202,17 +1205,17 @@ class ModelWriter { return; } - CreateRelationshipSpec(data_, actuator_path, MjcPhysicsTokens->mjcTarget, + CreateRelationshipSpec(layer_, actuator_spec, MjcPhysicsTokens->mjcTarget, target_path, pxr::SdfVariabilityUniform); - WriteUniformAttribute(actuator_path, pxr::SdfValueTypeNames->Int, + WriteUniformAttribute(actuator_spec, pxr::SdfValueTypeNames->Int, MjcPhysicsTokens->mjcGroup, actuator->group); if (!actuator->refsite->empty()) { int refsite_id = mj_name2id(model_, mjOBJ_SITE, actuator->refsite->c_str()); pxr::SdfPath refsite_path = site_paths_[refsite_id]; - CreateRelationshipSpec(data_, actuator_path, MjcPhysicsTokens->mjcRefSite, + CreateRelationshipSpec(layer_, actuator_spec, MjcPhysicsTokens->mjcRefSite, refsite_path, pxr::SdfVariabilityUniform); } @@ -1220,7 +1223,7 @@ class ModelWriter { int slidersite_id = mj_name2id(model_, mjOBJ_SITE, actuator->slidersite->c_str()); pxr::SdfPath slidersite_path = site_paths_[slidersite_id]; - CreateRelationshipSpec(data_, actuator_path, + CreateRelationshipSpec(layer_, actuator_spec, MjcPhysicsTokens->mjcSliderSite, slidersite_path, pxr::SdfVariabilityUniform); } @@ -1237,7 +1240,7 @@ class ModelWriter { } else if (value == mjLIMITED_FALSE) { limited_token = pxr::MjcPhysicsTokens->false_; } - WriteUniformAttribute(actuator_path, pxr::SdfValueTypeNames->Token, token, + WriteUniformAttribute(actuator_spec, pxr::SdfValueTypeNames->Token, token, limited_token); } @@ -1254,21 +1257,21 @@ class ModelWriter { {MjcPhysicsTokens->mjcCrankLength, actuator->cranklength}, }; for (const auto &[token, value] : actuator_double_attributes) { - WriteUniformAttribute(actuator_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(actuator_spec, pxr::SdfValueTypeNames->Double, token, value); } - WriteUniformAttribute(actuator_path, pxr::SdfValueTypeNames->Int, + WriteUniformAttribute(actuator_spec, pxr::SdfValueTypeNames->Int, MjcPhysicsTokens->mjcActDim, actuator->actdim); - WriteUniformAttribute(actuator_path, pxr::SdfValueTypeNames->Bool, + WriteUniformAttribute(actuator_spec, pxr::SdfValueTypeNames->Bool, MjcPhysicsTokens->mjcActEarly, (bool)actuator->actearly); - WriteUniformAttribute(actuator_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(actuator_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcInheritRange, actuator->inheritrange); WriteUniformAttribute( - actuator_path, pxr::SdfValueTypeNames->DoubleArray, + actuator_spec, pxr::SdfValueTypeNames->DoubleArray, MjcPhysicsTokens->mjcGear, pxr::VtDoubleArray(actuator->gear, actuator->gear + 6)); @@ -1286,10 +1289,10 @@ class ModelWriter { } else if (actuator->dyntype == mjtDyn::mjDYN_USER) { dyn_type = MjcPhysicsTokens->user; } - WriteUniformAttribute(actuator_path, pxr::SdfValueTypeNames->Token, + WriteUniformAttribute(actuator_spec, pxr::SdfValueTypeNames->Token, MjcPhysicsTokens->mjcDynType, dyn_type); WriteUniformAttribute( - actuator_path, pxr::SdfValueTypeNames->DoubleArray, + actuator_spec, pxr::SdfValueTypeNames->DoubleArray, MjcPhysicsTokens->mjcDynPrm, pxr::VtDoubleArray(actuator->dynprm, actuator->dynprm + 10)); @@ -1303,10 +1306,10 @@ class ModelWriter { } else if (actuator->gaintype == mjtGain::mjGAIN_USER) { gain_type = MjcPhysicsTokens->user; } - WriteUniformAttribute(actuator_path, pxr::SdfValueTypeNames->Token, + WriteUniformAttribute(actuator_spec, pxr::SdfValueTypeNames->Token, MjcPhysicsTokens->mjcGainType, gain_type); WriteUniformAttribute( - actuator_path, pxr::SdfValueTypeNames->DoubleArray, + actuator_spec, pxr::SdfValueTypeNames->DoubleArray, MjcPhysicsTokens->mjcGainPrm, pxr::VtDoubleArray(actuator->gainprm, actuator->gainprm + 10)); @@ -1320,108 +1323,108 @@ class ModelWriter { } else if (actuator->biastype == mjtBias::mjBIAS_USER) { bias_type = MjcPhysicsTokens->user; } - WriteUniformAttribute(actuator_path, pxr::SdfValueTypeNames->Token, + WriteUniformAttribute(actuator_spec, pxr::SdfValueTypeNames->Token, MjcPhysicsTokens->mjcBiasType, bias_type); WriteUniformAttribute( - actuator_path, pxr::SdfValueTypeNames->DoubleArray, + actuator_spec, pxr::SdfValueTypeNames->DoubleArray, MjcPhysicsTokens->mjcBiasPrm, pxr::VtDoubleArray(actuator->biasprm, actuator->biasprm + 10)); } void WriteActuators() { - pxr::SdfPath scope_path = - CreatePrimSpec(data_, body_paths_[kWorldIndex], kTokens->actuatorsScope, + auto scope = + CreatePrimSpec(layer_, body_paths_[kWorldIndex], kTokens->actuatorsScope, pxr::UsdGeomTokens->Scope); mjsActuator *actuator = mjs_asActuator(mjs_firstElement(spec_, mjOBJ_ACTUATOR)); while (actuator) { - WriteActuator(actuator, scope_path); + WriteActuator(actuator, scope->GetPath()); actuator = mjs_asActuator(mjs_nextElement(spec_, actuator->element)); } } - pxr::SdfPath WriteMeshGeom(const mjsGeom *geom, + pxr::SdfPrimSpecHandle WriteMeshGeom(const mjsGeom *geom, const pxr::SdfPath &body_path) { std::string mj_name = mjs_getName(geom->element)->empty() ? *geom->meshname : *mjs_getName(geom->element); auto name = GetAvailablePrimName(mj_name, pxr::UsdGeomTokens->Mesh, body_path); - pxr::SdfPath subcomponent_path = - CreatePrimSpec(data_, body_path, name, pxr::UsdGeomTokens->Xform); + auto subcomponent_spec = + CreatePrimSpec(layer_, body_path, name, pxr::UsdGeomTokens->Xform); // Reference the mesh asset written in WriteMeshes. - AddPrimReference(data_, subcomponent_path, mesh_paths_[*geom->meshname]); + AddPrimReference(layer_, subcomponent_spec, mesh_paths_[*geom->meshname]); // We want to use instancing with meshes, and it requires creating a parent // scope to be referenced, with the Mesh prim as a child. // To be able to actually manipulate the Mesh prim, we need to create and // return the corresponding `over` prim as a child of the referencing prim. - pxr::SdfPath over_mesh_path = - CreatePrimSpec(data_, subcomponent_path, kTokens->sourceMesh, + auto over_mesh_spec = + CreatePrimSpec(layer_, subcomponent_spec->GetPath(), kTokens->sourceMesh, pxr::UsdGeomTokens->Mesh, pxr::SdfSpecifierOver); - return over_mesh_path; + return over_mesh_spec; } - pxr::SdfPath WriteSiteGeom(const mjsSite *site, + pxr::SdfPrimSpecHandle WriteSiteGeom(const mjsSite *site, const pxr::SdfPath &body_path) { auto name = GetAvailablePrimName(*mjs_getName(site->element), pxr::UsdGeomTokens->Cube, body_path); int site_idx = mjs_getId(site->element); const mjtNum *size = &model_->site_size[site_idx * 3]; - pxr::SdfPath site_path; + pxr::SdfPrimSpecHandle site_spec; switch (site->type) { case mjGEOM_BOX: - site_path = WriteBox(name, size, body_path); + site_spec = WriteBox(name, size, body_path); break; case mjGEOM_SPHERE: - site_path = WriteSphere(name, size, body_path); + site_spec = WriteSphere(name, size, body_path); break; case mjGEOM_CAPSULE: - site_path = WriteCapsule(name, size, body_path); + site_spec = WriteCapsule(name, size, body_path); break; case mjGEOM_CYLINDER: - site_path = WriteCylinder(name, size, body_path); + site_spec = WriteCylinder(name, size, body_path); break; case mjGEOM_ELLIPSOID: - site_path = WriteEllipsoid(name, size, body_path); + site_spec = WriteEllipsoid(name, size, body_path); break; default: break; } - return site_path; + return site_spec; } - pxr::SdfPath WriteBox(const pxr::TfToken &name, const mjtNum *size, + pxr::SdfPrimSpecHandle WriteBox(const pxr::TfToken &name, const mjtNum *size, const pxr::SdfPath &body_path) { - pxr::SdfPath box_path = - CreatePrimSpec(data_, body_path, name, pxr::UsdGeomTokens->Cube); + pxr::SdfPrimSpecHandle box_spec = + CreatePrimSpec(layer_, body_path, name, pxr::UsdGeomTokens->Cube); // MuJoCo uses half sizes. Always set size to 2 (and correspondingly extent // from -1 to 1), and let scale determine the actual size. - pxr::SdfPath size_attr_path = - CreateAttributeSpec(data_, box_path, pxr::UsdGeomTokens->size, + auto size_attr_spec = + CreateAttributeSpec(layer_, box_spec, pxr::UsdGeomTokens->size, pxr::SdfValueTypeNames->Double); - SetAttributeDefault(data_, size_attr_path, 2.0); + SetAttributeDefault(layer_, size_attr_spec, 2.0); - pxr::SdfPath extent_attr_path = - CreateAttributeSpec(data_, box_path, pxr::UsdGeomTokens->extent, + auto extent_attr_spec = + CreateAttributeSpec(layer_, box_spec, pxr::UsdGeomTokens->extent, pxr::SdfValueTypeNames->Float3Array); - SetAttributeDefault(data_, extent_attr_path, + SetAttributeDefault(layer_, extent_attr_spec, pxr::VtArray( {pxr::GfVec3f(-1, -1, -1), pxr::GfVec3f(1, 1, 1)})); pxr::GfVec3f scale(static_cast(size[0]), static_cast(size[1]), static_cast(size[2])); - WriteScaleXformOp(box_path, scale); - WriteXformOpOrder(box_path, + WriteScaleXformOp(box_spec, scale); + WriteXformOpOrder(box_spec, pxr::VtArray{kTokens->xformOpScale}); - return box_path; + return box_spec; } - pxr::SdfPath WriteBoxGeom(const mjsGeom *geom, + pxr::SdfPrimSpecHandle WriteBoxGeom(const mjsGeom *geom, const pxr::SdfPath &body_path) { auto name = GetAvailablePrimName(*mjs_getName(geom->element), pxr::UsdGeomTokens->Cube, body_path); @@ -1431,25 +1434,25 @@ class ModelWriter { return WriteBox(name, geom_size, body_path); } - pxr::SdfPath WriteCapsule(const pxr::TfToken name, const mjtNum *size, + pxr::SdfPrimSpecHandle WriteCapsule(const pxr::TfToken name, const mjtNum *size, const pxr::SdfPath &body_path) { - pxr::SdfPath capsule_path = - CreatePrimSpec(data_, body_path, name, pxr::UsdGeomTokens->Capsule); + auto capsule_spec = + CreatePrimSpec(layer_, body_path, name, pxr::UsdGeomTokens->Capsule); - pxr::SdfPath radius_attr_path = - CreateAttributeSpec(data_, capsule_path, pxr::UsdGeomTokens->radius, + auto radius_attr_spec = + CreateAttributeSpec(layer_, capsule_spec, pxr::UsdGeomTokens->radius, pxr::SdfValueTypeNames->Double); - SetAttributeDefault(data_, radius_attr_path, (double)size[0]); + SetAttributeDefault(layer_, radius_attr_spec, (double)size[0]); - pxr::SdfPath height_attr_path = - CreateAttributeSpec(data_, capsule_path, pxr::UsdGeomTokens->height, + auto height_attr_spec = + CreateAttributeSpec(layer_, capsule_spec, pxr::UsdGeomTokens->height, pxr::SdfValueTypeNames->Double); // MuJoCo uses half sizes. - SetAttributeDefault(data_, height_attr_path, (double)(size[1] * 2)); - return capsule_path; + SetAttributeDefault(layer_, height_attr_spec, (double)(size[1] * 2)); + return capsule_spec; } - pxr::SdfPath WriteCapsuleGeom(const mjsGeom *geom, + pxr::SdfPrimSpecHandle WriteCapsuleGeom(const mjsGeom *geom, const pxr::SdfPath &body_path) { auto name = GetAvailablePrimName(*mjs_getName(geom->element), pxr::UsdGeomTokens->Capsule, body_path); @@ -1459,25 +1462,25 @@ class ModelWriter { return WriteCapsule(name, geom_size, body_path); } - pxr::SdfPath WriteCylinder(const pxr::TfToken name, const mjtNum *size, + pxr::SdfPrimSpecHandle WriteCylinder(const pxr::TfToken name, const mjtNum *size, const pxr::SdfPath &body_path) { - pxr::SdfPath cylinder_path = - CreatePrimSpec(data_, body_path, name, pxr::UsdGeomTokens->Cylinder); + auto cylinder_spec = + CreatePrimSpec(layer_, body_path, name, pxr::UsdGeomTokens->Cylinder); - pxr::SdfPath radius_attr_path = - CreateAttributeSpec(data_, cylinder_path, pxr::UsdGeomTokens->radius, + auto radius_attr_spec = + CreateAttributeSpec(layer_, cylinder_spec, pxr::UsdGeomTokens->radius, pxr::SdfValueTypeNames->Double); - SetAttributeDefault(data_, radius_attr_path, (double)size[0]); + SetAttributeDefault(layer_, radius_attr_spec, (double)size[0]); - pxr::SdfPath height_attr_path = - CreateAttributeSpec(data_, cylinder_path, pxr::UsdGeomTokens->height, + auto height_attr_spec = + CreateAttributeSpec(layer_, cylinder_spec, pxr::UsdGeomTokens->height, pxr::SdfValueTypeNames->Double); // MuJoCo uses half sizes. - SetAttributeDefault(data_, height_attr_path, (double)(size[1] * 2)); - return cylinder_path; + SetAttributeDefault(layer_, height_attr_spec, (double)(size[1] * 2)); + return cylinder_spec; } - pxr::SdfPath WriteCylinderGeom(const mjsGeom *geom, + pxr::SdfPrimSpecHandle WriteCylinderGeom(const mjsGeom *geom, const pxr::SdfPath &body_path) { auto name = GetAvailablePrimName(*mjs_getName(geom->element), pxr::UsdGeomTokens->Cylinder, body_path); @@ -1487,27 +1490,27 @@ class ModelWriter { return WriteCylinder(name, geom_size, body_path); } - pxr::SdfPath WriteEllipsoid(const pxr::TfToken name, const mjtNum *size, + pxr::SdfPrimSpecHandle WriteEllipsoid(const pxr::TfToken name, const mjtNum *size, const pxr::SdfPath &body_path) { - pxr::SdfPath ellipsoid_path = - CreatePrimSpec(data_, body_path, name, pxr::UsdGeomTokens->Sphere); + auto ellipsoid_spec = + CreatePrimSpec(layer_, body_path, name, pxr::UsdGeomTokens->Sphere); pxr::GfVec3f scale = {static_cast(size[0]), static_cast(size[1]), static_cast(size[2])}; - pxr::SdfPath radius_attr_path = - CreateAttributeSpec(data_, ellipsoid_path, pxr::UsdGeomTokens->radius, + auto radius_attr_spec = + CreateAttributeSpec(layer_, ellipsoid_spec, pxr::UsdGeomTokens->radius, pxr::SdfValueTypeNames->Double); - SetAttributeDefault(data_, radius_attr_path, 1.0); + SetAttributeDefault(layer_, radius_attr_spec, 1.0); - WriteScaleXformOp(ellipsoid_path, scale); - WriteXformOpOrder(ellipsoid_path, + WriteScaleXformOp(ellipsoid_spec, scale); + WriteXformOpOrder(ellipsoid_spec, pxr::VtArray{kTokens->xformOpScale}); - return ellipsoid_path; + return ellipsoid_spec; } - pxr::SdfPath WriteEllipsoidGeom(const mjsGeom *geom, + pxr::SdfPrimSpecHandle WriteEllipsoidGeom(const mjsGeom *geom, const pxr::SdfPath &body_path) { auto name = GetAvailablePrimName(*mjs_getName(geom->element), pxr::UsdGeomTokens->Sphere, body_path); @@ -1517,19 +1520,19 @@ class ModelWriter { return WriteEllipsoid(name, geom_size, body_path); } - pxr::SdfPath WriteSphere(const pxr::TfToken name, const mjtNum *size, + pxr::SdfPrimSpecHandle WriteSphere(const pxr::TfToken name, const mjtNum *size, const pxr::SdfPath &body_path) { - pxr::SdfPath sphere_path = - CreatePrimSpec(data_, body_path, name, pxr::UsdGeomTokens->Sphere); + auto sphere_spec = + CreatePrimSpec(layer_, body_path, name, pxr::UsdGeomTokens->Sphere); - pxr::SdfPath radius_attr_path = - CreateAttributeSpec(data_, sphere_path, pxr::UsdGeomTokens->radius, + auto radius_attr_spec = + CreateAttributeSpec(layer_, sphere_spec, pxr::UsdGeomTokens->radius, pxr::SdfValueTypeNames->Double); - SetAttributeDefault(data_, radius_attr_path, (double)size[0]); - return sphere_path; + SetAttributeDefault(layer_, radius_attr_spec, (double)size[0]); + return sphere_spec; } - pxr::SdfPath WriteSphereGeom(const mjsGeom *geom, + pxr::SdfPrimSpecHandle WriteSphereGeom(const mjsGeom *geom, const pxr::SdfPath &body_path) { auto name = GetAvailablePrimName(*mjs_getName(geom->element), pxr::UsdGeomTokens->Sphere, body_path); @@ -1538,10 +1541,10 @@ class ModelWriter { return WriteSphere(name, geom_size, body_path); } - pxr::SdfPath WritePlane(const pxr::TfToken &name, const mjtNum *size, + pxr::SdfPrimSpecHandle WritePlane(const pxr::TfToken &name, const mjtNum *size, const pxr::SdfPath &body_path) { - pxr::SdfPath plane_path = - CreatePrimSpec(data_, body_path, name, pxr::UsdGeomTokens->Plane); + auto plane_spec = + CreatePrimSpec(layer_, body_path, name, pxr::UsdGeomTokens->Plane); // MuJoCo uses half sizes. // Note that UsdGeomPlane is infinite for simulation purposes but can have @@ -1549,24 +1552,24 @@ class ModelWriter { double width = size[0] * 2.0; double length = size[1] * 2.0; - pxr::SdfPath width_attr_path = - CreateAttributeSpec(data_, plane_path, pxr::UsdGeomTokens->width, + auto width_attr_spec = + CreateAttributeSpec(layer_, plane_spec, pxr::UsdGeomTokens->width, pxr::SdfValueTypeNames->Double); - SetAttributeDefault(data_, width_attr_path, width); + SetAttributeDefault(layer_, width_attr_spec, width); - pxr::SdfPath length_attr_path = - CreateAttributeSpec(data_, plane_path, pxr::UsdGeomTokens->length, + auto length_attr_spec = + CreateAttributeSpec(layer_, plane_spec, pxr::UsdGeomTokens->length, pxr::SdfValueTypeNames->Double); - SetAttributeDefault(data_, length_attr_path, length); + SetAttributeDefault(layer_, length_attr_spec, length); // MuJoCo plane is always a XY plane with +Z up. // UsdGeomPlane is also a XY plane if axis is 'Z', which is default. // So no need to set axis attribute explicitly. - return plane_path; + return plane_spec; } - pxr::SdfPath WritePlaneGeom(const mjsGeom *geom, + pxr::SdfPrimSpecHandle WritePlaneGeom(const mjsGeom *geom, const pxr::SdfPath &body_path) { auto name = GetAvailablePrimName(*mjs_getName(geom->element), pxr::UsdGeomTokens->Plane, body_path); @@ -1583,54 +1586,54 @@ class ModelWriter { // Create a geom primitive and set its purpose to guide so it won't be // rendered. - pxr::SdfPath site_path = WriteSiteGeom(site, body_path); - SetPrimPurpose(data_, site_path, pxr::UsdGeomTokens->guide); + auto site_spec = WriteSiteGeom(site, body_path); + SetPrimPurpose(layer_, site_spec, pxr::UsdGeomTokens->guide); - ApplyApiSchema(data_, site_path, MjcPhysicsTokens->MjcSiteAPI); + ApplyApiSchema(layer_, site_spec, MjcPhysicsTokens->MjcSiteAPI); - WriteUniformAttribute(site_path, pxr::SdfValueTypeNames->Int, + WriteUniformAttribute(site_spec, pxr::SdfValueTypeNames->Int, MjcPhysicsTokens->mjcGroup, site->group); - WriteColorAndOpacityAttributes(site_path, site); + WriteColorAndOpacityAttributes(site_spec, site); int site_id = mjs_getId(site->element); auto transform = MujocoPosQuatToTransform(&model_->site_pos[3 * site_id], &model_->site_quat[4 * site_id]); - WriteTransformXformOp(site_path, transform); + WriteTransformXformOp(site_spec, transform); PrependToXformOpOrder( - site_path, pxr::VtArray{kTokens->xformOpTransform}); + site_spec, pxr::VtArray{kTokens->xformOpTransform}); - site_paths_[site_id] = site_path; + site_paths_[site_id] = site_spec->GetPath(); } void WriteGeom(mjsGeom *geom, const mjsBody *body) { const int body_id = mjs_getId(body->element); const auto &body_path = body_paths_[body_id]; - pxr::SdfPath geom_path; + pxr::SdfPrimSpecHandle geom_spec; int geom_id = mjs_getId(geom->element); switch (geom->type) { case mjGEOM_PLANE: - geom_path = WritePlaneGeom(geom, body_path); + geom_spec = WritePlaneGeom(geom, body_path); break; case mjGEOM_MESH: - geom_path = WriteMeshGeom(geom, body_path); + geom_spec = WriteMeshGeom(geom, body_path); break; case mjGEOM_BOX: - geom_path = WriteBoxGeom(geom, body_path); + geom_spec = WriteBoxGeom(geom, body_path); break; case mjGEOM_CAPSULE: - geom_path = WriteCapsuleGeom(geom, body_path); + geom_spec = WriteCapsuleGeom(geom, body_path); break; case mjGEOM_CYLINDER: - geom_path = WriteCylinderGeom(geom, body_path); + geom_spec = WriteCylinderGeom(geom, body_path); break; case mjGEOM_ELLIPSOID: - geom_path = WriteEllipsoidGeom(geom, body_path); + geom_spec = WriteEllipsoidGeom(geom, body_path); break; case mjGEOM_SPHERE: - geom_path = WriteSphereGeom(geom, body_path); + geom_spec = WriteSphereGeom(geom, body_path); break; default: TF_WARN(UnsupportedGeomTypeError, "Unsupported geom type for geom %d", @@ -1638,78 +1641,78 @@ class ModelWriter { return; } - WriteUniformAttribute(geom_path, pxr::SdfValueTypeNames->Int, + WriteUniformAttribute(geom_spec, pxr::SdfValueTypeNames->Int, MjcPhysicsTokens->mjcGroup, geom->group); if (model_->geom_contype[geom_id] == 0 && model_->geom_conaffinity[geom_id] == 0) { // If the geom is purely visual, apply the imageable API. - ApplyApiSchema(data_, geom_path, MjcPhysicsTokens->MjcImageableAPI); + ApplyApiSchema(layer_, geom_spec, MjcPhysicsTokens->MjcImageableAPI); } // Apply the physics schemas if we are writing physics and the // geom participates in collisions. if (model_->geom_contype[geom_id] != 0 || model_->geom_conaffinity[geom_id] != 0) { - ApplyApiSchema(data_, geom_path, + ApplyApiSchema(layer_, geom_spec, pxr::UsdPhysicsTokens->PhysicsCollisionAPI); - ApplyApiSchema(data_, geom_path, MjcPhysicsTokens->MjcCollisionAPI); + ApplyApiSchema(layer_, geom_spec, MjcPhysicsTokens->MjcCollisionAPI); WriteUniformAttribute( - geom_path, pxr::SdfValueTypeNames->Bool, + geom_spec, pxr::SdfValueTypeNames->Bool, MjcPhysicsTokens->mjcShellinertia, geom->typeinertia == mjtGeomInertia::mjINERTIA_SHELL); - WriteUniformAttribute(geom_path, pxr::SdfValueTypeNames->Int, + WriteUniformAttribute(geom_spec, pxr::SdfValueTypeNames->Int, MjcPhysicsTokens->mjcPriority, geom->priority); - WriteUniformAttribute(geom_path, pxr::SdfValueTypeNames->Int, + WriteUniformAttribute(geom_spec, pxr::SdfValueTypeNames->Int, MjcPhysicsTokens->mjcCondim, geom->condim); - WriteUniformAttribute(geom_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(geom_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcSolmix, geom->solmix); - WriteUniformAttribute(geom_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(geom_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcSolmix, geom->solmix); WriteUniformAttribute( - geom_path, pxr::SdfValueTypeNames->DoubleArray, + geom_spec, pxr::SdfValueTypeNames->DoubleArray, MjcPhysicsTokens->mjcSolref, pxr::VtArray(geom->solref, geom->solref + mjNREF)); WriteUniformAttribute( - geom_path, pxr::SdfValueTypeNames->DoubleArray, + geom_spec, pxr::SdfValueTypeNames->DoubleArray, MjcPhysicsTokens->mjcSolimp, pxr::VtArray(geom->solimp, geom->solimp + mjNIMP)); - WriteUniformAttribute(geom_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(geom_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcMargin, geom->margin); - WriteUniformAttribute(geom_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(geom_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcGap, geom->gap); if (geom->mass >= mjMINVAL || geom->density >= mjMINVAL) { - ApplyApiSchema(data_, geom_path, pxr::UsdPhysicsTokens->PhysicsMassAPI); + ApplyApiSchema(layer_, geom_spec, pxr::UsdPhysicsTokens->PhysicsMassAPI); } if (geom->mass >= mjMINVAL) { - pxr::SdfPath mass_attr = CreateAttributeSpec( - data_, geom_path, pxr::UsdPhysicsTokens->physicsMass, + auto mass_attr_spec = CreateAttributeSpec( + layer_, geom_spec, pxr::UsdPhysicsTokens->physicsMass, pxr::SdfValueTypeNames->Float, pxr::SdfVariabilityUniform); // Make sure to cast to float here since mjtNum might be a double. - SetAttributeDefault(data_, mass_attr, (float)geom->mass); + SetAttributeDefault(layer_, mass_attr_spec, (float)geom->mass); } // Even though density is not used for mass computation when mass exists // we want to retain the information anyways. if (geom->density >= mjMINVAL) { - pxr::SdfPath density_attr = CreateAttributeSpec( - data_, geom_path, pxr::UsdPhysicsTokens->physicsDensity, + auto density_attr_spec = CreateAttributeSpec( + layer_, geom_spec, pxr::UsdPhysicsTokens->physicsDensity, pxr::SdfValueTypeNames->Float, pxr::SdfVariabilityUniform); // Make sure to cast to float here since mjtNum might be a double. - SetAttributeDefault(data_, density_attr, (float)geom->density); + SetAttributeDefault(layer_, density_attr_spec, (float)geom->density); } mjsDefault *geom_default = mjs_getDefault(geom->element); @@ -1717,48 +1720,48 @@ class ModelWriter { if (geom->friction[0] != geom_default->geom->friction[0] || geom->friction[1] != geom_default->geom->friction[1] || geom->friction[2] != geom_default->geom->friction[2]) { - pxr::SdfPath physics_material_path = WritePhysicsMaterial(geom); - ApplyApiSchema(data_, geom_path, - pxr::UsdShadeTokens->MaterialBindingAPI); + auto physics_material_spec = WritePhysicsMaterial(geom); + ApplyApiSchema(layer_, geom_spec, pxr::UsdShadeTokens->MaterialBindingAPI); // Bind the material to this geom. CreateRelationshipSpec( - data_, geom_path, pxr::UsdShadeTokens->materialBinding, - physics_material_path, pxr::SdfVariabilityUniform); + layer_, geom_spec, + pxr::UsdShadeTokens->materialBinding, physics_material_spec->GetPath(), + pxr::SdfVariabilityUniform); } // For meshes, also apply PhysicsMeshCollisionAPI and set the // approximation attribute. if (geom->type == mjGEOM_MESH) { - ApplyApiSchema(data_, geom_path, + ApplyApiSchema(layer_, geom_spec, pxr::UsdPhysicsTokens->PhysicsMeshCollisionAPI); // Note: MuJoCo documentation states that for collision purposes, meshes // are always replaced with their convex hulls. Therefore, we set the // approximation attribute to convexHull explicitly. - pxr::SdfPath approximation_attr = CreateAttributeSpec( - data_, geom_path, pxr::UsdPhysicsTokens->physicsApproximation, + auto approximation_attr_spec = CreateAttributeSpec( + layer_, geom_spec, pxr::UsdPhysicsTokens->physicsApproximation, pxr::SdfValueTypeNames->Token, pxr::SdfVariabilityUniform); - SetAttributeDefault(data_, approximation_attr, + SetAttributeDefault(layer_, approximation_attr_spec, pxr::UsdPhysicsTokens->convexHull); } } else { // Currently imageable only has a group API. But since it's the same // naming in MjcCollisionsAPI we've already set it earlier in this // function. - ApplyApiSchema(data_, geom_path, MjcPhysicsTokens->MjcImageableAPI); + ApplyApiSchema(layer_, geom_spec, MjcPhysicsTokens->MjcImageableAPI); } mjsDefault *spec_default = mjs_getDefault(geom->element); pxr::TfToken valid_class_name = GetValidPrimName(*mjs_getName(spec_default->element)); pxr::SdfPath geom_class_path = class_path_.AppendChild(valid_class_name); - if (!data_->HasSpec(geom_class_path)) { - pxr::SdfPath class_path = - CreateClassSpec(data_, class_path_, valid_class_name); - auto visibility_attr = - CreateAttributeSpec(data_, class_path, pxr::UsdGeomTokens->visibility, + if (!layer_->HasSpec(geom_class_path)) { + auto class_spec = + CreateClassSpec(layer_, class_path_, valid_class_name); + auto visibility_attr_spec = + CreateAttributeSpec(layer_, class_spec, pxr::UsdGeomTokens->visibility, pxr::SdfValueTypeNames->Token); - SetAttributeDefault(data_, visibility_attr, + SetAttributeDefault(layer_, visibility_attr_spec, pxr::UsdGeomTokens->inherited); } @@ -1768,30 +1771,30 @@ class ModelWriter { body_paths_[kWorldIndex] .AppendChild(kTokens->materialsScope) .AppendChild(GetValidPrimName(*geom->material)); - if (data_->HasSpec(material_path)) { - ApplyApiSchema(data_, geom_path, + if (layer_->HasSpec(material_path)) { + ApplyApiSchema(layer_, geom_spec, pxr::UsdShadeTokens->MaterialBindingAPI); // Bind the material to this geom. - CreateRelationshipSpec(data_, geom_path, + CreateRelationshipSpec(layer_, geom_spec, pxr::UsdShadeTokens->materialBinding, material_path, pxr::SdfVariabilityUniform); } } - WriteColorAndOpacityAttributes(geom_path, geom); + WriteColorAndOpacityAttributes(geom_spec, geom); if (body_id == kWorldIndex) { - SetPrimKind(data_, geom_path, pxr::KindTokens->component); + SetPrimKind(layer_, geom_spec, pxr::KindTokens->component); } // Inherit from class. - AddPrimInherit(data_, geom_path, geom_class_path); + AddPrimInherit(layer_, geom_spec, geom_class_path); auto transform = MujocoPosQuatToTransform(&model_->geom_pos[3 * geom_id], &model_->geom_quat[4 * geom_id]); - WriteTransformXformOp(geom_path, transform); + WriteTransformXformOp(geom_spec, transform); PrependToXformOpOrder( - geom_path, pxr::VtArray{kTokens->xformOpTransform}); + geom_spec, pxr::VtArray{kTokens->xformOpTransform}); } void WriteSites(mjsBody *body) { @@ -1869,7 +1872,7 @@ class ModelWriter { auto joint_name = joint ? *mjs_getName(joint->element) : "FixedJoint"; pxr::TfToken joint_name_token = GetAvailablePrimName(joint_name, kTokens->joint, body1_path_usd); - pxr::SdfPath joint_path = CreatePrimSpec(data_, body1_path_usd, + auto joint_spec = CreatePrimSpec(layer_, body1_path_usd, joint_name_token, joint_prim_type); // Set body0 and body1 relationships @@ -1877,11 +1880,11 @@ class ModelWriter { // keeping the body0 relationship empty. if (body0_id_usd != kWorldIndex) { const pxr::SdfPath &body0_path_usd = body_paths_[body0_id_usd]; - CreateRelationshipSpec(data_, joint_path, + CreateRelationshipSpec(layer_, joint_spec, pxr::UsdPhysicsTokens->physicsBody0, body0_path_usd, pxr::SdfVariabilityUniform); } - CreateRelationshipSpec(data_, joint_path, + CreateRelationshipSpec(layer_, joint_spec, pxr::UsdPhysicsTokens->physicsBody1, body1_path_usd, pxr::SdfVariabilityUniform); @@ -1900,23 +1903,23 @@ class ModelWriter { pxr::GfRotation(pxr::GfVec3f::ZAxis(), mj_jnt_axis).GetQuat()); SetAttributeDefault( - data_, - CreateAttributeSpec(data_, joint_path, + layer_, + CreateAttributeSpec(layer_, joint_spec, pxr::UsdPhysicsTokens->physicsLocalPos1, pxr::SdfValueTypeNames->Float3), local_pos1); if (joint_prim_type == pxr::UsdPhysicsTokens->PhysicsRevoluteJoint || joint_prim_type == pxr::UsdPhysicsTokens->PhysicsPrismaticJoint) { SetAttributeDefault( - data_, - CreateAttributeSpec(data_, joint_path, + layer_, + CreateAttributeSpec(layer_, joint_spec, pxr::UsdPhysicsTokens->physicsLocalRot1, pxr::SdfValueTypeNames->Quatf), local_rot1); } else { SetAttributeDefault( - data_, - CreateAttributeSpec(data_, joint_path, + layer_, + CreateAttributeSpec(layer_, joint_spec, pxr::UsdPhysicsTokens->physicsLocalRot1, pxr::SdfValueTypeNames->Quatf), pxr::GfQuatf::GetIdentity()); @@ -1934,8 +1937,8 @@ class ModelWriter { pxr::GfVec3f local_pos0(jnt_pos_parent_local); SetAttributeDefault( - data_, - CreateAttributeSpec(data_, joint_path, + layer_, + CreateAttributeSpec(layer_, joint_spec, pxr::UsdPhysicsTokens->physicsLocalPos0, pxr::SdfValueTypeNames->Float3), local_pos0); @@ -1947,8 +1950,8 @@ class ModelWriter { .GetQuat()); SetAttributeDefault( - data_, - CreateAttributeSpec(data_, joint_path, + layer_, + CreateAttributeSpec(layer_, joint_spec, pxr::UsdPhysicsTokens->physicsLocalRot0, pxr::SdfValueTypeNames->Quatf), other_rot0); @@ -1956,8 +1959,8 @@ class ModelWriter { // Fixed joints have no frame and no axis per se. We simply need the // rotation quaternion of the body its on. SetAttributeDefault( - data_, - CreateAttributeSpec(data_, joint_path, + layer_, + CreateAttributeSpec(layer_, joint_spec, pxr::UsdPhysicsTokens->physicsLocalRot0, pxr::SdfValueTypeNames->Quatf), body1_transform_local.ExtractRotationQuat()); @@ -1971,8 +1974,8 @@ class ModelWriter { // The joint motion occurs around/along the Z-axis of the joint frame // established by localRot0/1. SetAttributeDefault( - data_, - CreateAttributeSpec(data_, joint_path, + layer_, + CreateAttributeSpec(layer_, joint_spec, pxr::UsdPhysicsTokens->physicsAxis, pxr::SdfValueTypeNames->Token), pxr::UsdPhysicsTokens->z); // "Z" axis @@ -1988,27 +1991,27 @@ class ModelWriter { lower_limit *= (180.0 / mjPI); upper_limit *= (180.0 / mjPI); SetAttributeDefault( - data_, - CreateAttributeSpec(data_, joint_path, + layer_, + CreateAttributeSpec(layer_, joint_spec, pxr::UsdPhysicsTokens->physicsLowerLimit, pxr::SdfValueTypeNames->Float), lower_limit); SetAttributeDefault( - data_, - CreateAttributeSpec(data_, joint_path, + layer_, + CreateAttributeSpec(layer_, joint_spec, pxr::UsdPhysicsTokens->physicsUpperLimit, pxr::SdfValueTypeNames->Float), upper_limit); } else if (type == mjJNT_SLIDE) { SetAttributeDefault( - data_, - CreateAttributeSpec(data_, joint_path, + layer_, + CreateAttributeSpec(layer_, joint_spec, pxr::UsdPhysicsTokens->physicsLowerLimit, pxr::SdfValueTypeNames->Float), lower_limit); SetAttributeDefault( - data_, - CreateAttributeSpec(data_, joint_path, + layer_, + CreateAttributeSpec(layer_, joint_spec, pxr::UsdPhysicsTokens->physicsUpperLimit, pxr::SdfValueTypeNames->Float), upper_limit); @@ -2016,46 +2019,46 @@ class ModelWriter { } // Finally write the mjcPhysicsJointAPI attributes. - ApplyApiSchema(data_, joint_path, MjcPhysicsTokens->MjcJointAPI); + ApplyApiSchema(layer_, joint_spec, MjcPhysicsTokens->MjcJointAPI); - WriteUniformAttribute(joint_path, pxr::SdfValueTypeNames->Int, + WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Int, MjcPhysicsTokens->mjcGroup, joint->group); WriteUniformAttribute( - joint_path, pxr::SdfValueTypeNames->DoubleArray, + joint_spec, pxr::SdfValueTypeNames->DoubleArray, MjcPhysicsTokens->mjcSpringdamper, pxr::VtArray(joint->springdamper, joint->springdamper + 2)); - WriteUniformAttribute(joint_path, pxr::SdfValueTypeNames->DoubleArray, + WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->DoubleArray, MjcPhysicsTokens->mjcSolreflimit, pxr::VtArray(joint->solref_limit, joint->solref_limit + mjNREF)); - WriteUniformAttribute(joint_path, pxr::SdfValueTypeNames->DoubleArray, + WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->DoubleArray, MjcPhysicsTokens->mjcSolimplimit, pxr::VtArray(joint->solimp_limit, joint->solimp_limit + mjNIMP)); WriteUniformAttribute( - joint_path, pxr::SdfValueTypeNames->DoubleArray, + joint_spec, pxr::SdfValueTypeNames->DoubleArray, MjcPhysicsTokens->mjcSolreffriction, pxr::VtArray(joint->solref_friction, joint->solref_friction + mjNREF)); WriteUniformAttribute( - joint_path, pxr::SdfValueTypeNames->DoubleArray, + joint_spec, pxr::SdfValueTypeNames->DoubleArray, MjcPhysicsTokens->mjcSolimpfriction, pxr::VtArray(joint->solimp_friction, joint->solimp_friction + mjNIMP)); - WriteUniformAttribute(joint_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcStiffness, joint->stiffness); - WriteUniformAttribute(joint_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcActuatorfrcrangeMin, joint->actfrcrange[0]); - WriteUniformAttribute(joint_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcActuatorfrcrangeMax, joint->actfrcrange[1]); @@ -2065,35 +2068,35 @@ class ModelWriter { } else if (joint->actfrclimited == mjLIMITED_FALSE) { actuatorfrclimited_token = MjcPhysicsTokens->false_; } - WriteUniformAttribute(joint_path, pxr::SdfValueTypeNames->Token, + WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Token, MjcPhysicsTokens->mjcActuatorfrclimited, actuatorfrclimited_token); - WriteUniformAttribute(joint_path, pxr::SdfValueTypeNames->Bool, + WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Bool, MjcPhysicsTokens->mjcActuatorgravcomp, static_cast(joint->actgravcomp)); - WriteUniformAttribute(joint_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcMargin, joint->margin); - WriteUniformAttribute(joint_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcRef, joint->ref); - WriteUniformAttribute(joint_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcSpringref, joint->springref); - WriteUniformAttribute(joint_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcArmature, joint->armature); - WriteUniformAttribute(joint_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcDamping, joint->damping); - WriteUniformAttribute(joint_path, pxr::SdfValueTypeNames->Double, + WriteUniformAttribute(joint_spec, pxr::SdfValueTypeNames->Double, MjcPhysicsTokens->mjcFrictionloss, joint->frictionloss); } if (joint_id >= 0) { - joint_paths_[joint_id] = joint_path; + joint_paths_[joint_id] = joint_spec->GetPath(); } } @@ -2103,14 +2106,14 @@ class ModelWriter { pxr::UsdGeomTokens->Camera, body_path); // Create a root Xform for the world body with the model name if it exists // otherwise called 'World'. - pxr::SdfPath camera_path = - CreatePrimSpec(data_, body_path, name, pxr::UsdGeomTokens->Camera); + auto camera_spec = + CreatePrimSpec(layer_, body_path, name, pxr::UsdGeomTokens->Camera); int cam_id = mjs_getId(spec_cam->element); auto transform = MujocoPosQuatToTransform(&model_->cam_pos[3 * cam_id], &model_->cam_quat[4 * cam_id]); - WriteTransformXformOp(camera_path, transform); - WriteXformOpOrder(camera_path, + WriteTransformXformOp(camera_spec, transform); + WriteXformOpOrder(camera_spec, pxr::VtArray{kTokens->xformOpTransform}); // If the camera intrinsics are specified, then it is important that we @@ -2134,15 +2137,15 @@ class ModelWriter { (cam_sensorsize[0] / 2.f - cam_intrinsic[2]) : vertical_apperture * aspect_ratio; - WriteUniformAttribute(camera_path, pxr::SdfValueTypeNames->Float2, + WriteUniformAttribute(camera_spec, pxr::SdfValueTypeNames->Float2, pxr::UsdGeomTokens->clippingRange, pxr::GfVec2f(znear, zfar)); - WriteUniformAttribute(camera_path, pxr::SdfValueTypeNames->Float, + WriteUniformAttribute(camera_spec, pxr::SdfValueTypeNames->Float, pxr::UsdGeomTokens->focalLength, znear); - WriteUniformAttribute(camera_path, pxr::SdfValueTypeNames->Float, + WriteUniformAttribute(camera_spec, pxr::SdfValueTypeNames->Float, pxr::UsdGeomTokens->verticalAperture, vertical_apperture); - WriteUniformAttribute(camera_path, pxr::SdfValueTypeNames->Float, + WriteUniformAttribute(camera_spec, pxr::SdfValueTypeNames->Float, pxr::UsdGeomTokens->horizontalAperture, horizontal_aperture); } @@ -2161,14 +2164,14 @@ class ModelWriter { kTokens->light, body_path); // Create a root Xform for the world body with the model name if it exists // otherwise called 'World'. - pxr::SdfPath light_path = - CreatePrimSpec(data_, body_path, name, pxr::UsdLuxTokens->SphereLight); + auto light_spec = + CreatePrimSpec(layer_, body_path, name, pxr::UsdLuxTokens->SphereLight); int light_id = mjs_getId(light->element); auto transform = MujocoPosQuatToTransform(&model_->light_pos[3 * light_id], &model_->light_dir[4 * light_id]); - WriteTransformXformOp(light_path, transform); - WriteXformOpOrder(light_path, + WriteTransformXformOp(light_spec, transform); + WriteXformOpOrder(light_spec, pxr::VtArray{kTokens->xformOpTransform}); } @@ -2189,13 +2192,13 @@ class ModelWriter { pxr::TfToken body_name = GetValidPrimName(*mjs_getName(body->element)); // Create Xform prim for body. - pxr::SdfPath body_path = CreatePrimSpec(data_, parent_path, body_name, + auto body_spec = CreatePrimSpec(layer_, parent_path, body_name, pxr::UsdGeomTokens->Xform); // The parent_path will be a component which makes the actual articulated // bodies subcomponents. auto kind = parent_id == kWorldIndex ? pxr::KindTokens->component : pxr::KindTokens->subcomponent; - SetPrimKind(data_, body_path, kind); + SetPrimKind(layer_, body_spec, kind); // If the parent is not the world body, but is child of the world body // then we need to apply the articulation root API. @@ -2205,7 +2208,7 @@ class ModelWriter { // there are multiple children. if (parent_parent_id == kWorldIndex && articulation_roots_.find(parent_id) == articulation_roots_.end()) { - ApplyApiSchema(data_, parent_path, + ApplyApiSchema(layer_, layer_->GetPrimAtPath(parent_path), pxr::UsdPhysicsTokens->PhysicsArticulationRootAPI); articulation_roots_.insert(parent_id); } @@ -2224,32 +2227,32 @@ class ModelWriter { // User might have specified the inertia via fullinertia and the // compiler has extracted all values properly. So leverage those // instead of doing the computation ourselves here. - ApplyApiSchema(data_, body_path, pxr::UsdPhysicsTokens->PhysicsMassAPI); - WriteUniformAttribute(body_path, pxr::SdfValueTypeNames->Float, + ApplyApiSchema(layer_, body_spec, pxr::UsdPhysicsTokens->PhysicsMassAPI); + WriteUniformAttribute(body_spec, pxr::SdfValueTypeNames->Float, pxr::UsdPhysicsTokens->physicsMass, (float)model_->body_mass[body_id]); mjtNum *body_ipos = &model_->body_ipos[body_id * 3]; pxr::GfVec3f inertial_pos(body_ipos[0], body_ipos[1], body_ipos[2]); - WriteUniformAttribute(body_path, pxr::SdfValueTypeNames->Point3f, + WriteUniformAttribute(body_spec, pxr::SdfValueTypeNames->Point3f, pxr::UsdPhysicsTokens->physicsCenterOfMass, inertial_pos); mjtNum *body_iquat = &model_->body_iquat[body_id * 4]; pxr::GfQuatf inertial_frame(body_iquat[0], body_iquat[1], body_iquat[2], body_iquat[3]); - WriteUniformAttribute(body_path, pxr::SdfValueTypeNames->Quatf, + WriteUniformAttribute(body_spec, pxr::SdfValueTypeNames->Quatf, pxr::UsdPhysicsTokens->physicsPrincipalAxes, inertial_frame); mjtNum *inertia = &model_->body_inertia[body_id * 3]; pxr::GfVec3f diag_inertia(inertia[0], inertia[1], inertia[2]); - WriteUniformAttribute(body_path, pxr::SdfValueTypeNames->Float3, + WriteUniformAttribute(body_spec, pxr::SdfValueTypeNames->Float3, pxr::UsdPhysicsTokens->physicsDiagonalInertia, diag_inertia); } - ApplyApiSchema(data_, body_path, + ApplyApiSchema(layer_, body_spec, pxr::UsdPhysicsTokens->PhysicsRigidBodyAPI); // Create classes if necessary @@ -2258,32 +2261,31 @@ class ModelWriter { pxr::TfToken body_class_name = GetValidPrimName(*mjs_getName(spec_default->element)); pxr::SdfPath body_class_path = class_path_.AppendChild(body_class_name); - if (!data_->HasSpec(body_class_path)) { - CreateClassSpec(data_, class_path_, body_class_name); + if (!layer_->HasSpec(body_class_path)) { + CreateClassSpec(layer_, class_path_, body_class_name); } // Create XformOp attribute for body transform. - pxr::SdfPath xform_op_path = - CreateAttributeSpec(data_, body_path, kTokens->xformOpTransform, + auto xform_op_spec = + CreateAttributeSpec(layer_, body_spec, kTokens->xformOpTransform, pxr::SdfValueTypeNames->Matrix4d); // mjModel will have all frames already accounted for so no need to worry // about them here. auto body_xform = MujocoPosQuatToTransform(&model_->body_pos[body_id * 3], &model_->body_quat[body_id * 4]); - SetAttributeDefault(data_, xform_op_path, body_xform); + SetAttributeDefault(layer_, xform_op_spec, body_xform); // Create XformOpOrder attribute for body transform order. // For us this is simply the transform we authored above. - WriteXformOpOrder(body_path, + WriteXformOpOrder(body_spec, pxr::VtArray{kTokens->xformOpTransform}); pxr::VtDictionary customData; customData[kTokens->body_name] = *mjs_getName(body->element); - SetPrimMetadata(data_, body_path, pxr::SdfFieldKeys->CustomData, - customData); + body_spec->SetField(pxr::SdfFieldKeys->CustomData, customData); - body_paths_[body_id] = body_path; + body_paths_[body_id] = body_spec->GetPath(); } void WriteBodies() { @@ -2304,35 +2306,31 @@ class ModelWriter { } } - pxr::SdfPath WriteWorldBody(const size_t body_index) { + pxr::SdfPrimSpecHandle WriteWorldBody(const size_t body_index) { // Create a root Xform for the world body with the model name if it exists // otherwise called 'World'. auto name = GetAvailablePrimName(*spec_->modelname, kTokens->world, pxr::SdfPath::AbsoluteRootPath()); - pxr::SdfPath world_group_path = - CreatePrimSpec(data_, pxr::SdfPath::AbsoluteRootPath(), name, + auto world_group_spec = + CreatePrimSpec(layer_, pxr::SdfPath::AbsoluteRootPath(), name, pxr::UsdGeomTokens->Xform); - SetPrimKind(data_, world_group_path, pxr::KindTokens->group); + SetPrimKind(layer_, world_group_spec, pxr::KindTokens->group); - return world_group_path; + return world_group_spec; } }; namespace mujoco { namespace usd { -bool WriteSpecToData(mjSpec *spec, pxr::SdfAbstractDataRefPtr &data) { - // Create pseudo root first. - data->CreateSpec(pxr::SdfPath::AbsoluteRootPath(), - pxr::SdfSpecTypePseudoRoot); - +bool WriteSpecToData(mjSpec *spec, pxr::SdfLayerRefPtr layer) { mjModel *model = mj_compile(spec, nullptr); if (model == nullptr) { TF_ERROR(MujocoCompilationError, "%s", mjs_getError(spec)); return false; } - ModelWriter(spec, model, data).Write(); + ModelWriter(spec, model, layer).Write(); return true; } diff --git a/src/experimental/usd/plugins/mjcf/mujoco_to_usd.h b/src/experimental/usd/plugins/mjcf/mujoco_to_usd.h index 4c5934c6..6c4205be 100644 --- a/src/experimental/usd/plugins/mjcf/mujoco_to_usd.h +++ b/src/experimental/usd/plugins/mjcf/mujoco_to_usd.h @@ -16,16 +16,16 @@ #define MUJOCO_SRC_EXPERIMENTAL_USD_PLUGINS_MJCF_MUJOCO_TO_USD_H_ #include -#include +#include namespace mujoco { namespace usd { -// Given an mjSpec, write it to a SdfAbstractData. +// Given an mjSpec, writes a USD representation of the data to the given layer. // // Args: // spec: mjSpec built programmatically or via parsed XML. -// data: SdfAbstractDataRefPtr that will be written to. -bool WriteSpecToData(mjSpec* spec, pxr::SdfAbstractDataRefPtr& data); +// layer: SdfLayerRefPtr that will be written to. +bool WriteSpecToData(mjSpec* spec, pxr::SdfLayerRefPtr layer); } // namespace usd } // namespace mujoco diff --git a/src/experimental/usd/plugins/mjcf/utils.cc b/src/experimental/usd/plugins/mjcf/utils.cc index db2eae85..b8c5f894 100644 --- a/src/experimental/usd/plugins/mjcf/utils.cc +++ b/src/experimental/usd/plugins/mjcf/utils.cc @@ -15,13 +15,16 @@ #include "mjcf/utils.h" #include -#include #include -#include +#include +#include +#include #include #include +#include #include +#include #include #include #include @@ -30,184 +33,122 @@ namespace { template -void AppendChild(pxr::SdfAbstractDataRefPtr& data, const pxr::SdfPath& specPath, - const pxr::TfToken& childKey, const T& child) { - // Get existing children. - std::vector children; - pxr::SdfAbstractDataTypedValue> getter(&children); - data->Has(specPath, childKey, &getter); - - children.push_back(child); - data->Set(specPath, childKey, - pxr::SdfAbstractDataConstTypedValue>(&children)); -} - -template -void AppendListOp(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& spec_path, const pxr::TfToken& field, +void AppendListOp(pxr::SdfLayerRefPtr layer, + const pxr::SdfPrimSpecHandle& prim_spec, const pxr::TfToken& field, const T& item) { - // Get existing list op. - pxr::SdfListOp list_op; - pxr::SdfAbstractDataTypedValue> getter(&list_op); - data->Has(spec_path, field, &getter); - - auto items = list_op.GetExplicitItems(); + pxr::SdfListOp listOp = + prim_spec->GetInfo(field).Get>(); + auto items = listOp.GetExplicitItems(); items.push_back(item); - list_op.SetExplicitItems(items); - data->Set(spec_path, field, - pxr::SdfAbstractDataConstTypedValue>(&list_op)); + listOp.SetExplicitItems(items); + prim_spec->SetInfo(field, pxr::VtValue::Take(listOp)); } template -void PrependListOp(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& spec_path, const pxr::TfToken& field, +void PrependListOp(pxr::SdfLayerRefPtr layer, + const pxr::SdfPrimSpecHandle& prim_spec, const pxr::TfToken& field, const T& item) { - // Get existing list op. - pxr::SdfListOp listOp; - pxr::SdfAbstractDataTypedValue> getter(&listOp); - data->Has(spec_path, field, &getter); - + pxr::SdfListOp listOp = + prim_spec->GetInfo(field).Get>(); auto prependedItems = listOp.GetPrependedItems(); prependedItems.insert(prependedItems.begin(), item); listOp.SetPrependedItems(prependedItems); - data->Set(spec_path, field, - pxr::SdfAbstractDataConstTypedValue>(&listOp)); + prim_spec->SetInfo(field, pxr::VtValue::Take(listOp)); } } // namespace namespace mujoco { namespace usd { -pxr::SdfPath CreatePrimSpec(pxr::SdfAbstractDataRefPtr& data, +pxr::SdfPrimSpecHandle CreatePrimSpec(pxr::SdfLayerRefPtr layer, const pxr::SdfPath& parent_path, const pxr::TfToken& name, const pxr::TfToken& type, pxr::SdfSpecifier specifier) { const pxr::SdfPath prim_path = parent_path.AppendChild(name); - data->CreateSpec(prim_path, pxr::SdfSpecTypePrim); - data->Set(prim_path, pxr::SdfFieldKeys->Specifier, - pxr::SdfAbstractDataConstTypedValue(&specifier)); + pxr::SdfPrimSpecHandle prim_spec = pxr::SdfCreatePrimInLayer(layer, prim_path); + layer->SetField(prim_path, pxr::SdfFieldKeys->Specifier, specifier); if (!type.IsEmpty()) { - data->Set(prim_path, pxr::SdfFieldKeys->TypeName, - pxr::SdfAbstractDataConstTypedValue(&type)); + layer->SetField(prim_path, pxr::SdfFieldKeys->TypeName, type); } - AppendChild(data, parent_path, pxr::SdfChildrenKeys->PrimChildren, name); - - return prim_path; + return prim_spec; } -pxr::SdfPath CreateAttributeSpec(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& prim_path, +pxr::SdfAttributeSpecHandle CreateAttributeSpec(pxr::SdfLayerRefPtr layer, + const pxr::SdfPrimSpecHandle& prim_spec, const pxr::TfToken& name, const pxr::SdfValueTypeName& type_name, pxr::SdfVariability variability) { - const pxr::SdfPath propertyPath = prim_path.AppendProperty(name); + const pxr::SdfPath propertyPath = prim_spec->GetPath().AppendProperty(name); // Early exit if the attribute spec already exists. - if (data->HasSpec(propertyPath)) { - return propertyPath; + if (layer->HasSpec(propertyPath)) { + return layer->GetAttributeAtPath(propertyPath); } - data->CreateSpec(propertyPath, pxr::SdfSpecTypeAttribute); + auto spec = pxr::SdfAttributeSpec::New(prim_spec, + name, type_name, variability); - pxr::TfToken typeNameToken = type_name.GetAsToken(); - data->Set(propertyPath, pxr::SdfFieldKeys->TypeName, - pxr::SdfAbstractDataConstTypedValue(&typeNameToken)); - if (variability != pxr::SdfVariabilityVarying) { - data->Set( - propertyPath, pxr::SdfFieldKeys->Variability, - pxr::SdfAbstractDataConstTypedValue(&variability)); - } - - AppendChild(data, prim_path, pxr::SdfChildrenKeys->PropertyChildren, name); - - return propertyPath; + return spec; } -pxr::SdfPath CreateRelationshipSpec(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& prim_path, +pxr::SdfRelationshipSpecHandle CreateRelationshipSpec(pxr::SdfLayerRefPtr layer, + const pxr::SdfPrimSpecHandle& prim_spec, const pxr::TfToken& relationship_name, const pxr::SdfPath& relationship_path, pxr::SdfVariability variability) { - pxr::SdfPath prop_path = prim_path.AppendProperty(relationship_name); - data->CreateSpec(prop_path, pxr::SdfSpecTypeRelationship); - if (variability != pxr::SdfVariabilityVarying) { - data->Set( - prop_path, pxr::SdfFieldKeys->Variability, - pxr::SdfAbstractDataConstTypedValue(&variability)); - } + auto spec = pxr::SdfRelationshipSpec::New(prim_spec, relationship_name); + spec->GetTargetPathList().Append(relationship_path); - AppendChild(data, prim_path, pxr::SdfChildrenKeys->PropertyChildren, - relationship_name); - - AppendChild(data, prop_path, pxr::SdfChildrenKeys->RelationshipTargetChildren, - relationship_path); - AppendListOp(data, prop_path, pxr::SdfFieldKeys->TargetPaths, - relationship_path); - - pxr::SdfPath target_path = prop_path.AppendTarget(relationship_path); - data->CreateSpec(target_path, pxr::SdfSpecTypeRelationshipTarget); - - return prop_path; + return spec; } -pxr::SdfPath CreateClassSpec(pxr::SdfAbstractDataRefPtr& data, +pxr::SdfPrimSpecHandle CreateClassSpec(pxr::SdfLayerRefPtr layer, const pxr::SdfPath& prim_path, const pxr::TfToken& class_name) { pxr::SdfPath class_path = prim_path.AppendChild(class_name); - pxr::SdfSpecifier class_specifier = pxr::SdfSpecifier::SdfSpecifierClass; - data->CreateSpec(class_path, pxr::SdfSpecTypePrim); - data->Set( - class_path, pxr::SdfFieldKeys->Specifier, - pxr::SdfAbstractDataConstTypedValue(&class_specifier)); + pxr::SdfPrimSpecHandle prim_spec = pxr::SdfCreatePrimInLayer(layer, class_path); + layer->SetField(class_path, pxr::SdfFieldKeys->Specifier, pxr::SdfSpecifier::SdfSpecifierClass); - AppendChild(data, prim_path, pxr::SdfChildrenKeys->PrimChildren, class_name); - - return class_path; + return prim_spec; } -void AddAttributeConnection(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& attribute_path, - const pxr::SdfPath& target_attribute_path) { - AppendChild(data, attribute_path, pxr::SdfChildrenKeys->ConnectionChildren, - target_attribute_path); - AppendListOp(data, attribute_path, pxr::SdfFieldKeys->ConnectionPaths, - target_attribute_path); - - data->CreateSpec(attribute_path.AppendTarget(target_attribute_path), - pxr::SdfSpecTypeConnection); +void AddAttributeConnection(pxr::SdfLayerRefPtr layer, + const pxr::SdfAttributeSpecHandle& attribute_spec, + const pxr::SdfAttributeSpecHandle& target_attribute_spec) { + attribute_spec->GetConnectionPathList().GetExplicitItems() = {target_attribute_spec->GetPath()}; } -void AddPrimReference(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& prim_path, +void AddPrimReference(pxr::SdfLayerRefPtr layer, + const pxr::SdfPrimSpecHandle& prim_spec, const pxr::SdfPath& referenced_prim_path) { - PrependListOp(data, prim_path, pxr::SdfFieldKeys->References, + PrependListOp(layer, prim_spec, pxr::SdfFieldKeys->References, pxr::SdfReference("", referenced_prim_path)); } -void AddPrimInherit(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& prim_path, +void AddPrimInherit(pxr::SdfLayerRefPtr layer, + const pxr::SdfPrimSpecHandle& prim_spec, const pxr::SdfPath& class_path) { - PrependListOp(data, prim_path, pxr::SdfFieldKeys->InheritPaths, class_path); + PrependListOp(layer, prim_spec, pxr::SdfFieldKeys->InheritPaths, class_path); } -void ApplyApiSchema(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& prim_path, +void ApplyApiSchema(pxr::SdfLayerRefPtr layer, + const pxr::SdfPrimSpecHandle& prim_spec, const pxr::TfToken& schema_name) { - PrependListOp(data, prim_path, pxr::UsdTokens->apiSchemas, schema_name); + PrependListOp(layer, prim_spec, pxr::UsdTokens->apiSchemas, schema_name); } -void SetPrimKind(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& prim_path, pxr::TfToken kind) { - SetPrimMetadata(data, prim_path, pxr::TfToken("kind"), kind); +void SetPrimKind(pxr::SdfLayerRefPtr layer, + const pxr::SdfPrimSpecHandle& prim_spec, pxr::TfToken kind) { + prim_spec->SetField(pxr::SdfFieldKeys->Kind, kind); } -void SetPrimPurpose(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& prim_path, pxr::TfToken purpose) { - const pxr::SdfPath attr_path = CreateAttributeSpec( - data, prim_path, pxr::UsdGeomTokens->purpose, +void SetPrimPurpose(pxr::SdfLayerRefPtr layer, + const pxr::SdfPrimSpecHandle& prim_spec, pxr::TfToken purpose) { + const pxr::SdfAttributeSpecHandle& attr = CreateAttributeSpec( + layer, prim_spec, pxr::UsdGeomTokens->purpose, pxr::SdfValueTypeNames->Token, pxr::SdfVariabilityUniform); - SetAttributeDefault(data, attr_path, purpose); + SetAttributeDefault(layer, attr, purpose); } } // namespace usd diff --git a/src/experimental/usd/plugins/mjcf/utils.h b/src/experimental/usd/plugins/mjcf/utils.h index 5b7ad71c..671963fb 100644 --- a/src/experimental/usd/plugins/mjcf/utils.h +++ b/src/experimental/usd/plugins/mjcf/utils.h @@ -15,11 +15,11 @@ #ifndef MUJOCO_SRC_EXPERIMENTAL_USD_PLUGINS_MJCF_UTILS_H_ #define MUJOCO_SRC_EXPERIMENTAL_USD_PLUGINS_MJCF_UTILS_H_ -#include - #include #include -#include +#include +#include +#include #include #include #include @@ -29,123 +29,97 @@ namespace mujoco { namespace usd { // Create a prim spec and append it as a child of parent_path. -pxr::SdfPath CreatePrimSpec( - pxr::SdfAbstractDataRefPtr& data, const pxr::SdfPath& parent_path, +pxr::SdfPrimSpecHandle CreatePrimSpec( + pxr::SdfLayerRefPtr layer, const pxr::SdfPath& parent_path, const pxr::TfToken& name, const pxr::TfToken& type = pxr::TfToken(), pxr::SdfSpecifier specifier = pxr::SdfSpecifier::SdfSpecifierDef); // Create an attribute spec and append it as a child of parent_path. // By default the attribute will be varying. -pxr::SdfPath CreateAttributeSpec( - pxr::SdfAbstractDataRefPtr& data, const pxr::SdfPath& prim_path, +pxr::SdfAttributeSpecHandle CreateAttributeSpec( + pxr::SdfLayerRefPtr layer, const pxr::SdfPrimSpecHandle& prim_spec, const pxr::TfToken& name, const pxr::SdfValueTypeName& type_name, pxr::SdfVariability variability = pxr::SdfVariabilityVarying); // Create a relationship spec and append it as a child of prim_path. -pxr::SdfPath CreateRelationshipSpec( - pxr::SdfAbstractDataRefPtr& data, const pxr::SdfPath& prim_path, +pxr::SdfRelationshipSpecHandle CreateRelationshipSpec( + pxr::SdfLayerRefPtr layer, const pxr::SdfPrimSpecHandle& prim_spec, const pxr::TfToken& relationship_name, const pxr::SdfPath& relationship_path, pxr::SdfVariability variability = pxr::SdfVariabilityVarying); -pxr::SdfPath CreateClassSpec(pxr::SdfAbstractDataRefPtr& data, +pxr::SdfPrimSpecHandle CreateClassSpec(pxr::SdfLayerRefPtr layer, const pxr::SdfPath& prim_path, const pxr::TfToken& class_name); -void AddAttributeConnection(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& attribute_path, - const pxr::SdfPath& target_attribute_path); +void AddAttributeConnection(pxr::SdfLayerRefPtr layer, + const pxr::SdfAttributeSpecHandle& attribute_spec, + const pxr::SdfAttributeSpecHandle& target_attribute_spec); -void AddPrimReference(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& prim_path, +void AddPrimReference(pxr::SdfLayerRefPtr layer, + const pxr::SdfPrimSpecHandle& prim_spec, const pxr::SdfPath& referenced_prim_path); -void AddPrimInherit(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& prim_path, +void AddPrimInherit(pxr::SdfLayerRefPtr layer, + const pxr::SdfPrimSpecHandle& prim_spec, const pxr::SdfPath& class_path); -void ApplyApiSchema(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& prim_path, +void ApplyApiSchema(pxr::SdfLayerRefPtr layer, + const pxr::SdfPrimSpecHandle& prim_spec, const pxr::TfToken& schema_name); -void SetPrimKind(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& prim_path, pxr::TfToken kind); +void SetPrimKind(pxr::SdfLayerRefPtr layer, + const pxr::SdfPrimSpecHandle& prim_spec, pxr::TfToken kind); -void SetPrimPurpose(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& prim_path, pxr::TfToken purpose); +void SetPrimPurpose(pxr::SdfLayerRefPtr layer, + const pxr::SdfPrimSpecHandle& prim_spec, pxr::TfToken purpose); // Set the value specified by key on any field at field_path. template -void SetField(pxr::SdfAbstractDataRefPtr& data, const pxr::SdfPath& field_path, +void SetField(pxr::SdfLayerRefPtr layer, const pxr::SdfPath& field_path, const pxr::TfToken key, T&& value) { - using Deduced = typename std::remove_reference_t; - const auto typed_val = pxr::SdfAbstractDataConstTypedValue(&value); - const pxr::SdfAbstractDataConstValue& untyped_val = typed_val; - - data->Set(field_path, key, untyped_val); + layer->SetField(field_path, key, value); } // Set the value specified by key on any field at field_path. template -void SetFieldTimeSample(pxr::SdfAbstractDataRefPtr& data, +void SetFieldTimeSample(pxr::SdfLayerRefPtr layer, const pxr::SdfPath& field_path, double time, T&& value) { - using Deduced = typename std::remove_reference_t; - const auto typed_val = pxr::SdfAbstractDataConstTypedValue(&value); - const pxr::SdfAbstractDataConstValue& untyped_val = typed_val; - - pxr::VtValue vt_value; - untyped_val.GetValue(&vt_value); - // NOTE: SetTimeSample doesn't accept an SdfAbstractDataConstValue yet. - data->SetTimeSample(field_path, time, vt_value); + layer->SetTimeSample(field_path, time, value); } + // Set the value specified by key on an attribute spec at attribute_path. template -void SetAttribute(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& attribute_path, const pxr::TfToken key, - T&& value) { - SetField(data, attribute_path, key, value); -} - -// Set the value specified by key on a prim spec at prim_path. -template -void SetPrimMetadata(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& prim_path, const pxr::TfToken key, - T&& value) { - SetAttribute(data, prim_path, key, value); -} - -// Set the value specified by key on an attribute spec at attribute_path. -template -void SetAttributeMetadata(pxr::SdfAbstractDataRefPtr& data, +void SetAttributeMetadata(pxr::SdfLayerRefPtr layer, const pxr::SdfPath& attribute_path, const pxr::TfToken key, T&& value) { - SetAttribute(data, attribute_path, key, value); + SetAttribute(layer, attribute_path, key, value); } // Set the default value on an attribute spec at attribute_path. template -void SetAttributeDefault(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& attribute_path, +void SetAttributeDefault(pxr::SdfLayerRefPtr layer, + const pxr::SdfAttributeSpecHandle& attribute, T&& default_value) { - SetAttribute(data, attribute_path, pxr::SdfFieldKeys->Default, default_value); + attribute->SetField(pxr::SdfFieldKeys->Default, default_value); } // Set the default value on an attribute spec at attribute_path. template -void SetAttributeTimeSample(pxr::SdfAbstractDataRefPtr& data, - const pxr::SdfPath& attribute_path, +void SetAttributeTimeSample(pxr::SdfLayerRefPtr layer, + const pxr::SdfAttributeSpecHandle& attr_spec, double time, T&& default_value) { - SetFieldTimeSample(data, attribute_path, time, default_value); + layer->SetTimeSample(attr_spec->GetPath(), time, default_value); } // Set the value specified by key on the root layer. template -void SetLayerMetadata(pxr::SdfAbstractDataRefPtr& data, const pxr::TfToken& key, +void SetLayerMetadata(pxr::SdfLayerRefPtr layer, const pxr::TfToken& key, T&& value) { - SetAttribute(data, pxr::SdfPath::AbsoluteRootPath(), key, value); + layer->SetField(pxr::SdfPath::AbsoluteRootPath(), key, value); } } // namespace usd