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