Files
test2/source/blender/freestyle/intern/geometry/Grid.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

399 lines
10 KiB
C
Raw Normal View History

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
2008-04-30 15:41:54 +00:00
#pragma once
2008-04-30 15:41:54 +00:00
/** \file
* \ingroup freestyle
* \brief Base class to define a cell grid surrounding the bounding box of the scene
*/
#include <cstring> // for memset
#include <float.h>
#include <stdint.h> // For POINTER_FROM_UINT, i.e. uintptr_t.
#include <vector>
2008-04-30 15:41:54 +00:00
#include "Geom.h"
#include "GeomUtils.h"
#include "Polygon.h"
2008-04-30 15:41:54 +00:00
#include "../system/FreestyleConfig.h"
2008-04-30 15:41:54 +00:00
#include "BLI_utildefines.h"
#include "MEM_guardedalloc.h"
2008-04-30 15:41:54 +00:00
using namespace std;
Attempt to fix a potential name conflict between Freestyle and the compositor. A crash in the Freestyle renderer was reported by Ton on IRC with a stack trace below. Note that #2 is in Freestyle, whereas #1 is in the compositor. The problem was observed in a debug build on OS X 10.7 (gcc 4.2, openmp disabled, no llvm). ---------------------------------------------------------------------- Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: 13 at address: 0x0000000000000000 [Switching to process 72386 thread 0xf303] 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 43 delete (this->m_outputsockets.back()); Current language: auto; currently c++ (gdb) where #0 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 #1 0x0000000100c29066 in Node::~Node (this=0x10e501c80) at COM_Node.h:49 #2 0x000000010089c273 in NodeShape::~NodeShape (this=0x10e501c80) at NodeShape.cpp:43 #3 0x000000010089910b in NodeGroup::destroy (this=0x10e501da0) at NodeGroup.cpp:61 #4 0x00000001008990cd in NodeGroup::destroy (this=0x10e5014b0) at NodeGroup.cpp:59 #5 0x00000001008990cd in NodeGroup::destroy (this=0x114e18da0) at NodeGroup.cpp:59 #6 0x00000001007e6602 in Controller::ClearRootNode (this=0x114e19640) at Controller.cpp:329 #7 0x00000001007ea52e in Controller::LoadMesh (this=0x114e19640, re=0x10aba4638, srl=0x1140f5258) at Controller.cpp:302 #8 0x00000001008030ad in prepare (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:302 #9 0x000000010080457a in FRS_do_stroke_rendering (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:600 #10 0x00000001006aeb9d in add_freestyle (re=0x10aba4638) at pipeline.c:1584 #11 0x00000001006aceb7 in do_render_3d (re=0x10aba4638) at pipeline.c:1094 #12 0x00000001006ae061 in do_render_fields_blur_3d (re=0x10aba4638) at pipeline.c:1367 #13 0x00000001006afa16 in do_render_composite_fields_blur_3d (re=0x10aba4638) at pipeline.c:1815 #14 0x00000001006b04e4 in do_render_all_options (re=0x10aba4638) at pipeline.c:2021 ---------------------------------------------------------------------- Apparently a name conflict between the two Blender modules is taking place. The present commit hence intends to address it by putting all the Freestyle C++ classes in the namespace 'Freestyle'. This revision will also prevent potential name conflicts with other Blender modules in the future. Special thanks to Lukas Toenne for the help with C++ namespace.
2013-04-09 00:46:49 +00:00
namespace Freestyle {
2008-04-30 15:41:54 +00:00
using namespace Geometry;
typedef vector<Polygon3r *> OccludersSet;
2008-04-30 15:41:54 +00:00
//
// Class to define cells used by the regular grid
//
///////////////////////////////////////////////////////////////////////////////
class Cell {
public:
Cell(Vec3r &orig)
{
_orig = orig;
}
virtual ~Cell() {}
inline void addOccluder(Polygon3r *o)
{
if (o) {
_occluders.push_back(o);
}
}
inline const Vec3r &getOrigin()
{
return _orig;
}
inline OccludersSet &getOccluders()
{
return _occluders;
}
private:
Vec3r _orig;
OccludersSet _occluders;
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Cell")
2008-04-30 15:41:54 +00:00
};
class GridVisitor {
public:
virtual ~GridVisitor(){}; // soc
2008-04-30 15:41:54 +00:00
virtual void discoverCell(Cell * /*cell*/) {}
virtual void examineOccluder(Polygon3r * /*occ*/) {}
virtual void finishCell(Cell * /*cell*/) {}
virtual bool stop()
{
return false;
}
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:GridVisitor")
2008-04-30 15:41:54 +00:00
};
/** Gathers all the occluders belonging to the cells traversed by the ray */
class allOccludersGridVisitor : public GridVisitor {
2008-04-30 15:41:54 +00:00
public:
allOccludersGridVisitor(OccludersSet &occluders) : GridVisitor(), occluders_(occluders) {}
virtual void examineOccluder(Polygon3r *occ);
OccludersSet &occluders()
{
return occluders_;
}
void clear()
{
occluders_.clear();
}
2008-04-30 15:41:54 +00:00
private:
OccludersSet &occluders_;
2008-04-30 15:41:54 +00:00
};
/** Finds the first intersection and breaks.
* The occluder and the intersection information are stored and accessible.
2008-04-30 15:41:54 +00:00
*/
class firstIntersectionGridVisitor : public GridVisitor {
// soc - changed order to remove warnings
public:
double u_, v_, t_;
private:
Polygon3r *occluder_;
Vec3r ray_org_, ray_dir_, cell_size_;
Cell *current_cell_;
2008-04-30 15:41:54 +00:00
public:
firstIntersectionGridVisitor(const Vec3r &ray_org, const Vec3r &ray_dir, const Vec3r &cell_size)
: GridVisitor(),
u_(0),
v_(0),
t_(DBL_MAX),
occluder_(0),
ray_org_(ray_org),
ray_dir_(ray_dir),
cell_size_(cell_size),
current_cell_(0)
{
}
virtual ~firstIntersectionGridVisitor() {}
virtual void discoverCell(Cell *cell)
{
current_cell_ = cell;
}
virtual void examineOccluder(Polygon3r *occ);
virtual bool stop();
Polygon3r *occluder()
{
return occluder_;
}
2008-04-30 15:41:54 +00:00
};
//
// Class to define a regular grid used for ray casting computations
//
///////////////////////////////////////////////////////////////////////////////
class Grid {
2008-04-30 15:41:54 +00:00
public:
/** Builds a Grid. Must be followed by a call to configure() */
Grid() {}
virtual ~Grid()
{
clear();
}
/** clears the grid
2022-08-19 13:49:13 +10:00
* Deletes all the cells, clears the hash-table, resets size, size of cell, number of cells.
*/
virtual void clear();
/** Sets the different parameters of the grid
* orig
* The grid origin
* size
* The grid's dimensions
* nb
* The number of cells of the grid
*/
virtual void configure(const Vec3r &orig, const Vec3r &size, uint nb);
/** returns a vector of integer containing the coordinates of the cell containing the point
* passed as argument
* p
* The point for which we're looking the cell
*/
inline void getCellCoordinates(const Vec3r &p, Vec3u &res)
{
int tmp;
for (int i = 0; i < 3; i++) {
tmp = (int)((p[i] - _orig[i]) / _cell_size[i]);
if (tmp < 0) {
res[i] = 0;
}
else if ((uint)tmp >= _cells_nb[i]) {
res[i] = _cells_nb[i] - 1;
}
else {
res[i] = tmp;
}
}
}
/** Fills the case corresponding to coord with the cell */
virtual void fillCell(const Vec3u &coord, Cell &cell) = 0;
/** returns the cell whose coordinates are passed as argument */
virtual Cell *getCell(const Vec3u &coord) = 0;
/** returns the cell containing the point passed as argument.
* If the cell is empty (contains no occluder), nullptr is returned:
* p
* The point for which we're looking the cell
*/
inline Cell *getCell(const Vec3r &p)
{
Vec3u coord;
getCellCoordinates(p, coord);
return getCell(coord);
}
/** Retrieves the x,y,z coordinates of the origin of the cell whose coordinates (i,j,k)
* is passed as argument:
* cell_coord
* i,j,k integer coordinates for the cell
* orig
* x,y,x vector to be filled in with the cell origin's coordinates
*/
inline void getCellOrigin(const Vec3u &cell_coord, Vec3r &orig)
{
for (uint i = 0; i < 3; i++) {
orig[i] = _orig[i] + cell_coord[i] * _cell_size[i];
}
}
/** Retrieves the box corresponding to the cell whose coordinates are passed as argument:
* cell_coord
* i,j,k integer coordinates for the cell
* min_out
* The min x,y,x vector of the box. Filled in by the method.
* max_out
* The max x,y,z coordinates of the box. Filled in by the method.
*/
inline void getCellBox(const Vec3u &cell_coord, Vec3r &min_out, Vec3r &max_out)
{
getCellOrigin(cell_coord, min_out);
max_out = min_out + _cell_size;
}
/** inserts a convex polygon occluder
* This method is quite coarse insofar as it adds all cells intersecting the polygon bounding
* box convex_poly The list of 3D points constituting a convex polygon
*/
void insertOccluder(Polygon3r *occluder);
/** Adds an occluder to the list of occluders */
void addOccluder(Polygon3r *occluder)
{
_occluders.push_back(occluder);
}
/** Casts a ray between a starting point and an ending point
* Returns the list of occluders contained in the cells intersected by this ray
* Starts with a call to InitRay.
*/
void castRay(const Vec3r &orig, const Vec3r &end, OccludersSet &occluders, uint timestamp);
// Prepares to cast ray without generating OccludersSet
void initAcceleratedRay(const Vec3r &orig, const Vec3r &end, uint timestamp);
/** Casts an infinite ray (still finishing at the end of the grid) from a starting point and in a
* given direction. Returns the list of occluders contained in the cells intersected by this ray
* Starts with a call to InitRay.
*/
void castInfiniteRay(const Vec3r &orig,
const Vec3r &dir,
OccludersSet &occluders,
uint timestamp);
// Prepares to cast ray without generating OccludersSet.
bool initAcceleratedInfiniteRay(const Vec3r &orig, const Vec3r &dir, uint timestamp);
/** Casts an infinite ray (still finishing at the end of the grid) from a starting point and in a
* given direction. Returns the first intersection (occluder,t,u,v) or null. Starts with a call
* to InitRay.
*/
2018-10-11 08:49:28 +11:00
Polygon3r *castRayToFindFirstIntersection(
const Vec3r &orig, const Vec3r &dir, double &t, double &u, double &v, uint timestamp);
/** Init all structures and values for computing the cells intersected by this new ray */
void initRay(const Vec3r &orig, const Vec3r &end, uint timestamp);
/** Init all structures and values for computing the cells intersected by this infinite ray.
* Returns false if the ray doesn't intersect the grid.
*/
bool initInfiniteRay(const Vec3r &orig, const Vec3r &dir, uint timestamp);
/** Accessors */
inline const Vec3r &getOrigin() const
{
return _orig;
}
inline Vec3r gridSize() const
{
return _size;
}
inline Vec3r getCellSize() const
{
return _cell_size;
}
// ARB profiling only:
inline OccludersSet *getOccluders()
{
return &_occluders;
}
void displayDebug()
{
cerr << "Cells nb : " << _cells_nb << endl;
cerr << "Cell size : " << _cell_size << endl;
cerr << "Origin : " << _orig << endl;
cerr << "Occluders nb : " << _occluders.size() << endl;
}
protected:
/** Core of castRay and castInfiniteRay, find occluders along the given ray */
inline void castRayInternal(GridVisitor &visitor)
{
Cell *current_cell = nullptr;
do {
current_cell = getCell(_current_cell);
if (current_cell) {
visitor.discoverCell(current_cell);
OccludersSet &occluders =
current_cell->getOccluders(); // FIXME: I had forgotten the ref &
for (OccludersSet::iterator it = occluders.begin(); it != occluders.end(); it++) {
if (POINTER_AS_UINT((*it)->userdata2) != _timestamp) {
(*it)->userdata2 = POINTER_FROM_UINT(_timestamp);
visitor.examineOccluder(*it);
}
}
visitor.finishCell(current_cell);
}
} while ((!visitor.stop()) && (nextRayCell(_current_cell, _current_cell)));
}
/** Returns the cell next to the cell passed as argument. */
bool nextRayCell(Vec3u &current_cell, Vec3u &next_cell);
uint _timestamp;
Vec3u _cells_nb; // number of cells for x,y,z axis
Vec3r _cell_size; // cell x,y,z dimensions
Vec3r _size; // grid x,y,x dimensions
Vec3r _orig; // grid origin
Vec3r _ray_dir; // direction vector for the ray
Vec3u _current_cell; // The current cell being processed (designated by its 3 coordinates)
Vec3r _pt; // Points corresponding to the incoming and outgoing intersections of one cell with
// the ray
real _t_end; // To know when we are at the end of the ray
real _t;
// OccludersSet _ray_occluders; // Set storing the occluders contained in the cells traversed by
// a ray
OccludersSet _occluders; // List of all occluders inserted in the grid
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Grid")
2008-04-30 15:41:54 +00:00
};
Optimized view map calculation by Alexander Beels. * View map calculation has been intensively optimized for speed by means of: 1) new spatial grid data structures (SphericalGrid for perspective cameras and BoxGrid for orthographic cameras; automatically switched based on the camera type); 2) a heuristic grid density calculation algorithm; and 3) new line visibility computation algorithms: A "traditional" algorithm for emulating old visibility algorithms, and a "cumulative" algorithm for improved, more consistent line visibility, both exploiting the new spatial grid data structures for fast ray casting. A new option "Raycasting Algorithm" was added to allow users to choose a ray casting (line visibility) algorithm. Available choices are: - Normal Ray Casting - Fast Ray Casting - Very Fast Ray Casting - Culled Traditional Visibility Detection - Unculled Traditional Visibility Detection - Culled Cumulative Visibility Detection - Unculled Cumulative Visibility Detection The first three algorithms are those available in the original Freestyle (the "normal" ray casting was used unconditionally, though). The "fast" and "very fast" ray casting algorithms achieve a faster calculation at the cost of less visibility accuracy. The last four are newly introduced optimized options. The culled versions of the new algorithms will exclude from visibility calculation those faces that lay outside the camera, which leads to a faster view map construction. The unculled counterparts will take all faces into account. The unculled visibility algorithms are useful when culling affects stroke chaining. The recommended options for users are the culled/unculled cumulative visibility algorithms. These options are meant to replace the old algorithms in the future. Performance improvements over the old algorithms depend on the scenes to be rendered. * Silhouette detection has also been considerably optimized for speed. Performance gains by this optimization do not depend on scenes. * Improper handling of error conditions in the view map construction was fixed.
2011-03-14 00:36:27 +00:00
//
// Class to walk through occluders in grid without building intermediate data structures
//
///////////////////////////////////////////////////////////////////////////////
class VirtualOccludersSet {
public:
VirtualOccludersSet(Grid &_grid) : grid(_grid){};
Polygon3r *begin();
Polygon3r *next();
Polygon3r *next(bool stopOnNewCell);
private:
Polygon3r *firstOccluderFromNextCell();
Grid &grid;
OccludersSet::iterator it, end;
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:VirtualOccludersSet")
Optimized view map calculation by Alexander Beels. * View map calculation has been intensively optimized for speed by means of: 1) new spatial grid data structures (SphericalGrid for perspective cameras and BoxGrid for orthographic cameras; automatically switched based on the camera type); 2) a heuristic grid density calculation algorithm; and 3) new line visibility computation algorithms: A "traditional" algorithm for emulating old visibility algorithms, and a "cumulative" algorithm for improved, more consistent line visibility, both exploiting the new spatial grid data structures for fast ray casting. A new option "Raycasting Algorithm" was added to allow users to choose a ray casting (line visibility) algorithm. Available choices are: - Normal Ray Casting - Fast Ray Casting - Very Fast Ray Casting - Culled Traditional Visibility Detection - Unculled Traditional Visibility Detection - Culled Cumulative Visibility Detection - Unculled Cumulative Visibility Detection The first three algorithms are those available in the original Freestyle (the "normal" ray casting was used unconditionally, though). The "fast" and "very fast" ray casting algorithms achieve a faster calculation at the cost of less visibility accuracy. The last four are newly introduced optimized options. The culled versions of the new algorithms will exclude from visibility calculation those faces that lay outside the camera, which leads to a faster view map construction. The unculled counterparts will take all faces into account. The unculled visibility algorithms are useful when culling affects stroke chaining. The recommended options for users are the culled/unculled cumulative visibility algorithms. These options are meant to replace the old algorithms in the future. Performance improvements over the old algorithms depend on the scenes to be rendered. * Silhouette detection has also been considerably optimized for speed. Performance gains by this optimization do not depend on scenes. * Improper handling of error conditions in the view map construction was fixed.
2011-03-14 00:36:27 +00:00
};
Attempt to fix a potential name conflict between Freestyle and the compositor. A crash in the Freestyle renderer was reported by Ton on IRC with a stack trace below. Note that #2 is in Freestyle, whereas #1 is in the compositor. The problem was observed in a debug build on OS X 10.7 (gcc 4.2, openmp disabled, no llvm). ---------------------------------------------------------------------- Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: 13 at address: 0x0000000000000000 [Switching to process 72386 thread 0xf303] 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 43 delete (this->m_outputsockets.back()); Current language: auto; currently c++ (gdb) where #0 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 #1 0x0000000100c29066 in Node::~Node (this=0x10e501c80) at COM_Node.h:49 #2 0x000000010089c273 in NodeShape::~NodeShape (this=0x10e501c80) at NodeShape.cpp:43 #3 0x000000010089910b in NodeGroup::destroy (this=0x10e501da0) at NodeGroup.cpp:61 #4 0x00000001008990cd in NodeGroup::destroy (this=0x10e5014b0) at NodeGroup.cpp:59 #5 0x00000001008990cd in NodeGroup::destroy (this=0x114e18da0) at NodeGroup.cpp:59 #6 0x00000001007e6602 in Controller::ClearRootNode (this=0x114e19640) at Controller.cpp:329 #7 0x00000001007ea52e in Controller::LoadMesh (this=0x114e19640, re=0x10aba4638, srl=0x1140f5258) at Controller.cpp:302 #8 0x00000001008030ad in prepare (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:302 #9 0x000000010080457a in FRS_do_stroke_rendering (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:600 #10 0x00000001006aeb9d in add_freestyle (re=0x10aba4638) at pipeline.c:1584 #11 0x00000001006aceb7 in do_render_3d (re=0x10aba4638) at pipeline.c:1094 #12 0x00000001006ae061 in do_render_fields_blur_3d (re=0x10aba4638) at pipeline.c:1367 #13 0x00000001006afa16 in do_render_composite_fields_blur_3d (re=0x10aba4638) at pipeline.c:1815 #14 0x00000001006b04e4 in do_render_all_options (re=0x10aba4638) at pipeline.c:2021 ---------------------------------------------------------------------- Apparently a name conflict between the two Blender modules is taking place. The present commit hence intends to address it by putting all the Freestyle C++ classes in the namespace 'Freestyle'. This revision will also prevent potential name conflicts with other Blender modules in the future. Special thanks to Lukas Toenne for the help with C++ namespace.
2013-04-09 00:46:49 +00:00
} /* namespace Freestyle */