1
1
forked from 0ad/0ad
0ad/source/dcdt/se/sr_vec.h
2007-10-16 08:12:48 +00:00

262 lines
10 KiB
C++

/** \file sr_vec.h
* Three dimensional vector */
# ifndef SR_VEC_H
# define SR_VEC_H
# include "sr_input.h"
# include "sr_output.h"
class SrVec;
class SrVec2;
/*! This "point typedef" is used mainly to coherently describe variables,
making possible to distiguish points from vectors parameters. */
typedef SrVec SrPnt;
/*! \class SrVec sr_vec.h
\brief Three dimensional vector.
Its three coordinates are of type float, and can be accessed with the
provided methods or as a float array, to be compatible with other libraries.
Access as a float array is done with an overloaded typecast, that should
correctly work with most compilers. */
class SrVec
{ public :
float x, y, z;
public :
static const SrVec null; //!< (0,0,0) null vector
static const SrVec one; //!< (1,1,1) vector
static const SrVec minusone; //!< (-1,-1,-1) vector
static const SrVec i; //!< (1,0,0) vector
static const SrVec j; //!< (0,1,0) vector
static const SrVec k; //!< (0,0,1) vector
public :
/*! Initializes SrVec as a null vector. Implemented inline. */
SrVec () : x(0), y(0), z(0) {}
/*! Initializes SrVec from an int pointer. Implemented inline. */
SrVec ( const int *v ) : x((float)v[0]), y((float)v[1]), z((float)v[2]) {}
/*! Initializes from a float pointer. Implemented inline. */
SrVec ( const float *v ) : x((float)v[0]), y((float)v[1]), z((float)v[2]) {}
/*! Initializes from a double pointer. Implemented inline. */
SrVec ( const double *v ) : x((float)v[0]), y((float)v[1]), z((float)v[2]) {}
/*! Copy constructor. Implemented inline. */
SrVec ( const SrVec& v ) : x(v.x), y(v.y), z(v.z) {}
/*! Initializes from a 2d vector: the z coordinate is set to zero. */
SrVec ( const SrVec2& v );
/*! Initializes with the three given float coordinates. Implemented inline. */
SrVec ( float a, float b, float c ) : x(a), y(b), z(c) {}
/*! Sets coordinates from an int pointer. Implemented inline. */
void set ( const int *v ) { x=(float)v[0]; y=(float)v[1]; z=(float)v[2]; }
/*! Sets coordinates from a float pointer. Implemented inline. */
void set ( const float *v ) { x=(float)v[0]; y=(float)v[1]; z=(float)v[2]; }
/*! Sets coordinates from a double pointer. Implemented inline. */
void set ( const double *v ) { x=(float)v[0]; y=(float)v[1]; z=(float)v[2]; }
/*! Sets coordinates from the three given float values. Implemented inline. */
void set ( float a, float b, float c ) { x=a; y=b; z=c; }
/*! Sets coordinates from another SrVec. Implemented inline. */
void set ( const SrVec& v ) { x=v.x; y=v.y; z=v.z; }
/*! Sets coordinates from a 2d vector: the z coordinate is set to zero. */
void set ( const SrVec2& v );
/*! Put in f the coordinate values. */
void get ( float f[3] ) const { f[0]=x; f[1]=y; f[2]=z; }
/*! Apply a rotation to SrVec around the X axis with
the angle 'a' where sa=sin(a) and ca=cos(a). */
void rotx ( float sa, float ca );
/*! Apply a rotation to SrVec around the Y axis with
the angle 'a' where sa=sin(a) and ca=cos(a). */
void roty ( float sa, float ca );
/*! Apply a rotation to SrVec around the Z axis with
the angle 'a' where sa=sin(a) and ca=cos(a). */
void rotz ( float sa, float ca );
/*! Same as the other rotx() method, but with one parameter
angle in radians. */
void rotx ( float radians );
/*! Same as the other roty() method, but with one parameter
angle in radians. */
void roty ( float radians );
/*! Same as the other rotz() method, but with one parameter
angle in radians. */
void rotz ( float radians );
/*! Makes each coordinate to have its absolute value. */
void abs ();
/*! Normalizes the vector. If its norm is 0, the vector is not changed. */
void normalize ();
/*! Sets the length to be n and returns the previous length */
float len ( float n );
/*! Returns the length of the vector. Equivalent to norm() */
float len () { return norm(); }
/*! Returns the norm (distance to zero) of the vector. If the vector is
null, zero is returned. */
float norm () const;
/*! Returns the square of the norm (x*x + y*y + z*z). */
float norm2 () const;
/*! Returns the norm, but using the max function of distance, which does not require sqrt() */
float norm_max () const;
/*! Returns a 2d orthogonal vector to the 2d vector(x,y) that is (-y,x)
The z coordinate of SrVec is not considered. Implemented inline. */
SrVec ortho2d () const { return SrVec(-y,x,0); }
/*! Returns true if all coordinates are zero; false otherwise. */
bool iszero () const { return x==0.0 && y==0.0 && z==0.0? true:false; }
/*! Returns true if the vector is inside the closed neighboorhood of point 0,0,0 and radius ds. */
bool nextzero ( float ds ) const { return norm2()<=ds*ds? true:false; }
/*! Allows member access like a vector. */
float& operator[] ( int i ) { return *((&x)+i); }
/*! Convertion to a float pointer. */
operator float* () const { return (float*)&x; }
/*! Copy operator from another SrVec. Implemented inline. */
void operator = ( const SrVec& v ) { set(v); }
/*! Copy operator from a 2d vector: the z coordinate is set to zero. */
void operator = ( const SrVec2& v ) { set(v); }
/*! Copy operator from an int pointer. Implemented inline. */
void operator = ( const int *v ) { set(v); }
/*! Copy operator from a float pointer. Implemented inline. */
void operator = ( const float *v ) { set(v); }
/*! Copy operator from a double pointer. Implemented inline. */
void operator = ( const double *v ) { set(v); }
/*! Operator-=() with another SrVec. Implemented inline. */
void operator -= ( const SrVec& v ) { x-=v.x; y-=v.y; z-=v.z; }
/*! Operator+=() with another SrVec. Implemented inline. */
void operator += ( const SrVec& v ) { x+=v.x; y+=v.y; z+=v.z; }
/*! Operator*=() with a float. Implemented inline. */
void operator *= ( float r ) { x*=r; y*=r; z*=r; }
/*! Operator/=() with a float. Implemented inline. */
void operator /= ( float r ) { x/=r; y/=r; z/=r; }
/*! Unary minus. Implemented inline. */
friend SrVec operator - ( const SrVec& v )
{ return SrVec ( -v.x, -v.y, -v.z ); }
/*! Adds two vectors. Implemented inline. */
friend SrVec operator + ( const SrVec& v1, const SrVec& v2 )
{ return SrVec (v1.x+v2.x, v1.y+v2.y, v1.z+v2.z); }
/*! Subtracts two vectors. Implemented inline. */
friend SrVec operator - ( const SrVec& v1, const SrVec& v2 )
{ return SrVec (v1.x-v2.x, v1.y-v2.y, v1.z-v2.z); }
/*! Comparison operator. Implemented inline. */
friend bool operator == ( const SrVec& v1, const SrVec& v2 )
{ return v1.x==v2.x && v1.y==v2.y && v1.z==v2.z? true:false; }
/*! Comparison operator. Implemented inline. */
friend bool operator != ( const SrVec& v1, const SrVec& v2 )
{ return v1.x!=v2.x || v1.y!=v2.y || v1.z!=v2.z? true:false; }
/*! Pos multiplication by scalar. Implemented inline. */
friend SrVec operator * ( const SrVec& v, float r )
{ return SrVec (v.x*r, v.y*r, v.z*r); }
/*! Pre multiplication by scalar. Implemented inline. */
friend SrVec operator * ( float r, const SrVec& v )
{ return SrVec (v.x*r, v.y*r, v.z*r); }
/*! Division by scalar. Implemented inline. */
friend SrVec operator / ( const SrVec& v, float r )
{ return SrVec (v.x/r, v.y/r, v.z/r); }
/*! Swaps the contents of v1 with v2. */
friend void swap ( SrVec& v1, SrVec& v2 );
/*! Returns true if dist(v1,v2)<=ds, otherwise returns false. Implemented inline. */
friend bool next ( const SrVec& v1, const SrVec& v2, float ds )
{ return dist2(v1,v2)<=ds*ds? true:false; }
/*! Returns the distance between v1 and v2 using norm_max(). */
friend float dist_max ( const SrVec& v1, const SrVec& v2 );
/*! Returns the distance between v1 and v2. */
friend float dist ( const SrVec& v1, const SrVec& v2 );
/*! Returns the square of the distance between v1 and v2. */
friend float dist2 ( const SrVec& v1, const SrVec& v2 );
/*! Returns the angle between v1 and v2, that is inside the interval [0,pi],
using acosf. The returned angle is in radians. */
friend float angle ( const SrVec& v1, const SrVec& v2 );
/*! Returns the angle between v1 and v2, but considering that
v1 and v2 are already normalized, ie, computes acosf(dot(v1,v2)). */
friend float angle_fornormvecs ( const SrVec& v1, const SrVec& v2 );
/*! Returns the cross product of v1 and v2. */
friend SrVec cross ( const SrVec& v1, const SrVec& v2 );
/*! Inline version of cross(), but as a member.
Attention: v1 or v2 cannot be the same as SrVec. */
void cross ( const SrVec& v1, const SrVec& v2 );
/*! Returns the dot product of v1 and v2 (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z).
Its interpretation is the length of the projection of v1 onto v2
( v1.v2 = |v1||v2|cos(ang) ). */
friend float dot ( const SrVec& v1, const SrVec& v2 );
/* Returns the normalized normal of triangle (a,b,c) */
friend SrVec triangle_normal ( const SrPnt& a, const SrPnt& b, const SrPnt& c );
/*! Returns -1,0,1 depending if v1 is less, equal or greater than v2,
using a comparison by coordinates. Parameters are passed by reference. */
friend int compare ( const SrVec& v1, const SrVec& v2 );
/*! Returns -1,0,1 depending if v1 is less, equal or greater than v2,
using a comparison by coordinates. Parameters are passed by pointers. */
friend int compare ( const SrVec* v1, const SrVec* v2 );
/*! Returns the linear interpolation of v1 v2 in parameter t ( v1(1-t)+v2(t) ). */
friend SrVec lerp ( const SrVec& v1, const SrVec& v2, float t );
/*! Outputs in format: "x y z". */
friend SrOutput& operator<< ( SrOutput& o, const SrVec& v );
/*! Inputs from format: "x y z". */
friend SrInput& operator>> ( SrInput& in, SrVec& v );
};
float angle ( const SrVec& v1, const SrVec& v2 );
//============================== end of file ===============================
# endif // SR_VEC_H