2 * Copyright (C) 2003-2006 Gabest
3 * http://www.gabest.org
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GNU Make; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
24 #include "CoordGeom.h"
26 #define EPSILON (1e-7)
27 #define BIGNUMBER (1e+9)
28 #define IsZero(d) (fabs(d) < EPSILON)
34 Vector::Vector(float x
, float y
, float z
)
41 void Vector::Set(float x
, float y
, float z
)
48 float Vector::Length()
50 return(sqrt(x
* x
+ y
* y
+ z
* z
));
58 float Vector::CrossSum()
60 return(x
*y
+ x
*z
+ y
*z
);
63 Vector
Vector::Cross()
65 return(Vector(x
*y
, x
*z
, y
*z
));
68 Vector
Vector::Pow(float exp
)
70 return(exp
== 0 ? Vector(1, 1, 1) : exp
== 1 ? *this : Vector(pow(x
, exp
), pow(y
, exp
), pow(z
, exp
)));
76 if(!l
|| l
== 1) return(*this);
77 return(*this * (1 / l
));
80 Vector
& Vector::Unitalize()
82 return(*this = Unit());
85 Vector
Vector::Normal(Vector
& a
, Vector
& b
)
87 return((a
- *this) % (b
- a
));
90 float Vector::Angle(Vector
& a
, Vector
& b
)
92 return(((a
- *this).Unit()).Angle((b
- *this).Unit()));
95 float Vector::Angle(Vector
& a
)
97 float angle
= *this | a
;
98 return((angle
> 1) ? 0 : (angle
< -1) ? PI
: acos(angle
));
101 void Vector::Angle(float& u
, float& v
)
107 if(IsZero(n
.z
)) v
= PI
/2 * Sgn(n
.x
);
108 else if(n
.z
> 0) v
= atan(n
.x
/ n
.z
);
109 else if(n
.z
< 0) v
= IsZero(n
.x
) ? PI
: (PI
* Sgn(n
.x
) + atan(n
.x
/ n
.z
));
112 Vector
Vector::Angle()
120 Vector
& Vector::Min(Vector
& a
)
122 x
= (x
< a
.x
) ? x
: a
.x
;
123 y
= (y
< a
.y
) ? y
: a
.y
;
124 z
= (z
< a
.z
) ? z
: a
.z
;
128 Vector
& Vector::Max(Vector
& a
)
130 x
= (x
> a
.x
) ? x
: a
.x
;
131 y
= (y
> a
.y
) ? y
: a
.y
;
132 z
= (z
> a
.z
) ? z
: a
.z
;
138 return(Vector(fabs(x
), fabs(y
), fabs(z
)));
141 Vector
Vector::Reflect(Vector
& n
)
143 return(n
* ((-*this) | n
) * 2 - (-*this));
146 Vector
Vector::Refract(Vector
& N
, float nFront
, float nBack
, float* nOut
)
150 float N_dot_D
= (N
| D
);
151 float n
= N_dot_D
>= 0 ? (nFront
/ nBack
) : (nBack
/ nFront
);
153 Vector cos_D
= N
* N_dot_D
;
154 Vector sin_T
= (cos_D
- D
) * n
;
156 float len_sin_T
= sin_T
| sin_T
;
160 if(nOut
) {*nOut
= N_dot_D
>= 0 ? nFront
: nBack
;}
161 return((*this).Reflect(N
));
164 float N_dot_T
= sqrt(1.0 - len_sin_T
);
165 if(N_dot_D
< 0) N_dot_T
= -N_dot_T
;
167 if(nOut
) {*nOut
= N_dot_D
>= 0 ? nBack
: nFront
;}
169 return(sin_T
- (N
* N_dot_T
));
172 Vector
Vector::Refract2(Vector
& N
, float nFrom
, float nTo
, float* nOut
)
176 float N_dot_D
= (N
| D
);
177 float n
= nFrom
/ nTo
;
179 Vector cos_D
= N
* N_dot_D
;
180 Vector sin_T
= (cos_D
- D
) * n
;
182 float len_sin_T
= sin_T
| sin_T
;
186 if(nOut
) {*nOut
= nFrom
;}
187 return((*this).Reflect(N
));
190 float N_dot_T
= sqrt(1.0 - len_sin_T
);
191 if(N_dot_D
< 0) N_dot_T
= -N_dot_T
;
193 if(nOut
) {*nOut
= nTo
;}
195 return(sin_T
- (N
* N_dot_T
));
198 float Vector::operator | (Vector
& v
)
200 return(x
* v
.x
+ y
* v
.y
+ z
* v
.z
);
203 Vector
Vector::operator % (Vector
& v
)
205 return(Vector(y
* v
.z
- z
* v
.y
, z
* v
.x
- x
* v
.z
, x
* v
.y
- y
* v
.x
));
208 float& Vector::operator [] (int i
)
210 return(!i
? x
: (i
== 1) ? y
: z
);
213 Vector
Vector::operator - ()
215 return(Vector(-x
, -y
, -z
));
218 bool Vector::operator == (const Vector
& v
) const
220 if(IsZero(x
- v
.x
) && IsZero(y
- v
.y
) && IsZero(z
- v
.z
)) return(true);
224 bool Vector::operator != (const Vector
& v
) const
226 return((*this == v
) ? false : true);
229 Vector
Vector::operator + (float d
)
231 return(Vector(x
+ d
, y
+ d
, z
+ d
));
234 Vector
Vector::operator + (Vector
& v
)
236 return(Vector(x
+ v
.x
, y
+ v
.y
, z
+ v
.z
));
239 Vector
Vector::operator - (float d
)
241 return(Vector(x
- d
, y
- d
, z
- d
));
244 Vector
Vector::operator - (Vector
& v
)
246 return(Vector(x
- v
.x
, y
- v
.y
, z
- v
.z
));
249 Vector
Vector::operator * (float d
)
251 return(Vector(x
* d
, y
* d
, z
* d
));
254 Vector
Vector::operator * (Vector
& v
)
256 return(Vector(x
* v
.x
, y
* v
.y
, z
* v
.z
));
259 Vector
Vector::operator / (float d
)
261 return(Vector(x
/ d
, y
/ d
, z
/ d
));
264 Vector
Vector::operator / (Vector
& v
)
266 return(Vector(x
/ v
.x
, y
/ v
.y
, z
/ v
.z
));
269 Vector
& Vector::operator += (float d
)
271 x
+= d
; y
+= d
; z
+= d
;
275 Vector
& Vector::operator += (Vector
& v
)
277 x
+= v
.x
; y
+= v
.y
; z
+= v
.z
;
281 Vector
& Vector::operator -= (float d
)
283 x
-= d
; y
-= d
; z
-= d
;
287 Vector
& Vector::operator -= (Vector
& v
)
289 x
-= v
.x
; y
-= v
.y
; z
-= v
.z
;
293 Vector
& Vector::operator *= (float d
)
295 x
*= d
; y
*= d
; z
*= d
;
299 Vector
& Vector::operator *= (Vector
& v
)
301 x
*= v
.x
; y
*= v
.y
; z
*= v
.z
;
305 Vector
& Vector::operator /= (float d
)
307 x
/= d
; y
/= d
; z
/= d
;
311 Vector
& Vector::operator /= (Vector
& v
)
313 x
/= v
.x
; y
/= v
.y
; z
/= v
.z
;
321 Ray::Ray(Vector
& p
, Vector
& d
)
327 void Ray::Set(Vector
& p
, Vector
& d
)
333 float Ray::GetDistanceFrom(Ray
& r
)
336 if(IsZero(t
)) return(-BIGNUMBER
); // plane is paralell to the ray, return -infinite
337 return(((r
.p
- p
) | r
.d
) / t
);
340 float Ray::GetDistanceFrom(Vector
& v
)
342 float t
= ((v
- p
) | d
) / (d
| d
);
343 return(((p
+ d
*t
) - v
).Length());
346 Vector
Ray::operator [] (float t
)
355 XForm::XForm(Ray
& r
, Vector
& s
, bool isWorldToLocal
)
357 Initalize(r
, s
, isWorldToLocal
);
360 void XForm::Initalize()
365 void XForm::Initalize(Ray
& r
, Vector
& s
, bool isWorldToLocal
)
369 if(m_isWorldToLocal
= isWorldToLocal
)
384 void XForm::operator *= (Vector
& v
)
393 void XForm::operator += (Vector
& v
)
402 void XForm::operator <<= (Vector
& v
)
405 x
.mat
[1][1] = cos(v
.x
); x
.mat
[1][2] = -sin(v
.x
);
406 x
.mat
[2][1] = sin(v
.x
); x
.mat
[2][2] = cos(v
.x
);
409 y
.mat
[0][0] = cos(v
.y
); y
.mat
[0][2] = -sin(v
.y
);
410 y
.mat
[2][0] = sin(v
.y
); y
.mat
[2][2] = cos(v
.y
);
413 z
.mat
[0][0] = cos(v
.z
); z
.mat
[0][1] = -sin(v
.z
);
414 z
.mat
[1][0] = sin(v
.z
); z
.mat
[1][1] = cos(v
.z
);
416 m
= m_isWorldToLocal
? (m
* y
* x
* z
) : (m
* z
* x
* y
);
419 void XForm::operator /= (Vector
& v
)
422 s
.x
= IsZero(v
.x
) ? 0 : 1 / v
.x
;
423 s
.y
= IsZero(v
.y
) ? 0 : 1 / v
.y
;
424 s
.z
= IsZero(v
.z
) ? 0 : 1 / v
.z
;
428 void XForm::operator -= (Vector
& v
)
433 void XForm::operator >>= (Vector
& v
)
438 Vector
XForm::operator < (Vector
& n
)
442 ret
.x
= n
.x
* m
.mat
[0][0] +
445 ret
.y
= n
.x
* m
.mat
[0][1] +
448 ret
.z
= n
.x
* m
.mat
[0][2] +
455 Vector
XForm::operator << (Vector
& v
)
459 ret
.x
= v
.x
* m
.mat
[0][0] +
463 ret
.y
= v
.x
* m
.mat
[0][1] +
467 ret
.z
= v
.x
* m
.mat
[0][2] +
475 Ray
XForm::operator << (Ray
& r
)
477 return(Ray(*this << r
.p
, *this < r
.d
));
484 XForm::Matrix::Matrix()
489 void XForm::Matrix::Initalize()
491 mat
[0][0] = 1; mat
[0][1] = 0; mat
[0][2] = 0; mat
[0][3] = 0;
492 mat
[1][0] = 0; mat
[1][1] = 1; mat
[1][2] = 0; mat
[1][3] = 0;
493 mat
[2][0] = 0; mat
[2][1] = 0; mat
[2][2] = 1; mat
[2][3] = 0;
494 mat
[3][0] = 0; mat
[3][1] = 0; mat
[3][2] = 0; mat
[3][3] = 1;
497 XForm::Matrix
XForm::Matrix::operator * (Matrix
& m
)
501 for(int i
= 0; i
< 4; i
++)
503 for(int j
= 0; j
< 4; j
++)
505 ret
.mat
[i
][j
] = mat
[i
][0] * m
.mat
[0][j
] +
506 mat
[i
][1] * m
.mat
[1][j
] +
507 mat
[i
][2] * m
.mat
[2][j
] +
508 mat
[i
][3] * m
.mat
[3][j
];
510 if(IsZero(ret
.mat
[i
][j
])) ret
.mat
[i
][j
] = 0;
517 XForm::Matrix
& XForm::Matrix::operator *= (XForm::Matrix
& m
)
519 return(*this = *this * m
);