@@ -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
5353typedef 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)
6269typedef struct {
6370 Vertex * verts ; // list of vertices that make up the polytope
@@ -1188,9 +1195,7 @@ static inline int maxFaces(Polytope* pt) {
11881195static 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
12201225static 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) {
12281234static 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
12511258static 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) {
12781286static 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