This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/freestyle/intern/geometry/Grid.h
Tamito Kajiyama 6569902081 Fix for svn:executable.
Reported by Bastien Montagne, thanks!
2012-12-11 23:01:21 +00:00

393 lines
11 KiB
C++

//
// Filename : Grid.h
// Author(s) : Stephane Grabli
// Purpose : Base class to define a cell grid surrounding
// the bounding box of the scene
// Date of creation : 30/07/2002
//
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) : Please refer to the COPYRIGHT file distributed
// with this source distribution.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef GRID_H
# define GRID_H
# include <cstring> // for memset
# include <float.h>
# include <vector>
# include "../system/FreestyleConfig.h"
# include "GeomUtils.h"
# include "Geom.h"
# include "Polygon.h"
using namespace std;
using namespace Geometry;
typedef vector<Polygon3r*> OccludersSet;
//
// Class to define cells used by the regular grid
//
///////////////////////////////////////////////////////////////////////////////
class LIB_GEOMETRY_EXPORT 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;
};
class GridVisitor{
public:
virtual ~GridVisitor() {}; //soc
virtual void discoverCell(Cell *cell) {}
virtual void examineOccluder(Polygon3r *occ) {}
virtual void finishCell(Cell *cell) {}
virtual bool stop() {return false;}
};
/*! Gathers all the occluders belonging to the cells
* traversed by the ray */
class allOccludersGridVisitor : public GridVisitor{
public:
allOccludersGridVisitor(OccludersSet& occluders)
:GridVisitor(), occluders_(occluders){}
virtual void examineOccluder(Polygon3r *occ);
OccludersSet& occluders() {return occluders_;}
void clear() {occluders_.clear();}
private:
OccludersSet& occluders_;
};
/*! Finds the first intersection and breaks. The occluder and
* the intersection information are stored and accessible.
*/
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_;
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_;}
};
//
// Class to define a regular grid used for ray casting computations
//
///////////////////////////////////////////////////////////////////////////////
class LIB_GEOMETRY_EXPORT Grid
{
public:
/*! Builds a Grid
* Must be followed by a call to configure()
*/
Grid() {}
virtual ~Grid() {
clear();
}
/*! clears the grid
* Deletes all the cells, clears the hashtable,
* 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, unsigned 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 ((unsigned)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 pased 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), NULL 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 (unsigned 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 constituing a convex polygon
*/
void insertOccluder(Polygon3r * convex_poly);
/*! 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,
unsigned timestamp);
// Prepares to cast ray without generating OccludersSet
void initAcceleratedRay(const Vec3r& orig,
const Vec3r& end,
unsigned 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,
unsigned timestamp);
// Prepares to cast ray without generating OccludersSet.
bool initAcceleratedInfiniteRay(const Vec3r& orig,
const Vec3r& dir,
unsigned 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.
*/
Polygon3r * castRayToFindFirstIntersection(const Vec3r& orig,
const Vec3r& dir,
double& t,
double& u,
double& v,
unsigned timestamp);
/*! Init all structures and values for computing
* the cells intersected by this new ray
*/
void initRay (const Vec3r &orig,
const Vec3r& end,
unsigned 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,
unsigned 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 = NULL;
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 ((unsigned long)(*it)->userdata2 != _timestamp) {
(*it)->userdata2 = (void*)_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);
unsigned _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
};
//
// 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;
};
#endif // GRID_H