/*
Copyright (C) 1997, 1998, 1999, 2000 by Alex Pfaffe
(Digital Dawn Graphics Inc)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _ddgVector_Class_
#define _ddgVector_Class_
#include "util/ddgutil.h"
class WEXP ddgVector2 {
public:
float v[2];
operator float* () { return v; }
inline float operator[](int n) const { return v[n]; }
inline float & operator[] (int n) { return v[n]; }
bool operator==(ddgVector2 u) { return v[0] == u[0] && v[1] == u[1]; }
bool operator!=(ddgVector2 u) { return v[0] != u[0] || v[1] != u[1]; }
friend bool operator == (const ddgVector2& u, const ddgVector2& v)
{ return v[0] == u[0] && v[1] == u[1];
}
friend bool operator != (const ddgVector2& u, const ddgVector2& v)
{ return v[0] != u[0] || v[1] != u[1];
}
void assign( float *a) { a[0] = v[0]; a[1] = v[1]; }
ddgVector2(void ) { }
ddgVector2(float *a ) { v[0] = a[0]; v[1] = a[1]; }
ddgVector2(float a, float b ) { v[0] = a; v[1] = b; }
ddgVector2( const ddgVector2* u ) { v[0] = u->v[0]; v[1] = u->v[1]; }
ddgVector2& operator=(const ddgVector2& s) { v[0] = s[0]; v[1] = s[1]; return *this; }
void zero( void ) { v[0] = v[1] = 0.0;}
void set(float a, float b ) { v[0] = a; v[1] = b; }
void set( const ddgVector2 *u ) { v[0] = u->v[0]; v[1] = u->v[1]; }
void get(float *a, float *b) { *a = v[0]; *b = v[1]; }
void add( const ddgVector2 *u ) { v[0] += u->v[0]; v[1] += u->v[1]; }
ddgVector2& operator+=( const ddgVector2& u)
{ v[0]+=u[0]; v[1] += u[1]; return *this; }
ddgVector2& operator-=( const ddgVector2& u)
{ v[0]-=u[0]; v[1] -= u[1]; return *this; }
ddgVector2& operator*=( const ddgVector2& u)
{ v[0]*=u[0]; v[1] *= u[1]; return *this; }
ddgVector2& operator*=( const float d)
{ v[0]*=d; v[1] *= d; return *this; }
ddgVector2& operator/=( const ddgVector2& u)
{ v[0]/=u[0]; v[1] /= u[1]; return *this; }
ddgVector2& operator/=( const float d)
{ v[0]/=d; v[1] /= d; return *this; }
inline friend ddgVector2 operator+( const ddgVector2& u, const ddgVector2& w)
{ return ddgVector2(u[0]+w[0],u[1]+w[1]); }
void subtract( ddgVector2 *u ) { v[0] -= u->v[0]; v[1] -= u->v[1]; }
inline friend ddgVector2 operator-( const ddgVector2& u, const ddgVector2& w)
{ return ddgVector2(u[0]-w[0],u[1]-w[1]); }
void multiply( float s ) { v[0] *= s; v[1] *= s; }
inline friend ddgVector2 operator*( const ddgVector2& u, const ddgVector2& w)
{ return ddgVector2(u[0]*w[0],u[1]*w[1]); }
void multiply( const ddgVector2 *u ) { v[0] *= u->v[0]; v[1] *= u->v[1]; }
void divide( float s ) { float s2=1.0f/s; multiply(s2); }
void divide( const ddgVector2* u ) { v[0] /= u->v[0]; v[1] /= u->v[1]; }
inline friend ddgVector2 operator/( const ddgVector2& u, const ddgVector2& w)
{ return ddgVector2(u[0]/w[0],u[1]/w[1]); }
float sizesq( void ) { return (v[0]*v[0]+v[1]*v[1]); }
float size( void ) { return sqrtf(sizesq()); }
bool null( void ) { return (v[0] == 0.0 && v[1] == 0.0); }
void normalize( void ) { divide(size()); }
float angle( const ddgVector2 *u ) { return ddgAngle::radtodeg(acosf(dot(u))); }
float dot ( const ddgVector2 *u )
{ return u->v[0]*v[0]+ u->v[1]*v[1]; }
inline friend float operator|( const ddgVector2& u, const ddgVector2& w)
{ return u[0]*w[0]+ u[1]*w[1]; }
void inverse() {multiply(-1.0);}
void minimum(ddgVector2* m )
{
if (m->v[0] < v[0] ) v[0] = m->v[0];
if (m->v[1] < v[1] ) v[1] = m->v[1];
}
void maximum(ddgVector2* m )
{
if (m->v[0] > v[0] ) v[0] = m->v[0];
if (m->v[1] > v[1] ) v[1] = m->v[1];
}
inline friend ddgVector2 operator*( const float d, const ddgVector2& u)
{ return ddgVector2(u[0]*d,u[1]*d); }
inline friend ddgVector2 operator*( const ddgVector2& u, const float d)
{ return ddgVector2(u[0]*d,u[1]*d); }
inline friend ddgVector2 operator/( const ddgVector2& u, const float d)
{ return ddgVector2(u[0]/d,u[1]/d); }
};
#ifdef DDGSTREAM
WEXP ostream& WFEXP operator << ( ostream&s, ddgVector2 v );
WEXP ostream& WFEXP operator << ( ostream&s, const ddgVector2* v );
WEXP istream& WFEXP operator >> ( istream& s, ddgVector2& v);
#endif // DDGSTREAM
class Matrix3;
class WEXP ddgVector3 {
public:
float v[3];
operator float* () { return v; }
inline float operator[](int n) const { return v[n]; }
inline float & operator[] (int n) { return v[n]; }
bool operator==(ddgVector3& u) { return v[0] == u[0] && v[1] == u[1] && v[2] == u[2]; }
bool operator!=(ddgVector3& u) { return v[0] != u[0] || v[1] != u[1] || v[2] != u[2]; }
friend bool operator == (const ddgVector3& u, const ddgVector3& v)
{ return v[0] == u[0] && v[1] == u[1] && v[2] == u[2];
}
friend bool operator != (const ddgVector3& u, const ddgVector3& v)
{ return v[0] != u[0] || v[1] != u[1] || v[2] != u[2];
}
void assign( float *a) { a[0] = v[0]; a[1] = v[1]; a[2] = v[2]; }
ddgVector3(void ) { }
ddgVector3(float *a ) { v[0] = a[0]; v[1] = a[1]; v[2] = a[2]; }
ddgVector3(float a, float b, float c ) { v[0] = a; v[1] = b; v[2] = c;}
ddgVector3( const ddgVector3* u ) { v[0] = u->v[0]; v[1] = u->v[1]; v[2] = u->v[2]; }
ddgVector3& operator=(const ddgVector3& s) { v[0] = s[0]; v[1] = s[1]; v[2] = s[2]; return *this; }
void zero( void ) { v[0] = v[1] = v[2] = 0.0;}
void set(float a, float b, float c ) { v[0] = a; v[1] = b; v[2] = c; }
void set( const ddgVector3 *u ) { v[0] = u->v[0]; v[1] = u->v[1]; v[2] = u->v[2]; }
void get(float *a, float *b, float *c) { *a = v[0]; *b = v[1]; *c = v[2]; }
void add( const ddgVector3 *u ) { v[0] += u->v[0]; v[1] += u->v[1]; v[2] += u->v[2]; }
ddgVector3& operator+=( const ddgVector3& u)
{ v[0]+=u[0]; v[1] += u[1]; v[2] += u[2]; return *this; }
ddgVector3& operator-=( const ddgVector3& u)
{ v[0]-=u[0]; v[1] -= u[1]; v[2] -= u[2]; return *this; }
ddgVector3& operator*=( const ddgVector3& u)
{ v[0]*=u[0]; v[1] *= u[1]; v[2] *= u[2]; return *this; }
ddgVector3& operator*=( const float d)
{ v[0]*= d; v[1] *= d; v[2] *= d; return *this; }
ddgVector3& operator/=( const ddgVector3& u)
{ v[0]/=u[0]; v[1] /= u[1]; v[2] /= u[2]; return *this; }
ddgVector3& operator/=( const float d)
{ v[0]/= d; v[1] /= d; v[2] /= d; return *this; }
inline friend ddgVector3 operator+( const ddgVector3& u, const ddgVector3& w)
{ return ddgVector3(u[0]+w[0],u[1]+w[1],u[2]+w[2]); }
void subtract( const ddgVector3 *u ) { v[0] -= u->v[0]; v[1] -= u->v[1]; v[2] -= u->v[2]; }
inline friend ddgVector3 operator-( const ddgVector3& u, const ddgVector3& w)
{ return ddgVector3(u[0]-w[0],u[1]-w[1],u[2]-w[2]); }
void multiply( float s ) { v[0] *= s; v[1] *= s; v[2] *= s; }
inline friend ddgVector3 operator*( const ddgVector3& u, const ddgVector3& w)
{ return ddgVector3(u[0]*w[0],u[1]*w[1],u[2]*w[2]); }
void multiply( const ddgVector3 *u ) { v[0] *= u->v[0]; v[1] *= u->v[1]; v[2] *= u->v[2]; }
void divide( float s ) { float s2=1.0f/s; multiply(s2); }
void divide( const ddgVector3* u ) { v[0] /= u->v[0]; v[1] /= u->v[1]; v[2] /= u->v[2]; }
inline friend ddgVector3 operator/( const ddgVector3& u, const ddgVector3& w)
{ return ddgVector3(u[0]/w[0],u[1]/w[1],u[2]/w[2]); }
float sizesq( void ) { return (v[0]*v[0]+v[1]*v[1]+v[2]*v[2]); }
float size( void ) { return sqrtf(sizesq()); }
bool null( void ) { return (v[0] == 0.0 && v[1] == 0.0 && v[2] == 0.0); }
void normalize( void ) { divide(size()); }
float angle( const ddgVector3 *u ) { return ddgAngle::radtodeg(acosf(dot(u))); }
void vectortoangle( void )
{
float yaw, pitch;
if (v[2] == 0 && v[0] == 0) // Directly overhead or underfoot.
{
yaw = 0;
if (v[1] > 0) pitch = 90.0f;
else pitch = 270.0f;
}
else
{
yaw = (float)(int) 90+ddgAngle::radtodeg(atan2f(v[2], v[0]));
yaw = ddgAngle::mod(yaw);
pitch = (float)(int) ddgAngle::radtodeg(atan2f(v[1], sqrtf(v[0]*v[0] + v[2]*v[2])));
pitch = ddgAngle::mod(pitch);
}
v[PITCH] = -pitch;
v[YAW] = yaw;
v[ROLL] = 0;
}
void angletovector (ddgVector3 *forward, ddgVector3 *right =0, ddgVector3 *up =0)
{
float angle;
static float sr, sp, sy, cr, cp, cy;
angle = ddgAngle::degtorad(v[YAW]);
sy = sinf(angle);
cy = cosf(angle);
angle = ddgAngle::degtorad(v[PITCH]);
sp = sinf(angle);
cp = cosf(angle);
angle = ddgAngle::degtorad(v[ROLL]);
sr = sinf(angle);
cr = cosf(angle);
if (forward)
{
forward->v[2] = -cp*cy;
forward->v[0] = -cp*sy;
forward->v[1] = -sp;
}
if (right)
{
right->v[2] = (sr*sp*cy+cr*-sy);
right->v[0] = (sr*sp*sy+cr*cy);
right->v[1] = -1*sr*cp;
}
if (up)
{
up->v[2] = (-cr*sp*cy+sr*-sy);
up->v[0] = (-cr*sp*sy+sr*cy);
up->v[1] = cr*cp;
}
}
void cross( const ddgVector3 *u, const ddgVector3 *w )
{
v[0] = u->v[2]*w->v[1] - u->v[1]*w->v[2];
v[1] = u->v[0]*w->v[2] - u->v[2]*w->v[0];
v[2] = u->v[1]*w->v[0] - u->v[0]*w->v[1];
}
inline friend ddgVector3 operator%( const ddgVector3& u, const ddgVector3& w)
{
return ddgVector3( u[2]*w[1] - u[1]*w[2],
u[0]*w[2] - u[2]*w[0],
u[1]*w[0] - u[0]*w[1]);
}
float dot ( const ddgVector3 *u )
{ return u->v[0]*v[0]+ u->v[1]*v[1]+ u->v[2]*v[2]; }
inline friend float operator|( const ddgVector3& u, const ddgVector3& w)
{ return u[0]*w[0]+ u[1]*w[1]+ u[2]*w[2]; }
void inverse() {multiply(-1.0);}
// Calculate the normal for 3 non colinear points in space.
void normal( const ddgVector3 *p0, const ddgVector3 *p1, const ddgVector3 *p2 )
{
ddgVector3 u( *p0 - *p1 ), v(*p2 - *p1);
cross(&u,&v);
}
// Calculate a nicer normal useful for regular grids.
void normal( const ddgVector3* v[9] );
// Return the reflection vector of this, given a normal.
// UNTESTED:
void reflect( ddgVector3 *n) // I - 2*(I.N)*N
{
ddgVector3 r(this);
r.multiply(-2*r.dot(n));
r.multiply(n);
r.add(this);
set(&r);
}
void refract( const ddgVector3 *n, float eta )
{
float IdotN = dot(n);
float k = 1 - eta*eta*(1- IdotN*IdotN);
if (k < 0) set(0,0,0);
else
{
ddgVector3 t(n);
t.multiply(eta*IdotN+sqrtf(k));
multiply(eta);
subtract(&t);
}
}
void minimum(const ddgVector3* m )
{
if (m->v[0] < v[0] ) v[0] = m->v[0];
if (m->v[1] < v[1] ) v[1] = m->v[1];
if (m->v[2] < v[2] ) v[2] = m->v[2];
}
void maximum(const ddgVector3* m )
{
if (m->v[0] > v[0] ) v[0] = m->v[0];
if (m->v[1] > v[1] ) v[1] = m->v[1];
if (m->v[2] > v[2] ) v[2] = m->v[2];
}
inline friend ddgVector3 operator*( const float d, const ddgVector3& u)
{ return ddgVector3(u[0]*d,u[1]*d,u[2]*d); }
inline friend ddgVector3 operator*( const ddgVector3& u, const float d)
{ return ddgVector3(u[0]*d,u[1]*d,u[2]*d); }
inline friend ddgVector3 operator/( const ddgVector3& u, const float d)
{ return ddgVector3(u[0]/d,u[1]/d,u[2]/d); }
};
#ifdef DDGSTREAM
WEXP ostream& WFEXP operator << ( ostream&s, ddgVector3 v );
WEXP ostream& WFEXP operator << ( ostream&s, const ddgVector3* v );
WEXP istream& WFEXP operator >> ( istream& s, ddgVector3& v);
#endif
class ddgMatrix4;
class WEXP ddgVector4 {
public:
float v[4];
operator float* () { return v; }
inline float operator[](int n) const { return v[n]; }
inline float & operator[] (int n) { return v[n]; }
bool operator==(ddgVector4& u)
{ return v[0] == u[0] && v[1] == u[1] && v[2] == u[2] && v[3] == u[3]; }
bool operator!=(ddgVector4& u)
{ return v[0] != u[0] || v[1] != u[1] || v[2] != u[2] || v[3] != u[3]; }
friend bool operator == (const ddgVector4& u, const ddgVector4& v)
{ return v[0] == u[0] && v[1] == u[1] && v[2] == u[2] && v[3] == u[3];
}
friend bool operator != (const ddgVector4& u, const ddgVector4& v)
{ return v[0] != u[0] || v[1] != u[1] || v[2] != u[2] || v[3] != u[3];
}
ddgVector4(void ) { }
ddgVector4(float a, float b, float c, float d ) { v[0] = a; v[1] = b; v[2] = c; v[3] = d;}
ddgVector4( const ddgVector4* u ) { v[0] = u->v[0]; v[1] = u->v[1]; v[2] = u->v[2]; v[3] = u->v[3];}
ddgVector4( const float* u ) { v[0] = u[0]; v[1] = u[1]; v[2] = u[2]; v[3] = u[3];}
ddgVector4( const ddgVector3* u ) { v[0] = u->v[0]; v[1] = u->v[1]; v[2] = u->v[2]; v[3] = 0;}
ddgVector4& operator=(const ddgVector4& u) { v[0] = u[0]; v[1] = u[1]; v[2] = u[2]; v[3] = u[3]; return *this; }
void zero( void ) { v[0] = v[1] = v[2] = v[3] = 0.0; }
void set(float a, float b, float c, float d ) { v[0] = a; v[1] = b; v[2] = c; v[3] = d; }
void set( const ddgVector3 *u ) { v[0] = u->v[0]; v[1] = u->v[1]; v[2] = u->v[2]; v[3] = 0;}
void set( const ddgVector4 *u ) { v[0] = u->v[0]; v[1] = u->v[1]; v[2] = u->v[2]; v[3] = u->v[3];}
void set( const float *u ) { v[0] = u[0]; v[1] = u[1]; v[2] = u[2]; v[3] = u[3];}
void get(float *a, float *b, float *c, float *d) { *a = v[0]; *b = v[1]; *c = v[2]; *d = v[3]; }
void add( const ddgVector4 *u ) { v[0] += u->v[0]; v[1] += u->v[1]; v[2] += u->v[2]; v[3] += u->v[3]; }
ddgVector4& operator+=( const ddgVector4& u)
{ v[0]+=u[0]; v[1] += u[1]; v[2] += u[2]; v[3] += u[3]; return *this; }
ddgVector4& operator-=( const ddgVector4& u)
{ v[0]-=u[0]; v[1] -= u[1]; v[2] -= u[2]; v[3] -= u[3]; return *this; }
ddgVector4& operator*=( const ddgVector4& u)
{ v[0]*=u[0]; v[1] *= u[1]; v[2] *= u[2]; v[3] *= u[3]; return *this; }
ddgVector4& operator*=( const float d)
{ v[0]*=d; v[1] *= d; v[2] *= d; v[3] *= d; return *this; }
ddgVector4& operator/=( const ddgVector4& u)
{ v[0]/=u[0]; v[1] /= u[1]; v[2] /= u[2]; v[3] /= u[3]; return *this; }
ddgVector4& operator/=( float d)
{ v[0]/=d; v[1] /= d; v[2] /= d; v[3] /= d; return *this; }
inline friend ddgVector4 operator+( const ddgVector4& u, const ddgVector4& w)
{ return ddgVector4(u[0]+w[0],u[1]+w[1],u[2]+w[2],u[3]+w[3]); }
void subtract( const ddgVector4 *u ) { v[0] -= u->v[0]; v[1] -= u->v[1]; v[2] -= u->v[2]; v[3] -= u->v[3]; }
inline friend ddgVector4 operator-( const ddgVector4& u, const ddgVector4& w)
{ return ddgVector4(u[0]-w[0],u[1]-w[1],u[2]-w[2],u[3]-w[3]); }
void multiply( float s ) { v[0] *= s; v[1] *= s; v[2] *= s; v[3] *= s; }
void multiply( ddgVector4* u ) { v[0] *= u->v[0]; v[1] *= u->v[1]; v[2] *= u->v[2]; v[3] *= u->v[3];}
inline friend ddgVector4 operator*( const ddgVector4& u, const ddgVector4& w)
{ return ddgVector4(u[0]*w[0],u[1]*w[1],u[2]*w[2],u[3]*w[3]); }
void divide( float s ) { v[0] /= s; v[1] /= s; v[2] /= s; v[3] /= s; }
void divide( const ddgVector4* u ) { v[0] /= u->v[0]; v[1] /= u->v[1]; v[2] /= u->v[2]; v[3] /= u->v[3];}
inline friend ddgVector4 operator/( const ddgVector4& u, const ddgVector4& w)
{ return ddgVector4(u[0]/w[0],u[1]/w[1],u[2]/w[2],u[3]/w[3]); }
bool null( void ) { return ((v[0] == v[1]) == (v[2] == v[3])) == 0.0; }
ddgVector4* multiply( const ddgMatrix4 *m1, const ddgVector4 *v1 );
inline friend ddgVector4 operator*( const float d, const ddgVector4& u)
{ return ddgVector4(u[0]*d,u[1]*d,u[2]*d,u[3]*d); }
inline friend ddgVector4 operator*( const ddgVector4& u, const float d)
{ return ddgVector4(u[0]*d,u[1]*d,u[2]*d,u[3]*d); }
inline friend ddgVector4 operator/( const ddgVector4& u, const float d)
{ return ddgVector4(u[0]/d,u[1]/d,u[2]/d,u[3]/d); }
float dot ( const ddgVector4 *u )
{ return u->v[0]*v[0]+ u->v[1]*v[1] + u->v[2] * v[2] + u->v[3] * v[3]; }
};
#ifdef DDGSTREAM
WEXP ostream& WFEXP operator << ( ostream&s, ddgVector4 v );
WEXP ostream& WFEXP operator << ( ostream&s, const ddgVector4* v );
WEXP istream& WFEXP operator >> ( istream& s, ddgVector4& v);
#endif // DDGSTREAM
#endif