Add maxhullvert.

PiperOrigin-RevId: 641092710
Change-Id: Ib4fa828a9c82531614f0a67de9990340dbb25406
This commit is contained in:
Baruch Tabanpour
2024-06-06 19:04:21 -07:00
committed by Copybara-Service
parent fb8bf206d9
commit ace0c8f0a3
11 changed files with 86 additions and 10 deletions
+9
View File
@@ -1233,6 +1233,13 @@ The full list of processing steps applied by the compiler to each mesh is as fol
faces at large angles relative to the average normal are excluded from the average. In this way, sharp edges (as in faces at large angles relative to the average normal are excluded from the average. In this way, sharp edges (as in
cube edges) are not smoothed. cube edges) are not smoothed.
.. _asset-mesh-maxhullvert:
:at:`maxhullvert`: :at-val:`int, "-1"`
Maximum number of vertices in a mesh's convex hull. Currently this is implemented by asking qhull
`to teminate <http://www.qhull.org/html/qh-optt.htm#TAn>`__ after :at:`maxhullvert` vertices. The default
value of -1 means "unlimited". Positive values must be larger than 3.
.. _asset-mesh-vertex: .. _asset-mesh-vertex:
:at:`vertex`: :at-val:`real(3*nvert), optional` :at:`vertex`: :at-val:`real(3*nvert), optional`
@@ -7666,6 +7673,8 @@ if omitted.
.. _default-mesh-scale: .. _default-mesh-scale:
.. _default-mesh-maxhullvert:
:el-prefix:`default/` |-| **mesh** (?) :el-prefix:`default/` |-| **mesh** (?)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+3 -1
View File
@@ -103,6 +103,8 @@
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`refpos<asset-mesh-refpos>` | :ref:`refquat<asset-mesh-refquat>` | :ref:`scale<asset-mesh-scale>` | :ref:`smoothnormal<asset-mesh-smoothnormal>` | | | | | | :ref:`refpos<asset-mesh-refpos>` | :ref:`refquat<asset-mesh-refquat>` | :ref:`scale<asset-mesh-scale>` | :ref:`smoothnormal<asset-mesh-smoothnormal>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`maxhullvert<asset-mesh-maxhullvert>` | | | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |_2| mesh |br| |_2| |L| | | .. table:: | | |_2| mesh |br| |_2| |L| | | .. table:: |
| :ref:`plugin | \* | :class: mjcf-attributes | | :ref:`plugin | \* | :class: mjcf-attributes |
@@ -1325,7 +1327,7 @@
| :ref:`mesh | ? | :class: mjcf-attributes | | :ref:`mesh | ? | :class: mjcf-attributes |
| <default-mesh>` | | | | <default-mesh>` | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`scale<default-mesh-scale>` | | | | | | | | | :ref:`scale<default-mesh-scale>` | :ref:`maxhullvert<default-mesh-maxhullvert>` | | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |_| default |br| |_| |L| | | .. table:: | | |_| default |br| |_| |L| | | .. table:: |
+9
View File
@@ -2,6 +2,15 @@
Changelog Changelog
========= =========
Upcoming version (not yet released)
-----------------------------------
General
^^^^^^^
1. Added :ref:`maxhullvert<asset-mesh-maxhullvert>`, the maximum number of vertices in a mesh's convex hull.
Version 3.1.6 (Jun 3, 2024) Version 3.1.6 (Jun 3, 2024)
--------------------------- ---------------------------
+1
View File
@@ -446,6 +446,7 @@ typedef struct mjsMesh_ { // mesh specification
double refquat[4]; // reference orientation double refquat[4]; // reference orientation
double scale[3]; // rescale mesh double scale[3]; // rescale mesh
mjtByte smoothnormal; // do not exclude large-angle faces from normals mjtByte smoothnormal; // do not exclude large-angle faces from normals
int maxhullvert; // maximum vertex count for the convex hull
mjFloatVec* uservert; // user vertex data mjFloatVec* uservert; // user vertex data
mjFloatVec* usernormal; // user normal data mjFloatVec* usernormal; // user normal data
mjFloatVec* usertexcoord; // user texcoord data mjFloatVec* usertexcoord; // user texcoord data
+1
View File
@@ -243,6 +243,7 @@ void mjs_defaultMesh(mjsMesh* mesh) {
memset(mesh, 0, sizeof(mjsMesh)); memset(mesh, 0, sizeof(mjsMesh));
mesh->refquat[0] = 1; mesh->refquat[0] = 1;
mesh->scale[0] = mesh->scale[1] = mesh->scale[2] = 1; mesh->scale[0] = mesh->scale[1] = mesh->scale[2] = 1;
mesh->maxhullvert = -1;
} }
+11 -6
View File
@@ -50,8 +50,8 @@
#include <mujoco/mjmacro.h> #include <mujoco/mjmacro.h>
#include <mujoco/mjmodel.h> #include <mujoco/mjmodel.h>
#include <mujoco/mjtnum.h>
#include <mujoco/mjplugin.h> #include <mujoco/mjplugin.h>
#include <mujoco/mjtnum.h>
#include "engine/engine_crossplatform.h" #include "engine/engine_crossplatform.h"
#include "engine/engine_io.h" #include "engine/engine_io.h"
#include "engine/engine_plugin.h" #include "engine/engine_plugin.h"
@@ -135,6 +135,7 @@ mjCMesh::mjCMesh(mjCModel* _model, mjCDef* _def) {
center_ = NULL; center_ = NULL;
graph_ = NULL; graph_ = NULL;
needhull_ = false; needhull_ = false;
maxhullvert_ = -1;
invalidorientation_.first = -1; invalidorientation_.first = -1;
invalidorientation_.second = -1; invalidorientation_.second = -1;
validarea_ = true; validarea_ = true;
@@ -223,6 +224,7 @@ void mjCMesh::CopyFromSpec() {
facetexcoord_ = spec_facetexcoord_; facetexcoord_ = spec_facetexcoord_;
file = &file_; file = &file_;
content_type = &content_type_; content_type = &content_type_;
maxhullvert_ = spec.maxhullvert;
uservert = &vert_; uservert = &vert_;
usernormal = &normal_; usernormal = &normal_;
userface = &face_; userface = &face_;
@@ -1548,12 +1550,17 @@ double& mjCMesh::GetVolumeRef(mjtGeomInertia type) {
// make graph describing convex hull // make graph describing convex hull
void mjCMesh::MakeGraph(void) { void mjCMesh::MakeGraph() {
int adr, ok, curlong, totlong, exitcode; int adr, ok, curlong, totlong, exitcode;
double* data; double* data;
facetT* facet, **facetp; facetT* facet, **facetp;
vertexT* vertex, *vertex1, **vertex1p; vertexT* vertex, *vertex1, **vertex1p;
char qhopt[10] = "qhull Qt";
std::string qhopt = "qhull Qt";
if (maxhullvert_ > -1) {
// qhull "TA" actually means "number of vertices added after the initial simplex"
qhopt += " TA" + std::to_string(maxhullvert_ - 4);
}
// graph not needed for small meshes // graph not needed for small meshes
if (nvert() < 4) { if (nvert() < 4) {
@@ -1585,7 +1592,7 @@ void mjCMesh::MakeGraph(void) {
qh->NOerrexit = false; qh->NOerrexit = false;
if (!exitcode) { if (!exitcode) {
// actual init // actual init
qh_initflags(qh, qhopt); qh_initflags(qh, const_cast<char*>(qhopt.c_str()));
qh_init_B(qh, data, nvert(), 3, False); qh_init_B(qh, data, nvert(), 3, False);
// construct convex hull // construct convex hull
@@ -1742,8 +1749,6 @@ void mjCMesh::MakeGraph(void) {
} }
} }
// copy graph into face data // copy graph into face data
void mjCMesh::CopyGraph(void) { void mjCMesh::CopyGraph(void) {
// only if face data is missing // only if face data is missing
+1
View File
@@ -778,6 +778,7 @@ class mjCMesh_ : public mjCBase {
// size of mesh data to be copied into mjModel // size of mesh data to be copied into mjModel
int szgraph_; // size of graph data in ints int szgraph_; // size of graph data in ints
bool needhull_; // needs convex hull for collisions bool needhull_; // needs convex hull for collisions
int maxhullvert_; // max vertex count of convex hull
mjCBoundingVolumeHierarchy tree_; // bounding volume hierarchy mjCBoundingVolumeHierarchy tree_; // bounding volume hierarchy
std::vector<double> face_aabb_; // bounding boxes of all faces std::vector<double> face_aabb_; // bounding boxes of all faces
+9 -3
View File
@@ -145,7 +145,7 @@ const char* MJCF[nMJCF][mjXATTRNUM] = {
{"default", "R", "1", "class"}, {"default", "R", "1", "class"},
{"<"}, {"<"},
{"mesh", "?", "1", "scale"}, {"mesh", "?", "2", "scale", "maxhullvert"},
{"material", "?", "10", "texture", "emission", "specular", "shininess", {"material", "?", "10", "texture", "emission", "specular", "shininess",
"reflectance", "metallic", "roughness", "rgba", "texrepeat", "texuniform"}, "reflectance", "metallic", "roughness", "rgba", "texrepeat", "texuniform"},
{"joint", "?", "22", "type", "group", "pos", "axis", "springdamper", {"joint", "?", "22", "type", "group", "pos", "axis", "springdamper",
@@ -221,8 +221,9 @@ const char* MJCF[nMJCF][mjXATTRNUM] = {
{"asset", "*", "0"}, {"asset", "*", "0"},
{"<"}, {"<"},
{"mesh", "*", "12", "name", "class", "content_type", "file", "vertex", "normal", {"mesh", "*", "13", "name", "class", "content_type", "file", "vertex", "normal",
"texcoord", "face", "refpos", "refquat", "scale", "smoothnormal"}, "texcoord", "face", "refpos", "refquat", "scale", "smoothnormal",
"maxhullvert"},
{"<"}, {"<"},
{"plugin", "*", "2", "plugin", "instance"}, {"plugin", "*", "2", "plugin", "instance"},
{"<"}, {"<"},
@@ -1391,6 +1392,11 @@ void mjXReader::OneMesh(XMLElement* elem, mjsMesh* pmesh) {
pmesh->smoothnormal = (n==1); pmesh->smoothnormal = (n==1);
} }
if (ReadAttrInt(elem, "maxhullvert", &n)) {
if (n != 0 && n < 4) throw mjXError(elem, "maxhullvert must be larger than 3");
pmesh->maxhullvert = n;
}
// read user vertex data // read user vertex data
if (ReadAttrTxt(elem, "vertex", text)) { if (ReadAttrTxt(elem, "vertex", text)) {
auto uservert = ReadAttrVec<float>(elem, "vertex"); auto uservert = ReadAttrVec<float>(elem, "vertex");
+8
View File
@@ -0,0 +1,8 @@
<mujoco>
<asset>
<mesh file="torus.obj" maxhullvert="4"/>
</asset>
<worldbody>
<geom type="mesh" mesh="torus"/>
</worldbody>
</mujoco>
+11
View File
@@ -0,0 +1,11 @@
<mujoco>
<default>
<mesh maxhullvert="64"/>
</default>
<asset>
<mesh file="torus.obj"/>
</asset>
<worldbody>
<geom type="mesh" mesh="torus"/>
</worldbody>
</mujoco>
+23
View File
@@ -41,6 +41,10 @@ static const char* const kCubePath =
"user/testdata/cube.xml"; "user/testdata/cube.xml";
static const char* const kTorusPath = static const char* const kTorusPath =
"user/testdata/torus.xml"; "user/testdata/torus.xml";
static const char* const kTorusMaxhullVertPath =
"user/testdata/torus_maxhullvert.xml";
static const char* const kTorusDefaultMaxhullVertPath =
"user/testdata/torus_maxhullvert_default.xml";
static const char* const kTorusShellPath = static const char* const kTorusShellPath =
"user/testdata/torus_shell.xml"; "user/testdata/torus_shell.xml";
static const char* const kConvexInertiaPath = static const char* const kConvexInertiaPath =
@@ -405,6 +409,25 @@ TEST_F(MjCMeshTest, TinyMeshLoads) {
mj_deleteModel(model); mj_deleteModel(model);
} }
// ------------- test max hull vert -------------------------------------------
TEST_F(MjCMeshTest, MaxHullVert) {
const std::string xml_path = GetTestDataFilePath(kTorusMaxhullVertPath);
std::array<char, 1024> error;
mjModel* model = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
ASSERT_GT(model->ngeom, 0);
ASSERT_EQ(model->mesh_graph[0], 4);
mj_deleteModel(model);
}
TEST_F(MjCMeshTest, MaxHullVertDefault) {
const std::string xml_path = GetTestDataFilePath(kTorusDefaultMaxhullVertPath);
std::array<char, 1024> error;
mjModel* model = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
ASSERT_GT(model->ngeom, 0);
ASSERT_EQ(model->mesh_graph[0], 64);
mj_deleteModel(model);
}
// ------------- test inline loading ------------------------------------------ // ------------- test inline loading ------------------------------------------
TEST_F(MjCMeshTest, FaceNormalAutogenerated) { TEST_F(MjCMeshTest, FaceNormalAutogenerated) {
static constexpr char xml[] = R"( static constexpr char xml[] = R"(