1 #pragma once
2 /****************************************************************************
3 *
4 * bound.h: Bound and tree api for general raytracing acceleration
5 * This is part of the yafray package
6 * Copyright (C) 2002 Alejandro Conty Estévez
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24 #ifndef Y_BOUND_H
25 #define Y_BOUND_H
26
27 #include <yafray_constants.h>
28 #include "ray.h"
29
30 __BEGIN_YAFRAY
31
32 /** Bounding box
33 *
34 * The bounding box class. A box aligned with the axis used to skip
35 * object, photons, and faces intersection when possible.
36 *
37 */
38
39 class bound_t;
40 YAFRAYCORE_EXPORT float bound_distance(const bound_t &l,const bound_t &r);
41 float b_intersect(const bound_t &l,const bound_t &r);
42
43 class YAFRAYCORE_EXPORT bound_t
44 {
45 //friend YAFRAYCORE_EXPORT float bound_distance(const bound_t &l,const bound_t &r);
46 //friend float b_intersect(const bound_t &l,const bound_t &r);
47
48 public:
49
50 /*! Main constructor.
51 * The box is defined by two points, this constructor just takes them.
52 *
53 * @param _a is the low corner (minx,miny,minz)
54 * @param _g is the up corner (maxx,maxy,maxz)
55 */
bound_t(const point3d_t & _a,const point3d_t & _g)56 bound_t(const point3d_t & _a,const point3d_t & _g) { a=_a; g=_g; /* null=false; */ };
57 //! Default constructor
bound_t()58 bound_t() {};
59
60 /*! Two child constructor.
61 * This creates a bound that includes the two given bounds. It's used when
62 * building a bounding tree
63 *
64 * @param r is one child bound
65 * @param l is another child bound
66 */
67 bound_t(const bound_t &r,const bound_t &l);
68 //! Sets the bound like the constructor
set(const point3d_t & _a,const point3d_t & _g)69 void set(const point3d_t &_a,const point3d_t &_g) { a=_a; g=_g; };
get(point3d_t & _a,point3d_t & _g)70 void get(point3d_t &_a,point3d_t &_g)const { _a=a; _g=g; };
71
72 //! Returns true if the given ray crosses the bound
73 //bool cross(const point3d_t &from,const vector3d_t &ray)const;
74 //! Returns true if the given ray crosses the bound closer than dist
75 //bool cross(const point3d_t &from, const vector3d_t &ray, float dist)const;
76 //bool cross(const point3d_t &from, const vector3d_t &ray, float &where, float dist)const;
77 bool cross(const ray_t &ray, float &enter, float &leave, const float dist)const;
78
79 //! Returns the volume of the bound
80 float vol() const;
81 //! Returns the lenght along X axis
longX()82 float longX()const {return g.x-a.x;};
83 //! Returns the lenght along Y axis
longY()84 float longY()const {return g.y-a.y;};
85 //! Returns the lenght along Y axis
longZ()86 float longZ()const {return g.z-a.z;};
87 //! Cuts the bound to have the given max X
setMaxX(float X)88 void setMaxX(float X) {g.x=X;};
89 //! Cuts the bound to have the given min X
setMinX(float X)90 void setMinX(float X) {a.x=X;};
91
92 //! Cuts the bound to have the given max Y
setMaxY(float Y)93 void setMaxY(float Y) {g.y=Y;};
94 //! Cuts the bound to have the given min Y
setMinY(float Y)95 void setMinY(float Y) {a.y=Y;};
96
97 //! Cuts the bound to have the given max Z
setMaxZ(float Z)98 void setMaxZ(float Z) {g.z=Z;};
99 //! Cuts the bound to have the given min Z
setMinZ(float Z)100 void setMinZ(float Z) {a.z=Z;};
101 //! Adjust bound size to include point p
102 void include(const point3d_t &p);
103 //! Returns true if the point is inside the bound
includes(const point3d_t & pn)104 bool includes(const point3d_t &pn)const
105 {
106 return ( ( pn.x >= a.x ) && ( pn.x <= g.x) &&
107 ( pn.y >= a.y ) && ( pn.y <= g.y) &&
108 ( pn.z >= a.z ) && ( pn.z <= g.z) );
109 };
centerX()110 float centerX()const {return (g.x+a.x)*0.5;};
centerY()111 float centerY()const {return (g.y+a.y)*0.5;};
centerZ()112 float centerZ()const {return (g.z+a.z)*0.5;};
center()113 point3d_t center()const {return (g+a)*0.5;};
largestAxis()114 int largestAxis()
115 {
116 vector3d_t d = g-a;
117 return (d.x>d.y) ? ((d.x>d.z) ? 0 : 2) : ((d.y>d.z) ? 1:2 );
118 }
grow(float d)119 void grow(float d)
120 {
121 a.x-=d;
122 a.y-=d;
123 a.z-=d;
124 g.x+=d;
125 g.y+=d;
126 g.z+=d;
127 };
128
129 // protected: // Lynx; need these to be public.
130 //! Two points define the box
131 point3d_t a,g;
132 };
133
include(const point3d_t & p)134 inline void bound_t::include(const point3d_t &p)
135 {
136 a.x = std::min(a.x, p.x);
137 a.y = std::min(a.y, p.y);
138 a.z = std::min(a.z, p.z);
139 g.x = std::max(g.x, p.x);
140 g.y = std::max(g.y, p.y);
141 g.z = std::max(g.z, p.z);
142 }
143
cross(const ray_t & ray,float & enter,float & leave,const float dist)144 inline bool bound_t::cross(const ray_t &ray, float &enter, float &leave, const float dist)const
145 {
146 // Smits method
147 const point3d_t &a0=a,&a1=g;
148 const point3d_t &p = ray.from-a0;
149
150 float lmin=-1e38, lmax=1e38, ltmin, ltmax; //infinity check initial values
151
152 if (ray.dir.x != 0){
153 float invrx = 1./ray.dir.x;
154 if (invrx > 0){
155 lmin = -p.x * invrx;
156 lmax = ((a1.x - a0.x) - p.x) * invrx;
157 }else{
158 lmin = ((a1.x - a0.x) - p.x) * invrx;
159 lmax = -p.x * invrx;
160 }
161
162 if((lmax<0) || (lmin>dist)) return false;
163 }
164 if (ray.dir.y != 0){
165 float invry = 1./ray.dir.y;
166 if (invry > 0){
167 ltmin = -p.y * invry;
168 ltmax = ((a1.y - a0.y) - p.y) * invry;
169 }else{
170 ltmin = ((a1.y - a0.y) - p.y) * invry;
171 ltmax = -p.y * invry;
172 }
173 lmin = std::max(ltmin,lmin);
174 lmax = std::min(ltmax,lmax);
175
176 if((lmax<0) || (lmin>dist)) return false;
177 }
178 if (ray.dir.z != 0){
179 float invrz = 1./ray.dir.z;
180 if (invrz > 0){
181 ltmin = -p.z * invrz;
182 ltmax = ((a1.z - a0.z) - p.z) * invrz;
183 }else{
184 ltmin = ((a1.z - a0.z) - p.z) * invrz;
185 ltmax = -p.z * invrz;
186 }
187 lmin = std::max(ltmin,lmin);
188 lmax = std::min(ltmax,lmax);
189
190 if((lmax<0) || (lmin>dist)) return false;
191 }
192 if((lmin <= lmax) && (lmax >= 0) && (lmin<=dist))
193 {
194 enter=lmin; //(lmin>0) ? lmin : 0;
195 leave=lmax;
196 return true;
197 }
198
199 return false;
200 }
201
202
203 class YAFRAYCORE_EXPORT exBound_t: public bound_t
204 {
205 public:
exBound_t(const bound_t & b)206 exBound_t(const bound_t &b)
207 {
208 for(int i=0;i<3;++i)
209 {
210 center[i] = ((double)a[i] + (double)g[i])*0.5;
211 halfSize[i] = ((double)g[i] - (double)a[i])*0.5;
212 }
213 }
214
215 double center[3];
216 double halfSize[3];
217 };
218
219
220 __END_YAFRAY
221
222 #endif // Y_BOUND_H
223