Add visualisation groups to skins.

PiperOrigin-RevId: 458441645
Change-Id: I14324e8efda5142b2718a5cc9215228c7556dbf7
This commit is contained in:
Alessio Quaglino
2022-07-01 04:56:46 -07:00
committed by Copybara-Service
parent 040deb161f
commit 2d0995b47c
19 changed files with 256 additions and 115 deletions
+1
View File
@@ -217,6 +217,7 @@ void mjv_defaultOption(mjvOption* vopt) {
vopt->jointgroup[i] = state;
vopt->tendongroup[i] = state;
vopt->actuatorgroup[i] = state;
vopt->skingroup[i] = state;
}
for (int i=0; i<mjNVISFLAG; i++) {
+106 -95
View File
@@ -1767,9 +1767,18 @@ void mjv_updateCamera(const mjModel* m, mjData* d, mjvCamera* cam, mjvScene* scn
}
// update skins only
// update all skins, here for backward API compatibility
void mjv_updateSkin(const mjModel* m, mjData* d, mjvScene* scn) {
mjvOption opt;
mjv_defaultOption(&opt);
mjv_updateActiveSkin(m, d, scn, &opt);
mju_warning("mjv_updateSkin is deprecated, please use mjv_updateActiveSkin.");
}
// update visible skins only
void mjv_updateActiveSkin(const mjModel* m, mjData* d, mjvScene* scn, const mjvOption* opt) {
// process skins
for (int i=0; i<m->nskin; i++) {
// get info
@@ -1782,111 +1791,113 @@ void mjv_updateSkin(const mjModel* m, mjData* d, mjvScene* scn) {
memset(scn->skinvert + 3*vertadr, 0, 3*vertnum*sizeof(float));
memset(scn->skinnormal + 3*vertadr, 0, 3*vertnum*sizeof(float));
// accumulate positions from all bones
for (int j=m->skin_boneadr[i];
j<m->skin_boneadr[i]+m->skin_bonenum[i];
j++) {
// get bind pose
mjtNum bindpos[3] = {
(mjtNum) m->skin_bonebindpos[3*j],
(mjtNum) m->skin_bonebindpos[3*j+1],
(mjtNum) m->skin_bonebindpos[3*j+2]
};
mjtNum bindquat[4] = {
(mjtNum) m->skin_bonebindquat[4*j],
(mjtNum) m->skin_bonebindquat[4*j+1],
(mjtNum) m->skin_bonebindquat[4*j+2],
(mjtNum) m->skin_bonebindquat[4*j+3]
};
// compute rotation
int bodyid = m->skin_bonebodyid[j];
mjtNum quat[4], quatneg[4], rotate[9];
mju_negQuat(quatneg, bindquat);
mju_mulQuat(quat, d->xquat+4*bodyid, quatneg);
mju_quat2Mat(rotate, quat);
// compute translation
mjtNum translate[3];
mju_rotVecMat(translate, bindpos, rotate);
mju_sub3(translate, d->xpos+3*bodyid, translate);
// process all bone vertices
for (int k=m->skin_bonevertadr[j];
k<m->skin_bonevertadr[j]+m->skin_bonevertnum[j];
k++) {
// vertex id and weight
int vid = m->skin_bonevertid[k];
float vweight = m->skin_bonevertweight[k];
// get original position
mjtNum pos[3] = {
(mjtNum) m->skin_vert[3*(vertadr+vid)],
(mjtNum) m->skin_vert[3*(vertadr+vid)+1],
(mjtNum) m->skin_vert[3*(vertadr+vid)+2],
if (opt->skingroup[m->skin_group[i]]) {
// accumulate positions from all bones
for (int j=m->skin_boneadr[i];
j<m->skin_boneadr[i]+m->skin_bonenum[i];
j++) {
// get bind pose
mjtNum bindpos[3] = {
(mjtNum) m->skin_bonebindpos[3*j],
(mjtNum) m->skin_bonebindpos[3*j+1],
(mjtNum) m->skin_bonebindpos[3*j+2]
};
mjtNum bindquat[4] = {
(mjtNum) m->skin_bonebindquat[4*j],
(mjtNum) m->skin_bonebindquat[4*j+1],
(mjtNum) m->skin_bonebindquat[4*j+2],
(mjtNum) m->skin_bonebindquat[4*j+3]
};
// transform
mjtNum pos1[3];
mju_rotVecMat(pos1, pos, rotate);
mju_addTo3(pos1, translate);
// compute rotation
int bodyid = m->skin_bonebodyid[j];
mjtNum quat[4], quatneg[4], rotate[9];
mju_negQuat(quatneg, bindquat);
mju_mulQuat(quat, d->xquat+4*bodyid, quatneg);
mju_quat2Mat(rotate, quat);
// accumulate position
scn->skinvert[3*(vertadr+vid)] += vweight*(float)pos1[0];
scn->skinvert[3*(vertadr+vid)+1] += vweight*(float)pos1[1];
scn->skinvert[3*(vertadr+vid)+2] += vweight*(float)pos1[2];
}
}
// compute translation
mjtNum translate[3];
mju_rotVecMat(translate, bindpos, rotate);
mju_sub3(translate, d->xpos+3*bodyid, translate);
// compute vertex normals from face normals
for (int k=faceadr; k<faceadr+facenum; k++) {
// get face vertex indices
int vid[3] = {
m->skin_face[3*k],
m->skin_face[3*k+1],
m->skin_face[3*k+2]
};
// process all bone vertices
for (int k=m->skin_bonevertadr[j];
k<m->skin_bonevertadr[j]+m->skin_bonevertnum[j];
k++) {
// vertex id and weight
int vid = m->skin_bonevertid[k];
float vweight = m->skin_bonevertweight[k];
// get triangle edges
mjtNum vec01[3], vec02[3];
for (int r=0; r<3; r++) {
vec01[r] = scn->skinvert[3*(vertadr+vid[1])+r] - scn->skinvert[3*(vertadr+vid[0])+r];
vec02[r] = scn->skinvert[3*(vertadr+vid[2])+r] - scn->skinvert[3*(vertadr+vid[0])+r];
}
// get original position
mjtNum pos[3] = {
(mjtNum) m->skin_vert[3*(vertadr+vid)],
(mjtNum) m->skin_vert[3*(vertadr+vid)+1],
(mjtNum) m->skin_vert[3*(vertadr+vid)+2],
};
// compute face normal
mjtNum nrm[3];
mju_cross(nrm, vec01, vec02);
// transform
mjtNum pos1[3];
mju_rotVecMat(pos1, pos, rotate);
mju_addTo3(pos1, translate);
// add normal to each vertex with weight = area
for (int r=0; r<3; r++) {
for (int t=0; t<3; t++) {
scn->skinnormal[3*(vertadr+vid[r])+t] += nrm[t];
// accumulate position
scn->skinvert[3*(vertadr+vid)] += vweight*(float)pos1[0];
scn->skinvert[3*(vertadr+vid)+1] += vweight*(float)pos1[1];
scn->skinvert[3*(vertadr+vid)+2] += vweight*(float)pos1[2];
}
}
}
// normalize normals
for (int k=vertadr; k<vertadr+vertnum; k++) {
float s = sqrtf(
scn->skinnormal[3*k]*scn->skinnormal[3*k] +
scn->skinnormal[3*k+1]*scn->skinnormal[3*k+1] +
scn->skinnormal[3*k+2]*scn->skinnormal[3*k+2]
);
float scl = 1/mjMAX(mjMINVAL, s);
// compute vertex normals from face normals
for (int k=faceadr; k<faceadr+facenum; k++) {
// get face vertex indices
int vid[3] = {
m->skin_face[3*k],
m->skin_face[3*k+1],
m->skin_face[3*k+2]
};
scn->skinnormal[3*k] *= scl;
scn->skinnormal[3*k+1] *= scl;
scn->skinnormal[3*k+2] *= scl;
}
// get triangle edges
mjtNum vec01[3], vec02[3];
for (int r=0; r<3; r++) {
vec01[r] = scn->skinvert[3*(vertadr+vid[1])+r] - scn->skinvert[3*(vertadr+vid[0])+r];
vec02[r] = scn->skinvert[3*(vertadr+vid[2])+r] - scn->skinvert[3*(vertadr+vid[0])+r];
}
// inflate
if (m->skin_inflate[i]) {
float inflate = m->skin_inflate[i];
// compute face normal
mjtNum nrm[3];
mju_cross(nrm, vec01, vec02);
// add normal to each vertex with weight = area
for (int r=0; r<3; r++) {
for (int t=0; t<3; t++) {
scn->skinnormal[3*(vertadr+vid[r])+t] += nrm[t];
}
}
}
// normalize normals
for (int k=vertadr; k<vertadr+vertnum; k++) {
scn->skinvert[3*k] += inflate*scn->skinnormal[3*k];
scn->skinvert[3*k+1] += inflate*scn->skinnormal[3*k+1];
scn->skinvert[3*k+2] += inflate*scn->skinnormal[3*k+2];
float s = sqrtf(
scn->skinnormal[3*k]*scn->skinnormal[3*k] +
scn->skinnormal[3*k+1]*scn->skinnormal[3*k+1] +
scn->skinnormal[3*k+2]*scn->skinnormal[3*k+2]
);
float scl = 1/mjMAX(mjMINVAL, s);
scn->skinnormal[3*k] *= scl;
scn->skinnormal[3*k+1] *= scl;
scn->skinnormal[3*k+2] *= scl;
}
// inflate
if (m->skin_inflate[i]) {
float inflate = m->skin_inflate[i];
for (int k=vertadr; k<vertadr+vertnum; k++) {
scn->skinvert[3*k] += inflate*scn->skinnormal[3*k];
scn->skinvert[3*k+1] += inflate*scn->skinnormal[3*k+1];
scn->skinvert[3*k+2] += inflate*scn->skinnormal[3*k+2];
}
}
}
}
@@ -1909,6 +1920,6 @@ void mjv_updateScene(const mjModel* m, mjData* d, const mjvOption* opt,
// update skins
if (opt->flags[mjVIS_SKIN]) {
mjv_updateSkin(m, d, scn);
mjv_updateActiveSkin(m, d, scn, opt);
}
}
+3
View File
@@ -51,6 +51,9 @@ MJAPI void mjv_updateCamera(const mjModel* m, mjData* d, mjvCamera* cam, mjvScen
// update skins only
MJAPI void mjv_updateSkin(const mjModel* m, mjData* d, mjvScene* scn);
// update visible skins only
MJAPI void mjv_updateActiveSkin(const mjModel* m, mjData* d, mjvScene* scn, const mjvOption* opt);
#ifdef __cplusplus
}
#endif
+4
View File
@@ -67,6 +67,7 @@ mjCComposite::mjCComposite(void) {
mjuu_setvec(skinrgba, 1, 1, 1, 1);
skininflate = 0;
skinsubgrid = 0;
skingroup = 0;
// clear add flags
for (int i=0; i<mjNCOMPKINDS; i++) {
@@ -1053,6 +1054,7 @@ void mjCComposite::MakeSkin2(mjCModel* model) {
skin->material = skinmaterial;
mjuu_copyvec(skin->rgba, skinrgba, 4);
skin->inflate = skininflate;
skin->group = skingroup;
// populate mesh: two sides
for (int i=0; i<2; i++) {
@@ -1473,6 +1475,7 @@ void mjCComposite::MakeSkin2Subgrid(mjCModel* model) {
skin->material = skinmaterial;
mjuu_copyvec(skin->rgba, skinrgba, 4);
skin->inflate = skininflate;
skin->group = skingroup;
// populate mesh: two sides
mjtNum S = spacing/(1+skinsubgrid);
@@ -1643,6 +1646,7 @@ void mjCComposite::MakeSkin3(mjCModel* model) {
skin->material = skinmaterial;
mjuu_copyvec(skin->rgba, skinrgba, 4);
skin->inflate = skininflate;
skin->group = skingroup;
// box
if (type==mjCOMPTYPE_BOX) {
+1
View File
@@ -94,6 +94,7 @@ class mjCComposite {
float skinrgba[4]; // skin rgba
float skininflate; // inflate skin
int skinsubgrid; // number of skin subgrid points; 0: none (2D only)
int skingroup; // skin group of the composite object
// element options
bool add[mjNCOMPKINDS]; // add element
+1 -1
View File
@@ -1408,6 +1408,7 @@ mjCSkin::mjCSkin(mjCModel* _model) {
rgba[0] = rgba[1] = rgba[2] = 0.5f;
rgba[3] = 1.0f;
inflate = 0;
group = 0;
vert.clear();
texcoord.clear();
@@ -1530,7 +1531,6 @@ void mjCSkin::Compile(const mjVFS* vfs) {
throw mjCError(this, "unkown material '%s' in skin", material.c_str());
}
// set total vertex weights to 0
vector<float> vw;
size_t nvert = vert.size()/3;
+1
View File
@@ -1628,6 +1628,7 @@ void mjCModel::CopyObjects(mjModel* m) {
// set fields
m->skin_matid[i] = psk->matid;
copyvec(m->skin_rgba+4*i, psk->rgba, 4);
m->skin_group[i] = psk->group;
m->skin_inflate[i] = psk->inflate;
m->skin_vertadr[i] = vert_adr;
m->skin_vertnum[i] = psk->vert.size()/3;
+1
View File
@@ -504,6 +504,7 @@ class mjCSkin: public mjCBase {
std::string material; // name of material used for rendering
float rgba[4]; // rgba when material is omitted
float inflate; // inflate in normal direction
int group; // group for visualization
// mesh
std::vector<float> vert; // vertex positions
+12 -3
View File
@@ -22,6 +22,7 @@
#include <vector>
#include <mujoco/mjmodel.h>
#include <mujoco/mjvisualize.h>
#include "engine/engine_macro.h"
#include "engine/engine_util_errmem.h"
#include "engine/engine_util_misc.h"
@@ -165,8 +166,8 @@ static const char* MJCF[nMJCF][mjXATTRNUM] = {
{"hfield", "*", "5", "name", "file", "nrow", "ncol", "size"},
{"mesh", "*", "11", "name", "class", "file", "vertex", "normal",
"texcoord", "face", "refpos", "refquat", "scale", "smoothnormal"},
{"skin", "*", "8", "name", "file", "material", "rgba", "inflate",
"vertex", "texcoord", "face"},
{"skin", "*", "9", "name", "file", "material", "rgba", "inflate",
"vertex", "texcoord", "face", "group"},
{"<"},
{"bone", "*", "5", "body", "bindpos", "bindquat", "vertid", "vertweight"},
{">"},
@@ -210,7 +211,7 @@ static const char* MJCF[nMJCF][mjXATTRNUM] = {
"limited", "range", "margin", "solreflimit", "solimplimit",
"frictionloss", "solreffriction", "solimpfriction",
"material", "rgba", "width"},
{"skin", "?", "5", "texcoord", "material", "rgba", "inflate", "subgrid"},
{"skin", "?", "6", "texcoord", "material", "group", "rgba", "inflate", "subgrid"},
{"geom", "?", "17", "type", "contype", "conaffinity", "condim",
"group", "priority", "size", "material", "rgba", "friction", "mass",
"density", "solmix", "solref", "solimp", "margin", "gap"},
@@ -983,6 +984,10 @@ void mjXReader::OneSkin(XMLElement* elem, mjCSkin* pskin) {
ReadAttrTxt(elem, "name", pskin->name);
ReadAttrTxt(elem, "file", pskin->file);
ReadAttrTxt(elem, "material", pskin->material);
ReadAttrInt(elem, "group", &pskin->group);
if (pskin->group<0 || pskin->group>=mjNGROUP) {
throw mjXError(elem, "skin group must be between 0 and 5");
}
ReadAttr(elem, "rgba", 4, pskin->rgba, text);
ReadAttr(elem, "inflate", 1, &pskin->inflate, text);
@@ -1617,6 +1622,10 @@ void mjXReader::OneComposite(XMLElement* elem, mjCBody* pbody, mjCDef* def) {
ReadAttr(eskin, "rgba", 4, comp.skinrgba, text);
ReadAttr(eskin, "inflate", 1, &comp.skininflate, text);
ReadAttrInt(eskin, "subgrid", &comp.skinsubgrid);
ReadAttrInt(eskin, "group", &comp.skingroup, 0);
if (comp.skingroup<0 || comp.skingroup>=mjNGROUP) {
throw mjXError(eskin, "skin group must be between 0 and 5");
}
}
// set type-specific defaults
+1
View File
@@ -125,6 +125,7 @@ void mjXWriter::OneSkin(XMLElement* elem, mjCSkin* pskin) {
WriteAttrTxt(elem, "name", pskin->name);
WriteAttrTxt(elem, "file", pskin->file);
WriteAttrTxt(elem, "material", pskin->material);
WriteAttrInt(elem, "group", pskin->group, 0);
WriteAttr(elem, "rgba", 4, pskin->rgba, mydef.geom.rgba);
WriteAttr(elem, "inflate", 1, &pskin->inflate, &zero);