Add built-in cone mesh type.

Also delete `prism` type since it is subsumed by cone.

PiperOrigin-RevId: 790992343
Change-Id: I7a9c6f2a4377489173acd64b23086c748d2cee8e
This commit is contained in:
Yuval Tassa
2025-08-04 19:34:35 -07:00
committed by Copybara-Service
parent 4a91c34239
commit a5a6379f83
13 changed files with 167 additions and 111 deletions
+5 -7
View File
@@ -1340,15 +1340,13 @@ The full list of processing steps applied by the compiler to each mesh is as fol
**subdivision**: integer in [0-10]: The number of subdivisions to apply to the pyramid. **subdivision**: integer in [0-10]: The number of subdivisions to apply to the pyramid.
:at-val:`prism` (nvert) :at-val:`cone` (nvert, radius)
An extruded regular unit polygon. The convex hull of a regular unit polygon at z = -1 and a unit polygon with the given radiusat z = 1.
If radius is 1, the mesh a prism. If radius is 0, only a single vertex is place at (0, 0, 1) and the mesh is a
**nvert**: integer >= 3: The number vertices in the polygon. discrete cone. If radius is positive, the mesh is a truncated discrete cone.
:at-val:`cone` (nvert)
The convex hull of a regular unit polygon and the vertex (0, 0, 1).
**nvert**: integer >= 3: The number vertices in the polygon. **nvert**: integer >= 3: The number vertices in the polygon.
|br| **radius**: real in [0, 1]: The radius of the top face.
:at-val:`torus` (radius, resolution) :at-val:`torus` (radius, resolution)
A torus with major radius of 1 and given minor radius. A torus with major radius of 1 and given minor radius.
-1
View File
@@ -1788,7 +1788,6 @@ typedef enum mjtMeshBuiltin_ { // type of built-in procedural mesh
mjMESH_BUILTIN_NONE = 0, // no built-in mesh mjMESH_BUILTIN_NONE = 0, // no built-in mesh
mjMESH_BUILTIN_SPHERE, // sphere mjMESH_BUILTIN_SPHERE, // sphere
mjMESH_BUILTIN_HEMISPHERE, // hemisphere mjMESH_BUILTIN_HEMISPHERE, // hemisphere
mjMESH_BUILTIN_PRISM, // prism
mjMESH_BUILTIN_CONE, // cone mjMESH_BUILTIN_CONE, // cone
mjMESH_BUILTIN_TORUS, // torus mjMESH_BUILTIN_TORUS, // torus
mjMESH_BUILTIN_WEDGE, // wedge mjMESH_BUILTIN_WEDGE, // wedge
-1
View File
@@ -74,7 +74,6 @@ typedef enum mjtMeshBuiltin_ { // type of built-in procedural mesh
mjMESH_BUILTIN_NONE = 0, // no built-in mesh mjMESH_BUILTIN_NONE = 0, // no built-in mesh
mjMESH_BUILTIN_SPHERE, // sphere mjMESH_BUILTIN_SPHERE, // sphere
mjMESH_BUILTIN_HEMISPHERE, // hemisphere mjMESH_BUILTIN_HEMISPHERE, // hemisphere
mjMESH_BUILTIN_PRISM, // prism
mjMESH_BUILTIN_CONE, // cone mjMESH_BUILTIN_CONE, // cone
mjMESH_BUILTIN_TORUS, // torus mjMESH_BUILTIN_TORUS, // torus
mjMESH_BUILTIN_WEDGE, // wedge mjMESH_BUILTIN_WEDGE, // wedge
+4 -5
View File
@@ -800,11 +800,10 @@ ENUMS: Mapping[str, EnumDecl] = dict([
('mjMESH_BUILTIN_NONE', 0), ('mjMESH_BUILTIN_NONE', 0),
('mjMESH_BUILTIN_SPHERE', 1), ('mjMESH_BUILTIN_SPHERE', 1),
('mjMESH_BUILTIN_HEMISPHERE', 2), ('mjMESH_BUILTIN_HEMISPHERE', 2),
('mjMESH_BUILTIN_PRISM', 3), ('mjMESH_BUILTIN_CONE', 3),
('mjMESH_BUILTIN_CONE', 4), ('mjMESH_BUILTIN_TORUS', 4),
('mjMESH_BUILTIN_TORUS', 5), ('mjMESH_BUILTIN_WEDGE', 5),
('mjMESH_BUILTIN_WEDGE', 6), ('mjMESH_BUILTIN_PLATE', 6),
('mjMESH_BUILTIN_PLATE', 7),
]), ]),
)), )),
('mjtBuiltin', ('mjtBuiltin',
+7 -10
View File
@@ -1003,7 +1003,7 @@ PYBIND11_MODULE(_specs, m) {
py::return_value_policy::reference_internal); py::return_value_policy::reference_internal);
mjsMesh.def( mjsMesh.def(
"make_wedge", "make_wedge",
[](raw::MjsMesh* self, std::array<int, 2>& resolution, double radius, [](raw::MjsMesh* self, std::array<int, 2>& resolution,
std::array<double, 2>& fov, double gamma) { std::array<double, 2>& fov, double gamma) {
double params[5] = {static_cast<double>(resolution[0]), double params[5] = {static_cast<double>(resolution[0]),
static_cast<double>(resolution[1]), fov[0], fov[1], static_cast<double>(resolution[1]), fov[0], fov[1],
@@ -1011,21 +1011,18 @@ PYBIND11_MODULE(_specs, m) {
if (mjs_makeMesh(self, mjMESH_BUILTIN_WEDGE, params, 5)) { if (mjs_makeMesh(self, mjMESH_BUILTIN_WEDGE, params, 5)) {
throw pybind11::value_error(mjs_getError(mjs_getSpec(self->element))); throw pybind11::value_error(mjs_getError(mjs_getSpec(self->element)));
} }
self->scale[0] = radius;
self->scale[1] = radius;
self->scale[2] = radius;
}, },
py::arg("resolution") = std::array<int, 2>{0, 0}, py::arg("radius"), py::arg("resolution") = std::array<int, 2>{0, 0},
py::arg("fov") = std::array<double, 2>{0, 0}, py::arg("gamma") = 0); py::arg("fov") = std::array<double, 2>{0, 0}, py::arg("gamma") = 0);
mjsMesh.def( mjsMesh.def(
"make_prism", "make_cone",
[](raw::MjsMesh* self, int nedge) { [](raw::MjsMesh* self, int nedge, double radius) {
double params[1] = {static_cast<double>(nedge)}; double params[2] = {static_cast<double>(nedge), radius};
if (mjs_makeMesh(self, mjMESH_BUILTIN_PRISM, params, 1)) { if (mjs_makeMesh(self, mjMESH_BUILTIN_CONE, params, 2)) {
throw pybind11::value_error(mjs_getError(mjs_getSpec(self->element))); throw pybind11::value_error(mjs_getError(mjs_getSpec(self->element)));
} }
}, },
py::arg("nedge")); py::arg("nedge"), py::arg("radius"));
mjsMesh.def( mjsMesh.def(
"make_plate", "make_plate",
[](raw::MjsMesh* self, std::array<int, 2>& resolution) { [](raw::MjsMesh* self, std::array<int, 2>& resolution) {
+13 -4
View File
@@ -486,12 +486,21 @@ class SpecsTest(absltest.TestCase):
def test_make_mesh(self): def test_make_mesh(self):
spec = mujoco.MjSpec() spec = mujoco.MjSpec()
mesh = spec.add_mesh(name='wedge') mesh = spec.add_mesh(name='wedge')
mesh.make_wedge(resolution=[25, 25], radius=.1, fov=[90, 45], gamma=0) mesh.make_wedge(resolution=[25, 25], fov=[90, 45], gamma=0)
mesh = spec.add_mesh(name='prism')
mesh.make_cone(nedge=5, radius=1)
mesh = spec.add_mesh(name='cone')
mesh.make_cone(nedge=6, radius=0)
model = spec.compile() model = spec.compile()
self.assertEqual(model.nmesh, 1) self.assertEqual(model.nmesh, 3)
self.assertEqual(model.nmeshvert, 25 * 25) self.assertEqual(model.mesh_vertnum[0], 25 * 25)
np.testing.assert_array_equal(model.mesh_scale[0], [0.1, 0.1, 0.1]) self.assertEqual(model.mesh_vertnum[1], 10)
self.assertEqual(model.mesh_vertnum[2], 7)
def test_compile_errors_with_line_info(self): def test_compile_errors_with_line_info(self):
spec = mujoco.MjSpec() spec = mujoco.MjSpec()
+55 -52
View File
@@ -505,62 +505,65 @@ mjsMaterial* mjs_addMaterial(mjSpec* s, const mjsDefault* defspec) {
int mjs_makeMesh(mjsMesh* mesh, mjtMeshBuiltin builtin, double* params, int nparams) { int mjs_makeMesh(mjsMesh* mesh, mjtMeshBuiltin builtin, double* params, int nparams) {
mjCMesh* meshC = static_cast<mjCMesh*>(mesh->element); mjCMesh* meshC = static_cast<mjCMesh*>(mesh->element);
mjCModel* m = meshC->model; mjCModel* m = meshC->model;
if (builtin == mjMESH_BUILTIN_WEDGE) { switch (builtin) {
if (nparams != 5) { case mjMESH_BUILTIN_WEDGE: {
m->SetError(mjCError(0, "Wedge builtin mesh types require 5 parameters")); if (nparams != 5) {
return -1; m->SetError(mjCError(0, "Wedge builtin mesh types require 5 parameters"));
return -1;
}
int resolution[2] = {static_cast<int>(params[0]),
static_cast<int>(params[1])};
double fov[2] = {params[2], params[3]};
double gamma = params[4];
if (fov[0] <= 0 || fov[0] > 180) {
m->SetError(mjCError(0, "fov[0] must be a float between (0, 180] degrees"));
return -1;
}
if (fov[1] <= 0 || fov[1] > 90) {
m->SetError(mjCError(0, "`fov[1]` must be a float between (0, 90] degrees"));
return -1;
}
if (resolution[0] <= 0 || resolution[1] <= 0) {
m->SetError(mjCError(0, "Horizontal and vertical resolutions must be positive"));
return -1;
}
if (gamma < 0 || gamma > 1) {
m->SetError(mjCError(0, "`gamma` must be a nonnegative float between [0, 1]"));
return -1;
}
meshC->MakeWedge(resolution, fov, gamma);
return 0;
} }
int resolution[2] = {static_cast<int>(params[0]),
static_cast<int>(params[1])}; case mjMESH_BUILTIN_PLATE: {
double fov[2] = {params[2], params[3]}; if (nparams != 2) {
double gamma = params[4]; m->SetError(mjCError(0, "Plate builtin mesh type requires 2 parameters"));
if (fov[0] <= 0 || fov[0] > 180) { return -1;
m->SetError( }
mjCError(0, "fov[0] must be a float between (0, 180] degrees")); int resolution[2] = {static_cast<int>(params[0]),
return -1; static_cast<int>(params[1])};
if (resolution[0] <= 0 || resolution[1] <= 0) {
m->SetError(mjCError(0, "Horizontal and vertical resolutions must be positive"));
return -1;
}
meshC->MakeRect(resolution);
return 0;
} }
if (fov[1] <= 0 || fov[1] > 90) {
m->SetError( case mjMESH_BUILTIN_CONE: {
mjCError(0, "`fov[1]` must be a float between (0, 90] degrees")); if (nparams != 2) {
return -1; m->SetError(mjCError(0, "Cone mesh type requires 2 parameters"));
return -1;
}
int nedge = static_cast<int>(params[0]);
meshC->MakeCone(nedge, params[1]);
return 0;
} }
if (resolution[0] <= 0 || resolution[1] <= 0) {
m->SetError( default:
mjCError(0, "Horizontal and vertical resolutions must be positive")); m->SetError(mjCError(0, "Unsupported mesh type"));
return -1; return 1;
}
if (gamma < 0 || gamma > 1) {
m->SetError(
mjCError(0, "`gamma` must be a nonnegative float between [0, 1]"));
return -1;
}
meshC->MakeWedge(resolution, fov, gamma);
return 0;
} else if (builtin == mjMESH_BUILTIN_PLATE) {
if (nparams != 2) {
m->SetError(mjCError(0, "Plate builtin mesh type requires 2 parameters"));
return -1;
}
int resolution[2] = {static_cast<int>(params[0]),
static_cast<int>(params[1])};
if (resolution[0] <= 0 || resolution[1] <= 0) {
m->SetError(
mjCError(0, "Horizontal and vertical resolutions must be positive"));
return -1;
}
meshC->MakeRect(resolution);
return 0;
} else if (builtin == mjMESH_BUILTIN_PRISM) {
if (nparams != 1) {
m->SetError(mjCError(0, "Prism mesh type requires 1 parameter"));
return -1;
}
int nedge = static_cast<int>(params[0]);
meshC->MakePrism(nedge);
return 0;
} }
m->SetError(mjCError(0, "Unsupported mesh type"));
return 1;
} }
// add pair to model // add pair to model
+63 -14
View File
@@ -184,6 +184,8 @@ static void ReadFromBuffer(T* dst, const char* src) {
std::memcpy(dst, src, sizeof(T)); std::memcpy(dst, src, sizeof(T));
} }
//------------------ class mjCMesh implementation -------------------------------------------------- //------------------ class mjCMesh implementation --------------------------------------------------
mjCMesh::mjCMesh(mjCModel* _model, mjCDef* _def) { mjCMesh::mjCMesh(mjCModel* _model, mjCDef* _def) {
@@ -432,6 +434,8 @@ void mjCMesh::LoadSDF() {
delete[] field; delete[] field;
} }
void mjCMesh::CacheMesh(mjCCache* cache, const mjResource* resource) { void mjCMesh::CacheMesh(mjCCache* cache, const mjResource* resource) {
if (cache == nullptr) return; if (cache == nullptr) return;
@@ -521,6 +525,8 @@ struct VertexKey {
} // namespace } // namespace
// convert vertices to double precision and remove repeated vertices if requested // convert vertices to double precision and remove repeated vertices if requested
void mjCMesh::ProcessVertices(const std::vector<float>& vert, bool remove_repeated) { void mjCMesh::ProcessVertices(const std::vector<float>& vert, bool remove_repeated) {
vert_.clear(); vert_.clear();
@@ -622,6 +628,8 @@ bool mjCMesh::IsMSH() const {
return content_type_ == "model/vnd.mujoco.msh"; return content_type_ == "model/vnd.mujoco.msh";
} }
// load mesh from resource; throw error on failure // load mesh from resource; throw error on failure
void mjCMesh::LoadFromResource(mjResource* resource, bool remove_repeated) { void mjCMesh::LoadFromResource(mjResource* resource, bool remove_repeated) {
// set content type from resource name // set content type from resource name
@@ -645,6 +653,8 @@ void mjCMesh::LoadFromResource(mjResource* resource, bool remove_repeated) {
} }
} }
// compiler wrapper // compiler wrapper
void mjCMesh::Compile(const mjVFS* vfs) { void mjCMesh::Compile(const mjVFS* vfs) {
try { try {
@@ -658,6 +668,8 @@ void mjCMesh::Compile(const mjVFS* vfs) {
} }
} }
// compiler // compiler
void mjCMesh::TryCompile(const mjVFS* vfs) { void mjCMesh::TryCompile(const mjVFS* vfs) {
bool fromCache = false; bool fromCache = false;
@@ -1106,6 +1118,8 @@ void mjCMesh::LoadOBJ(mjResource* resource, bool remove_repeated) {
ProcessVertices(attrib.vertices, remove_repeated); ProcessVertices(attrib.vertices, remove_repeated);
} }
// load mesh from cached asset, return true on success // load mesh from cached asset, return true on success
bool mjCMesh::LoadCachedMesh(mjCCache *cache, const mjResource* resource) { bool mjCMesh::LoadCachedMesh(mjCCache *cache, const mjResource* resource) {
auto process_mesh = [&](const void* data) { auto process_mesh = [&](const void* data) {
@@ -1177,6 +1191,8 @@ bool mjCMesh::LoadCachedMesh(mjCCache *cache, const mjResource* resource) {
return cache->PopulateData(resource, process_mesh); return cache->PopulateData(resource, process_mesh);
} }
// load STL binary mesh // load STL binary mesh
void mjCMesh::LoadSTL(mjResource* resource) { void mjCMesh::LoadSTL(mjResource* resource) {
bool righthand = scale[0] * scale[1] * scale[2] > 0; bool righthand = scale[0] * scale[1] * scale[2] > 0;
@@ -1339,6 +1355,8 @@ void mjCMesh::LoadMSH(mjResource* resource, bool remove_repeated) {
ProcessVertices(vert, remove_repeated); ProcessVertices(vert, remove_repeated);
} }
// compute the volume and center-of-mass of the mesh given the face centroid // compute the volume and center-of-mass of the mesh given the face centroid
double mjCMesh::ComputeVolume(double CoM[3], const double facecen[3]) const { double mjCMesh::ComputeVolume(double CoM[3], const double facecen[3]) const {
double normal[3], center[3], total_volume = 0; double normal[3], center[3], total_volume = 0;
@@ -1376,6 +1394,8 @@ double mjCMesh::ComputeVolume(double CoM[3], const double facecen[3]) const {
return total_volume; return total_volume;
} }
// compute the surface area and center-of-mass of the mesh given the face centroid // compute the surface area and center-of-mass of the mesh given the face centroid
double mjCMesh::ComputeSurfaceArea(double CoM[3], const double facecen[3]) const { double mjCMesh::ComputeSurfaceArea(double CoM[3], const double facecen[3]) const {
double surface = 0; double surface = 0;
@@ -1402,6 +1422,8 @@ double mjCMesh::ComputeSurfaceArea(double CoM[3], const double facecen[3]) const
return surface; return surface;
} }
// apply transformations // apply transformations
void mjCMesh::ApplyTransformations() { void mjCMesh::ApplyTransformations() {
// translate // translate
@@ -1470,6 +1492,8 @@ void mjCMesh::ApplyTransformations() {
} }
} }
// find centroid of faces, return total area // find centroid of faces, return total area
double mjCMesh::ComputeFaceCentroid(double facecen[3]) const { double mjCMesh::ComputeFaceCentroid(double facecen[3]) const {
double total_area = 0; double total_area = 0;
@@ -1496,6 +1520,8 @@ double mjCMesh::ComputeFaceCentroid(double facecen[3]) const {
return total_area; return total_area;
} }
void mjCMesh::Process() { void mjCMesh::Process() {
// create half-edge structure (if mesh was in XML) // create half-edge structure (if mesh was in XML)
if (halfedge_.empty()) { if (halfedge_.empty()) {
@@ -1737,6 +1763,7 @@ double mjCMesh::ComputeInertia(double inert[6], const double CoM[3]) const {
} }
void mjCMesh::Rotate(double quat[4]) { void mjCMesh::Rotate(double quat[4]) {
// rotate vertices and normals of mesh by quaternion // rotate vertices and normals of mesh by quaternion
double neg[4] = {quat[0], -quat[1], -quat[2], -quat[3]}; double neg[4] = {quat[0], -quat[1], -quat[2], -quat[3]};
@@ -1804,17 +1831,20 @@ void mjCMesh::CheckInitialMesh() const {
// get inertia pointer // return inertia pointer
double* mjCMesh::GetInertiaBoxPtr() { double* mjCMesh::GetInertiaBoxPtr() {
return boxsz_; return boxsz_;
} }
// return volume or surface area
double mjCMesh::GetVolumeRef() const { double mjCMesh::GetVolumeRef() const {
return (inertia == mjMESH_INERTIA_SHELL) ? surface_ : volume_; return (inertia == mjMESH_INERTIA_SHELL) ? surface_ : volume_;
} }
// make graph describing convex hull // make graph describing convex hull
void mjCMesh::MakeGraph() { void mjCMesh::MakeGraph() {
int adr, ok, curlong, totlong, exitcode; int adr, ok, curlong, totlong, exitcode;
@@ -1999,6 +2029,8 @@ void mjCMesh::MakeGraph() {
} }
} }
// copy graph into face data // copy graph into face data
void mjCMesh::CopyGraph() { void mjCMesh::CopyGraph() {
// only if face data is missing // only if face data is missing
@@ -2022,6 +2054,8 @@ void mjCMesh::CopyGraph() {
} }
} }
// make a mesh of a spherical wedge // make a mesh of a spherical wedge
void mjCMesh::MakeWedge(int resolution[2], double fov[2], double gamma) { void mjCMesh::MakeWedge(int resolution[2], double fov[2], double gamma) {
std::vector<double> x_edges(resolution[0] + 1, 0); std::vector<double> x_edges(resolution[0] + 1, 0);
@@ -2047,6 +2081,8 @@ void mjCMesh::MakeWedge(int resolution[2], double fov[2], double gamma) {
9 * resolution[0] * resolution[1]); 9 * resolution[0] * resolution[1]);
} }
// make a mesh of a rectangle // make a mesh of a rectangle
void mjCMesh::MakeRect(int resolution[2]) { void mjCMesh::MakeRect(int resolution[2]) {
std::vector<double> x_edges(resolution[0] + 1, 0); std::vector<double> x_edges(resolution[0] + 1, 0);
@@ -2089,23 +2125,36 @@ void mjCMesh::MakeRect(int resolution[2]) {
6 * (resolution[0] - 1) * (resolution[1] - 1)); 6 * (resolution[0] - 1) * (resolution[1] - 1));
} }
// make a mesh of a prism
void mjCMesh::MakePrism(int nedge) {
int layer = 2;
std::vector<float> uservert(3 * nedge * layer, 0);
// make a mesh of a generalized discrete cone
void mjCMesh::MakeCone(int nedge, double radius) {
int n = 3 * (nedge + (radius > 0 ? nedge : 1));
std::vector<float> uservert(n, 0);
// bottom face
for (int i = 0; i < nedge; i++) { for (int i = 0; i < nedge; i++) {
for (int j = 0; j < layer; j++) { uservert[3 * i + 0] = std::cos(2 * i * mjPI / nedge);
int v = i * layer + j; uservert[3 * i + 1] = std::sin(2 * i * mjPI / nedge);
uservert[3 * v + 0] = std::cos(2 * i * mjPI / nedge); uservert[3 * i + 2] = -1;
uservert[3 * v + 1] = std::sin(2 * i * mjPI / nedge);
uservert[3 * v + 2] = -1 + 2 * j / (layer - 1);
}
} }
mjs_setFloat(spec.uservert, uservert.data(), 3 * nedge * layer); // top face or single point
if (radius > 0) {
for (int i = nedge; i < 2 * nedge; i++) {
uservert[3 * i + 0] = radius * std::cos(2 * i * mjPI / nedge);
uservert[3 * i + 1] = radius * std::sin(2 * i * mjPI / nedge);
uservert[3 * i + 2] = 1;
}
} else {
uservert[3 * nedge + 2] = 1;
}
mjs_setFloat(spec.uservert, uservert.data(), n);
} }
// compute vertex normals // compute vertex normals
void mjCMesh::MakeNormal() { void mjCMesh::MakeNormal() {
// only if normal data is missing // only if normal data is missing
@@ -2435,8 +2484,7 @@ void MeshPolygon::InsertFace(int v1, int v2, int v3) {
// return the traverse vertices of the polygon; there may be multiple paths if the polygon is // return the transverse vertices of the polygon, multiple paths possible if not connected
// not connected
std::vector<std::vector<int> > MeshPolygon::Paths() const { std::vector<std::vector<int> > MeshPolygon::Paths() const {
std::vector<std::vector<int> > paths; std::vector<std::vector<int> > paths;
// shortcut if polygon is just a triangular face // shortcut if polygon is just a triangular face
@@ -2550,6 +2598,7 @@ void mjCMesh::MakePolygons() {
} }
//------------------ class mjCSkin implementation -------------------------------------------------- //------------------ class mjCSkin implementation --------------------------------------------------
// constructor // constructor
+1 -1
View File
@@ -1053,7 +1053,7 @@ class mjCMesh: public mjCMesh_, private mjsMesh {
// make a mesh of a predefined shape // make a mesh of a predefined shape
void MakeWedge(int resolution[2], double fov[2], double gamma); void MakeWedge(int resolution[2], double fov[2], double gamma);
void MakeRect(int resolution[2]); void MakeRect(int resolution[2]);
void MakePrism(int nedge); void MakeCone(int nedge, double radius);
// accessors // accessors
const mjsPlugin& Plugin() const { return plugin; } const mjsPlugin& Plugin() const { return plugin; }
+1 -2
View File
@@ -827,12 +827,11 @@ const mjMap meshinertia_map[4] = {
// mesh builtin type // mesh builtin type
const int meshbuiltin_sz = 8; const int meshbuiltin_sz = 7;
const mjMap meshbuiltin_map[meshbuiltin_sz] = { const mjMap meshbuiltin_map[meshbuiltin_sz] = {
{"none", mjMESH_BUILTIN_NONE}, {"none", mjMESH_BUILTIN_NONE},
{"sphere", mjMESH_BUILTIN_SPHERE}, {"sphere", mjMESH_BUILTIN_SPHERE},
{"hemisphere", mjMESH_BUILTIN_HEMISPHERE}, {"hemisphere", mjMESH_BUILTIN_HEMISPHERE},
{"prism", mjMESH_BUILTIN_PRISM},
{"cone", mjMESH_BUILTIN_CONE}, {"cone", mjMESH_BUILTIN_CONE},
{"torus", mjMESH_BUILTIN_TORUS}, {"torus", mjMESH_BUILTIN_TORUS},
{"wedge", mjMESH_BUILTIN_WEDGE}, {"wedge", mjMESH_BUILTIN_WEDGE},
+12 -7
View File
@@ -1,13 +1,18 @@
<mujoco model='makemesh'> <mujoco model="makemesh">
<asset> <asset>
<mesh name="wedge" builtin="wedge" params="25 25 180 90 0"/> <mesh name="wedge" builtin="wedge" params="10 10 60 60 0"/>
<mesh name="plate" builtin="plate" params="37 37" scale="3 5 2"/> <mesh name="prism3" builtin="cone" params="3 1" scale=".3 .3 .3"/>
<mesh name="prism" builtin="prism" params="3"/> <mesh name="prism5" builtin="cone" params="5 1" scale=".3 .3 .1"/>
<mesh name="cone6" builtin="cone" params="6 0" scale=".3 .3 .7"/>
<mesh name="cone4" builtin="cone" params="4 .5" scale=".3 .3 .3"/>
</asset> </asset>
<worldbody> <worldbody>
<geom mesh="wedge" type="mesh"/> <light pos="0 0 10"/>
<geom mesh="plate" type="mesh" contype="0" conaffinity="0"/> <geom mesh="wedge" type="mesh" euler="90 -90 0"/>
<geom mesh="prism" type="mesh" pos="0 0 3"/> <geom mesh="prism5" type="mesh" pos="2 0 0" euler="90 0 0"/>
<geom mesh="prism3" type="mesh" pos="3 0 0"/>
<geom mesh="cone6" type="mesh" pos="4 0 0" euler="90 0 0"/>
<geom mesh="cone4" type="mesh" pos="5 0 0" />
</worldbody> </worldbody>
</mujoco> </mujoco>
+2 -2
View File
@@ -2044,10 +2044,10 @@ TEST_F(XMLReaderTest, UnsupportedMesh) {
static constexpr char xml[] = R"( static constexpr char xml[] = R"(
<mujoco> <mujoco>
<asset> <asset>
<mesh name="cone" builtin="cone" params="25 25 180 90 0"/> <mesh name="torus" builtin="torus" params="25 25 180 90 0"/>
</asset> </asset>
<worldbody> <worldbody>
<geom type="mesh" mesh="cone"/> <geom type="mesh" mesh="torus"/>
</worldbody> </worldbody>
</mujoco> </mujoco>
)"; )";
+4 -5
View File
@@ -501,11 +501,10 @@ public enum mjtMeshBuiltin : int{
mjMESH_BUILTIN_NONE = 0, mjMESH_BUILTIN_NONE = 0,
mjMESH_BUILTIN_SPHERE = 1, mjMESH_BUILTIN_SPHERE = 1,
mjMESH_BUILTIN_HEMISPHERE = 2, mjMESH_BUILTIN_HEMISPHERE = 2,
mjMESH_BUILTIN_PRISM = 3, mjMESH_BUILTIN_CONE = 3,
mjMESH_BUILTIN_CONE = 4, mjMESH_BUILTIN_TORUS = 4,
mjMESH_BUILTIN_TORUS = 5, mjMESH_BUILTIN_WEDGE = 5,
mjMESH_BUILTIN_WEDGE = 6, mjMESH_BUILTIN_PLATE = 6,
mjMESH_BUILTIN_PLATE = 7,
} }
public enum mjtBuiltin : int{ public enum mjtBuiltin : int{
mjBUILTIN_NONE = 0, mjBUILTIN_NONE = 0,