Blender  V2.93
SphericalGrid.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 SPHERICAL_GRID_LOGGING 0
25 
26 // I would like to avoid using deque because including ViewMap.h and <deque> or <vector> separately
27 // results in redefinitions of identifiers. ViewMap.h already includes <vector> so it should be a
28 // 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 
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:SphericalGrid: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:
103  class Iterator {
104  public:
105  // epsilon is not used in this class, but other grids with the same interface may need an
106  // epsilon
107  explicit Iterator(SphericalGrid &grid, Vec3r &center, real epsilon = 1.0e-06);
108  void initBeforeTarget();
109  void initAfterTarget();
110  void nextOccluder();
111  void nextOccludee();
112  bool validBeforeTarget();
113  bool validAfterTarget();
114  WFace *getWFace() const;
116  void reportDepth(Vec3r origin, Vec3r u, real t);
117 
118  private:
119  bool testOccluder(bool wantOccludee);
120  void markCurrentOccludeeCandidate(real depth);
121 
122  Cell *_cell;
123  Vec3r _target;
124  bool _foundOccludee;
125  real _occludeeDepth;
126  // deque<OccluderData*>::iterator _current, _occludeeCandidate;
127  vector<OccluderData *>::iterator _current, _occludeeCandidate;
128 
129 #ifdef WITH_CXX_GUARDEDALLOC
130  MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SphericalGrid:Iterator")
131 #endif
132  };
133 
135  public:
136  explicit Transform() = default;
137  explicit Transform(Transform &other);
138  Vec3r operator()(const Vec3r &point) const;
139  static Vec3r sphericalProjection(const Vec3r &M);
140  };
141 
142  private:
143  // Prevent implicit copies and assignments.
144  SphericalGrid(const SphericalGrid &other);
145  SphericalGrid &operator=(const SphericalGrid &other);
146 
147  public:
148  explicit SphericalGrid(OccluderSource &source,
149  GridDensityProvider &density,
150  ViewMap *viewMap,
151  Vec3r &viewpoint,
152  bool enableQI);
153  virtual ~SphericalGrid();
154 
155  // Generate Cell structure
156  void assignCells(OccluderSource &source, GridDensityProvider &density, ViewMap *viewMap);
157  // Fill Cells
158  void distributePolygons(OccluderSource &source);
159  // Insert one polygon into each matching cell, return true if any cell consumes the polygon
160  bool insertOccluder(OccluderSource &source, OccluderData *&occluder);
161  // Sort occluders in each cell
162  void reorganizeCells();
163 
164  Cell *findCell(const Vec3r &point);
165 
166  // Accessors:
167  bool orthographicProjection() const;
168  const Vec3r &viewpoint() const;
169  bool enableQI() const;
170 
171  private:
172  void getCellCoordinates(const Vec3r &point, unsigned &x, unsigned &y);
173 
175  // typedef PointerSequence<deque<OccluderData*>, OccluderData*> occluderContainer;
177  unsigned _cellsX, _cellsY;
178  float _cellSize;
179  float _cellOrigin[2];
180  cellContainer _cells;
181  occluderContainer _faces;
182  Vec3r _viewpoint;
183  bool _enableQI;
184 
185 #ifdef WITH_CXX_GUARDEDALLOC
186  MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SphericalGrid")
187 #endif
188 };
189 
191 {
192  _current = _cell->faces.begin();
193  while (_current != _cell->faces.end() && !testOccluder(false)) {
194  ++_current;
195  }
196 }
197 
199 {
200  if (_foundOccludee) {
201 #if SPHERICAL_GRID_LOGGING
202  if (G.debug & G_DEBUG_FREESTYLE) {
203  std::cout << "\tStarting occludee search from occludeeCandidate at depth " << _occludeeDepth
204  << std::endl;
205  }
206 #endif
207  _current = _occludeeCandidate;
208  return;
209  }
210 
211 #if SPHERICAL_GRID_LOGGING
212  if (G.debug & G_DEBUG_FREESTYLE) {
213  std::cout << "\tStarting occludee search from current position" << std::endl;
214  }
215 #endif
216 
217  while (_current != _cell->faces.end() && !testOccluder(true)) {
218  ++_current;
219  }
220 }
221 
222 inline bool SphericalGrid::Iterator::testOccluder(bool wantOccludee)
223 {
224  // End-of-list is not even a valid iterator position
225  if (_current == _cell->faces.end()) {
226  // Returning true seems strange, but it will break us out of whatever loop is calling
227  // testOccluder, and _current=_cell->face.end() will make the calling routine give up.
228  return true;
229  }
230 #if SPHERICAL_GRID_LOGGING
231  if (G.debug & G_DEBUG_FREESTYLE) {
232  std::cout << "\tTesting occluder " << (*_current)->poly.getVertices()[0];
233  for (unsigned int i = 1; i < (*_current)->poly.getVertices().size(); ++i) {
234  std::cout << ", " << (*_current)->poly.getVertices()[i];
235  }
236  std::cout << " from shape " << (*_current)->face->GetVertex(0)->shape()->GetId() << std::endl;
237  }
238 #endif
239 
240  // If we have an occluder candidate and we are unambiguously after it, abort
241  if (_foundOccludee && (*_current)->shallowest > _occludeeDepth) {
242 #if SPHERICAL_GRID_LOGGING
243  if (G.debug & G_DEBUG_FREESTYLE) {
244  std::cout << "\t\tAborting: shallowest > occludeeCandidate->deepest" << std::endl;
245  }
246 #endif
247  _current = _cell->faces.end();
248 
249  // See note above
250  return true;
251  }
252 
253  // Specific continue or stop conditions when searching for each type
254  if (wantOccludee) {
255  if ((*_current)->deepest < _target[2]) {
256 #if SPHERICAL_GRID_LOGGING
257  if (G.debug & G_DEBUG_FREESTYLE) {
258  std::cout << "\t\tSkipping: shallower than target while looking for occludee" << std::endl;
259  }
260 #endif
261  return false;
262  }
263  }
264  else {
265  if ((*_current)->shallowest > _target[2]) {
266 #if SPHERICAL_GRID_LOGGING
267  if (G.debug & G_DEBUG_FREESTYLE) {
268  std::cout << "\t\tStopping: deeper than target while looking for occluder" << std::endl;
269  }
270 #endif
271  return true;
272  }
273  }
274 
275  // Depthwise, this is a valid occluder.
276 
277  // Check to see if target is in the 2D bounding box
278  Vec3r bbMin, bbMax;
279  (*_current)->poly.getBBox(bbMin, bbMax);
280  if (_target[0] < bbMin[0] || _target[0] > bbMax[0] || _target[1] < bbMin[1] ||
281  _target[1] > bbMax[1]) {
282 #if SPHERICAL_GRID_LOGGING
283  if (G.debug & G_DEBUG_FREESTYLE) {
284  std::cout << "\t\tSkipping: bounding box violation" << std::endl;
285  }
286 #endif
287  return false;
288  }
289 
290  // We've done all the corner cutting we can. Let the caller work out whether or not the geometry
291  // is correct.
292  return true;
293 }
294 
296 {
297  // The reported depth is the length of a ray in camera space. We need to convert it into the
298  // distance from viewpoint If origin is the viewpoint, depth == t. A future optimization could
299  // allow the caller to tell us if origin is viewponit or target, at the cost of changing the
300  // OptimizedGrid API.
301  real depth = (origin + u * t).norm();
302 #if SPHERICAL_GRID_LOGGING
303  if (G.debug & G_DEBUG_FREESTYLE) {
304  std::cout << "\t\tReporting depth of occluder/ee: " << depth;
305  }
306 #endif
307  if (depth > _target[2]) {
308 #if SPHERICAL_GRID_LOGGING
309  if (G.debug & G_DEBUG_FREESTYLE) {
310  std::cout << " is deeper than target" << std::endl;
311  }
312 #endif
313  // If the current occluder is the best occludee so far, save it.
314  if (!_foundOccludee || _occludeeDepth > depth) {
315  markCurrentOccludeeCandidate(depth);
316  }
317  }
318  else {
319 #if SPHERICAL_GRID_LOGGING
320  if (G.debug & G_DEBUG_FREESTYLE) {
321  std::cout << std::endl;
322  }
323 #endif
324  }
325 }
326 
328 {
329  if (_current != _cell->faces.end()) {
330  do {
331  ++_current;
332  } while (_current != _cell->faces.end() && !testOccluder(false));
333  }
334 }
335 
337 {
338  if (_current != _cell->faces.end()) {
339  do {
340  ++_current;
341  } while (_current != _cell->faces.end() && !testOccluder(true));
342  }
343 }
344 
346 {
347  return _current != _cell->faces.end() && (*_current)->shallowest <= _target[2];
348 }
349 
351 {
352  return _current != _cell->faces.end();
353 }
354 
355 inline void SphericalGrid::Iterator::markCurrentOccludeeCandidate(real depth)
356 {
357 #if SPHERICAL_GRID_LOGGING
358  if (G.debug & G_DEBUG_FREESTYLE) {
359  std::cout << "\t\tFound occludeeCandidate at depth " << depth << std::endl;
360  }
361 #endif
362  _occludeeCandidate = _current;
363  _occludeeDepth = depth;
364  _foundOccludee = true;
365 }
366 
368 {
369  return (*_current)->face;
370 }
371 
373 {
374  return &((*_current)->cameraSpacePolygon);
375 }
376 
378  : poly(p), cameraSpacePolygon(source.getCameraSpacePolygon()), face(source.getWFace())
379 {
380  const Vec3r viewpoint(0, 0, 0);
381  // Get the point on the camera-space polygon that is closest to the viewpoint
382  // shallowest is the distance from the viewpoint to that point
384 
385  // Get the point on the camera-space polygon that is furthest from the viewpoint
386  // deepest is the distance from the viewpoint to that point
387  deepest = cameraSpacePolygon.getVertices()[2].norm();
388  for (unsigned int i = 0; i < 2; ++i) {
389  real t = cameraSpacePolygon.getVertices()[i].norm();
390  if (t > deepest) {
391  deepest = t;
392  }
393  }
394 }
395 
396 inline void SphericalGrid::Cell::checkAndInsert(OccluderSource &source,
397  Polygon3r &poly,
398  OccluderData *&occluder)
399 {
400  if (GridHelpers::insideProscenium(boundary, poly)) {
401  if (occluder == NULL) {
402  // Disposal of occluder will be handled in SphericalGrid::distributePolygons(),
403  // or automatically by SphericalGrid::_faces;
404  occluder = new OccluderData(source, poly);
405  }
406  faces.push_back(occluder);
407  }
408 }
409 
411 {
412  Polygon3r &poly(source.getGridSpacePolygon());
413  occluder = NULL;
414 
415  Vec3r bbMin, bbMax;
416  poly.getBBox(bbMin, bbMax);
417  // Check overlapping cells
418  unsigned startX, startY, endX, endY;
419  getCellCoordinates(bbMin, startX, startY);
420  getCellCoordinates(bbMax, endX, endY);
421 
422  for (unsigned int i = startX; i <= endX; ++i) {
423  for (unsigned int j = startY; j <= endY; ++j) {
424  if (_cells[i * _cellsY + j] != NULL) {
425  _cells[i * _cellsY + j]->checkAndInsert(source, poly, occluder);
426  }
427  }
428  }
429 
430  return occluder != NULL;
431 }
432 
433 } /* 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
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition: btVector3.h:263
const vector< Point > & getVertices() const
Definition: Polygon.h:81
void getBBox(Point &min, Point &max) const
Definition: Polygon.h:86
void reportDepth(Vec3r origin, Vec3r u, real t)
Iterator(SphericalGrid &grid, Vec3r &center, real epsilon=1.0e-06)
static Vec3r sphericalProjection(const Vec3r &M)
Vec3r operator()(const Vec3r &point) const
void assignCells(OccluderSource &source, GridDensityProvider &density, ViewMap *viewMap)
const Vec3r & viewpoint() const
bool orthographicProjection() const
Cell * findCell(const Vec3r &point)
void distributePolygons(OccluderSource &source)
bool insertOccluder(OccluderSource &source, OccluderData *&occluder)
#define M
static char faces[256]
VecMat::Vec3< real > Vec3r
Definition: Geom.h:42
real distancePointToPolygon(const Vec3r &point, const Polygon3r &poly)
Definition: GridHelpers.h:95
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
OccluderData(OccluderSource &source, Polygon3r &p)
#define G(x, y, z)