Blender V4.3
BoxGrid.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
9
10#include <algorithm>
11#include <stdexcept>
12
13#include "BoxGrid.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 BoxGrid::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 BoxGrid::Cell::compareOccludersByShallowestPoint(const BoxGrid::OccluderData *a,
41 const BoxGrid::OccluderData *b)
42{
43 return a->shallowest < b->shallowest;
44}
45
46void BoxGrid::Cell::indexPolygons()
47{
48 // Sort occluders by their shallowest points.
49 sort(faces.begin(), faces.end(), compareOccludersByShallowestPoint);
50}
51
52// Iterator
54
55BoxGrid::Iterator::Iterator(BoxGrid &grid, Vec3r &center, real /*epsilon*/)
56 : _target(grid.transform(center)), _foundOccludee(false)
57{
58 // Find target cell
59 _cell = grid.findCell(_target);
60#if BOX_GRID_LOGGING
61 if (G.debug & G_DEBUG_FREESTYLE) {
62 cout << "Searching for occluders of edge centered at " << _target << " in cell ["
63 << 1_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// BoxGrid
74
75BoxGrid::BoxGrid(OccluderSource &source,
76 GridDensityProvider &density,
77 ViewMap *viewMap,
79 bool enableQI)
80 : _viewpoint(viewpoint), _enableQI(enableQI)
81{
82 // Generate Cell structure
83 if (G.debug & G_DEBUG_FREESTYLE) {
84 cout << "Generate Cell structure" << endl;
85 }
86 assignCells(source, density, viewMap);
87
88 // Fill Cells
89 if (G.debug & G_DEBUG_FREESTYLE) {
90 cout << "Distribute occluders" << endl;
91 }
92 distributePolygons(source);
93
94 // Reorganize Cells
95 if (G.debug & G_DEBUG_FREESTYLE) {
96 cout << "Reorganize cells" << endl;
97 }
99
100 if (G.debug & G_DEBUG_FREESTYLE) {
101 cout << "Ready to use BoxGrid" << endl;
102 }
103}
104
105BoxGrid::~BoxGrid() = default;
106
108 GridDensityProvider &density,
109 ViewMap *viewMap)
110{
111 _cellSize = density.cellSize();
112 _cellsX = density.cellsX();
113 _cellsY = density.cellsY();
114 _cellOrigin[0] = density.cellOrigin(0);
115 _cellOrigin[1] = density.cellOrigin(1);
116 if (G.debug & G_DEBUG_FREESTYLE) {
117 cout << "Using " << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square."
118 << endl;
119 cout << "Cell origin: " << _cellOrigin[0] << ", " << _cellOrigin[1] << endl;
120 }
121
122 // Now allocate the cell table and fill it with default (empty) cells
123 _cells.resize(_cellsX * _cellsY);
124 for (cellContainer::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) {
125 (*i) = nullptr;
126 }
127
128 // Identify cells that will be used, and set the dimensions for each
129 ViewMap::fedges_container &fedges = viewMap->FEdges();
130 for (ViewMap::fedges_container::iterator f = fedges.begin(), fend = fedges.end(); f != fend; ++f)
131 {
132 if ((*f)->isInImage()) {
133 Vec3r point = transform((*f)->center3d());
134 uint i, j;
135 getCellCoordinates(point, i, j);
136 if (_cells[i * _cellsY + j] == nullptr) {
137 // This is an uninitialized cell
138 real x, y, width, height;
139
140 x = _cellOrigin[0] + _cellSize * i;
141 width = _cellSize;
142
143 y = _cellOrigin[1] + _cellSize * j;
144 height = _cellSize;
145
146 // Initialize cell
147 Cell *b = _cells[i * _cellsY + j] = new Cell();
148 b->setDimensions(x, y, width, height);
149 }
150 }
151 }
152}
153
155{
156 ulong nFaces = 0;
157 ulong nKeptFaces = 0;
158
159 for (source.begin(); source.isValid(); source.next()) {
160 OccluderData *occluder = nullptr;
161
162 try {
163 if (insertOccluder(source, occluder)) {
164 _faces.push_back(occluder);
165 ++nKeptFaces;
166 }
167 }
168 catch (...) {
169 // If an exception was thrown, _faces.push_back() cannot have succeeded.
170 // occluder is not owned by anyone, and must be deleted.
171 // If the exception was thrown before or during new OccluderData(), then
172 // occluder is nullptr, and this delete is harmless.
173 delete occluder;
174 throw;
175 }
176 ++nFaces;
177 }
178 if (G.debug & G_DEBUG_FREESTYLE) {
179 cout << "Distributed " << nFaces << " occluders. Retained " << nKeptFaces << "." << endl;
180 }
181}
182
184{
185 // Sort the occluders by shallowest point
186 for (vector<Cell *>::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) {
187 if (*i != nullptr) {
188 (*i)->indexPolygons();
189 }
190 }
191}
192
193void BoxGrid::getCellCoordinates(const Vec3r &point, uint &x, uint &y)
194{
195 x = min(_cellsX - 1, uint(floor(max(double(0.0f), point[0] - _cellOrigin[0]) / _cellSize)));
196 y = min(_cellsY - 1, uint(floor(max(double(0.0f), point[1] - _cellOrigin[1]) / _cellSize)));
197}
198
199BoxGrid::Cell *BoxGrid::findCell(const Vec3r &point)
200{
201 uint x, y;
202 getCellCoordinates(point, x, y);
203 return _cells[x * _cellsY + y];
204}
205
207{
208 return true;
209}
210
212{
213 return _viewpoint;
214}
215
217{
218 return _enableQI;
219}
220
221Vec3r BoxGrid::Transform::operator()(const Vec3r &point) const
222{
223 return Vec3r(point[0], point[1], -point[2]);
224}
225
226} /* namespace Freestyle */
@ G_DEBUG_FREESTYLE
unsigned long ulong
unsigned int uint
Class to define a cell grid surrounding the projected image of a scene.
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 Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture 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
static DBVT_INLINE btDbvtNode * sort(btDbvtNode *n, btDbvtNode *&r)
Definition btDbvt.cpp:418
Iterator(BoxGrid &grid, Vec3r &center, real epsilon=1.0e-06)
Definition BoxGrid.cpp:55
Transform transform
Definition BoxGrid.h:156
void assignCells(OccluderSource &source, GridDensityProvider &density, ViewMap *viewMap)
Definition BoxGrid.cpp:107
const Vec3r & viewpoint() const
Definition BoxGrid.cpp:211
Cell * findCell(const Vec3r &point)
Definition BoxGrid.cpp:199
bool enableQI() const
Definition BoxGrid.cpp:216
void distributePolygons(OccluderSource &source)
Definition BoxGrid.cpp:154
bool insertOccluder(OccluderSource &source, OccluderData *&occluder)
Definition BoxGrid.h:387
bool orthographicProjection() const
Definition BoxGrid.cpp:206
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)
static char faces[256]
#define G(x, y, z)
VecMat::Vec3< real > Vec3r
Definition Geom.h:30
inherits from class Rep
Definition AppCanvas.cpp:20
static uint a[3]
Definition RandGen.cpp:82
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