Add spaces around comparison operators.
PiperOrigin-RevId: 573620198 Change-Id: Icf295cc0dd381a4a7f0e2c94f2e12b499193e862
This commit is contained in:
committed by
Copybara-Service
parent
a1b6026b8c
commit
a9ee497e33
@@ -39,12 +39,12 @@ void mjccd_center(const void *obj, ccd_vec3_t *center) {
|
|||||||
int v = ccd->vert;
|
int v = ccd->vert;
|
||||||
|
|
||||||
// return geom position
|
// return geom position
|
||||||
if (g>=0) {
|
if (g >= 0) {
|
||||||
mju_copy3(center->v, ccd->data->geom_xpos + 3*g);
|
mju_copy3(center->v, ccd->data->geom_xpos + 3*g);
|
||||||
}
|
}
|
||||||
|
|
||||||
// return flex element position
|
// return flex element position
|
||||||
else if (e>=0) {
|
else if (e >= 0) {
|
||||||
mju_copy3(center->v, ccd->data->flexelem_aabb + 6*(ccd->model->flex_elemadr[f]+e));
|
mju_copy3(center->v, ccd->data->flexelem_aabb + 6*(ccd->model->flex_elemadr[f]+e));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,14 +64,14 @@ void mjccd_support(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *vec) {
|
|||||||
int g = ccd->geom;
|
int g = ccd->geom;
|
||||||
|
|
||||||
//-------------------------- flex element or vertex -----------------------------
|
//-------------------------- flex element or vertex -----------------------------
|
||||||
if (g<0) {
|
if (g < 0) {
|
||||||
int f = ccd->flex;
|
int f = ccd->flex;
|
||||||
int dim = m->flex_dim[f];
|
int dim = m->flex_dim[f];
|
||||||
mjtNum *res = vec->v;
|
mjtNum *res = vec->v;
|
||||||
const mjtNum *dir = _dir->v;
|
const mjtNum *dir = _dir->v;
|
||||||
|
|
||||||
// flex element
|
// flex element
|
||||||
if (ccd->elem>=0) {
|
if (ccd->elem >= 0) {
|
||||||
int e = ccd->elem;
|
int e = ccd->elem;
|
||||||
const int* edata = m->flex_elem + m->flex_elemdataadr[f] + e*(dim+1);
|
const int* edata = m->flex_elem + m->flex_elemdataadr[f] + e*(dim+1);
|
||||||
const mjtNum* vert = d->flexvert_xpos + 3*m->flex_vertadr[f];
|
const mjtNum* vert = d->flexvert_xpos + 3*m->flex_vertadr[f];
|
||||||
@@ -79,11 +79,11 @@ void mjccd_support(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *vec) {
|
|||||||
// find element vertex with largest projection along dir
|
// find element vertex with largest projection along dir
|
||||||
mju_copy3(res, vert+3*edata[0]);
|
mju_copy3(res, vert+3*edata[0]);
|
||||||
mjtNum best = mju_dot3(res, dir);
|
mjtNum best = mju_dot3(res, dir);
|
||||||
for (int i=1; i<=dim; i++) {
|
for (int i=1; i <= dim; i++) {
|
||||||
mjtNum dot = mju_dot3(vert+3*edata[i], dir);
|
mjtNum dot = mju_dot3(vert+3*edata[i], dir);
|
||||||
|
|
||||||
// better vertex found: assign
|
// better vertex found: assign
|
||||||
if (dot>best) {
|
if (dot > best) {
|
||||||
best = dot;
|
best = dot;
|
||||||
mju_copy3(res, vert+3*edata[i]);
|
mju_copy3(res, vert+3*edata[i]);
|
||||||
}
|
}
|
||||||
@@ -285,7 +285,7 @@ static int mjc_MPRIteration(mjtCCD* obj1, mjtCCD* obj2, const ccd_t* ccd,
|
|||||||
mju_zero3(con->frame+3);
|
mju_zero3(con->frame+3);
|
||||||
|
|
||||||
// both geoms: fix contact frame normal
|
// both geoms: fix contact frame normal
|
||||||
if (obj1->geom>=0 && obj2->geom>=0) {
|
if (obj1->geom >= 0 && obj2->geom >= 0) {
|
||||||
mjc_fixNormal(m, d, con, obj1->geom, obj2->geom);
|
mjc_fixNormal(m, d, con, obj1->geom, obj2->geom);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1130,7 +1130,7 @@ int mjc_HFieldElem(const mjModel* m, const mjData* d, mjContact* con,
|
|||||||
int dim = m->flex_dim[f];
|
int dim = m->flex_dim[f];
|
||||||
const int* edata = m->flex_elem + m->flex_elemdataadr[f] + e*(dim+1);
|
const int* edata = m->flex_elem + m->flex_elemdataadr[f] + e*(dim+1);
|
||||||
mjtNum* evert[4] = {NULL, NULL, NULL, NULL};
|
mjtNum* evert[4] = {NULL, NULL, NULL, NULL};
|
||||||
for (int i=0; i<=dim; i++) {
|
for (int i=0; i <= dim; i++) {
|
||||||
evert[i] = d->flexvert_xpos + 3*(m->flex_vertadr[f] + edata[i]);
|
evert[i] = d->flexvert_xpos + 3*(m->flex_vertadr[f] + edata[i]);
|
||||||
}
|
}
|
||||||
mjtNum* ecenter = d->flexelem_aabb + 6*(m->flex_elemadr[f]+e);
|
mjtNum* ecenter = d->flexelem_aabb + 6*(m->flex_elemadr[f]+e);
|
||||||
@@ -1145,7 +1145,7 @@ int mjc_HFieldElem(const mjModel* m, const mjData* d, mjContact* con,
|
|||||||
|
|
||||||
// save elem vertices, transform to hfield frame
|
// save elem vertices, transform to hfield frame
|
||||||
mjtNum savevert[4][3];
|
mjtNum savevert[4][3];
|
||||||
for (int i=0; i<=dim; i++) {
|
for (int i=0; i <= dim; i++) {
|
||||||
mju_copy3(savevert[i], evert[i]);
|
mju_copy3(savevert[i], evert[i]);
|
||||||
mju_sub3(vec, evert[i], hpos);
|
mju_sub3(vec, evert[i], hpos);
|
||||||
mju_mulMatTVec(evert[i], hmat, vec, 3, 3);
|
mju_mulMatTVec(evert[i], hmat, vec, 3, 3);
|
||||||
@@ -1161,7 +1161,7 @@ int mjc_HFieldElem(const mjModel* m, const mjData* d, mjContact* con,
|
|||||||
xmin = xmax = evert[0][0];
|
xmin = xmax = evert[0][0];
|
||||||
ymin = ymax = evert[0][1];
|
ymin = ymax = evert[0][1];
|
||||||
zmin = zmax = evert[0][2];
|
zmin = zmax = evert[0][2];
|
||||||
for (int i=1; i<=dim; i++) {
|
for (int i=1; i <= dim; i++) {
|
||||||
xmin = mju_min(xmin, evert[i][0]);
|
xmin = mju_min(xmin, evert[i][0]);
|
||||||
xmax = mju_max(xmax, evert[i][0]);
|
xmax = mju_max(xmax, evert[i][0]);
|
||||||
ymin = mju_min(ymin, evert[i][1]);
|
ymin = mju_min(ymin, evert[i][1]);
|
||||||
@@ -1175,7 +1175,7 @@ int mjc_HFieldElem(const mjModel* m, const mjData* d, mjContact* con,
|
|||||||
(ymin-margin > hsize[1]) || (ymax+margin < -hsize[1]) ||
|
(ymin-margin > hsize[1]) || (ymax+margin < -hsize[1]) ||
|
||||||
(zmin-margin > hsize[2]) || (zmax+margin < -hsize[3])) {
|
(zmin-margin > hsize[2]) || (zmax+margin < -hsize[3])) {
|
||||||
// restore vertices and center
|
// restore vertices and center
|
||||||
for (int i=0; i<=dim; i++) {
|
for (int i=0; i <= dim; i++) {
|
||||||
mju_copy3(evert[i], savevert[i]);
|
mju_copy3(evert[i], savevert[i]);
|
||||||
}
|
}
|
||||||
mju_copy3(ecenter, savecenter);
|
mju_copy3(ecenter, savecenter);
|
||||||
@@ -1217,23 +1217,23 @@ int mjc_HFieldElem(const mjModel* m, const mjData* d, mjContact* con,
|
|||||||
|
|
||||||
// process all prisms in sub-grid
|
// process all prisms in sub-grid
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
for (int r=rmin; r<rmax; r++) {
|
for (int r=rmin; r < rmax; r++) {
|
||||||
int nvert = 0;
|
int nvert = 0;
|
||||||
for (int c=cmin; c<=cmax; c++) {
|
for (int c=cmin; c <= cmax; c++) {
|
||||||
for (int k=0; k<2; k++) {
|
for (int k=0; k < 2; k++) {
|
||||||
// send vertex to prism constructor
|
// send vertex to prism constructor
|
||||||
addVert(&nvert, &prism, dx*c-hsize[0], dy*(r+dr[k])-hsize[1],
|
addVert(&nvert, &prism, dx*c-hsize[0], dy*(r+dr[k])-hsize[1],
|
||||||
hdata[(r+dr[k])*ncol+c]*hsize[2]+margin);
|
hdata[(r+dr[k])*ncol+c]*hsize[2]+margin);
|
||||||
|
|
||||||
// check for enough vertices
|
// check for enough vertices
|
||||||
if (nvert>2) {
|
if (nvert > 2) {
|
||||||
// prism height test
|
// prism height test
|
||||||
if (prism.v[3][2]<zmin && prism.v[4][2]<zmin && prism.v[5][2]<zmin) {
|
if (prism.v[3][2] < zmin && prism.v[4][2] < zmin && prism.v[5][2] < zmin) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// run MPR, save contact
|
// run MPR, save contact
|
||||||
if (ccdMPRPenetration(&prism, &obj, &ccd, &depth, &dirccd, &vecccd)==0) {
|
if (ccdMPRPenetration(&prism, &obj, &ccd, &depth, &dirccd, &vecccd) == 0) {
|
||||||
if (!ccdVec3Eq(&dirccd, ccd_vec3_origin)) {
|
if (!ccdVec3Eq(&dirccd, ccd_vec3_origin)) {
|
||||||
// fill in contact data, transform to global coordinates
|
// fill in contact data, transform to global coordinates
|
||||||
con[cnt].dist = -depth;
|
con[cnt].dist = -depth;
|
||||||
@@ -1244,7 +1244,7 @@ int mjc_HFieldElem(const mjModel* m, const mjData* d, mjContact* con,
|
|||||||
|
|
||||||
// count, stop if max number reached
|
// count, stop if max number reached
|
||||||
cnt++;
|
cnt++;
|
||||||
if (cnt>=mjMAXCONPAIR) {
|
if (cnt >= mjMAXCONPAIR) {
|
||||||
r = rmax+1;
|
r = rmax+1;
|
||||||
c = cmax+1;
|
c = cmax+1;
|
||||||
k = 3;
|
k = 3;
|
||||||
@@ -1258,7 +1258,7 @@ int mjc_HFieldElem(const mjModel* m, const mjData* d, mjContact* con,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// restore elem vertices and center
|
// restore elem vertices and center
|
||||||
for (int i=0; i<=dim; i++) {
|
for (int i=0; i <= dim; i++) {
|
||||||
mju_copy3(evert[i], savevert[i]);
|
mju_copy3(evert[i], savevert[i]);
|
||||||
}
|
}
|
||||||
mju_copy3(ecenter, savecenter);
|
mju_copy3(ecenter, savecenter);
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ static inline void resetArena(mjData* d) {
|
|||||||
#ifdef ADDRESS_SANITIZER
|
#ifdef ADDRESS_SANITIZER
|
||||||
if (!d->threadpool) {
|
if (!d->threadpool) {
|
||||||
ASAN_POISON_MEMORY_REGION(
|
ASAN_POISON_MEMORY_REGION(
|
||||||
(char*)d->arena + d->parena, d->narena - d->pstack - d->parena);
|
(char*)d->arena + d->parena, d->narena - d->pstack - d->parena);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -145,19 +145,19 @@ static int filterSphere(const mjtNum pos1[3], const mjtNum pos2[3], mjtNum bound
|
|||||||
// filter contact based on bounding sphere test
|
// filter contact based on bounding sphere test
|
||||||
static int mj_filterSphere(const mjModel* m, mjData* d, int g1, int g2, mjtNum margin) {
|
static int mj_filterSphere(const mjModel* m, mjData* d, int g1, int g2, mjtNum margin) {
|
||||||
// neither geom is a plane
|
// neither geom is a plane
|
||||||
if (m->geom_rbound[g1]>0 && m->geom_rbound[g2]>0) {
|
if (m->geom_rbound[g1] > 0 && m->geom_rbound[g2] > 0) {
|
||||||
return filterSphere(d->geom_xpos + 3*g1, d->geom_xpos + 3*g2,
|
return filterSphere(d->geom_xpos + 3*g1, d->geom_xpos + 3*g2,
|
||||||
m->geom_rbound[g1] + m->geom_rbound[g2] + margin);
|
m->geom_rbound[g1] + m->geom_rbound[g2] + margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
// one geom is a plane
|
// one geom is a plane
|
||||||
if (m->geom_type[g1]==mjGEOM_PLANE && m->geom_rbound[g2]>0
|
if (m->geom_type[g1] == mjGEOM_PLANE && m->geom_rbound[g2] > 0
|
||||||
&& planeGeomDist(m, d, g1, g2) > margin + m->geom_rbound[g2]) {
|
&& planeGeomDist(m, d, g1, g2) > margin + m->geom_rbound[g2]) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (m->geom_type[g2]==mjGEOM_PLANE && m->geom_rbound[g1]>0
|
if (m->geom_type[g2] == mjGEOM_PLANE && m->geom_rbound[g1] > 0
|
||||||
&& planeGeomDist(m, d, g2, g1) > margin + m->geom_rbound[g1]) {
|
&& planeGeomDist(m, d, g2, g1) > margin + m->geom_rbound[g1]) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -186,7 +186,7 @@ static int filterBodyPair(int weldbody1, int weldparent1, int weldbody2,
|
|||||||
|
|
||||||
// return 1 if bodyflex can collide, 0 otherwise
|
// return 1 if bodyflex can collide, 0 otherwise
|
||||||
static int canCollide(const mjModel* m, int bf) {
|
static int canCollide(const mjModel* m, int bf) {
|
||||||
if (bf<m->nbody) {
|
if (bf < m->nbody) {
|
||||||
return (m->body_contype[bf] || m->body_conaffinity[bf]);
|
return (m->body_contype[bf] || m->body_conaffinity[bf]);
|
||||||
} else {
|
} else {
|
||||||
int f = bf - m->nbody;
|
int f = bf - m->nbody;
|
||||||
@@ -199,10 +199,10 @@ static int canCollide(const mjModel* m, int bf) {
|
|||||||
// return 1 if two bodyflexes can collide, 0 otherwise
|
// return 1 if two bodyflexes can collide, 0 otherwise
|
||||||
static int canCollide2(const mjModel* m, int bf1, int bf2) {
|
static int canCollide2(const mjModel* m, int bf1, int bf2) {
|
||||||
int nbody = m->nbody;
|
int nbody = m->nbody;
|
||||||
int contype1 = (bf1<nbody) ? m->body_contype[bf1] : m->flex_contype[bf1-nbody];
|
int contype1 = (bf1 < nbody) ? m->body_contype[bf1] : m->flex_contype[bf1-nbody];
|
||||||
int conaffinity1 = (bf1<nbody) ? m->body_conaffinity[bf1] : m->flex_conaffinity[bf1-nbody];
|
int conaffinity1 = (bf1 < nbody) ? m->body_conaffinity[bf1] : m->flex_conaffinity[bf1-nbody];
|
||||||
int contype2 = (bf2<nbody) ? m->body_contype[bf2] : m->flex_contype[bf2-nbody];
|
int contype2 = (bf2 < nbody) ? m->body_contype[bf2] : m->flex_contype[bf2-nbody];
|
||||||
int conaffinity2 = (bf2<nbody) ? m->body_conaffinity[bf2] : m->flex_conaffinity[bf2-nbody];
|
int conaffinity2 = (bf2 < nbody) ? m->body_conaffinity[bf2] : m->flex_conaffinity[bf2-nbody];
|
||||||
|
|
||||||
// opposite of bitmask filter
|
// opposite of bitmask filter
|
||||||
return (!filterBitmask(contype1, conaffinity1, contype2, conaffinity2));
|
return (!filterBitmask(contype1, conaffinity1, contype2, conaffinity2));
|
||||||
@@ -212,7 +212,7 @@ static int canCollide2(const mjModel* m, int bf1, int bf2) {
|
|||||||
|
|
||||||
// return 1 if element is active, 0 otherwise
|
// return 1 if element is active, 0 otherwise
|
||||||
int mj_isElemActive(const mjModel* m, int f, int e) {
|
int mj_isElemActive(const mjModel* m, int f, int e) {
|
||||||
if (m->flex_dim[f]<3) {
|
if (m->flex_dim[f] < 3) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return (m->flex_elemlayer[m->flex_elemadr[f]+e] < m->flex_activelayers[f]);
|
return (m->flex_elemlayer[m->flex_elemadr[f]+e] < m->flex_activelayers[f]);
|
||||||
@@ -226,19 +226,19 @@ int mj_isElemActive(const mjModel* m, int f, int e) {
|
|||||||
// compare contact pairs by their geom/elem/vert IDs
|
// compare contact pairs by their geom/elem/vert IDs
|
||||||
quicksortfunc(contactcompare, context, el1, el2) {
|
quicksortfunc(contactcompare, context, el1, el2) {
|
||||||
const mjModel* m = (const mjModel*) context;
|
const mjModel* m = (const mjModel*) context;
|
||||||
mjContact* con1 = (mjContact*)el1;
|
mjContact* c1 = (mjContact*)el1;
|
||||||
mjContact* con2 = (mjContact*)el2;
|
mjContact* c2 = (mjContact*)el2;
|
||||||
|
|
||||||
// get colliding object ids
|
// get colliding object ids
|
||||||
int con1_obj1 = con1->geom[0]>=0 ? con1->geom[0] : (con1->elem[0]>=0 ? con1->elem[0] : con1->vert[0]);
|
int con1_obj1 = c1->geom[0] >= 0 ? c1->geom[0] : (c1->elem[0] >= 0 ? c1->elem[0] : c1->vert[0]);
|
||||||
int con1_obj2 = con1->geom[1]>=0 ? con1->geom[1] : (con1->elem[1]>=0 ? con1->elem[1] : con1->vert[1]);
|
int con1_obj2 = c1->geom[1] >= 0 ? c1->geom[1] : (c1->elem[1] >= 0 ? c1->elem[1] : c1->vert[1]);
|
||||||
int con2_obj1 = con2->geom[0]>=0 ? con2->geom[0] : (con2->elem[0]>=0 ? con2->elem[0] : con2->vert[0]);
|
int con2_obj1 = c2->geom[0] >= 0 ? c2->geom[0] : (c2->elem[0] >= 0 ? c2->elem[0] : c2->vert[0]);
|
||||||
int con2_obj2 = con2->geom[1]>=0 ? con2->geom[1] : (con2->elem[1]>=0 ? con2->elem[1] : con2->vert[1]);
|
int con2_obj2 = c2->geom[1] >= 0 ? c2->geom[1] : (c2->elem[1] >= 0 ? c2->elem[1] : c2->vert[1]);
|
||||||
|
|
||||||
// for geom:geom, reproduce the order of contacts without mj_collideTree
|
// for geom:geom, reproduce the order of contacts without mj_collideTree
|
||||||
// normally sorted by (g1, g2), but in mj_collideGeoms, g1 and g2 are swapped based on geom_type
|
// normally sorted by (g1, g2), but in mj_collideGeoms, g1 and g2 are swapped based on geom_type
|
||||||
// here we undo this swapping for the purpose of sorting - needs to be done for each mjContact
|
// here we undo this swapping for the purpose of sorting - needs to be done for each mjContact
|
||||||
if (con1->geom[0]>=0 && con1->geom[1] && con2->geom[0]>=0 && con2->geom[1]) {
|
if (c1->geom[0] >= 0 && c1->geom[1] && c2->geom[0] >= 0 && c2->geom[1]) {
|
||||||
if (m->geom_type[con1_obj1] > m->geom_type[con1_obj2]) {
|
if (m->geom_type[con1_obj1] > m->geom_type[con1_obj2]) {
|
||||||
int tmp = con1_obj1;
|
int tmp = con1_obj1;
|
||||||
con1_obj1 = con1_obj2;
|
con1_obj1 = con1_obj2;
|
||||||
@@ -298,7 +298,7 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// process bodyflex pairs returned by broadphase, merge with predefined geom pairs
|
// process bodyflex pairs returned by broadphase, merge with predefined geom pairs
|
||||||
int pairadr = 0;
|
int pairadr = 0;
|
||||||
for (int i=0; i<nbfpair; i++) {
|
for (int i=0; i < nbfpair; i++) {
|
||||||
// reconstruct bodyflex pair ids
|
// reconstruct bodyflex pair ids
|
||||||
int bf1 = (broadphasepair[i]>>16) & 0xFFFF;
|
int bf1 = (broadphasepair[i]>>16) & 0xFFFF;
|
||||||
int bf2 = broadphasepair[i] & 0xFFFF;
|
int bf2 = broadphasepair[i] & 0xFFFF;
|
||||||
@@ -317,8 +317,8 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
int startadr = pairadr;
|
int startadr = pairadr;
|
||||||
if (npair) {
|
if (npair) {
|
||||||
// test all predefined pairs for which pair_signature<=signature
|
// test all predefined pairs for which pair_signature<=signature
|
||||||
while (pairadr<npair && m->pair_signature[pairadr]<=signature) {
|
while (pairadr < npair && m->pair_signature[pairadr] <= signature) {
|
||||||
if (m->pair_signature[pairadr]==signature) {
|
if (m->pair_signature[pairadr] == signature) {
|
||||||
merged = 1;
|
merged = 1;
|
||||||
}
|
}
|
||||||
mj_collideGeoms(m, d, pairadr++, -1);
|
mj_collideGeoms(m, d, pairadr++, -1);
|
||||||
@@ -334,30 +334,31 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
int exadr = 0;
|
int exadr = 0;
|
||||||
if (nexclude) {
|
if (nexclude) {
|
||||||
// advance exadr while exclude_signature < signature
|
// advance exadr while exclude_signature < signature
|
||||||
while (exadr<nexclude && m->exclude_signature[exadr]<signature) {
|
while (exadr < nexclude && m->exclude_signature[exadr] < signature) {
|
||||||
exadr++;
|
exadr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip this bodyflex pair if its signature is found in exclude array
|
// skip this bodyflex pair if its signature is found in exclude array
|
||||||
if (exadr<nexclude && m->exclude_signature[exadr]==signature) {
|
if (exadr < nexclude && m->exclude_signature[exadr] == signature) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get bodyflex info
|
// get bodyflex info
|
||||||
int isbody1 = (bf1<nbody);
|
int isbody1 = (bf1 < nbody);
|
||||||
int isbody2 = (bf2<nbody);
|
int isbody2 = (bf2 < nbody);
|
||||||
int bvh1 = (isbody1 ? m->body_bvhadr[bf1] : m->flex_bvhadr[bf1-nbody]);
|
int bvh1 = (isbody1 ? m->body_bvhadr[bf1] : m->flex_bvhadr[bf1-nbody]);
|
||||||
int bvh2 = (isbody2 ? m->body_bvhadr[bf2] : m->flex_bvhadr[bf2-nbody]);
|
int bvh2 = (isbody2 ? m->body_bvhadr[bf2] : m->flex_bvhadr[bf2-nbody]);
|
||||||
|
int geomadr1 = (isbody1 ? m->body_geomadr[bf1] : -1);
|
||||||
|
int geomadr2 = (isbody2 ? m->body_geomadr[bf2] : -1);
|
||||||
|
|
||||||
// process bodyflex pair: two single-geom bodies
|
// process bodyflex pair: two single-geom bodies
|
||||||
if (isbody1 && isbody2 && m->body_geomnum[bf1]==1 && m->body_geomnum[bf2]==1) {
|
if (isbody1 && isbody2 && m->body_geomnum[bf1] == 1 && m->body_geomnum[bf2] == 1) {
|
||||||
mj_collideGeomPair(m, d, m->body_geomadr[bf1], m->body_geomadr[bf2],
|
mj_collideGeomPair(m, d, geomadr1, geomadr2, merged, startadr, pairadr);
|
||||||
merged, startadr, pairadr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// process bodyflex pair: midphase
|
// process bodyflex pair: midphase
|
||||||
else if (!mjDISABLED(mjDSBL_MIDPHASE) && bvh1>=0 && bvh2>=0) {
|
else if (!mjDISABLED(mjDSBL_MIDPHASE) && bvh1 >= 0 && bvh2 >= 0) {
|
||||||
int ncon_before = d->ncon;
|
int ncon_before = d->ncon;
|
||||||
mj_collideTree(m, d, bf1, bf2, merged, startadr, pairadr);
|
mj_collideTree(m, d, bf1, bf2, merged, startadr, pairadr);
|
||||||
int ncon_after = d->ncon;
|
int ncon_after = d->ncon;
|
||||||
@@ -369,13 +370,13 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// process bodyflex pair: all-to-all
|
// process bodyflex pair: all-to-all
|
||||||
else {
|
else {
|
||||||
int geomadr_end1 = m->body_geomadr[bf1] + m->body_geomnum[bf1];
|
int geomadr_end1 = geomadr1 + m->body_geomnum[bf1];
|
||||||
int geomadr_end2 = m->body_geomadr[bf2] + m->body_geomnum[bf2];
|
int geomadr_end2 = geomadr2 + m->body_geomnum[bf2];
|
||||||
|
|
||||||
// body : body
|
// body : body
|
||||||
if (isbody1 && isbody2) {
|
if (isbody1 && isbody2) {
|
||||||
for (int g1=m->body_geomadr[bf1]; g1<geomadr_end1; g1++) {
|
for (int g1=geomadr1; g1 < geomadr_end1; g1++) {
|
||||||
for (int g2=m->body_geomadr[bf2]; g2<geomadr_end2; g2++) {
|
for (int g2=geomadr2; g2 < geomadr_end2; g2++) {
|
||||||
mj_collideGeomPair(m, d, g1, g2, merged, startadr, pairadr);
|
mj_collideGeomPair(m, d, g1, g2, merged, startadr, pairadr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -386,7 +387,7 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
int f = bf2 - nbody;
|
int f = bf2 - nbody;
|
||||||
|
|
||||||
// process body geoms
|
// process body geoms
|
||||||
for (int g=m->body_geomadr[bf1]; g<geomadr_end1; g++) {
|
for (int g=m->body_geomadr[bf1]; g < geomadr_end1; g++) {
|
||||||
// bitmask filtering at the geom-flex level
|
// bitmask filtering at the geom-flex level
|
||||||
if (filterBitmask(m->geom_contype[g], m->geom_conaffinity[g],
|
if (filterBitmask(m->geom_contype[g], m->geom_conaffinity[g],
|
||||||
m->flex_contype[f], m->flex_conaffinity[f])) {
|
m->flex_contype[f], m->flex_conaffinity[f])) {
|
||||||
@@ -394,13 +395,14 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// plane special processing
|
// plane special processing
|
||||||
if (m->geom_type[g]==mjGEOM_PLANE) {
|
if (m->geom_type[g] == mjGEOM_PLANE) {
|
||||||
mj_collidePlaneFlex(m, d, g, f);
|
mj_collidePlaneFlex(m, d, g, f);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// collide geom with flex elements
|
// collide geom with flex elements
|
||||||
for (int e=0; e<m->flex_elemnum[f]; e++) {
|
int elemnum = m->flex_elemnum[f];
|
||||||
|
for (int e=0; e < elemnum; e++) {
|
||||||
mj_collideGeomElem(m, d, g, f, e);
|
mj_collideGeomElem(m, d, g, f, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -412,8 +414,8 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
int f2 = bf2 - nbody;
|
int f2 = bf2 - nbody;
|
||||||
|
|
||||||
// collide elements of two flexes
|
// collide elements of two flexes
|
||||||
for (int e1=0; e1<m->flex_elemnum[f1]; e1++) {
|
for (int e1=0; e1 < m->flex_elemnum[f1]; e1++) {
|
||||||
for (int e2=0; e2<m->flex_elemnum[f2]; e2++) {
|
for (int e2=0; e2 < m->flex_elemnum[f2]; e2++) {
|
||||||
mj_collideElems(m, d, f1, e1, f2, e2);
|
mj_collideElems(m, d, f1, e1, f2, e2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -423,13 +425,13 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// finish merging predefined geom pairs
|
// finish merging predefined geom pairs
|
||||||
if (npair) {
|
if (npair) {
|
||||||
while (pairadr<npair) {
|
while (pairadr < npair) {
|
||||||
mj_collideGeoms(m, d, pairadr++, -1);
|
mj_collideGeoms(m, d, pairadr++, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// flex self-collisions
|
// flex self-collisions
|
||||||
for (int f=0; f<m->nflex; f++) {
|
for (int f=0; f < m->nflex; f++) {
|
||||||
if (!m->flex_rigid[f] && (m->flex_contype[f] & m->flex_conaffinity[f])) {
|
if (!m->flex_rigid[f] && (m->flex_contype[f] & m->flex_conaffinity[f])) {
|
||||||
// internal collisions
|
// internal collisions
|
||||||
if (m->flex_internal[f]) {
|
if (m->flex_internal[f]) {
|
||||||
@@ -437,14 +439,14 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// active element collisions
|
// active element collisions
|
||||||
if (m->flex_selfcollide[f]!=mjFLEXSELF_NONE) {
|
if (m->flex_selfcollide[f] != mjFLEXSELF_NONE) {
|
||||||
// element-element: midphase
|
// element-element: midphase
|
||||||
if (!mjDISABLED(mjDSBL_MIDPHASE) &&
|
if (!mjDISABLED(mjDSBL_MIDPHASE) &&
|
||||||
m->flex_selfcollide[f]!=mjFLEXSELF_NARROW &&
|
m->flex_selfcollide[f] != mjFLEXSELF_NARROW &&
|
||||||
m->flex_bvhadr[f]>=0) {
|
m->flex_bvhadr[f] >= 0) {
|
||||||
// select midphase mode
|
// select midphase mode
|
||||||
if (m->flex_selfcollide[f]==mjFLEXSELF_BVH ||
|
if (m->flex_selfcollide[f] == mjFLEXSELF_BVH ||
|
||||||
(m->flex_selfcollide[f]==mjFLEXSELF_AUTO && m->flex_dim[f]==3)) {
|
(m->flex_selfcollide[f] == mjFLEXSELF_AUTO && m->flex_dim[f] == 3)) {
|
||||||
mj_collideTree(m, d, nbody+f, nbody+f, 0, 0, 0);
|
mj_collideTree(m, d, nbody+f, nbody+f, 0, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
mj_collideFlexSAP(m, d, f);
|
mj_collideFlexSAP(m, d, f);
|
||||||
@@ -454,9 +456,9 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
// element-element: direct
|
// element-element: direct
|
||||||
else {
|
else {
|
||||||
int flex_elemnum = m->flex_elemnum[f];
|
int flex_elemnum = m->flex_elemnum[f];
|
||||||
for (int e1=0; e1<flex_elemnum; e1++) {
|
for (int e1=0; e1 < flex_elemnum; e1++) {
|
||||||
if (mj_isElemActive(m, f, e1)) {
|
if (mj_isElemActive(m, f, e1)) {
|
||||||
for (int e2=e1+1; e2<flex_elemnum; e2++) {
|
for (int e2=e1+1; e2 < flex_elemnum; e2++) {
|
||||||
if (mj_isElemActive(m, f, e2)) {
|
if (mj_isElemActive(m, f, e2)) {
|
||||||
mj_collideElems(m, d, f, e1, f, e2);
|
mj_collideElems(m, d, f, e1, f, e2);
|
||||||
}
|
}
|
||||||
@@ -497,7 +499,7 @@ typedef struct mjCollisionTree_ mjCollisionTree;
|
|||||||
// collision tree allocation
|
// collision tree allocation
|
||||||
static mjCollisionTree* mj_stackAllocTree(mjData* d, int max_stack) {
|
static mjCollisionTree* mj_stackAllocTree(mjData* d, int max_stack) {
|
||||||
return (mjCollisionTree*) mj_stackAllocByte(
|
return (mjCollisionTree*) mj_stackAllocByte(
|
||||||
d, max_stack * sizeof(mjCollisionTree), _Alignof(mjCollisionTree));
|
d, max_stack * sizeof(mjCollisionTree), _Alignof(mjCollisionTree));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -576,7 +578,7 @@ int mj_collideOBB(const mjtNum aabb1[6], const mjtNum aabb2[6],
|
|||||||
if (xmat[i]) {
|
if (xmat[i]) {
|
||||||
normal[i][j][k] = xmat[i][3*k+j];
|
normal[i][j][k] = xmat[i][3*k+j];
|
||||||
} else {
|
} else {
|
||||||
normal[i][j][k] = (j==k);
|
normal[i][j][k] = (j == k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -669,9 +671,9 @@ void mj_collideTree(const mjModel* m, mjData* d, int bf1, int bf2,
|
|||||||
stack[0].node1 = stack[0].node2 = 0;
|
stack[0].node1 = stack[0].node2 = 0;
|
||||||
|
|
||||||
// for body:flex, if body has planes, call mj_collidePlaneFlex directly
|
// for body:flex, if body has planes, call mj_collidePlaneFlex directly
|
||||||
if (isbody1 && !isbody2 && m->body_weldid[bf1]==0) {
|
if (isbody1 && !isbody2 && m->body_weldid[bf1] == 0) {
|
||||||
for (int i=m->body_geomadr[bf1]; i<m->body_geomadr[bf1]+m->body_geomnum[bf1]; i++) {
|
for (int i=m->body_geomadr[bf1]; i < m->body_geomadr[bf1]+m->body_geomnum[bf1]; i++) {
|
||||||
if (m->geom_type[i]==mjGEOM_PLANE) {
|
if (m->geom_type[i] == mjGEOM_PLANE) {
|
||||||
mj_collidePlaneFlex(m, d, i, f2);
|
mj_collidePlaneFlex(m, d, i, f2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -683,18 +685,18 @@ void mj_collideTree(const mjModel* m, mjData* d, int bf1, int bf2,
|
|||||||
nstack--;
|
nstack--;
|
||||||
int node1 = stack[nstack].node1;
|
int node1 = stack[nstack].node1;
|
||||||
int node2 = stack[nstack].node2;
|
int node2 = stack[nstack].node2;
|
||||||
mjtByte isleaf1 = (child1[2*node1]<0) && (child1[2*node1+1]<0);
|
mjtByte isleaf1 = (child1[2*node1] < 0) && (child1[2*node1+1] < 0);
|
||||||
mjtByte isleaf2 = (child2[2*node2]<0) && (child2[2*node2+1]<0);
|
mjtByte isleaf2 = (child2[2*node2] < 0) && (child2[2*node2+1] < 0);
|
||||||
int nodeid1 = m->bvh_nodeid[bvhadr1 + node1];
|
int nodeid1 = m->bvh_nodeid[bvhadr1 + node1];
|
||||||
int nodeid2 = m->bvh_nodeid[bvhadr2 + node2];
|
int nodeid2 = m->bvh_nodeid[bvhadr2 + node2];
|
||||||
|
|
||||||
// SHOULD NOT OCCUR
|
// SHOULD NOT OCCUR
|
||||||
if ((isleaf1 && nodeid1<0) || (isleaf2 && nodeid2<0)) {
|
if ((isleaf1 && nodeid1 < 0) || (isleaf2 && nodeid2 < 0)) {
|
||||||
mju_error("BVH leaf has invalid node id");
|
mju_error("BVH leaf has invalid node id");
|
||||||
}
|
}
|
||||||
|
|
||||||
// self-collision: avoid repeated pairs
|
// self-collision: avoid repeated pairs
|
||||||
if (bf1==bf2 && node1>node2) {
|
if (bf1 == bf2 && node1 > node2) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -702,8 +704,8 @@ void mj_collideTree(const mjModel* m, mjData* d, int bf1, int bf2,
|
|||||||
if (isbody1 && isbody2) {
|
if (isbody1 && isbody2) {
|
||||||
// both are leaves
|
// both are leaves
|
||||||
if (isleaf1 && isleaf2) {
|
if (isleaf1 && isleaf2) {
|
||||||
mjtNum margin = mj_assignMargin(m,
|
mjtNum maxmargin = mju_max(m->geom_margin[nodeid1], m->geom_margin[nodeid2]);
|
||||||
mju_max(m->geom_margin[nodeid1], m->geom_margin[nodeid2]));
|
mjtNum margin = mj_assignMargin(m, maxmargin);
|
||||||
|
|
||||||
if (!mj_filterSphere(m, d, nodeid1, nodeid2, margin)) {
|
if (!mj_filterSphere(m, d, nodeid1, nodeid2, margin)) {
|
||||||
if (mj_collideOBB(m->geom_aabb + 6*nodeid1, m->geom_aabb + 6*nodeid2,
|
if (mj_collideOBB(m->geom_aabb + 6*nodeid1, m->geom_aabb + 6*nodeid2,
|
||||||
@@ -719,8 +721,8 @@ void mj_collideTree(const mjModel* m, mjData* d, int bf1, int bf2,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if no intersection at intermediate levels, stop
|
// if no intersection at intermediate levels, stop
|
||||||
mjtNum margin = mj_assignMargin(m,
|
mjtNum maxmargin = mju_max(m->body_margin[bf1], m->body_margin[bf2]);
|
||||||
mju_max(m->body_margin[bf1], m->body_margin[bf2]));
|
mjtNum margin = mj_assignMargin(m, maxmargin);
|
||||||
if (!mj_collideOBB(bvh1 + 6*node1, bvh2 + 6*node2,
|
if (!mj_collideOBB(bvh1 + 6*node1, bvh2 + 6*node2,
|
||||||
d->xipos + 3*bf1, d->ximat + 9*bf1,
|
d->xipos + 3*bf1, d->ximat + 9*bf1,
|
||||||
d->xipos + 3*bf2, d->ximat + 9*bf2,
|
d->xipos + 3*bf2, d->ximat + 9*bf2,
|
||||||
@@ -733,8 +735,8 @@ void mj_collideTree(const mjModel* m, mjData* d, int bf1, int bf2,
|
|||||||
else if (isbody1 && !isbody2) {
|
else if (isbody1 && !isbody2) {
|
||||||
// both are leaves
|
// both are leaves
|
||||||
if (isleaf1 && isleaf2) {
|
if (isleaf1 && isleaf2) {
|
||||||
mjtNum margin = mj_assignMargin(m,
|
mjtNum maxmargin = mju_max(m->geom_margin[nodeid1], m->flex_margin[f2]);
|
||||||
mju_max(m->geom_margin[nodeid1], m->flex_margin[f2]));
|
mjtNum margin = mj_assignMargin(m, maxmargin);
|
||||||
|
|
||||||
if (!filterBitmask(m->geom_contype[nodeid1], m->geom_conaffinity[nodeid1],
|
if (!filterBitmask(m->geom_contype[nodeid1], m->geom_conaffinity[nodeid1],
|
||||||
m->flex_contype[f2], m->flex_conaffinity[f2]) &&
|
m->flex_contype[f2], m->flex_conaffinity[f2]) &&
|
||||||
@@ -745,7 +747,7 @@ void mj_collideTree(const mjModel* m, mjData* d, int bf1, int bf2,
|
|||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
margin, NULL, NULL, &initialize)) {
|
margin, NULL, NULL, &initialize)) {
|
||||||
// collide unless geom is plane (plane:flex handled separately)
|
// collide unless geom is plane (plane:flex handled separately)
|
||||||
if (m->geom_type[nodeid1]!=mjGEOM_PLANE) {
|
if (m->geom_type[nodeid1] != mjGEOM_PLANE) {
|
||||||
mj_collideGeomElem(m, d, nodeid1, f2, nodeid2);
|
mj_collideGeomElem(m, d, nodeid1, f2, nodeid2);
|
||||||
}
|
}
|
||||||
d->bvh_active[node1 + bvhadr1] = 1;
|
d->bvh_active[node1 + bvhadr1] = 1;
|
||||||
@@ -756,12 +758,12 @@ void mj_collideTree(const mjModel* m, mjData* d, int bf1, int bf2,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if no intersection at intermediate levels, stop
|
// if no intersection at intermediate levels, stop
|
||||||
mjtNum margin = mj_assignMargin(m,
|
mjtNum maxmargin = mju_max(m->body_margin[bf1], m->flex_margin[f2]);
|
||||||
mju_max(m->body_margin[bf1], m->flex_margin[f2]));
|
mjtNum margin = mj_assignMargin(m, maxmargin);
|
||||||
if (!mj_collideOBB(bvh1 + 6*node1, bvh2 + 6*node2,
|
if (!mj_collideOBB(bvh1 + 6*node1, bvh2 + 6*node2,
|
||||||
d->xipos + 3*bf1, d->ximat + 9*bf1,
|
d->xipos + 3*bf1, d->ximat + 9*bf1,
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
margin, product, offset, &initialize)) {
|
margin, product, offset, &initialize)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -783,8 +785,8 @@ void mj_collideTree(const mjModel* m, mjData* d, int bf1, int bf2,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if no intersection at intermediate levels, stop
|
// if no intersection at intermediate levels, stop
|
||||||
mjtNum margin = mj_assignMargin(m,
|
mjtNum maxmargin = mju_max(m->flex_margin[f1], m->flex_margin[f2]);
|
||||||
mju_max(m->flex_margin[f1], m->flex_margin[f2]));
|
mjtNum margin = mj_assignMargin(m, maxmargin);
|
||||||
if (filterBox(bvh1 + 6*node1, bvh2 + 6*node2, margin)) {
|
if (filterBox(bvh1 + 6*node1, bvh2 + 6*node2, margin)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -863,28 +865,28 @@ void mj_collideTree(const mjModel* m, mjData* d, int bf1, int bf2,
|
|||||||
// make AAMM (xmin[3], xmax[3]) for one bodyflex
|
// make AAMM (xmin[3], xmax[3]) for one bodyflex
|
||||||
static void makeAAMM(const mjModel* m, mjData* d, mjtNum* aamm, int bf, const mjtNum* frame) {
|
static void makeAAMM(const mjModel* m, mjData* d, mjtNum* aamm, int bf, const mjtNum* frame) {
|
||||||
// body
|
// body
|
||||||
if (bf<m->nbody) {
|
if (bf < m->nbody) {
|
||||||
int body = bf;
|
int body = bf;
|
||||||
int body_geomnum = m->body_geomnum[body];
|
int body_geomnum = m->body_geomnum[body];
|
||||||
|
|
||||||
// process all body geoms (body is collidable, should have geoms)
|
// process all body geoms (body is collidable, should have geoms)
|
||||||
for (int i=0; i<body_geomnum; i++) {
|
for (int i=0; i < body_geomnum; i++) {
|
||||||
int geom = m->body_geomadr[body]+i;
|
int geom = m->body_geomadr[body]+i;
|
||||||
mjtNum margin = mjENABLED(mjENBL_OVERRIDE) ? 0.5*m->opt.o_margin : m->geom_margin[geom];
|
mjtNum margin = mjENABLED(mjENBL_OVERRIDE) ? 0.5*m->opt.o_margin : m->geom_margin[geom];
|
||||||
mjtNum _aamm[6];
|
mjtNum _aamm[6];
|
||||||
|
|
||||||
// set _aamm for this geom
|
// set _aamm for this geom
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
mjtNum cen = mju_dot3(d->geom_xpos+3*geom, frame+3*j);
|
mjtNum cen = mju_dot3(d->geom_xpos+3*geom, frame+3*j);
|
||||||
_aamm[j] = cen - m->geom_rbound[geom] - margin;
|
_aamm[j] = cen - m->geom_rbound[geom] - margin;
|
||||||
_aamm[j+3] = cen + m->geom_rbound[geom] + margin;
|
_aamm[j+3] = cen + m->geom_rbound[geom] + margin;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update body aamm
|
// update body aamm
|
||||||
if (i==0) {
|
if (i == 0) {
|
||||||
mju_copy(aamm, _aamm, 6);
|
mju_copy(aamm, _aamm, 6);
|
||||||
} else {
|
} else {
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
aamm[j] = mju_min(aamm[j], _aamm[j]);
|
aamm[j] = mju_min(aamm[j], _aamm[j]);
|
||||||
aamm[j+3] = mju_max(aamm[j+3], _aamm[j+3]);
|
aamm[j+3] = mju_max(aamm[j+3], _aamm[j+3]);
|
||||||
}
|
}
|
||||||
@@ -906,11 +908,11 @@ static void makeAAMM(const mjModel* m, mjData* d, mjtNum* aamm, int bf, const mj
|
|||||||
mju_mulMatVec(v, frame, vbase+3*i, 3, 3);
|
mju_mulMatVec(v, frame, vbase+3*i, 3, 3);
|
||||||
|
|
||||||
// update aamm
|
// update aamm
|
||||||
if (i==0) {
|
if (i == 0) {
|
||||||
mju_copy3(aamm, v);
|
mju_copy3(aamm, v);
|
||||||
mju_copy3(aamm+3, v);
|
mju_copy3(aamm+3, v);
|
||||||
} else {
|
} else {
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
aamm[j] = mju_min(aamm[j], v[j]);
|
aamm[j] = mju_min(aamm[j], v[j]);
|
||||||
aamm[j+3] = mju_max(aamm[j+3], v[j]);
|
aamm[j+3] = mju_max(aamm[j+3], v[j]);
|
||||||
}
|
}
|
||||||
@@ -946,7 +948,7 @@ static void add_pair(const mjModel* m, int bf1, int bf2,
|
|||||||
int body_geomadr1 = m->body_geomadr[bf1];
|
int body_geomadr1 = m->body_geomadr[bf1];
|
||||||
int body_geomnum1 = m->body_geomnum[bf1];
|
int body_geomnum1 = m->body_geomnum[bf1];
|
||||||
contype1 = conaffinity1 = 0;
|
contype1 = conaffinity1 = 0;
|
||||||
for (int i=body_geomadr1; i<body_geomadr1+body_geomnum1; i++) {
|
for (int i=body_geomadr1; i < body_geomadr1+body_geomnum1; i++) {
|
||||||
contype1 |= m->geom_contype[i];
|
contype1 |= m->geom_contype[i];
|
||||||
conaffinity1 |= m->geom_conaffinity[i];
|
conaffinity1 |= m->geom_conaffinity[i];
|
||||||
}
|
}
|
||||||
@@ -960,7 +962,7 @@ static void add_pair(const mjModel* m, int bf1, int bf2,
|
|||||||
int body_geomadr2 = m->body_geomadr[bf2];
|
int body_geomadr2 = m->body_geomadr[bf2];
|
||||||
int body_geomnum2 = m->body_geomnum[bf2];
|
int body_geomnum2 = m->body_geomnum[bf2];
|
||||||
contype2 = conaffinity2 = 0;
|
contype2 = conaffinity2 = 0;
|
||||||
for (int i=body_geomadr2; i<body_geomadr2+body_geomnum2; i++) {
|
for (int i=body_geomadr2; i < body_geomadr2+body_geomnum2; i++) {
|
||||||
contype2 |= m->geom_contype[i];
|
contype2 |= m->geom_contype[i];
|
||||||
conaffinity2 |= m->geom_conaffinity[i];
|
conaffinity2 |= m->geom_conaffinity[i];
|
||||||
}
|
}
|
||||||
@@ -1021,7 +1023,7 @@ quicksortfunc(SAPcompare, context, el1, el2) {
|
|||||||
// using sweep-and-prune along specified axis (0-2).
|
// using sweep-and-prune along specified axis (0-2).
|
||||||
static int mj_SAP(mjData* d, const mjtNum* aamm, int n, int axis, int* pair, int maxpair) {
|
static int mj_SAP(mjData* d, const mjtNum* aamm, int n, int axis, int* pair, int maxpair) {
|
||||||
// check inputs
|
// check inputs
|
||||||
if (n>=0x10000 || axis<0 || axis>2 || maxpair<1) {
|
if (n >= 0x10000 || axis < 0 || axis > 2 || maxpair < 1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1030,7 +1032,7 @@ static int mj_SAP(mjData* d, const mjtNum* aamm, int n, int axis, int* pair, int
|
|||||||
mjtSAP* activebuf = (mjtSAP*) mj_stackAllocByte(d, 2*n*sizeof(mjtSAP), _Alignof(mjtSAP));
|
mjtSAP* activebuf = (mjtSAP*) mj_stackAllocByte(d, 2*n*sizeof(mjtSAP), _Alignof(mjtSAP));
|
||||||
|
|
||||||
// init sortbuf with specified axis
|
// init sortbuf with specified axis
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
sortbuf[2*i].id_ismax = i;
|
sortbuf[2*i].id_ismax = i;
|
||||||
sortbuf[2*i].value = (float)aamm[6*i+axis];
|
sortbuf[2*i].value = (float)aamm[6*i+axis];
|
||||||
sortbuf[2*i+1].id_ismax = i + 0x10000;
|
sortbuf[2*i+1].id_ismax = i + 0x10000;
|
||||||
@@ -1042,10 +1044,10 @@ static int mj_SAP(mjData* d, const mjtNum* aamm, int n, int axis, int* pair, int
|
|||||||
|
|
||||||
// define the other two axes
|
// define the other two axes
|
||||||
int axisA, axisB;
|
int axisA, axisB;
|
||||||
if (axis==0) {
|
if (axis == 0) {
|
||||||
axisA = 1;
|
axisA = 1;
|
||||||
axisB = 2;
|
axisB = 2;
|
||||||
} else if (axis==1) {
|
} else if (axis == 1) {
|
||||||
axisA = 0;
|
axisA = 0;
|
||||||
axisB = 2;
|
axisB = 2;
|
||||||
} else {
|
} else {
|
||||||
@@ -1056,10 +1058,10 @@ static int mj_SAP(mjData* d, const mjtNum* aamm, int n, int axis, int* pair, int
|
|||||||
// sweep and prune
|
// sweep and prune
|
||||||
int cnt = 0; // size of active list
|
int cnt = 0; // size of active list
|
||||||
int npair = 0; // number of pairs added
|
int npair = 0; // number of pairs added
|
||||||
for (int i=0; i<2*n; i++) {
|
for (int i=0; i < 2*n; i++) {
|
||||||
// min value: collide with all in list, add
|
// min value: collide with all in list, add
|
||||||
if (!(sortbuf[i].id_ismax & 0x10000)) {
|
if (!(sortbuf[i].id_ismax & 0x10000)) {
|
||||||
for (int j=0; j<cnt; j++) {
|
for (int j=0; j < cnt; j++) {
|
||||||
// get ids: no need to mask ismax because activebuf entries never have the ismax bit,
|
// get ids: no need to mask ismax because activebuf entries never have the ismax bit,
|
||||||
// and sortbuf[i].id_ismax is tested above
|
// and sortbuf[i].id_ismax is tested above
|
||||||
int id1 = activebuf[j].id_ismax;
|
int id1 = activebuf[j].id_ismax;
|
||||||
@@ -1075,7 +1077,7 @@ static int mj_SAP(mjData* d, const mjtNum* aamm, int n, int axis, int* pair, int
|
|||||||
|
|
||||||
// add pair, check buffer size
|
// add pair, check buffer size
|
||||||
pair[npair++] = (id1<<16) + id2;
|
pair[npair++] = (id1<<16) + id2;
|
||||||
if (npair>=maxpair) {
|
if (npair >= maxpair) {
|
||||||
return maxpair;
|
return maxpair;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1088,9 +1090,9 @@ static int mj_SAP(mjData* d, const mjtNum* aamm, int n, int axis, int* pair, int
|
|||||||
// max value: remove corresponding min value from list
|
// max value: remove corresponding min value from list
|
||||||
else {
|
else {
|
||||||
int toremove = sortbuf[i].id_ismax & 0xFFFF;
|
int toremove = sortbuf[i].id_ismax & 0xFFFF;
|
||||||
for (int j=0; j<cnt; j++) {
|
for (int j=0; j < cnt; j++) {
|
||||||
if (activebuf[j].id_ismax==toremove) {
|
if (activebuf[j].id_ismax == toremove) {
|
||||||
if (j<cnt-1) {
|
if (j < cnt-1) {
|
||||||
memmove(activebuf+j, activebuf+j+1, sizeof(mjtSAP)*(cnt-1-j));
|
memmove(activebuf+j, activebuf+j+1, sizeof(mjtSAP)*(cnt-1-j));
|
||||||
}
|
}
|
||||||
cnt--;
|
cnt--;
|
||||||
@@ -1159,9 +1161,9 @@ int mj_broadphase(const mjModel* m, mjData* d, int* bfpair, int maxpair) {
|
|||||||
|
|
||||||
// b1 is world body with geoms, or world-welded body with plane
|
// b1 is world body with geoms, or world-welded body with plane
|
||||||
if ((b1 == 0 && m->body_geomnum[b1] > 0) ||
|
if ((b1 == 0 && m->body_geomnum[b1] > 0) ||
|
||||||
(m->body_weldid[b1]==0 && hasPlane(m, b1))) {
|
(m->body_weldid[b1] == 0 && hasPlane(m, b1))) {
|
||||||
// add b1:body pairs that are not welded together
|
// add b1:body pairs that are not welded together
|
||||||
for (int b2=0; b2<nbody; b2++) {
|
for (int b2=0; b2 < nbody; b2++) {
|
||||||
// cannot colide
|
// cannot colide
|
||||||
if (!canCollide(m, b2)) {
|
if (!canCollide(m, b2)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -1179,7 +1181,7 @@ int mj_broadphase(const mjModel* m, mjData* d, int* bfpair, int maxpair) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add all b1:flex pairs
|
// add all b1:flex pairs
|
||||||
for (int f=0; f<nflex; f++) {
|
for (int f=0; f < nflex; f++) {
|
||||||
add_pair(m, b1, nbody+f, &npair, bfpair, maxpair);
|
add_pair(m, b1, nbody+f, &npair, bfpair, maxpair);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1200,7 +1202,7 @@ int mj_broadphase(const mjModel* m, mjData* d, int* bfpair, int maxpair) {
|
|||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cnt==0) {
|
if (cnt == 0) {
|
||||||
return npair;
|
return npair;
|
||||||
}
|
}
|
||||||
mju_scl3(cen, cen, 1.0/cnt);
|
mju_scl3(cen, cen, 1.0/cnt);
|
||||||
@@ -1226,20 +1228,20 @@ int mj_broadphase(const mjModel* m, mjData* d, int* bfpair, int maxpair) {
|
|||||||
mj_markStack(d);
|
mj_markStack(d);
|
||||||
int* bfid = mj_stackAllocInt(d, nbodyflex);
|
int* bfid = mj_stackAllocInt(d, nbodyflex);
|
||||||
int ncollide = 0;
|
int ncollide = 0;
|
||||||
for (int i=1; i<nbodyflex; i++) {
|
for (int i=1; i < nbodyflex; i++) {
|
||||||
if (canCollide(m, i)) {
|
if (canCollide(m, i)) {
|
||||||
bfid[ncollide++] = i;
|
bfid[ncollide++] = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// nothing collidable
|
// nothing collidable
|
||||||
if (ncollide<2) {
|
if (ncollide < 2) {
|
||||||
goto endbroad;
|
goto endbroad;
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate and construct AAMMs for collidable only
|
// allocate and construct AAMMs for collidable only
|
||||||
mjtNum* aamm = mj_stackAllocNum(d, 6*ncollide);
|
mjtNum* aamm = mj_stackAllocNum(d, 6*ncollide);
|
||||||
for (int i=0; i<ncollide; i++) {
|
for (int i=0; i < ncollide; i++) {
|
||||||
makeAAMM(m, d, aamm+6*i, bfid[i], frame);
|
makeAAMM(m, d, aamm+6*i, bfid[i], frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1247,17 +1249,17 @@ int mj_broadphase(const mjModel* m, mjData* d, int* bfpair, int maxpair) {
|
|||||||
int maxsappair = ncollide*(ncollide-1)/2;
|
int maxsappair = ncollide*(ncollide-1)/2;
|
||||||
int* sappair = mj_stackAllocInt(d, maxsappair);
|
int* sappair = mj_stackAllocInt(d, maxsappair);
|
||||||
int nsappair = mj_SAP(d, aamm, ncollide, 0, sappair, maxsappair);
|
int nsappair = mj_SAP(d, aamm, ncollide, 0, sappair, maxsappair);
|
||||||
if (nsappair<0) {
|
if (nsappair < 0) {
|
||||||
mjERROR("SAP failed");
|
mjERROR("SAP failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter SAP pairs, convert to bodyflex pairs
|
// filter SAP pairs, convert to bodyflex pairs
|
||||||
for (int i=0; i<nsappair; i++) {
|
for (int i=0; i < nsappair; i++) {
|
||||||
int bf1 = bfid[sappair[i] >> 16];
|
int bf1 = bfid[sappair[i] >> 16];
|
||||||
int bf2 = bfid[sappair[i] & 0xFFFF];
|
int bf2 = bfid[sappair[i] & 0xFFFF];
|
||||||
|
|
||||||
// body pair: prune based on weld filter
|
// body pair: prune based on weld filter
|
||||||
if (bf1<nbody && bf2<nbody) {
|
if (bf1 < nbody && bf2 < nbody) {
|
||||||
int weld1 = m->body_weldid[bf1];
|
int weld1 = m->body_weldid[bf1];
|
||||||
int weld2 = m->body_weldid[bf2];
|
int weld2 = m->body_weldid[bf2];
|
||||||
int parent_weld1 = m->body_weldid[m->body_parentid[weld1]];
|
int parent_weld1 = m->body_weldid[m->body_parentid[weld1]];
|
||||||
@@ -1295,34 +1297,34 @@ static void mj_contactParam(const mjModel* m, int* condim, mjtNum* gap,
|
|||||||
mjtNum fri[3];
|
mjtNum fri[3];
|
||||||
|
|
||||||
// get parameters from geom1 or flex1
|
// get parameters from geom1 or flex1
|
||||||
int priority1 = (f1<0) ? m->geom_priority[g1] : m->flex_priority[f1];
|
int priority1 = (f1 < 0) ? m->geom_priority[g1] : m->flex_priority[f1];
|
||||||
int condim1 = (f1<0) ? m->geom_condim[g1] : m->flex_condim[f1];
|
int condim1 = (f1 < 0) ? m->geom_condim[g1] : m->flex_condim[f1];
|
||||||
mjtNum gap1 = (f1<0) ? m->geom_gap[g1] : m->flex_gap[f1];
|
mjtNum gap1 = (f1 < 0) ? m->geom_gap[g1] : m->flex_gap[f1];
|
||||||
mjtNum solmix1 = (f1<0) ? m->geom_solmix[g1] : m->flex_solmix[f1];
|
mjtNum solmix1 = (f1 < 0) ? m->geom_solmix[g1] : m->flex_solmix[f1];
|
||||||
const mjtNum* solref1 = (f1<0) ? m->geom_solref+g1*mjNREF : m->flex_solref+f1*mjNREF;
|
const mjtNum* solref1 = (f1 < 0) ? m->geom_solref+g1*mjNREF : m->flex_solref+f1*mjNREF;
|
||||||
const mjtNum* solimp1 = (f1<0) ? m->geom_solimp+g1*mjNIMP : m->flex_solimp+f1*mjNIMP;
|
const mjtNum* solimp1 = (f1 < 0) ? m->geom_solimp+g1*mjNIMP : m->flex_solimp+f1*mjNIMP;
|
||||||
const mjtNum* friction1 = (f1<0) ? m->geom_friction+g1*3 : m->flex_friction+f1*3;
|
const mjtNum* friction1 = (f1 < 0) ? m->geom_friction+g1*3 : m->flex_friction+f1*3;
|
||||||
|
|
||||||
// get parameters from geom2 or flex2
|
// get parameters from geom2 or flex2
|
||||||
int priority2 = (f2<0) ? m->geom_priority[g2] : m->flex_priority[f2];
|
int priority2 = (f2 < 0) ? m->geom_priority[g2] : m->flex_priority[f2];
|
||||||
int condim2 = (f2<0) ? m->geom_condim[g2] : m->flex_condim[f2];
|
int condim2 = (f2 < 0) ? m->geom_condim[g2] : m->flex_condim[f2];
|
||||||
mjtNum gap2 = (f2<0) ? m->geom_gap[g2] : m->flex_gap[f2];
|
mjtNum gap2 = (f2 < 0) ? m->geom_gap[g2] : m->flex_gap[f2];
|
||||||
mjtNum solmix2 = (f2<0) ? m->geom_solmix[g2] : m->flex_solmix[f2];
|
mjtNum solmix2 = (f2 < 0) ? m->geom_solmix[g2] : m->flex_solmix[f2];
|
||||||
const mjtNum* solref2 = (f2<0) ? m->geom_solref+g2*mjNREF : m->flex_solref+f2*mjNREF;
|
const mjtNum* solref2 = (f2 < 0) ? m->geom_solref+g2*mjNREF : m->flex_solref+f2*mjNREF;
|
||||||
const mjtNum* solimp2 = (f2<0) ? m->geom_solimp+g2*mjNIMP : m->flex_solimp+f2*mjNIMP;
|
const mjtNum* solimp2 = (f2 < 0) ? m->geom_solimp+g2*mjNIMP : m->flex_solimp+f2*mjNIMP;
|
||||||
const mjtNum* friction2 = (f2<0) ? m->geom_friction+g2*3 : m->flex_friction+f2*3;
|
const mjtNum* friction2 = (f2 < 0) ? m->geom_friction+g2*3 : m->flex_friction+f2*3;
|
||||||
|
|
||||||
// gap: max
|
// gap: max
|
||||||
*gap = mju_max(gap1, gap2);
|
*gap = mju_max(gap1, gap2);
|
||||||
|
|
||||||
// different priority: copy from item with higher priority
|
// different priority: copy from item with higher priority
|
||||||
if (priority1>priority2) {
|
if (priority1 > priority2) {
|
||||||
*condim = condim1;
|
*condim = condim1;
|
||||||
mju_copy(solref, solref1, mjNREF);
|
mju_copy(solref, solref1, mjNREF);
|
||||||
mju_copy(solimp, solimp1, mjNIMP);
|
mju_copy(solimp, solimp1, mjNIMP);
|
||||||
mju_copy(fri, friction1, 3);
|
mju_copy(fri, friction1, 3);
|
||||||
}
|
}
|
||||||
else if (priority1<priority2) {
|
else if (priority1 < priority2) {
|
||||||
*condim = condim2;
|
*condim = condim2;
|
||||||
mju_copy(solref, solref2, mjNREF);
|
mju_copy(solref, solref2, mjNREF);
|
||||||
mju_copy(solimp, solimp2, mjNIMP);
|
mju_copy(solimp, solimp2, mjNIMP);
|
||||||
@@ -1336,37 +1338,37 @@ static void mj_contactParam(const mjModel* m, int* condim, mjtNum* gap,
|
|||||||
|
|
||||||
// compute solver mix factor
|
// compute solver mix factor
|
||||||
mjtNum mix;
|
mjtNum mix;
|
||||||
if (solmix1>=mjMINVAL && solmix2>=mjMINVAL) {
|
if (solmix1 >= mjMINVAL && solmix2 >= mjMINVAL) {
|
||||||
mix = solmix1 / (solmix1 + solmix2);
|
mix = solmix1 / (solmix1 + solmix2);
|
||||||
} else if (solmix1<mjMINVAL && solmix2<mjMINVAL) {
|
} else if (solmix1 < mjMINVAL && solmix2 < mjMINVAL) {
|
||||||
mix = 0.5;
|
mix = 0.5;
|
||||||
} else if (solmix1<mjMINVAL) {
|
} else if (solmix1 < mjMINVAL) {
|
||||||
mix = 0.0;
|
mix = 0.0;
|
||||||
} else {
|
} else {
|
||||||
mix = 1.0;
|
mix = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reference standard: mix
|
// reference standard: mix
|
||||||
if (solref1[0]>0 && solref2[0]>0) {
|
if (solref1[0] > 0 && solref2[0] > 0) {
|
||||||
for (int i=0; i<mjNREF; i++) {
|
for (int i=0; i < mjNREF; i++) {
|
||||||
solref[i] = mix*solref1[i] + (1-mix)*solref2[i];
|
solref[i] = mix*solref1[i] + (1-mix)*solref2[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// reference direct: min
|
// reference direct: min
|
||||||
else {
|
else {
|
||||||
for (int i=0; i<mjNREF; i++) {
|
for (int i=0; i < mjNREF; i++) {
|
||||||
solref[i] = mju_min(solref1[i], solref2[i]);
|
solref[i] = mju_min(solref1[i], solref2[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// impedance: mix
|
// impedance: mix
|
||||||
for (int i=0; i<mjNIMP; i++) {
|
for (int i=0; i < mjNIMP; i++) {
|
||||||
solimp[i] = mix*solimp1[i] + (1-mix)*solimp2[i];
|
solimp[i] = mix*solimp1[i] + (1-mix)*solimp2[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// friction: max
|
// friction: max
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
fri[i] = mju_max(friction1[i], friction2[i]);
|
fri[i] = mju_max(friction1[i], friction2[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1379,7 +1381,7 @@ static void mj_contactParam(const mjModel* m, int* condim, mjtNum* gap,
|
|||||||
friction[4] = fri[2];
|
friction[4] = fri[2];
|
||||||
|
|
||||||
// SHOULD NOT OCCUR
|
// SHOULD NOT OCCUR
|
||||||
if (*condim>6 || *condim<1) {
|
if (*condim > 6 || *condim < 1) {
|
||||||
mjERROR("Invalid condim value: %d", *condim);
|
mjERROR("Invalid condim value: %d", *condim);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1501,7 +1503,7 @@ void mj_collideGeoms(const mjModel* m, mjData* d, int g1, int g2) {
|
|||||||
|
|
||||||
// allocate mjContact[mjMAXCONPAIR] on the arena
|
// allocate mjContact[mjMAXCONPAIR] on the arena
|
||||||
mjContact* con =
|
mjContact* con =
|
||||||
(mjContact*) mj_arenaAllocByte(d, sizeof(mjContact) * mjMAXCONPAIR, _Alignof(mjContact));
|
(mjContact*) mj_arenaAllocByte(d, sizeof(mjContact) * mjMAXCONPAIR, _Alignof(mjContact));
|
||||||
if (!con) {
|
if (!con) {
|
||||||
mj_warning(d, mjWARN_CONTACTFULL, d->ncon);
|
mj_warning(d, mjWARN_CONTACTFULL, d->ncon);
|
||||||
return;
|
return;
|
||||||
@@ -1578,7 +1580,7 @@ void mj_collideGeoms(const mjModel* m, mjData* d, int g1, int g2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add contacts returned by collision detector
|
// add contacts returned by collision detector
|
||||||
for (int i=0; i<num; i++) {
|
for (int i=0; i < num; i++) {
|
||||||
// set contact ids
|
// set contact ids
|
||||||
con[i].geom[0] = g1;
|
con[i].geom[0] = g1;
|
||||||
con[i].geom[1] = g2;
|
con[i].geom[1] = g2;
|
||||||
@@ -1622,7 +1624,7 @@ void mj_collidePlaneFlex(const mjModel* m, mjData* d, int g, int f) {
|
|||||||
mj_contactParam(m, &condim, &gap, solref, solimp, friction, g, -1, -1, f);
|
mj_contactParam(m, &condim, &gap, solref, solimp, friction, g, -1, -1, f);
|
||||||
|
|
||||||
// collide all flex vertices with plane
|
// collide all flex vertices with plane
|
||||||
for (int i=0; i<flex_vertnum; i++) {
|
for (int i=0; i < flex_vertnum; i++) {
|
||||||
mjtNum* v = d->flexvert_xpos + 3*(m->flex_vertadr[f]+i);
|
mjtNum* v = d->flexvert_xpos + 3*(m->flex_vertadr[f]+i);
|
||||||
|
|
||||||
// distance from plane to vertex
|
// distance from plane to vertex
|
||||||
@@ -1678,7 +1680,7 @@ static int planeVertex(mjContact* con, const mjtNum* pos, mjtNum rad,
|
|||||||
|
|
||||||
// project, check distance
|
// project, check distance
|
||||||
mjtNum dst = mju_dot3(ev, nrm);
|
mjtNum dst = mju_dot3(ev, nrm);
|
||||||
if (dst<=-2*rad) {
|
if (dst <= -2*rad) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1698,13 +1700,13 @@ void mj_collideFlexInternal(const mjModel* m, mjData* d, int f) {
|
|||||||
int flex_evpairnum = m->flex_evpairnum[f];
|
int flex_evpairnum = m->flex_evpairnum[f];
|
||||||
|
|
||||||
// predefined element-vertex
|
// predefined element-vertex
|
||||||
for (int i=0; i<flex_evpairnum; i++) {
|
for (int i=0; i < flex_evpairnum; i++) {
|
||||||
const int* ev = m->flex_evpair + 2*m->flex_evpairadr[f] + 2*i;
|
const int* ev = m->flex_evpair + 2*m->flex_evpairadr[f] + 2*i;
|
||||||
mj_collideElemVert(m, d, f, ev[0], ev[1]);
|
mj_collideElemVert(m, d, f, ev[0], ev[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// within-element for tetrahedral only
|
// within-element for tetrahedral only
|
||||||
if (m->flex_dim[f]!=3) {
|
if (m->flex_dim[f] != 3) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1725,7 +1727,7 @@ void mj_collideFlexInternal(const mjModel* m, mjData* d, int f) {
|
|||||||
|
|
||||||
// process all elements
|
// process all elements
|
||||||
const mjtNum* vertxpos = d->flexvert_xpos + 3*m->flex_vertadr[f];
|
const mjtNum* vertxpos = d->flexvert_xpos + 3*m->flex_vertadr[f];
|
||||||
for (int e=0; e<flex_elemnum; e++) {
|
for (int e=0; e < flex_elemnum; e++) {
|
||||||
const int* edata = m->flex_elem + m->flex_elemdataadr[f] + e*4;
|
const int* edata = m->flex_elem + m->flex_elemdataadr[f] + e*4;
|
||||||
con.elem[0] = e;
|
con.elem[0] = e;
|
||||||
|
|
||||||
@@ -1766,14 +1768,14 @@ void mj_collideFlexSAP(const mjModel* m, mjData* d, int f) {
|
|||||||
int* elid = mj_stackAllocInt(d, m->flex_elemnum[f]);
|
int* elid = mj_stackAllocInt(d, m->flex_elemnum[f]);
|
||||||
int nactive = 0;
|
int nactive = 0;
|
||||||
int flex_elemnum = m->flex_elemnum[f];
|
int flex_elemnum = m->flex_elemnum[f];
|
||||||
for (int i=0; i<flex_elemnum; i++) {
|
for (int i=0; i < flex_elemnum; i++) {
|
||||||
if (mj_isElemActive(m, f, i)) {
|
if (mj_isElemActive(m, f, i)) {
|
||||||
elid[nactive++] = i;
|
elid[nactive++] = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// nothing active
|
// nothing active
|
||||||
if (nactive<2) {
|
if (nactive < 2) {
|
||||||
mj_freeStack(d);
|
mj_freeStack(d);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1781,25 +1783,25 @@ void mj_collideFlexSAP(const mjModel* m, mjData* d, int f) {
|
|||||||
// allocate and construct AAMMs for active elements
|
// allocate and construct AAMMs for active elements
|
||||||
mjtNum* aamm = mj_stackAllocNum(d, 6*nactive);
|
mjtNum* aamm = mj_stackAllocNum(d, 6*nactive);
|
||||||
const mjtNum* elemaabb = d->flexelem_aabb + 6*m->flex_elemadr[f];
|
const mjtNum* elemaabb = d->flexelem_aabb + 6*m->flex_elemadr[f];
|
||||||
for (int i=0; i<nactive; i++) {
|
for (int i=0; i < nactive; i++) {
|
||||||
mju_sub3(aamm+6*i+0, elemaabb+6*elid[i], elemaabb+6*elid[i]+3);
|
mju_sub3(aamm+6*i+0, elemaabb+6*elid[i], elemaabb+6*elid[i]+3);
|
||||||
mju_add3(aamm+6*i+3, elemaabb+6*elid[i], elemaabb+6*elid[i]+3);
|
mju_add3(aamm+6*i+3, elemaabb+6*elid[i], elemaabb+6*elid[i]+3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// select largest axis from flex bvh
|
// select largest axis from flex bvh
|
||||||
const mjtNum* bvh = d->bvh_aabb_dyn + 6*(m->flex_bvhadr[f] - m->nbvhstatic);
|
const mjtNum* bvh = d->bvh_aabb_dyn + 6*(m->flex_bvhadr[f] - m->nbvhstatic);
|
||||||
int axis = (bvh[3]>bvh[4] && bvh[3]>bvh[5]) ? 0 : (bvh[4]>bvh[5] ? 1 : 2);
|
int axis = (bvh[3] > bvh[4] && bvh[3] > bvh[5]) ? 0 : (bvh[4] > bvh[5] ? 1 : 2);
|
||||||
|
|
||||||
// call SAP; hard limit on number of pairs to avoid out-of-memory
|
// call SAP; hard limit on number of pairs to avoid out-of-memory
|
||||||
int maxsappair = mjMIN(nactive*(nactive-1)/2, 1000000);
|
int maxsappair = mjMIN(nactive*(nactive-1)/2, 1000000);
|
||||||
int* sappair = mj_stackAllocInt(d, maxsappair);
|
int* sappair = mj_stackAllocInt(d, maxsappair);
|
||||||
int nsappair = mj_SAP(d, aamm, nactive, axis, sappair, maxsappair);
|
int nsappair = mj_SAP(d, aamm, nactive, axis, sappair, maxsappair);
|
||||||
if (nsappair<0) {
|
if (nsappair < 0) {
|
||||||
mjERROR("SAP failed");
|
mjERROR("SAP failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// send SAP pairs to nearphase
|
// send SAP pairs to nearphase
|
||||||
for (int i=0; i<nsappair; i++) {
|
for (int i=0; i < nsappair; i++) {
|
||||||
int e1 = elid[sappair[i] >> 16];
|
int e1 = elid[sappair[i] >> 16];
|
||||||
int e2 = elid[sappair[i] & 0xFFFF];
|
int e2 = elid[sappair[i] & 0xFFFF];
|
||||||
mj_collideElems(m, d, f, e1, f, e2);
|
mj_collideElems(m, d, f, e1, f, e2);
|
||||||
@@ -1829,62 +1831,62 @@ void mj_collideGeomElem(const mjModel* m, mjData* d, int g, int f, int e) {
|
|||||||
int b = m->geom_bodyid[g];
|
int b = m->geom_bodyid[g];
|
||||||
const int* edata = m->flex_elem + m->flex_elemdataadr[f] + e*(dim+1);
|
const int* edata = m->flex_elem + m->flex_elemdataadr[f] + e*(dim+1);
|
||||||
const int* bdata = m->flex_vertbodyid + m->flex_vertadr[f];
|
const int* bdata = m->flex_vertbodyid + m->flex_vertadr[f];
|
||||||
for (int i=0; i<=dim; i++) {
|
for (int i=0; i <= dim; i++) {
|
||||||
if (b==bdata[edata[i]]) {
|
if (b == bdata[edata[i]]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate mjContact[mjMAXCONPAIR] on the arena
|
// allocate mjContact[mjMAXCONPAIR] on the arena
|
||||||
mjContact* con =
|
mjContact* con =
|
||||||
(mjContact*) mj_arenaAllocByte(d, sizeof(mjContact) * mjMAXCONPAIR, _Alignof(mjContact));
|
(mjContact*) mj_arenaAllocByte(d, sizeof(mjContact) * mjMAXCONPAIR, _Alignof(mjContact));
|
||||||
if (!con) {
|
if (!con) {
|
||||||
mj_warning(d, mjWARN_CONTACTFULL, d->ncon);
|
mj_warning(d, mjWARN_CONTACTFULL, d->ncon);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sphere/capsule/box : capsule
|
// sphere/capsule/box : capsule
|
||||||
if (dim==1 && (type==mjGEOM_SPHERE || type==mjGEOM_CAPSULE || type==mjGEOM_BOX)) {
|
if (dim == 1 && (type == mjGEOM_SPHERE || type == mjGEOM_CAPSULE || type == mjGEOM_BOX)) {
|
||||||
// make capsule from vertices
|
// make capsule from vertices
|
||||||
mjtNum pos[3], mat[9], size[2];
|
mjtNum pos[3], mat[9], size[2];
|
||||||
mj_makeCapsule(m, d, f, m->flex_elem + m->flex_elemdataadr[f] + e*2,
|
mj_makeCapsule(m, d, f, m->flex_elem + m->flex_elemdataadr[f] + e*2,
|
||||||
pos, mat, size);
|
pos, mat, size);
|
||||||
|
|
||||||
// call raw primitive for corresponding geom type
|
// call raw primitive for corresponding geom type
|
||||||
if (type==mjGEOM_SPHERE) {
|
if (type == mjGEOM_SPHERE) {
|
||||||
num = mjraw_SphereCapsule(con, margin,
|
num = mjraw_SphereCapsule(con, margin,
|
||||||
d->geom_xpos+3*g, d->geom_xmat+9*g, m->geom_size+3*g,
|
d->geom_xpos+3*g, d->geom_xmat+9*g, m->geom_size+3*g,
|
||||||
pos, mat, size);
|
pos, mat, size);
|
||||||
}
|
}
|
||||||
else if (type==mjGEOM_CAPSULE) {
|
else if (type == mjGEOM_CAPSULE) {
|
||||||
num = mjraw_CapsuleCapsule(con, margin,
|
num = mjraw_CapsuleCapsule(con, margin,
|
||||||
d->geom_xpos+3*g, d->geom_xmat+9*g, m->geom_size+3*g,
|
d->geom_xpos+3*g, d->geom_xmat+9*g, m->geom_size+3*g,
|
||||||
pos, mat, size);
|
pos, mat, size);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
num = mjraw_CapsuleBox(con, margin,
|
num = mjraw_CapsuleBox(con, margin,
|
||||||
pos, mat, size,
|
pos, mat, size,
|
||||||
d->geom_xpos+3*g, d->geom_xmat+9*g, m->geom_size+3*g);
|
d->geom_xpos+3*g, d->geom_xmat+9*g, m->geom_size+3*g);
|
||||||
|
|
||||||
// reverse contact normals, since box geom is second
|
// reverse contact normals, since box geom is second
|
||||||
for (int i=0; i<num; i++) {
|
for (int i=0; i < num; i++) {
|
||||||
mju_scl3(con[i].frame, con[i].frame, -1);
|
mju_scl3(con[i].frame, con[i].frame, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// heightfield : elem
|
// heightfield : elem
|
||||||
else if (type==mjGEOM_HFIELD) {
|
else if (type == mjGEOM_HFIELD) {
|
||||||
num = mjc_HFieldElem(m, d, con, g, f, e, margin);
|
num = mjc_HFieldElem(m, d, con, g, f, e, margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sphere : triangle
|
// sphere : triangle
|
||||||
else if (type==mjGEOM_SPHERE && dim==2) {
|
else if (type == mjGEOM_SPHERE && dim == 2) {
|
||||||
const mjtNum* vertxpos = d->flexvert_xpos + 3*m->flex_vertadr[f];
|
const mjtNum* vertxpos = d->flexvert_xpos + 3*m->flex_vertadr[f];
|
||||||
num = mjraw_SphereTriangle(con, margin,
|
num = mjraw_SphereTriangle(con, margin,
|
||||||
d->geom_xpos+3*g, m->geom_size[3*g],
|
d->geom_xpos+3*g, m->geom_size[3*g],
|
||||||
vertxpos + 3*edata[0], vertxpos + 3*edata[1],
|
vertxpos + 3*edata[0], vertxpos + 3*edata[1],
|
||||||
vertxpos + 3*edata[2], m->flex_radius[f]);
|
vertxpos + 3*edata[2], m->flex_radius[f]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// general geom : elem
|
// general geom : elem
|
||||||
@@ -1905,7 +1907,7 @@ void mj_collideGeomElem(const mjModel* m, mjData* d, int g, int f, int e) {
|
|||||||
mj_contactParam(m, &condim, &gap, solref, solimp, friction, g, -1, -1, f);
|
mj_contactParam(m, &condim, &gap, solref, solimp, friction, g, -1, -1, f);
|
||||||
|
|
||||||
// add contacts
|
// add contacts
|
||||||
for (int i=0; i<num; i++) {
|
for (int i=0; i < num; i++) {
|
||||||
// set contact ids
|
// set contact ids
|
||||||
con[i].geom[0] = g;
|
con[i].geom[0] = g;
|
||||||
con[i].geom[1] = -1;
|
con[i].geom[1] = -1;
|
||||||
@@ -1937,7 +1939,7 @@ void mj_collideElems(const mjModel* m, mjData* d, int f1, int e1, int f2, int e2
|
|||||||
int num;
|
int num;
|
||||||
|
|
||||||
// ignore margin in self-collisions
|
// ignore margin in self-collisions
|
||||||
if (f1==f2) {
|
if (f1 == f2) {
|
||||||
margin = 0;
|
margin = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1952,10 +1954,10 @@ void mj_collideElems(const mjModel* m, mjData* d, int f1, int e1, int f2, int e2
|
|||||||
const int* edata2 = m->flex_elem + m->flex_elemdataadr[f2] + e2*(dim2+1);
|
const int* edata2 = m->flex_elem + m->flex_elemdataadr[f2] + e2*(dim2+1);
|
||||||
const int* bdata1 = m->flex_vertbodyid + m->flex_vertadr[f1];
|
const int* bdata1 = m->flex_vertbodyid + m->flex_vertadr[f1];
|
||||||
const int* bdata2 = m->flex_vertbodyid + m->flex_vertadr[f2];
|
const int* bdata2 = m->flex_vertbodyid + m->flex_vertadr[f2];
|
||||||
for (int i1=0; i1<=dim1; i1++) {
|
for (int i1=0; i1 <= dim1; i1++) {
|
||||||
int b1 = bdata1[edata1[i1]];
|
int b1 = bdata1[edata1[i1]];
|
||||||
for (int i2=0; i2<=dim2; i2++) {
|
for (int i2=0; i2 <= dim2; i2++) {
|
||||||
if (b1==bdata2[edata2[i2]]) {
|
if (b1 == bdata2[edata2[i2]]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1963,14 +1965,14 @@ void mj_collideElems(const mjModel* m, mjData* d, int f1, int e1, int f2, int e2
|
|||||||
|
|
||||||
// allocate mjContact[mjMAXCONPAIR] on the arena
|
// allocate mjContact[mjMAXCONPAIR] on the arena
|
||||||
mjContact* con =
|
mjContact* con =
|
||||||
(mjContact*) mj_arenaAllocByte(d, sizeof(mjContact) * mjMAXCONPAIR, _Alignof(mjContact));
|
(mjContact*) mj_arenaAllocByte(d, sizeof(mjContact) * mjMAXCONPAIR, _Alignof(mjContact));
|
||||||
if (!con) {
|
if (!con) {
|
||||||
mj_warning(d, mjWARN_CONTACTFULL, d->ncon);
|
mj_warning(d, mjWARN_CONTACTFULL, d->ncon);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// capsule : capsule
|
// capsule : capsule
|
||||||
if (dim1==1 && dim2==1) {
|
if (dim1 == 1 && dim2 == 1) {
|
||||||
// make capsules from vertices
|
// make capsules from vertices
|
||||||
mjtNum pos1[3], mat1[9], size1[2];
|
mjtNum pos1[3], mat1[9], size1[2];
|
||||||
mjtNum pos2[3], mat2[9], size2[2];
|
mjtNum pos2[3], mat2[9], size2[2];
|
||||||
@@ -2001,12 +2003,12 @@ void mj_collideElems(const mjModel* m, mjData* d, int f1, int e1, int f2, int e2
|
|||||||
mj_contactParam(m, &condim, &gap, solref, solimp, friction, -1, -1, f1, f2);
|
mj_contactParam(m, &condim, &gap, solref, solimp, friction, -1, -1, f1, f2);
|
||||||
|
|
||||||
// ignore gap in self collision, since margin is ignored
|
// ignore gap in self collision, since margin is ignored
|
||||||
if (f1==f2) {
|
if (f1 == f2) {
|
||||||
gap = 0;
|
gap = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add contacts
|
// add contacts
|
||||||
for (int i=0; i<num; i++) {
|
for (int i=0; i < num; i++) {
|
||||||
// set contact ids
|
// set contact ids
|
||||||
con[i].geom[0] = -1;
|
con[i].geom[0] = -1;
|
||||||
con[i].geom[1] = -1;
|
con[i].geom[1] = -1;
|
||||||
@@ -2054,14 +2056,14 @@ void mj_collideElemVert(const mjModel* m, mjData* d, int f, int e, int v) {
|
|||||||
|
|
||||||
// allocate mjContact[mjMAXCONPAIR] on the arena
|
// allocate mjContact[mjMAXCONPAIR] on the arena
|
||||||
mjContact* con =
|
mjContact* con =
|
||||||
(mjContact*) mj_arenaAllocByte(d, sizeof(mjContact) * mjMAXCONPAIR, _Alignof(mjContact));
|
(mjContact*) mj_arenaAllocByte(d, sizeof(mjContact) * mjMAXCONPAIR, _Alignof(mjContact));
|
||||||
if (!con) {
|
if (!con) {
|
||||||
mj_warning(d, mjWARN_CONTACTFULL, d->ncon);
|
mj_warning(d, mjWARN_CONTACTFULL, d->ncon);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sphere : capsule
|
// sphere : capsule
|
||||||
if (dim==1) {
|
if (dim == 1) {
|
||||||
mjtNum pos[3], mat[9], size[2];
|
mjtNum pos[3], mat[9], size[2];
|
||||||
mjtNum I[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
|
mjtNum I[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
|
||||||
mj_makeCapsule(m, d, f, edata, pos, mat, size);
|
mj_makeCapsule(m, d, f, edata, pos, mat, size);
|
||||||
@@ -2069,11 +2071,11 @@ void mj_collideElemVert(const mjModel* m, mjData* d, int f, int e, int v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sphere : triangle
|
// sphere : triangle
|
||||||
else if (dim==2) {
|
else if (dim == 2) {
|
||||||
const mjtNum* vertxpos = d->flexvert_xpos + 3*m->flex_vertadr[f];
|
const mjtNum* vertxpos = d->flexvert_xpos + 3*m->flex_vertadr[f];
|
||||||
num = mjraw_SphereTriangle(con, 0, vert, radius,
|
num = mjraw_SphereTriangle(con, 0, vert, radius,
|
||||||
vertxpos + 3*edata[0], vertxpos + 3*edata[1],
|
vertxpos + 3*edata[0], vertxpos + 3*edata[1],
|
||||||
vertxpos + 3*edata[2], radius);
|
vertxpos + 3*edata[2], radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sphere : tetrahdron
|
// sphere : tetrahdron
|
||||||
@@ -2094,7 +2096,7 @@ void mj_collideElemVert(const mjModel* m, mjData* d, int f, int e, int v) {
|
|||||||
mj_contactParam(m, &condim, &gap, solref, solimp, friction, -1, -1, f, f);
|
mj_contactParam(m, &condim, &gap, solref, solimp, friction, -1, -1, f, f);
|
||||||
|
|
||||||
// add contacts
|
// add contacts
|
||||||
for (int i=0; i<num; i++) {
|
for (int i=0; i < num; i++) {
|
||||||
// set contact ids
|
// set contact ids
|
||||||
con[i].geom[0] = -1;
|
con[i].geom[0] = -1;
|
||||||
con[i].geom[1] = -1;
|
con[i].geom[1] = -1;
|
||||||
|
|||||||
@@ -520,10 +520,10 @@ static mjtNum pointSegment(mjtNum res[2], const mjtNum p[2],
|
|||||||
mjtNum a = mju_dot(uv, up, 2) / mju_max(mjMINVAL, mju_dot(uv, uv, 2));
|
mjtNum a = mju_dot(uv, up, 2) / mju_max(mjMINVAL, mju_dot(uv, uv, 2));
|
||||||
|
|
||||||
// find nearest point to p, clamp to u or v if a is not in (0,1)
|
// find nearest point to p, clamp to u or v if a is not in (0,1)
|
||||||
if (a<=0) {
|
if (a <= 0) {
|
||||||
res[0] = u[0];
|
res[0] = u[0];
|
||||||
res[1] = u[1];
|
res[1] = u[1];
|
||||||
} else if (a>=1) {
|
} else if (a >= 1) {
|
||||||
res[0] = v[0];
|
res[0] = v[0];
|
||||||
res[1] = v[1];
|
res[1] = v[1];
|
||||||
} else {
|
} else {
|
||||||
@@ -582,7 +582,7 @@ int mjraw_SphereTriangle(mjContact* con, mjtNum margin,
|
|||||||
mjtNum sign3 = areaSign(p, b, o);
|
mjtNum sign3 = areaSign(p, b, o);
|
||||||
|
|
||||||
// p is inside triangle
|
// p is inside triangle
|
||||||
if (sign1==sign2 && sign2==sign3) {
|
if (sign1 == sign2 && sign2 == sign3) {
|
||||||
// P is nearest point to S within triangle
|
// P is nearest point to S within triangle
|
||||||
mju_copy3(X, P);
|
mju_copy3(X, P);
|
||||||
}
|
}
|
||||||
@@ -596,7 +596,7 @@ int mjraw_SphereTriangle(mjContact* con, mjtNum margin,
|
|||||||
dstx[2] = pointSegment(x[2], p, b, o);
|
dstx[2] = pointSegment(x[2], p, b, o);
|
||||||
|
|
||||||
// select minimum
|
// select minimum
|
||||||
int best = (dstx[0]<dstx[1] && dstx[0]<dstx[2]) ? 0 : (dstx[1]<dstx[2] ? 1 : 2);
|
int best = (dstx[0] < dstx[1] && dstx[0] < dstx[2]) ? 0 : (dstx[1] < dstx[2] ? 1 : 2);
|
||||||
|
|
||||||
// convert x[best] to 3D
|
// convert x[best] to 3D
|
||||||
mju_scl3(X, V1, x[best][0]);
|
mju_scl3(X, V1, x[best][0]);
|
||||||
@@ -609,7 +609,7 @@ int mjraw_SphereTriangle(mjContact* con, mjtNum margin,
|
|||||||
mjtNum dst = mju_normalize3(nrm);
|
mjtNum dst = mju_normalize3(nrm);
|
||||||
|
|
||||||
// exit if too far
|
// exit if too far
|
||||||
if (dst>rbound) {
|
if (dst > rbound) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+178
-176
@@ -43,44 +43,44 @@ static mjtNum geomDistance(const mjModel* m, const mjData* d, const mjpPlugin* p
|
|||||||
|
|
||||||
// see https://iquilezles.org/articles/distfunctions/
|
// see https://iquilezles.org/articles/distfunctions/
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case mjGEOM_PLANE:
|
case mjGEOM_PLANE:
|
||||||
return x[2];
|
return x[2];
|
||||||
case mjGEOM_SPHERE:
|
case mjGEOM_SPHERE:
|
||||||
return mju_norm3(x) - size[0];
|
return mju_norm3(x) - size[0];
|
||||||
case mjGEOM_BOX:
|
case mjGEOM_BOX:
|
||||||
a[0] = mju_abs(x[0]) - size[0];
|
a[0] = mju_abs(x[0]) - size[0];
|
||||||
a[1] = mju_abs(x[1]) - size[1];
|
a[1] = mju_abs(x[1]) - size[1];
|
||||||
a[2] = mju_abs(x[2]) - size[2];
|
a[2] = mju_abs(x[2]) - size[2];
|
||||||
b[0] = mju_max(a[0], 0);
|
b[0] = mju_max(a[0], 0);
|
||||||
b[1] = mju_max(a[1], 0);
|
b[1] = mju_max(a[1], 0);
|
||||||
b[2] = mju_max(a[2], 0);
|
b[2] = mju_max(a[2], 0);
|
||||||
return mju_norm3(b) + mju_min(mju_max(a[0], mju_max(a[1], a[2])), 0);
|
return mju_norm3(b) + mju_min(mju_max(a[0], mju_max(a[1], a[2])), 0);
|
||||||
case mjGEOM_CAPSULE:
|
case mjGEOM_CAPSULE:
|
||||||
a[0] = x[0];
|
a[0] = x[0];
|
||||||
a[1] = x[1];
|
a[1] = x[1];
|
||||||
a[2] = x[2] - mju_clip(x[2], -size[1], size[1]);
|
a[2] = x[2] - mju_clip(x[2], -size[1], size[1]);
|
||||||
return mju_norm3(a) - size[0];
|
return mju_norm3(a) - size[0];
|
||||||
case mjGEOM_ELLIPSOID:
|
case mjGEOM_ELLIPSOID:
|
||||||
a[0] = x[0] / size[0];
|
a[0] = x[0] / size[0];
|
||||||
a[1] = x[1] / size[1];
|
a[1] = x[1] / size[1];
|
||||||
a[2] = x[2] / size[2];
|
a[2] = x[2] / size[2];
|
||||||
b[0] = a[0] / size[0];
|
b[0] = a[0] / size[0];
|
||||||
b[1] = a[1] / size[1];
|
b[1] = a[1] / size[1];
|
||||||
b[2] = a[2] / size[2];
|
b[2] = a[2] / size[2];
|
||||||
mjtNum k0 = mju_norm3(a);
|
mjtNum k0 = mju_norm3(a);
|
||||||
mjtNum k1 = mju_norm3(b);
|
mjtNum k1 = mju_norm3(b);
|
||||||
return k0 * (k0 - 1.0) / k1;
|
return k0 * (k0 - 1.0) / k1;
|
||||||
case mjGEOM_CYLINDER:
|
case mjGEOM_CYLINDER:
|
||||||
a[0] = mju_sqrt(x[0]*x[0]+x[1]*x[1]) - size[0];
|
a[0] = mju_sqrt(x[0]*x[0]+x[1]*x[1]) - size[0];
|
||||||
a[1] = mju_abs(x[2]) - size[1];
|
a[1] = mju_abs(x[2]) - size[1];
|
||||||
b[0] = mju_max(a[0], 0);
|
b[0] = mju_max(a[0], 0);
|
||||||
b[1] = mju_max(a[1], 0);
|
b[1] = mju_max(a[1], 0);
|
||||||
return mju_min(mju_max(a[0], a[1]), 0) + mju_norm(b, 2);
|
return mju_min(mju_max(a[0], a[1]), 0) + mju_norm(b, 2);
|
||||||
case mjGEOM_SDF:
|
case mjGEOM_SDF:
|
||||||
return p->sdf_distance(x, d, i);
|
return p->sdf_distance(x, d, i);
|
||||||
default:
|
default:
|
||||||
mjERROR("sdf collisions not available for geom type %d", type);
|
mjERROR("sdf collisions not available for geom type %d", type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,83 +92,83 @@ static void geomGradient(mjtNum gradient[3], const mjModel* m, const mjData* d,
|
|||||||
|
|
||||||
// see https://iquilezles.org/articles/distfunctions/
|
// see https://iquilezles.org/articles/distfunctions/
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case mjGEOM_PLANE:
|
case mjGEOM_PLANE:
|
||||||
mju_zero3(gradient);
|
mju_zero3(gradient);
|
||||||
gradient[2] = 1;
|
gradient[2] = 1;
|
||||||
break;
|
break;
|
||||||
case mjGEOM_SPHERE:
|
case mjGEOM_SPHERE:
|
||||||
mju_copy3(gradient, x);
|
mju_copy3(gradient, x);
|
||||||
c = mju_norm3(x);
|
c = mju_norm3(x);
|
||||||
gradient[0] *= 1. / c;
|
gradient[0] *= 1. / c;
|
||||||
gradient[1] *= 1. / c;
|
gradient[1] *= 1. / c;
|
||||||
gradient[2] *= 1. / c;
|
gradient[2] *= 1. / c;
|
||||||
break;
|
break;
|
||||||
case mjGEOM_BOX:
|
case mjGEOM_BOX:
|
||||||
mju_zero3(gradient);
|
mju_zero3(gradient);
|
||||||
a[0] = mju_abs(x[0]) - size[0];
|
a[0] = mju_abs(x[0]) - size[0];
|
||||||
a[1] = mju_abs(x[1]) - size[1];
|
a[1] = mju_abs(x[1]) - size[1];
|
||||||
a[2] = mju_abs(x[2]) - size[2];
|
a[2] = mju_abs(x[2]) - size[2];
|
||||||
int k = a[0] > a[1] ? 0 : 1;
|
int k = a[0] > a[1] ? 0 : 1;
|
||||||
int l = a[2] > a[k] ? 2 : k;
|
int l = a[2] > a[k] ? 2 : k;
|
||||||
if (a[l]<0) {
|
if (a[l] < 0) {
|
||||||
gradient[l] = x[l] / mju_abs(x[l]);
|
gradient[l] = x[l] / mju_abs(x[l]);
|
||||||
} else {
|
} else {
|
||||||
b[0] = mju_max(a[0], 0);
|
b[0] = mju_max(a[0], 0);
|
||||||
b[1] = mju_max(a[1], 0);
|
b[1] = mju_max(a[1], 0);
|
||||||
b[2] = mju_max(a[2], 0);
|
b[2] = mju_max(a[2], 0);
|
||||||
c = mju_norm3(b);
|
c = mju_norm3(b);
|
||||||
gradient[0] = a[0]>0 ? b[0] / c * x[0] / mju_abs(x[0]) : 0;
|
gradient[0] = a[0] > 0 ? b[0] / c * x[0] / mju_abs(x[0]) : 0;
|
||||||
gradient[1] = a[1]>0 ? b[1] / c * x[1] / mju_abs(x[1]) : 0;
|
gradient[1] = a[1] > 0 ? b[1] / c * x[1] / mju_abs(x[1]) : 0;
|
||||||
gradient[2] = a[2]>0 ? b[2] / c * x[2] / mju_abs(x[2]) : 0;
|
gradient[2] = a[2] > 0 ? b[2] / c * x[2] / mju_abs(x[2]) : 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case mjGEOM_CAPSULE:
|
case mjGEOM_CAPSULE:
|
||||||
a[0] = x[0];
|
a[0] = x[0];
|
||||||
a[1] = x[1];
|
a[1] = x[1];
|
||||||
a[2] = x[2] - mju_clip(x[2], -size[1], size[1]);
|
a[2] = x[2] - mju_clip(x[2], -size[1], size[1]);
|
||||||
c = mju_norm3(a);
|
c = mju_norm3(a);
|
||||||
gradient[0] = a[0] / c;
|
gradient[0] = a[0] / c;
|
||||||
gradient[1] = a[1] / c;
|
gradient[1] = a[1] / c;
|
||||||
gradient[2] = a[2] / c;
|
gradient[2] = a[2] / c;
|
||||||
break;
|
break;
|
||||||
case mjGEOM_ELLIPSOID:
|
case mjGEOM_ELLIPSOID:
|
||||||
a[0] = x[0] / size[0];
|
a[0] = x[0] / size[0];
|
||||||
a[1] = x[1] / size[1];
|
a[1] = x[1] / size[1];
|
||||||
a[2] = x[2] / size[2];
|
a[2] = x[2] / size[2];
|
||||||
b[0] = a[0] / size[0];
|
b[0] = a[0] / size[0];
|
||||||
b[1] = a[1] / size[1];
|
b[1] = a[1] / size[1];
|
||||||
b[2] = a[2] / size[2];
|
b[2] = a[2] / size[2];
|
||||||
mjtNum k0 = mju_norm3(a);
|
mjtNum k0 = mju_norm3(a);
|
||||||
mjtNum k1 = mju_norm3(b);
|
mjtNum k1 = mju_norm3(b);
|
||||||
gradient[0] = a[0]*(2.*k0 - 1.) / k1 + k0*(k0 - 1.) * b[0]/(k1*k1);
|
gradient[0] = a[0]*(2.*k0 - 1.) / k1 + k0*(k0 - 1.) * b[0]/(k1*k1);
|
||||||
gradient[1] = a[1]*(2.*k0 - 1.) / k1 + k0*(k0 - 1.) * b[1]/(k1*k1);
|
gradient[1] = a[1]*(2.*k0 - 1.) / k1 + k0*(k0 - 1.) * b[1]/(k1*k1);
|
||||||
gradient[2] = a[2]*(2.*k0 - 1.) / k1 + k0*(k0 - 1.) * b[2]/(k1*k1);
|
gradient[2] = a[2]*(2.*k0 - 1.) / k1 + k0*(k0 - 1.) * b[2]/(k1*k1);
|
||||||
break;
|
break;
|
||||||
case mjGEOM_CYLINDER:
|
case mjGEOM_CYLINDER:
|
||||||
c = mju_sqrt(x[0]*x[0]+x[1]*x[1]);
|
c = mju_sqrt(x[0]*x[0]+x[1]*x[1]);
|
||||||
e = mju_abs(x[2]);
|
e = mju_abs(x[2]);
|
||||||
a[0] = c - size[0];
|
a[0] = c - size[0];
|
||||||
a[1] = e - size[1];
|
a[1] = e - size[1];
|
||||||
mjtNum grada[3] = {x[0] / c, x[1] / c, x[2] / e};
|
mjtNum grada[3] = {x[0] / c, x[1] / c, x[2] / e};
|
||||||
int j = a[0] > a[1] ? 0 : 1;
|
int j = a[0] > a[1] ? 0 : 1;
|
||||||
if (a[j] < 0) {
|
if (a[j] < 0) {
|
||||||
gradient[0] = j==0 ? grada[0] : 0;
|
gradient[0] = j == 0 ? grada[0] : 0;
|
||||||
gradient[1] = j==0 ? grada[1] : 0;
|
gradient[1] = j == 0 ? grada[1] : 0;
|
||||||
gradient[2] = j==1 ? grada[2] : 0;
|
gradient[2] = j == 1 ? grada[2] : 0;
|
||||||
} else {
|
} else {
|
||||||
b[0] = mju_max(a[0], 0);
|
b[0] = mju_max(a[0], 0);
|
||||||
b[1] = mju_max(a[1], 0);
|
b[1] = mju_max(a[1], 0);
|
||||||
mjtNum bnorm = mju_norm(b, 2);
|
mjtNum bnorm = mju_norm(b, 2);
|
||||||
gradient[0] = grada[0] * b[0] / bnorm;
|
gradient[0] = grada[0] * b[0] / bnorm;
|
||||||
gradient[1] = grada[1] * b[0] / bnorm;
|
gradient[1] = grada[1] * b[0] / bnorm;
|
||||||
gradient[2] = grada[2] * b[1] / bnorm;
|
gradient[2] = grada[2] * b[1] / bnorm;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case mjGEOM_SDF:
|
case mjGEOM_SDF:
|
||||||
p->sdf_gradient(gradient, x, d, i);
|
p->sdf_gradient(gradient, x, d, i);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mjERROR("sdf collisions not available for geom type %d", type);
|
mjERROR("sdf collisions not available for geom type %d", type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,16 +179,16 @@ mjtNum mjc_distance(const mjModel* m, const mjData* d, const mjSDF* s, const mjt
|
|||||||
mjtNum y[3];
|
mjtNum y[3];
|
||||||
|
|
||||||
switch (s->type) {
|
switch (s->type) {
|
||||||
case mjSDFTYPE_SINGLE:
|
case mjSDFTYPE_SINGLE:
|
||||||
return geomDistance(m, d, s->plugin[0], s->id[0], x, s->geomtype[0]);
|
return geomDistance(m, d, s->plugin[0], s->id[0], x, s->geomtype[0]);
|
||||||
case mjSDFTYPE_INTERSECTION:
|
case mjSDFTYPE_INTERSECTION:
|
||||||
mju_rotVecMat(y, x, s->relmat);
|
mju_rotVecMat(y, x, s->relmat);
|
||||||
mju_addTo3(y, s->relpos);
|
mju_addTo3(y, s->relpos);
|
||||||
return mju_max(geomDistance(m, d, s->plugin[0], s->id[0], x, s->geomtype[0]),
|
return mju_max(geomDistance(m, d, s->plugin[0], s->id[0], x, s->geomtype[0]),
|
||||||
geomDistance(m, d, s->plugin[1], s->id[1], y, s->geomtype[1]));
|
geomDistance(m, d, s->plugin[1], s->id[1], y, s->geomtype[1]));
|
||||||
default:
|
default:
|
||||||
mjERROR("SDF type not available");
|
mjERROR("SDF type not available");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,33 +199,33 @@ void mjc_gradient(const mjModel* m, const mjData* d, const mjSDF* s,
|
|||||||
const mjtNum* point[2] = {x, y};
|
const mjtNum* point[2] = {x, y};
|
||||||
|
|
||||||
switch (s->type) {
|
switch (s->type) {
|
||||||
case mjSDFTYPE_INTERSECTION:
|
case mjSDFTYPE_INTERSECTION:
|
||||||
mju_rotVecMat(y, x, s->relmat);
|
mju_rotVecMat(y, x, s->relmat);
|
||||||
mju_addTo3(y, s->relpos);
|
mju_addTo3(y, s->relpos);
|
||||||
int i = geomDistance(m, d, s->plugin[0], s->id[0], x, s->geomtype[0]) >
|
int i = geomDistance(m, d, s->plugin[0], s->id[0], x, s->geomtype[0]) >
|
||||||
geomDistance(m, d, s->plugin[1], s->id[1], y, s->geomtype[1]) ? 0 : 1;
|
geomDistance(m, d, s->plugin[1], s->id[1], y, s->geomtype[1]) ? 0 : 1;
|
||||||
geomGradient(gradient, m, d, s->plugin[i], s->id[i], point[i], s->geomtype[i]);
|
geomGradient(gradient, m, d, s->plugin[i], s->id[i], point[i], s->geomtype[i]);
|
||||||
if (i==1) {
|
if (i == 1) {
|
||||||
mju_rotVecMatT(gradient, gradient, s->relmat);
|
mju_rotVecMatT(gradient, gradient, s->relmat);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case mjSDFTYPE_AVERAGE:
|
case mjSDFTYPE_AVERAGE:
|
||||||
mju_rotVecMat(y, x, s->relmat);
|
mju_rotVecMat(y, x, s->relmat);
|
||||||
mju_addTo3(y, s->relpos);
|
mju_addTo3(y, s->relpos);
|
||||||
mjtNum grad1[3], grad2[3];
|
mjtNum grad1[3], grad2[3];
|
||||||
geomGradient(grad1, m, d, s->plugin[0], s->id[0], x, s->geomtype[0]);
|
geomGradient(grad1, m, d, s->plugin[0], s->id[0], x, s->geomtype[0]);
|
||||||
mju_normalize3(grad1);
|
mju_normalize3(grad1);
|
||||||
geomGradient(grad2, m, d, s->plugin[1], s->id[1], y, s->geomtype[1]);
|
geomGradient(grad2, m, d, s->plugin[1], s->id[1], y, s->geomtype[1]);
|
||||||
mju_rotVecMatT(grad2, grad2, s->relmat);
|
mju_rotVecMatT(grad2, grad2, s->relmat);
|
||||||
mju_normalize3(grad2);
|
mju_normalize3(grad2);
|
||||||
mju_sub3(gradient, grad1, grad2);
|
mju_sub3(gradient, grad1, grad2);
|
||||||
mju_normalize3(gradient);
|
mju_normalize3(gradient);
|
||||||
break;
|
break;
|
||||||
case mjSDFTYPE_SINGLE:
|
case mjSDFTYPE_SINGLE:
|
||||||
geomGradient(gradient, m, d, s->plugin[0], s->id[0], point[0], s->geomtype[0]);
|
geomGradient(gradient, m, d, s->plugin[0], s->id[0], point[0], s->geomtype[0]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mjERROR("SDF type not available");
|
mjERROR("SDF type not available");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,7 +257,7 @@ static void undoTransformation(const mjModel* m, const mjData* d, int g,
|
|||||||
mjtNum sdf_xpos[3], mjtNum sdf_quat[4]) {
|
mjtNum sdf_xpos[3], mjtNum sdf_quat[4]) {
|
||||||
mjtNum* xpos = d->geom_xpos + 3 * g;
|
mjtNum* xpos = d->geom_xpos + 3 * g;
|
||||||
mjtNum* xmat = d->geom_xmat + 9 * g;
|
mjtNum* xmat = d->geom_xmat + 9 * g;
|
||||||
if (m->geom_type[g]==mjGEOM_MESH || m->geom_type[g]==mjGEOM_SDF) {
|
if (m->geom_type[g] == mjGEOM_MESH || m->geom_type[g] == mjGEOM_SDF) {
|
||||||
mjtNum negpos[3], negquat[4], xquat[4];
|
mjtNum negpos[3], negquat[4], xquat[4];
|
||||||
mjtNum* pos = m->mesh_pos + 3 * m->geom_dataid[g];
|
mjtNum* pos = m->mesh_pos + 3 * m->geom_dataid[g];
|
||||||
mjtNum* quat = m->mesh_quat + 4 * m->geom_dataid[g];
|
mjtNum* quat = m->mesh_quat + 4 * m->geom_dataid[g];
|
||||||
@@ -328,19 +328,19 @@ static int addContact(mjtNum* points, mjContact* con, const mjtNum x[3],
|
|||||||
// finds minimum of Frank-Wolfe objective
|
// finds minimum of Frank-Wolfe objective
|
||||||
static mjtNum stepFrankWolfe(mjtNum x[3], const mjtNum* corners, int ncorners,
|
static mjtNum stepFrankWolfe(mjtNum x[3], const mjtNum* corners, int ncorners,
|
||||||
const mjModel* m, const mjSDF* sdf, mjData* d) {
|
const mjModel* m, const mjSDF* sdf, mjData* d) {
|
||||||
for (int step=0; step<m->opt.sdf_iterations; step++) {
|
for (int step=0; step < m->opt.sdf_iterations; step++) {
|
||||||
mjtNum best = 1e10, fun, s[3], grad[3];
|
mjtNum best = 1e10, fun, s[3], grad[3];
|
||||||
|
|
||||||
// evaluate gradient
|
// evaluate gradient
|
||||||
mjc_gradient(m, d, sdf, grad, x);
|
mjc_gradient(m, d, sdf, grad, x);
|
||||||
|
|
||||||
// evaluate all corners
|
// evaluate all corners
|
||||||
for (int i=0; i<ncorners; i++) {
|
for (int i=0; i < ncorners; i++) {
|
||||||
// compute sdf
|
// compute sdf
|
||||||
fun = mju_dot3(corners + 3*i, grad);
|
fun = mju_dot3(corners + 3*i, grad);
|
||||||
|
|
||||||
// save argmin
|
// save argmin
|
||||||
if (fun<best) {
|
if (fun < best) {
|
||||||
best = fun;
|
best = fun;
|
||||||
mju_copy3(s, corners + 3*i);
|
mju_copy3(s, corners + 3*i);
|
||||||
}
|
}
|
||||||
@@ -360,16 +360,16 @@ static mjtNum stepGradient(mjtNum x[3], const mjModel* m, const mjSDF* s,
|
|||||||
mjData* d) {
|
mjData* d) {
|
||||||
mjtNum alpha = 0.2; // step along the gradient direction
|
mjtNum alpha = 0.2; // step along the gradient direction
|
||||||
|
|
||||||
for (int step=0; step<m->opt.sdf_iterations; step++) {
|
for (int step=0; step < m->opt.sdf_iterations; step++) {
|
||||||
mjtNum grad[3];
|
mjtNum grad[3];
|
||||||
|
|
||||||
// evaluate gradient
|
// evaluate gradient
|
||||||
mjc_gradient(m, d, s, grad, x);
|
mjc_gradient(m, d, s, grad, x);
|
||||||
|
|
||||||
// sanity check
|
// sanity check
|
||||||
if (isnan(grad[0]) || grad[0]>mjMAXVAL || grad[0]<-mjMAXVAL ||
|
if (isnan(grad[0]) || grad[0] > mjMAXVAL || grad[0] < -mjMAXVAL ||
|
||||||
isnan(grad[1]) || grad[1]>mjMAXVAL || grad[1]<-mjMAXVAL ||
|
isnan(grad[1]) || grad[1] > mjMAXVAL || grad[1] < -mjMAXVAL ||
|
||||||
isnan(grad[2]) || grad[2]>mjMAXVAL || grad[2]<-mjMAXVAL) {
|
isnan(grad[2]) || grad[2] > mjMAXVAL || grad[2] < -mjMAXVAL) {
|
||||||
return mjMAXVAL;
|
return mjMAXVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,7 +422,7 @@ static int triangleIntersect(const mjtNum triangle[9], const mjModel* m,
|
|||||||
// coordinate change
|
// coordinate change
|
||||||
mju_addTo3(center, p);
|
mju_addTo3(center, p);
|
||||||
|
|
||||||
return mjc_distance(m, d, sdf, center)<r;
|
return mjc_distance(m, d, sdf, center) < r;
|
||||||
}
|
}
|
||||||
|
|
||||||
// intersect with circumsphere of bounding box
|
// intersect with circumsphere of bounding box
|
||||||
@@ -436,7 +436,7 @@ static int boxIntersect(const mjtNum bvh[6], const mjtNum offset[3],
|
|||||||
mju_addTo3(candidate, offset);
|
mju_addTo3(candidate, offset);
|
||||||
|
|
||||||
// check if inside the bounding box
|
// check if inside the bounding box
|
||||||
return mjc_distance(m, d, s, candidate)<r;
|
return mjc_distance(m, d, s, candidate) < r;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------- mesh vs sdf broad phase --------------------------------------------
|
//---------------------------- mesh vs sdf broad phase --------------------------------------------
|
||||||
@@ -460,7 +460,7 @@ static void collideBVH(const mjModel* m, mjData* d, int g,
|
|||||||
};
|
};
|
||||||
typedef struct CollideTreeArgs_ CollideTreeArgs;
|
typedef struct CollideTreeArgs_ CollideTreeArgs;
|
||||||
CollideTreeArgs* stack = (CollideTreeArgs*) mj_stackAllocByte(
|
CollideTreeArgs* stack = (CollideTreeArgs*) mj_stackAllocByte(
|
||||||
d, max_stack * sizeof(CollideTreeArgs), _Alignof(CollideTreeArgs));
|
d, max_stack * sizeof(CollideTreeArgs), _Alignof(CollideTreeArgs));
|
||||||
|
|
||||||
int nstack = 0;
|
int nstack = 0;
|
||||||
stack[nstack].node = 0;
|
stack[nstack].node = 0;
|
||||||
@@ -480,7 +480,7 @@ static void collideBVH(const mjModel* m, mjData* d, int g,
|
|||||||
}
|
}
|
||||||
if (boxIntersect(bvh+6*node, offset, rotation, m, sdf, d)) {
|
if (boxIntersect(bvh+6*node, offset, rotation, m, sdf, d)) {
|
||||||
faces[*npoints] = faceid[node];
|
faces[*npoints] = faceid[node];
|
||||||
if (++(*npoints)==MAXSDFFACE) {
|
if (++(*npoints) == MAXSDFFACE) {
|
||||||
mju_warning("mjc_MeshSDF: too many bounding volumes, some contacts may be missed");
|
mju_warning("mjc_MeshSDF: too many bounding volumes, some contacts may be missed");
|
||||||
mj_freeStack(d);
|
mj_freeStack(d);
|
||||||
return;
|
return;
|
||||||
@@ -498,7 +498,7 @@ static void collideBVH(const mjModel* m, mjData* d, int g,
|
|||||||
visited[node] = 1;
|
visited[node] = 1;
|
||||||
|
|
||||||
// recursive call
|
// recursive call
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i < 2; i++) {
|
||||||
if (child[2*node+i] != -1) {
|
if (child[2*node+i] != -1) {
|
||||||
if (nstack >= max_stack) mjERROR("BVH stack depth exceeded.");
|
if (nstack >= max_stack) mjERROR("BVH stack depth exceeded.");
|
||||||
stack[nstack].node = child[2*node+i];
|
stack[nstack].node = child[2*node+i];
|
||||||
@@ -551,9 +551,9 @@ int mjc_MeshSDF(const mjModel* m, const mjData* d, mjContact* con, int g1, int g
|
|||||||
collideBVH(m, (mjData*)d, g1, offset, rotation, faces, &npoints, &n0, &sdf);
|
collideBVH(m, (mjData*)d, g1, offset, rotation, faces, &npoints, &n0, &sdf);
|
||||||
|
|
||||||
// Frank-Wolfe algorithm
|
// Frank-Wolfe algorithm
|
||||||
for (int i=0; i<npoints; i++) {
|
for (int i=0; i < npoints; i++) {
|
||||||
int face = faceadr + faces[i];
|
int face = faceadr + faces[i];
|
||||||
for (int v=0; v<3; v++) {
|
for (int v=0; v < 3; v++) {
|
||||||
mjtNum vec[3] = {
|
mjtNum vec[3] = {
|
||||||
m->mesh_vert[3*(vertadr+m->mesh_face[3*face+v])+0],
|
m->mesh_vert[3*(vertadr+m->mesh_face[3*face+v])+0],
|
||||||
m->mesh_vert[3*(vertadr+m->mesh_face[3*face+v])+1],
|
m->mesh_vert[3*(vertadr+m->mesh_face[3*face+v])+1],
|
||||||
@@ -576,13 +576,13 @@ int mjc_MeshSDF(const mjModel* m, const mjData* d, mjContact* con, int g1, int g
|
|||||||
x[2] = (corners[2]+corners[5]+corners[8])/3;
|
x[2] = (corners[2]+corners[5]+corners[8])/3;
|
||||||
|
|
||||||
// SHOULD NOT OCCUR
|
// SHOULD NOT OCCUR
|
||||||
if (ncandidate==MAXMESHPNT) mjERROR("too many contact points");
|
if (ncandidate == MAXMESHPNT)mjERROR("too many contact points");
|
||||||
|
|
||||||
// Frank-Wolfe
|
// Frank-Wolfe
|
||||||
depth = stepFrankWolfe(x, corners, 3, m, &sdf, (mjData*)d);
|
depth = stepFrankWolfe(x, corners, 3, m, &sdf, (mjData*)d);
|
||||||
|
|
||||||
// store candidate if there is penetration
|
// store candidate if there is penetration
|
||||||
if (depth<0) {
|
if (depth < 0) {
|
||||||
mju_copy3(candidate + 3*ncandidate, x);
|
mju_copy3(candidate + 3*ncandidate, x);
|
||||||
index[ncandidate] = ncandidate;
|
index[ncandidate] = ncandidate;
|
||||||
dist[ncandidate++] = depth;
|
dist[ncandidate++] = depth;
|
||||||
@@ -593,7 +593,7 @@ int mjc_MeshSDF(const mjModel* m, const mjData* d, mjContact* con, int g1, int g
|
|||||||
mjQUICKSORT(index, ncandidate, sizeof(int), distcompare, dist);
|
mjQUICKSORT(index, ncandidate, sizeof(int), distcompare, dist);
|
||||||
|
|
||||||
// add only the first mjMAXCONPAIR pairs
|
// add only the first mjMAXCONPAIR pairs
|
||||||
for (int i=0; i<mju_min(ncandidate, mjMAXCONPAIR); i++) {
|
for (int i=0; i < mju_min(ncandidate, mjMAXCONPAIR); i++) {
|
||||||
cnt = addContact(points, con, candidate + 3*index[i], pos2true, sdf_quat,
|
cnt = addContact(points, con, candidate + 3*index[i], pos2true, sdf_quat,
|
||||||
dist[index[i]], cnt, m, &sdf, (mjData*)d);
|
dist[index[i]], cnt, m, &sdf, (mjData*)d);
|
||||||
}
|
}
|
||||||
@@ -633,7 +633,7 @@ int mjc_SDF(const mjModel* m, const mjData* d, mjContact* con, int g1, int g2, m
|
|||||||
mapPose(pos1true, squat1, pos2true, squat2, offset12, rotation12);
|
mapPose(pos1true, squat1, pos2true, squat2, offset12, rotation12);
|
||||||
|
|
||||||
// axis-aligned bounding boxes in g1 frame
|
// axis-aligned bounding boxes in g1 frame
|
||||||
for (int i=0; i<8; i++) {
|
for (int i=0; i < 8; i++) {
|
||||||
vec1[0] = (i&1 ? size1[0]+size1[3] : size1[0]-size1[3]);
|
vec1[0] = (i&1 ? size1[0]+size1[3] : size1[0]-size1[3]);
|
||||||
vec1[1] = (i&2 ? size1[1]+size1[4] : size1[1]-size1[4]);
|
vec1[1] = (i&2 ? size1[1]+size1[4] : size1[1]-size1[4]);
|
||||||
vec1[2] = (i&4 ? size1[2]+size1[5] : size1[2]-size1[5]);
|
vec1[2] = (i&4 ? size1[2]+size1[5] : size1[2]-size1[5]);
|
||||||
@@ -645,7 +645,7 @@ int mjc_SDF(const mjModel* m, const mjData* d, mjContact* con, int g1, int g2, m
|
|||||||
mju_rotVecMat(vec2, vec2, rotation1);
|
mju_rotVecMat(vec2, vec2, rotation1);
|
||||||
mju_addTo3(vec2, offset1);
|
mju_addTo3(vec2, offset1);
|
||||||
|
|
||||||
for (int k=0; k<3; k++) {
|
for (int k=0; k < 3; k++) {
|
||||||
aabb1[0+k] = mju_min(aabb1[0+k], vec1[k]);
|
aabb1[0+k] = mju_min(aabb1[0+k], vec1[k]);
|
||||||
aabb1[3+k] = mju_max(aabb1[3+k], vec1[k]);
|
aabb1[3+k] = mju_max(aabb1[3+k], vec1[k]);
|
||||||
aabb2[0+k] = mju_min(aabb2[0+k], vec2[k]);
|
aabb2[0+k] = mju_min(aabb2[0+k], vec2[k]);
|
||||||
@@ -654,13 +654,13 @@ int mjc_SDF(const mjModel* m, const mjData* d, mjContact* con, int g1, int g2, m
|
|||||||
}
|
}
|
||||||
|
|
||||||
// intersection of aabbs
|
// intersection of aabbs
|
||||||
for (int k=0; k<3; k++) {
|
for (int k=0; k < 3; k++) {
|
||||||
aabb[0+k] = mju_max(aabb1[0+k], aabb2[0+k]);
|
aabb[0+k] = mju_max(aabb1[0+k], aabb2[0+k]);
|
||||||
aabb[3+k] = mju_min(aabb1[3+k], aabb2[3+k]);
|
aabb[3+k] = mju_min(aabb1[3+k], aabb2[3+k]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// no intersection if max < min
|
// no intersection if max < min
|
||||||
if (aabb[3]<aabb[0] || aabb[4]<aabb[1] || aabb[5]<aabb[2]) {
|
if (aabb[3] < aabb[0] || aabb[4] < aabb[1] || aabb[5] < aabb[2]) {
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,7 +696,7 @@ int mjc_SDF(const mjModel* m, const mjData* d, mjContact* con, int g1, int g2, m
|
|||||||
mjtNum contacts[3*mjMAXCONPAIR];
|
mjtNum contacts[3*mjMAXCONPAIR];
|
||||||
|
|
||||||
int i = 0, j = 0;
|
int i = 0, j = 0;
|
||||||
while (i<m->opt.sdf_initpoints) {
|
while (i < m->opt.sdf_initpoints) {
|
||||||
x[0] = aabb[0] + (aabb[3]-aabb[0]) * mju_Halton(j, 2);
|
x[0] = aabb[0] + (aabb[3]-aabb[0]) * mju_Halton(j, 2);
|
||||||
x[1] = aabb[1] + (aabb[4]-aabb[1]) * mju_Halton(j, 3);
|
x[1] = aabb[1] + (aabb[4]-aabb[1]) * mju_Halton(j, 3);
|
||||||
x[2] = aabb[2] + (aabb[5]-aabb[2]) * mju_Halton(j, 5);
|
x[2] = aabb[2] + (aabb[5]-aabb[2]) * mju_Halton(j, 5);
|
||||||
@@ -723,7 +723,9 @@ int mjc_SDF(const mjModel* m, const mjData* d, mjContact* con, int g1, int g2, m
|
|||||||
cnt = addContact(contacts, con, x, pos2true, squat2, dist, cnt, m, &sdf, (mjData*)d);
|
cnt = addContact(contacts, con, x, pos2true, squat2, dist, cnt, m, &sdf, (mjData*)d);
|
||||||
|
|
||||||
// SHOULD NOT OCCUR
|
// SHOULD NOT OCCUR
|
||||||
if (cnt>mjMAXCONPAIR) mjERROR("too many contact points");
|
if (cnt > mjMAXCONPAIR) {
|
||||||
|
mjERROR("too many contact points");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cnt;
|
return cnt;
|
||||||
|
|||||||
@@ -124,11 +124,11 @@ int mj_isDual(const mjModel* m) {
|
|||||||
// assign/clamp contact friction parameters
|
// assign/clamp contact friction parameters
|
||||||
void mj_assignFriction(const mjModel* m, mjtNum* target, const mjtNum* source) {
|
void mj_assignFriction(const mjModel* m, mjtNum* target, const mjtNum* source) {
|
||||||
if (mjENABLED(mjENBL_OVERRIDE)) {
|
if (mjENABLED(mjENBL_OVERRIDE)) {
|
||||||
for (int i=0; i<5; i++) {
|
for (int i=0; i < 5; i++) {
|
||||||
target[i] = mju_max(mjMINMU, m->opt.o_friction[i]);
|
target[i] = mju_max(mjMINMU, m->opt.o_friction[i]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i=0; i<5; i++) {
|
for (int i=0; i < 5; i++) {
|
||||||
target[i] = mju_max(mjMINMU, source[i]);
|
target[i] = mju_max(mjMINMU, source[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,20 +181,20 @@ static int mj_elemBodyWeight(const mjModel* m, const mjData* d, int f, int e, in
|
|||||||
// compute inverse distances from contact point to element vertices
|
// compute inverse distances from contact point to element vertices
|
||||||
// save body ids, find vertex v in element
|
// save body ids, find vertex v in element
|
||||||
int vid = -1;
|
int vid = -1;
|
||||||
for (int i=0; i<=dim; i++) {
|
for (int i=0; i <= dim; i++) {
|
||||||
mjtNum dist = mju_dist3(point, vert+3*edata[i]);
|
mjtNum dist = mju_dist3(point, vert+3*edata[i]);
|
||||||
weight[i] = 1.0/(mju_max(mjMINVAL, dist));
|
weight[i] = 1.0/(mju_max(mjMINVAL, dist));
|
||||||
body[i] = m->flex_vertbodyid[m->flex_vertadr[f] + edata[i]];
|
body[i] = m->flex_vertbodyid[m->flex_vertadr[f] + edata[i]];
|
||||||
|
|
||||||
// check if element vertex matches v
|
// check if element vertex matches v
|
||||||
if (edata[i]==v) {
|
if (edata[i] == v) {
|
||||||
vid = i;
|
vid = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// v found in e: skip and shift remaining
|
// v found in e: skip and shift remaining
|
||||||
if (vid>=0) {
|
if (vid >= 0) {
|
||||||
while (vid<dim) {
|
while (vid < dim) {
|
||||||
weight[vid] = weight[vid+1];
|
weight[vid] = weight[vid+1];
|
||||||
body[vid] = body[vid+1];
|
body[vid] = body[vid+1];
|
||||||
vid++;
|
vid++;
|
||||||
@@ -242,9 +242,9 @@ int mj_addContact(const mjModel* m, mjData* d, const mjContact* con) {
|
|||||||
|
|
||||||
// add #size rows to constraint Jacobian; set pos, margin, frictionloss, type, id
|
// add #size rows to constraint Jacobian; set pos, margin, frictionloss, type, id
|
||||||
static void mj_addConstraint(const mjModel* m, mjData* d,
|
static void mj_addConstraint(const mjModel* m, mjData* d,
|
||||||
const mjtNum* jac, const mjtNum* pos,
|
const mjtNum* jac, const mjtNum* pos,
|
||||||
const mjtNum* margin, mjtNum frictionloss,
|
const mjtNum* margin, mjtNum frictionloss,
|
||||||
int size, int type, int id, int NV, const int* chain) {
|
int size, int type, int id, int NV, const int* chain) {
|
||||||
int empty, nv = m->nv, nefc = d->nefc;
|
int empty, nv = m->nv, nefc = d->nefc;
|
||||||
int *nnz = d->efc_J_rownnz, *adr = d->efc_J_rowadr, *ind = d->efc_J_colind;
|
int *nnz = d->efc_J_rownnz, *adr = d->efc_J_rowadr, *ind = d->efc_J_colind;
|
||||||
mjtNum *J = d->efc_J;
|
mjtNum *J = d->efc_J;
|
||||||
@@ -665,7 +665,7 @@ void mj_instantiateEquality(const mjModel* m, mjData* d) {
|
|||||||
flex_edgenum = m->flex_edgenum[id[0]];
|
flex_edgenum = m->flex_edgenum[id[0]];
|
||||||
|
|
||||||
// add one constraint per edge
|
// add one constraint per edge
|
||||||
for (int e=flex_edgeadr; e<flex_edgeadr+flex_edgenum; e++) {
|
for (int e=flex_edgeadr; e < flex_edgeadr+flex_edgenum; e++) {
|
||||||
// position error
|
// position error
|
||||||
cpos[0] = d->flexedge_length[e] - m->flexedge_length0[e];
|
cpos[0] = d->flexedge_length[e] - m->flexedge_length0[e];
|
||||||
|
|
||||||
@@ -930,14 +930,14 @@ void mj_instantiateContact(const mjModel* m, mjData* d) {
|
|||||||
con->efc_address = d->nefc;
|
con->efc_address = d->nefc;
|
||||||
|
|
||||||
// special case: single body on each side
|
// special case: single body on each side
|
||||||
if ((con->geom[0]>=0 || con->vert[0]>=0) &&
|
if ((con->geom[0] >= 0 || con->vert[0] >= 0) &&
|
||||||
(con->geom[1]>=0 || con->vert[1]>=0)) {
|
(con->geom[1] >= 0 || con->vert[1] >= 0)) {
|
||||||
// get bodies
|
// get bodies
|
||||||
int bid[2];
|
int bid[2];
|
||||||
for (int side=0; side < 2; side++) {
|
for (int side=0; side < 2; side++) {
|
||||||
bid[side] = (con->geom[side]>=0) ?
|
bid[side] = (con->geom[side] >= 0) ?
|
||||||
m->geom_bodyid[con->geom[side]] :
|
m->geom_bodyid[con->geom[side]] :
|
||||||
m->flex_vertbodyid[m->flex_vertadr[con->flex[side]] + con->vert[side]];
|
m->flex_vertbodyid[m->flex_vertadr[con->flex[side]] + con->vert[side]];
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute Jacobian differences
|
// compute Jacobian differences
|
||||||
@@ -956,16 +956,16 @@ void mj_instantiateContact(const mjModel* m, mjData* d) {
|
|||||||
int nb = 0;
|
int nb = 0;
|
||||||
int bid[8];
|
int bid[8];
|
||||||
mjtNum bweight[8];
|
mjtNum bweight[8];
|
||||||
for (int side=0; side<2; side++) {
|
for (int side=0; side < 2; side++) {
|
||||||
// geom
|
// geom
|
||||||
if (con->geom[side]>=0) {
|
if (con->geom[side] >= 0) {
|
||||||
bid[nb] = m->geom_bodyid[con->geom[side]];
|
bid[nb] = m->geom_bodyid[con->geom[side]];
|
||||||
bweight[nb] = side ? +1 : -1;
|
bweight[nb] = side ? +1 : -1;
|
||||||
nb++;
|
nb++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// flex vert
|
// flex vert
|
||||||
else if (con->vert[side]>=0) {
|
else if (con->vert[side] >= 0) {
|
||||||
bid[nb] = m->flex_vertbodyid[m->flex_vertadr[con->flex[side]] + con->vert[side]];
|
bid[nb] = m->flex_vertbodyid[m->flex_vertadr[con->flex[side]] + con->vert[side]];
|
||||||
bweight[nb] = side ? +1 : -1;
|
bweight[nb] = side ? +1 : -1;
|
||||||
nb++;
|
nb++;
|
||||||
@@ -977,7 +977,7 @@ void mj_instantiateContact(const mjModel* m, mjData* d) {
|
|||||||
con->vert[1-side], con->pos, bid+nb, bweight+nb);
|
con->vert[1-side], con->pos, bid+nb, bweight+nb);
|
||||||
|
|
||||||
// negative sign for first side of contact
|
// negative sign for first side of contact
|
||||||
if (side==0) {
|
if (side == 0) {
|
||||||
mju_scl(bweight+nb, bweight+nb, -1, nw);
|
mju_scl(bweight+nb, bweight+nb, -1, nw);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -986,7 +986,7 @@ void mj_instantiateContact(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// combine weighted Jacobians
|
// combine weighted Jacobians
|
||||||
NV = mj_jacSum(m, d, chain, nb, bid, bweight, con->pos, jacdif, dim>3);
|
NV = mj_jacSum(m, d, chain, nb, bid, bweight, con->pos, jacdif, dim > 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip contact if no DOFs affected
|
// skip contact if no DOFs affected
|
||||||
@@ -1068,7 +1068,7 @@ void mj_diagApprox(const mjModel* m, mjData* d) {
|
|||||||
id = d->efc_id[i];
|
id = d->efc_id[i];
|
||||||
|
|
||||||
// clear edge counter
|
// clear edge counter
|
||||||
if (d->efc_type[i]!=mjEQ_FLEX) {
|
if (d->efc_type[i] != mjEQ_FLEX) {
|
||||||
edgecnt = 0;
|
edgecnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1139,31 +1139,33 @@ void mj_diagApprox(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// add the average translation and rotation components from both sides
|
// add the average translation and rotation components from both sides
|
||||||
tran = rot = 0;
|
tran = rot = 0;
|
||||||
for (int side=0; side<2; side++) {
|
for (int side=0; side < 2; side++) {
|
||||||
// get bodies and weights
|
// get bodies and weights
|
||||||
int nb, bid[4];
|
int nb, bid[4];
|
||||||
mjtNum bweight[4];
|
mjtNum bweight[4];
|
||||||
|
|
||||||
// geom
|
// geom
|
||||||
if (con->geom[side]>=0) {
|
if (con->geom[side] >= 0) {
|
||||||
bid[0] = m->geom_bodyid[con->geom[side]];
|
bid[0] = m->geom_bodyid[con->geom[side]];
|
||||||
bweight[0] = 1;
|
bweight[0] = 1;
|
||||||
nb = 1;
|
nb = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// flex vert
|
// flex vert
|
||||||
} else if (con->vert[side]>=0) {
|
else if (con->vert[side] >= 0) {
|
||||||
bid[0] = m->flex_vertbodyid[m->flex_vertadr[con->flex[side]] + con->vert[side]];
|
bid[0] = m->flex_vertbodyid[m->flex_vertadr[con->flex[side]] + con->vert[side]];
|
||||||
bweight[0] = 1;
|
bweight[0] = 1;
|
||||||
nb = 1;
|
nb = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// flex elem
|
// flex elem
|
||||||
} else {
|
else {
|
||||||
nb = mj_elemBodyWeight(m, d, con->flex[side], con->elem[side],
|
nb = mj_elemBodyWeight(m, d, con->flex[side], con->elem[side],
|
||||||
con->vert[1-side], con->pos, bid, bweight);
|
con->vert[1-side], con->pos, bid, bweight);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add weighted average over bodies
|
// add weighted average over bodies
|
||||||
for (int k=0; k<nb; k++) {
|
for (int k=0; k < nb; k++) {
|
||||||
tran += m->body_invweight0[2*bid[k]] * bweight[k];
|
tran += m->body_invweight0[2*bid[k]] * bweight[k];
|
||||||
rot += m->body_invweight0[2*bid[k]+1] * bweight[k];
|
rot += m->body_invweight0[2*bid[k]+1] * bweight[k];
|
||||||
}
|
}
|
||||||
@@ -1188,7 +1190,7 @@ void mj_diagApprox(const mjModel* m, mjData* d) {
|
|||||||
else {
|
else {
|
||||||
for (int j=0; j < dim-1; j++) {
|
for (int j=0; j < dim-1; j++) {
|
||||||
fri = con->friction[j];
|
fri = con->friction[j];
|
||||||
dA[i+2*j] = dA[i+2*j+1] = tran + fri*fri*(j<2 ? tran : rot);
|
dA[i+2*j] = dA[i+2*j+1] = tran + fri*fri*(j < 2 ? tran : rot);
|
||||||
}
|
}
|
||||||
|
|
||||||
// processed 2*dim-2 elements in one i-loop iteration; advance counter
|
// processed 2*dim-2 elements in one i-loop iteration; advance counter
|
||||||
@@ -1401,7 +1403,7 @@ void mj_makeImpedance(const mjModel* m, mjData* d) {
|
|||||||
// elliptic contacts use solreffriction in non-normal directions, if non-zero
|
// elliptic contacts use solreffriction in non-normal directions, if non-zero
|
||||||
int elliptic_friction = (tp == mjCNSTR_CONTACT_ELLIPTIC) && (j > 0);
|
int elliptic_friction = (tp == mjCNSTR_CONTACT_ELLIPTIC) && (j > 0);
|
||||||
mjtNum* ref = elliptic_friction && (solreffriction[0] || solreffriction[1]) ?
|
mjtNum* ref = elliptic_friction && (solreffriction[0] || solreffriction[1]) ?
|
||||||
solreffriction : solref;
|
solreffriction : solref;
|
||||||
|
|
||||||
// friction: K = 0
|
// friction: K = 0
|
||||||
if (tp == mjCNSTR_FRICTION_DOF || tp == mjCNSTR_FRICTION_TENDON || elliptic_friction) {
|
if (tp == mjCNSTR_FRICTION_DOF || tp == mjCNSTR_FRICTION_TENDON || elliptic_friction) {
|
||||||
@@ -1526,7 +1528,7 @@ static int mj_jacSumCount(const mjModel* m, mjData* d, int* chain,
|
|||||||
NV = mj_bodyChain(m, body[0], chain);
|
NV = mj_bodyChain(m, body[0], chain);
|
||||||
|
|
||||||
// accumulate remaining
|
// accumulate remaining
|
||||||
for (int i=1; i<n; i++) {
|
for (int i=1; i < n; i++) {
|
||||||
// get body chain
|
// get body chain
|
||||||
int bodyNV = mj_bodyChain(m, body[i], bodychain);
|
int bodyNV = mj_bodyChain(m, body[i], bodychain);
|
||||||
if (!bodyNV) {
|
if (!bodyNV) {
|
||||||
@@ -1649,7 +1651,7 @@ static int mj_ne(const mjModel* m, mjData* d, int* nnz) {
|
|||||||
flex_edgenum = m->flex_edgenum[id[0]];
|
flex_edgenum = m->flex_edgenum[id[0]];
|
||||||
|
|
||||||
// process edges of this flex
|
// process edges of this flex
|
||||||
for (int e=flex_edgeadr; e<flex_edgeadr+flex_edgenum; e++) {
|
for (int e=flex_edgeadr; e < flex_edgeadr+flex_edgenum; e++) {
|
||||||
int b1 = m->flex_vertbodyid[m->flex_vertadr[id[0]] + m->flex_edge[2*e]];
|
int b1 = m->flex_vertbodyid[m->flex_vertadr[id[0]] + m->flex_edge[2*e]];
|
||||||
int b2 = m->flex_vertbodyid[m->flex_vertadr[id[0]] + m->flex_edge[2*e+1]];
|
int b2 = m->flex_vertbodyid[m->flex_vertadr[id[0]] + m->flex_edge[2*e+1]];
|
||||||
|
|
||||||
@@ -1665,7 +1667,7 @@ static int mj_ne(const mjModel* m, mjData* d, int* nnz) {
|
|||||||
|
|
||||||
// accumulate counts; flex NV already accumulated
|
// accumulate counts; flex NV already accumulated
|
||||||
ne += mj_addConstraintCount(m, size, NV);
|
ne += mj_addConstraintCount(m, size, NV);
|
||||||
nnze += (m->eq_type[i]==mjEQ_FLEX) ? NV : size*NV;
|
nnze += (m->eq_type[i] == mjEQ_FLEX) ? NV : size*NV;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1805,7 +1807,7 @@ static int mj_nc(const mjModel* m, mjData* d, int* nnz) {
|
|||||||
int nb = 0, bid[8];
|
int nb = 0, bid[8];
|
||||||
for (int side=0; side < 2; side++) {
|
for (int side=0; side < 2; side++) {
|
||||||
// geom
|
// geom
|
||||||
if (con->geom[side]>=0) {
|
if (con->geom[side] >= 0) {
|
||||||
bid[nb++] = m->geom_bodyid[con->geom[side]];
|
bid[nb++] = m->geom_bodyid[con->geom[side]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1819,7 +1821,7 @@ static int mj_nc(const mjModel* m, mjData* d, int* nnz) {
|
|||||||
int f = con->flex[side];
|
int f = con->flex[side];
|
||||||
int fdim = m->flex_dim[f];
|
int fdim = m->flex_dim[f];
|
||||||
const int* edata = m->flex_elem + m->flex_elemdataadr[f] + con->elem[side]*(fdim+1);
|
const int* edata = m->flex_elem + m->flex_elemdataadr[f] + con->elem[side]*(fdim+1);
|
||||||
for (int k=0; k<=fdim; k++) {
|
for (int k=0; k <= fdim; k++) {
|
||||||
bid[nb++] = m->flex_vertbodyid[m->flex_vertadr[f] + edata[k]];
|
bid[nb++] = m->flex_vertbodyid[m->flex_vertadr[f] + edata[k]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -284,7 +284,7 @@ void mj_camlight(const mjModel* m, mjData* d) {
|
|||||||
// adjust for mode
|
// adjust for mode
|
||||||
switch ((mjtCamLight) m->cam_mode[i]) {
|
switch ((mjtCamLight) m->cam_mode[i]) {
|
||||||
case mjCAMLIGHT_FIXED:
|
case mjCAMLIGHT_FIXED:
|
||||||
break;
|
break;
|
||||||
case mjCAMLIGHT_TRACK:
|
case mjCAMLIGHT_TRACK:
|
||||||
case mjCAMLIGHT_TRACKCOM:
|
case mjCAMLIGHT_TRACKCOM:
|
||||||
// fixed global orientation
|
// fixed global orientation
|
||||||
@@ -393,15 +393,15 @@ void mj_updateDynamicBVH(const mjModel* m, mjData* d, int bvhadr, int bvhnum) {
|
|||||||
mju_zeroInt(modified, bvhnum);
|
mju_zeroInt(modified, bvhnum);
|
||||||
|
|
||||||
// mark leafs as modified
|
// mark leafs as modified
|
||||||
for (int i=0; i<bvhnum; i++) {
|
for (int i=0; i < bvhnum; i++) {
|
||||||
if (m->bvh_nodeid[bvhadr+i]>=0) {
|
if (m->bvh_nodeid[bvhadr+i] >= 0) {
|
||||||
modified[i] = 1;
|
modified[i] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update non-leafs in backward pass (parents come before children)
|
// update non-leafs in backward pass (parents come before children)
|
||||||
for (int i=bvhnum-1; i>=0; i--) {
|
for (int i=bvhnum-1; i >= 0; i--) {
|
||||||
if (m->bvh_nodeid[bvhadr+i]<0) {
|
if (m->bvh_nodeid[bvhadr+i] < 0) {
|
||||||
int child1 = m->bvh_child[2*(bvhadr+i)];
|
int child1 = m->bvh_child[2*(bvhadr+i)];
|
||||||
int child2 = m->bvh_child[2*(bvhadr+i)+1];
|
int child2 = m->bvh_child[2*(bvhadr+i)+1];
|
||||||
|
|
||||||
@@ -413,13 +413,13 @@ void mj_updateDynamicBVH(const mjModel* m, mjData* d, int bvhadr, int bvhnum) {
|
|||||||
|
|
||||||
// compute new (min, max)
|
// compute new (min, max)
|
||||||
mjtNum xmin[3], xmax[3];
|
mjtNum xmin[3], xmax[3];
|
||||||
for (int k=0; k<3; k++) {
|
for (int k=0; k < 3; k++) {
|
||||||
xmin[k] = mju_min(aabb1[k] - aabb1[k+3], aabb2[k] - aabb2[k+3]);
|
xmin[k] = mju_min(aabb1[k] - aabb1[k+3], aabb2[k] - aabb2[k+3]);
|
||||||
xmax[k] = mju_max(aabb1[k] + aabb1[k+3], aabb2[k] + aabb2[k+3]);
|
xmax[k] = mju_max(aabb1[k] + aabb1[k+3], aabb2[k] + aabb2[k+3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert to (center, size)
|
// convert to (center, size)
|
||||||
for (int k=0; k<3; k++) {
|
for (int k=0; k < 3; k++) {
|
||||||
aabb[k] = 0.5*(xmax[k]+xmin[k]);
|
aabb[k] = 0.5*(xmax[k]+xmin[k]);
|
||||||
aabb[k+3] = 0.5*(xmax[k]-xmin[k]);
|
aabb[k+3] = 0.5*(xmax[k]-xmin[k]);
|
||||||
}
|
}
|
||||||
@@ -446,20 +446,20 @@ void mj_flex(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute Cartesian positions of flex vertices
|
// compute Cartesian positions of flex vertices
|
||||||
for (int f=0; f<m->nflex; f++) {
|
for (int f=0; f < m->nflex; f++) {
|
||||||
int vstart = m->flex_vertadr[f];
|
int vstart = m->flex_vertadr[f];
|
||||||
int vend = m->flex_vertadr[f] + m->flex_vertnum[f];
|
int vend = m->flex_vertadr[f] + m->flex_vertnum[f];
|
||||||
|
|
||||||
// centered: copy body position
|
// centered: copy body position
|
||||||
if (m->flex_centered[f]) {
|
if (m->flex_centered[f]) {
|
||||||
for (int i=vstart; i<vend; i++) {
|
for (int i=vstart; i < vend; i++) {
|
||||||
mju_copy3(d->flexvert_xpos+3*i, d->xpos+3*m->flex_vertbodyid[i]);
|
mju_copy3(d->flexvert_xpos+3*i, d->xpos+3*m->flex_vertbodyid[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// non-centered: map from local to global
|
// non-centered: map from local to global
|
||||||
else {
|
else {
|
||||||
for (int i=vstart; i<vend; i++) {
|
for (int i=vstart; i < vend; i++) {
|
||||||
mju_rotVecMat(d->flexvert_xpos+3*i, m->flex_vert+3*i, d->xmat+9*m->flex_vertbodyid[i]);
|
mju_rotVecMat(d->flexvert_xpos+3*i, m->flex_vert+3*i, d->xmat+9*m->flex_vertbodyid[i]);
|
||||||
mju_addTo3(d->flexvert_xpos+3*i, d->xpos+3*m->flex_vertbodyid[i]);
|
mju_addTo3(d->flexvert_xpos+3*i, d->xpos+3*m->flex_vertbodyid[i]);
|
||||||
}
|
}
|
||||||
@@ -467,11 +467,11 @@ void mj_flex(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute flex element aabb
|
// compute flex element aabb
|
||||||
for (int f=0; f<m->nflex; f++) {
|
for (int f=0; f < m->nflex; f++) {
|
||||||
int dim = m->flex_dim[f];
|
int dim = m->flex_dim[f];
|
||||||
|
|
||||||
// process elements of this flex
|
// process elements of this flex
|
||||||
for (int e=0; e<m->flex_elemnum[f]; e++) {
|
for (int e=0; e < m->flex_elemnum[f]; e++) {
|
||||||
const int* edata = m->flex_elem + m->flex_elemdataadr[f] + e*(dim+1);
|
const int* edata = m->flex_elem + m->flex_elemdataadr[f] + e*(dim+1);
|
||||||
const mjtNum* vert = d->flexvert_xpos + 3*m->flex_vertadr[f];
|
const mjtNum* vert = d->flexvert_xpos + 3*m->flex_vertadr[f];
|
||||||
|
|
||||||
@@ -479,8 +479,8 @@ void mj_flex(const mjModel* m, mjData* d) {
|
|||||||
mjtNum xmin[3], xmax[3];
|
mjtNum xmin[3], xmax[3];
|
||||||
mju_copy3(xmin, vert+3*edata[0]);
|
mju_copy3(xmin, vert+3*edata[0]);
|
||||||
mju_copy3(xmax, vert+3*edata[0]);
|
mju_copy3(xmax, vert+3*edata[0]);
|
||||||
for (int i=1; i<=dim; i++) {
|
for (int i=1; i <= dim; i++) {
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
mjtNum value = vert[3*edata[i]+j];
|
mjtNum value = vert[3*edata[i]+j];
|
||||||
xmin[j] = mju_min(xmin[j], value);
|
xmin[j] = mju_min(xmin[j], value);
|
||||||
xmax[j] = mju_max(xmax[j], value);
|
xmax[j] = mju_max(xmax[j], value);
|
||||||
@@ -500,14 +500,14 @@ void mj_flex(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// update flex bhv_aabb_dyn if needed
|
// update flex bhv_aabb_dyn if needed
|
||||||
if (!mjDISABLED(mjDSBL_MIDPHASE)) {
|
if (!mjDISABLED(mjDSBL_MIDPHASE)) {
|
||||||
for (int f=0; f<m->nflex; f++) {
|
for (int f=0; f < m->nflex; f++) {
|
||||||
if (m->flex_bvhadr[f]>=0) {
|
if (m->flex_bvhadr[f] >= 0) {
|
||||||
int flex_bvhadr = m->flex_bvhadr[f];
|
int flex_bvhadr = m->flex_bvhadr[f];
|
||||||
int flex_bvhnum = m->flex_bvhnum[f];
|
int flex_bvhnum = m->flex_bvhnum[f];
|
||||||
|
|
||||||
// copy element aabbs to bhv leaf aabbs
|
// copy element aabbs to bhv leaf aabbs
|
||||||
for (int i=flex_bvhadr; i<flex_bvhadr+flex_bvhnum; i++) {
|
for (int i=flex_bvhadr; i < flex_bvhadr+flex_bvhnum; i++) {
|
||||||
if (m->bvh_nodeid[i]>=0) {
|
if (m->bvh_nodeid[i] >= 0) {
|
||||||
mju_copy(d->bvh_aabb_dyn + 6*(i - m->nbvhstatic),
|
mju_copy(d->bvh_aabb_dyn + 6*(i - m->nbvhstatic),
|
||||||
d->flexelem_aabb + 6*(m->flex_elemadr[f] + m->bvh_nodeid[i]), 6);
|
d->flexelem_aabb + 6*(m->flex_elemadr[f] + m->bvh_nodeid[i]), 6);
|
||||||
}
|
}
|
||||||
@@ -535,18 +535,18 @@ void mj_flex(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute lengths and Jacobians of edges
|
// compute lengths and Jacobians of edges
|
||||||
for (int f=0; f<m->nflex; f++) {
|
for (int f=0; f < m->nflex; f++) {
|
||||||
// skip if edges cannot generate forces
|
// skip if edges cannot generate forces
|
||||||
if (m->flex_rigid[f] ||
|
if (m->flex_rigid[f] ||
|
||||||
(m->flex_edgeequality[f]==0 &&
|
(m->flex_edgeequality[f] == 0 &&
|
||||||
m->flex_edgestiffness[f]==0 && m->flex_edgedamping[f]==0)) {
|
m->flex_edgestiffness[f] == 0 && m->flex_edgedamping[f] == 0)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// process edges of this flex
|
// process edges of this flex
|
||||||
int vbase = m->flex_vertadr[f];
|
int vbase = m->flex_vertadr[f];
|
||||||
int ebase = m->flex_edgeadr[f];
|
int ebase = m->flex_edgeadr[f];
|
||||||
for (int e=0; e<m->flex_edgenum[f]; e++) {
|
for (int e=0; e < m->flex_edgenum[f]; e++) {
|
||||||
int v1 = m->flex_edge[2*(ebase+e)];
|
int v1 = m->flex_edge[2*(ebase+e)];
|
||||||
int v2 = m->flex_edge[2*(ebase+e)+1];
|
int v2 = m->flex_edge[2*(ebase+e)+1];
|
||||||
int b1 = m->flex_vertbodyid[vbase+v1];
|
int b1 = m->flex_vertbodyid[vbase+v1];
|
||||||
@@ -562,7 +562,7 @@ void mj_flex(const mjModel* m, mjData* d) {
|
|||||||
// sparse edge Jacobian
|
// sparse edge Jacobian
|
||||||
if (issparse) {
|
if (issparse) {
|
||||||
// set rowadr
|
// set rowadr
|
||||||
if (ebase+e>0) {
|
if (ebase+e > 0) {
|
||||||
rowadr[ebase+e] = rowadr[ebase+e-1] + rownnz[ebase+e-1];
|
rowadr[ebase+e] = rowadr[ebase+e-1] + rownnz[ebase+e-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1110,7 +1110,7 @@ void mj_transmission(const mjModel* m, mjData* d) {
|
|||||||
const mjContact* con = d->contact+j;
|
const mjContact* con = d->contact+j;
|
||||||
|
|
||||||
// contact involving flex, continue
|
// contact involving flex, continue
|
||||||
if (con->geom[0]<0 || con->geom[1]<0) {
|
if (con->geom[0] < 0 || con->geom[1] < 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1772,7 +1772,7 @@ void mj_rnePostConstraint(const mjModel* m, mjData* d) {
|
|||||||
con = d->contact+i;
|
con = d->contact+i;
|
||||||
|
|
||||||
// skip contact involving flex
|
// skip contact involving flex
|
||||||
if (con->geom[0]<0 || con->geom[1]<0) {
|
if (con->geom[0] < 0 || con->geom[1] < 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1471,12 +1471,12 @@ void mjd_passive_vel(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// flex edge damping
|
// flex edge damping
|
||||||
for (int f=0; f<m->nflex; f++) {
|
for (int f=0; f < m->nflex; f++) {
|
||||||
if (!m->flex_rigid[f] && m->flex_edgedamping[f]) {
|
if (!m->flex_rigid[f] && m->flex_edgedamping[f]) {
|
||||||
mjtNum B = -m->flex_edgedamping[f];
|
mjtNum B = -m->flex_edgedamping[f];
|
||||||
|
|
||||||
// process edges of this flex
|
// process edges of this flex
|
||||||
for (int e=m->flex_edgeadr[f]; e<m->flex_edgeadr[f]+m->flex_edgenum[f]; e++) {
|
for (int e=m->flex_edgeadr[f]; e < m->flex_edgeadr[f]+m->flex_edgenum[f]; e++) {
|
||||||
// add sparse or dense
|
// add sparse or dense
|
||||||
if (mj_isSparse(m)) {
|
if (mj_isSparse(m)) {
|
||||||
addJTBJSparse(m, d, d->flexedge_J, &B, 1, e,
|
addJTBJSparse(m, d, d->flexedge_J, &B, 1, e,
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ void mj_fwdVelocity(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// returns the next act given the current act_dot, after clamping
|
// returns the next act given the current act_dot, after clamping
|
||||||
static mjtNum nextActivation(const mjModel* m, const mjData* d,
|
static mjtNum nextActivation(const mjModel* m, const mjData* d,
|
||||||
int actuator_id, int act_adr, mjtNum act_dot) {
|
int actuator_id, int act_adr, mjtNum act_dot) {
|
||||||
mjtNum act = d->act[act_adr];
|
mjtNum act = d->act[act_adr];
|
||||||
|
|
||||||
if (m->actuator_dyntype[actuator_id] == mjDYN_FILTEREXACT) {
|
if (m->actuator_dyntype[actuator_id] == mjDYN_FILTEREXACT) {
|
||||||
@@ -569,7 +569,7 @@ void mj_solCG_island_multithreaded(const mjModel* m, mjData* d) {
|
|||||||
mj_markStack(d);
|
mj_markStack(d);
|
||||||
// allocate array of arguments to be passed to threads
|
// allocate array of arguments to be passed to threads
|
||||||
mjSolIslandArgs* sol_cg_island_args =
|
mjSolIslandArgs* sol_cg_island_args =
|
||||||
mj_stackAllocByte(d, sizeof(mjSolIslandArgs) * d->nisland, _Alignof(mjSolIslandArgs));
|
mj_stackAllocByte(d, sizeof(mjSolIslandArgs) * d->nisland, _Alignof(mjSolIslandArgs));
|
||||||
mjTask* tasks = mj_stackAllocByte(d, sizeof(mjTask) * d->nisland, _Alignof(mjTask));
|
mjTask* tasks = mj_stackAllocByte(d, sizeof(mjTask) * d->nisland, _Alignof(mjTask));
|
||||||
|
|
||||||
for (int island = 0; island < d->nisland; ++island) {
|
for (int island = 0; island < d->nisland; ++island) {
|
||||||
|
|||||||
+33
-36
@@ -444,19 +444,16 @@ static int safeAddToBufferSize(intptr_t* offset, size_t* nbuffer,
|
|||||||
|
|
||||||
// allocate and initialize mjModel structure
|
// allocate and initialize mjModel structure
|
||||||
mjModel* mj_makeModel(
|
mjModel* mj_makeModel(
|
||||||
int nq, int nv, int nu, int na, int nbody, int nbvh, int nbvhstatic,
|
int nq, int nv, int nu, int na, int nbody, int nbvh, int nbvhstatic, int nbvhdynamic, int njnt,
|
||||||
int nbvhdynamic, int njnt, int ngeom, int nsite, int ncam, int nlight,
|
int ngeom, int nsite, int ncam, int nlight, int nflex, int nflexvert, int nflexedge,
|
||||||
int nflex, int nflexvert, int nflexedge, int nflexelem, int nflexelemdata,
|
int nflexelem, int nflexelemdata, int nflexshelldata, int nflexevpair, int nflextexcoord,
|
||||||
int nflexshelldata, int nflexevpair, int nflextexcoord, int nmesh,
|
int nmesh, int nmeshvert, int nmeshnormal, int nmeshtexcoord, int nmeshface, int nmeshgraph,
|
||||||
int nmeshvert, int nmeshnormal, int nmeshtexcoord, int nmeshface,
|
int nskin, int nskinvert, int nskintexvert, int nskinface, int nskinbone, int nskinbonevert,
|
||||||
int nmeshgraph, int nskin, int nskinvert, int nskintexvert, int nskinface,
|
int nhfield, int nhfielddata, int ntex, int ntexdata, int nmat, int npair, int nexclude, int neq,
|
||||||
int nskinbone, int nskinbonevert, int nhfield, int nhfielddata, int ntex,
|
int ntendon, int nwrap, int nsensor, int nnumeric, int nnumericdata, int ntext, int ntextdata,
|
||||||
int ntexdata, int nmat, int npair, int nexclude, int neq, int ntendon,
|
int ntuple, int ntupledata, int nkey, int nmocap, int nplugin, int npluginattr, int nuser_body,
|
||||||
int nwrap, int nsensor, int nnumeric, int nnumericdata, int ntext,
|
int nuser_jnt, int nuser_geom, int nuser_site, int nuser_cam, int nuser_tendon,
|
||||||
int ntextdata, int ntuple, int ntupledata, int nkey, int nmocap,
|
int nuser_actuator, int nuser_sensor, int nnames, int npaths) {
|
||||||
int nplugin, int npluginattr, int nuser_body, int nuser_jnt, int nuser_geom,
|
|
||||||
int nuser_site, int nuser_cam, int nuser_tendon, int nuser_actuator,
|
|
||||||
int nuser_sensor, int nnames, int npaths) {
|
|
||||||
intptr_t offset = 0;
|
intptr_t offset = 0;
|
||||||
|
|
||||||
// allocate mjModel
|
// allocate mjModel
|
||||||
@@ -602,21 +599,21 @@ mjModel* mj_copyModel(mjModel* dest, const mjModel* src) {
|
|||||||
// allocate new model if needed
|
// allocate new model if needed
|
||||||
if (!dest) {
|
if (!dest) {
|
||||||
dest = mj_makeModel(
|
dest = mj_makeModel(
|
||||||
src->nq, src->nv, src->nu, src->na, src->nbody, src->nbvh,
|
src->nq, src->nv, src->nu, src->na, src->nbody, src->nbvh,
|
||||||
src->nbvhstatic, src->nbvhdynamic, src->njnt, src->ngeom, src->nsite,
|
src->nbvhstatic, src->nbvhdynamic, src->njnt, src->ngeom, src->nsite,
|
||||||
src->ncam, src->nlight, src->nflex, src->nflexvert, src->nflexedge,
|
src->ncam, src->nlight, src->nflex, src->nflexvert, src->nflexedge,
|
||||||
src->nflexelem, src->nflexelemdata, src->nflexshelldata,
|
src->nflexelem, src->nflexelemdata, src->nflexshelldata,
|
||||||
src->nflexevpair, src->nflextexcoord, src->nmesh, src->nmeshvert,
|
src->nflexevpair, src->nflextexcoord, src->nmesh, src->nmeshvert,
|
||||||
src->nmeshnormal, src->nmeshtexcoord, src->nmeshface, src->nmeshgraph,
|
src->nmeshnormal, src->nmeshtexcoord, src->nmeshface, src->nmeshgraph,
|
||||||
src->nskin, src->nskinvert, src->nskintexvert, src->nskinface,
|
src->nskin, src->nskinvert, src->nskintexvert, src->nskinface,
|
||||||
src->nskinbone, src->nskinbonevert, src->nhfield, src->nhfielddata,
|
src->nskinbone, src->nskinbonevert, src->nhfield, src->nhfielddata,
|
||||||
src->ntex, src->ntexdata, src->nmat, src->npair, src->nexclude,
|
src->ntex, src->ntexdata, src->nmat, src->npair, src->nexclude,
|
||||||
src->neq, src->ntendon, src->nwrap, src->nsensor, src->nnumeric,
|
src->neq, src->ntendon, src->nwrap, src->nsensor, src->nnumeric,
|
||||||
src->nnumericdata, src->ntext, src->ntextdata, src->ntuple,
|
src->nnumericdata, src->ntext, src->ntextdata, src->ntuple,
|
||||||
src->ntupledata, src->nkey, src->nmocap, src->nplugin, src->npluginattr,
|
src->ntupledata, src->nkey, src->nmocap, src->nplugin, src->npluginattr,
|
||||||
src->nuser_body, src->nuser_jnt, src->nuser_geom, src->nuser_site,
|
src->nuser_body, src->nuser_jnt, src->nuser_geom, src->nuser_site,
|
||||||
src->nuser_cam, src->nuser_tendon, src->nuser_actuator,
|
src->nuser_cam, src->nuser_tendon, src->nuser_actuator,
|
||||||
src->nuser_sensor, src->nnames, src->npaths);
|
src->nuser_sensor, src->nnames, src->npaths);
|
||||||
}
|
}
|
||||||
if (!dest) {
|
if (!dest) {
|
||||||
mjERROR("failed to make mjModel. Invalid sizes.");
|
mjERROR("failed to make mjModel. Invalid sizes.");
|
||||||
@@ -1333,8 +1330,8 @@ static inline void* stackallocinternal(mjData* d, mjStackInfo* stack_info, size_
|
|||||||
char* prev_pstack_ptr = (char*)(stack_info->top);
|
char* prev_pstack_ptr = (char*)(stack_info->top);
|
||||||
size_t prev_misalign = (uintptr_t)prev_pstack_ptr % _Alignof(size_t);
|
size_t prev_misalign = (uintptr_t)prev_pstack_ptr % _Alignof(size_t);
|
||||||
size_t* prev_usage_ptr =
|
size_t* prev_usage_ptr =
|
||||||
(size_t*)(prev_pstack_ptr +
|
(size_t*)(prev_pstack_ptr +
|
||||||
(prev_misalign ? _Alignof(size_t) - prev_misalign : 0));
|
(prev_misalign ? _Alignof(size_t) - prev_misalign : 0));
|
||||||
ASAN_UNPOISON_MEMORY_REGION(prev_usage_ptr, sizeof(size_t));
|
ASAN_UNPOISON_MEMORY_REGION(prev_usage_ptr, sizeof(size_t));
|
||||||
usage = current_alloc_usage + *prev_usage_ptr;
|
usage = current_alloc_usage + *prev_usage_ptr;
|
||||||
ASAN_POISON_MEMORY_REGION(prev_usage_ptr, sizeof(size_t));
|
ASAN_POISON_MEMORY_REGION(prev_usage_ptr, sizeof(size_t));
|
||||||
@@ -1343,7 +1340,7 @@ static inline void* stackallocinternal(mjData* d, mjStackInfo* stack_info, size_
|
|||||||
// store new stack usage in the red zone
|
// store new stack usage in the red zone
|
||||||
size_t misalign = new_top_ptr % _Alignof(size_t);
|
size_t misalign = new_top_ptr % _Alignof(size_t);
|
||||||
size_t* usage_ptr =
|
size_t* usage_ptr =
|
||||||
(size_t*)(new_top_ptr + (misalign ? _Alignof(size_t) - misalign : 0));
|
(size_t*)(new_top_ptr + (misalign ? _Alignof(size_t) - misalign : 0));
|
||||||
ASAN_UNPOISON_MEMORY_REGION(usage_ptr, sizeof(size_t));
|
ASAN_UNPOISON_MEMORY_REGION(usage_ptr, sizeof(size_t));
|
||||||
*usage_ptr = usage;
|
*usage_ptr = usage;
|
||||||
ASAN_POISON_MEMORY_REGION(usage_ptr, sizeof(size_t));
|
ASAN_POISON_MEMORY_REGION(usage_ptr, sizeof(size_t));
|
||||||
@@ -1403,7 +1400,7 @@ __attribute__((always_inline))
|
|||||||
static inline void markstackinternal(mjData* d, mjStackInfo* stack_info) {
|
static inline void markstackinternal(mjData* d, mjStackInfo* stack_info) {
|
||||||
size_t top_old = stack_info->top;
|
size_t top_old = stack_info->top;
|
||||||
mjStackFrame* s =
|
mjStackFrame* s =
|
||||||
(mjStackFrame*) stackallocinternal(d, stack_info, sizeof(mjStackFrame), _Alignof(mjStackFrame));
|
(mjStackFrame*) stackallocinternal(d, stack_info, sizeof(mjStackFrame), _Alignof(mjStackFrame));
|
||||||
s->pbase = stack_info->stack_base;
|
s->pbase = stack_info->stack_base;
|
||||||
s->pstack = top_old;
|
s->pstack = top_old;
|
||||||
#ifdef ADDRESS_SANITIZER
|
#ifdef ADDRESS_SANITIZER
|
||||||
@@ -1447,8 +1444,8 @@ static inline void freestackinternal(mjStackInfo* stack_info) {
|
|||||||
#define mjSYMBOLIZELEN 256
|
#define mjSYMBOLIZELEN 256
|
||||||
char dbginfo[mjSYMBOLIZELEN];
|
char dbginfo[mjSYMBOLIZELEN];
|
||||||
__sanitizer_symbolize_pc(
|
__sanitizer_symbolize_pc(
|
||||||
s->pc, "mj_markStack %F at %S has no corresponding mj_freeStack",
|
s->pc, "mj_markStack %F at %S has no corresponding mj_freeStack",
|
||||||
dbginfo, sizeof(dbginfo));
|
dbginfo, sizeof(dbginfo));
|
||||||
dbginfo[mjSYMBOLIZELEN - 1] = '\0';
|
dbginfo[mjSYMBOLIZELEN - 1] = '\0';
|
||||||
mjERROR("%s", dbginfo);
|
mjERROR("%s", dbginfo);
|
||||||
#undef mjSYMBOLIZELEN
|
#undef mjSYMBOLIZELEN
|
||||||
@@ -1584,7 +1581,7 @@ static void _resetData(const mjModel* m, mjData* d, unsigned char debug_value) {
|
|||||||
mju_zero(d->qvel, m->nv);
|
mju_zero(d->qvel, m->nv);
|
||||||
mju_zero(d->act, m->na);
|
mju_zero(d->act, m->na);
|
||||||
mju_zero(d->ctrl, m->nu);
|
mju_zero(d->ctrl, m->nu);
|
||||||
for (int i=0; i<m->neq; i++) d->eq_active[i] = m->eq_active0[i];
|
for (int i=0; i < m->neq; i++) d->eq_active[i] = m->eq_active0[i];
|
||||||
mju_zero(d->qfrc_applied, m->nv);
|
mju_zero(d->qfrc_applied, m->nv);
|
||||||
mju_zero(d->xfrc_applied, 6*m->nbody);
|
mju_zero(d->xfrc_applied, 6*m->nbody);
|
||||||
mju_zero(d->qacc, m->nv);
|
mju_zero(d->qacc, m->nv);
|
||||||
@@ -1966,7 +1963,7 @@ const char* mj_validateReferences(const mjModel* m) {
|
|||||||
if (m->geom_dataid[i] >= m->nhfield || m->geom_dataid[i] < -1) {
|
if (m->geom_dataid[i] >= m->nhfield || m->geom_dataid[i] < -1) {
|
||||||
return "Invalid model: geom_dataid out of bounds.";
|
return "Invalid model: geom_dataid out of bounds.";
|
||||||
}
|
}
|
||||||
} else if ((m->geom_type[i]==mjGEOM_MESH) || (m->geom_type[i]==mjGEOM_SDF)) {
|
} else if ((m->geom_type[i] == mjGEOM_MESH) || (m->geom_type[i] == mjGEOM_SDF)) {
|
||||||
if (m->geom_dataid[i] >= m->nmesh || m->geom_dataid[i] < -1) {
|
if (m->geom_dataid[i] >= m->nmesh || m->geom_dataid[i] < -1) {
|
||||||
return "Invalid model: geom_dataid out of bounds.";
|
return "Invalid model: geom_dataid out of bounds.";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ void mj_passive(const mjModel* m, mjData* d) {
|
|||||||
stiffness = m->jnt_stiffness[i];
|
stiffness = m->jnt_stiffness[i];
|
||||||
|
|
||||||
// disabled : nothing to do
|
// disabled : nothing to do
|
||||||
if (stiffness==0) {
|
if (stiffness == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ void mj_passive(const mjModel* m, mjData* d) {
|
|||||||
damping = m->flex_edgedamping[f];
|
damping = m->flex_edgedamping[f];
|
||||||
|
|
||||||
// disabled or rigid: nothing to do
|
// disabled or rigid: nothing to do
|
||||||
if (m->flex_rigid[f] || (stiffness==0 && damping==0)) {
|
if (m->flex_rigid[f] || (stiffness == 0 && damping == 0)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -362,7 +362,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->nbody) fprintf(fp, "\n");
|
if (m->nbody) fprintf(fp, "\n");
|
||||||
|
|
||||||
// BVHs
|
// BVHs
|
||||||
for (int i=0; i<m->nbvh; i++) {
|
for (int i=0; i < m->nbvh; i++) {
|
||||||
fprintf(fp, "\nBVH %d:\n", i);
|
fprintf(fp, "\nBVH %d:\n", i);
|
||||||
object_class = &m->nbvh;
|
object_class = &m->nbvh;
|
||||||
MJMODEL_POINTERS
|
MJMODEL_POINTERS
|
||||||
@@ -428,7 +428,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->nlight) fprintf(fp, "\n");
|
if (m->nlight) fprintf(fp, "\n");
|
||||||
|
|
||||||
// flexes
|
// flexes
|
||||||
for (int i=0; i<m->nflex; i++) {
|
for (int i=0; i < m->nflex; i++) {
|
||||||
fprintf(fp, "\nFLEX %d:\n", i);
|
fprintf(fp, "\nFLEX %d:\n", i);
|
||||||
fprintf(fp, " " NAME_FORMAT, "name");
|
fprintf(fp, " " NAME_FORMAT, "name");
|
||||||
fprintf(fp, " %s\n", m->names + m->name_flexadr[i]);
|
fprintf(fp, " %s\n", m->names + m->name_flexadr[i]);
|
||||||
|
|||||||
+25
-25
@@ -844,15 +844,15 @@ mjtNum mju_rayFlex(const mjModel* m, const mjData* d, int flex_layer, mjtByte fl
|
|||||||
// compute bounding box
|
// compute bounding box
|
||||||
mjtNum box[3][2] = {{0, 0}, {0, 0}, {0, 0}};
|
mjtNum box[3][2] = {{0, 0}, {0, 0}, {0, 0}};
|
||||||
mjtNum* vert = d->flexvert_xpos + 3*m->flex_vertadr[flexid];
|
mjtNum* vert = d->flexvert_xpos + 3*m->flex_vertadr[flexid];
|
||||||
for (int i=0; i<m->flex_vertnum[flexid]; i++) {
|
for (int i=0; i < m->flex_vertnum[flexid]; i++) {
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
// update minimum along side j
|
// update minimum along side j
|
||||||
if (box[j][0]>vert[3*i+j] || i==0) {
|
if (box[j][0] > vert[3*i+j] || i == 0) {
|
||||||
box[j][0] = vert[3*i+j];
|
box[j][0] = vert[3*i+j];
|
||||||
}
|
}
|
||||||
|
|
||||||
// update maximum along side j
|
// update maximum along side j
|
||||||
if (box[j][1]<vert[3*i+j] || i==0) {
|
if (box[j][1] < vert[3*i+j] || i == 0) {
|
||||||
box[j][1] = vert[3*i+j];
|
box[j][1] = vert[3*i+j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -860,28 +860,28 @@ mjtNum mju_rayFlex(const mjModel* m, const mjData* d, int flex_layer, mjtByte fl
|
|||||||
|
|
||||||
// adjust box for radius
|
// adjust box for radius
|
||||||
mjtNum radius = m->flex_radius[flexid];
|
mjtNum radius = m->flex_radius[flexid];
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
box[j][0] -= radius;
|
box[j][0] -= radius;
|
||||||
box[j][1] += radius;
|
box[j][1] += radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
// construct box geom
|
// construct box geom
|
||||||
mjtNum pos[3], size[3], mat[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
|
mjtNum pos[3], size[3], mat[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
pos[j] = 0.5*(box[j][0]+box[j][1]);
|
pos[j] = 0.5*(box[j][0]+box[j][1]);
|
||||||
size[j] = 0.5*(box[j][1]-box[j][0]);
|
size[j] = 0.5*(box[j][1]-box[j][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply bounding-box filter
|
// apply bounding-box filter
|
||||||
if (ray_box(pos, mat, size, pnt, vec, NULL)<0) {
|
if (ray_box(pos, mat, size, pnt, vec, NULL) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// construct basis vectors of normal plane
|
// construct basis vectors of normal plane
|
||||||
mjtNum b0[3] = {1, 1, 1}, b1[3];
|
mjtNum b0[3] = {1, 1, 1}, b1[3];
|
||||||
if (mju_abs(vec[0])>=mju_abs(vec[1]) && mju_abs(vec[0])>=mju_abs(vec[2])) {
|
if (mju_abs(vec[0]) >= mju_abs(vec[1]) && mju_abs(vec[0]) >= mju_abs(vec[2])) {
|
||||||
b0[0] = 0;
|
b0[0] = 0;
|
||||||
} else if (mju_abs(vec[1])>=mju_abs(vec[2])) {
|
} else if (mju_abs(vec[1]) >= mju_abs(vec[2])) {
|
||||||
b0[1] = 0;
|
b0[1] = 0;
|
||||||
} else {
|
} else {
|
||||||
b0[2] = 0;
|
b0[2] = 0;
|
||||||
@@ -895,9 +895,9 @@ mjtNum mju_rayFlex(const mjModel* m, const mjData* d, int flex_layer, mjtByte fl
|
|||||||
mjtNum x = -1;
|
mjtNum x = -1;
|
||||||
|
|
||||||
// check edges if rendered, or if skin
|
// check edges if rendered, or if skin
|
||||||
if (flg_edge || (dim>1 && flg_skin)) {
|
if (flg_edge || (dim > 1 && flg_skin)) {
|
||||||
for (int e=m->flex_edgeadr[flexid];
|
int edge_end = m->flex_edgeadr[flexid]+m->flex_edgenum[flexid];
|
||||||
e<m->flex_edgeadr[flexid]+m->flex_edgenum[flexid]; e++) {
|
for (int e=m->flex_edgeadr[flexid]; e < edge_end; e++) {
|
||||||
// get vertices for this edge
|
// get vertices for this edge
|
||||||
mjtNum* v1 = d->flexvert_xpos + 3*(m->flex_vertadr[flexid]+m->flex_edge[2*e]);
|
mjtNum* v1 = d->flexvert_xpos + 3*(m->flex_vertadr[flexid]+m->flex_edge[2*e]);
|
||||||
mjtNum* v2 = d->flexvert_xpos + 3*(m->flex_vertadr[flexid]+m->flex_edge[2*e+1]);
|
mjtNum* v2 = d->flexvert_xpos + 3*(m->flex_vertadr[flexid]+m->flex_edge[2*e+1]);
|
||||||
@@ -916,7 +916,7 @@ mjtNum mju_rayFlex(const mjModel* m, const mjData* d, int flex_layer, mjtByte fl
|
|||||||
mjtNum sol = mju_rayGeom(pos, mat, size, pnt, vec, mjGEOM_CAPSULE);
|
mjtNum sol = mju_rayGeom(pos, mat, size, pnt, vec, mjGEOM_CAPSULE);
|
||||||
|
|
||||||
// update
|
// update
|
||||||
if (sol>=0 && (x<0 || sol<x)) {
|
if (sol >= 0 && (x < 0 || sol < x)) {
|
||||||
x = sol;
|
x = sol;
|
||||||
|
|
||||||
// construct intersection point
|
// construct intersection point
|
||||||
@@ -935,8 +935,8 @@ mjtNum mju_rayFlex(const mjModel* m, const mjData* d, int flex_layer, mjtByte fl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check vertices if rendered (and edges not checked)
|
// check vertices if rendered (and edges not checked)
|
||||||
else if (flg_vert && !(dim>1 && flg_skin)) {
|
else if (flg_vert && !(dim > 1 && flg_skin)) {
|
||||||
for (int v=0; v<m->flex_vertnum[flexid]; v++) {
|
for (int v=0; v < m->flex_vertnum[flexid]; v++) {
|
||||||
// get vertex
|
// get vertex
|
||||||
mjtNum* vpos = d->flexvert_xpos + 3*(m->flex_vertadr[flexid] + v);
|
mjtNum* vpos = d->flexvert_xpos + 3*(m->flex_vertadr[flexid] + v);
|
||||||
|
|
||||||
@@ -947,7 +947,7 @@ mjtNum mju_rayFlex(const mjModel* m, const mjData* d, int flex_layer, mjtByte fl
|
|||||||
mjtNum sol = mju_rayGeom(vpos, NULL, size, pnt, vec, mjGEOM_SPHERE);
|
mjtNum sol = mju_rayGeom(vpos, NULL, size, pnt, vec, mjGEOM_SPHERE);
|
||||||
|
|
||||||
// update
|
// update
|
||||||
if (sol>=0 && (x<0 || sol<x)) {
|
if (sol >= 0 && (x < 0 || sol < x)) {
|
||||||
x = sol;
|
x = sol;
|
||||||
*vertid = v;
|
*vertid = v;
|
||||||
}
|
}
|
||||||
@@ -955,11 +955,11 @@ mjtNum mju_rayFlex(const mjModel* m, const mjData* d, int flex_layer, mjtByte fl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check faces if rendered
|
// check faces if rendered
|
||||||
if (dim>1 && (flg_face || flg_skin)) {
|
if (dim > 1 && (flg_face || flg_skin)) {
|
||||||
for (int e=0; e<m->flex_elemnum[flexid]; e++) {
|
for (int e=0; e < m->flex_elemnum[flexid]; e++) {
|
||||||
// skip if 3D element is not visible
|
// skip if 3D element is not visible
|
||||||
int elayer = m->flex_elemlayer[m->flex_elemadr[flexid]+e];
|
int elayer = m->flex_elemlayer[m->flex_elemadr[flexid]+e];
|
||||||
if (dim==3 && ((flg_skin && elayer>0) || (!flg_skin && elayer!=flex_layer))) {
|
if (dim == 3 && ((flg_skin && elayer > 0) || (!flg_skin && elayer != flex_layer))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -968,22 +968,22 @@ mjtNum mju_rayFlex(const mjModel* m, const mjData* d, int flex_layer, mjtByte fl
|
|||||||
mjtNum* v1 = d->flexvert_xpos + 3*(m->flex_vertadr[flexid] + edata[0]);
|
mjtNum* v1 = d->flexvert_xpos + 3*(m->flex_vertadr[flexid] + edata[0]);
|
||||||
mjtNum* v2 = d->flexvert_xpos + 3*(m->flex_vertadr[flexid] + edata[1]);
|
mjtNum* v2 = d->flexvert_xpos + 3*(m->flex_vertadr[flexid] + edata[1]);
|
||||||
mjtNum* v3 = d->flexvert_xpos + 3*(m->flex_vertadr[flexid] + edata[2]);
|
mjtNum* v3 = d->flexvert_xpos + 3*(m->flex_vertadr[flexid] + edata[2]);
|
||||||
mjtNum* v4 = dim==2 ? NULL : d->flexvert_xpos + 3*(m->flex_vertadr[flexid] + edata[3]);
|
mjtNum* v4 = dim == 2 ? NULL : d->flexvert_xpos + 3*(m->flex_vertadr[flexid] + edata[3]);
|
||||||
mjtNum* vptr[4][3] = {{v1, v2, v3}, {v1, v2, v4}, {v1, v3, v4}, {v2, v3, v4}};
|
mjtNum* vptr[4][3] = {{v1, v2, v3}, {v1, v2, v4}, {v1, v3, v4}, {v2, v3, v4}};
|
||||||
int vid[4][3] = {{0, 1, 2}, {0, 1, 3}, {0, 2, 3}, {1, 2, 3}};
|
int vid[4][3] = {{0, 1, 2}, {0, 1, 3}, {0, 2, 3}, {1, 2, 3}};
|
||||||
|
|
||||||
// process triangles of this element
|
// process triangles of this element
|
||||||
for (int i=0; i<(dim==2?1:4); i++) {
|
for (int i=0; i < (dim == 2?1:4); i++) {
|
||||||
// copy vertices into triangle representation
|
// copy vertices into triangle representation
|
||||||
mjtNum v[3][3];
|
mjtNum v[3][3];
|
||||||
for (int j=0; j<3; j++)
|
for (int j=0; j < 3; j++)
|
||||||
mju_copy3(v[j], vptr[i][j]);
|
mju_copy3(v[j], vptr[i][j]);
|
||||||
|
|
||||||
// intersect ray with triangle
|
// intersect ray with triangle
|
||||||
mjtNum sol = ray_triangle(v, pnt, vec, b0, b1);
|
mjtNum sol = ray_triangle(v, pnt, vec, b0, b1);
|
||||||
|
|
||||||
// update
|
// update
|
||||||
if (sol>=0 && (x<0 || sol<x)) {
|
if (sol >= 0 && (x < 0 || sol < x)) {
|
||||||
x = sol;
|
x = sol;
|
||||||
|
|
||||||
// construct intersection point
|
// construct intersection point
|
||||||
@@ -996,9 +996,9 @@ mjtNum mju_rayFlex(const mjModel* m, const mjData* d, int flex_layer, mjtByte fl
|
|||||||
mju_dist3(v[1], intersect),
|
mju_dist3(v[1], intersect),
|
||||||
mju_dist3(v[2], intersect)
|
mju_dist3(v[2], intersect)
|
||||||
};
|
};
|
||||||
if (dist[0]<=dist[1] && dist[0]<=dist[2]) {
|
if (dist[0] <= dist[1] && dist[0] <= dist[2]) {
|
||||||
*vertid = edata[vid[i][0]];
|
*vertid = edata[vid[i][0]];
|
||||||
} else if (dist[1]<=dist[2]){
|
} else if (dist[1] <= dist[2]){
|
||||||
*vertid = edata[vid[i][1]];
|
*vertid = edata[vid[i][1]];
|
||||||
} else {
|
} else {
|
||||||
*vertid = edata[vid[i][2]];
|
*vertid = edata[vid[i][2]];
|
||||||
|
|||||||
+16
-16
@@ -208,8 +208,8 @@ static void cam_project(mjtNum sensordata[2], const mjtNum target_xpos[3],
|
|||||||
rotation[1][1] = 1;
|
rotation[1][1] = 1;
|
||||||
rotation[2][2] = 1;
|
rotation[2][2] = 1;
|
||||||
rotation[3][3] = 1;
|
rotation[3][3] = 1;
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
rotation[i][j] = cam_xmat[j*3+i];
|
rotation[i][j] = cam_xmat[j*3+i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,11 +237,11 @@ static void cam_project(mjtNum sensordata[2], const mjtNum target_xpos[3],
|
|||||||
|
|
||||||
// projection matrix (3x4): product of all 4 matrices
|
// projection matrix (3x4): product of all 4 matrices
|
||||||
mjtNum proj[3][4] = {0};
|
mjtNum proj[3][4] = {0};
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
for (int k=0; k<4; k++) {
|
for (int k=0; k < 4; k++) {
|
||||||
for (int l=0; l<4; l++) {
|
for (int l=0; l < 4; l++) {
|
||||||
for (int n=0; n<4; n++) {
|
for (int n=0; n < 4; n++) {
|
||||||
proj[i][n] += image[i][j] * focal[j][k] * rotation[k][l] * translation[l][n];
|
proj[i][n] += image[i][j] * focal[j][k] * rotation[k][l] * translation[l][n];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -256,10 +256,10 @@ static void cam_project(mjtNum sensordata[2], const mjtNum target_xpos[3],
|
|||||||
// project world coordinates into pixel space, see:
|
// project world coordinates into pixel space, see:
|
||||||
// https://en.wikipedia.org/wiki/3D_projection#Mathematical_formula
|
// https://en.wikipedia.org/wiki/3D_projection#Mathematical_formula
|
||||||
mjtNum pixel_coord_hom[3] = {0};
|
mjtNum pixel_coord_hom[3] = {0};
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
for (int j=0; j<4; j++) {
|
for (int j=0; j < 4; j++) {
|
||||||
pixel_coord_hom[i] += proj[i][j] * pos_hom[j];
|
pixel_coord_hom[i] += proj[i][j] * pos_hom[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// avoid dividing by tiny numbers
|
// avoid dividing by tiny numbers
|
||||||
@@ -716,8 +716,8 @@ void mj_sensorAcc(const mjModel* m, mjData* d) {
|
|||||||
// contact pointer, contacting bodies (-1 for flex)
|
// contact pointer, contacting bodies (-1 for flex)
|
||||||
con = d->contact + j;
|
con = d->contact + j;
|
||||||
int conbody[2];
|
int conbody[2];
|
||||||
for (int k=0; k<2; k++) {
|
for (int k=0; k < 2; k++) {
|
||||||
conbody[k] = (con->geom[k]>=0) ? m->geom_bodyid[con->geom[k]] : -1;
|
conbody[k] = (con->geom[k] >= 0) ? m->geom_bodyid[con->geom[k]] : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// select contacts involving sensorized body
|
// select contacts involving sensorized body
|
||||||
@@ -950,14 +950,14 @@ void mj_energyPos(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// add flex-level springs
|
// add flex-level springs
|
||||||
if (!mjDISABLED(mjDSBL_PASSIVE)) {
|
if (!mjDISABLED(mjDSBL_PASSIVE)) {
|
||||||
for (int i=0; i<m->nflex; i++) {
|
for (int i=0; i < m->nflex; i++) {
|
||||||
stiffness = m->flex_edgestiffness[i];
|
stiffness = m->flex_edgestiffness[i];
|
||||||
if (m->flex_rigid[i] || stiffness==0) {
|
if (m->flex_rigid[i] || stiffness == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// process edges of this flex
|
// process edges of this flex
|
||||||
for (int e=m->flex_edgeadr[i]; e<m->flex_edgeadr[i]+m->flex_edgenum[i]; e++) {
|
for (int e=m->flex_edgeadr[i]; e < m->flex_edgeadr[i]+m->flex_edgenum[i]; e++) {
|
||||||
mjtNum displacement = m->flexedge_length0[e] - d->flexedge_length[e];
|
mjtNum displacement = m->flexedge_length0[e] - d->flexedge_length[e];
|
||||||
d->energy[0] += 0.5*stiffness*displacement*displacement;
|
d->energy[0] += 0.5*stiffness*displacement*displacement;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,14 +115,14 @@ static void set0(mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// compute body_invweight0
|
// compute body_invweight0
|
||||||
m->body_invweight0[0] = m->body_invweight0[1] = 0.0;
|
m->body_invweight0[0] = m->body_invweight0[1] = 0.0;
|
||||||
for (int i=1; i<m->nbody; i++) {
|
for (int i=1; i < m->nbody; i++) {
|
||||||
// static bodies: zero invweight0
|
// static bodies: zero invweight0
|
||||||
if (m->body_weldid[i] == 0) {
|
if (m->body_weldid[i] == 0) {
|
||||||
m->body_invweight0[2*i] = m->body_invweight0[2*i+1] = 0;
|
m->body_invweight0[2*i] = m->body_invweight0[2*i+1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// accelerate simple bodies with no rotations
|
// accelerate simple bodies with no rotations
|
||||||
else if (m->body_simple[i]==2) {
|
else if (m->body_simple[i] == 2) {
|
||||||
mjtNum mass = m->body_mass[i];
|
mjtNum mass = m->body_mass[i];
|
||||||
if (!mass) { // SHOULD NOT OCCUR
|
if (!mass) { // SHOULD NOT OCCUR
|
||||||
mjERROR("moving body %d has 0 mass", i);
|
mjERROR("moving body %d has 0 mass", i);
|
||||||
@@ -147,7 +147,7 @@ static void set0(mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute dof_invweight0
|
// compute dof_invweight0
|
||||||
for (int i=0; i<m->njnt; i++) {
|
for (int i=0; i < m->njnt; i++) {
|
||||||
// simple body with no rotations: no off-diagonal inertia
|
// simple body with no rotations: no off-diagonal inertia
|
||||||
if (m->body_simple[m->jnt_bodyid[i]] == 2) {
|
if (m->body_simple[m->jnt_bodyid[i]] == 2) {
|
||||||
int id = m->jnt_dofadr[i];
|
int id = m->jnt_dofadr[i];
|
||||||
@@ -200,14 +200,14 @@ static void set0(mjModel* m, mjData* d) {
|
|||||||
// compute flexedge_invweight0, tendon_invweight0, actuator_acc0
|
// compute flexedge_invweight0, tendon_invweight0, actuator_acc0
|
||||||
if (nv) {
|
if (nv) {
|
||||||
// compute flexedge_invweight0
|
// compute flexedge_invweight0
|
||||||
for (int f=0; f<m->nflex; f++) {
|
for (int f=0; f < m->nflex; f++) {
|
||||||
for (int i=m->flex_edgeadr[f]; i<m->flex_edgeadr[f]+m->flex_edgenum[f]; i++) {
|
for (int i=m->flex_edgeadr[f]; i < m->flex_edgeadr[f]+m->flex_edgenum[f]; i++) {
|
||||||
// bodies connected by edge
|
// bodies connected by edge
|
||||||
int b1 = m->flex_vertbodyid[m->flex_vertadr[f] + m->flex_edge[2*i]];
|
int b1 = m->flex_vertbodyid[m->flex_vertadr[f] + m->flex_edge[2*i]];
|
||||||
int b2 = m->flex_vertbodyid[m->flex_vertadr[f] + m->flex_edge[2*i+1]];
|
int b2 = m->flex_vertbodyid[m->flex_vertadr[f] + m->flex_edge[2*i+1]];
|
||||||
|
|
||||||
// accelerate edges that connect simple bodies with no rotations
|
// accelerate edges that connect simple bodies with no rotations
|
||||||
if (m->body_simple[b1]==2 && m->body_simple[b2]==2) {
|
if (m->body_simple[b1] == 2 && m->body_simple[b2] == 2) {
|
||||||
m->flexedge_invweight0[i] = (1/m->body_mass[b1] + 1/m->body_mass[b2])/2;
|
m->flexedge_invweight0[i] = (1/m->body_mass[b1] + 1/m->body_mass[b2])/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,7 +217,7 @@ static void set0(mjModel* m, mjData* d) {
|
|||||||
if (mj_isSparse(m)) {
|
if (mj_isSparse(m)) {
|
||||||
mju_zero(tmp, nv);
|
mju_zero(tmp, nv);
|
||||||
int end = d->flexedge_J_rowadr[i] + d->flexedge_J_rownnz[i];
|
int end = d->flexedge_J_rowadr[i] + d->flexedge_J_rownnz[i];
|
||||||
for (int j=d->flexedge_J_rowadr[i]; j<end; j++) {
|
for (int j=d->flexedge_J_rowadr[i]; j < end; j++) {
|
||||||
tmp[d->flexedge_J_colind[j]] = d->flexedge_J[j];
|
tmp[d->flexedge_J_colind[j]] = d->flexedge_J[j];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -232,7 +232,7 @@ static void set0(mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute tendon_invweight0
|
// compute tendon_invweight0
|
||||||
for (int i=0; i<m->ntendon; i++) {
|
for (int i=0; i < m->ntendon; i++) {
|
||||||
// make dense vector into tmp
|
// make dense vector into tmp
|
||||||
if (mj_isSparse(m)) {
|
if (mj_isSparse(m)) {
|
||||||
mju_zero(tmp, nv);
|
mju_zero(tmp, nv);
|
||||||
@@ -422,8 +422,8 @@ static void setStat(mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// adjust body size for flex edges involving body
|
// adjust body size for flex edges involving body
|
||||||
for (int f=0; f<m->nflex; f++) {
|
for (int f=0; f < m->nflex; f++) {
|
||||||
for (int e=m->flex_edgeadr[f]; e<m->flex_edgeadr[f]+m->flex_edgenum[f]; e++) {
|
for (int e=m->flex_edgeadr[f]; e < m->flex_edgeadr[f]+m->flex_edgenum[f]; e++) {
|
||||||
int b1 = m->flex_vertbodyid[m->flex_vertadr[f]+m->flex_edge[2*e]];
|
int b1 = m->flex_vertbodyid[m->flex_vertadr[f]+m->flex_edge[2*e]];
|
||||||
int b2 = m->flex_vertbodyid[m->flex_vertadr[f]+m->flex_edge[2*e+1]];
|
int b2 = m->flex_vertbodyid[m->flex_vertadr[f]+m->flex_edge[2*e+1]];
|
||||||
|
|
||||||
|
|||||||
+48
-48
@@ -100,22 +100,22 @@ const char* mjTIMERSTRING[mjNTIMER]= {
|
|||||||
// return size of a single state element
|
// return size of a single state element
|
||||||
static inline int mj_stateElemSize(const mjModel* m, mjtState spec) {
|
static inline int mj_stateElemSize(const mjModel* m, mjtState spec) {
|
||||||
switch (spec) {
|
switch (spec) {
|
||||||
case mjSTATE_TIME: return 1;
|
case mjSTATE_TIME: return 1;
|
||||||
case mjSTATE_QPOS: return m->nq;
|
case mjSTATE_QPOS: return m->nq;
|
||||||
case mjSTATE_QVEL: return m->nv;
|
case mjSTATE_QVEL: return m->nv;
|
||||||
case mjSTATE_ACT: return m->na;
|
case mjSTATE_ACT: return m->na;
|
||||||
case mjSTATE_WARMSTART: return m->nv;
|
case mjSTATE_WARMSTART: return m->nv;
|
||||||
case mjSTATE_CTRL: return m->nu;
|
case mjSTATE_CTRL: return m->nu;
|
||||||
case mjSTATE_QFRC_APPLIED: return m->nv;
|
case mjSTATE_QFRC_APPLIED: return m->nv;
|
||||||
case mjSTATE_XFRC_APPLIED: return 6*m->nbody;
|
case mjSTATE_XFRC_APPLIED: return 6*m->nbody;
|
||||||
case mjSTATE_EQ_ACTIVE: return m->neq; // mjtByte, stored as mjtNum in state vector
|
case mjSTATE_EQ_ACTIVE: return m->neq; // mjtByte, stored as mjtNum in state vector
|
||||||
case mjSTATE_MOCAP_POS: return 3*m->nmocap;
|
case mjSTATE_MOCAP_POS: return 3*m->nmocap;
|
||||||
case mjSTATE_MOCAP_QUAT: return 4*m->nmocap;
|
case mjSTATE_MOCAP_QUAT: return 4*m->nmocap;
|
||||||
case mjSTATE_USERDATA: return m->nuserdata;
|
case mjSTATE_USERDATA: return m->nuserdata;
|
||||||
case mjSTATE_PLUGIN: return m->npluginstate;
|
case mjSTATE_PLUGIN: return m->npluginstate;
|
||||||
default:
|
default:
|
||||||
mjERROR("invalid state element %u", spec);
|
mjERROR("invalid state element %u", spec);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,21 +124,21 @@ static inline int mj_stateElemSize(const mjModel* m, mjtState spec) {
|
|||||||
// return pointer to a single state element
|
// return pointer to a single state element
|
||||||
static inline mjtNum* mj_stateElemPtr(const mjModel* m, mjData* d, mjtState spec) {
|
static inline mjtNum* mj_stateElemPtr(const mjModel* m, mjData* d, mjtState spec) {
|
||||||
switch (spec) {
|
switch (spec) {
|
||||||
case mjSTATE_TIME: return &d->time;
|
case mjSTATE_TIME: return &d->time;
|
||||||
case mjSTATE_QPOS: return d->qpos;
|
case mjSTATE_QPOS: return d->qpos;
|
||||||
case mjSTATE_QVEL: return d->qvel;
|
case mjSTATE_QVEL: return d->qvel;
|
||||||
case mjSTATE_ACT: return d->act;
|
case mjSTATE_ACT: return d->act;
|
||||||
case mjSTATE_WARMSTART: return d->qacc_warmstart;
|
case mjSTATE_WARMSTART: return d->qacc_warmstart;
|
||||||
case mjSTATE_CTRL: return d->ctrl;
|
case mjSTATE_CTRL: return d->ctrl;
|
||||||
case mjSTATE_QFRC_APPLIED: return d->qfrc_applied;
|
case mjSTATE_QFRC_APPLIED: return d->qfrc_applied;
|
||||||
case mjSTATE_XFRC_APPLIED: return d->xfrc_applied;
|
case mjSTATE_XFRC_APPLIED: return d->xfrc_applied;
|
||||||
case mjSTATE_MOCAP_POS: return d->mocap_pos;
|
case mjSTATE_MOCAP_POS: return d->mocap_pos;
|
||||||
case mjSTATE_MOCAP_QUAT: return d->mocap_quat;
|
case mjSTATE_MOCAP_QUAT: return d->mocap_quat;
|
||||||
case mjSTATE_USERDATA: return d->userdata;
|
case mjSTATE_USERDATA: return d->userdata;
|
||||||
case mjSTATE_PLUGIN: return d->plugin_state;
|
case mjSTATE_PLUGIN: return d->plugin_state;
|
||||||
default:
|
default:
|
||||||
mjERROR("invalid state element %u", spec);
|
mjERROR("invalid state element %u", spec);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +248,7 @@ int mj_mergeChain(const mjModel* m, int* chain, int b1, int b2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// neither body is movable: empty chain
|
// neither body is movable: empty chain
|
||||||
if (b1==0 && b2==0) {
|
if (b1 == 0 && b2 == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,19 +257,19 @@ int mj_mergeChain(const mjModel* m, int* chain, int b1, int b2) {
|
|||||||
da2 = m->body_dofadr[b2] + m->body_dofnum[b2] - 1;
|
da2 = m->body_dofadr[b2] + m->body_dofnum[b2] - 1;
|
||||||
|
|
||||||
// merge chains
|
// merge chains
|
||||||
while (da1>=0 || da2>=0) {
|
while (da1 >= 0 || da2 >= 0) {
|
||||||
chain[NV] = mjMAX(da1, da2);
|
chain[NV] = mjMAX(da1, da2);
|
||||||
if (da1==chain[NV]) {
|
if (da1 == chain[NV]) {
|
||||||
da1 = m->dof_parentid[da1];
|
da1 = m->dof_parentid[da1];
|
||||||
}
|
}
|
||||||
if (da2==chain[NV]) {
|
if (da2 == chain[NV]) {
|
||||||
da2 = m->dof_parentid[da2];
|
da2 = m->dof_parentid[da2];
|
||||||
}
|
}
|
||||||
NV++;
|
NV++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reverse order of chain: make it increasing
|
// reverse order of chain: make it increasing
|
||||||
for (int i=0; i<NV/2; i++) {
|
for (int i=0; i < NV/2; i++) {
|
||||||
int tmp = chain[i];
|
int tmp = chain[i];
|
||||||
chain[i] = chain[NV-i-1];
|
chain[i] = chain[NV-i-1];
|
||||||
chain[NV-i-1] = tmp;
|
chain[NV-i-1] = tmp;
|
||||||
@@ -283,7 +283,7 @@ int mj_mergeChain(const mjModel* m, int* chain, int b1, int b2) {
|
|||||||
// merge dof chains for two simple bodies
|
// merge dof chains for two simple bodies
|
||||||
int mj_mergeChainSimple(const mjModel* m, int* chain, int b1, int b2) {
|
int mj_mergeChainSimple(const mjModel* m, int* chain, int b1, int b2) {
|
||||||
// swap bodies if wrong order
|
// swap bodies if wrong order
|
||||||
if (b1>b2) {
|
if (b1 > b2) {
|
||||||
int tmp = b1;
|
int tmp = b1;
|
||||||
b1 = b2;
|
b1 = b2;
|
||||||
b2 = tmp;
|
b2 = tmp;
|
||||||
@@ -293,17 +293,17 @@ int mj_mergeChainSimple(const mjModel* m, int* chain, int b1, int b2) {
|
|||||||
int n1 = m->body_dofnum[b1], n2 = m->body_dofnum[b2];
|
int n1 = m->body_dofnum[b1], n2 = m->body_dofnum[b2];
|
||||||
|
|
||||||
// both fixed: nothing to do
|
// both fixed: nothing to do
|
||||||
if (n1==0 && n2==0) {
|
if (n1 == 0 && n2 == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy b1 dofs
|
// copy b1 dofs
|
||||||
for (int i=0; i<n1; i++) {
|
for (int i=0; i < n1; i++) {
|
||||||
chain[i] = m->body_dofadr[b1] + i;
|
chain[i] = m->body_dofadr[b1] + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy b2 dofs
|
// copy b2 dofs
|
||||||
for (int i=0; i<n2; i++) {
|
for (int i=0; i < n2; i++) {
|
||||||
chain[n1+i] = m->body_dofadr[b2] + i;
|
chain[n1+i] = m->body_dofadr[b2] + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,7 +317,7 @@ int mj_bodyChain(const mjModel* m, int body, int* chain) {
|
|||||||
// simple body
|
// simple body
|
||||||
if (m->body_simple[body]) {
|
if (m->body_simple[body]) {
|
||||||
int dofnum = m->body_dofnum[body];
|
int dofnum = m->body_dofnum[body];
|
||||||
for (int i=0; i<dofnum; i++) {
|
for (int i=0; i < dofnum; i++) {
|
||||||
chain[i] = m->body_dofadr[body] + i;
|
chain[i] = m->body_dofadr[body] + i;
|
||||||
}
|
}
|
||||||
return dofnum;
|
return dofnum;
|
||||||
@@ -331,7 +331,7 @@ int mj_bodyChain(const mjModel* m, int body, int* chain) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// not movable: empty chain
|
// not movable: empty chain
|
||||||
if (body==0) {
|
if (body == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,13 +340,13 @@ int mj_bodyChain(const mjModel* m, int body, int* chain) {
|
|||||||
int NV = 0;
|
int NV = 0;
|
||||||
|
|
||||||
// construct chain from child to parent
|
// construct chain from child to parent
|
||||||
while (da>=0) {
|
while (da >= 0) {
|
||||||
chain[NV++] = da;
|
chain[NV++] = da;
|
||||||
da = m->dof_parentid[da];
|
da = m->dof_parentid[da];
|
||||||
}
|
}
|
||||||
|
|
||||||
// reverse order of chain: make it increasing
|
// reverse order of chain: make it increasing
|
||||||
for (int i=0; i<NV/2; i++) {
|
for (int i=0; i < NV/2; i++) {
|
||||||
int tmp = chain[i];
|
int tmp = chain[i];
|
||||||
chain[i] = chain[NV-i-1];
|
chain[i] = chain[NV-i-1];
|
||||||
chain[NV-i-1] = tmp;
|
chain[NV-i-1] = tmp;
|
||||||
@@ -737,7 +737,7 @@ int mj_jacSum(const mjModel* m, mjData* d, int* chain,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// accumulate remaining
|
// accumulate remaining
|
||||||
for (int i=1; i<n; i++) {
|
for (int i=1; i < n; i++) {
|
||||||
// get body chain and Jacobian
|
// get body chain and Jacobian
|
||||||
int bodyNV = mj_bodyChain(m, body[i], bodychain);
|
int bodyNV = mj_bodyChain(m, body[i], bodychain);
|
||||||
if (!bodyNV) {
|
if (!bodyNV) {
|
||||||
@@ -762,7 +762,7 @@ int mj_jacSum(const mjModel* m, mjData* d, int* chain,
|
|||||||
mju_scl(jac, jac, weight[0], flg_rot ? 6*nv : 3*nv);
|
mju_scl(jac, jac, weight[0], flg_rot ? 6*nv : 3*nv);
|
||||||
|
|
||||||
// accumulate remaining
|
// accumulate remaining
|
||||||
for (int i=1; i<n; i++) {
|
for (int i=1; i < n; i++) {
|
||||||
mj_jac(m, d, jp, jr, point, body[i]);
|
mj_jac(m, d, jp, jr, point, body[i]);
|
||||||
mju_addToScl(jac, jtmp, weight[i], flg_rot ? 6*nv : 3*nv);
|
mju_addToScl(jac, jtmp, weight[i], flg_rot ? 6*nv : 3*nv);
|
||||||
}
|
}
|
||||||
@@ -1477,13 +1477,13 @@ void mj_applyFT(const mjModel* m, mjData* d,
|
|||||||
// compute J'*f and accumulate
|
// compute J'*f and accumulate
|
||||||
if (force) {
|
if (force) {
|
||||||
mju_mulMatTVec(qforce, jacp, force, 3, NV);
|
mju_mulMatTVec(qforce, jacp, force, 3, NV);
|
||||||
for (int i=0; i<NV; i++) {
|
for (int i=0; i < NV; i++) {
|
||||||
qfrc_target[chain[i]] += qforce[i];
|
qfrc_target[chain[i]] += qforce[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (torque) {
|
if (torque) {
|
||||||
mju_mulMatTVec(qforce, jacr, torque, 3, NV);
|
mju_mulMatTVec(qforce, jacr, torque, 3, NV);
|
||||||
for (int i=0; i<NV; i++) {
|
for (int i=0; i < NV; i++) {
|
||||||
qfrc_target[chain[i]] += qforce[i];
|
qfrc_target[chain[i]] += qforce[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
// stack allocate and initialize new mjArrayList
|
// stack allocate and initialize new mjArrayList
|
||||||
mjArrayList* mju_arrayListCreate(mjData* d, size_t element_size, size_t initial_capacity) {
|
mjArrayList* mju_arrayListCreate(mjData* d, size_t element_size, size_t initial_capacity) {
|
||||||
mjArrayList* array_list = (mjArrayList*) mj_stackAllocByte(
|
mjArrayList* array_list = (mjArrayList*) mj_stackAllocByte(
|
||||||
d, sizeof(mjArrayList), _Alignof(mjArrayList));
|
d, sizeof(mjArrayList), _Alignof(mjArrayList));
|
||||||
initial_capacity = mjMAX(1, initial_capacity);
|
initial_capacity = mjMAX(1, initial_capacity);
|
||||||
array_list->d = d;
|
array_list->d = d;
|
||||||
array_list->element_size = element_size;
|
array_list->element_size = element_size;
|
||||||
@@ -35,7 +35,7 @@ mjArrayList* mju_arrayListCreate(mjData* d, size_t element_size, size_t initial_
|
|||||||
|
|
||||||
// allocate array list buffer
|
// allocate array list buffer
|
||||||
array_list->buffer = (void*) mj_stackAllocByte(
|
array_list->buffer = (void*) mj_stackAllocByte(
|
||||||
d, element_size * initial_capacity, _Alignof(mjtMaxAlign));
|
d, element_size * initial_capacity, _Alignof(mjtMaxAlign));
|
||||||
return array_list;
|
return array_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ void mju_arrayListAdd(mjArrayList* array_list, void* element) {
|
|||||||
if (cursor->next_segment == NULL) {
|
if (cursor->next_segment == NULL) {
|
||||||
// add a new segment with twice the capacity of the last segment
|
// add a new segment with twice the capacity of the last segment
|
||||||
cursor->next_segment = mju_arrayListCreate(
|
cursor->next_segment = mju_arrayListCreate(
|
||||||
cursor->d, cursor->element_size, 2 * cursor->capacity);
|
cursor->d, cursor->element_size, 2 * cursor->capacity);
|
||||||
}
|
}
|
||||||
cursor = cursor->next_segment;
|
cursor = cursor->next_segment;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -630,7 +630,7 @@ static uint32_t _decode(char ch) {
|
|||||||
// returns number of chars written in buf: 4 * [(ndata + 2) / 3] + 1
|
// returns number of chars written in buf: 4 * [(ndata + 2) / 3] + 1
|
||||||
size_t mju_encodeBase64(char* buf, const uint8_t* data, size_t ndata) {
|
size_t mju_encodeBase64(char* buf, const uint8_t* data, size_t ndata) {
|
||||||
static const char *table =
|
static const char *table =
|
||||||
"ABCDEFGHIJKLMNOPQRSTUBWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
"ABCDEFGHIJKLMNOPQRSTUBWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
|
||||||
int i = 0, j = 0;
|
int i = 0, j = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -379,19 +379,19 @@ void mju_addToSparseInc(mjtNum* dst, const mjtNum* src,
|
|||||||
int adrs = 0, adrd = 0, inds = indsrc[0], indd = inddst[0];
|
int adrs = 0, adrd = 0, inds = indsrc[0], indd = inddst[0];
|
||||||
while (1) {
|
while (1) {
|
||||||
// common non-zero index
|
// common non-zero index
|
||||||
if (inds==indd) {
|
if (inds == indd) {
|
||||||
// add
|
// add
|
||||||
dst[adrd] += src[adrs];
|
dst[adrd] += src[adrs];
|
||||||
|
|
||||||
// advance src
|
// advance src
|
||||||
if (++adrs<nnzsrc) {
|
if (++adrs < nnzsrc) {
|
||||||
inds = indsrc[adrs];
|
inds = indsrc[adrs];
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// advance dst
|
// advance dst
|
||||||
if (++adrd<nnzdst) {
|
if (++adrd < nnzdst) {
|
||||||
indd = inddst[adrd];
|
indd = inddst[adrd];
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
@@ -399,8 +399,8 @@ void mju_addToSparseInc(mjtNum* dst, const mjtNum* src,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// src non-zero index smaller: advance src
|
// src non-zero index smaller: advance src
|
||||||
else if (inds<indd) {
|
else if (inds < indd) {
|
||||||
if (++adrs<nnzsrc) {
|
if (++adrs < nnzsrc) {
|
||||||
inds = indsrc[adrs];
|
inds = indsrc[adrs];
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
@@ -409,7 +409,7 @@ void mju_addToSparseInc(mjtNum* dst, const mjtNum* src,
|
|||||||
|
|
||||||
// dst non-zero index smaller: advance dst
|
// dst non-zero index smaller: advance dst
|
||||||
else {
|
else {
|
||||||
if (++adrd<nnzdst) {
|
if (++adrd < nnzdst) {
|
||||||
indd = inddst[adrd];
|
indd = inddst[adrd];
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
@@ -425,8 +425,8 @@ int mju_addToSparseMat(mjtNum* dst, const mjtNum* src, int n, int nrow, mjtNum s
|
|||||||
int dst_nnz, int src_nnz, int* dst_ind, const int* src_ind,
|
int dst_nnz, int src_nnz, int* dst_ind, const int* src_ind,
|
||||||
mjtNum* buf, int* buf_ind) {
|
mjtNum* buf, int* buf_ind) {
|
||||||
// check for identical pattern
|
// check for identical pattern
|
||||||
if (dst_nnz==src_nnz) {
|
if (dst_nnz == src_nnz) {
|
||||||
if (dst_nnz==0) {
|
if (dst_nnz == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (mju_compare(dst_ind, src_ind, dst_nnz)) {
|
if (mju_compare(dst_ind, src_ind, dst_nnz)) {
|
||||||
@@ -442,40 +442,40 @@ int mju_addToSparseMat(mjtNum* dst, const mjtNum* src, int n, int nrow, mjtNum s
|
|||||||
int dadr = dst_nnz ? dst_ind[0] : n+1;
|
int dadr = dst_nnz ? dst_ind[0] : n+1;
|
||||||
|
|
||||||
// merge matrices
|
// merge matrices
|
||||||
while (si<src_nnz || di<dst_nnz) {
|
while (si < src_nnz || di < dst_nnz) {
|
||||||
// both
|
// both
|
||||||
if (sadr==dadr) {
|
if (sadr == dadr) {
|
||||||
for (int k=0; k<nrow; k++) {
|
for (int k=0; k < nrow; k++) {
|
||||||
buf[nrow*nnz + k] = dst[di + k*dst_nnz] + scl*src[si + k*src_nnz];
|
buf[nrow*nnz + k] = dst[di + k*dst_nnz] + scl*src[si + k*src_nnz];
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_ind[nnz++] = sadr;
|
buf_ind[nnz++] = sadr;
|
||||||
si++;
|
si++;
|
||||||
di++;
|
di++;
|
||||||
sadr = si<src_nnz ? src_ind[si] : n+1;
|
sadr = si < src_nnz ? src_ind[si] : n+1;
|
||||||
dadr = di<dst_nnz ? dst_ind[di] : n+1;
|
dadr = di < dst_nnz ? dst_ind[di] : n+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// dst only
|
// dst only
|
||||||
else if (dadr<sadr) {
|
else if (dadr < sadr) {
|
||||||
for (int k=0; k<nrow; k++) {
|
for (int k=0; k < nrow; k++) {
|
||||||
buf[nrow*nnz + k] = dst[di + k*dst_nnz];
|
buf[nrow*nnz + k] = dst[di + k*dst_nnz];
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_ind[nnz++] = dadr;
|
buf_ind[nnz++] = dadr;
|
||||||
di++;
|
di++;
|
||||||
dadr = di<dst_nnz ? dst_ind[di] : n+1;
|
dadr = di < dst_nnz ? dst_ind[di] : n+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// src only
|
// src only
|
||||||
else {
|
else {
|
||||||
for (int k=0; k<nrow; k++) {
|
for (int k=0; k < nrow; k++) {
|
||||||
buf[nrow*nnz + k] = scl*src[si + k*src_nnz];
|
buf[nrow*nnz + k] = scl*src[si + k*src_nnz];
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_ind[nnz++] = sadr;
|
buf_ind[nnz++] = sadr;
|
||||||
si++;
|
si++;
|
||||||
sadr = si<src_nnz ? src_ind[si] : n+1;
|
sadr = si < src_nnz ? src_ind[si] : n+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,8 +492,8 @@ int mju_addToSparseMat(mjtNum* dst, const mjtNum* src, int n, int nrow, mjtNum s
|
|||||||
int mju_addChains(int* res, int n, int NV1, int NV2,
|
int mju_addChains(int* res, int n, int NV1, int NV2,
|
||||||
const int* chain1, const int* chain2) {
|
const int* chain1, const int* chain2) {
|
||||||
// check for identical pattern
|
// check for identical pattern
|
||||||
if (NV1==NV2) {
|
if (NV1 == NV2) {
|
||||||
if (NV1==0) {
|
if (NV1 == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (mju_compare(chain1, chain2, NV1)) {
|
if (mju_compare(chain1, chain2, NV1)) {
|
||||||
@@ -508,28 +508,28 @@ int mju_addChains(int* res, int n, int NV1, int NV2,
|
|||||||
int adr2 = NV2 ? chain2[0] : n+1;
|
int adr2 = NV2 ? chain2[0] : n+1;
|
||||||
|
|
||||||
// merge chains
|
// merge chains
|
||||||
while (i1<NV1 || i2<NV2) {
|
while (i1 < NV1 || i2 < NV2) {
|
||||||
// both
|
// both
|
||||||
if (adr1==adr2) {
|
if (adr1 == adr2) {
|
||||||
res[NV++] = adr1;
|
res[NV++] = adr1;
|
||||||
i1++;
|
i1++;
|
||||||
i2++;
|
i2++;
|
||||||
adr1 = i1<NV1 ? chain1[i1] : n+1;
|
adr1 = i1 < NV1 ? chain1[i1] : n+1;
|
||||||
adr2 = i2<NV2 ? chain2[i2] : n+1;
|
adr2 = i2 < NV2 ? chain2[i2] : n+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// chain1 only
|
// chain1 only
|
||||||
else if (adr1<adr2) {
|
else if (adr1 < adr2) {
|
||||||
res[NV++] = adr1;
|
res[NV++] = adr1;
|
||||||
i1++;
|
i1++;
|
||||||
adr1 = i1<NV1 ? chain1[i1] : n+1;
|
adr1 = i1 < NV1 ? chain1[i1] : n+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// chain2 only
|
// chain2 only
|
||||||
else {
|
else {
|
||||||
res[NV++] = adr2;
|
res[NV++] = adr2;
|
||||||
i2++;
|
i2++;
|
||||||
adr2 = i2<NV2 ? chain2[i2] : n+1;
|
adr2 = i2 < NV2 ? chain2[i2] : n+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -169,15 +169,15 @@ void mjv_makeScene(const mjModel* m, mjvScene* scn, int maxgeom) {
|
|||||||
|
|
||||||
// count max number of flex faces to be rendered (depending on vis options)
|
// count max number of flex faces to be rendered (depending on vis options)
|
||||||
int nface = 0;
|
int nface = 0;
|
||||||
for (int f=0; f<nflex; f++) {
|
for (int f=0; f < nflex; f++) {
|
||||||
// 1D : 0
|
// 1D : 0
|
||||||
if (m->flex_dim[f]==0) {
|
if (m->flex_dim[f] == 0) {
|
||||||
scn->flexfacenum[f] = 0;
|
scn->flexfacenum[f] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2D: 2*fragments + 2*elements
|
// 2D: 2*fragments + 2*elements
|
||||||
else if (m->flex_dim[f]==2) {
|
else if (m->flex_dim[f] == 2) {
|
||||||
scn->flexfacenum[f] = 2*m->flex_shellnum[f] + 2*m->flex_elemnum[f];
|
scn->flexfacenum[f] = 2*m->flex_shellnum[f] + 2*m->flex_elemnum[f];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3D: max(fragments, 4*maxlayer)
|
// 3D: max(fragments, 4*maxlayer)
|
||||||
@@ -187,8 +187,8 @@ void mjv_makeScene(const mjModel* m, mjvScene* scn, int maxgeom) {
|
|||||||
while (nlayer) {
|
while (nlayer) {
|
||||||
// count elements in this layer
|
// count elements in this layer
|
||||||
nlayer = 0;
|
nlayer = 0;
|
||||||
for (int e=0; e<m->flex_elemnum[f]; e++) {
|
for (int e=0; e < m->flex_elemnum[f]; e++) {
|
||||||
if (m->flex_elemlayer[m->flex_elemadr[f]+e]==layer) {
|
if (m->flex_elemlayer[m->flex_elemadr[f]+e] == layer) {
|
||||||
nlayer++;
|
nlayer++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,8 +234,8 @@ void mjv_makeScene(const mjModel* m, mjvScene* scn, int maxgeom) {
|
|||||||
memcpy(scn->flexedge, m->flex_edge, 2*m->nflexedge*sizeof(int));
|
memcpy(scn->flexedge, m->flex_edge, 2*m->nflexedge*sizeof(int));
|
||||||
|
|
||||||
// compute flexfaceadr
|
// compute flexfaceadr
|
||||||
for (int f=0; f<nflex; f++) {
|
for (int f=0; f < nflex; f++) {
|
||||||
scn->flexfaceadr[f] = f==0 ? 0 : scn->flexfaceadr[f-1]+scn->flexfacenum[f-1];
|
scn->flexfaceadr[f] = f == 0 ? 0 : scn->flexfaceadr[f-1]+scn->flexfacenum[f-1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -546,7 +546,7 @@ void mjv_initPerturb(const mjModel* m, mjData* d, const mjvScene* scn, mjvPertur
|
|||||||
pert->localmass = 3 / mju_max(invmass, mjMINVAL);
|
pert->localmass = 3 / mju_max(invmass, mjMINVAL);
|
||||||
|
|
||||||
// scale localmass with flex average number of edges per vertex
|
// scale localmass with flex average number of edges per vertex
|
||||||
if (pert->flexselect>=0 && !m->flex_rigid[pert->flexselect]) {
|
if (pert->flexselect >= 0 && !m->flex_rigid[pert->flexselect]) {
|
||||||
pert->localmass *= (2.0*m->flex_edgenum[pert->flexselect]) /
|
pert->localmass *= (2.0*m->flex_edgenum[pert->flexselect]) /
|
||||||
(mjtNum)m->flex_vertnum[pert->flexselect];
|
(mjtNum)m->flex_vertnum[pert->flexselect];
|
||||||
}
|
}
|
||||||
@@ -773,7 +773,7 @@ int mjv_select(const mjModel* m, const mjData* d, const mjvOption* vopt,
|
|||||||
*flexid = -1;
|
*flexid = -1;
|
||||||
if (vopt->flags[mjVIS_FLEXVERT] || vopt->flags[mjVIS_FLEXEDGE] ||
|
if (vopt->flags[mjVIS_FLEXVERT] || vopt->flags[mjVIS_FLEXEDGE] ||
|
||||||
vopt->flags[mjVIS_FLEXFACE] || vopt->flags[mjVIS_FLEXSKIN]) {
|
vopt->flags[mjVIS_FLEXFACE] || vopt->flags[mjVIS_FLEXSKIN]) {
|
||||||
for (int i=0; i<m->nflex; i++) {
|
for (int i=0; i < m->nflex; i++) {
|
||||||
// process one flex
|
// process one flex
|
||||||
int vertid;
|
int vertid;
|
||||||
mjtNum newdist = mju_rayFlex(m, d, vopt->flex_layer,
|
mjtNum newdist = mju_rayFlex(m, d, vopt->flex_layer,
|
||||||
@@ -782,7 +782,7 @@ int mjv_select(const mjModel* m, const mjData* d, const mjvOption* vopt,
|
|||||||
i, pos, ray, &vertid);
|
i, pos, ray, &vertid);
|
||||||
|
|
||||||
// update if closer intersection found
|
// update if closer intersection found
|
||||||
if (newdist>=0 && (newdist<flexdist || flexdist<0)) {
|
if (newdist >= 0 && (newdist < flexdist || flexdist < 0)) {
|
||||||
flexdist = newdist;
|
flexdist = newdist;
|
||||||
flexbodyid = m->flex_vertbodyid[m->flex_vertadr[i] + vertid];
|
flexbodyid = m->flex_vertbodyid[m->flex_vertadr[i] + vertid];
|
||||||
*flexid = i;
|
*flexid = i;
|
||||||
@@ -842,9 +842,9 @@ int mjv_select(const mjModel* m, const mjData* d, const mjvOption* vopt,
|
|||||||
// find smallest non-negative distance
|
// find smallest non-negative distance
|
||||||
mjtNum raydist[3] = {geomdist, flexdist, skindist};
|
mjtNum raydist[3] = {geomdist, flexdist, skindist};
|
||||||
int best = -1;
|
int best = -1;
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
if (raydist[i]>=0) {
|
if (raydist[i] >= 0) {
|
||||||
if (best<0 || raydist[best]>raydist[i]) {
|
if (best < 0 || raydist[best] > raydist[i]) {
|
||||||
best = i;
|
best = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,9 +148,9 @@ static void addContactGeom(const mjModel* m, mjData* d, const mjtByte* flags,
|
|||||||
// label contacting geom names or ids
|
// label contacting geom names or ids
|
||||||
if (vopt->label == mjLABEL_CONTACTPOINT) {
|
if (vopt->label == mjLABEL_CONTACTPOINT) {
|
||||||
char contactlabel[2][48];
|
char contactlabel[2][48];
|
||||||
for (int k=0; k<2; k++) {
|
for (int k=0; k < 2; k++) {
|
||||||
// make geom label
|
// make geom label
|
||||||
if (con->geom[k]>=0) {
|
if (con->geom[k] >= 0) {
|
||||||
const char* geomname = mj_id2name(m, mjOBJ_GEOM, con->geom[k]);
|
const char* geomname = mj_id2name(m, mjOBJ_GEOM, con->geom[k]);
|
||||||
if (geomname) {
|
if (geomname) {
|
||||||
mjSNPRINTF(contactlabel[k], "%s", geomname);
|
mjSNPRINTF(contactlabel[k], "%s", geomname);
|
||||||
@@ -164,7 +164,7 @@ static void addContactGeom(const mjModel* m, mjData* d, const mjtByte* flags,
|
|||||||
else {
|
else {
|
||||||
const char* flexname = mj_id2name(m, mjOBJ_FLEX, con->flex[k]);
|
const char* flexname = mj_id2name(m, mjOBJ_FLEX, con->flex[k]);
|
||||||
if (flexname) {
|
if (flexname) {
|
||||||
if (con->elem[k]>=0) {
|
if (con->elem[k] >= 0) {
|
||||||
mjSNPRINTF(contactlabel[k], "%s.e%d", flexname, con->elem[k]);
|
mjSNPRINTF(contactlabel[k], "%s.e%d", flexname, con->elem[k]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -172,7 +172,7 @@ static void addContactGeom(const mjModel* m, mjData* d, const mjtByte* flags,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (con->elem[k]>=0) {
|
if (con->elem[k] >= 0) {
|
||||||
mjSNPRINTF(contactlabel[k], "f%d.e%d", con->flex[k], con->elem[k]);
|
mjSNPRINTF(contactlabel[k], "f%d.e%d", con->flex[k], con->elem[k]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -265,9 +265,9 @@ static void addContactGeom(const mjModel* m, mjData* d, const mjtByte* flags,
|
|||||||
|
|
||||||
// get bodyflex ids
|
// get bodyflex ids
|
||||||
int bf[2];
|
int bf[2];
|
||||||
for (int k=0; k<2; k++) {
|
for (int k=0; k < 2; k++) {
|
||||||
bf[k] = (con->geom[k]>=0) ? m->geom_bodyid[con->geom[k]] :
|
bf[k] = (con->geom[k] >= 0) ? m->geom_bodyid[con->geom[k]] :
|
||||||
m->nbody + con->flex[k];
|
m->nbody + con->flex[k];
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure arrow points towards bodyflex with higher id
|
// make sure arrow points towards bodyflex with higher id
|
||||||
@@ -599,7 +599,7 @@ void mjv_addGeoms(const mjModel* m, mjData* d, const mjvOption* vopt,
|
|||||||
if ((vopt->flags[mjVIS_FLEXVERT] || vopt->flags[mjVIS_FLEXEDGE] ||
|
if ((vopt->flags[mjVIS_FLEXVERT] || vopt->flags[mjVIS_FLEXEDGE] ||
|
||||||
vopt->flags[mjVIS_FLEXFACE] || vopt->flags[mjVIS_FLEXSKIN]) &&
|
vopt->flags[mjVIS_FLEXFACE] || vopt->flags[mjVIS_FLEXSKIN]) &&
|
||||||
(category & catmask)) {
|
(category & catmask)) {
|
||||||
for (int i=0; i<m->nflex; i++) {
|
for (int i=0; i < m->nflex; i++) {
|
||||||
if (vopt->flexgroup[mjMAX(0, mjMIN(mjNGROUP-1, m->flex_group[i]))]) {
|
if (vopt->flexgroup[mjMAX(0, mjMIN(mjNGROUP-1, m->flex_group[i]))]) {
|
||||||
START
|
START
|
||||||
|
|
||||||
@@ -614,7 +614,7 @@ void mjv_addGeoms(const mjModel* m, mjData* d, const mjvOption* vopt,
|
|||||||
setMaterial(m, thisgeom, m->flex_matid[i], m->flex_rgba+4*i, vopt->flags);
|
setMaterial(m, thisgeom, m->flex_matid[i], m->flex_rgba+4*i, vopt->flags);
|
||||||
|
|
||||||
// set texcoord
|
// set texcoord
|
||||||
if (m->flex_texcoordadr[i]>=0) {
|
if (m->flex_texcoordadr[i] >= 0) {
|
||||||
thisgeom->texcoord = 1;
|
thisgeom->texcoord = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -622,17 +622,17 @@ void mjv_addGeoms(const mjModel* m, mjData* d, const mjvOption* vopt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// glow flex if selected
|
// glow flex if selected
|
||||||
if (pert->flexselect==i) {
|
if (pert->flexselect == i) {
|
||||||
markselected(&m->vis, thisgeom);
|
markselected(&m->vis, thisgeom);
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip if alpha is 0
|
// skip if alpha is 0
|
||||||
if (thisgeom->rgba[3]==0) {
|
if (thisgeom->rgba[3] == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// vopt->label
|
// vopt->label
|
||||||
if (vopt->label==mjLABEL_FLEX) {
|
if (vopt->label == mjLABEL_FLEX) {
|
||||||
makeLabel(m, mjOBJ_FLEX, i, thisgeom->label);
|
makeLabel(m, mjOBJ_FLEX, i, thisgeom->label);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -723,11 +723,11 @@ void mjv_addGeoms(const mjModel* m, mjData* d, const mjvOption* vopt,
|
|||||||
// flex BVH
|
// flex BVH
|
||||||
if (vopt->flags[mjVIS_FLEXBVH]) {
|
if (vopt->flags[mjVIS_FLEXBVH]) {
|
||||||
float rgba[] = {1, 0, 0, 0.1};
|
float rgba[] = {1, 0, 0, 0.1};
|
||||||
for (int f=0; f<m->nflex; f++) {
|
for (int f=0; f < m->nflex; f++) {
|
||||||
if (m->flex_bvhnum[f] &&
|
if (m->flex_bvhnum[f] &&
|
||||||
vopt->flexgroup[mjMAX(0, mjMIN(mjNGROUP-1, m->flex_group[f]))]) {
|
vopt->flexgroup[mjMAX(0, mjMIN(mjNGROUP-1, m->flex_group[f]))]) {
|
||||||
for (int i=m->flex_bvhadr[f]; i<m->flex_bvhadr[f]+m->flex_bvhnum[f]; i++) {
|
for (int i=m->flex_bvhadr[f]; i < m->flex_bvhadr[f]+m->flex_bvhnum[f]; i++) {
|
||||||
int isleaf = m->bvh_child[2*i]==-1 && m->bvh_child[2*i+1]==-1;
|
int isleaf = m->bvh_child[2*i] == -1 && m->bvh_child[2*i+1] == -1;
|
||||||
if (scn->ngeom >= scn->maxgeom) break;
|
if (scn->ngeom >= scn->maxgeom) break;
|
||||||
if (m->bvh_depth[i] != vopt->bvh_depth) {
|
if (m->bvh_depth[i] != vopt->bvh_depth) {
|
||||||
if (!isleaf || m->bvh_depth[i] > vopt->bvh_depth) {
|
if (!isleaf || m->bvh_depth[i] > vopt->bvh_depth) {
|
||||||
@@ -743,7 +743,7 @@ void mjv_addGeoms(const mjModel* m, mjData* d, const mjvOption* vopt,
|
|||||||
// b/304453879 : add LINEBOX geom for bounding box visualization
|
// b/304453879 : add LINEBOX geom for bounding box visualization
|
||||||
|
|
||||||
START
|
START
|
||||||
mjv_initGeom(thisgeom, mjGEOM_BOX, aabb+3, aabb, NULL, rgba);
|
mjv_initGeom(thisgeom, mjGEOM_BOX, aabb+3, aabb, NULL, rgba);
|
||||||
FINISH
|
FINISH
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1351,7 +1351,7 @@ void mjv_addGeoms(const mjModel* m, mjData* d, const mjvOption* vopt,
|
|||||||
if (m->geom_type[i] == mjGEOM_MESH || m->geom_type[i] == mjGEOM_SDF) {
|
if (m->geom_type[i] == mjGEOM_MESH || m->geom_type[i] == mjGEOM_SDF) {
|
||||||
thisgeom->dataid *= 2;
|
thisgeom->dataid *= 2;
|
||||||
if (m->mesh_graphadr[m->geom_dataid[i]] >= 0 && vopt->flags[mjVIS_CONVEXHULL] &&
|
if (m->mesh_graphadr[m->geom_dataid[i]] >= 0 && vopt->flags[mjVIS_CONVEXHULL] &&
|
||||||
(m->geom_contype[i] || m->geom_conaffinity[i])) {
|
(m->geom_contype[i] || m->geom_conaffinity[i])) {
|
||||||
thisgeom->dataid += 1;
|
thisgeom->dataid += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1646,7 +1646,7 @@ void mjv_addGeoms(const mjModel* m, mjData* d, const mjvOption* vopt,
|
|||||||
mju_addToScl3(vfar[3], y, zver[1]);
|
mju_addToScl3(vfar[3], y, zver[1]);
|
||||||
|
|
||||||
// triangulation and wireframe of the frustum
|
// triangulation and wireframe of the frustum
|
||||||
for (int e=0; e<4; e++) {
|
for (int e=0; e < 4; e++) {
|
||||||
START
|
START
|
||||||
mju_sub3(x, vfar[e], vnear[e]);
|
mju_sub3(x, vfar[e], vnear[e]);
|
||||||
mju_sub3(y, vnear[(e+1)%4], vnear[e]);
|
mju_sub3(y, vnear[(e+1)%4], vnear[e]);
|
||||||
@@ -1839,7 +1839,7 @@ void mjv_addGeoms(const mjModel* m, mjData* d, const mjvOption* vopt,
|
|||||||
for (int j=0; j < npoints-1; j++) {
|
for (int j=0; j < npoints-1; j++) {
|
||||||
START
|
START
|
||||||
|
|
||||||
sz[0] = m->tendon_width[i];
|
sz[0] = m->tendon_width[i];
|
||||||
|
|
||||||
// construct geom
|
// construct geom
|
||||||
mjv_connector(thisgeom, mjGEOM_CAPSULE, sz[0], catenary+3*j, catenary+3*j+3);
|
mjv_connector(thisgeom, mjGEOM_CAPSULE, sz[0], catenary+3*j, catenary+3*j+3);
|
||||||
@@ -2300,7 +2300,7 @@ static void makeSmooth(float* _face, float* _normal, mjtNum radius, mjtByte flg_
|
|||||||
float* face = _face + 9*nface;
|
float* face = _face + 9*nface;
|
||||||
float* normal = _normal + 9*nface;
|
float* normal = _normal + 9*nface;
|
||||||
int ind[3] = {i0, i1, i2};
|
int ind[3] = {i0, i1, i2};
|
||||||
int sign = radius>0 ? 1 : -1;
|
int sign = radius > 0 ? 1 : -1;
|
||||||
|
|
||||||
// flat shading
|
// flat shading
|
||||||
if (flg_flat) {
|
if (flg_flat) {
|
||||||
@@ -2315,7 +2315,7 @@ static void makeSmooth(float* _face, float* _normal, mjtNum radius, mjtByte flg_
|
|||||||
mju_normalize3(nrm);
|
mju_normalize3(nrm);
|
||||||
|
|
||||||
// set all vertex normals equal to face normal
|
// set all vertex normals equal to face normal
|
||||||
for (int k=0; k<3; k++){
|
for (int k=0; k < 3; k++){
|
||||||
normal[3*k+0] = (float) (sign*nrm[0]);
|
normal[3*k+0] = (float) (sign*nrm[0]);
|
||||||
normal[3*k+1] = (float) (sign*nrm[1]);
|
normal[3*k+1] = (float) (sign*nrm[1]);
|
||||||
normal[3*k+2] = (float) (sign*nrm[2]);
|
normal[3*k+2] = (float) (sign*nrm[2]);
|
||||||
@@ -2324,7 +2324,7 @@ static void makeSmooth(float* _face, float* _normal, mjtNum radius, mjtByte flg_
|
|||||||
|
|
||||||
// smooth shading
|
// smooth shading
|
||||||
else {
|
else {
|
||||||
for (int k=0; k<3; k++){
|
for (int k=0; k < 3; k++){
|
||||||
normal[3*k+0] = (float) (sign*vertnorm[3*ind[k]+0]);
|
normal[3*k+0] = (float) (sign*vertnorm[3*ind[k]+0]);
|
||||||
normal[3*k+1] = (float) (sign*vertnorm[3*ind[k]+1]);
|
normal[3*k+1] = (float) (sign*vertnorm[3*ind[k]+1]);
|
||||||
normal[3*k+2] = (float) (sign*vertnorm[3*ind[k]+2]);
|
normal[3*k+2] = (float) (sign*vertnorm[3*ind[k]+2]);
|
||||||
@@ -2332,7 +2332,7 @@ static void makeSmooth(float* _face, float* _normal, mjtNum radius, mjtByte flg_
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set positions: vertices offset by radius*normal
|
// set positions: vertices offset by radius*normal
|
||||||
for (int k=0; k<3; k++){
|
for (int k=0; k < 3; k++){
|
||||||
face[3*k+0] = (float) (vertxpos[3*ind[k]+0] + radius*vertnorm[3*ind[k]+0]);
|
face[3*k+0] = (float) (vertxpos[3*ind[k]+0] + radius*vertnorm[3*ind[k]+0]);
|
||||||
face[3*k+1] = (float) (vertxpos[3*ind[k]+1] + radius*vertnorm[3*ind[k]+1]);
|
face[3*k+1] = (float) (vertxpos[3*ind[k]+1] + radius*vertnorm[3*ind[k]+1]);
|
||||||
face[3*k+2] = (float) (vertxpos[3*ind[k]+2] + radius*vertnorm[3*ind[k]+2]);
|
face[3*k+2] = (float) (vertxpos[3*ind[k]+2] + radius*vertnorm[3*ind[k]+2]);
|
||||||
@@ -2354,13 +2354,13 @@ static void makeSide(float* _face, float* _normal, mjtNum radius,
|
|||||||
mjtNum v01[3] = {v1[0]-v0[0], v1[1]-v0[1], v1[2]-v0[2]};
|
mjtNum v01[3] = {v1[0]-v0[0], v1[1]-v0[1], v1[2]-v0[2]};
|
||||||
mjtNum nrm[3];
|
mjtNum nrm[3];
|
||||||
mju_cross(nrm, v01, vertnorm+3*i1);
|
mju_cross(nrm, v01, vertnorm+3*i1);
|
||||||
if (radius<0) {
|
if (radius < 0) {
|
||||||
mju_scl3(nrm, nrm, -1);
|
mju_scl3(nrm, nrm, -1);
|
||||||
}
|
}
|
||||||
mju_normalize3(nrm);
|
mju_normalize3(nrm);
|
||||||
|
|
||||||
// set normals
|
// set normals
|
||||||
for (int k=0; k<3; k++){
|
for (int k=0; k < 3; k++){
|
||||||
normal[3*k+0] = (float) nrm[0];
|
normal[3*k+0] = (float) nrm[0];
|
||||||
normal[3*k+1] = (float) nrm[1];
|
normal[3*k+1] = (float) nrm[1];
|
||||||
normal[3*k+2] = (float) nrm[2];
|
normal[3*k+2] = (float) nrm[2];
|
||||||
@@ -2368,8 +2368,8 @@ static void makeSide(float* _face, float* _normal, mjtNum radius,
|
|||||||
|
|
||||||
// set positions
|
// set positions
|
||||||
int ind[3] = {i0, i1, i1};
|
int ind[3] = {i0, i1, i1};
|
||||||
for (int k=0; k<3; k++){
|
for (int k=0; k < 3; k++){
|
||||||
mjtNum sign = (k==1 ? -1 : +1);
|
mjtNum sign = (k == 1 ? -1 : +1);
|
||||||
face[3*k+0] = (float) (vertxpos[3*ind[k]+0] + sign*radius*vertnorm[3*ind[k]+0]);
|
face[3*k+0] = (float) (vertxpos[3*ind[k]+0] + sign*radius*vertnorm[3*ind[k]+0]);
|
||||||
face[3*k+1] = (float) (vertxpos[3*ind[k]+1] + sign*radius*vertnorm[3*ind[k]+1]);
|
face[3*k+1] = (float) (vertxpos[3*ind[k]+1] + sign*radius*vertnorm[3*ind[k]+1]);
|
||||||
face[3*k+2] = (float) (vertxpos[3*ind[k]+2] + sign*radius*vertnorm[3*ind[k]+2]);
|
face[3*k+2] = (float) (vertxpos[3*ind[k]+2] + sign*radius*vertnorm[3*ind[k]+2]);
|
||||||
@@ -2403,39 +2403,39 @@ void mjv_updateActiveFlex(const mjModel* m, mjData* d, mjvScene* scn, const mjvO
|
|||||||
scn->flexskinopt = opt->flags[mjVIS_FLEXSKIN];
|
scn->flexskinopt = opt->flags[mjVIS_FLEXSKIN];
|
||||||
|
|
||||||
// convert vertex positions from mjtNum to float
|
// convert vertex positions from mjtNum to float
|
||||||
for (int v=0; v<3*m->nflexvert; v++) {
|
for (int v=0; v < 3*m->nflexvert; v++) {
|
||||||
scn->flexvert[v] = (float) d->flexvert_xpos[v];
|
scn->flexvert[v] = (float) d->flexvert_xpos[v];
|
||||||
}
|
}
|
||||||
|
|
||||||
// construct faces
|
// construct faces
|
||||||
for (int f=0; f<m->nflex; f++) {
|
for (int f=0; f < m->nflex; f++) {
|
||||||
int dim = m->flex_dim[f];
|
int dim = m->flex_dim[f];
|
||||||
mjtNum radius = m->flex_radius[f];
|
mjtNum radius = m->flex_radius[f];
|
||||||
mjtByte flg_flat = m->flex_flatskin[f];
|
mjtByte flg_flat = m->flex_flatskin[f];
|
||||||
const mjtNum* vertxpos = d->flexvert_xpos + 3*m->flex_vertadr[f];
|
const mjtNum* vertxpos = d->flexvert_xpos + 3*m->flex_vertadr[f];
|
||||||
float* face = scn->flexface + 9*scn->flexfaceadr[f];
|
float* face = scn->flexface + 9*scn->flexfaceadr[f];
|
||||||
float* normal = scn->flexnormal + 9*scn->flexfaceadr[f];
|
float* normal = scn->flexnormal + 9*scn->flexfaceadr[f];
|
||||||
float* texdst = m->flex_texcoordadr[f]>=0 ?
|
float* texdst = m->flex_texcoordadr[f] >= 0 ?
|
||||||
scn->flextexcoord + 6*scn->flexfaceadr[f] : NULL;
|
scn->flextexcoord + 6*scn->flexfaceadr[f] : NULL;
|
||||||
const float* texsrc = m->flex_texcoordadr[f]>=0 ?
|
const float* texsrc = m->flex_texcoordadr[f] >= 0 ?
|
||||||
m->flex_texcoord + 2*m->flex_texcoordadr[f] : NULL;
|
m->flex_texcoord + 2*m->flex_texcoordadr[f] : NULL;
|
||||||
|
|
||||||
// 1D, or face and skin disabled: no faces
|
// 1D, or face and skin disabled: no faces
|
||||||
if (dim==1 || (!opt->flags[mjVIS_FLEXFACE] && !opt->flags[mjVIS_FLEXSKIN])) {
|
if (dim == 1 || (!opt->flags[mjVIS_FLEXFACE] && !opt->flags[mjVIS_FLEXSKIN])) {
|
||||||
scn->flexfaceused[f] = 0;
|
scn->flexfaceused[f] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2D or 3D face: faces from elements, flat normals, texture
|
// 2D or 3D face: faces from elements, flat normals, texture
|
||||||
else if (!opt->flags[mjVIS_FLEXSKIN]) {
|
else if (!opt->flags[mjVIS_FLEXSKIN]) {
|
||||||
int nface = 0;
|
int nface = 0;
|
||||||
for (int e=0; e<m->flex_elemnum[f]; e++) {
|
for (int e=0; e < m->flex_elemnum[f]; e++) {
|
||||||
// in 3D, show only elements in selected layer
|
// in 3D, show only elements in selected layer
|
||||||
if (dim==2 || m->flex_elemlayer[m->flex_elemadr[f]+e]==opt->flex_layer) {
|
if (dim == 2 || m->flex_elemlayer[m->flex_elemadr[f]+e] == opt->flex_layer) {
|
||||||
// get element data
|
// get element data
|
||||||
const int* edata = m->flex_elem + m->flex_elemdataadr[f] + e*(dim+1);
|
const int* edata = m->flex_elem + m->flex_elemdataadr[f] + e*(dim+1);
|
||||||
|
|
||||||
// triangles: two faces per element
|
// triangles: two faces per element
|
||||||
if (dim==2) {
|
if (dim == 2) {
|
||||||
makeFace(face, normal, radius, vertxpos, nface, edata[0], edata[1], edata[2]);
|
makeFace(face, normal, radius, vertxpos, nface, edata[0], edata[1], edata[2]);
|
||||||
copyTex(texdst, texsrc, nface, edata[0], edata[1], edata[2]);
|
copyTex(texdst, texsrc, nface, edata[0], edata[1], edata[2]);
|
||||||
nface++;
|
nface++;
|
||||||
@@ -2482,27 +2482,27 @@ void mjv_updateActiveFlex(const mjModel* m, mjData* d, mjvScene* scn, const mjvO
|
|||||||
mju_zero(vertnorm, 3*m->flex_vertnum[f]);
|
mju_zero(vertnorm, 3*m->flex_vertnum[f]);
|
||||||
|
|
||||||
// add vertex normals: top element sides in 2D, shell fragments in 3D
|
// add vertex normals: top element sides in 2D, shell fragments in 3D
|
||||||
if (dim==2) {
|
if (dim == 2) {
|
||||||
for (int e=0; e<m->flex_elemnum[f]; e++) {
|
for (int e=0; e < m->flex_elemnum[f]; e++) {
|
||||||
const int* edata = m->flex_elem + m->flex_elemdataadr[f] + e*(dim+1);
|
const int* edata = m->flex_elem + m->flex_elemdataadr[f] + e*(dim+1);
|
||||||
addNormal(vertnorm, vertxpos, edata[0], edata[1], edata[2]);
|
addNormal(vertnorm, vertxpos, edata[0], edata[1], edata[2]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int s=0; s<m->flex_shellnum[f]; s++) {
|
for (int s=0; s < m->flex_shellnum[f]; s++) {
|
||||||
const int* sdata = m->flex_shell + m->flex_shelldataadr[f] + s*dim;
|
const int* sdata = m->flex_shell + m->flex_shelldataadr[f] + s*dim;
|
||||||
addNormal(vertnorm, vertxpos, sdata[0], sdata[1], sdata[2]);
|
addNormal(vertnorm, vertxpos, sdata[0], sdata[1], sdata[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// normalize vertex normals
|
// normalize vertex normals
|
||||||
for (int i=0; i<m->flex_vertnum[f]; i++) {
|
for (int i=0; i < m->flex_vertnum[f]; i++) {
|
||||||
mju_normalize3(vertnorm+3*i);
|
mju_normalize3(vertnorm+3*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create faces, offset along smoothed vertex normals, and texcoord
|
// create faces, offset along smoothed vertex normals, and texcoord
|
||||||
int nface = 0;
|
int nface = 0;
|
||||||
if (dim==2) {
|
if (dim == 2) {
|
||||||
for (int e=0; e<m->flex_elemnum[f]; e++) {
|
for (int e=0; e < m->flex_elemnum[f]; e++) {
|
||||||
const int* edata = m->flex_elem + m->flex_elemdataadr[f] + e*(dim+1);
|
const int* edata = m->flex_elem + m->flex_elemdataadr[f] + e*(dim+1);
|
||||||
makeSmooth(face, normal, radius, flg_flat, vertnorm, vertxpos,
|
makeSmooth(face, normal, radius, flg_flat, vertnorm, vertxpos,
|
||||||
nface, edata[0], edata[1], edata[2]);
|
nface, edata[0], edata[1], edata[2]);
|
||||||
@@ -2514,7 +2514,7 @@ void mjv_updateActiveFlex(const mjModel* m, mjData* d, mjvScene* scn, const mjvO
|
|||||||
nface++;
|
nface++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int s=0; s<m->flex_shellnum[f]; s++) {
|
for (int s=0; s < m->flex_shellnum[f]; s++) {
|
||||||
const int* sdata = m->flex_shell + m->flex_shelldataadr[f] + s*dim;
|
const int* sdata = m->flex_shell + m->flex_shelldataadr[f] + s*dim;
|
||||||
makeSmooth(face, normal, radius, flg_flat, vertnorm, vertxpos,
|
makeSmooth(face, normal, radius, flg_flat, vertnorm, vertxpos,
|
||||||
nface, sdata[0], sdata[1], sdata[2]);
|
nface, sdata[0], sdata[1], sdata[2]);
|
||||||
@@ -2524,8 +2524,8 @@ void mjv_updateActiveFlex(const mjModel* m, mjData* d, mjvScene* scn, const mjvO
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2D: close sides using shell fragments
|
// 2D: close sides using shell fragments
|
||||||
if (dim==2) {
|
if (dim == 2) {
|
||||||
for (int s=0; s<m->flex_shellnum[f]; s++) {
|
for (int s=0; s < m->flex_shellnum[f]; s++) {
|
||||||
const int* sdata = m->flex_shell + m->flex_shelldataadr[f] + s*dim;
|
const int* sdata = m->flex_shell + m->flex_shelldataadr[f] + s*dim;
|
||||||
makeSide(face, normal, radius, vertnorm, vertxpos,
|
makeSide(face, normal, radius, vertnorm, vertxpos,
|
||||||
nface, sdata[0], sdata[1]);
|
nface, sdata[0], sdata[1]);
|
||||||
@@ -2665,10 +2665,10 @@ void mjv_updateActiveSkin(const mjModel* m, mjData* d, mjvScene* scn, const mjvO
|
|||||||
// normalize normals
|
// normalize normals
|
||||||
for (int k=vertadr; k < vertadr+vertnum; k++) {
|
for (int k=vertadr; k < vertadr+vertnum; k++) {
|
||||||
float s = sqrtf(
|
float s = sqrtf(
|
||||||
scn->skinnormal[3*k]*scn->skinnormal[3*k] +
|
scn->skinnormal[3*k+0]*scn->skinnormal[3*k+0] +
|
||||||
scn->skinnormal[3*k+1]*scn->skinnormal[3*k+1] +
|
scn->skinnormal[3*k+1]*scn->skinnormal[3*k+1] +
|
||||||
scn->skinnormal[3*k+2]*scn->skinnormal[3*k+2]
|
scn->skinnormal[3*k+2]*scn->skinnormal[3*k+2]
|
||||||
);
|
);
|
||||||
float scl = 1/mjMAX(mjMINVAL, s);
|
float scl = 1/mjMAX(mjMINVAL, s);
|
||||||
|
|
||||||
scn->skinnormal[3*k] *= scl;
|
scn->skinnormal[3*k] *= scl;
|
||||||
|
|||||||
Reference in New Issue
Block a user