Add mjModel.mesh_scale: scaling applied to asset vertices.
PiperOrigin-RevId: 625083195 Change-Id: I36290282379e57ad23ec771d65d1bd6bf2a75b07
This commit is contained in:
committed by
Copybara-Service
parent
9f1651b7bd
commit
7b3f1a0261
@@ -2,6 +2,15 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
Upcoming version (not yet released)
|
||||
-----------------------------------
|
||||
|
||||
General
|
||||
^^^^^^^
|
||||
1. Added `mjModel.mesh_scale`: the scaling applied to asset vertices, as specified in the :ref:`scale<asset-mesh-scale>`
|
||||
attribute.
|
||||
|
||||
|
||||
Version 3.1.4 (April 10th, 2024)
|
||||
--------------------------------
|
||||
|
||||
|
||||
@@ -1165,6 +1165,7 @@ struct mjModel_ {
|
||||
int* mesh_facenormal; // normal face data (nmeshface x 3)
|
||||
int* mesh_facetexcoord; // texture face data (nmeshface x 3)
|
||||
int* mesh_graph; // convex graph data (nmeshgraph x 1)
|
||||
mjtNum* mesh_scale; // scaling applied to asset vertices (nmesh x 3)
|
||||
mjtNum* mesh_pos; // translation applied to asset vertices (nmesh x 3)
|
||||
mjtNum* mesh_quat; // rotation applied to asset vertices (nmesh x 4)
|
||||
int* mesh_pathadr; // address of asset path for mesh; -1: none (nmesh x 1)
|
||||
|
||||
@@ -880,6 +880,7 @@ struct mjModel_ {
|
||||
int* mesh_facenormal; // normal face data (nmeshface x 3)
|
||||
int* mesh_facetexcoord; // texture face data (nmeshface x 3)
|
||||
int* mesh_graph; // convex graph data (nmeshgraph x 1)
|
||||
mjtNum* mesh_scale; // scaling applied to asset vertices (nmesh x 3)
|
||||
mjtNum* mesh_pos; // translation applied to asset vertices (nmesh x 3)
|
||||
mjtNum* mesh_quat; // rotation applied to asset vertices (nmesh x 4)
|
||||
int* mesh_pathadr; // address of asset path for mesh; -1: none (nmesh x 1)
|
||||
|
||||
@@ -365,6 +365,7 @@
|
||||
XMJV( int, mesh_bvhadr, nmesh, 1 ) \
|
||||
XMJV( int, mesh_bvhnum, nmesh, 1 ) \
|
||||
XMJV( int, mesh_graphadr, nmesh, 1 ) \
|
||||
X ( mjtNum, mesh_scale, nmesh, 3 ) \
|
||||
X ( mjtNum, mesh_pos, nmesh, 3 ) \
|
||||
X ( mjtNum, mesh_quat, nmesh, 4 ) \
|
||||
X ( float, mesh_vert, nmeshvert, 3 ) \
|
||||
|
||||
@@ -2655,6 +2655,13 @@ STRUCTS: Mapping[str, StructDecl] = dict([
|
||||
),
|
||||
doc='convex graph data (nmeshgraph x 1)', # pylint: disable=line-too-long
|
||||
),
|
||||
StructFieldDecl(
|
||||
name='mesh_scale',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjtNum'),
|
||||
),
|
||||
doc='scaling applied to asset vertices (nmesh x 3)',
|
||||
),
|
||||
StructFieldDecl(
|
||||
name='mesh_pos',
|
||||
type=PointerType(
|
||||
|
||||
@@ -534,11 +534,15 @@ mjModel* mj_makeModel(
|
||||
m->nuser_actuator = nuser_actuator;
|
||||
m->nuser_sensor = nuser_sensor;
|
||||
m->nnames = nnames;
|
||||
m->nnames_map = mjLOAD_MULTIPLE
|
||||
* (nbody + njnt + ngeom + nsite + ncam + nlight + nflex + nmesh
|
||||
+ nskin + nhfield + ntex + nmat + npair + nexclude + neq
|
||||
+ ntendon + nu + nsensor + nnumeric + ntext + ntuple
|
||||
+ nkey + nplugin);
|
||||
long nnames_map = (long)nbody + njnt + ngeom + nsite + ncam + nlight + nflex + nmesh + nskin +
|
||||
nhfield + ntex + nmat + npair + nexclude + neq + ntendon + nu + nsensor +
|
||||
nnumeric + ntext + ntuple + nkey + nplugin;
|
||||
if (nnames_map >= INT_MAX / mjLOAD_MULTIPLE) {
|
||||
mju_free(m);
|
||||
mju_warning("Invalid model: size of nnames_map is larger than INT_MAX");
|
||||
return 0;
|
||||
}
|
||||
m->nnames_map = mjLOAD_MULTIPLE * nnames_map;
|
||||
m->npaths = npaths;
|
||||
|
||||
#define X(name) \
|
||||
|
||||
@@ -2123,6 +2123,7 @@ void mjCModel::CopyObjects(mjModel* m) {
|
||||
m->mesh_graphadr[i] = (pme->szgraph() ? graph_adr : -1);
|
||||
m->mesh_bvhnum[i] = pme->tree().nbvh;
|
||||
m->mesh_bvhadr[i] = pme->tree().nbvh ? bvh_adr : -1;
|
||||
copyvec(&m->mesh_scale[3 * i], pme->get_scale(), 3);
|
||||
copyvec(&m->mesh_pos[3 * i], pme->GetOffsetPosPtr(), 3);
|
||||
copyvec(&m->mesh_quat[4 * i], pme->GetOffsetQuatPtr(), 4);
|
||||
|
||||
|
||||
@@ -815,12 +815,12 @@ class mjCMesh: public mjCMesh_, private mjsMesh {
|
||||
const mjCBoundingVolumeHierarchy& tree() { return tree_; }
|
||||
|
||||
void Compile(const mjVFS* vfs); // compiler
|
||||
double* GetPosPtr(mjtGeomInertia type); // get position
|
||||
double* GetQuatPtr(mjtGeomInertia type); // get orientation
|
||||
double* GetPosPtr(mjtGeomInertia type); // get position
|
||||
double* GetQuatPtr(mjtGeomInertia type); // get orientation
|
||||
double* GetOffsetPosPtr(); // get position offset for geom
|
||||
double* GetOffsetQuatPtr(); // get orientation offset for geom
|
||||
double* GetInertiaBoxPtr(mjtGeomInertia type); // get inertia box
|
||||
double& GetVolumeRef(mjtGeomInertia type); // get volume
|
||||
double* GetInertiaBoxPtr(mjtGeomInertia type); // get inertia box
|
||||
double& GetVolumeRef(mjtGeomInertia type); // get volume
|
||||
void FitGeom(mjCGeom* geom, double* meshpos); // approximate mesh with simple geom
|
||||
bool HasTexcoord() const; // texcoord not null
|
||||
void DelTexcoord(); // delete texcoord
|
||||
@@ -852,7 +852,7 @@ class mjCMesh: public mjCMesh_, private mjsMesh {
|
||||
void ApplyTransformations(); // apply user transformations
|
||||
void ComputeFaceCentroid(double[3]); // compute centroid of all faces
|
||||
void RemoveRepeated(void); // remove repeated vertices
|
||||
void CheckMesh(mjtGeomInertia type); // check if the mesh is valid
|
||||
void CheckMesh(mjtGeomInertia type); // check if the mesh is valid
|
||||
|
||||
// mesh data to be copied into mjModel
|
||||
float* vert_; // vertex data (3*nvert), relative to (pos, quat)
|
||||
|
||||
@@ -58,6 +58,11 @@ static const char* const kDuplicateOBJPath =
|
||||
static const char* const kMalformedFaceOBJPath =
|
||||
"user/testdata/malformed_face.xml";
|
||||
|
||||
std::vector<mjtNum> AsVector(const mjtNum* array, int n) {
|
||||
return std::vector<mjtNum>(array, array + n);
|
||||
}
|
||||
|
||||
using ::testing::ElementsAre;
|
||||
using ::testing::HasSubstr;
|
||||
using ::testing::IsNull;
|
||||
using ::testing::NotNull;
|
||||
@@ -863,6 +868,27 @@ TEST_F(MjCMeshTest, MeshPosQuat) {
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
TEST_F(MjCMeshTest, MeshScale) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<asset>
|
||||
<mesh name="pyramid" vertex="0 0 0 1 0 0 0 1 0 0 0 1"/>
|
||||
<mesh name="pyramid_scaled" vertex="0 0 0 1 0 0 0 1 0 0 0 1" scale="0.9 1 -1"/>
|
||||
</asset>
|
||||
<worldbody>
|
||||
<geom type="mesh" name="geom1" mesh="pyramid"/>
|
||||
<geom type="mesh" name="geom2" mesh="pyramid_scaled"/>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
)";
|
||||
mjModel* model = LoadModelFromString(xml);
|
||||
ASSERT_THAT(model, NotNull());
|
||||
|
||||
EXPECT_THAT(AsVector(model->mesh_scale + 0, 3), ElementsAre(1, 1, 1));
|
||||
EXPECT_THAT(AsVector(model->mesh_scale + 3, 3), ElementsAre(0.9, 1, -1));
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
// ----------------------------- texcoord -------------------------------------
|
||||
|
||||
TEST_F(MjCMeshTest, CreateFaceTexCoord) {
|
||||
|
||||
@@ -5374,6 +5374,7 @@ public unsafe struct mjModel_ {
|
||||
public int* mesh_facenormal;
|
||||
public int* mesh_facetexcoord;
|
||||
public int* mesh_graph;
|
||||
public double* mesh_scale;
|
||||
public double* mesh_pos;
|
||||
public double* mesh_quat;
|
||||
public int* mesh_pathadr;
|
||||
|
||||
Reference in New Issue
Block a user