1 /****************************************************************************
2  *
3  * 			vector3d.cc: Vector 3d and point manipulation implementation
4  *      This is part of the yafray package
5  *      Copyright (C) 2002 Alejandro Conty Estévez
6  *
7  *      This library is free software; you can redistribute it and/or
8  *      modify it under the terms of the GNU Lesser General Public
9  *      License as published by the Free Software Foundation; either
10  *      version 2.1 of the License, or (at your option) any later version.
11  *
12  *      This library is distributed in the hope that it will be useful,
13  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *      Lesser General Public License for more details.
16  *
17  *      You should have received a copy of the GNU Lesser General Public
18  *      License along with this library; if not, write to the Free Software
19  *      Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  *
21  */
22 
23 #include <core_api/vector3d.h>
24 #include <core_api/matrix4.h>
25 
26 __BEGIN_YAFRAY
27 
operator <<(std::ostream & out,const vector3d_t & v)28 std::ostream & operator << (std::ostream &out,const vector3d_t &v)
29 {
30 	out<<"("<<v.x<<","<<v.y<<","<<v.z<<")";
31 	return out;
32 }
33 
34 
operator <<(std::ostream & out,const point3d_t & p)35 std::ostream & operator << (std::ostream &out,const point3d_t &p)
36 {
37 	out<<"("<<p.x<<","<<p.y<<","<<p.z<<")";
38 	return out;
39 }
40 
41 
operator ==(const vector3d_t & a,const vector3d_t & b)42 bool  operator == ( const vector3d_t &a,const vector3d_t &b)
43 {
44 	if(a.x!=b.x) return false;
45 	if(a.y!=b.y) return false;
46 	if(a.z!=b.z) return false;
47 	return true;
48 }
49 
operator !=(const vector3d_t & a,const vector3d_t & b)50 bool  operator != ( const vector3d_t &a,const vector3d_t &b)
51 {
52 	if(a.x!=b.x) return true;
53 	if(a.y!=b.y) return true;
54 	if(a.z!=b.z) return true;
55 	return false;
56 }
57 
58 /* vector3d_t refract(const vector3d_t &n,const vector3d_t &v,float IOR)
59 {
60 	vector3d_t N=n,I,T;
61 	float eta=IOR;
62 	I=-v;
63 	if((v*n)<0)
64 	{
65 		N=-n;
66 		eta=IOR;
67 	}
68 	else
69 	{
70 		N=n;
71 		eta=1.0/IOR;
72 	}
73 	float IdotN = v*N;
74 	float k = 1 - eta*eta*(1 - IdotN*IdotN);
75 	T= (k < 0) ? vector3d_t(0,0,0) : (eta*I + (eta*IdotN - sqrt(k))*N);
76 	T.normalize();
77 	return T;
78 } */
79 
80 /*! refract a ray given the IOR. All directions (n, wi and wo) point away from the intersection point.
81 	\return true when refraction was possible, false when total inner reflrection occurs (wo is not computed then)
82 	\param IOR Index of refraction, or precisely the ratio of eta_t/eta_i, where eta_i is by definition the
83 				medium in which n points. E.g. "outside" is air, "inside" is water, the normal points outside,
84 				IOR = eta_air / eta_water = 1.33
85 */
refract(const vector3d_t & n,const vector3d_t & wi,vector3d_t & wo,float IOR)86 bool refract(const vector3d_t &n,const vector3d_t &wi, vector3d_t &wo, float IOR)
87 {
88 	vector3d_t N=n,I,T;
89 	float eta=IOR;
90 	I=-wi;
91 	float cos_v_n = wi*n;
92 	if((cos_v_n)<0)
93 	{
94 		N=-n;
95 		cos_v_n = -cos_v_n;
96 	}
97 	else
98 	{
99 		eta=1.0/IOR;
100 	}
101 	float k = 1 - eta*eta*(1 - cos_v_n*cos_v_n);
102 	if(k<= 0.f) return false;
103 
104 	wo = eta*I + (eta*cos_v_n - fSqrt(k))*N;
105 	wo.normalize();
106 
107 	return true;
108 }
109 
fresnel(const vector3d_t & I,const vector3d_t & n,float IOR,float & Kr,float & Kt)110 void fresnel(const vector3d_t & I, const vector3d_t & n, float IOR, float &Kr, float &Kt)
111 {
112 	float eta;
113 	vector3d_t N;
114 
115 	if((I*n)<0)
116 	{
117 		//eta=1.0/IOR;
118 		eta=IOR;
119 		N=-n;
120 	}
121 	else
122 	{
123 		eta=IOR;
124 		N=n;
125 	}
126 	float c=I*N;
127 	float g=eta*eta+c*c-1;
128 	if(g<=0)
129 		g=0;
130 	else
131 		g=fSqrt(g);
132 	float aux=c*(g+c);
133 
134 	Kr=( ( 0.5*(g-c)*(g-c) )/( (g+c)*(g+c) ) ) *
135 		   ( 1+ ((aux-1)*(aux-1))/( (aux+1)*(aux+1) ) );
136 	if(Kr<1.0)
137 		Kt=1-Kr;
138 	else
139 		Kt=0;
140 }
141 
142 
143 // 'Faster' Schlick fresnel approximation,
fast_fresnel(const vector3d_t & I,const vector3d_t & n,float IORF,float & Kr,float & Kt)144 void fast_fresnel(const vector3d_t & I, const vector3d_t & n, float IORF,
145 		float &Kr, float &Kt)
146 {
147 	float t = 1 - (I*n);
148 	//t = (t<0)?0:((t>1)?1:t);
149 	float t2 = t*t;
150 	Kr = IORF + (1 - IORF) * t2*t2*t;
151 	Kt = 1-Kr;
152 }
153 
154 // P.Shirley's concentric disk algorithm, maps square to disk
ShirleyDisk(float r1,float r2,float & u,float & v)155 void ShirleyDisk(float r1, float r2, float &u, float &v)
156 {
157 	float phi=0, r=0, a=2*r1-1, b=2*r2-1;
158 	if (a>-b) {
159 		if (a>b) {	// Reg.1
160 			r = a;
161 			phi = M_PI_4 * (b/a);
162 		}
163 		else {			// Reg.2
164 			r = b;
165 			phi = M_PI_4 * (2 - a/b);
166 		}
167 	}
168 	else {
169 		if (a<b) {	// Reg.3
170 			r = -a;
171 			phi = M_PI_4 * (4 + b/a);
172 		}
173 		else {			// Reg.4
174 			r = -b;
175 			if (b!=0)
176 				phi = M_PI_4 * (6 - a/b);
177 			else
178 				phi = 0;
179 		}
180 	}
181 	u = r * fCos(phi);
182 	v = r * fSin(phi);
183 }
184 
185 
186 
187 YAFRAYCORE_EXPORT int myseed=123212;
188 
randomVectorCone(const vector3d_t & D,const vector3d_t & U,const vector3d_t & V,float cosang,float z1,float z2)189 vector3d_t randomVectorCone(const vector3d_t &D,
190 				const vector3d_t &U, const vector3d_t &V,
191 				float cosang, float z1, float z2)
192 {
193   float t1=M_2PI*z1, t2=1.0-(1.0-cosang)*z2;
194   return (U*fCos(t1) + V*fSin(t1))*fSqrt(1.0-t2*t2) + D*t2;
195 }
196 
randomVectorCone(const vector3d_t & dir,float cangle,float r1,float r2)197 vector3d_t randomVectorCone(const vector3d_t &dir, float cangle, float r1, float r2)
198 {
199 	vector3d_t u, v;
200 	createCS(dir, u, v);
201 	return randomVectorCone(dir, u, v, cangle, r1, r2);
202 }
203 
discreteVectorCone(const vector3d_t & dir,float cangle,int sample,int square)204 vector3d_t discreteVectorCone(const vector3d_t &dir, float cangle, int sample, int square)
205 {
206 	float r1=(float)(sample / square)/(float)square;
207 	float r2=(float)(sample % square)/(float)square;
208 	float tt = M_2PI * r1;
209 	float ss = fAcos(1.0 - (1.0 - cangle)*r2);
210 	vector3d_t	vx(fCos(ss),fSin(ss)*fCos(tt),fSin(ss)*fSin(tt));
211 	vector3d_t	i(1,0,0),c;
212 	matrix4x4_t M(1);
213 	if((std::fabs(dir.y)>0.0) || (std::fabs(dir.z)>0.0))
214 	{
215 		M[0][0]=dir.x;
216 		M[1][0]=dir.y;
217 		M[2][0]=dir.z;
218 		c=i^dir;
219 		c.normalize();
220 		M[0][1]=c.x;
221 		M[1][1]=c.y;
222 		M[2][1]=c.z;
223 		c=dir^c;
224 		c.normalize();
225 		M[0][2]=c.x;
226 		M[1][2]=c.y;
227 		M[2][2]=c.z;
228 	}
229 	else if(dir.x<0.0) M[0][0]=-1.0;
230 	return M*vx;
231 }
232 
233 __END_YAFRAY
234