CrystalSpace

Public API Reference

Main Page   Modules   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

box.h

Go to the documentation of this file.
00001 /*
00002     Copyright (C) 1998-2002 by Jorrit Tyberghein
00003     Largely rewritten by Ivan Avramovic <ivan@avramovic.com>
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public
00016     License along with this library; if not, write to the Free
00017     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 */
00019 
00020 #ifndef __CS_BOX_H__
00021 #define __CS_BOX_H__
00022 
00030 #include "cstypes.h"    // for bool
00031 #include "vector2.h"
00032 #include "vector3.h"
00033 #include "segment.h"
00034 
00035 class csPlane3;
00036 class csTransform;
00037 
00042 #define CS_BOUNDINGBOX_MAXVALUE 1000000000.
00043 
00047 
00048 #define CS_BOX_CORNER_xy 0
00049 
00050 #define CS_BOX_CORNER_xY 1
00051 
00052 #define CS_BOX_CORNER_Xy 2
00053 
00054 #define CS_BOX_CORNER_XY 3
00055 
00061 
00062 #define CS_BOX_EDGE_xy_Xy 0
00063 
00064 #define CS_BOX_EDGE_Xy_xy 1
00065 
00066 #define CS_BOX_EDGE_Xy_XY 2
00067 
00068 #define CS_BOX_EDGE_XY_Xy 3
00069 
00070 #define CS_BOX_EDGE_XY_xY 4
00071 
00072 #define CS_BOX_EDGE_xY_XY 5
00073 
00074 #define CS_BOX_EDGE_xY_xy 6
00075 
00076 #define CS_BOX_EDGE_xy_xY 7
00077 
00086 class csBox2
00087 {
00088 private:
00089   struct bEdge
00090   {
00091     uint8 v1, v2;       // Indices of vertex in bounding box (CS_BOX_CORNER_...)
00092   };
00093   // Index by edge number. Edge e and e+1 with e even are opposite edges.
00094   // (CS_BOX_EDGE_...)
00095   static bEdge edges[8];
00096 
00097 protected:
00099   csVector2 minbox;
00101   csVector2 maxbox;
00102 
00103 public:
00105   float MinX () const { return minbox.x; }
00107   float MinY () const { return minbox.y; }
00109   float MaxX () const { return maxbox.x; }
00111   float MaxY () const { return maxbox.y; }
00113   float Min (int idx) const { return idx ? minbox.y : minbox.x; }
00115   float Max (int idx) const { return idx ? maxbox.y : maxbox.x; }
00117   const csVector2& Min () const { return minbox; }
00119   const csVector2& Max () const { return maxbox; }
00120 
00128   csVector2 GetCorner (int corner) const;
00129 
00133   csVector2 GetCenter () const { return (minbox+maxbox)/2; }
00134 
00139   void SetCenter (const csVector2& c);
00140 
00144   void SetSize (const csVector2& s);
00145 
00150   void GetEdgeInfo (int edge, int& v1, int& v2) const
00151   {
00152     v1 = edges[edge].v1;
00153     v2 = edges[edge].v2;
00154   }
00155 
00160   csSegment2 GetEdge (int edge) const
00161   {
00162     return csSegment2 (GetCorner (edges[edge].v1), GetCorner (edges[edge].v2));
00163   }
00164 
00169   void GetEdge (int edge, csSegment2& e) const
00170   {
00171     e.SetStart (GetCorner (edges[edge].v1));
00172     e.SetEnd (GetCorner (edges[edge].v2));
00173   }
00174 
00181   static bool Intersect (float minx, float miny, float maxx, float maxy,
00182     csVector2* poly, int num_poly);
00183 
00190   static bool Intersect (const csVector2& minbox, const csVector2& maxbox,
00191     csVector2* poly, int num_poly)
00192   {
00193     return Intersect (minbox.x, minbox.y, maxbox.x, maxbox.y, poly, num_poly);
00194   }
00195 
00202   bool Intersect (csVector2* poly, int num_poly) const
00203   {
00204     return Intersect (minbox, maxbox, poly, num_poly);
00205   }
00206 
00208   bool In (float x, float y) const
00209   {
00210     if (x < minbox.x || x > maxbox.x) return false;
00211     if (y < minbox.y || y > maxbox.y) return false;
00212     return true;
00213   }
00214 
00216   bool In (const csVector2& v) const
00217   {
00218     return In (v.x, v.y);
00219   }
00220 
00222   bool Overlap (const csBox2& box) const
00223   {
00224     if (maxbox.x < box.minbox.x || minbox.x > box.maxbox.x) return false;
00225     if (maxbox.y < box.minbox.y || minbox.y > box.maxbox.y) return false;
00226     return true;
00227   }
00228 
00230   bool Contains (const csBox2& box) const
00231   {
00232     return (box.minbox.x >= minbox.x && box.maxbox.x <= maxbox.x) &&
00233            (box.minbox.y >= minbox.y && box.maxbox.y <= maxbox.y);
00234   }
00235 
00237   bool Empty () const
00238   {
00239     if (minbox.x > maxbox.x) return true;
00240     if (minbox.y > maxbox.y) return true;
00241     return false;
00242   }
00243 
00248   float SquaredOriginDist () const;
00249 
00255   float SquaredOriginMaxDist () const;
00256 
00258   void StartBoundingBox ()
00259   {
00260     minbox.x =  CS_BOUNDINGBOX_MAXVALUE;  minbox.y =  CS_BOUNDINGBOX_MAXVALUE;
00261     maxbox.x = -CS_BOUNDINGBOX_MAXVALUE;  maxbox.y = -CS_BOUNDINGBOX_MAXVALUE;
00262   }
00263 
00265   void StartBoundingBox (const csVector2& v)
00266   {
00267     minbox = v;
00268     maxbox = v;
00269   }
00270 
00272   void StartBoundingBox (float x, float y)
00273   {
00274     minbox.x = maxbox.x = x;
00275     minbox.y = maxbox.y = y;
00276   }
00277 
00279   void AddBoundingVertex (float x, float y)
00280   {
00281     if (x < minbox.x) minbox.x = x;  if (x > maxbox.x) maxbox.x = x;
00282     if (y < minbox.y) minbox.y = y;  if (y > maxbox.y) maxbox.y = y;
00283   }
00284 
00286   void AddBoundingVertex (const csVector2& v)
00287   {
00288     AddBoundingVertex (v.x, v.y);
00289   }
00290 
00296   void AddBoundingVertexSmart (float x, float y)
00297   {
00298     if (x < minbox.x) minbox.x = x; else if (x > maxbox.x) maxbox.x = x;
00299     if (y < minbox.y) minbox.y = y; else if (y > maxbox.y) maxbox.y = y;
00300   }
00301 
00307   void AddBoundingVertexSmart (const csVector2& v)
00308   {
00309     AddBoundingVertexSmart (v.x, v.y);
00310   }
00311 
00312   //-----
00313   // Maintenance Note: The csBox2 constructors and Set() appear at this point
00314   // in the file, rather than earlier, in order to appease the OpenStep 4.2
00315   // compiler.  Specifically, the problem is that the compiler botches code
00316   // generation if an unseen method (which is later declared inline) is
00317   // called from within another inline method.  For instance, if the
00318   // constructors were listed at the top of the file, rather than here, the
00319   // compiler would see calls to Empty() and StartBoundingBox() before seeing
00320   // declarations for them.  In such a situation, the buggy compiler
00321   // generates a broken object file.  The simple work-around of textually
00322   // reorganizing the file ensures that the declarations for Empty() and
00323   // StartBoundingBox() are seen before they are called.
00324   //-----
00325 
00327   csBox2 () : minbox (CS_BOUNDINGBOX_MAXVALUE, CS_BOUNDINGBOX_MAXVALUE),
00328              maxbox (-CS_BOUNDINGBOX_MAXVALUE, -CS_BOUNDINGBOX_MAXVALUE) {}
00329 
00331   csBox2 (const csVector2& v) : minbox (v.x, v.y), maxbox (v.x, v.y) {}
00332 
00334   csBox2 (float x1, float y1, float x2, float y2) :
00335     minbox (x1, y1), maxbox (x2, y2)
00336   { if (Empty ()) StartBoundingBox (); }
00337 
00339   void Set (const csVector2& bmin, const csVector2& bmax)
00340   {
00341     minbox = bmin;
00342     maxbox = bmax;
00343   }
00344 
00346   void Set (float x1, float y1, float x2, float y2)
00347   {
00348     if (x1>x2 || y1>y2) StartBoundingBox();
00349     else { minbox.x = x1;  minbox.y = y1;  maxbox.x = x2;  maxbox.y = y2; }
00350   }
00351 
00353   void SetMin (int idx, float val)
00354   {
00355     if (idx == 1) minbox.y = val;
00356     else minbox.x = val;
00357   }
00358 
00360   void SetMax (int idx, float val)
00361   {
00362     if (idx == 1) maxbox.y = val;
00363     else maxbox.x = val;
00364   }
00365 
00367   csBox2& operator+= (const csBox2& box);
00369   csBox2& operator+= (const csVector2& point);
00371   csBox2& operator*= (const csBox2& box);
00373   bool TestIntersect (const csBox2& box) const;
00374 
00376   friend csBox2 operator+ (const csBox2& box1, const csBox2& box2);
00378   friend csBox2 operator+ (const csBox2& box, const csVector2& point);
00380   friend csBox2 operator* (const csBox2& box1, const csBox2& box2);
00381 
00383   friend bool operator== (const csBox2& box1, const csBox2& box2);
00385   friend bool operator!= (const csBox2& box1, const csBox2& box2);
00387   friend bool operator< (const csBox2& box1, const csBox2& box2);
00389   friend bool operator> (const csBox2& box1, const csBox2& box2);
00391   friend bool operator< (const csVector2& point, const csBox2& box);
00392 };
00393 
00398 
00399 #define CS_BOX_CORNER_xyz 0
00400 
00401 #define CS_BOX_CORNER_xyZ 1
00402 
00403 #define CS_BOX_CORNER_xYz 2
00404 
00405 #define CS_BOX_CORNER_xYZ 3
00406 
00407 #define CS_BOX_CORNER_Xyz 4
00408 
00409 #define CS_BOX_CORNER_XyZ 5
00410 
00411 #define CS_BOX_CORNER_XYz 6
00412 
00413 #define CS_BOX_CORNER_XYZ 7
00414 
00420 
00421 #define CS_BOX_SIDE_x 0
00422 
00423 #define CS_BOX_SIDE_X 1
00424 
00425 #define CS_BOX_SIDE_y 2
00426 
00427 #define CS_BOX_SIDE_Y 3
00428 
00429 #define CS_BOX_SIDE_z 4
00430 
00431 #define CS_BOX_SIDE_Z 5
00432 
00433 #define CS_BOX_INSIDE 6
00434 
00440 
00441 #define CS_BOX_EDGE_Xyz_xyz 0
00442 
00443 #define CS_BOX_EDGE_xyz_Xyz 1
00444 
00445 #define CS_BOX_EDGE_xyz_xYz 2
00446 
00447 #define CS_BOX_EDGE_xYz_xyz 3
00448 
00449 #define CS_BOX_EDGE_xYz_XYz 4
00450 
00451 #define CS_BOX_EDGE_XYz_xYz 5
00452 
00453 #define CS_BOX_EDGE_XYz_Xyz 6
00454 
00455 #define CS_BOX_EDGE_Xyz_XYz 7
00456 
00457 #define CS_BOX_EDGE_Xyz_XyZ 8
00458 
00459 #define CS_BOX_EDGE_XyZ_Xyz 9
00460 
00461 #define CS_BOX_EDGE_XyZ_XYZ 10
00462 
00463 #define CS_BOX_EDGE_XYZ_XyZ 11
00464 
00465 #define CS_BOX_EDGE_XYZ_XYz 12
00466 
00467 #define CS_BOX_EDGE_XYz_XYZ 13
00468 
00469 #define CS_BOX_EDGE_XYZ_xYZ 14
00470 
00471 #define CS_BOX_EDGE_xYZ_XYZ 15
00472 
00473 #define CS_BOX_EDGE_xYZ_xYz 16
00474 
00475 #define CS_BOX_EDGE_xYz_xYZ 17
00476 
00477 #define CS_BOX_EDGE_xYZ_xyZ 18
00478 
00479 #define CS_BOX_EDGE_xyZ_xYZ 19
00480 
00481 #define CS_BOX_EDGE_xyZ_xyz 20
00482 
00483 #define CS_BOX_EDGE_xyz_xyZ 21
00484 
00485 #define CS_BOX_EDGE_xyZ_XyZ 22
00486 
00487 #define CS_BOX_EDGE_XyZ_xyZ 23
00488 
00497 class csBox3
00498 {
00499 protected:
00501   csVector3 minbox;
00503   csVector3 maxbox;
00505   struct bEdge
00506   {
00507     uint8 v1, v2; // Indices of vertex in bounding box (CS_BOX_CORNER_...)
00508     uint8 fl, fr; // Indices of left/right faces sharing edge (CS_BOX_SIDE_...)
00509   };
00511   typedef uint8 bFace[4];       
00516   static bEdge edges[24];
00518   static bFace faces[6];
00519 public:
00521   float MinX () const { return minbox.x; }
00523   float MinY () const { return minbox.y; }
00525   float MinZ () const { return minbox.z; }
00527   float MaxX () const { return maxbox.x; }
00529   float MaxY () const { return maxbox.y; }
00531   float MaxZ () const { return maxbox.z; }
00533   float Min (int idx) const
00534   { return idx == 1 ? minbox.y : idx == 0 ? minbox.x : minbox.z; }
00536   float Max (int idx) const
00537   { return idx == 1 ? maxbox.y : idx == 0 ? maxbox.x : maxbox.z; }
00539   const csVector3& Min () const { return minbox; }
00541   const csVector3& Max () const { return maxbox; }
00542 
00551   csVector3 GetCorner (int corner) const;
00552 
00557   void GetEdgeInfo (int edge, int& v1, int& v2, int& fleft, int& fright) const
00558   {
00559     v1 = edges[edge].v1;
00560     v2 = edges[edge].v2;
00561     fleft = edges[edge].fl;
00562     fright = edges[edge].fr;
00563   }
00564 
00569   uint8* GetFaceEdges (int face) const
00570   {
00571     return faces[face];
00572   }
00573 
00577   csVector3 GetCenter () const { return (minbox+maxbox)/2; }
00578 
00583   void SetCenter (const csVector3& c);
00584 
00588   void SetSize (const csVector3& s);
00589 
00594   csBox2 GetSide (int side) const;
00595 
00602   int GetVisibleSides (const csVector3& pos, int* visible_sides) const;
00603 
00608   static int OtherSide (int side)
00609   {
00610     return side ^ 1;
00611   }
00612 
00618   csSegment3 GetEdge (int edge) const
00619   {
00620     return csSegment3 (GetCorner (edges[edge].v1), GetCorner (edges[edge].v2));
00621   }
00622 
00628   void GetEdge (int edge, csSegment3& e) const
00629   {
00630     e.SetStart (GetCorner (edges[edge].v1));
00631     e.SetEnd (GetCorner (edges[edge].v2));
00632   }
00633 
00635   bool In (float x, float y, float z) const
00636   {
00637     if (x < minbox.x || x > maxbox.x) return false;
00638     if (y < minbox.y || y > maxbox.y) return false;
00639     if (z < minbox.z || z > maxbox.z) return false;
00640     return true;
00641   }
00642 
00644   bool In (const csVector3& v) const
00645   {
00646     return In (v.x, v.y, v.z);
00647   }
00648 
00650   bool Overlap (const csBox3& box) const
00651   {
00652     if (maxbox.x < box.minbox.x || minbox.x > box.maxbox.x) return false;
00653     if (maxbox.y < box.minbox.y || minbox.y > box.maxbox.y) return false;
00654     if (maxbox.z < box.minbox.z || minbox.z > box.maxbox.z) return false;
00655     return true;
00656   }
00657 
00659   bool Contains (const csBox3& box) const
00660   {
00661     return (box.minbox.x >= minbox.x && box.maxbox.x <= maxbox.x) &&
00662            (box.minbox.y >= minbox.y && box.maxbox.y <= maxbox.y) &&
00663            (box.minbox.z >= minbox.z && box.maxbox.z <= maxbox.z);
00664   }
00665 
00667   bool Empty () const
00668   {
00669     if (minbox.x > maxbox.x) return true;
00670     if (minbox.y > maxbox.y) return true;
00671     if (minbox.z > maxbox.z) return true;
00672     return false;
00673   }
00674 
00676   void StartBoundingBox ()
00677   {
00678     minbox.x =  CS_BOUNDINGBOX_MAXVALUE;
00679     minbox.y =  CS_BOUNDINGBOX_MAXVALUE;
00680     minbox.z =  CS_BOUNDINGBOX_MAXVALUE;
00681     maxbox.x = -CS_BOUNDINGBOX_MAXVALUE;
00682     maxbox.y = -CS_BOUNDINGBOX_MAXVALUE;
00683     maxbox.z = -CS_BOUNDINGBOX_MAXVALUE;
00684   }
00685 
00687   void StartBoundingBox (const csVector3& v)
00688   {
00689     minbox = v; maxbox = v;
00690   }
00691 
00693   void AddBoundingVertex (float x, float y, float z)
00694   {
00695     if (x < minbox.x) minbox.x = x; if (x > maxbox.x) maxbox.x = x;
00696     if (y < minbox.y) minbox.y = y; if (y > maxbox.y) maxbox.y = y;
00697     if (z < minbox.z) minbox.z = z; if (z > maxbox.z) maxbox.z = z;
00698   }
00699 
00701   void AddBoundingVertex (const csVector3& v)
00702   {
00703     AddBoundingVertex (v.x, v.y, v.z);
00704   }
00705 
00711   void AddBoundingVertexSmart (float x, float y, float z)
00712   {
00713     if (x < minbox.x) minbox.x = x; else if (x > maxbox.x) maxbox.x = x;
00714     if (y < minbox.y) minbox.y = y; else if (y > maxbox.y) maxbox.y = y;
00715     if (z < minbox.z) minbox.z = z; else if (z > maxbox.z) maxbox.z = z;
00716   }
00717 
00723   void AddBoundingVertexSmart (const csVector3& v)
00724   {
00725     AddBoundingVertexSmart (v.x, v.y, v.z);
00726   }
00727 
00728   //-----
00729   // Maintenance Note: The csBox3 constructors and Set() appear at this point
00730   // in the file, rather than earlier, in order to appease the OpenStep 4.2
00731   // compiler.  Specifically, the problem is that the compiler botches code
00732   // generation if an unseen method (which is later declared inline) is
00733   // called from within another inline method.  For instance, if the
00734   // constructors were listed at the top of the file, rather than here, the
00735   // compiler would see calls to Empty() and StartBoundingBox() before seeing
00736   // declarations for them.  In such a situation, the buggy compiler
00737   // generated a broken object file.  The simple work-around of textually
00738   // reorganizing the file ensures that the declarations for Empty() and
00739   // StartBoundingBox() are seen before they are called.
00740   //-----
00741 
00743   csBox3 () :
00744     minbox ( CS_BOUNDINGBOX_MAXVALUE,
00745              CS_BOUNDINGBOX_MAXVALUE,
00746              CS_BOUNDINGBOX_MAXVALUE),
00747     maxbox (-CS_BOUNDINGBOX_MAXVALUE,
00748             -CS_BOUNDINGBOX_MAXVALUE,
00749             -CS_BOUNDINGBOX_MAXVALUE) {}
00750 
00752   csBox3 (const csVector3& v) : minbox (v), maxbox (v) { }
00753 
00755   csBox3 (const csVector3& v1, const csVector3& v2) :
00756         minbox (v1), maxbox (v2)
00757   { if (Empty ()) StartBoundingBox (); }
00758 
00760   csBox3 (float x1, float y1, float z1, float x2, float y2, float z2) :
00761     minbox (x1, y1, z1), maxbox (x2, y2, z2)
00762   { if (Empty ()) StartBoundingBox (); }
00763 
00765   void Set (const csVector3& bmin, const csVector3& bmax)
00766   {
00767     minbox = bmin;
00768     maxbox = bmax;
00769   }
00770 
00772   void Set (float x1, float y1, float z1, float x2, float y2, float z2)
00773   {
00774     if (x1>x2 || y1>y2 || z1>z2) StartBoundingBox();
00775     else
00776     {
00777       minbox.x = x1; minbox.y = y1; minbox.z = z1;
00778       maxbox.x = x2; maxbox.y = y2; maxbox.z = z2;
00779     }
00780   }
00781 
00783   void SetMin (int idx, float val)
00784   {
00785     if (idx == 1) minbox.y = val;
00786     else if (idx == 0) minbox.x = val;
00787     else minbox.z = val;
00788   }
00789 
00791   void SetMax (int idx, float val)
00792   {
00793     if (idx == 1) maxbox.y = val;
00794     else if (idx == 0) maxbox.x = val;
00795     else maxbox.z = val;
00796   }
00797 
00801   bool AdjacentX (const csBox3& other) const;
00802 
00806   bool AdjacentY (const csBox3& other) const;
00807 
00811   bool AdjacentZ (const csBox3& other) const;
00812 
00819   int Adjacent (const csBox3& other) const;
00820 
00827   int CalculatePointSegment (const csVector3& pos) const;
00828 
00837   void GetConvexOutline (const csVector3& pos,
00838         csVector3* array, int& num_array, bool bVisible=false) const;
00839 
00843   bool Between (const csBox3& box1, const csBox3& box2) const;
00844 
00849   void ManhattanDistance (const csBox3& other, csVector3& dist) const;
00850 
00855   float SquaredOriginDist () const;
00856 
00862   float SquaredOriginMaxDist () const;
00863 
00875   bool ProjectBox (const csTransform& trans, float fov, float sx, float sy,
00876         csBox2& sbox, float& min_z, float& max_z) const;
00877 
00879   csBox3& operator+= (const csBox3& box);
00881   csBox3& operator+= (const csVector3& point);
00883   csBox3& operator*= (const csBox3& box);
00885   bool TestIntersect (const csBox3& box) const;
00886 
00888   friend csBox3 operator+ (const csBox3& box1, const csBox3& box2);
00890   friend csBox3 operator+ (const csBox3& box, const csVector3& point);
00892   friend csBox3 operator* (const csBox3& box1, const csBox3& box2);
00893 
00895   friend bool operator== (const csBox3& box1, const csBox3& box2);
00897   friend bool operator!= (const csBox3& box1, const csBox3& box2);
00899   friend bool operator< (const csBox3& box1, const csBox3& box2);
00901   friend bool operator> (const csBox3& box1, const csBox3& box2);
00903   friend bool operator< (const csVector3& point, const csBox3& box);
00904 };
00905 
00908 #endif // __CS_BOX_H__

Generated for Crystal Space by doxygen 1.2.14