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
+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);