Blender  V2.93
BoxGrid.cpp
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 
22 #include <algorithm>
23 #include <stdexcept>
24 
25 #include "BoxGrid.h"
26 
27 #include "BKE_global.h"
28 
29 using namespace std;
30 
31 namespace Freestyle {
32 
33 // Helper Classes
34 
35 // OccluderData
37 
38 // Cell
40 
41 void BoxGrid::Cell::setDimensions(real x, real y, real sizeX, real sizeY)
42 {
43  const real epsilon = 1.0e-06;
44  boundary[0] = x - epsilon;
45  boundary[1] = x + sizeX + epsilon;
46  boundary[2] = y - epsilon;
47  boundary[3] = y + sizeY + epsilon;
48 }
49 
50 bool BoxGrid::Cell::compareOccludersByShallowestPoint(const BoxGrid::OccluderData *a,
51  const BoxGrid::OccluderData *b)
52 {
53  return a->shallowest < b->shallowest;
54 }
55 
56 void BoxGrid::Cell::indexPolygons()
57 {
58  // Sort occluders by their shallowest points.
59  sort(faces.begin(), faces.end(), compareOccludersByShallowestPoint);
60 }
61 
62 // Iterator
64 
65 BoxGrid::Iterator::Iterator(BoxGrid &grid, Vec3r &center, real /*epsilon*/)
66  : _target(grid.transform(center)), _foundOccludee(false)
67 {
68  // Find target cell
69  _cell = grid.findCell(_target);
70 #if BOX_GRID_LOGGING
71  if (G.debug & G_DEBUG_FREESTYLE) {
72  cout << "Searching for occluders of edge centered at " << _target << " in cell ["
73  << 1_cell->boundary[0] << ", " << _cell->boundary[1] << ", " << _cell->boundary[2] << ", "
74  << _cell->boundary[3] << "] (" << _cell->faces.size() << " occluders)" << endl;
75  }
76 #endif
77 
78  // Set iterator
79  _current = _cell->faces.begin();
80 }
81 
82 // BoxGrid
84 
85 BoxGrid::BoxGrid(OccluderSource &source,
86  GridDensityProvider &density,
87  ViewMap *viewMap,
89  bool enableQI)
90  : _viewpoint(viewpoint), _enableQI(enableQI)
91 {
92  // Generate Cell structure
93  if (G.debug & G_DEBUG_FREESTYLE) {
94  cout << "Generate Cell structure" << endl;
95  }
96  assignCells(source, density, viewMap);
97 
98  // Fill Cells
99  if (G.debug & G_DEBUG_FREESTYLE) {
100  cout << "Distribute occluders" << endl;
101  }
102  distributePolygons(source);
103 
104  // Reorganize Cells
105  if (G.debug & G_DEBUG_FREESTYLE) {
106  cout << "Reorganize cells" << endl;
107  }
108  reorganizeCells();
109 
110  if (G.debug & G_DEBUG_FREESTYLE) {
111  cout << "Ready to use BoxGrid" << endl;
112  }
113 }
114 
115 BoxGrid::~BoxGrid() = default;
116 
118  GridDensityProvider &density,
119  ViewMap *viewMap)
120 {
121  _cellSize = density.cellSize();
122  _cellsX = density.cellsX();
123  _cellsY = density.cellsY();
124  _cellOrigin[0] = density.cellOrigin(0);
125  _cellOrigin[1] = density.cellOrigin(1);
126  if (G.debug & G_DEBUG_FREESTYLE) {
127  cout << "Using " << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square."
128  << endl;
129  cout << "Cell origin: " << _cellOrigin[0] << ", " << _cellOrigin[1] << endl;
130  }
131 
132  // Now allocate the cell table and fill it with default (empty) cells
133  _cells.resize(_cellsX * _cellsY);
134  for (cellContainer::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) {
135  (*i) = NULL;
136  }
137 
138  // Identify cells that will be used, and set the dimensions for each
139  ViewMap::fedges_container &fedges = viewMap->FEdges();
140  for (ViewMap::fedges_container::iterator f = fedges.begin(), fend = fedges.end(); f != fend;
141  ++f) {
142  if ((*f)->isInImage()) {
143  Vec3r point = transform((*f)->center3d());
144  unsigned int i, j;
145  getCellCoordinates(point, i, j);
146  if (_cells[i * _cellsY + j] == nullptr) {
147  // This is an uninitialized cell
148  real x, y, width, height;
149 
150  x = _cellOrigin[0] + _cellSize * i;
151  width = _cellSize;
152 
153  y = _cellOrigin[1] + _cellSize * j;
154  height = _cellSize;
155 
156  // Initialize cell
157  Cell *b = _cells[i * _cellsY + j] = new Cell();
158  b->setDimensions(x, y, width, height);
159  }
160  }
161  }
162 }
163 
165 {
166  unsigned long nFaces = 0;
167  unsigned long nKeptFaces = 0;
168 
169  for (source.begin(); source.isValid(); source.next()) {
170  OccluderData *occluder = nullptr;
171 
172  try {
173  if (insertOccluder(source, occluder)) {
174  _faces.push_back(occluder);
175  ++nKeptFaces;
176  }
177  }
178  catch (...) {
179  // If an exception was thrown, _faces.push_back() cannot have succeeded.
180  // occluder is not owned by anyone, and must be deleted.
181  // If the exception was thrown before or during new OccluderData(), then
182  // occluder is NULL, and this delete is harmless.
183  delete occluder;
184  throw;
185  }
186  ++nFaces;
187  }
188  if (G.debug & G_DEBUG_FREESTYLE) {
189  cout << "Distributed " << nFaces << " occluders. Retained " << nKeptFaces << "." << endl;
190  }
191 }
192 
194 {
195  // Sort the occluders by shallowest point
196  for (vector<Cell *>::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) {
197  if (*i != NULL) {
198  (*i)->indexPolygons();
199  }
200  }
201 }
202 
203 void BoxGrid::getCellCoordinates(const Vec3r &point, unsigned &x, unsigned &y)
204 {
205  x = min(_cellsX - 1, (unsigned)floor(max((double)0.0f, point[0] - _cellOrigin[0]) / _cellSize));
206  y = min(_cellsY - 1, (unsigned)floor(max((double)0.0f, point[1] - _cellOrigin[1]) / _cellSize));
207 }
208 
209 BoxGrid::Cell *BoxGrid::findCell(const Vec3r &point)
210 {
211  unsigned int x, y;
212  getCellCoordinates(point, x, y);
213  return _cells[x * _cellsY + y];
214 }
215 
217 {
218  return true;
219 }
220 
221 const Vec3r &BoxGrid::viewpoint() const
222 {
223  return _viewpoint;
224 }
225 
226 bool BoxGrid::enableQI() const
227 {
228  return _enableQI;
229 }
230 
232 {
233  return Vec3r(point[0], point[1], -point[2]);
234 }
235 
236 } /* namespace Freestyle */
@ G_DEBUG_FREESTYLE
Definition: BKE_global.h:140
Class to define a cell grid surrounding the projected image of a scene.
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 GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_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
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
void sort(btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V, int t)
Helper function of 3X3 SVD for sorting singular values.
Vec3r operator()(const Vec3r &point) const
Definition: BoxGrid.cpp:231
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
vector< FEdge * > fedges_container
Definition: ViewMap.h:66
fedges_container & FEdges()
Definition: ViewMap.h:129
static char faces[256]
VecMat::Vec3< real > Vec3r
Definition: Geom.h:42
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
float max
ccl_device_inline float2 floor(const float2 &a)
#define G(x, y, z)