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