Skip to content

Commit eec6e43

Browse files
kbayescopybara-github
authored andcommitted
Bit compress face vertices in EPA to reduce memory needed. The parameter ccd_iteration is only supported to 1000, so we only need 10 bits for vertex index.
PiperOrigin-RevId: 885690198 Change-Id: I4c6af170ddc86316d3e9cfaf7ca7e0e4fac8a416
1 parent e57d95e commit eec6e43

1 file changed

Lines changed: 54 additions & 40 deletions

File tree

src/engine/engine_collision_gjk.c

Lines changed: 54 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,20 @@ static inline void lincomb(mjtNum res[3], const mjtNum* coef, int n, const mjtNu
5151

5252
// one face in a polytope
5353
typedef struct {
54-
int verts[3]; // indices of the three vertices of the face in the polytope
54+
int verts; // indices of the three vertices of the face in the polytope
5555
int adj[3]; // adjacent faces, one for each edge: [v1,v2], [v2,v3], [v3,v1]
5656
mjtNum v[3]; // projection of the origin on face, can be used as face normal
5757
mjtNum dist2; // squared norm of v; negative if deleted
5858
int index; // index in map; -1: not in map, -2: deleted from polytope
5959
} Face;
6060

61+
// return int[3] with lower 30 bits split between three int
62+
#define EPA_VERT_EXPAND(n) \
63+
{ (n) & 0x3FF, \
64+
(n) >> 10 & 0x3FF, \
65+
(n) >> 20 & 0x3FF }
66+
67+
6168
// polytope used in the Expanding Polytope Algorithm (EPA)
6269
typedef struct {
6370
Vertex* verts; // list of vertices that make up the polytope
@@ -1188,9 +1195,7 @@ static inline int maxFaces(Polytope* pt) {
11881195
static inline mjtNum attachFace(Polytope* pt, int v1, int v2, int v3,
11891196
int adj1, int adj2, int adj3) {
11901197
Face* face = &pt->faces[pt->nfaces++];
1191-
face->verts[0] = v1;
1192-
face->verts[1] = v2;
1193-
face->verts[2] = v3;
1198+
face->verts = v1 + (v2 << 10) + (v3 << 20);
11941199

11951200
// adjacent faces
11961201
face->adj[0] = adj1;
@@ -1218,8 +1223,9 @@ static inline void addEdge(Polytope* pt, int index, int edge) {
12181223

12191224
// get edge index where vertex lies
12201225
static inline int getEdge(Face* face, int vertex) {
1221-
if (face->verts[0] == vertex) return 0;
1222-
if (face->verts[1] == vertex) return 1;
1226+
int verts[3] = EPA_VERT_EXPAND(face->verts);
1227+
if (verts[0] == vertex) return 0;
1228+
if (verts[1] == vertex) return 1;
12231229
return 2;
12241230
}
12251231

@@ -1228,14 +1234,15 @@ static inline int getEdge(Face* face, int vertex) {
12281234
static int horizonRec(Polytope* pt, Face* face, int e) {
12291235
// v is visible from w so it is deleted and adjacent faces are checked
12301236
if (dot3(face->v, pt->horizon.w) - face->dist2 > mjMINVAL) {
1237+
int verts[3] = EPA_VERT_EXPAND(face->verts);
12311238
deleteFace(pt, face);
12321239

12331240
// recursively search the adjacent faces on the next two edges
12341241
for (int k = 1; k < 3; k++) {
12351242
int i = (e + k) % 3;
12361243
Face* adjFace = &pt->faces[face->adj[i]];
12371244
if (adjFace->index > -2) {
1238-
int adjEdge = getEdge(adjFace, face->verts[(i + 1) % 3]);
1245+
int adjEdge = getEdge(adjFace, verts[(i + 1) % 3]);
12391246
if (!horizonRec(pt, adjFace, adjEdge)) {
12401247
addEdge(pt, face->adj[i], adjEdge);
12411248
}
@@ -1250,24 +1257,25 @@ static int horizonRec(Polytope* pt, Face* face, int e) {
12501257
// create horizon given the face as starting point
12511258
static void horizon(Polytope* pt, Face* face) {
12521259
deleteFace(pt, face);
1260+
int verts[3] = EPA_VERT_EXPAND(face->verts);
12531261

12541262
// first edge
12551263
Face* adjFace = &pt->faces[face->adj[0]];
1256-
int adjEdge = getEdge(adjFace, face->verts[1]);
1264+
int adjEdge = getEdge(adjFace, verts[1]);
12571265
if (!horizonRec(pt, adjFace, adjEdge)) {
12581266
addEdge(pt, face->adj[0], adjEdge);
12591267
}
12601268

12611269
// second edge
12621270
adjFace = &pt->faces[face->adj[1]];
1263-
adjEdge = getEdge(adjFace, face->verts[2]);
1271+
adjEdge = getEdge(adjFace, verts[2]);
12641272
if (adjFace->index > -2 && !horizonRec(pt, adjFace, adjEdge)) {
12651273
addEdge(pt, face->adj[1], adjEdge);
12661274
}
12671275

12681276
// third edge
12691277
adjFace = &pt->faces[face->adj[2]];
1270-
adjEdge = getEdge(adjFace, face->verts[0]);
1278+
adjEdge = getEdge(adjFace, verts[0]);
12711279
if (adjFace->index > -2 && !horizonRec(pt, adjFace, adjEdge)) {
12721280
addEdge(pt, face->adj[2], adjEdge);
12731281
}
@@ -1278,9 +1286,10 @@ static void horizon(Polytope* pt, Face* face) {
12781286
static mjtNum epaWitness(const Polytope* pt, const Face* face, mjtNum x1[3], mjtNum x2[3]) {
12791287
// compute affine coordinates for witness points on plane defined by face
12801288
mjtNum lambda[3];
1281-
Vertex* v1 = pt->verts + face->verts[0];
1282-
Vertex* v2 = pt->verts + face->verts[1];
1283-
Vertex* v3 = pt->verts + face->verts[2];
1289+
int verts[3] = EPA_VERT_EXPAND(face->verts);
1290+
Vertex* v1 = pt->verts + verts[0];
1291+
Vertex* v2 = pt->verts + verts[1];
1292+
Vertex* v3 = pt->verts + verts[2];
12841293
triAffineCoord(lambda, v1->vert, v2->vert, v3->vert, face->v);
12851294

12861295
// witness point on geom 1
@@ -1306,7 +1315,7 @@ static Face* epa(mjCCDStatus* status, Polytope* pt, mjCCDObj* obj1, mjCCDObj* ob
13061315
tolerance = mjMINVAL;
13071316
}
13081317

1309-
int k, kmax = status->max_iterations;
1318+
int k, kmax = status->max_iterations < 1000 ? status->max_iterations : 1000;
13101319
for (k = 0; k < kmax; k++) {
13111320
pface = face;
13121321

@@ -1376,12 +1385,13 @@ static Face* epa(mjCCDStatus* status, Polytope* pt, mjCCDObj* obj1, mjCCDObj* ob
13761385
}
13771386

13781387
// attach first face
1379-
int horIndex = pt->horizon.indices[0], horEdge = pt->horizon.edges[0];
1380-
Face* horFace = &pt->faces[horIndex];
1381-
int v1 = horFace->verts[horEdge],
1382-
v2 = horFace->verts[(horEdge + 1) % 3];
1383-
horFace->adj[horEdge] = nfaces;
1384-
mjtNum dist2 = attachFace(pt, wi, v2, v1, nfaces + nedges - 1, horIndex, nfaces + 1);
1388+
int hznIndex = pt->horizon.indices[0], hznEdge = pt->horizon.edges[0];
1389+
Face* hznFace = &pt->faces[hznIndex];
1390+
int hznVerts[3] = EPA_VERT_EXPAND(hznFace->verts);
1391+
int v1 = hznVerts[hznEdge],
1392+
v2 = hznVerts[(hznEdge + 1) % 3];
1393+
hznFace->adj[hznEdge] = nfaces;
1394+
mjtNum dist2 = attachFace(pt, wi, v2, v1, nfaces + nedges - 1, hznIndex, nfaces + 1);
13851395

13861396
// unrecoverable numerical issue
13871397
if (dist2 == 0) {
@@ -1401,12 +1411,13 @@ static Face* epa(mjCCDStatus* status, Polytope* pt, mjCCDObj* obj1, mjCCDObj* ob
14011411
int cur = nfaces + i; // index of attached face
14021412
int next = nfaces + (i + 1) % nedges; // index of next face
14031413

1404-
horIndex = pt->horizon.indices[i], horEdge = pt->horizon.edges[i];
1405-
horFace = &pt->faces[horIndex];
1406-
v1 = horFace->verts[horEdge];
1407-
v2 = horFace->verts[(horEdge + 1) % 3];
1408-
horFace->adj[horEdge] = cur;
1409-
dist2 = attachFace(pt, wi, v2, v1, cur - 1, horIndex, next);
1414+
hznIndex = pt->horizon.indices[i], hznEdge = pt->horizon.edges[i];
1415+
hznFace = &pt->faces[hznIndex];
1416+
int hznVerts2[3] = EPA_VERT_EXPAND(hznFace->verts);
1417+
v1 = hznVerts2[hznEdge];
1418+
v2 = hznVerts2[(hznEdge + 1) % 3];
1419+
hznFace->adj[hznEdge] = cur;
1420+
dist2 = attachFace(pt, wi, v2, v1, cur - 1, hznIndex, next);
14101421

14111422
// unrecoverable numerical issue
14121423
if (dist2 == 0) {
@@ -2078,18 +2089,19 @@ static void multicontact(Polytope* pt, Face* face, mjCCDStatus* status,
20782089

20792090
mjtNum face1[mjMAX_POLYVERT * 3], face2[mjMAX_POLYVERT * 3], endverts[mjMAX_POLYVERT * 3];
20802091
// get vertices of faces from EPA
2081-
int v11i = pt->verts[face->verts[0]].index1;
2082-
int v12i = pt->verts[face->verts[1]].index1;
2083-
int v13i = pt->verts[face->verts[2]].index1;
2084-
int v21i = pt->verts[face->verts[0]].index2;
2085-
int v22i = pt->verts[face->verts[1]].index2;
2086-
int v23i = pt->verts[face->verts[2]].index2;
2087-
mjtNum* v11 = pt->verts[face->verts[0]].vert1;
2088-
mjtNum* v12 = pt->verts[face->verts[1]].vert1;
2089-
mjtNum* v13 = pt->verts[face->verts[2]].vert1;
2090-
mjtNum* v21 = pt->verts[face->verts[0]].vert2;
2091-
mjtNum* v22 = pt->verts[face->verts[1]].vert2;
2092-
mjtNum* v23 = pt->verts[face->verts[2]].vert2;
2092+
int verts[3] = EPA_VERT_EXPAND(face->verts);
2093+
int v11i = pt->verts[verts[0]].index1;
2094+
int v12i = pt->verts[verts[1]].index1;
2095+
int v13i = pt->verts[verts[2]].index1;
2096+
int v21i = pt->verts[verts[0]].index2;
2097+
int v22i = pt->verts[verts[1]].index2;
2098+
int v23i = pt->verts[verts[2]].index2;
2099+
mjtNum* v11 = pt->verts[verts[0]].vert1;
2100+
mjtNum* v12 = pt->verts[verts[1]].vert1;
2101+
mjtNum* v13 = pt->verts[verts[2]].vert1;
2102+
mjtNum* v21 = pt->verts[verts[0]].vert2;
2103+
mjtNum* v22 = pt->verts[verts[1]].vert2;
2104+
mjtNum* v23 = pt->verts[verts[2]].vert2;
20932105

20942106
// get dimensions of features of geoms 1 and 2
20952107
int nface1 = simplexDim(&v11i, &v12i, &v13i, &v11, &v12, &v13);
@@ -2147,7 +2159,7 @@ static void multicontact(Polytope* pt, Face* face, mjCCDStatus* status,
21472159

21482160
// recover geom1 matching edge or face
21492161
if (edgecon1) {
2150-
copy3(face1, pt->verts[face->verts[0]].vert1);
2162+
copy3(face1, pt->verts[verts[0]].vert1);
21512163
copy3(face1 + 3, endverts + 3*i);
21522164
nface1 = 2;
21532165
} else {
@@ -2162,7 +2174,7 @@ static void multicontact(Polytope* pt, Face* face, mjCCDStatus* status,
21622174

21632175
// recover geom2 matching edge or face
21642176
if (edgecon2) {
2165-
copy3(face2, pt->verts[face->verts[0]].vert2);
2177+
copy3(face2, pt->verts[verts[0]].vert2);
21662178
copy3(face2 + 3, endverts + 3*i);
21672179
nface2 = 2;
21682180
} else {
@@ -2369,3 +2381,5 @@ mjtNum mjc_ccd(const mjCCDConfig* config, mjCCDStatus* status, mjCCDObj* obj1, m
23692381
}
23702382
return status->dist;
23712383
}
2384+
2385+
#undef EPA_VERT_EXPAND

0 commit comments

Comments
 (0)