Adds built-in superellipsoid mesh.

PiperOrigin-RevId: 791196831
Change-Id: I1d864f6e620870f016377a4d9e2e26d1a23fd77e
This commit is contained in:
Yuval Tassa
2025-08-05 07:01:52 -07:00
committed by Copybara-Service
parent e74cee652f
commit 705ec6d7fb
12 changed files with 253 additions and 137 deletions
+9
View File
@@ -1348,6 +1348,15 @@ The full list of processing steps applied by the compiler to each mesh is as fol
**nvert**: integer >= 3: The number vertices in the polygon.
|br| **radius**: real in [0, 1]: The radius of the top face.
:at-val:`supersphere` (resolution, e, n)
A generalization of a sphere, also known as a superellipsoid (we use "supersphere" since semiaxis rescaling is
performed by the :ref:`scale<asset-mesh-scale>` attribute). If the **n** and **e** parameters are both 1, the
shape is a sphere. See `here <https://en.wikipedia.org/wiki/Superellipsoid>`__ for the definition of superspheres.
**resolution** integer >= 4: The discretization of both major and minor radii.
|br| **e**: real >= 0: The "east-west" exponent.
|br| **n**: real >= 0: The "north-south" exponent.
:at-val:`supertorus` (resolution, radius, s, t)
A generalization of a torus with major radius of 1 and given minor radius. If the **s** and **t** parameters are
both 1, the shape is a torus. See `here <https://en.wikipedia.org/wiki/Supertoroid>`__ for details regarding
+1
View File
@@ -1789,6 +1789,7 @@ typedef enum mjtMeshBuiltin_ { // type of built-in procedural mesh
mjMESH_BUILTIN_SPHERE, // sphere
mjMESH_BUILTIN_HEMISPHERE, // hemisphere
mjMESH_BUILTIN_CONE, // cone
mjMESH_BUILTIN_SUPERSPHERE, // supersphere
mjMESH_BUILTIN_SUPERTORUS, // supertorus
mjMESH_BUILTIN_WEDGE, // wedge
mjMESH_BUILTIN_PLATE, // plate
+1
View File
@@ -75,6 +75,7 @@ typedef enum mjtMeshBuiltin_ { // type of built-in procedural mesh
mjMESH_BUILTIN_SPHERE, // sphere
mjMESH_BUILTIN_HEMISPHERE, // hemisphere
mjMESH_BUILTIN_CONE, // cone
mjMESH_BUILTIN_SUPERSPHERE, // supersphere
mjMESH_BUILTIN_SUPERTORUS, // supertorus
mjMESH_BUILTIN_WEDGE, // wedge
mjMESH_BUILTIN_PLATE, // plate
+4 -3
View File
@@ -801,9 +801,10 @@ ENUMS: Mapping[str, EnumDecl] = dict([
('mjMESH_BUILTIN_SPHERE', 1),
('mjMESH_BUILTIN_HEMISPHERE', 2),
('mjMESH_BUILTIN_CONE', 3),
('mjMESH_BUILTIN_SUPERTORUS', 4),
('mjMESH_BUILTIN_WEDGE', 5),
('mjMESH_BUILTIN_PLATE', 6),
('mjMESH_BUILTIN_SUPERSPHERE', 4),
('mjMESH_BUILTIN_SUPERTORUS', 5),
('mjMESH_BUILTIN_WEDGE', 6),
('mjMESH_BUILTIN_PLATE', 7),
]),
)),
('mjtBuiltin',
+9
View File
@@ -1041,6 +1041,15 @@ PYBIND11_MODULE(_specs, m) {
}
},
py::arg("nedge"), py::arg("radius"));
mjsMesh.def(
"make_supersphere",
[](raw::MjsMesh* self, int resolution, double e, double n) {
double params[3] = {static_cast<double>(resolution), e, n};
if (mjs_makeMesh(self, mjMESH_BUILTIN_SUPERSPHERE, params, 3)) {
throw pybind11::value_error(mjs_getError(mjs_getSpec(self->element)));
}
},
py::arg("resolution"), py::arg("e"), py::arg("n"));
mjsMesh.def(
"make_supertorus",
[](raw::MjsMesh* self, int resolution, double radius, double s,
+6 -2
View File
@@ -502,17 +502,21 @@ class SpecsTest(absltest.TestCase):
mesh = spec.add_mesh(name='sphere')
mesh.make_sphere(subdivision=2)
mesh = spec.add_mesh(name='supertoroid')
mesh = spec.add_mesh(name='supertorus')
mesh.make_supertorus(resolution=10, radius=0.5, s=1, t=1)
mesh = spec.add_mesh(name='supersphere')
mesh.make_supersphere(resolution=20, e=2, n=1)
model = spec.compile()
self.assertEqual(model.nmesh, 6)
self.assertEqual(model.nmesh, 7)
self.assertEqual(model.mesh_vertnum[0], 25 * 25)
self.assertEqual(model.mesh_vertnum[1], 10)
self.assertEqual(model.mesh_vertnum[2], 7)
self.assertEqual(model.mesh_vertnum[3], 2 * (4 + 1) * (4 + 2) + 2)
self.assertEqual(model.mesh_vertnum[4], 2 + 10 * 4**2)
self.assertEqual(model.mesh_vertnum[5], 100)
self.assertEqual(model.mesh_vertnum[6], 20 * (20 -1) + 2)
def test_compile_errors_with_line_info(self):
spec = mujoco.MjSpec()
+24
View File
@@ -542,6 +542,30 @@ int mjs_makeMesh(mjsMesh* mesh, mjtMeshBuiltin builtin, double* params, int npar
return 0;
}
case mjMESH_BUILTIN_SUPERSPHERE: {
if (nparams != 3) {
m->SetError(mjCError(0, "Supersphere mesh type requires 3 parameters"));
return -1;
}
int res = static_cast<int>(params[0]);
if (res < 3) {
m->SetError(mjCError(0, "Supersphere resolution must be greater than 2"));
return -1;
}
double e = params[1];
if (e < 0) {
m->SetError(mjCError(0, "Supersphere 'e' cannot be negative"));
return -1;
}
double n = params[2];
if (n < 0) {
m->SetError(mjCError(0, "Supersphere 'n' cannot be negative"));
return -1;
}
meshC->MakeSupersphere(res, e, n);
return 0;
}
case mjMESH_BUILTIN_SUPERTORUS: {
if (nparams != 4) {
m->SetError(mjCError(0, "Supertorus mesh type requires 4 parameters"));
+62
View File
@@ -2292,6 +2292,68 @@ void mjCMesh::MakeSphere(int subdiv, bool make_faces) {
// make a mesh of a supersphere
void mjCMesh::MakeSupersphere(int res, double e, double n) {
// allocate vertices and faces
int nvert = (res - 1) * res + 2;
int nface = 2 * res * (res - 1);
std::vector<float> vert;
vert.reserve(3 * nvert);
std::vector<int> face;
face.reserve(3 * nface);
// south pole
vert.insert(vert.end(), {0.0f, 0.0f, -1.0f});
// rings
for (int i = 1; i < res; i++) {
double v = -mjPI/2 + i * mjPI / res;
for (int j = 0; j < res; j++) {
double u = -mjPI + j * 2 * mjPI / res;
vert.push_back(aux_c(v, n) * aux_c(u, e));
vert.push_back(aux_c(v, n) * aux_s(u, e));
vert.push_back(aux_s(v, n));
}
}
// north pole
vert.insert(vert.end(), {0.0f, 0.0f, 1.0f});
// south pole faces
for (int j = 0; j < res; j++) {
int v2 = 1 + j;
int v3 = 1 + (j + 1) % res;
face.insert(face.end(), {0, v3, v2});
}
// ring faces
for (int i = 0; i < res - 2; i++) {
for (int j = 0; j < res; j++) {
int v1 = 1 + i * res + j;
int v2 = 1 + i * res + (j + 1) % res;
int v4 = 1 + (i + 1) * res + j;
int v3 = 1 + (i + 1) * res + (j + 1) % res;
face.insert(face.end(), {v1, v2, v4});
face.insert(face.end(), {v2, v3, v4});
}
}
// north pole faces
int north_pole_idx = nvert - 1;
int last_ring_start_idx = 1 + (res - 2) * res;
for (int j = 0; j < res; j++) {
int v1 = last_ring_start_idx + j;
int v2 = last_ring_start_idx + (j + 1) % res;
face.insert(face.end(), {v1, v2, north_pole_idx});
}
// save vertices and faces
mjs_setFloat(spec.uservert, vert.data(), vert.size());
mjs_setInt(spec.userface, face.data(), face.size());
}
// make a mesh of a torus (subsumed by supertorus, kept for reference only)
void mjCMesh::MakeTorus(int res, double radius) {
// allocate vertices and faces
+1
View File
@@ -1055,6 +1055,7 @@ class mjCMesh: public mjCMesh_, private mjsMesh {
void MakeSphere(int subdiv, bool make_faces);
void MakeTorus(int res, double radius);
void MakeSupertorus(int res, double radius, double s, double t);
void MakeSupersphere(int res, double e, double n);
void MakeWedge(int resolution[2], double fov[2], double gamma);
void MakeRect(int resolution[2]);
void MakeCone(int nedge, double radius);
+130 -129
View File
@@ -557,24 +557,24 @@ const mjMap TFAuto_map[3] = {
// joint type
const int joint_sz = 4;
const mjMap joint_map[joint_sz] = {
{"free", mjJNT_FREE},
{"ball", mjJNT_BALL},
{"slide", mjJNT_SLIDE},
{"hinge", mjJNT_HINGE}
{"free", mjJNT_FREE},
{"ball", mjJNT_BALL},
{"slide", mjJNT_SLIDE},
{"hinge", mjJNT_HINGE}
};
// geom type
const mjMap geom_map[mjNGEOMTYPES] = {
{"plane", mjGEOM_PLANE},
{"hfield", mjGEOM_HFIELD},
{"sphere", mjGEOM_SPHERE},
{"capsule", mjGEOM_CAPSULE},
{"ellipsoid", mjGEOM_ELLIPSOID},
{"cylinder", mjGEOM_CYLINDER},
{"box", mjGEOM_BOX},
{"mesh", mjGEOM_MESH},
{"sdf", mjGEOM_SDF}
{"plane", mjGEOM_PLANE},
{"hfield", mjGEOM_HFIELD},
{"sphere", mjGEOM_SPHERE},
{"capsule", mjGEOM_CAPSULE},
{"ellipsoid", mjGEOM_ELLIPSOID},
{"cylinder", mjGEOM_CYLINDER},
{"box", mjGEOM_BOX},
{"mesh", mjGEOM_MESH},
{"sdf", mjGEOM_SDF}
};
@@ -617,267 +617,268 @@ const mjMap texrole_map[texrole_sz] = {
// integrator type
const int integrator_sz = 4;
const mjMap integrator_map[integrator_sz] = {
{"Euler", mjINT_EULER},
{"RK4", mjINT_RK4},
{"implicit", mjINT_IMPLICIT},
{"implicitfast", mjINT_IMPLICITFAST}
{"Euler", mjINT_EULER},
{"RK4", mjINT_RK4},
{"implicit", mjINT_IMPLICIT},
{"implicitfast", mjINT_IMPLICITFAST}
};
// cone type
const int cone_sz = 2;
const mjMap cone_map[cone_sz] = {
{"pyramidal", mjCONE_PYRAMIDAL},
{"elliptic", mjCONE_ELLIPTIC}
{"pyramidal", mjCONE_PYRAMIDAL},
{"elliptic", mjCONE_ELLIPTIC}
};
// Jacobian type
const int jac_sz = 3;
const mjMap jac_map[jac_sz] = {
{"dense", mjJAC_DENSE},
{"sparse", mjJAC_SPARSE},
{"auto", mjJAC_AUTO}
{"dense", mjJAC_DENSE},
{"sparse", mjJAC_SPARSE},
{"auto", mjJAC_AUTO}
};
// solver type
const int solver_sz = 3;
const mjMap solver_map[solver_sz] = {
{"PGS", mjSOL_PGS},
{"CG", mjSOL_CG},
{"Newton", mjSOL_NEWTON}
{"PGS", mjSOL_PGS},
{"CG", mjSOL_CG},
{"Newton", mjSOL_NEWTON}
};
// constraint type
const int equality_sz = 6;
const mjMap equality_map[equality_sz] = {
{"connect", mjEQ_CONNECT},
{"weld", mjEQ_WELD},
{"joint", mjEQ_JOINT},
{"tendon", mjEQ_TENDON},
{"flex", mjEQ_FLEX},
{"distance", mjEQ_DISTANCE}
{"connect", mjEQ_CONNECT},
{"weld", mjEQ_WELD},
{"joint", mjEQ_JOINT},
{"tendon", mjEQ_TENDON},
{"flex", mjEQ_FLEX},
{"distance", mjEQ_DISTANCE}
};
// type for texture
const int texture_sz = 3;
const mjMap texture_map[texture_sz] = {
{"2d", mjTEXTURE_2D},
{"cube", mjTEXTURE_CUBE},
{"skybox", mjTEXTURE_SKYBOX}
{"2d", mjTEXTURE_2D},
{"cube", mjTEXTURE_CUBE},
{"skybox", mjTEXTURE_SKYBOX}
};
// colorspace for texture
const int colorspace_sz = 3;
const mjMap colorspace_map[colorspace_sz] = {
{"auto", mjCOLORSPACE_AUTO},
{"linear", mjCOLORSPACE_LINEAR},
{"sRGB", mjCOLORSPACE_SRGB}
{"auto", mjCOLORSPACE_AUTO},
{"linear", mjCOLORSPACE_LINEAR},
{"sRGB", mjCOLORSPACE_SRGB}
};
// builtin type for texture
const int builtin_sz = 4;
const mjMap builtin_map[builtin_sz] = {
{"none", mjBUILTIN_NONE},
{"gradient", mjBUILTIN_GRADIENT},
{"checker", mjBUILTIN_CHECKER},
{"flat", mjBUILTIN_FLAT}
{"none", mjBUILTIN_NONE},
{"gradient", mjBUILTIN_GRADIENT},
{"checker", mjBUILTIN_CHECKER},
{"flat", mjBUILTIN_FLAT}
};
// mark type for texture
const int mark_sz = 4;
const mjMap mark_map[mark_sz] = {
{"none", mjMARK_NONE},
{"edge", mjMARK_EDGE},
{"cross", mjMARK_CROSS},
{"random", mjMARK_RANDOM}
{"none", mjMARK_NONE},
{"edge", mjMARK_EDGE},
{"cross", mjMARK_CROSS},
{"random", mjMARK_RANDOM}
};
// dyn type
const int dyn_sz = 6;
const mjMap dyn_map[dyn_sz] = {
{"none", mjDYN_NONE},
{"integrator", mjDYN_INTEGRATOR},
{"filter", mjDYN_FILTER},
{"filterexact", mjDYN_FILTEREXACT},
{"muscle", mjDYN_MUSCLE},
{"user", mjDYN_USER}
{"none", mjDYN_NONE},
{"integrator", mjDYN_INTEGRATOR},
{"filter", mjDYN_FILTER},
{"filterexact", mjDYN_FILTEREXACT},
{"muscle", mjDYN_MUSCLE},
{"user", mjDYN_USER}
};
// gain type
const int gain_sz = 4;
const mjMap gain_map[gain_sz] = {
{"fixed", mjGAIN_FIXED},
{"affine", mjGAIN_AFFINE},
{"muscle", mjGAIN_MUSCLE},
{"user", mjGAIN_USER}
{"fixed", mjGAIN_FIXED},
{"affine", mjGAIN_AFFINE},
{"muscle", mjGAIN_MUSCLE},
{"user", mjGAIN_USER}
};
// bias type
const int bias_sz = 4;
const mjMap bias_map[bias_sz] = {
{"none", mjBIAS_NONE},
{"affine", mjBIAS_AFFINE},
{"muscle", mjBIAS_MUSCLE},
{"user", mjBIAS_USER}
{"none", mjBIAS_NONE},
{"affine", mjBIAS_AFFINE},
{"muscle", mjBIAS_MUSCLE},
{"user", mjBIAS_USER}
};
// stage type
const int stage_sz = 4;
const mjMap stage_map[stage_sz] = {
{"none", mjSTAGE_NONE},
{"pos", mjSTAGE_POS},
{"vel", mjSTAGE_VEL},
{"acc", mjSTAGE_ACC}
{"none", mjSTAGE_NONE},
{"pos", mjSTAGE_POS},
{"vel", mjSTAGE_VEL},
{"acc", mjSTAGE_ACC}
};
// data type
const int datatype_sz = 4;
const mjMap datatype_map[datatype_sz] = {
{"real", mjDATATYPE_REAL},
{"positive", mjDATATYPE_POSITIVE},
{"axis", mjDATATYPE_AXIS},
{"quaternion", mjDATATYPE_QUATERNION}
{"real", mjDATATYPE_REAL},
{"positive", mjDATATYPE_POSITIVE},
{"axis", mjDATATYPE_AXIS},
{"quaternion", mjDATATYPE_QUATERNION}
};
// contact data type
const mjMap condata_map[mjNCONDATA] = {
{"found", mjCONDATA_FOUND},
{"force", mjCONDATA_FORCE},
{"torque", mjCONDATA_TORQUE},
{"dist", mjCONDATA_DIST},
{"pos", mjCONDATA_POS},
{"normal", mjCONDATA_NORMAL},
{"tangent", mjCONDATA_TANGENT}
{"found", mjCONDATA_FOUND},
{"force", mjCONDATA_FORCE},
{"torque", mjCONDATA_TORQUE},
{"dist", mjCONDATA_DIST},
{"pos", mjCONDATA_POS},
{"normal", mjCONDATA_NORMAL},
{"tangent", mjCONDATA_TANGENT}
};
// contact reduction type
const int reduce_sz = 4;
const mjMap reduce_map[reduce_sz] = {
{"none", 0},
{"mindist", 1},
{"maxforce", 2},
{"netforce", 3}
{"none", 0},
{"mindist", 1},
{"maxforce", 2},
{"netforce", 3}
};
// LR mode
const int lrmode_sz = 4;
const mjMap lrmode_map[lrmode_sz] = {
{"none", mjLRMODE_NONE},
{"muscle", mjLRMODE_MUSCLE},
{"muscleuser", mjLRMODE_MUSCLEUSER},
{"all", mjLRMODE_ALL}
{"none", mjLRMODE_NONE},
{"muscle", mjLRMODE_MUSCLE},
{"muscleuser", mjLRMODE_MUSCLEUSER},
{"all", mjLRMODE_ALL}
};
// composite type
const mjMap comp_map[mjNCOMPTYPES] = {
{"particle", mjCOMPTYPE_PARTICLE},
{"grid", mjCOMPTYPE_GRID},
{"rope", mjCOMPTYPE_ROPE},
{"loop", mjCOMPTYPE_LOOP},
{"cable", mjCOMPTYPE_CABLE},
{"cloth", mjCOMPTYPE_CLOTH}
{"particle", mjCOMPTYPE_PARTICLE},
{"grid", mjCOMPTYPE_GRID},
{"rope", mjCOMPTYPE_ROPE},
{"loop", mjCOMPTYPE_LOOP},
{"cable", mjCOMPTYPE_CABLE},
{"cloth", mjCOMPTYPE_CLOTH}
};
// composite joint kind
const mjMap jkind_map[1] = {
{"main", mjCOMPKIND_JOINT}
{"main", mjCOMPKIND_JOINT}
};
// composite rope shape
const mjMap shape_map[mjNCOMPSHAPES] = {
{"s", mjCOMPSHAPE_LINE},
{"cos(s)", mjCOMPSHAPE_COS},
{"sin(s)", mjCOMPSHAPE_SIN},
{"0", mjCOMPSHAPE_ZERO}
{"s", mjCOMPSHAPE_LINE},
{"cos(s)", mjCOMPSHAPE_COS},
{"sin(s)", mjCOMPSHAPE_SIN},
{"0", mjCOMPSHAPE_ZERO}
};
// mesh type
const mjMap meshtype_map[2] = {
{"false", mjINERTIA_VOLUME},
{"true", mjINERTIA_SHELL},
{"false", mjINERTIA_VOLUME},
{"true", mjINERTIA_SHELL},
};
// mesh inertia type
const mjMap meshinertia_map[4] = {
{"convex", mjMESH_INERTIA_CONVEX},
{"legacy", mjMESH_INERTIA_LEGACY},
{"exact", mjMESH_INERTIA_EXACT},
{"shell", mjMESH_INERTIA_SHELL}
{"convex", mjMESH_INERTIA_CONVEX},
{"legacy", mjMESH_INERTIA_LEGACY},
{"exact", mjMESH_INERTIA_EXACT},
{"shell", mjMESH_INERTIA_SHELL}
};
// mesh builtin type
const int meshbuiltin_sz = 7;
const int meshbuiltin_sz = 8;
const mjMap meshbuiltin_map[meshbuiltin_sz] = {
{"none", mjMESH_BUILTIN_NONE},
{"sphere", mjMESH_BUILTIN_SPHERE},
{"hemisphere", mjMESH_BUILTIN_HEMISPHERE},
{"cone", mjMESH_BUILTIN_CONE},
{"supertorus", mjMESH_BUILTIN_SUPERTORUS},
{"wedge", mjMESH_BUILTIN_WEDGE},
{"plate", mjMESH_BUILTIN_PLATE}
{"none", mjMESH_BUILTIN_NONE},
{"sphere", mjMESH_BUILTIN_SPHERE},
{"hemisphere", mjMESH_BUILTIN_HEMISPHERE},
{"cone", mjMESH_BUILTIN_CONE},
{"supertorus", mjMESH_BUILTIN_SUPERTORUS},
{"supersphere", mjMESH_BUILTIN_SUPERSPHERE},
{"wedge", mjMESH_BUILTIN_WEDGE},
{"plate", mjMESH_BUILTIN_PLATE}
};
// flexcomp type
const mjMap fcomp_map[mjNFCOMPTYPES] = {
{"grid", mjFCOMPTYPE_GRID},
{"box", mjFCOMPTYPE_BOX},
{"cylinder", mjFCOMPTYPE_CYLINDER},
{"ellipsoid", mjFCOMPTYPE_ELLIPSOID},
{"square", mjFCOMPTYPE_SQUARE},
{"disc", mjFCOMPTYPE_DISC},
{"circle", mjFCOMPTYPE_CIRCLE},
{"mesh", mjFCOMPTYPE_MESH},
{"gmsh", mjFCOMPTYPE_GMSH},
{"direct", mjFCOMPTYPE_DIRECT}
{"grid", mjFCOMPTYPE_GRID},
{"box", mjFCOMPTYPE_BOX},
{"cylinder", mjFCOMPTYPE_CYLINDER},
{"ellipsoid", mjFCOMPTYPE_ELLIPSOID},
{"square", mjFCOMPTYPE_SQUARE},
{"disc", mjFCOMPTYPE_DISC},
{"circle", mjFCOMPTYPE_CIRCLE},
{"mesh", mjFCOMPTYPE_MESH},
{"gmsh", mjFCOMPTYPE_GMSH},
{"direct", mjFCOMPTYPE_DIRECT}
};
// flexcomp dof type
const mjMap fdof_map[mjNFCOMPDOFS] = {
{"full", mjFCOMPDOF_FULL},
{"radial", mjFCOMPDOF_RADIAL},
{"trilinear", mjFCOMPDOF_TRILINEAR}
{"full", mjFCOMPDOF_FULL},
{"radial", mjFCOMPDOF_RADIAL},
{"trilinear", mjFCOMPDOF_TRILINEAR}
};
// flex selfcollide type
const mjMap flexself_map[5] = {
{"none", mjFLEXSELF_NONE},
{"narrow", mjFLEXSELF_NARROW},
{"bvh", mjFLEXSELF_BVH},
{"sap", mjFLEXSELF_SAP},
{"auto", mjFLEXSELF_AUTO},
{"none", mjFLEXSELF_NONE},
{"narrow", mjFLEXSELF_NARROW},
{"bvh", mjFLEXSELF_BVH},
{"sap", mjFLEXSELF_SAP},
{"auto", mjFLEXSELF_AUTO},
};
// flex elastic 2d type
const mjMap elastic2d_map[5] = {
{"none", 0},
{"bend", 1},
{"stretch", 2},
{"both", 3},
{"none", 0},
{"bend", 1},
{"stretch", 2},
{"both", 3},
};
+2
View File
@@ -2,6 +2,7 @@
<asset>
<mesh name="sphere" builtin="sphere" params="2" scale=".8 .8 .8"/>
<mesh name="hemisphere" builtin="hemisphere" params="4" scale=".8 .8 .8"/>
<mesh name="supersphere" builtin="supersphere" params="50 2 1" scale=".8 .8 .8"/>
<mesh name="toroid" builtin="supertorus" params="50 .5 .42 1.42" scale=".8 .8 .8"/>
<mesh name="wedge" builtin="wedge" params="10 10 60 60 0"/>
<mesh name="prism3" builtin="cone" params="3 1" scale=".3 .3 .3"/>
@@ -14,6 +15,7 @@
<light pos="0 0 10"/>
<geom mesh="sphere" type="mesh" pos="-3 0 0"/>
<geom mesh="hemisphere" type="mesh" pos="-1 0 0"/>
<geom mesh="supersphere" type="mesh" pos="2 0 2"/>
<geom mesh="toroid" type="mesh" pos="-1 0 2"/>
<geom mesh="wedge" type="mesh" euler="90 -90 0"/>
<geom mesh="prism5" type="mesh" pos="2 0 0" euler="90 0 0"/>
+4 -3
View File
@@ -502,9 +502,10 @@ public enum mjtMeshBuiltin : int{
mjMESH_BUILTIN_SPHERE = 1,
mjMESH_BUILTIN_HEMISPHERE = 2,
mjMESH_BUILTIN_CONE = 3,
mjMESH_BUILTIN_SUPERTORUS = 4,
mjMESH_BUILTIN_WEDGE = 5,
mjMESH_BUILTIN_PLATE = 6,
mjMESH_BUILTIN_SUPERSPHERE = 4,
mjMESH_BUILTIN_SUPERTORUS = 5,
mjMESH_BUILTIN_WEDGE = 6,
mjMESH_BUILTIN_PLATE = 7,
}
public enum mjtBuiltin : int{
mjBUILTIN_NONE = 0,