/* ColDet - C++ 3D Collision Detection Library * Copyright (C) 2000 Amir Geva * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * Any comments, questions and bug reports send to: * photon@photoneffect.com * * Or visit the home page: http://photoneffect.com/coldet/ */ #include "sysdep.h" #include "box.h" __CD__BEGIN // point in box test bool Box::intersect(const Vector3D& p) const { const Vector3D& pos=getPosition(); const Vector3D& s=getSize(); if (p.x(pos.x+s.x)) return false; if (p.y(pos.y+s.y)) return false; if (p.z(pos.z+s.z)) return false; return true; } // Non-oriented intersection test bool Box::intersect(const Box& b) { const Vector3D& t1=getPosition(); Vector3D t2=getPosition()+getSize(); const Vector3D& p1=b.getPosition(); Vector3D p2=b.getPosition()+b.getSize(); return (Max(p1.x,t1.x) <= Min(p2.x,t2.x) && Max(p1.y,t1.y) <= Min(p2.y,t2.y) && Max(p1.z,t1.z) <= Min(p2.z,t2.z)); } BoxedTriangle::BoxedTriangle(const Vector3D& _1, const Vector3D& _2, const Vector3D& _3) : BoxTreeNode(), Triangle(_1,_2,_3) { m_Pos.x=Min(Min(_1.x,_2.x),_3.x); m_Pos.y=Min(Min(_1.y,_2.y),_3.y); m_Pos.z=Min(Min(_1.z,_2.z),_3.z); Vector3D mx; mx.x=Max(Max(_1.x,_2.x),_3.x); mx.y=Max(Max(_1.y,_2.y),_3.y); mx.z=Max(Max(_1.z,_2.z),_3.z); m_Size=mx-getPosition(); m_Center=getPosition()+0.5f*getSize(); } int BoxTreeInnerNode::createSons(const Vector3D& center) { int longest=0; Vector3D p=getPosition(); Vector3D s=getSize(); if (1) { Vector3D dist(Vector3D::Zero); for(unsigned i=0;icenter.x - center.x); dist.y+=flabs(bt->center.y - center.y); dist.z+=flabs(bt->center.z - center.z); } if (dist.y>dist.x && dist.y>dist.z) longest=1; else if (dist.z>dist.x && dist.z>dist.y) longest=2; } else { int dist[3]; dist[0]=dist[1]=dist[2]=0; for(unsigned i=0;icenter[j] > center[j]) dist[j]++; else dist[j]--; } for(int j=0;j<3;j++) dist[j]=abs(dist[j]); if (dist[1]center; mn.x=Min(Min(Min(bt->v1.x,bt->v2.x),bt->v3.x),mn.x); mn.y=Min(Min(Min(bt->v1.y,bt->v2.y),bt->v3.y),mn.y); mn.z=Min(Min(Min(bt->v1.z,bt->v2.z),bt->v3.z),mn.z); mx.x=Max(Max(Max(bt->v1.x,bt->v2.x),bt->v3.x),mx.x); mx.y=Max(Max(Max(bt->v1.y,bt->v2.y),bt->v3.y),mx.y); mx.z=Max(Max(Max(bt->v1.z,bt->v2.z),bt->v3.z),mx.z); } center/=float(m_Boxes.size()); m_Pos=mn; m_Size=mx-mn; if (m_Size.x==0.0f) { m_Size.x=0.002f; m_Pos.x-=0.001f; } if (m_Size.y==0.0f) { m_Size.y=0.002f; m_Pos.y-=0.001f; } if (m_Size.z==0.0f) { m_Size.z=0.002f; m_Pos.z-=0.001f; } m_Center=getPosition()+0.5f*getSize(); } int BoxTreeInnerNode::divide(int p_depth) { if (m_Boxes.empty()) return 0; Vector3D center; recalcBounds(center); int longest=createSons(center); BoxTreeInnerNode* f=static_cast(m_First); BoxTreeInnerNode* s=static_cast(m_Second); int depth=1; int bnum=m_Boxes.size(); #ifdef _DEBUG int fnum=0; #endif for(unsigned i=0;icenter[longest]m_Boxes.push_back(bt); #ifdef _DEBUG fnum++; #endif } else { s->m_Boxes.push_back(bt); } } int b1num=f->m_Boxes.size(); int b2num=s->m_Boxes.size(); if ((b1num==bnum || b2num==bnum))// && p_depth>m_logdepth) { delete m_First; m_First=NULL; delete m_Second; m_Second=NULL; return depth+1; } m_Boxes.clear(); if (f->m_Boxes.empty()) { delete m_First; m_First=NULL; } else if (f->m_Boxes.size()==1) { BoxedTriangle* bt=f->m_Boxes.back(); delete m_First; m_First=bt; } else depth=f->divide(p_depth+1); if (s->m_Boxes.empty()) { delete m_Second; m_Second=NULL; } else if (s->m_Boxes.size()==1) { BoxedTriangle* bt=s->m_Boxes.back(); delete m_Second; m_Second=bt; } else depth=Max(depth,s->divide(p_depth+1)); return depth+1; } __CD__BEGIN