OBox OBox::box_triangle(const Triangle& t) { Vec3f e0 = t.get_v1()-t.get_v0(); Vec3f e1 = t.get_v2()-t.get_v1(); Vec3f e2 = t.get_v0()-t.get_v2(); Vec3f X,Y,Z; if(sqr_length(e0) > sqr_length(e1)) { if(sqr_length(e0) > sqr_length(e2)) { X = normalize(e0); Y = normalize(e1 - X * dot(X, e1)); } else { X = normalize(e2); Y = normalize(e0 - X * dot(X, e0)); } } else { if(sqr_length(e1) > sqr_length(e2)) { X = normalize(e1); Y = normalize(e2 - X * dot(X, e2)); } else { X = normalize(e2); Y = normalize(e0 - X * dot(X, e0)); } } Z = cross(X,Y); const Mat3x3f Rot(X,Y,Z); Vec3f p0 = Rot * t.get_v0(); Vec3f p1 = Rot * t.get_v1(); Vec3f p2 = Rot * t.get_v2(); Vec3f pmin = v_min(p0, v_min(p1, p2)); Vec3f pmax = v_max(p0, v_max(p1, p2)); Vec3f centre_close = v_max(pmin, v_min(pmax, Rot * t.get_centre())); return OBox(Rot, AABox(pmin, pmax, centre_close)); }
OBox OBox::box_and_split(const std::vector<Triangle>& invec, std::vector<Triangle>& lvec, std::vector<Triangle>& rvec) { // Obtain the rotation matrix for the OBB const Mat3x3f Rot = compute_rotation(invec); const int N_tri = invec.size(); const int N_pts = 3*N_tri; // Compute the rotated set of points and the extents of the point aligned // BBox. vector<Vec3f> pts(N_pts); Vec3f tri_pmin(FLT_MAX), tri_pmax(-FLT_MAX); for(int i=0;i<N_tri;++i) { const Triangle& tri = invec[i]; int offs = 3*i; pts[offs ] = Rot*tri.get_v0(); pts[offs+1] = Rot*tri.get_v1(); pts[offs+2] = Rot*tri.get_v2(); for(int j=0;j<3;++j) { tri_pmin = v_min(pts[offs+j], tri_pmin); tri_pmax = v_max(pts[offs+j], tri_pmax); } } // Find the point closest to the centre. const Vec3f centre = tri_pmin + 0.5f*(tri_pmax-tri_pmin); Vec3f centre_close; float min_dist = FLT_MAX; for(int i=0;i<N_pts;++i) { Vec3f v = pts[i]; float sl = sqr_length(centre-v); if(sl < min_dist) { min_dist = sl; centre_close = v; } } // Partition the triangles const float thresh = centre[0]; for(int i=0;i<N_tri;++i) { Vec3f p = Rot * invec[i].get_centre(); if( p[0] > thresh) rvec.push_back(invec[i]); else lvec.push_back(invec[i]); } // If all triangles landed in one box, split them naively. if(lvec.empty() || rvec.empty()) { lvec.clear(); lvec.insert(lvec.end(), invec.begin(), invec.begin()+N_tri/2); rvec.clear(); rvec.insert(rvec.end(), invec.begin()+N_tri/2, invec.end()); } return OBox(Rot, AABox(tri_pmin, tri_pmax, centre_close)); }
OBox transform(const OBox& _box, const Quaternion& _rotation, const Vec3& _translation) noexcept { return OBox(transform(_box.center, _rotation) + _translation, _box.halfSides, _box.orientation * _rotation); }
OBox transform(const OBox& _box, const Vec3& _translation) noexcept { return OBox(_box.center + _translation, _box.halfSides, _box.orientation); }