1 #ifndef CPP_COLLISION_INCLUDE_COLLISION_GRID_VIRTUAL_H_ 2 #define CPP_COLLISION_INCLUDE_COLLISION_GRID_VIRTUAL_H_ 17 namespace accelerators {
19 template <
class DIRECTION = HorizontalGr
id>
26 return AABB(*aabb_fcl);
30 template <
class DIRECTION = HorizontalGr
id>
32 auto sg_aabb = sg_ptr->
getAABB();
33 return AABB(*sg_aabb);
38 bounds = getAABB<HorizontalGrid>(sg_ptr);
50 double min_x = std::numeric_limits<double>::max();
51 double max_x = std::numeric_limits<double>::min();
52 double min_y = std::numeric_limits<double>::max();
53 double max_y = std::numeric_limits<double>::min();
54 if (objects_in.size() == 0) {
61 for (
auto obj : objects_in) {
64 min_x = std::min(min_x, aabb.
x_min);
65 min_y = std::min(min_y, aabb.
y_min);
66 max_x = std::max(max_x, aabb.
x_max);
67 max_y = std::max(max_y, aabb.
y_max);
70 bounds =
AABB(min_x, max_x, min_y, max_y);
88 std::set<CollisionObject*>& candidates) {
90 if (proxy.
mask & obj.mask) {
91 candidates.insert(obj.obj_ptr);
100 typedef Eigen::Matrix<uint64_t, Eigen::Dynamic, 1>
VectorXi64;
102 template <
class DIRECTION = HorizontalGr
id>
105 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
107 constructHelper(rotated_bounds->
x_min, rotated_bounds->
x_max,
108 rotated_bounds->
y_min, rotated_bounds->
y_max, sett);
113 constructHelper(rotated_bounds->
x_min, rotated_bounds->
x_max,
114 rotated_bounds->
y_min, rotated_bounds->
y_max, sett);
115 for (
auto obj : sg_ptr->
unpack()) {
123 constructHelper(rotated_bounds->
x_min, rotated_bounds->
x_max,
124 rotated_bounds->
y_min, rotated_bounds->
y_max, sett);
126 for (
auto obj : objects_in) {
136 int cell_start = getCell_first(aabb.
x_min);
137 int cell_end = getCell_first(aabb.
x_max);
138 registerObjectId(obj);
139 aabbs_.push_back(aabb);
140 aabbs_2_.emplace_back(aabb);
142 ObjectProxy proxy = CreateProxy(obj, aabbs_.back());
143 for (
int i = cell_start; i <= cell_end; i++) {
144 cells_[i].addObject(proxy);
163 int cell_start = getCell_first(aabb.
x_min);
164 int cell_end = getCell_first(aabb.
x_max);
173 for (
int i = cell_start; i <= cell_end; i++) {
174 numchecks_ += cells_[i].objects.size();
181 for (
int i = 0; i < objects_optimized_id_.size(); i++) {
185 collision_candidates2.push_back(objects_optimized_id_[i]);
190 std::sort(collision_candidates2.begin(), collision_candidates2.end());
191 std::set<int> collision_candidates_set;
192 for (
auto el : collision_candidates) {
193 collision_candidates_set.insert(el);
195 std::sort(collision_candidates.begin(), collision_candidates.end());
196 int found_count = std::unique(collision_candidates.begin(),
197 collision_candidates.end()) -
198 collision_candidates.begin();
199 int real_count = std::unique(collision_candidates2.begin(),
200 collision_candidates2.end()) -
201 collision_candidates2.begin();
203 volatile int missed = real_count - found_count;
205 bool bMissed =
false;
207 for (
auto el : collision_candidates2) {
208 if (collision_candidates_set.find(el) ==
209 collision_candidates_set.end()) {
215 if (missed > 0 || bMissed) {
216 std::cout <<
"broadphase verification: miss\n";
217 throw std::exception();
224 collision_checked_id_.fill(0);
225 int numcands_local = 0;
228 std::vector<OBB_SAT2D, Eigen::aligned_allocator<OBB_SAT2D>>
230 obb1_fast_container.emplace_back(obb1->
center(), obb1->
r_x() * 2,
234 for (
auto el : collision_candidates) {
235 if ((el < 0) || (el >= fast_obbs_.size())) {
236 std::cout <<
"internal error";
237 throw std::exception();
240 if (!collision_checked_id_(el)) {
241 collision_checked_id_(el) = 1;
244 if (skip_obb_bbox || aabbs_2_[el].collides(aabb2)) {
245 if (fast_obbs_[el].
overlaps(*(obb1_fast_container.begin()))) {
246 numcands_ += numcands_local;
252 }
else if (optimize_triangles_ &&
256 std::vector<OBB_SAT2D, Eigen::aligned_allocator<OBB_SAT2D>>
258 obb1_fast_container.emplace_back(obb1->
center(), obb1->
r_x() * 2,
262 for (
auto el : collision_candidates) {
263 if (!collision_checked_id_(el)) {
264 collision_checked_id_(el) = 1;
268 if (aabbs_2_[el].collides(aabb2)) {
269 collision_candidates2.push_back(el);
273 for (
auto el : collision_candidates2) {
275 (*(obb1_fast_container.begin())))) {
276 numcands_ += numcands_local;
281 for (
auto el : collision_candidates) {
282 if (!collision_checked_id_(el)) {
283 collision_checked_id_(el) = 1;
287 if (aabbs_2_[el].collides(aabb2)) {
288 collision_candidates2.push_back(el);
292 for (
auto el : collision_candidates2) {
293 if (object_by_id_[el]->collide(*obj)) {
294 numcands_ += numcands_local;
299 numcands_ += numcands_local;
306 int cell_start = getCell_first(aabb.
x_min);
307 int cell_end = getCell_first(aabb.
x_max);
314 for (
int i = cell_start; i <= cell_end; i++) {
315 numchecks_ += cells_[i].objects.size();
319 collision_checked_id_.fill(0);
320 int numcands_local = 0;
321 for (
auto el : collision_candidates) {
322 if (!collision_checked_id_(el)) {
323 collision_checked_id_(el) = 1;
325 if (aabbs_2_[el].collides(aabb2)) {
327 candidates.push_back(el);
331 numcands_ += numcands_local;
338 uint64_t proxy_mask = proxy.
mask;
340 int cell_start_idx = cell_start_[cell_ind];
341 int cell_end_idx = cell_end_[cell_ind];
342 if (cell_end_idx < cell_start_idx)
return 0;
343 auto object_iterator = objects_optimized_id_.begin() + cell_start_idx;
344 uint64_t* mask_iterator = masks_optimized_.data() + cell_start_idx;
346 for (
int obj_idx = cell_start_idx; obj_idx <= cell_end_idx; obj_idx++) {
347 if (*mask_iterator & proxy_mask) {
348 candidates.push_back(*object_iterator);
357 auto search = object_ids_.find(obj);
358 if (search != object_ids_.end()) {
359 return search->second;
361 throw std::exception();
364 inline int finalizeCreation(
void) {
365 cell_start_.resize(cells_.size());
366 cell_end_.resize(cells_.size());
367 int total_objects = 0;
368 for (
auto cell : cells_) {
369 total_objects += cell.objects.size();
371 objects_optimized_id_.clear();
372 object_by_id_.clear();
373 object_by_id_.resize(object_ids_.size());
374 collision_checked_id_ = Eigen::VectorXi::Zero(object_ids_.size());
376 masks_optimized_ = VectorXi64::Zero(total_objects);
377 res_mask_optimized_ = Eigen::VectorXi::Zero(total_objects);
380 all_triangles_ = optimize_triangles_;
382 for (
int i = 0; i < cells_.size(); i++) {
383 cell_start_[i] = objects_optimized_id_.size();
384 for (
auto el : cells_[i].
objects) {
390 if (all_triangles_ &&
392 all_triangles_ =
false;
395 objects_optimized_id_.push_back(getObjectId(el.obj_ptr));
396 object_by_id_[objects_optimized_id_.back()] = el.obj_ptr;
397 masks_optimized_[objects_optimized_id_.size() - 1] = el.mask;
399 cell_end_[i] = objects_optimized_id_.size() - 1;
404 inline uint64_t get_mask(
const AABB& obj) {
405 int cell_second_start = getCell_second(obj.
y_min);
406 int cell_second_end = getCell_second(obj.
y_max);
408 uint64_t cur_one = (uint64_t)0x1 << cell_second_start;
409 for (
int i = cell_second_start; i <= cell_second_end; i++) {
418 uint64_t mask = get_mask(aabb);
424 object_ids_.insert(std::make_pair(obj, (
int)object_ids_.size()));
429 fast_obbs_.emplace_back(obb_in->
center(), obb_in->
r_x() * 2,
433 if (optimize_triangles_) {
438 fast_triangles_.emplace_back(*tri_in);
449 auto aabb_fcl = obj->
getAABB();
450 return AABB(*aabb_fcl);
454 inline int getCell_first(
double first) {
455 if (first < first_start_)
return 0;
456 if (first >= first_end_)
return cells_.size() - 1;
457 return std::floor((first - first_start_) * inv_cell_size_first_) + 1;
460 inline int getCell_second(
double second) {
461 if (second < second_start_)
return 0;
462 if (second >= second_end_)
return cells_second_size_full - 1;
463 return std::floor((second - second_start_) * inv_cell_size_second_) + 1;
466 static constexpr
int cells_second_size = 62;
467 static constexpr
int cells_second_size_full = cells_second_size + 2;
468 std::vector<GridCell> cells_;
469 std::vector<AABB> aabbs_;
470 std::vector<AABB_SAT2D> aabbs_2_;
472 VectorXi64 masks_optimized_;
473 Eigen::VectorXi res_mask_optimized_;
476 std::vector<OBB_SAT2D, Eigen::aligned_allocator<OBB_SAT2D>> fast_obbs_;
477 Eigen::VectorXi collision_checked_id_;
479 std::map<const CollisionObject*, int> object_ids_;
484 std::vector<Triangle_SAT2D, Eigen::aligned_allocator<Triangle_SAT2D>>
489 bool optimize_triangles_;
492 double inv_cell_size_first_;
493 double inv_cell_size_second_;
497 double second_start_;
499 double gridlen_second_;
504 void constructHelper(
double x_start,
double x_end,
double y_start,
507 cells_.resize(numcells_ + 2);
509 first_start_ = x_start;
510 gridlen_ = first_end_ - first_start_;
512 second_start_ = y_start;
513 gridlen_second_ = second_end_ - second_start_;
516 inv_cell_size_first_ = (double)numcells_ / gridlen_;
517 inv_cell_size_second_ = (double)cells_second_size / gridlen_second_;
Eigen::Vector2d local_y_axis() const
int addObject(const CollisionObject *obj)
ContainerGrid(const ShapeGroup *sg_ptr, AABB *rotated_bounds, const ContainerSettings &sett)
std::vector< T, boost::alignment::aligned_allocator< T, 16 > > aligned_vector
int getBestGridOrientationAndBounds(const ShapeGroup *sg_ptr, AABB &bounds, int &orientation)
#define TIMER_grid_narrowphase
ContainerGrid(aligned_vector< collision::CollisionObject *> objects_in, AABB *rotated_bounds, const ContainerSettings &sett)
virtual CollisionObjectClass getCollisionObjectClass() const
std::vector< ShapeConstPtr > unpack() const
Returns Vector of all shapes contained inside the ShapeGroup.
Eigen::Matrix< uint64_t, Eigen::Dynamic, 1 > VectorXi64
std::shared_ptr< const collision::RectangleAABB > getAABB() const
bool collides_eps(const AABB_SAT2D &other, double eps)
ShapeGroup can contain simple shapes.
#define TIMER_grid_hashing
AABB getAABB(const CollisionObject *obj)
int checkCollision(const CollisionObject *obj, const ContainerCollisionRequest &req)
int addObject(ObjectProxy obj)
int orientation(Point p, Point q, Point r)
virtual CollisionObjectType getCollisionObjectType() const
int windowQuery(AABB &aabb, aligned_vector< int > &candidates)
int getCandidates(ObjectProxy &proxy, std::set< CollisionObject *> &candidates)
virtual std::shared_ptr< const collision::RectangleAABB > getAABB() const =0
Base class for CollisionObjects and some of their groups.
Eigen::Vector2d local_x_axis() const
EIGEN_MAKE_ALIGNED_OPERATOR_NEW ContainerGrid(AABB *rotated_bounds, const ContainerSettings &sett)
bool overlaps(const Triangle_SAT2D &tri, const OBB_SAT2D &obb)
#define TIMER_grid_candidates
std::vector< ObjectProxy > objects
Eigen::Vector2d center() const
Get geometric center of shape.