Add support for parsing 'st' primvar from USD.
PiperOrigin-RevId: 786277487 Change-Id: Id99e6bf6a656b623950c363597da3930ee4c00e3
This commit is contained in:
committed by
Copybara-Service
parent
4f43a7d08e
commit
8383bd439c
@@ -264,10 +264,13 @@ bool MaybeParseGeomPrimitive(const pxr::UsdPrim& prim, T* element,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
mjsMesh* ParseUsdMesh(mjSpec* spec, const pxr::UsdPrim& prim, mjsGeom* geom, pxr::UsdGeomXformCache& xform_cache) {
|
mjsMesh* ParseUsdMesh(mjSpec* spec, const pxr::UsdPrim& prim, mjsGeom* geom,
|
||||||
|
pxr::UsdGeomXformCache& xform_cache) {
|
||||||
if (!prim.IsA<pxr::UsdGeomMesh>()) {
|
if (!prim.IsA<pxr::UsdGeomMesh>()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
mjsMesh* mesh = mjs_addMesh(spec, nullptr);
|
||||||
|
|
||||||
geom->type = mjGEOM_MESH;
|
geom->type = mjGEOM_MESH;
|
||||||
pxr::UsdGeomMesh usd_mesh(prim);
|
pxr::UsdGeomMesh usd_mesh(prim);
|
||||||
std::vector<float> uservert;
|
std::vector<float> uservert;
|
||||||
@@ -276,6 +279,15 @@ mjsMesh* ParseUsdMesh(mjSpec* spec, const pxr::UsdPrim& prim, mjsGeom* geom, pxr
|
|||||||
pxr::VtVec3fArray points;
|
pxr::VtVec3fArray points;
|
||||||
usd_mesh.GetPointsAttr().Get(&points);
|
usd_mesh.GetPointsAttr().Get(&points);
|
||||||
|
|
||||||
|
pxr::VtVec2fArray uvs;
|
||||||
|
pxr::VtIntArray uv_indices;
|
||||||
|
std::vector<float> texcoord;
|
||||||
|
std::vector<int> userfacetexcoord;
|
||||||
|
|
||||||
|
pxr::UsdGeomPrimvarsAPI primvarsAPI(prim);
|
||||||
|
pxr::UsdGeomPrimvar st_primvar =
|
||||||
|
primvarsAPI.FindPrimvarWithInheritance(pxr::TfToken("st"));
|
||||||
|
|
||||||
uservert.reserve(points.size() * 3);
|
uservert.reserve(points.size() * 3);
|
||||||
for (const auto& pt : points) {
|
for (const auto& pt : points) {
|
||||||
uservert.push_back(pt[0]);
|
uservert.push_back(pt[0]);
|
||||||
@@ -283,6 +295,40 @@ mjsMesh* ParseUsdMesh(mjSpec* spec, const pxr::UsdPrim& prim, mjsGeom* geom, pxr
|
|||||||
uservert.push_back(pt[2]);
|
uservert.push_back(pt[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool has_uvs = st_primvar.HasAuthoredValue();
|
||||||
|
bool face_varying_uvs = has_uvs && st_primvar.GetInterpolation() ==
|
||||||
|
pxr::UsdGeomTokens->faceVarying;
|
||||||
|
bool st_indexed = st_primvar.IsIndexed();
|
||||||
|
if (has_uvs) {
|
||||||
|
pxr::VtVec2fArray uvs;
|
||||||
|
st_primvar.Get(&uvs);
|
||||||
|
|
||||||
|
if (st_indexed) {
|
||||||
|
st_primvar.GetIndices(&uv_indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the UVs do not vary per point per face, then we need to compute the
|
||||||
|
// effective uv array taking indexing into account as we do not support UV
|
||||||
|
// indexing in mujoco.
|
||||||
|
if (!face_varying_uvs && st_primvar.IsIndexed()) {
|
||||||
|
texcoord.reserve(uv_indices.size() * 2);
|
||||||
|
for (const auto& idx : uv_indices) {
|
||||||
|
auto uv = uvs[idx];
|
||||||
|
texcoord.push_back(uv[0]);
|
||||||
|
// USD origin is bottom left, MuJoCo is top left.
|
||||||
|
texcoord.push_back(1.0f - uv[1]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
texcoord.reserve(uvs.size() * 2);
|
||||||
|
for (const auto& uv : uvs) {
|
||||||
|
texcoord.push_back(uv[0]);
|
||||||
|
// USD origin is bottom left, MuJoCo is top left.
|
||||||
|
texcoord.push_back(1.0f - uv[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mjs_setFloat(mesh->usertexcoord, texcoord.data(), texcoord.size());
|
||||||
|
}
|
||||||
|
|
||||||
pxr::VtIntArray indices;
|
pxr::VtIntArray indices;
|
||||||
usd_mesh.GetFaceVertexIndicesAttr().Get(&indices);
|
usd_mesh.GetFaceVertexIndicesAttr().Get(&indices);
|
||||||
pxr::VtIntArray counts;
|
pxr::VtIntArray counts;
|
||||||
@@ -298,13 +344,22 @@ mjsMesh* ParseUsdMesh(mjSpec* spec, const pxr::UsdPrim& prim, mjsGeom* geom, pxr
|
|||||||
userface.push_back(indices[vtx_idx]);
|
userface.push_back(indices[vtx_idx]);
|
||||||
userface.push_back(indices[vtx_idx + k]);
|
userface.push_back(indices[vtx_idx + k]);
|
||||||
userface.push_back(indices[vtx_idx + k + 1]);
|
userface.push_back(indices[vtx_idx + k + 1]);
|
||||||
|
|
||||||
|
// If the UVs vary per face, then we need to compute the effective
|
||||||
|
// index array after we've created the triangle fan for non triangular
|
||||||
|
// faces.
|
||||||
|
if (face_varying_uvs) {
|
||||||
|
userfacetexcoord.push_back(st_indexed ? uv_indices[vtx_idx] : vtx_idx);
|
||||||
|
userfacetexcoord.push_back(st_indexed ? uv_indices[vtx_idx + k]
|
||||||
|
: vtx_idx + k);
|
||||||
|
userfacetexcoord.push_back(st_indexed ? uv_indices[vtx_idx + k + 1]
|
||||||
|
: vtx_idx + k + 1);
|
||||||
|
}
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
vtx_idx += count;
|
vtx_idx += count;
|
||||||
}
|
}
|
||||||
|
|
||||||
mjsMesh* mesh = mjs_addMesh(spec, nullptr);
|
|
||||||
|
|
||||||
auto world_xform = xform_cache.GetLocalToWorldTransform(prim);
|
auto world_xform = xform_cache.GetLocalToWorldTransform(prim);
|
||||||
auto scale = GetScale(world_xform);
|
auto scale = GetScale(world_xform);
|
||||||
mesh->scale[0] = scale[0];
|
mesh->scale[0] = scale[0];
|
||||||
@@ -316,6 +371,11 @@ mjsMesh* ParseUsdMesh(mjSpec* spec, const pxr::UsdPrim& prim, mjsGeom* geom, pxr
|
|||||||
mjs_setFloat(mesh->uservert, uservert.data(), uservert.size());
|
mjs_setFloat(mesh->uservert, uservert.data(), uservert.size());
|
||||||
mjs_setInt(mesh->userface, userface.data(), userface.size());
|
mjs_setInt(mesh->userface, userface.data(), userface.size());
|
||||||
|
|
||||||
|
if (face_varying_uvs) {
|
||||||
|
mjs_setInt(mesh->userfacetexcoord, userfacetexcoord.data(),
|
||||||
|
userfacetexcoord.size());
|
||||||
|
}
|
||||||
|
|
||||||
mjs_setString(geom->meshname, mesh_name.c_str());
|
mjs_setString(geom->meshname, mesh_name.c_str());
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user