Blender  V2.93
BoxGrid.h
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #pragma once
18 
24 #define BOX_GRID_LOGGING 0
25 
26 // I would like to avoid using deque because including ViewMap.h and <deque> or <vector>
27 // separately results in redefinitions of identifiers. ViewMap.h already includes <vector>
28 // so it should be a safe fall-back.
29 //#include <vector>
30 //#include <deque>
31 
32 #include "GridDensityProvider.h"
33 #include "OccluderSource.h"
34 #include "ViewMap.h"
35 
36 #include "../geometry/BBox.h"
37 #include "../geometry/GridHelpers.h"
38 #include "../geometry/Polygon.h"
39 
40 #include "../system/PointerSequence.h"
41 
42 #include "../winged_edge/WEdge.h"
43 
44 #include "BKE_global.h"
45 
46 #ifdef WITH_CXX_GUARDEDALLOC
47 # include "MEM_guardedalloc.h"
48 #endif
49 
50 namespace Freestyle {
51 
52 class BoxGrid {
53  public:
54  // Helper classes
55  struct OccluderData {
56  explicit OccluderData(OccluderSource &source, Polygon3r &p);
60  // N.B. We could, of course, store face in poly's userdata member, like the old ViewMapBuilder
61  // code does. However, code comments make it clear that userdata is deprecated, so we avoid the
62  // temptation to save 4 or 8 bytes.
64 
65 #ifdef WITH_CXX_GUARDEDALLOC
66  MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BoxGrid:OccluderData")
67 #endif
68  };
69 
70  private:
71  struct Cell {
72  // Can't store Cell in a vector without copy and assign
73  // Cell(const Cell& other);
74  // Cell& operator=(const Cell& other);
75 
76  explicit Cell() = default;
77 
78  static bool compareOccludersByShallowestPoint(const OccluderData *a, const OccluderData *b);
79 
80  void setDimensions(real x, real y, real sizeX, real sizeY);
81  void checkAndInsert(OccluderSource &source, Polygon3r &poly, OccluderData *&occluder);
82  void indexPolygons();
83 
84  real boundary[4];
85  // deque<OccluderData*> faces;
86  vector<OccluderData *> faces;
87  };
88 
89  public:
90  /* Iterator needs to allow the user to avoid full 3D comparison in two cases:
91  *
92  * (1) Where (*current)->deepest < target[2], where the occluder is unambiguously in front of the
93  * target point.
94  *
95  * (2) Where (*current)->shallowest > target[2], where the occluder is unambiguously in back of
96  * the target point.
97  *
98  * In addition, when used by OptimizedFindOccludee, Iterator should stop iterating as soon as it
99  * has an occludee candidate and (*current)->shallowest > candidate[2], because at that point
100  * forward no new occluder could possibly be a better occludee.
101  */
102  class Iterator {
103  public:
104  // epsilon is not used in this class, but other grids with the same interface may need an
105  // epsilon
106  explicit Iterator(BoxGrid &grid, Vec3r &center, real epsilon = 1.0e-06);
107  void initBeforeTarget();
108  void initAfterTarget();
109  void nextOccluder();
110  void nextOccludee();
111  bool validBeforeTarget();
112  bool validAfterTarget();
113  WFace *getWFace() const;
115  void reportDepth(Vec3r origin, Vec3r u, real t);
116 
117  private:
118  bool testOccluder(bool wantOccludee);
119  void markCurrentOccludeeCandidate(real depth);
120 
121  Cell *_cell;
122  Vec3r _target;
123  bool _foundOccludee;
124  real _occludeeDepth;
125  // deque<OccluderData*>::iterator _current, _occludeeCandidate;
126  vector<OccluderData *>::iterator _current, _occludeeCandidate;
127 
128 #ifdef WITH_CXX_GUARDEDALLOC
129  MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BoxGrid:Iterator")
130 #endif
131  };
132 
134  public:
135  explicit Transform() = default;
136  explicit Transform(Transform &other);
137  Vec3r operator()(const Vec3r &point) const;
138  };
139 
140  private:
141  // Prevent implicit copies and assignments.
142  BoxGrid(const BoxGrid &other);
143  BoxGrid &operator=(const BoxGrid &other);
144 
145  public:
146  explicit BoxGrid(OccluderSource &source,
147  GridDensityProvider &density,
148  ViewMap *viewMap,
149  Vec3r &viewpoint,
150  bool enableQI);
151  virtual ~BoxGrid();
152 
153  // Generate Cell structure
154  void assignCells(OccluderSource &source, GridDensityProvider &density, ViewMap *viewMap);
155  // Fill Cells
156  void distributePolygons(OccluderSource &source);
157  // Insert one polygon into each matching cell, return true if any cell consumes the polygon
158  bool insertOccluder(OccluderSource &source, OccluderData *&occluder);
159  // Sort occluders in each cell
160  void reorganizeCells();
161 
162  Cell *findCell(const Vec3r &point);
163 
164  // Accessors:
165  bool orthographicProjection() const;
166  const Vec3r &viewpoint() const;
167  bool enableQI() const;
169 
170  private:
171  void getCellCoordinates(const Vec3r &point, unsigned &x, unsigned &y);
172 
174  // typedef PointerSequence<deque<OccluderData*>, OccluderData*> occluderContainer;
176  unsigned _cellsX, _cellsY;
177  float _cellSize;
178  float _cellOrigin[2];
179  cellContainer _cells;
180  occluderContainer _faces;
181  Vec3r _viewpoint;
182  bool _enableQI;
183 
184 #ifdef WITH_CXX_GUARDEDALLOC
185  MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BoxGrid")
186 #endif
187 };
188 
190 {
191  _current = _cell->faces.begin();
192  while (_current != _cell->faces.end() && !testOccluder(false)) {
193  ++_current;
194  }
195 }
196 
198 {
199  if (_foundOccludee) {
200 #if BOX_GRID_LOGGING
201  if (G.debug & G_DEBUG_FREESTYLE) {
202  std::cout << "\tStarting occludee search from occludeeCandidate at depth " << _occludeeDepth
203  << std::endl;
204  }
205 #endif
206  _current = _occludeeCandidate;
207  return;
208  }
209 
210 #if BOX_GRID_LOGGING
211  if (G.debug & G_DEBUG_FREESTYLE) {
212  std::cout << "\tStarting occludee search from current position" << std::endl;
213  }
214 #endif
215 
216  while (_current != _cell->faces.end() && !testOccluder(true)) {
217  ++_current;
218  }
219 }
220 
221 inline bool BoxGrid::Iterator::testOccluder(bool wantOccludee)
222 {
223  // End-of-list is not even a valid iterator position
224  if (_current == _cell->faces.end()) {
225  // Returning true seems strange, but it will break us out of whatever loop is calling
226  // testOccluder, and _current = _cell->face.end() will make the calling routine give up.
227  return true;
228  }
229 #if BOX_GRID_LOGGING
230  if (G.debug & G_DEBUG_FREESTYLE) {
231  std::cout << "\tTesting occluder " << (*_current)->poly.getVertices()[0];
232  for (unsigned int i = 1; i < (*_current)->poly.getVertices().size(); ++i) {
233  std::cout << ", " << (*_current)->poly.getVertices()[i];
234  }
235  std::cout << " from shape " << (*_current)->face->GetVertex(0)->shape()->GetId() << std::endl;
236  }
237 #endif
238 
239  // If we have an occluder candidate and we are unambiguously after it, abort
240  if (_foundOccludee && (*_current)->shallowest > _occludeeDepth) {
241 #if BOX_GRID_LOGGING
242  if (G.debug & G_DEBUG_FREESTYLE) {
243  std::cout << "\t\tAborting: shallowest > occludeeCandidate->deepest" << std::endl;
244  }
245 #endif
246  _current = _cell->faces.end();
247 
248  // See note above
249  return true;
250  }
251 
252  // Specific continue or stop conditions when searching for each type
253  if (wantOccludee) {
254  if ((*_current)->deepest < _target[2]) {
255 #if BOX_GRID_LOGGING
256  if (G.debug & G_DEBUG_FREESTYLE) {
257  std::cout << "\t\tSkipping: shallower than target while looking for occludee" << std::endl;
258  }
259 #endif
260  return false;
261  }
262  }
263  else {
264  if ((*_current)->shallowest > _target[2]) {
265 #if BOX_GRID_LOGGING
266  if (G.debug & G_DEBUG_FREESTYLE) {
267  std::cout << "\t\tStopping: deeper than target while looking for occluder" << std::endl;
268  }
269 #endif
270  return true;
271  }
272  }
273 
274  // Depthwise, this is a valid occluder.
275 
276  // Check to see if target is in the 2D bounding box
277  Vec3r bbMin, bbMax;
278  (*_current)->poly.getBBox(bbMin, bbMax);
279  if (_target[0] < bbMin[0] || _target[0] > bbMax[0] || _target[1] < bbMin[1] ||
280  _target[1] > bbMax[1]) {
281 #if BOX_GRID_LOGGING
282  if (G.debug & G_DEBUG_FREESTYLE) {
283  std::cout << "\t\tSkipping: bounding box violation" << std::endl;
284  }
285 #endif
286  return false;
287  }
288 
289  // We've done all the corner cutting we can.
290  // Let the caller work out whether or not the geometry is correct.
291  return true;
292 }
293 
295 {
296  // The reported depth is the length of a ray in camera space
297  // We need to convert it into a Z-value in grid space
298  real depth = -(origin + (u * t))[2];
299 #if BOX_GRID_LOGGING
300  if (G.debug & G_DEBUG_FREESTYLE) {
301  std::cout << "\t\tReporting depth of occluder/ee: " << depth;
302  }
303 #endif
304  if (depth > _target[2]) {
305 #if BOX_GRID_LOGGING
306  if (G.debug & G_DEBUG_FREESTYLE) {
307  std::cout << " is deeper than target" << std::endl;
308  }
309 #endif
310  // If the current occluder is the best occludee so far, save it.
311  if (!_foundOccludee || _occludeeDepth > depth) {
312  markCurrentOccludeeCandidate(depth);
313  }
314  }
315  else {
316 #if BOX_GRID_LOGGING
317  if (G.debug & G_DEBUG_FREESTYLE) {
318  std::cout << std::endl;
319  }
320 #endif
321  }
322 }
323 
325 {
326  if (_current != _cell->faces.end()) {
327  do {
328  ++_current;
329  } while (_current != _cell->faces.end() && !testOccluder(false));
330  }
331 }
332 
334 {
335  if (_current != _cell->faces.end()) {
336  do {
337  ++_current;
338  } while (_current != _cell->faces.end() && !testOccluder(true));
339  }
340 }
341 
343 {
344  return _current != _cell->faces.end() && (*_current)->shallowest <= _target[2];
345 }
346 
348 {
349  return _current != _cell->faces.end();
350 }
351 
352 inline void BoxGrid::Iterator::markCurrentOccludeeCandidate(real depth)
353 {
354 #if BOX_GRID_LOGGING
355  if (G.debug & G_DEBUG_FREESTYLE) {
356  std::cout << "\t\tFound occludeeCandidate at depth " << depth << std::endl;
357  }
358 #endif
359  _occludeeCandidate = _current;
360  _occludeeDepth = depth;
361  _foundOccludee = true;
362 }
363 
365 {
366  return (*_current)->face;
367 }
368 
370 {
371  return &((*_current)->cameraSpacePolygon);
372 }
373 
375  : poly(p), cameraSpacePolygon(source.getCameraSpacePolygon()), face(source.getWFace())
376 {
377  // Set shallowest and deepest based on bbox
378  Vec3r min, max;
379  poly.getBBox(min, max);
380  shallowest = min[2];
381  deepest = max[2];
382 }
383 
384 inline void BoxGrid::Cell::checkAndInsert(OccluderSource &source,
385  Polygon3r &poly,
386  OccluderData *&occluder)
387 {
388  if (GridHelpers::insideProscenium(boundary, poly)) {
389  if (occluder == NULL) {
390  // Disposal of occluder will be handled in BoxGrid::distributePolygons(),
391  // or automatically by BoxGrid::_faces;
392  occluder = new OccluderData(source, poly);
393  }
394  faces.push_back(occluder);
395  }
396 }
397 
398 inline bool BoxGrid::insertOccluder(OccluderSource &source, OccluderData *&occluder)
399 {
400  Polygon3r &poly(source.getGridSpacePolygon());
401  occluder = NULL;
402 
403  Vec3r bbMin, bbMax;
404  poly.getBBox(bbMin, bbMax);
405  // Check overlapping cells
406  unsigned startX, startY, endX, endY;
407  getCellCoordinates(bbMin, startX, startY);
408  getCellCoordinates(bbMax, endX, endY);
409 
410  for (unsigned int i = startX; i <= endX; ++i) {
411  for (unsigned int j = startY; j <= endY; ++j) {
412  if (_cells[i * _cellsY + j] != NULL) {
413  _cells[i * _cellsY + j]->checkAndInsert(source, poly, occluder);
414  }
415  }
416  }
417 
418  return occluder != NULL;
419 }
420 
421 } /* namespace Freestyle */
@ G_DEBUG_FREESTYLE
Definition: BKE_global.h:140
NSNotificationCenter * center
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
Class to define a cell grid surrounding the projected image of a scene.
Read Guarded memory(de)allocation.
Class to define a cell grid surrounding the projected image of a scene.
Classes to define a View Map (ViewVertex, ViewEdge, etc.)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
Polygon3r * getCameraSpacePolygon()
Definition: BoxGrid.h:369
Iterator(BoxGrid &grid, Vec3r &center, real epsilon=1.0e-06)
Definition: BoxGrid.cpp:65
void reportDepth(Vec3r origin, Vec3r u, real t)
Definition: BoxGrid.h:294
WFace * getWFace() const
Definition: BoxGrid.h:364
Vec3r operator()(const Vec3r &point) const
Definition: BoxGrid.cpp:231
Transform(Transform &other)
Transform transform
Definition: BoxGrid.h:168
void assignCells(OccluderSource &source, GridDensityProvider &density, ViewMap *viewMap)
Definition: BoxGrid.cpp:117
const Vec3r & viewpoint() const
Definition: BoxGrid.cpp:221
void reorganizeCells()
Definition: BoxGrid.cpp:193
Cell * findCell(const Vec3r &point)
Definition: BoxGrid.cpp:209
bool enableQI() const
Definition: BoxGrid.cpp:226
void distributePolygons(OccluderSource &source)
Definition: BoxGrid.cpp:164
bool insertOccluder(OccluderSource &source, OccluderData *&occluder)
Definition: BoxGrid.h:398
bool orthographicProjection() const
Definition: BoxGrid.cpp:216
void getBBox(Point &min, Point &max) const
Definition: Polygon.h:86
static char faces[256]
VecMat::Vec3< real > Vec3r
Definition: Geom.h:42
bool insideProscenium(const real proscenium[4], const Polygon3r &polygon)
Definition: GridHelpers.h:126
inherits from class Rep
Definition: AppCanvas.cpp:32
static unsigned x[3]
Definition: RandGen.cpp:87
static unsigned a[3]
Definition: RandGen.cpp:92
double real
Definition: Precision.h:26
static double epsilon
#define min(a, b)
Definition: sort.c:51
OccluderData(OccluderSource &source, Polygon3r &p)
Definition: BoxGrid.h:374
float max
#define G(x, y, z)