soc-2008-mxcurioni: merged changes to revision 14747, cosmetic changes for source/blender/freestyle

This commit is contained in:
Maxime Curioni
2008-05-08 19:16:40 +00:00
365 changed files with 1331 additions and 824 deletions

View File

@@ -0,0 +1,388 @@
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
#include "Grid.h"
#include "BBox.h"
#include <cassert>
#include <stdexcept>
// Grid Visitors
/////////////////
void allOccludersGridVisitor::examineOccluder(Polygon3r *occ){
occluders_.push_back(occ);
}
bool inBox(const Vec3r& inter, const Vec3r& box_min, const Vec3r& box_max){
if(((inter.x()>=box_min.x()) && (inter.x() <box_max.x()))
&& ((inter.y()>=box_min.y()) && (inter.y() <box_max.y()))
&& ((inter.z()>=box_min.z()) && (inter.z() <box_max.z()))
){
return true;
}
return false;
}
void firstIntersectionGridVisitor::examineOccluder(Polygon3r *occ){
// check whether the edge and the polygon plane are coincident:
//-------------------------------------------------------------
//first let us compute the plane equation.
Vec3r v1(((occ)->getVertices())[0]);
Vec3d normal((occ)->getNormal());
double d = -(v1 * normal);
double tmp_u, tmp_v, tmp_t;
if((occ)->rayIntersect(ray_org_, ray_dir_, tmp_t, tmp_u, tmp_v)){
if (fabs(ray_dir_ * normal) > 0.0001){
// Check whether the intersection is in the cell:
if(inBox(ray_org_+tmp_t*ray_dir_/ray_dir_.norm(), current_cell_->getOrigin(), current_cell_->getOrigin()+cell_size_)){
//Vec3d bboxdiag(_scene3d->bbox().getMax()-_scene3d->bbox().getMin());
//if ((t>1.0E-06*(min(min(bboxdiag.x(),bboxdiag.y()),bboxdiag.z()))) && (t<raylength)){
if(tmp_t < t_){
occluder_ = occ;
u_ = tmp_u;
v_ = tmp_v;
t_ = tmp_t;
}
}else{
occ->userdata2 = 0;
}
}
}
}
bool firstIntersectionGridVisitor::stop(){
if(occluder_)
return true;
return false;
}
// Grid
/////////////////
void Grid::clear() {
if (_occluders.size() != 0) {
for(OccludersSet::iterator it = _occluders.begin();
it != _occluders.end();
it++) {
delete (*it);
}
_occluders.clear();
}
_size = Vec3r(0, 0, 0);
_cell_size = Vec3r(0, 0, 0);
_orig = Vec3r(0, 0, 0);
_cells_nb = Vec3u(0, 0, 0);
//_ray_occluders.clear();
}
void Grid::configure(const Vec3r& orig,
const Vec3r& size,
unsigned nb) {
_orig = orig;
Vec3r tmpSize=size;
// Compute the volume of the desired grid
real grid_vol = size[0] * size[1] * size[2];
if(grid_vol == 0){
double min=DBL_MAX;
int index;
int nzeros=0;
for(int i=0;i<3;++i){
if(size[i] == 0){
++nzeros;
index=i;
}
if((size[i]!=0) && (min>size[i])){
min=size[i];
}
}
if(nzeros>1){
throw std::runtime_error("Warning: the 3D grid has more than one null dimension");
}
tmpSize[index]=min;
_orig[index] = _orig[index]-min/2;
}
// Compute the desired volume of a single cell
real cell_vol = grid_vol / nb;
// The edge of such a cubic cell is cubic root of cellVolume
real edge = pow(cell_vol, 1.0 / 3.0);
// We compute the number of cells par edge
// such as we cover at least the whole box.
unsigned i;
for (i = 0; i < 3; i++)
_cells_nb[i] = (unsigned)floor(tmpSize[i] / edge) + 1;
_size = tmpSize;
for(i = 0; i < 3; i++)
_cell_size[i] = _size[i] / _cells_nb[i];
}
void Grid::insertOccluder(Polygon3r* occluder) {
const vector<Vec3r> vertices = occluder->getVertices();
if (vertices.size() == 0)
return;
// add this occluder to the grid's occluders list
addOccluder(occluder);
// find the bbox associated to this polygon
Vec3r min, max;
occluder->getBBox(min, max);
// Retrieve the cell x, y, z cordinates associated with these min and max
Vec3u imax, imin;
getCellCoordinates(max, imax);
getCellCoordinates(min, imin);
// We are now going to fill in the cells overlapping with the
// polygon bbox.
// If the polygon is a triangle (most of cases), we also
// check for each of these cells if it is overlapping with
// the triangle in order to only fill in the ones really overlapping
// the triangle.
unsigned i, x, y, z;
vector<Vec3r>::const_iterator it;
Vec3u coord;
if (vertices.size() == 3) { // Triangle case
Vec3r triverts[3];
i = 0;
for(it = vertices.begin();
it != vertices.end();
it++) {
triverts[i] = Vec3r(*it);
i++;
}
Vec3r boxmin, boxmax;
for (z = imin[2]; z <= imax[2]; z++)
for (y = imin[1]; y <= imax[1]; y++)
for (x = imin[0]; x <= imax[0]; x++) {
coord[0] = x;
coord[1] = y;
coord[2] = z;
// We retrieve the box coordinates of the current cell
getCellBox(coord, boxmin, boxmax);
// We check whether the triangle and the box ovewrlap:
Vec3r boxcenter((boxmin + boxmax) / 2.0);
Vec3r boxhalfsize(_cell_size / 2.0);
if (GeomUtils::overlapTriangleBox(boxcenter, boxhalfsize, triverts)) {
// We must then create the Cell and add it to the cells list
// if it does not exist yet.
// We must then add the occluder to the occluders list of this cell.
Cell* cell = getCell(coord);
if (!cell) {
cell = new Cell(boxmin);
fillCell(coord, *cell);
}
cell->addOccluder(occluder);
}
}
}
else { // The polygon is not a triangle, we add all the cells overlapping the polygon bbox.
for (z = imin[2]; z <= imax[2]; z++)
for (y = imin[1]; y <= imax[1]; y++)
for (x = imin[0]; x <= imax[0]; x++) {
coord[0] = x;
coord[1] = y;
coord[2] = z;
Cell* cell = getCell(coord);
if (!cell) {
Vec3r orig;
getCellOrigin(coord, orig);
cell = new Cell(orig);
fillCell(coord, *cell);
}
cell->addOccluder(occluder);
}
}
}
bool Grid::nextRayCell(Vec3u& current_cell, Vec3u& next_cell) {
next_cell = current_cell;
real t_min, t;
unsigned i;
t_min = FLT_MAX; // init tmin with handle of the case where one or 2 _u[i] = 0.
unsigned coord = 0; // predominant coord(0=x, 1=y, 2=z)
// using a parametric equation of
// a line : B = A + t u, we find
// the tx, ty and tz respectively coresponding
// to the intersections with the plans:
// x = _cell_size[0], y = _cell_size[1], z = _cell_size[2]
for (i = 0; i < 3; i++) {
if (_ray_dir[i] == 0)
continue;
if (_ray_dir[i] > 0)
t = (_cell_size[i] - _pt[i]) / _ray_dir[i];
else
t = -_pt[i] / _ray_dir[i];
if (t < t_min) {
t_min = t;
coord = i;
}
}
// We use the parametric line equation and
// the found t (tamx) to compute the
// B coordinates:
Vec3r pt_tmp(_pt);
_pt = pt_tmp + t_min * _ray_dir;
// We express B coordinates in the next cell
// coordinates system. We just have to
// set the coordinate coord of B to 0
// of _CellSize[coord] depending on the sign
// of _u[coord]
if (_ray_dir[coord] > 0) {
next_cell[coord]++;
_pt[coord] -= _cell_size[coord];
// if we are out of the grid, we must stop
if (next_cell[coord] >= _cells_nb[coord])
return false;
}
else {
int tmp = next_cell[coord] - 1;
_pt[coord] = _cell_size[coord];
if (tmp < 0)
return false;
next_cell[coord]--;
}
_t += t_min;
if (_t >= _t_end)
return false;
return true;
}
void Grid::castRay(const Vec3r& orig,
const Vec3r& end,
OccludersSet& occluders,
unsigned timestamp) {
initRay(orig, end, timestamp);
allOccludersGridVisitor visitor(occluders);
castRayInternal(visitor);
}
void Grid::castInfiniteRay(const Vec3r& orig,
const Vec3r& dir,
OccludersSet& occluders,
unsigned timestamp) {
Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm());
bool inter = initInfiniteRay(orig, dir, timestamp);
if(!inter)
return;
allOccludersGridVisitor visitor(occluders);
castRayInternal(visitor);
}
Polygon3r* Grid::castRayToFindFirstIntersection(const Vec3r& orig,
const Vec3r& dir,
double& t,
double& u,
double& v,
unsigned timestamp){
Polygon3r *occluder = 0;
Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm());
bool inter = initInfiniteRay(orig, dir, timestamp);
if(!inter){
return 0;
}
firstIntersectionGridVisitor visitor(orig,dir,_cell_size);
castRayInternal(visitor);
occluder = visitor.occluder();
t = visitor.t_;
u = visitor.u_;
v = visitor.v_;
return occluder;
}
void Grid::initRay (const Vec3r &orig,
const Vec3r& end,
unsigned timestamp) {
_ray_dir = end - orig;
_t_end = _ray_dir.norm();
_t = 0;
_ray_dir.normalize();
_timestamp = timestamp;
for(unsigned i = 0; i < 3; i++) {
_current_cell[i] = (unsigned)floor((orig[i] - _orig[i]) / _cell_size[i]);
unsigned u = _current_cell[i];
_pt[i] = orig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
}
//_ray_occluders.clear();
}
bool Grid::initInfiniteRay (const Vec3r &orig,
const Vec3r& dir,
unsigned timestamp) {
_ray_dir = dir;
_t_end = FLT_MAX;
_t = 0;
_ray_dir.normalize();
_timestamp = timestamp;
// check whether the origin is in or out the box:
Vec3r boxMin(_orig);
Vec3r boxMax(_orig+_size);
BBox<Vec3r> box(boxMin, boxMax);
if(box.inside(orig)){
for(unsigned i = 0; i < 3; i++) {
_current_cell[i] = (unsigned)floor((orig[i] - _orig[i]) / _cell_size[i]);
unsigned u = _current_cell[i];
_pt[i] = orig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
}
}else{
// is the ray intersecting the box?
real tmin(-1.0), tmax(-1.0);
if(GeomUtils::intersectRayBBox(orig, _ray_dir, boxMin, boxMax, 0, _t_end, tmin, tmax)){
assert(tmin != -1.0);
Vec3r newOrig = orig + tmin*_ray_dir;
for(unsigned i = 0; i < 3; i++) {
_current_cell[i] = (unsigned)floor((newOrig[i] - _orig[i]) / _cell_size[i]);
if(_current_cell[i] == _cells_nb[i])
_current_cell[i] = _cells_nb[i] - 1;
unsigned u = _current_cell[i];
_pt[i] = newOrig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
}
}else{
return false;
}
}
//_ray_occluders.clear();
return true;
}