Blender  V3.3
SphericalGrid.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
8 #include <algorithm>
9 #include <stdexcept>
10 
11 #include "SphericalGrid.h"
12 
13 #include "BKE_global.h"
14 
15 using namespace std;
16 
17 namespace Freestyle {
18 
19 // Helper Classes
20 
21 // OccluderData
23 
24 // Cell
26 
27 void SphericalGrid::Cell::setDimensions(real x, real y, real sizeX, real sizeY)
28 {
29  const real epsilon = 1.0e-06;
30  boundary[0] = x - epsilon;
31  boundary[1] = x + sizeX + epsilon;
32  boundary[2] = y - epsilon;
33  boundary[3] = y + sizeY + epsilon;
34 }
35 
36 bool SphericalGrid::Cell::compareOccludersByShallowestPoint(const SphericalGrid::OccluderData *a,
37  const SphericalGrid::OccluderData *b)
38 {
39  return a->shallowest < b->shallowest;
40 }
41 
42 void SphericalGrid::Cell::indexPolygons()
43 {
44  // Sort occluders by their shallowest points.
45  sort(faces.begin(), faces.end(), compareOccludersByShallowestPoint);
46 }
47 
48 // Iterator
50 
51 SphericalGrid::Iterator::Iterator(SphericalGrid &grid, Vec3r &center, real /*epsilon*/)
52  : _target(SphericalGrid::Transform::sphericalProjection(center)), _foundOccludee(false)
53 {
54  // Find target cell
55  _cell = grid.findCell(_target);
56 #if SPHERICAL_GRID_LOGGING
57  if (G.debug & G_DEBUG_FREESTYLE) {
58  cout << "Searching for occluders of edge centered at " << _target << " in cell ["
59  << _cell->boundary[0] << ", " << _cell->boundary[1] << ", " << _cell->boundary[2] << ", "
60  << _cell->boundary[3] << "] (" << _cell->faces.size() << " occluders)" << endl;
61  }
62 #endif
63 
64  // Set iterator
65  _current = _cell->faces.begin();
66 }
67 
68 // SphericalGrid
70 
71 SphericalGrid::SphericalGrid(OccluderSource &source,
73  ViewMap *viewMap,
75  bool enableQI)
76  : _viewpoint(viewpoint), _enableQI(enableQI)
77 {
78  if (G.debug & G_DEBUG_FREESTYLE) {
79  cout << "Generate Cell structure" << endl;
80  }
81  // Generate Cell structure
82  assignCells(source, density, viewMap);
83  if (G.debug & G_DEBUG_FREESTYLE) {
84  cout << "Distribute occluders" << endl;
85  }
86  // Fill Cells
87  distributePolygons(source);
88  if (G.debug & G_DEBUG_FREESTYLE) {
89  cout << "Reorganize cells" << endl;
90  }
91  // Reorganize Cells
93  if (G.debug & G_DEBUG_FREESTYLE) {
94  cout << "Ready to use SphericalGrid" << endl;
95  }
96 }
97 
99 
102  ViewMap *viewMap)
103 {
104  _cellSize = density.cellSize();
105  _cellsX = density.cellsX();
106  _cellsY = density.cellsY();
107  _cellOrigin[0] = density.cellOrigin(0);
108  _cellOrigin[1] = density.cellOrigin(1);
109  if (G.debug & G_DEBUG_FREESTYLE) {
110  cout << "Using " << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square."
111  << endl;
112  cout << "Cell origin: " << _cellOrigin[0] << ", " << _cellOrigin[1] << endl;
113  }
114 
115  // Now allocate the cell table and fill it with default (empty) cells
116  _cells.resize(_cellsX * _cellsY);
117  for (cellContainer::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) {
118  (*i) = NULL;
119  }
120 
121  // Identify cells that will be used, and set the dimensions for each
122  ViewMap::fedges_container &fedges = viewMap->FEdges();
123  for (ViewMap::fedges_container::iterator f = fedges.begin(), fend = fedges.end(); f != fend;
124  ++f) {
125  if ((*f)->isInImage()) {
127  unsigned i, j;
128  getCellCoordinates(point, i, j);
129  if (_cells[i * _cellsY + j] == nullptr) {
130  // This is an uninitialized cell
131  real x, y, width, height;
132 
133  x = _cellOrigin[0] + _cellSize * i;
134  width = _cellSize;
135 
136  y = _cellOrigin[1] + _cellSize * j;
137  height = _cellSize;
138 
139  // Initialize cell
140  Cell *b = _cells[i * _cellsY + j] = new Cell();
141  b->setDimensions(x, y, width, height);
142  }
143  }
144  }
145 }
146 
148 {
149  unsigned long nFaces = 0;
150  unsigned long nKeptFaces = 0;
151 
152  for (source.begin(); source.isValid(); source.next()) {
153  OccluderData *occluder = nullptr;
154 
155  try {
156  if (insertOccluder(source, occluder)) {
157  _faces.push_back(occluder);
158  ++nKeptFaces;
159  }
160  }
161  catch (...) {
162  // If an exception was thrown, _faces.push_back() cannot have succeeded. Occluder is not
163  // owned by anyone, and must be deleted. If the exception was thrown before or during new
164  // OccluderData(), then occluder is NULL, and this delete is harmless.
165  delete occluder;
166  throw;
167  }
168  ++nFaces;
169  }
170  if (G.debug & G_DEBUG_FREESTYLE) {
171  cout << "Distributed " << nFaces << " occluders. Retained " << nKeptFaces << "." << endl;
172  }
173 }
174 
176 {
177  // Sort the occluders by shallowest point
178  for (vector<Cell *>::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) {
179  if (*i != NULL) {
180  (*i)->indexPolygons();
181  }
182  }
183 }
184 
185 void SphericalGrid::getCellCoordinates(const Vec3r &point, unsigned &x, unsigned &y)
186 {
187  x = min(_cellsX - 1, (unsigned)floor(max((double)0.0f, point[0] - _cellOrigin[0]) / _cellSize));
188  y = min(_cellsY - 1, (unsigned)floor(max((double)0.0f, point[1] - _cellOrigin[1]) / _cellSize));
189 }
190 
191 SphericalGrid::Cell *SphericalGrid::findCell(const Vec3r &point)
192 {
193  unsigned x, y;
194  getCellCoordinates(point, x, y);
195  return _cells[x * _cellsY + y];
196 }
197 
199 {
200  return false;
201 }
202 
204 {
205  return _viewpoint;
206 }
207 
209 {
210  return _enableQI;
211 }
212 
214 {
215  return sphericalProjection(point);
216 }
217 
219 {
220  Vec3r newPoint;
221 
222  newPoint[0] = ::atan(M[0] / M[2]);
223  newPoint[1] = ::atan(M[1] / M[2]);
224  newPoint[2] = ::sqrt(M[0] * M[0] + M[1] * M[1] + M[2] * M[2]);
225 
226  return newPoint;
227 }
228 
229 } /* namespace Freestyle */
@ G_DEBUG_FREESTYLE
Definition: BKE_global.h:181
sqrt(x)+1/max(0
NSNotificationCenter * center
_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
_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
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
Class to define a cell grid surrounding the projected image of a scene.
void sort(btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V, int t)
Helper function of 3X3 SVD for sorting singular values.
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)
vector< FEdge * > fedges_container
Definition: ViewMap.h:52
fedges_container & FEdges()
Definition: ViewMap.h:115
#define M
static char faces[256]
#define G(x, y, z)
inherits from class Rep
Definition: AppCanvas.cpp:18
static unsigned x[3]
Definition: RandGen.cpp:73
static unsigned a[3]
Definition: RandGen.cpp:78
double real
Definition: Precision.h:12
INLINE Rall1d< T, V, S > atan(const Rall1d< T, V, S > &x)
Definition: rall1d.h:375
T floor(const T &a)
static double epsilon
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static const pxr::TfToken density("density", pxr::TfToken::Immortal)
#define min(a, b)
Definition: sort.c:35
float max