00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef __CS_FRUSTRUM_H__
00020 #define __CS_FRUSTRUM_H__
00021
00029 #include "csextern.h"
00030
00031 #include "cstypes.h"
00032 #include "csutil/refcount.h"
00033 #include "csgeom/vector3.h"
00034
00035 class csPlane3;
00036 template<class T>
00037 class csPtr;
00038 class csTransform;
00039 class csSegment3;
00040
00046 enum
00047 {
00049 CS_FRUST_OUTSIDE = 0,
00051 CS_FRUST_INSIDE = 1,
00053 CS_FRUST_COVERED = 2,
00055 CS_FRUST_PARTIAL = 3
00056 };
00059 enum csClipType
00060 {
00061 CS_CLIPINFO_ORIGINAL = 0,
00062 CS_CLIPINFO_ONEDGE = 1,
00063 CS_CLIPINFO_INSIDE = 2
00064 };
00065
00072 struct CS_CRYSTALSPACE_EXPORT csClipInfo
00073 {
00074
00075 csClipType type;
00076 union
00077 {
00078 struct { int idx; } original;
00079 struct { int i1, i2; float r; } onedge;
00080 struct { csClipInfo* ci1, * ci2; float r; } inside;
00081 };
00082
00083 csClipInfo () : type (CS_CLIPINFO_ORIGINAL) { }
00084 void Clear ();
00085 ~csClipInfo () { Clear (); }
00086
00088 inline void Copy (csClipInfo& other)
00089 {
00090 if (&other == this) return;
00091 Clear ();
00092 type = other.type;
00093 if (type == CS_CLIPINFO_INSIDE)
00094 {
00095 inside.r = other.inside.r;
00096 inside.ci1 = new csClipInfo ();
00097 inside.ci1->Copy (*other.inside.ci1);
00098 inside.ci2 = new csClipInfo ();
00099 inside.ci2->Copy (*other.inside.ci2);
00100 }
00101 else if (type == CS_CLIPINFO_ORIGINAL)
00102 original.idx = other.original.idx;
00103 else
00104 onedge = other.onedge;
00105 }
00106
00108 inline void Move (csClipInfo& other)
00109 {
00110 if (&other == this) return;
00111 Clear ();
00112 type = other.type;
00113 if (type == CS_CLIPINFO_INSIDE)
00114 inside = other.inside;
00115 else if (type == CS_CLIPINFO_ORIGINAL)
00116 original.idx = other.original.idx;
00117 else
00118 onedge = other.onedge;
00119 other.type = CS_CLIPINFO_ORIGINAL;
00120 }
00121
00122 inline void Dump (int indent)
00123 {
00124 char ind[255];
00125 int i;
00126 for (i = 0 ; i < indent ; i++) ind[i] = ' ';
00127 ind[i] = 0;
00128 switch (type)
00129 {
00130 case CS_CLIPINFO_ORIGINAL:
00131 printf ("%s ORIGINAL idx=%d\n", ind, original.idx);
00132 break;
00133 case CS_CLIPINFO_ONEDGE:
00134 printf ("%s ONEDGE i1=%d i2=%d r=%g\n", ind, onedge.i1, onedge.i2,
00135 onedge.r);
00136 break;
00137 case CS_CLIPINFO_INSIDE:
00138 printf ("%s INSIDE r=%g\n", ind, inside.r);
00139 inside.ci1->Dump (indent+2);
00140 inside.ci2->Dump (indent+2);
00141 break;
00142 }
00143 fflush (stdout);
00144 }
00145 };
00146
00157 class CS_CRYSTALSPACE_EXPORT csFrustum : public csRefCount
00158 {
00159 private:
00161 csVector3 origin;
00162
00168 csVector3* vertices;
00170 size_t num_vertices;
00172 size_t max_vertices;
00173
00175 csPlane3* backplane;
00176
00184 bool wide;
00185
00190 bool mirrored;
00191
00193 void Clear ();
00194
00196 void ExtendVertexArray (size_t num);
00197
00198 public:
00199
00201 csFrustum (const csVector3& o) :
00202 origin (o), vertices (0), num_vertices (0), max_vertices (0),
00203 backplane (0), wide (false), mirrored (false)
00204 { }
00205
00211 csFrustum (const csVector3& o, csVector3* verts, size_t num_verts,
00212 csPlane3* backp = 0);
00213
00219 csFrustum (const csVector3& o, size_t num_verts,
00220 csPlane3* backp = 0);
00221
00223 csFrustum (const csFrustum ©);
00224
00226 const csFrustum& operator= (const csFrustum& other);
00227
00229 virtual ~csFrustum ();
00230
00232 inline void SetOrigin (const csVector3& o) { origin = o; }
00233
00235 inline csVector3& GetOrigin () { return origin; }
00236
00238 inline const csVector3& GetOrigin () const { return origin; }
00239
00245 inline void SetMirrored (bool m) { mirrored = m; }
00246
00248 inline bool IsMirrored () const { return mirrored; }
00249
00256 void SetBackPlane (const csPlane3& plane);
00257
00261 inline csPlane3* GetBackPlane () const { return backplane; }
00262
00266 void RemoveBackPlane ();
00267
00271 void AddVertex (const csVector3& v);
00272
00276 inline size_t GetVertexCount () const { return num_vertices; }
00277
00281 inline csVector3& GetVertex (size_t idx)
00282 {
00283 CS_ASSERT (idx < num_vertices);
00284 return vertices[idx];
00285 }
00286
00290 inline const csVector3& GetVertex (size_t idx) const
00291 {
00292 CS_ASSERT (idx < num_vertices);
00293 return vertices[idx];
00294 }
00295
00299 inline csVector3* GetVertices () const { return vertices; }
00300
00304 void Transform (csTransform* trans);
00305
00311 void ClipToPlane (csVector3& v1, csVector3& v2);
00312
00321 static void ClipToPlane (csVector3* vertices, size_t& num_vertices,
00322 csClipInfo* clipinfo, const csVector3& v1, const csVector3& v2);
00323
00324 CS_DEPRECATED_METHOD_MSG("num_vertices type changed to size_t")
00325 static void ClipToPlane (csVector3* vertices, int& num_vertices,
00326 csClipInfo* clipinfo, const csVector3& v1, const csVector3& v2)
00327 {
00328 size_t nv;
00329 ClipToPlane (vertices, nv, clipinfo, v1, v2);
00330 num_vertices = int (nv);
00331 }
00332
00341 static void ClipToPlane (csVector3* vertices, size_t& num_vertices,
00342 csClipInfo* clipinfo, const csPlane3& plane);
00343
00344 CS_DEPRECATED_METHOD_MSG("num_vertices type changed to size_t")
00345 static void ClipToPlane (csVector3* vertices, int& num_vertices,
00346 csClipInfo* clipinfo, const csPlane3& plane)
00347 {
00348 size_t nv;
00349 ClipToPlane (vertices, nv, clipinfo, plane);
00350 num_vertices = int (nv);
00351 }
00352
00359 void ClipPolyToPlane (csPlane3* plane);
00360
00366 csPtr<csFrustum> Intersect (const csFrustum& other) const;
00367
00382 csPtr<csFrustum> Intersect (csVector3* poly, size_t num) const;
00383
00398 static csPtr<csFrustum> Intersect (
00399 const csVector3& frust_origin, csVector3* frust, size_t num_frust,
00400 csVector3* poly, size_t num);
00401
00416 static csPtr<csFrustum> Intersect (
00417 const csVector3& frust_origin, csVector3* frust, size_t num_frust,
00418 const csVector3& v1, const csVector3& v2, const csVector3& v3);
00419
00425 bool Intersect (csSegment3& segment);
00426
00432 static int Classify (csVector3* frustum, size_t num_frust,
00433 csVector3* poly, size_t num_poly);
00434
00441 static int BatchClassify (csVector3* frustum, csVector3* frustumNormals,
00442 size_t num_frust, csVector3* poly, size_t num_poly);
00443
00448 bool Contains (const csVector3& point);
00449
00456 static bool Contains (csVector3* frustum, size_t num_frust,
00457 const csVector3& point);
00458
00464 static bool Contains (csVector3* frustum, size_t num_frust,
00465 const csPlane3& plane, const csVector3& point);
00466
00468 inline bool IsEmpty () const { return !wide && vertices == 0; }
00469
00471 inline bool IsInfinite () const { return wide && vertices == 0 && backplane == 0; }
00472
00477 inline bool IsWide () const { return wide && vertices == 0; }
00478
00483 void MakeInfinite ();
00484
00488 void MakeEmpty ();
00489 };
00490
00493 #endif // __CS_FRUSTRUM_H__