Code_TYMPAN  4.4.0
Industrial site acoustic simulation
GridAccelerator.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) <2012> <EDF-R&D> <FRANCE>
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10  * See the GNU General Public License for more details.
11  * You should have received a copy of the GNU General Public License along
12  * with this program; if not, write to the Free Software Foundation, Inc.,
13  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14  */
15 
16 #include "GridAccelerator.h"
17 
18 #include <math.h>
19 
20 GridAccelerator::GridAccelerator(std::vector<Shape*>* _initialMesh, BBox _globalBox)
21  : Accelerator(_initialMesh, _globalBox)
22 {
23  for (unsigned int i = 0; i < _initialMesh->size(); i++)
24  {
25  primitives.push_back(_initialMesh->at(i));
26  }
27 }
28 
30 {
31  // Compute bounds and choose grid resolution
32  for (uint32_t i = 0; i < primitives.size(); ++i)
33  {
34  bounds = bounds.Union(primitives[i]->getBBox());
35  }
36  vec3 delta = bounds.pMax - bounds.pMin;
37 
38  // Find _voxelsPerUnitDist_ for grid
39  int maxAxis = bounds.MaximumExtend();
40  float invMaxWidth = 1.f / delta[maxAxis];
41  float cubeRoot = 3.f * powf(float(primitives.size()), 1.f / 3.f);
42  float voxelsPerUnitDist = cubeRoot * invMaxWidth;
43  for (int axis = 0; axis < 3; ++axis)
44  {
45  nVoxels[axis] = Round2Int(delta[axis] * voxelsPerUnitDist);
46  nVoxels[axis] = Clamp(nVoxels[axis], 1, 64);
47  }
48 
49  // Compute voxel widths and allocate voxels
50  for (int axis = 0; axis < 3; ++axis)
51  {
52  width[axis] = delta[axis] / nVoxels[axis];
53  invWidth[axis] = (width[axis] == 0.f) ? 0.f : 1.f / width[axis];
54  }
55  int nv = nVoxels[0] * nVoxels[1] * nVoxels[2];
56  voxels = new Voxel*[nv]();
57  // Add primitives to grid voxels
58  for (uint32_t i = 0; i < primitives.size(); ++i)
59  {
60  // Find voxel extent of primitive
61  BBox pb = primitives[i]->getBBox();
62  int vmin[3], vmax[3];
63  for (int axis = 0; axis < 3; ++axis)
64  {
65  vmin[axis] = posToVoxel(pb.pMin, axis);
66  vmax[axis] = posToVoxel(pb.pMax, axis);
67  }
68 
69  // Add primitive to overlapping voxels
70  for (int z = vmin[2]; z <= vmax[2]; ++z)
71  for (int y = vmin[1]; y <= vmax[1]; ++y)
72  for (int x = vmin[0]; x <= vmax[0]; ++x)
73  {
74  int o = offset(x, y, z);
75  if (!voxels[o])
76  {
77  // Allocate new voxel and store primitive in it
78  voxels[o] = new Voxel(primitives.at(i));
79  }
80  else
81  {
82  // Add primitive to already-allocated voxel
83  voxels[o]->AddPrimitive(primitives.at(i));
84  }
85  }
86  }
87 
88  return true;
89 }
90 
91 decimal GridAccelerator::traverse(Ray* r, std::list<Intersection>& result) const
92 {
93  decimal rayT = NAN;
94  decimal intermin = -1.;
95  vec3 grid = r->getPosition() + r->getDirection() * r->getMint();
96  if (bounds.Inside(grid))
97  {
98  rayT = r->getMint();
99  }
100  else if (!bounds.IntersectP(r->getPosition(), r->getDirection(), &rayT))
101  {
102  // PBRT_GRID_RAY_MISSED_BOUNDS();
103  return false;
104  }
105  vec3 gridIntersect = r->getPosition() + r->getDirection() * rayT;
106 
107  // Set up 3D DDA for ray
108  float NextCrossingT[3], DeltaT[3];
109  int Step[3], Out[3], Pos[3];
110  for (int axis = 0; axis < 3; ++axis)
111  {
112  // Compute current voxel for axis
113  Pos[axis] = posToVoxel(gridIntersect, axis);
114  if (r->getDirection()[axis] >= 0)
115  {
116  // Handle ray with positive direction for voxel stepping
117  NextCrossingT[axis] =
118  rayT + (voxelToPos(Pos[axis] + 1, axis) - gridIntersect[axis]) / r->getDirection()[axis];
119  DeltaT[axis] = width[axis] / r->getDirection()[axis];
120  Step[axis] = 1;
121  Out[axis] = nVoxels[axis];
122  }
123  else
124  {
125  // Handle ray with negative direction for voxel stepping
126  NextCrossingT[axis] =
127  rayT + (voxelToPos(Pos[axis], axis) - gridIntersect[axis]) / r->getDirection()[axis];
128  DeltaT[axis] = -width[axis] / r->getDirection()[axis];
129  Step[axis] = -1;
130  Out[axis] = -1;
131  }
132  }
133 
134  // Walk ray through voxel grid
135  for (;;)
136  {
137  // Check for intersection in current voxel and advance to next
138  Voxel* voxel = voxels[offset(Pos[0], Pos[1], Pos[2])];
139  if (voxel != NULL)
140  {
141  voxel->Intersect(r, result, intermin, intersectionChoice);
142  }
143 
144  // Advance to next voxel
145 
146  // Find _stepAxis_ for stepping to next voxel
147  int bits = ((NextCrossingT[0] < NextCrossingT[1]) << 2) +
148  ((NextCrossingT[0] < NextCrossingT[2]) << 1) + ((NextCrossingT[1] < NextCrossingT[2]));
149  const int cmpToAxis[8] = {2, 1, 2, 1, 2, 2, 0, 0};
150  int stepAxis = cmpToAxis[bits];
151  if (r->getMaxt() < NextCrossingT[stepAxis])
152  {
153  break;
154  }
155  Pos[stepAxis] += Step[stepAxis];
156  if (Pos[stepAxis] == Out[stepAxis])
157  {
158  break;
159  }
160  NextCrossingT[stepAxis] += DeltaT[stepAxis];
161  }
162  return intermin;
163 }
164 
165 bool Voxel::Intersect(Ray* ray, std::list<Intersection>& result, decimal& intermin,
167 {
168 
169  // Loop over primitives in voxel and find intersections
170  bool hitSomething = false;
171 
172  for (uint32_t i = 0; i < primitives.size(); ++i)
173  {
174  Shape* prim = primitives[i];
175  Intersection currentIntersection;
176  if (prim->getIntersection(*ray, currentIntersection) && currentIntersection.t > 0.0001)
177  {
178  hitSomething = true;
179  result.push_back(currentIntersection);
180 
181  intermin = leafTreatment::keepFunction(choice, result, intermin);
182  }
183  }
184  return hitSomething;
185 }
Base class for accelerators.
Definition: Accelerator.h:27
leafTreatment::treatment intersectionChoice
Intersection choice.
Definition: Accelerator.h:100
Definition of a bounding box which is aligned along the axis (BBox AABB).
Definition: BBox.h:32
vec3 pMax
Upper point of the BBox.
Definition: BBox.h:36
bool IntersectP(vec3 rayPos, vec3 rayDir, decimal *hitt0=NULL, decimal *hitt1=NULL) const
Compute the intersection between a Ray and this BBox.
Definition: BBox.h:243
BBox Union(const BBox &b, const vec3 &p)
Union of a point and a BBox. A new BBox is created.
Definition: BBox.h:110
bool Inside(const vec3 &pt) const
Return true if the point pt is inside the BBox.
Definition: BBox.h:360
vec3 pMin
Lower point of the BBox.
Definition: BBox.h:35
int MaximumExtend() const
Return the index of the dominant direction (maximal dimension). Index is 0 for x, 1 for y,...
Definition: BBox.h:218
GridAccelerator(std::vector< Shape * > *_initialMesh=NULL, BBox _globalBox=BBox())
Constructor.
int offset(int x, int y, int z) const
virtual decimal traverse(Ray *r, std::list< Intersection > &result) const
Run this accelerator.
std::vector< Shape * > primitives
Pointer to all the shapes (different from initialMesh) as it is reordered.
int posToVoxel(const vec3 &P, int axis) const
virtual bool build()
Build this accelerator.
float voxelToPos(int p, int axis) const
: Describes a ray by a pair of unsigned int. The first one gives the source number (in the range 0-40...
Definition: Ray.h:38
decimal getMaxt() const
Return maxt.
Definition: Ray.h:326
decimal getMint() const
Return mint.
Definition: Ray.h:316
vec3 getPosition() const
Return starting point ray.
Definition: Ray.h:356
vec3 getDirection() const
Return direction of the ray.
Definition: Ray.h:346
base class for shapes (Cylindre, Mesh, Sphere, Triangle,...)
Definition: Shape.h:57
virtual bool getIntersection(Ray &ray, Intersection &inter)
Get the Intersection between a ray and this shape.
Definition: Shape.h:109
float decimal
Definition: mathlib.h:45
int Round2Int(float val)
Definition: mathlib.h:1404
float Clamp(float val, float low, float high)
Definition: mathlib.h:1367
base_vec3< decimal > vec3
Definition: mathlib.h:381
decimal keepFunction(treatment choice, std::list< Intersection > &currentIntersections, decimal currentTmin)
std::vector< Shape * > primitives
Vector containing the primitives.
void AddPrimitive(Shape *prim)
bool Intersect(Ray *ray, std::list< Intersection > &result, decimal &intermin, leafTreatment::treatment choice)
Intersection struct.
Definition: Shape.h:46
decimal t
Definition: Shape.h:48