Free Electron
QuadTree.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2021 Free Electron Organization
2  Any use of this software requires a license. If a valid license
3  was not distributed with this file, visit freeelectron.org. */
4 
5 /** @file */
6 
7 #ifndef __surface_QuadTree_h__
8 #define __surface_QuadTree_h__
9 
10 namespace fe
11 {
12 namespace ext
13 {
14 
15 /**************************************************************************//**
16  @brief Triangular storage using divisions by quarters
17 
18  @ingroup surface
19 *//***************************************************************************/
20 class FE_DL_EXPORT QuadTree:
21  public FlatTree,
22  public ObjectSafeShared<QuadTree>,
23  public CastableAs<QuadTree>
24 {
25  public:
26  QuadTree(void);
27 virtual ~QuadTree(void);
28 
29 virtual void setRefinement(U32 a_refinement) { m_subdivMax=a_refinement; }
30 
31 virtual void populate(
32  const Vector3i* a_pElementArray,
33  const SpatialVector* a_pVertexArray,
34  const SpatialVector* a_pNormalArray,
35  const Vector2* a_pUVArray,
36  const Color* a_pColorArray,
37  const I32* a_pTriangleIndexArray,
38  const I32* a_pPointIndexArray,
39  const I32* a_pPrimitiveIndexArray,
40  const I32* a_pPartitionIndexArray,
41  U32 a_primitives,U32 a_vertices,
42  const SpatialVector& a_center,F32 a_radius);
43 virtual Real nearestPoint(const SpatialVector& a_origin,
44  Real a_maxDistance,BWORD a_anyHit,U32 a_hitLimit,
45  const sp<PartitionI>& a_rspPartition,
46  Array< sp<SpatialTreeI::Hit> >& a_rHitArray)
47  const;
48 virtual Real rayImpact(const SpatialVector& a_origin,
49  const SpatialVector& a_direction,
50  Real a_maxDistance,BWORD a_anyHit,U32 a_hitLimit,
51  const sp<PartitionI>& a_rspPartition,
52  Array< sp<SpatialTreeI::Hit> >& a_rHitArray)
53  const;
54 
55 virtual void draw(sp<DrawI> a_spDrawI,const fe::Color* a_pColor) const;
56 
57 static void expandBox(SpatialVector& a_rMin,SpatialVector& a_rMax,
58  const SpatialVector& a_rLowPoint,
59  const SpatialVector& a_rHighPoint);
60 
61  Real nearestTo(BWORD a_mutable,BWORD a_directional,
62  const SpatialVector& a_origin,
63  const SpatialVector& a_direction,
64  Real a_maxDistance,BWORD a_anyHit,U32 a_hitLimit,
65  const sp<PartitionI>& a_rspPartition,
66  Array< sp<SpatialTreeI::Hit> >& a_rHitArray,
67  U32 a_subdivMax) const;
68 
69  void age(void);
70 
71  class Key
72  {
73  public:
74  U32 m_ballIndex;
75  SpatialVector m_center;
76 
77  static int compare(const void* a_pVoid1,const void* a_pVoid2);
78  };
79 
80  class FE_DL_EXPORT BaseNode:
81  public DAGNode,
82  public CastableAs<BaseNode>
83  {
84  public:
85  U32 m_level;
86  String m_debugText;
87 
88  Vector4 m_boundSphere;
89 
90  //* bounding box
91  SpatialVector m_boundMin;
92  SpatialVector m_boundMax;
93 
94  BaseNode(void):
95  m_level(0)
96  {
97  setName("QuadTree::BaseNode");
98  set(m_boundSphere);
99  }
100  virtual ~BaseNode(void) {}
101 
102  void subdivide(
103  const Vector3i* a_pElementArray,
104  const SpatialVector* a_pVertexArray,
105  const SpatialVector* a_pNormalArray,
106  const Vector2* a_pUVArray,
107  const Key* a_pKeys,
108  U32 a_keyIndex,U32 a_keyCount,
109  U32 a_level,U32 a_maxLevel,
110  U32 a_timeStamp);
111 
112  virtual void subdivideOne(
113  const Vector3i* a_pElementArray,
114  const SpatialVector* a_pVertexArray,
115  const SpatialVector* a_pNormalArray,
116  const Vector2* a_pUVArray,
117  U32 a_triangleIndex,
118  U32 a_level,U32 a_maxLevel,
119  U32 a_timeStamp) =0;
120  virtual void subdivideAll(
121  const Vector3i* a_pElementArray,
122  const SpatialVector* a_pVertexArray,
123  const SpatialVector* a_pNormalArray,
124  const Vector2* a_pUVArray,
125  U32 a_level,U32 a_maxLevel,
126  U32 a_timeStamp) =0;
127 
128  void draw(sp<DrawI> a_spDrawI,
129  const Vector3i* a_pElementArray,
130  const SpatialVector* a_pVertexArray,
131  const SpatialVector* a_pNormalArray,
132  const Color* a_pColor,
133  U32 a_level) const;
134  static void calcFrames(
135  SpatialTransform& a_rTransform1,
136  SpatialTransform& a_rTransform2,
137  const SpatialVector& a_rVertex1,
138  const SpatialVector& a_rNormal1,
139  const SpatialVector& a_rVertex2,
140  const SpatialVector& a_rNormal2);
141  Real separation(const SpatialVector& a_origin) const;
142 
143  void nearestTo(BWORD a_mutable,BWORD a_directional,
144  const SpatialVector& a_origin,
145  const SpatialVector& a_direction,
146  Real a_maxDistance,BWORD a_anyHit,
147  U32 a_hitLimit,
148  const sp<PartitionI>& a_rspPartition,
150  a_rHitArray,
151  CountedPool<Hit>& a_rHitPool,
152  U32 a_subdivMax,
153  SurfaceI::Accuracy a_accuracy,
154  const Vector3i* a_pElementArray,
155  const I32* a_pPointIndexArray,
156  const SpatialVector* a_pVertexArray,
157  const SpatialVector* a_pNormalArray,
158  const Vector2* a_pUVArray,
159  const Color* a_pColorArray,
160  const Ball* a_pBallArray,
161  U32 a_timeStamp) const;
162 
163  virtual I32 face(U32 a_keyIndex,
164  const Ball* a_pBallArray) const =0;
165  virtual U32 faceCount(void) const =0;
166  virtual
167  const I32* facePointIndex(
168  const Ball* a_pBallArray,
169  const Vector3i* a_pElementArray,
170  const I32* a_pPointIndexArray,
171  U32 a_keyIndex) const =0;
172  virtual
173  const SpatialVector* faceVertex(
174  const Ball* a_pBallArray,
175  const Vector3i* a_pElementArray,
176  const SpatialVector* a_pVertexArray,
177  U32 a_keyIndex) const =0;
178  virtual
179  const SpatialVector* faceNormal(
180  const Ball* a_pBallArray,
181  const Vector3i* a_pElementArray,
182  const SpatialVector* a_pNormalArray,
183  U32 a_keyIndex) const =0;
184  virtual
185  const Vector2* faceUV(
186  const Ball* a_pBallArray,
187  const Vector3i* a_pElementArray,
188  const Vector2* a_pUVArray,
189  U32 a_keyIndex) const =0;
190  virtual
191  const Color* faceColor(
192  const Ball* a_pBallArray,
193  const Vector3i* a_pElementArray,
194  const Color* a_pColorArray,
195  U32 a_keyIndex) const =0;
196 
197  virtual I32 ballIndex(U32 a_keyIndex) const { return -1; }
198  virtual
199  const Vector4 sphereData(U32 a_keyIndex,
200  const Ball* a_pBallArray) const
201  { return Vector4(0.0f,0.0f,0.0f,0.0f); }
202 
203  void prune(U32 a_timeStamp);
204  };
205 
206  class FE_DL_EXPORT Node:
207  public BaseNode,
208  public CastableAs<Node>
209  {
210  public:
211  Key* m_pKeyArray;
212  U32 m_keyCount;
213 
214  //* only for QuadTree::addJob()
215  hp<QuadTree> m_hpQuadTree;
216 
217  Node(void):
218  m_pKeyArray(NULL),
219  m_keyCount(0)
220  {
221  setName("QuadTree::Node");
222  }
223 
224  virtual ~Node(void) {}
225 
226  void refine(
227  const Vector3i* a_pElementArray,
228  const SpatialVector* a_pVertexArray,
229  const SpatialVector* a_pNormalArray,
230  SpatialVector* a_pVertexScratch,
231  const Vector3u& a_divisions,
232  const Ball* a_pBallArray,
233  U32 a_capacity);
234  void split(U32 a_axis,Key*& a_rpKeys,U32& a_rKeyCount,
235  U32 divisions,
236  Key** a_rppKeys,U32* a_rpKeyCount);
237  static U32 quickSelect(Key*& a_rpKeys,U32& a_keyCount,
238  U32 a_selectIndex,U32 a_axis);
239  static U32 select(Key*& a_rpKeys,U32 a_count,
240  U32 a_left,U32 a_right,
241  U32 a_selectIndex,U32 a_axis);
242  static U32 partition(Key*& a_rpKeys,U32 a_count,
243  U32 a_left,U32 a_right,
244  U32 a_pivotIndex,U32 a_axis);
245 
246  void calcBounds(
247  const SpatialVector* a_pVertexArray,
248  const U32 a_vertexCount);
249  void calcBounds(
250  const Vector3i* a_pElementArray,
251  const SpatialVector* a_pVertexArray,
252  SpatialVector* a_pVertexScratch,
253  const Ball* a_pBallArray);
254 
255  virtual void subdivideOne(
256  const Vector3i* a_pElementArray,
257  const SpatialVector* a_pVertexArray,
258  const SpatialVector* a_pNormalArray,
259  const Vector2* a_pUVArray,
260  U32 a_triangleIndex,
261  U32 a_level,U32 a_maxLevel,U32 a_timeStamp);
262  virtual void subdivideAll(
263  const Vector3i* a_pElementArray,
264  const SpatialVector* a_pVertexArray,
265  const SpatialVector* a_pNormalArray,
266  const Vector2* a_pUVArray,
267  U32 a_level,U32 a_maxLevel,
268  U32 a_timeStamp);
269 
270  virtual I32 face(U32 a_keyIndex,const Ball* a_pBallArray) const
271  { FEASSERT(a_keyIndex<m_keyCount);
272  return a_pBallArray[ballIndex(a_keyIndex)]
273  .m_faceIndex; }
274 
275  virtual U32 faceCount(void) const
276  { return m_keyCount; }
277  virtual
278  const I32* facePointIndex(
279  const Ball* a_pBallArray,
280  const Vector3i* a_pElementArray,
281  const I32* a_pPointIndexArray,
282  U32 a_keyIndex) const
283  {
284  const U32 faceIndex=
285  face(a_keyIndex,a_pBallArray);
286  const U32 startIndex=
287  a_pElementArray[faceIndex][0];
288  return &a_pPointIndexArray[startIndex];
289  }
290  virtual
291  const SpatialVector* faceVertex(
292  const Ball* a_pBallArray,
293  const Vector3i* a_pElementArray,
294  const SpatialVector* a_pVertexArray,
295  U32 a_keyIndex) const
296  {
297  const U32 faceIndex=
298  face(a_keyIndex,a_pBallArray);
299  const U32 startIndex=
300  a_pElementArray[faceIndex][0];
301  return &a_pVertexArray[startIndex];
302  }
303  virtual
304  const SpatialVector* faceNormal(
305  const Ball* a_pBallArray,
306  const Vector3i* a_pElementArray,
307  const SpatialVector* a_pNormalArray,
308  U32 a_keyIndex) const
309  {
310  const U32 faceIndex=
311  face(a_keyIndex,a_pBallArray);
312  const U32 startIndex=
313  a_pElementArray[faceIndex][0];
314  return &a_pNormalArray[startIndex];
315  }
316  virtual
317  const Vector2* faceUV(
318  const Ball* a_pBallArray,
319  const Vector3i* a_pElementArray,
320  const Vector2* a_pUVArray,
321  U32 a_keyIndex) const
322  {
323  const U32 faceIndex=
324  face(a_keyIndex,a_pBallArray);
325  const U32 startIndex=
326  a_pElementArray[faceIndex][0];
327  return a_pUVArray? &a_pUVArray[startIndex]:
328  NULL;
329  }
330  virtual
331  const Color* faceColor(
332  const Ball* a_pBallArray,
333  const Vector3i* a_pElementArray,
334  const Color* a_pColorArray,
335  U32 a_keyIndex) const
336  {
337  const U32 faceIndex=
338  face(a_keyIndex,a_pBallArray);
339  const U32 startIndex=
340  a_pElementArray[faceIndex][0];
341  return a_pColorArray?
342  &a_pColorArray[startIndex]: NULL;
343  }
344 
345  virtual I32 ballIndex(U32 a_keyIndex) const
346  { FEASSERT(a_keyIndex<m_keyCount);
347  return m_pKeyArray[a_keyIndex].m_ballIndex; }
348  virtual
349  const Vector4 sphereData(U32 a_keyIndex,
350  const Ball* a_pBallArray) const
351  { FEASSERT(a_keyIndex<m_keyCount);
352  return a_pBallArray[m_pKeyArray[a_keyIndex]
353  .m_ballIndex].m_sphere; }
354  };
355 
356  class FE_DL_EXPORT SubNode:
357  public BaseNode,
358  public CastableAs<SubNode>
359  {
360  public:
361  Vector3i* m_pSubdivPrimitiveArray;
362  SpatialVector* m_pSubdivVertexArray;
363  SpatialVector* m_pSubdivNormalArray;
364  Vector2* m_pSubdivUVArray;
365  U32 m_serial;
366  U32 m_subdivCount;
367  U32 m_subdivLevel;
368  U32 m_timeStamp;
369 
370  SubNode(void):
371  m_pSubdivPrimitiveArray(NULL),
372  m_pSubdivVertexArray(NULL),
373  m_pSubdivNormalArray(NULL),
374  m_pSubdivUVArray(NULL),
375  m_serial(0),
376  m_subdivCount(0),
377  m_subdivLevel(0),
378  m_timeStamp(0)
379  {
380  setName("QuadTree::SubNode");
381  }
382 
383  virtual ~SubNode(void)
384  {
385  delete[] m_pSubdivUVArray;
386  delete[] m_pSubdivNormalArray;
387  delete[] m_pSubdivVertexArray;
388  delete[] m_pSubdivPrimitiveArray;
389  }
390 
391  virtual void subdivideOne(
392  const Vector3i* a_pElementArray,
393  const SpatialVector* a_pVertexArray,
394  const SpatialVector* a_pNormalArray,
395  const Vector2* a_pUVArray,
396  U32 a_triangleIndex,
397  U32 a_level,U32 a_maxLevel,U32 a_timeStamp);
398  virtual void subdivideAll(
399  const Vector3i* a_pElementArray,
400  const SpatialVector* a_pVertexArray,
401  const SpatialVector* a_pNormalArray,
402  const Vector2* a_pUVArray,
403  U32 a_level,U32 a_maxLevel,
404  U32 a_timeStamp);
405 
406  //* TODO redo
407  virtual I32 face(U32 a_keyIndex,const Ball* a_pBallArray) const
408  { return a_keyIndex; }
409 
410  virtual U32 faceCount(void) const
411  { return m_subdivCount/3; }
412  virtual
413  const I32* facePointIndex(
414  const Ball* a_pBallArray,
415  const Vector3i* a_pElementArray,
416  const I32* a_pPointIndexArray,
417  U32 a_keyIndex) const
418  {
419  return NULL;
420  }
421  const SpatialVector* faceVertex(
422  const Ball* a_pBallArray,
423  const Vector3i* a_pElementArray,
424  const SpatialVector* a_pVertexArray,
425  U32 a_keyIndex) const
426 // { FEASSERT((a_keyIndex+1)*a_grain<=m_subdivCount);
427 // return &m_pSubdivVertexArray[a_keyIndex*a_grain]; }
428  {
429  const U32 startIndex=
430  a_pElementArray[a_keyIndex][0];
431  return &m_pSubdivVertexArray[startIndex];
432  }
433 
434  virtual
435  const SpatialVector* faceNormal(
436  const Ball* a_pBallArray,
437  const Vector3i* a_pElementArray,
438  const SpatialVector* a_pNormalArray,
439  U32 a_keyIndex) const
440 // { FEASSERT((a_keyIndex+1)*a_grain<=m_subdivCount);
441 // return &m_pSubdivNormalArray[a_keyIndex*a_grain]; }
442  {
443  const U32 startIndex=
444  a_pElementArray[a_keyIndex][0];
445  return &m_pSubdivNormalArray[startIndex];
446  }
447 
448  virtual
449  const Vector2* faceUV(
450  const Ball* a_pBallArray,
451  const Vector3i* a_pElementArray,
452  const Vector2* a_pUVArray,
453  U32 a_keyIndex) const
454 // { FEASSERT((a_keyIndex+1)*a_grain<=m_subdivCount);
455 // return m_pSubdivUVArray?
456 // &m_pSubdivUVArray[a_keyIndex*a_grain]:
457 // NULL; }
458  {
459  const U32 startIndex=
460  a_pElementArray[a_keyIndex][0];
461  return m_pSubdivUVArray?
462  &m_pSubdivUVArray[startIndex]:
463  NULL;
464  }
465 
466  virtual
467  const Color* faceColor(
468  const Ball* a_pBallArray,
469  const Vector3i* a_pElementArray,
470  const Color* a_pColorArray,
471  U32 a_keyIndex) const
472  {
473  //* TODO
474  return NULL;
475  }
476  };
477 
478  class Child
479  {
480  public:
481  Child(void): m_spNode(NULL),m_distance(0.0) {}
482  sp<BaseNode> m_spNode;
483  F32 m_distance;
484 
485  static int compare(const void* a_pVoid1,const void* a_pVoid2);
486  };
487 
488  class Worker: public Thread::Functor
489  {
490  public:
491  Worker(sp< JobQueue<I32> > a_spJobQueue,
492  U32 a_id,String a_stage):
493  m_spJobQueue(a_spJobQueue),
494  m_id(a_id) {}
495 
496  void operate(void);
497 
498  void setObject(sp<Component> a_spQuadTree)
499  { m_spQuadTree=a_spQuadTree; }
500 
501  private:
502  sp< JobQueue<I32> > m_spJobQueue;
503  U32 m_id;
504  sp<QuadTree> m_spQuadTree;
505  };
506 
507  class Job
508  {
509  public:
510  Job(void) {}
511  ~Job(void) {}
512 
513  sp<Node> m_spNode;
514  };
515 
516  void cacheSpheres(const SpatialVector& a_center,
517  F32 a_radius);
518  void buildGraph(void);
519 
520  void addJob(sp<Node> a_spNode);
521 
522 const Job lookupJob(I32 a_index);
523 
524  sp<Node> m_spRootNode;
525  sp<DrawMode> m_spWireframe;
526 
527  protected:
528  void prune(void);
529  void lockSafe(void);
530  void unlockSafe(void);
531 
532  Vector3u m_divisions;
533  U32 m_capacity;
534  U32 m_subdivMax;
535  U32 m_ageStamp;
536  U32 m_timeStamp;
537  U32 m_verticesUsed;
538 
539  sp< Gang<Worker,I32> > m_spGang;
540  Array<Job> m_jobArray;
541 };
542 
543 } /* namespace ext */
544 } /* namespace fe */
545 
546 #endif /* __surface_QuadTree_h__ */
kernel
Definition: namespace.dox:3
Node in a Directed Acyclic Graph.
Definition: DAGNode.h:18
Special vector for color (RGBA)
Definition: Color.h:21
Safe handle for shared pointer.
Definition: Handled.h:61
Automatically reference-counted string container.
Definition: String.h:128
Wrapper for std::vector.
Definition: Array.h:21
Intrusive Smart Pointer.
Definition: src/core/ptr.h:53
Triangular storage using a simple array.
Definition: FlatTree.h:20
Triangular storage using divisions by quarters.
Definition: QuadTree.h:20
Per-class participation non-RTTI fallback dynamic casting mechanism.
Definition: Castable.h:192
Object level locking for thread safety.
Definition: SafeShared.h:220