template< class T >
class Vector3
{
public:
T x, y, z; // The compisite forces.
// METHODS //
Vector3 ( T X=0.0f, T Y=0.0f, T Z=0.0f )
{
x=X;
y=Y;
z=Z;
}
// Normal methods
const T xyTheta() const { return atan2( y, x ); }
const T yzTheta() const { return atan2( y, z ); }
const T xzTheta() const { return atan2( z, x ); }
// UNTESTED! (But no need, so...)
const Vector3 xyTheta( T newA ) const // newA = New Angle
{
const T M = magnitude();
// If sin(A) = y/M
// y = M * sin(A)
// newY = M * sin(newA)
// newX = M * cos(newA)
return Vector3
(
M * cos( newA ),
M * sin( newA )
);
}
// Get the magnitude of the vector.
const T magnitude() const { return sqrt( x*x + y*y + z*z ); }
const T magnitude2() const { return x*x + y*y + z*z; }
/* I decided that this should NOT return itself.
Although I WAS treating it as a get(), I found that this
function might be more apropriet to treat like an operator.
(An operator returns a NEW onject.)
Although this may not be intuitive, the overloaded
operator=(T) will take it's place. This provides me
with easy ways to get what a vector would look like a X magnitude
without modifying it, but also an easy way to modify it.
*/
const Vector3 magnitude( T newMagnitude ) const
{
// We'll call sqrt() on mag if it's not zero.
T mag = magnitude2();
// Avoid a divide by zero.
if( !mag )
return Vector3( 0.0f, 0.0f, 0.0f );
// Find the rate of change.
T k = newMagnitude / sqrt( mag );
// Change x, y, and z.
return *this * k;
}
T xyMagnitude() { return sqrt( x*x + y*y ); } const
T yzMagnitude() { return sqrt( y*y + z*z ); } const
T xzMagnitude() { return sqrt( x*x + z*z ); } const
T yzMagnitude2() { return y*y + z*z; } const
T xyMagnitude2() { return x*x + y*y; } const
T xzMagnitude2() { return x*x + z*z; } const
/* Although magnitude() doesn't modify itself, I though it
more intuitive that clamp WOULD modify itself.
*/
Vector3& clampMag( T max )
{
// I bet an extra multiplication is cheaper than sqrt(), so...
if( this->magnitude2() > max*max )
*this = max;
return *this;
}
Vector3& normalize()
{
return *this /= magnitude();
}
// Math and arithmetic operators:
const Vector3 operator + ( Vector3 right ) const
{
return Vector3( x + right.x, y + right.y, z + right.z );
}
const Vector3 operator - ( Vector3 right ) const
{
return Vector3( x - right.x, y - right.y, z - right.z );
}
const Vector3 operator * ( T right ) const
{
return Vector3( x*right, y*right, z*right );
}
const Vector3 operator * ( Vector3 right ) const
{
return Vector3( x*right.x, y*right.y, z*right.z );
}
const Vector3 operator / ( T right ) const
{
return Vector3( x/right, y/right, z/right );
}
// Unary operator.
const Vector3 operator - () const
{
return Vector3( -x, -y, -z );
}
// Assignment operators.
const Vector3& operator = ( PolarVector right )
{
x = right.x();
y = right.y();
return *this;
}
/* This sets the magnitude to the value of right.
It might seem a little unintuitive, but I deemed it
the more apropriet way to do this compaired with mag( newMag ).
*/
const Vector3& operator = ( const T newMag )
{
T mag = magnitude2();
// Avoid a divide by zero.
if( !mag )
return *this;
// Find the rate of change.
T k = newMag / sqrt( mag );
// Change x, y, and z.
return (*this) *= k;
}
Vector3& operator += ( Vector3 right )
{
x += right.x;
y += right.y;
z += right.z;
return *this;
}
Vector3& operator -= ( Vector3 right )
{
x -= right.x;
y -= right.y;
z -= right.z;
return *this;
}
Vector3& operator *= ( T right )
{
x *= right;
y *= right;
z *= right;
return *this;
}
Vector3& operator /= ( T right )
{
x /= right;
y /= right;
z /= right;
return *this;
}
// IMPLICITE CONVERSIONS //
/* True if either x, y, or z is non-zero.
Good for inside if statements. I know implicite bool convertion
might not be the BEST solution, but there's not GREAT solution
I know of.
*/
operator const bool() const
{
return x || y || z;
}
};
template< class T >
class Vector3
{
public:
T x, y, z; // The compisite forces.
Vector3( const T X, const T Y, const T Z )
: x(X), y(Y), z(Z)
{
}
Vector3()
: x(0), y(0), z(0)
{
}
// Theta on different axies.
T xyTheta() const { return atan2( y, x ); }
T yzTheta() const { return atan2( y, z ); }
T xzTheta() const { return atan2( z, x ); }
// UNTESTED! (But no need, so...)
Vector3 xyTheta( const T newA ) const // newA = New Angle
{
const T M = magnitude();
// If sin(A) = y/M
// y = M * sin(A)
// newY = M * sin(newA)
// newX = M * cos(newA)
return Vector3
(
M * cos( newA ),
M * sin( newA ),
0.0f
);
}
/* Get the magnitude of the vector. */
const T magnitudeSqr() const { return x*x + y*y + z*z; }
const T magnitude() const { return sqrt( magnitudeSqr() ); }
T yzMagnitudeSqr() { return y*y + z*z; } const
T xyMagnitudeSqr() { return x*x + y*y; } const
T xzMagnitudeSqr() { return x*x + z*z; } const
T xyMagnitude() const { return sqrt( yzMagnitudeSqr() ); }
T yzMagnitude() const { return sqrt( xyMagnitudeSqr() ); }
T xzMagnitude() const { return sqrt( xzMagnitudeSqr() ); }
Vector3& normalize()
{
return *this /= magnitude();
}
/* This sets the magnitude to the value of right. */
Vector3& magnitude( const T newMag )
{
T mag = magnitudeSqr();
// Avoid a divide by zero.
if( !mag )
return *this;
// Find the rate of change.
T k = newMag / sqrt( mag );
// Change x, y, and z.
return (*this) *= k;
}
Vector3& clampMag( const T max )
{
// I bet an extra multiplication is cheaper than sqrt(), so...
if( this->magnitudeSqr() > max*max )
this->magnitude( max );
return *this;
}
// Unary operator.
Vector3 operator - () const
{
return Vector3( -x, -y, -z );
}
// Assignment operators.
Vector3& operator = ( PolarVector right )
{
x = right.x();
y = right.y();
return *this;
}
template< class Y >
Vector3& operator = ( Vector3<Y> right )
{
x = right.x;
y = right.y;
z = right.z;
return *this;
}
template< class Y >
Vector3& operator += ( Vector3<Y> right )
{
x += right.x;
y += right.y;
z += right.z;
return *this;
}
template< class Y >
Vector3& operator -= ( Vector3<Y> right )
{
x -= right.x;
y -= right.y;
z -= right.z;
return *this;
}
template< class Y >
Vector3& operator *= ( Y right )
{
x *= right;
y *= right;
z *= right;
return *this;
}
template< class Y >
Vector3& operator /= ( Y right )
{
x /= right;
y /= right;
z /= right;
return *this;
}
/* TODO get help on this. How does B multiply?
static Vector3 resolute( Vector3 A, Vector3 B )
{
// According to wiki: C = (A*B)/mag(B)^2 * B
return B * ( product(B)/B.magnitude2() );
// Won't work: bulshit errors.
// But don't need.
}
*/
// IMPLICITE CONVERSIONS //
/* True if either x, y, or z is non-zero.
Good for inside if statements.
I know there there are potential problems.
I'll watch out for them and adjust WHEN they occure.
*/
operator const bool() const
{
return x || y || z;
}
};
// MATH OPERATION WITH VECTORS //
/* Having them return const takes out nonsense operations like (a*b)=c */
template< class T > inline
const Vector3<T> operator + ( const Vector3<T>& a, const Vector3<T>& b )
{
return Vector3<T>( a ) += b;
}
template< class T > inline
const Vector3<T> operator - ( const Vector3<T>& a, const Vector3<T>& b )
{
return Vector3<T>( a ) -= b;
}
/* Dot product.
I think * for dot product and ^ for cross is intuitive ENOUGH.
*/
template< class T, class Y > inline
const T operator * ( const Vector3<T>& a, const Vector3<Y>& b )
{
return Vector3<T>( a ) *= b;
}
// Scaler operators:
template< class T, class Y > inline
const Vector3<T> operator * ( const Vector3<T>& a, const Y b )
{
return Vector3<T>( a ) *= b;
}
template< class T, class Y > inline
const Vector3<T> operator * ( const T b, const Vector3<Y>& a )
{
return a * b;
}
template< class T, class Y > inline
const Vector3<T> operator / ( const Vector3<T>& a, const Y b )
{
return Vector3<T>( a ) /= b;
}
template< class T, class Y > inline
const Vector3<T> magnitude( const Vector3<T>& vect, const Y newMagnitude )
{
return Vector3<T>( vect ).magnitude( newMagnitude );
}
// If there was any input... (input is a vector representing directional input.
if( input = speed ) // Speed is a pre-defined float
{
// Vector=float does nothing if the magnitude is zero (it'll return false).
// But, we'll get the proper magnitude otherwise, AND it'll return true!
// ( Sacraficing clarity for wittyness :D )
// If a shot can be fired...
if( keyStates[ SDLK_a] // AWESOME mode invoked by 'a'
|| ticks-timeOfLastShot > delay
|| SDL_JoystickGetButton( joystick , 5 ) // AWESOME mode invoked by triggers.
|| SDL_JoystickGetButton( joystick , 4 ) )
{
// Looks dangerous, but I have things set up so I don't need to worry
// about memory allocation/deallocation. I really do.
new Bullet
(
player->pos + input.magnitude( 15 ), // Spawn point. Input does NOT take the magnitude of 15 because of changes I made to Vector3
input, // Initial velocity (why I set input's magnitude to speed).
GLVector3( 0.0f, 0.0f, input.xyTheta() * R_TO_D ) // The rotation vector.
);
timeOfLastShot = ticks;
// The player gets kicked back.
player->vel = input.magnitude( speed );
rot.z = input.xyTheta() * R_TO_D;