/* ----------------------------------------------------------------------- * * This file is part of GEL, http://www.imm.dtu.dk/GEL * Copyright (C) the authors and DTU Informatics * For license and list of authors, see ../../doc/intro.pdf * ----------------------------------------------------------------------- */ #include #include "../CGLA/statistics.h" #include "../CGLA/eigensolution.h" #include "../CGLA/Mat4x4f.h" #include "AABox.h" #include "OBox.h" #include "Triangle.h" using namespace std; using namespace CGLA; namespace { Mat3x3f compute_rotation(const vector& invec) { const int N_tri = invec.size(); Mat3x3f C; float a_H = 0; Vec3f m_H(0); for(int i=0;i CGLA::TINY) Y = normalize(Y-X*dot(X,Y)); Z = normalize(cross(X,Y)); } else if(n_eig==1) { Y = Vec3f(X[2],X[0],X[1]); Y = normalize(Y-X*dot(X,Y)); Z = normalize(cross(X,Y)); } else { X=Vec3f(1,0,0); Y=Vec3f(0,1,0); Z=Vec3f(0,0,1); } return Mat3x3f(X,Y,Z); } } namespace Geometry { bool OBox::intersect(const CGLA::Vec3f& p, const CGLA::Vec3f& d) const { Vec3f pr = R * p; Vec3f dr = R * d; return aabox.intersect(pr, dr); } 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& invec, std::vector& lvec, std::vector& 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 pts(N_pts); Vec3f tri_pmin(FLT_MAX), tri_pmax(-FLT_MAX); for(int i=0;i 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)); } }