Blender V4.3
SphericalGrid.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10#include <algorithm>
11#include <stdexcept>
12
13#include "SphericalGrid.h"
14
15#include "BLI_sys_types.h"
16
17#include "BKE_global.hh"
18
19using namespace std;
20
21namespace Freestyle {
22
23// Helper Classes
24
25// OccluderData
27
28// Cell
30
31void SphericalGrid::Cell::setDimensions(real x, real y, real sizeX, real sizeY)
32{
33 const real epsilon = 1.0e-06;
34 boundary[0] = x - epsilon;
35 boundary[1] = x + sizeX + epsilon;
36 boundary[2] = y - epsilon;
37 boundary[3] = y + sizeY + epsilon;
38}
39
40bool SphericalGrid::Cell::compareOccludersByShallowestPoint(const SphericalGrid::OccluderData *a,
41 const SphericalGrid::OccluderData *b)
42{
43 return a->shallowest < b->shallowest;
44}
45
46void SphericalGrid::Cell::indexPolygons()
47{
48 // Sort occluders by their shallowest points.
49 sort(faces.begin(), faces.end(), compareOccludersByShallowestPoint);
50}
51
52// Iterator
54
56 : _target(SphericalGrid::Transform::sphericalProjection(center)), _foundOccludee(false)
57{
58 // Find target cell
59 _cell = grid.findCell(_target);
60#if SPHERICAL_GRID_LOGGING
61 if (G.debug & G_DEBUG_FREESTYLE) {
62 cout << "Searching for occluders of edge centered at " << _target << " in cell ["
63 << _cell->boundary[0] << ", " << _cell->boundary[1] << ", " << _cell->boundary[2] << ", "
64 << _cell->boundary[3] << "] (" << _cell->faces.size() << " occluders)" << endl;
65 }
66#endif
67
68 // Set iterator
69 _current = _cell->faces.begin();
70}
71
72// SphericalGrid
74
75SphericalGrid::SphericalGrid(OccluderSource &source,
76 GridDensityProvider &density,
77 ViewMap *viewMap,
79 bool enableQI)
80 : _viewpoint(viewpoint), _enableQI(enableQI)
81{
82 if (G.debug & G_DEBUG_FREESTYLE) {
83 cout << "Generate Cell structure" << endl;
84 }
85 // Generate Cell structure
86 assignCells(source, density, viewMap);
87 if (G.debug & G_DEBUG_FREESTYLE) {
88 cout << "Distribute occluders" << endl;
89 }
90 // Fill Cells
91 distributePolygons(source);
92 if (G.debug & G_DEBUG_FREESTYLE) {
93 cout << "Reorganize cells" << endl;
94 }
95 // Reorganize Cells
97 if (G.debug & G_DEBUG_FREESTYLE) {
98 cout << "Ready to use SphericalGrid" << endl;
99 }
100}
101
103
105 GridDensityProvider &density,
106 ViewMap *viewMap)
107{
108 _cellSize = density.cellSize();
109 _cellsX = density.cellsX();
110 _cellsY = density.cellsY();
111 _cellOrigin[0] = density.cellOrigin(0);
112 _cellOrigin[1] = density.cellOrigin(1);
113 if (G.debug & G_DEBUG_FREESTYLE) {
114 cout << "Using " << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square."
115 << endl;
116 cout << "Cell origin: " << _cellOrigin[0] << ", " << _cellOrigin[1] << endl;
117 }
118
119 // Now allocate the cell table and fill it with default (empty) cells
120 _cells.resize(_cellsX * _cellsY);
121 for (cellContainer::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) {
122 (*i) = nullptr;
123 }
124
125 // Identify cells that will be used, and set the dimensions for each
126 ViewMap::fedges_container &fedges = viewMap->FEdges();
127 for (ViewMap::fedges_container::iterator f = fedges.begin(), fend = fedges.end(); f != fend; ++f)
128 {
129 if ((*f)->isInImage()) {
130 Vec3r point = SphericalGrid::Transform::sphericalProjection((*f)->center3d());
131 uint i, j;
132 getCellCoordinates(point, i, j);
133 if (_cells[i * _cellsY + j] == nullptr) {
134 // This is an uninitialized cell
135 real x, y, width, height;
136
137 x = _cellOrigin[0] + _cellSize * i;
138 width = _cellSize;
139
140 y = _cellOrigin[1] + _cellSize * j;
141 height = _cellSize;
142
143 // Initialize cell
144 Cell *b = _cells[i * _cellsY + j] = new Cell();
145 b->setDimensions(x, y, width, height);
146 }
147 }
148 }
149}
150
152{
153 ulong nFaces = 0;
154 ulong nKeptFaces = 0;
155
156 for (source.begin(); source.isValid(); source.next()) {
157 OccluderData *occluder = nullptr;
158
159 try {
160 if (insertOccluder(source, occluder)) {
161 _faces.push_back(occluder);
162 ++nKeptFaces;
163 }
164 }
165 catch (...) {
166 // If an exception was thrown, _faces.push_back() cannot have succeeded. Occluder is not
167 // owned by anyone, and must be deleted. If the exception was thrown before or during new
168 // OccluderData(), then occluder is nullptr, and this delete is harmless.
169 delete occluder;
170 throw;
171 }
172 ++nFaces;
173 }
174 if (G.debug & G_DEBUG_FREESTYLE) {
175 cout << "Distributed " << nFaces << " occluders. Retained " << nKeptFaces << "." << endl;
176 }
177}
178
180{
181 // Sort the occluders by shallowest point
182 for (vector<Cell *>::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) {
183 if (*i != nullptr) {
184 (*i)->indexPolygons();
185 }
186 }
187}
188
189void SphericalGrid::getCellCoordinates(const Vec3r &point, uint &x, uint &y)
190{
191 x = min(_cellsX - 1, uint(floor(max(double(0.0f), point[0] - _cellOrigin[0]) / _cellSize)));
192 y = min(_cellsY - 1, uint(floor(max(double(0.0f), point[1] - _cellOrigin[1]) / _cellSize)));
193}
194
195SphericalGrid::Cell *SphericalGrid::findCell(const Vec3r &point)
196{
197 uint x, y;
198 getCellCoordinates(point, x, y);
199 return _cells[x * _cellsY + y];
200}
201
203{
204 return false;
205}
206
208{
209 return _viewpoint;
210}
211
213{
214 return _enableQI;
215}
216
217Vec3r SphericalGrid::Transform::operator()(const Vec3r &point) const
218{
219 return sphericalProjection(point);
220}
221
222Vec3r SphericalGrid::Transform::sphericalProjection(const Vec3r &M)
223{
224 Vec3r newPoint;
225
226 newPoint[0] = ::atan(M[0] / M[2]);
227 newPoint[1] = ::atan(M[1] / M[2]);
228 newPoint[2] = ::sqrt(M[0] * M[0] + M[1] * M[1] + M[2] * M[2]);
229
230 return newPoint;
231}
232
233} /* namespace Freestyle */
@ G_DEBUG_FREESTYLE
sqrt(x)+1/max(0
unsigned long ulong
unsigned int uint
Class to define a cell grid surrounding the projected image of a scene.
static DBVT_INLINE btDbvtNode * sort(btDbvtNode *n, btDbvtNode *&r)
Definition btDbvt.cpp:418
Iterator(SphericalGrid &grid, Vec3r &center, real epsilon=1.0e-06)
static Vec3r sphericalProjection(const Vec3r &M)
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:53
fedges_container & FEdges()
Definition ViewMap.h:116
local_group_size(16, 16) .push_constant(Type b
ccl_device_inline float2 floor(const float2 a)
#define M
#define G(x, y, z)
inherits from class Rep
Definition AppCanvas.cpp:20
static uint x[3]
Definition RandGen.cpp:77
double real
Definition Precision.h:14
double epsilon
default precision while comparing with Equal(..,..) functions. Initialized at 0.0000001.
Definition utility.cpp:22
#define min(a, b)
Definition sort.c:32
float max