38
38
#include " cc/array_safety.h"
39
39
#include " engine/engine_passive.h"
40
40
#include < mujoco/mjspec.h>
41
+ #include < mujoco/mujoco.h>
41
42
#include " user/user_api.h"
42
43
#include " user/user_cache.h"
43
44
#include " user/user_model.h"
@@ -347,12 +348,6 @@ const char* ResolveOrientation(double* quat, bool degree, const char* sequence,
347
348
348
349
// ------------------------- class mjCBoundingVolumeHierarchy implementation ------------------------
349
350
350
- // constructor
351
- mjCBoundingVolumeHierarchy::mjCBoundingVolumeHierarchy () {
352
- mjuu_setvec (ipos_, 0 , 0 , 0 );
353
- mjuu_setvec (iquat_, 1 , 0 , 0 , 0 );
354
- }
355
-
356
351
357
352
// assign position and orientation
358
353
void mjCBoundingVolumeHierarchy::Set (double ipos_element[3 ], double iquat_element[4 ]) {
@@ -369,17 +364,29 @@ void mjCBoundingVolumeHierarchy::AllocateBoundingVolumes(int nleaf) {
369
364
nodeid_.clear ();
370
365
level_.clear ();
371
366
bvleaf_.clear ();
372
- bvleaf_.resize (nleaf);
367
+ bvleaf_.reserve (nleaf);
373
368
}
374
369
375
370
376
371
void mjCBoundingVolumeHierarchy::RemoveInactiveVolumes (int nmax) {
377
372
bvleaf_.erase (bvleaf_.begin () + nmax, bvleaf_.end ());
378
373
}
379
374
375
+ const mjCBoundingVolume*
376
+ mjCBoundingVolumeHierarchy::AddBoundingVolume (int id, int contype, int conaffinity,
377
+ const double * pos, const double * quat,
378
+ const double * aabb) {
379
+ bvleaf_.emplace_back (id, contype, conaffinity, pos, quat, aabb);
380
+ return &bvleaf_.back ();
381
+ }
382
+
380
383
381
- mjCBoundingVolume* mjCBoundingVolumeHierarchy::GetBoundingVolume (int id) {
382
- return bvleaf_.data () + id;
384
+ const mjCBoundingVolume*
385
+ mjCBoundingVolumeHierarchy::AddBoundingVolume (const int * id, int contype, int conaffinity,
386
+ const double * pos, const double * quat,
387
+ const double * aabb) {
388
+ bvleaf_.emplace_back (id, contype, conaffinity, pos, quat, aabb);
389
+ return &bvleaf_.back ();
383
390
}
384
391
385
392
@@ -391,12 +398,12 @@ void mjCBoundingVolumeHierarchy::CreateBVH() {
391
398
elements.reserve (bvleaf_.size ());
392
399
double qinv[4 ] = {iquat_[0 ], -iquat_[1 ], -iquat_[2 ], -iquat_[3 ]};
393
400
for (int i = 0 ; i < bvleaf_.size (); i++) {
394
- if (bvleaf_[i].conaffinity || bvleaf_[i].contype ) {
401
+ if (bvleaf_[i].Conaffinity () || bvleaf_[i].Contype () ) {
395
402
BVElement element;
396
403
element.e = &bvleaf_[i];
397
- double vert[3 ] = {element.e ->pos [ 0 ] - ipos_[0 ],
398
- element.e ->pos [ 1 ] - ipos_[1 ],
399
- element.e ->pos [ 2 ] - ipos_[2 ]};
404
+ double vert[3 ] = {element.e ->Pos ( 0 ) - ipos_[0 ],
405
+ element.e ->Pos ( 1 ) - ipos_[1 ],
406
+ element.e ->Pos ( 2 ) - ipos_[2 ]};
400
407
mjuu_rotVecQuat (element.lpos , vert, qinv);
401
408
elements.push_back (std::move (element));
402
409
}
@@ -412,34 +419,35 @@ int mjCBoundingVolumeHierarchy::MakeBVH(
412
419
if (nelements == 0 ) {
413
420
return -1 ;
414
421
}
415
- double AAMM[6 ] = {mjMAXVAL, mjMAXVAL, mjMAXVAL, -mjMAXVAL, -mjMAXVAL, -mjMAXVAL};
422
+ constexpr double kMaxVal = std::numeric_limits<double >::max ();
423
+ double AAMM[6 ] = {kMaxVal , kMaxVal , kMaxVal , -kMaxVal , -kMaxVal , -kMaxVal };
416
424
417
425
// inverse transformation
418
426
double qinv[4 ] = {iquat_[0 ], -iquat_[1 ], -iquat_[2 ], -iquat_[3 ]};
419
427
420
428
// accumulate AAMM over elements
421
429
for (auto element = elements_begin; element != elements_end; ++element) {
422
430
// transform element aabb to aamm format
423
- double aamm[6 ] = {element->e ->aabb [ 0 ] - element->e ->aabb [ 3 ] ,
424
- element->e ->aabb [ 1 ] - element->e ->aabb [ 4 ] ,
425
- element->e ->aabb [ 2 ] - element->e ->aabb [ 5 ] ,
426
- element->e ->aabb [ 0 ] + element->e ->aabb [ 3 ] ,
427
- element->e ->aabb [ 1 ] + element->e ->aabb [ 4 ] ,
428
- element->e ->aabb [ 2 ] + element->e ->aabb [ 5 ] };
431
+ double aamm[6 ] = {element->e ->AABB ( 0 ) - element->e ->AABB ( 3 ) ,
432
+ element->e ->AABB ( 1 ) - element->e ->AABB ( 4 ) ,
433
+ element->e ->AABB ( 2 ) - element->e ->AABB ( 5 ) ,
434
+ element->e ->AABB ( 0 ) + element->e ->AABB ( 3 ) ,
435
+ element->e ->AABB ( 1 ) + element->e ->AABB ( 4 ) ,
436
+ element->e ->AABB ( 2 ) + element->e ->AABB ( 5 ) };
429
437
430
438
// update node AAMM
431
- for (int v=0 ; v< 8 ; v++) {
439
+ for (int v=0 ; v < 8 ; v++) {
432
440
double vert[3 ], box[3 ];
433
441
vert[0 ] = (v&1 ? aamm[3 ] : aamm[0 ]);
434
442
vert[1 ] = (v&2 ? aamm[4 ] : aamm[1 ]);
435
443
vert[2 ] = (v&4 ? aamm[5 ] : aamm[2 ]);
436
444
437
445
// rotate to the body inertial frame if specified
438
- if (element->e ->quat ) {
439
- mjuu_rotVecQuat (box, vert, element->e ->quat );
440
- box[0 ] += element->e ->pos [ 0 ] - ipos_[0 ];
441
- box[1 ] += element->e ->pos [ 1 ] - ipos_[1 ];
442
- box[2 ] += element->e ->pos [ 2 ] - ipos_[2 ];
446
+ if (element->e ->Quat () ) {
447
+ mjuu_rotVecQuat (box, vert, element->e ->Quat () );
448
+ box[0 ] += element->e ->Pos ( 0 ) - ipos_[0 ];
449
+ box[1 ] += element->e ->Pos ( 1 ) - ipos_[1 ];
450
+ box[2 ] += element->e ->Pos ( 2 ) - ipos_[2 ];
443
451
mjuu_rotVecQuat (vert, box, qinv);
444
452
}
445
453
@@ -453,66 +461,73 @@ int mjCBoundingVolumeHierarchy::MakeBVH(
453
461
}
454
462
455
463
// inflate flat AABBs
456
- for (int i= 0 ; i< 3 ; i++) {
457
- if (std::abs (AAMM[i]- AAMM[i+3 ])< mjEPS) {
458
- AAMM[i+ 0 ] -= mjEPS;
459
- AAMM[i+ 3 ] += mjEPS;
464
+ for (int i = 0 ; i < 3 ; i++) {
465
+ if (std::abs (AAMM[i] - AAMM[i+3 ]) < mjEPS) {
466
+ AAMM[i + 0 ] -= mjEPS;
467
+ AAMM[i + 3 ] += mjEPS;
460
468
}
461
469
}
462
470
463
471
// store current index
464
472
int index = nbvh_++;
465
473
child_.push_back (-1 );
466
474
child_.push_back (-1 );
467
- nodeid_.push_back (nullptr );
475
+ nodeid_.push_back (-1 );
476
+ nodeidptr_.push_back (nullptr );
468
477
level_.push_back (lev);
469
478
470
479
// store bounding box of the current node
471
- for ( int i= 0 ; i< 3 ; i++) {
472
- bvh_.push_back ((AAMM[3 +i ] + AAMM[i ]) / 2 );
473
- }
474
- for ( int i= 0 ; i< 3 ; i++) {
475
- bvh_.push_back ((AAMM[3 +i ] - AAMM[i ]) / 2 );
476
- }
480
+ bvh_. push_back ((AAMM[ 3 ] + AAMM[ 0 ]) / 2 );
481
+ bvh_.push_back ((AAMM[4 ] + AAMM[1 ]) / 2 );
482
+ bvh_. push_back ((AAMM[ 5 ] + AAMM[ 2 ]) / 2 );
483
+ bvh_. push_back ((AAMM[ 3 ] - AAMM[ 0 ]) / 2 );
484
+ bvh_.push_back ((AAMM[4 ] - AAMM[1 ]) / 2 );
485
+ bvh_. push_back ((AAMM[ 5 ] - AAMM[ 2 ]) / 2 );
477
486
478
487
// leaf node, return
479
- if (nelements== 1 ) {
480
- for ( int i= 0 ; i< 2 ; i++) {
481
- child_[2 *index +i ] = -1 ;
482
- }
483
- nodeid_ [index ] = (int *)elements_begin->e ->GetId ();
488
+ if (nelements == 1 ) {
489
+ child_[ 2 * index + 0 ] = - 1 ;
490
+ child_[2 *index + 1 ] = -1 ;
491
+ nodeid_[ index ] = *elements_begin-> e -> Id ();
492
+ nodeidptr_ [index ] = (int *)elements_begin->e ->Id ();
484
493
return index ;
485
494
}
486
495
487
496
// find longest axis, by a margin of at least mjEPS, default to 0
488
497
int axis = 0 ;
489
- double edges[3 ] = { AAMM[3 ]- AAMM[0 ], AAMM[4 ]- AAMM[1 ], AAMM[5 ]- AAMM[2 ] };
498
+ double edges[3 ] = {AAMM[3 ] - AAMM[0 ], AAMM[4 ] - AAMM[1 ], AAMM[5 ] - AAMM[2 ]};
490
499
if (edges[1 ] >= edges[0 ] + mjEPS) axis = 1 ;
491
500
if (edges[2 ] >= edges[axis] + mjEPS) axis = 2 ;
492
501
493
502
// find median along the axis
503
+ auto compare = [&](const BVElement& e1 , const BVElement& e2 ) {
504
+ if (std::abs (e1 .lpos [axis] - e2 .lpos [axis]) > mjEPS) {
505
+ return e1 .lpos [axis] < e2 .lpos [axis];
506
+ }
507
+ // comparing pointers gives a stable sort, because they both come from the same array
508
+ return e1 .e < e2 .e ;
509
+ };
510
+
494
511
// note: nth_element performs a partial sort of elements
495
- BVElementCompare compare;
496
- compare.axis = axis;
497
512
int m = nelements / 2 ;
498
513
std::nth_element (elements_begin, elements_begin + m, elements_end, compare);
499
514
500
515
// recursive calls
501
516
if (m > 0 ) {
502
- child_[2 *index + 0 ] = MakeBVH (elements_begin, elements_begin + m, lev+ 1 );
517
+ child_[2 *index + 0 ] = MakeBVH (elements_begin, elements_begin + m, lev + 1 );
503
518
}
504
519
505
520
if (m != nelements) {
506
- child_[2 *index + 1 ] = MakeBVH (elements_begin + m, elements_end, lev+ 1 );
521
+ child_[2 *index + 1 ] = MakeBVH (elements_begin + m, elements_end, lev + 1 );
507
522
}
508
523
509
524
// SHOULD NOT OCCUR
510
- if (child_[2 *index + 0 ]== -1 && child_[2 *index + 1 ]== -1 ) {
525
+ if (child_[2 *index + 0 ] == -1 && child_[2 *index + 1 ] == -1 ) {
511
526
mju_error (" this should have been a leaf, body=%s nelements=%d" ,
512
527
name_.c_str (), nelements);
513
528
}
514
529
515
- if (lev> mjMAXTREEDEPTH) {
530
+ if (lev > mjMAXTREEDEPTH) {
516
531
mju_warning (" max tree depth exceeded in body=%s" , name_.c_str ());
517
532
}
518
533
@@ -1595,8 +1610,9 @@ void mjCBody::ComputeBVH() {
1595
1610
1596
1611
tree.Set (ipos, iquat);
1597
1612
tree.AllocateBoundingVolumes (geoms.size ());
1598
- for (int i=0 ; i<geoms.size (); i++) {
1599
- geoms[i]->SetBoundingVolume (tree.GetBoundingVolume (i));
1613
+ for (const mjCGeom* geom : geoms) {
1614
+ tree.AddBoundingVolume (&geom->id , geom->contype , geom->conaffinity ,
1615
+ geom->pos , geom->quat , geom->aabb );
1600
1616
}
1601
1617
tree.CreateBVH ();
1602
1618
}
@@ -2463,17 +2479,6 @@ double mjCGeom::GetVolume() const {
2463
2479
2464
2480
2465
2481
2466
- void mjCGeom::SetBoundingVolume (mjCBoundingVolume* bv) const {
2467
- bv->SetId (&id);
2468
- bv->contype = contype;
2469
- bv->conaffinity = conaffinity;
2470
- bv->aabb = aabb;
2471
- bv->pos = pos;
2472
- bv->quat = quat;
2473
- }
2474
-
2475
-
2476
-
2477
2482
// set geom diagonal inertia given density
2478
2483
void mjCGeom::SetInertia (void ) {
2479
2484
// get from mesh
0 commit comments