Gray C++ Libraries  0.0.2
A set of C++ libraries for MSVC, GNU on Windows, WinCE, Linux
cSphere.h
Go to the documentation of this file.
1 //
4 //
5 
6 #ifndef _INC_cSphere_H
7 #define _INC_cSphere_H
8 #ifndef NO_PRAGMA_ONCE
9 #pragma once
10 #endif
11 
12 #include "cBounds3.h"
14 
15 namespace GrayLib
16 {
17  UNITTEST2_PREDEF(cSphere);
18  class cVariant;
19 
20  class GRAYLIB_LINK DECLSPEC_UUID("{fc4dda18-7e6b-4a0d-9be3-34366ddb059c}") cSpheref
21  {
24 
25  public:
26  typedef float DVALUE_t; //!< Dimension value type.
27  cVector3f m_vCenter; //!< Sphere center
28  DVALUE_t m_fRadius; //!< Sphere radius
29 
30  public:
31 
32  cSpheref(DVALUE_t fObjectRadius = 0) noexcept
33  : m_fRadius(fObjectRadius)
34  {
36  }
37  cSpheref(const cVector3f& vObjectCenter, DVALUE_t fObjectRadius) noexcept
38  : m_vCenter(vObjectCenter)
39  , m_fRadius(fObjectRadius)
40  {}
41  cSpheref(DVALUE_t x, DVALUE_t y, DVALUE_t z, DVALUE_t r = 0) noexcept
42  : m_vCenter(x, y, z)
43  , m_fRadius(r)
44  {}
45 
46  // Testing
47  DVALUE_t get_Radius() const
48  {
49  return m_fRadius;
50  }
51  DVALUE_t get_RadiusSq() const
52  {
53  return Calc::Sqr(m_fRadius);
54  }
55  const cVector3f& get_Center() const
56  {
57  return m_vCenter;
58  }
59 
60  bool isZero() const
61  {
62  return(m_fRadius <= 0);
63  }
64  bool operator == (const cSpheref& sphere) const
65  {
66  return(sphere.m_vCenter == m_vCenter && sphere.m_fRadius == m_fRadius);
67  }
68 
69  bool IsInSphere(const cVector3f& v) const
70  {
73  DVALUE_t fDistSq = m_vCenter.GetDistSq(v);
74  return(fDistSq <= get_RadiusSq());
75  }
76  bool IsInSphere(DVALUE_t _x, DVALUE_t _y, DVALUE_t _z) const
77  {
78  return IsInSphere(cVector3f(_x, _y, _z));
79  }
80 
81  bool IsInSphere(const cSpheref& s) const
82  {
85  DVALUE_t fDistSq = m_vCenter.GetDistSq(s.m_vCenter);
86  return (fDistSq <= Calc::Sqr(m_fRadius - s.m_fRadius));
87  }
88 
89  bool IsOverlapSphere(const cVector3f& vObjectCenter, DVALUE_t fObjectRadius) const
90  {
92  DVALUE_t fDistSq = m_vCenter.GetDistSq(vObjectCenter);
93  return (fDistSq <= Calc::Sqr(m_fRadius + fObjectRadius));
94  }
95  bool IsOverlapSphere(const cSpheref& s) const
96  {
97  return IsOverlapSphere(s.m_vCenter, s.m_fRadius);
98  }
99 
100  GINTERSECT_TYPE GetIntersectSphere(const cSpheref& s) const
101  {
106  DVALUE_t fDistSq = m_vCenter.GetDistSq(s.m_vCenter);
107  if (fDistSq >= Calc::Sqr(m_fRadius + s.m_fRadius))
108  return GINTERSECT_None;
109  DVALUE_t fRadiusDiff = m_fRadius - s.m_fRadius;
110  if (fDistSq <= Calc::Sqr(fRadiusDiff))
111  {
112  // one is inside the other.
113  if (fRadiusDiff < 0) // s is larger.
114  return GINTERSECT_In2; // *this is inside s
115  return GINTERSECT_In1; // s is inside *this.
116  }
117  return GINTERSECT_Partial; // partial overlap.
118  }
119 
120  GINTERSECT_TYPE GetIntersectBounds(const cBounds3f& bbox) const;
121  bool IsIntersectSegment(const cSegment3f& segment) const;
122  bool TestRay(const cVector3f& vPickRayOrig, const cVector3f& vPickRayDir) const;
123 
124  // Init operators
125  void SetSphere(const cVector3f &vObjectCenter, DVALUE_t fObjectRadius)
126  {
127  m_vCenter = vObjectCenter;
128  m_fRadius = fObjectRadius;
129  }
130  void SetZero()
131  {
132  m_vCenter.SetZero();
133  m_fRadius = 0;
134  }
135  void SetMax()
136  {
137  m_vCenter.SetZero();
138  m_fRadius = k_FLT_MAX2;
139  }
140  void SetFromBoxO(const cBounds3f& box)
141  {
144  m_vCenter = box.get_Center();
145  m_fRadius = box.get_Radius();
146  }
147  void SetFromBoxI(const cBounds3f& box)
148  {
151  m_vCenter = box.get_Center();
152  m_fRadius = box.get_MaxDelta() / 2;
153  }
154 
155  // Change operators.
156 
157  void put_Radius(DVALUE_t fObjectRadius)
158  {
159  m_fRadius = fObjectRadius;
160  }
161  void ScaleCoords(DVALUE_t fScale)
162  {
163  m_fRadius *= fScale;
164  m_vCenter *= fScale;
165  }
166 
167  void Encapsulate(const cVector3f& v);
168  void UnionSphere(const cSpheref& sphere);
169 
171 
172  void OrthoTransform(const cMatrix4x4f& xform)
173  {
175  cVector3f vAx(xform.m[0][0], xform.m[1][0], xform.m[2][0]); // transposed ??
176  DVALUE_t fScale = vAx.get_Magnitude();
177  m_fRadius *= fScale;
178  m_vCenter = m_vCenter.GetProj(xform);
179  }
180 
181  void BoundsAffineTransform(const cMatrix4x4f& xform)
182  {
184  cVector3f vAx(xform.m[0][0], xform.m[1][0], xform.m[2][0]); // transposed ??
185  cVector3f vAy(xform.m[0][1], xform.m[1][1], xform.m[2][1]);
186  cVector3f vAz(xform.m[0][2], xform.m[1][2], xform.m[2][2]);
187 
188  DVALUE_t fLenX = vAx.get_MagnitudeSq();
189  DVALUE_t fLenY = vAy.get_MagnitudeSq();
190  DVALUE_t fLenZ = vAz.get_MagnitudeSq();
191  DVALUE_t fScale = Calc::Sqrt(Calc::Max3(fLenX, fLenY, fLenZ));
192 
193  m_fRadius *= fScale;
194  m_vCenter = m_vCenter.GetProj(xform);
195  }
196 
197  void ComputeBoundingSphere(const cVector3f* pVerts, UINT dwNumVertices, size_t dwStride);
198 
199  // Serialize
200  ITERATE_t v_SetSphere(const cVariant& vArgs, ITERATE_t i = 0);
201  void v_GetSphere(cVariant& vArgs) const;
202 
203  ITERATE_t v_SetSphereRev(const cVariant& vArgs, ITERATE_t i = 0);
204  void v_GetSphereRev(cVariant& vArgs) const;
205 
206  UNITTEST_FRIEND(cSphere);
207  };
208 
209  class GRAYLIB_LINK cSphere2 : public cSpheref
210  {
214 
215  typedef cSpheref SUPER_t;
216 
217  protected:
218  DVALUE_t m_fRadiusSq; //!< keep radius squared. for faster access.
219  public:
220  cSphere2()
221  : cSpheref(cVector3f(0.0f, 0.0f, 0.0f), 0.0f)
222  , m_fRadiusSq(0.0f)
223  {}
224 
225  cSphere2(const cVector3f& vCenter, DVALUE_t fObjectRadius)
226  : cSpheref(vCenter, fObjectRadius)
227  , m_fRadiusSq(Calc::Sqr(fObjectRadius))
228  {}
229 
230  void put_Radius(DVALUE_t fRadius)
231  {
232  SUPER_t::put_Radius(fRadius);
233  m_fRadiusSq = Calc::Sqr(fRadius);
234  }
235  DVALUE_t get_RadiusSq() const
236  {
237  return m_fRadiusSq;
238  }
239  void SetSphere(const cVector3f &vCenter, DVALUE_t fRadius)
240  {
241  SUPER_t::SetSphere(vCenter, fRadius);
242  m_fRadiusSq = Calc::Sqr(fRadius);
243  }
244 
245  GINTERSECT_TYPE GetRayIntersectionFrustum(const cVector3f &vRayOrigin,
246  const cVector3f &vRayDir,
247  cVector3f* pvIntersect, DVALUE_t fDistMaxSq) const;
248 
249  bool IsRayIntersectionInFront(const cVector3f& vRayOrigin,
250  const cVector3f &vRayDir,
251  cVector3f* pvIntersect) const;
252 
253  bool IsRayIntersectionDistSq(const cVector3f& vRayOrigin,
254  const cVector3f &vRayDir,
255  DVALUE_t fDistMaxSq,
256  OUT cVector3f* pvIntersect) const;
257  };
258 
259  class GRAYLIB_LINK cSphereWork
260  {
263 
264  private:
265  int m_iPass; //!< pass 1 or 2 on the data set.
266 
268  cVector3f m_xmin, m_xmax, m_ymin, m_ymax, m_zmin, m_zmax; //!< used to compute box. after pass 1
269  cSphere2 m_sphere; //!< valid after pass 2
270 
271  public:
272  cSphereWork();
273  void InitWork();
274 
276  void AddVertex(const cVector3f& vTmp);
277  void InitPass2(); // we are about to make pass2 on the data set
278 
279  void AddVertices1(const cVector3f* pVerts, UINT dwNumVertices, size_t dwStride);
280  void AddVertices2(const cVector3f* pVerts, UINT dwNumVertices, size_t dwStride);
281 
282  // results
283  cBounds3f get_Box() const
284  {
286  cBounds3f bbox;
287  bbox.m_vMin.x = m_xmin.x;
288  bbox.m_vMin.y = m_ymin.y;
289  bbox.m_vMin.z = m_zmin.z;
290  bbox.m_vMax.x = m_xmax.x;
291  bbox.m_vMax.y = m_ymax.y;
292  bbox.m_vMax.z = m_zmax.z;
293  return bbox;
294  }
295  cSphere2 get_Sphere() const // get a box from my first pass data.
296  {
298  return m_sphere;
299  }
300  };
301 }
302 #endif // _INC_cSphere_H
#define GRAYLIB_LINK
Definition: GrayLibBase.h:35
#define DECLSPEC_UUID(x)
Definition: IUnknown.h:19
Definition: cVariant.h:26
Definition: cMesh.h:22
UNITTEST2_PREDEF(cQuadtree)