Archived

This topic is now archived and is closed to further replies.

paulecoyote

Anyone have decent 3D Vector Class source code to share?

Recommended Posts

Hi all, I''m looking for a decent 3d vector class that represents i, j, k and may have useful utility functions in there to boot. Alternatively a very through tutorial on rolling your own. I can read and write C, C#, C++ and Java - but it''s actually for a Java application. As it''s for a game float precision is prefered . I''ve googled it and seem to get many seemingly conflicting implementations, and I seem to have lost my Maths books. Although I''m writing my own I want to check that what I''m doing is right, and I don''t want to completly re-invent the wheel if someone else somewhere has kindy shared this infomation. Cheers, Paul

Share this post


Link to post
Share on other sites
It is easy if you understand the vector math. I have vector classes in 2d, 3d, and 4d that I created for my engine. It comes to a little over 2000 lines of code if you add the lines in the header file. You shouldn''t need a tutorial to create the vector class(es). It you don''t know the math, I suggest getting a calculus book. I have a few my sis gave me that goes over vectors. Or I suggest the books Mathematics for 3D Game Programming & Computer Graphics (although a little light on vectors besides the easy parts) and Programming Dynamic Character Animation (they have whole chapters to vectors, matrices, and quaternions that are decent). I doubt you will find a tutorial that actually teaches you anything but good luck. I hope this helped.

Share this post


Link to post
Share on other sites
Yeah - I should know this stuff - was taught it but haven''t use it for years so I''m not sure of it anymore. As I said I am writing my own but I kind of would like some guiding code / tutorial to make sure I''m doing the right thing.
I''ll head down the library on the weekend if I remember, I refuse to buy a book for something I just need to brush up on rather then learn from scratch. I programmed neural nets at university ffs.

Share this post


Link to post
Share on other sites

// Vector3.h


#ifndef VECTOR_H
#define VECTOR_H

class Vector3
{
public:
Vector3();
Vector3(const Vector3 &v);
Vector3(const float x, const float y,const float z);
Vector3(const float *v);
Vector3(const double *v);

float &x();
const float &x() const;

float &y();
const float &y() const;

float &z();
const float &z() const;

float &operator[](const int i);
const float &operator[](const int i) const;

bool operator==(const Vector3 &v) const;
bool operator!=(const Vector3 &v) const;

Vector3 &operator= (const Vector3 &v);
Vector3 &operator= (const float *);
Vector3 &operator= (const double *);
Vector3 &operator+=(const Vector3 &v);
Vector3 &operator-=(const Vector3 &v);
float operator*(const Vector3 &v) const; // shorthand for dotprod

Vector3 &operator*=(const float &x);
Vector3 operator-() const;

Vector3 operator*(const float s) const; // Scale a vector

Vector3 operator+(const Vector3 &v) const;
Vector3 operator-(const Vector3 &v) const;

float * operator *();

Vector3 cross(const Vector3 &v);
void LinearInterp(Vector3 &v1, Vector3 &v2, float t);

void scale(const float &x);
void scale(const Vector3 &x);
void normalize();
void abs();
float dotprod(const Vector3 &v) const;
float dist(const Vector3 &x) const;
float length() const;

protected:

float vec[3];
};

#endif


// Vector3.cpp

#include "Vector3.h"

#include <cassert>
#include <cmath>
#include <cstdio>

Vector3::Vector3()
{
vec[0]=vec[1]=vec[2]=0;
}

Vector3::Vector3(const Vector3 &v)
{
vec[0]=v.vec[0];
vec[1]=v.vec[1];
vec[2]=v.vec[2];
}

Vector3::Vector3(const float x, const float y,const float z)
{
vec[0]=x;
vec[1]=y;
vec[2]=z;
}

Vector3::Vector3(const float *v)
{
vec[0]=v[0];
vec[1]=v[1];
vec[2]=v[2];
}

Vector3::Vector3(const double *v)
{
vec[0]=(float)v[0];
vec[1]=(float)v[1];
vec[2]=(float)v[2];
}

float &Vector3::x()
{
return vec[0];
}

const float &Vector3::x() const
{
return vec[0];
}

float &Vector3::y()
{
return vec[1];
}

const float &Vector3::y() const
{
return vec[1];
}

float &Vector3::z()
{
return vec[2];
}

const float &Vector3::z() const
{
return vec[2];
}

float &Vector3::operator[](const int i)
{
assert(i>=0 && i<3);
return vec[i];
}

const float &Vector3::operator[](const int i) const
{
assert(i>=0 && i<3);
return vec[i];
}

bool Vector3::operator==(const Vector3 &v) const
{
if(vec[0]==v[0] && vec[1]==v[1] && vec[2]==v[2]) return true;
return false;
}

bool Vector3::operator!=(const Vector3 &v) const
{
if(vec[0]==v[0] && vec[1]==v[1] && vec[2]==v[2]) return false;
return true;
}

Vector3 &Vector3::operator= (const Vector3 &v)
{
vec[0]=v[0];
vec[1]=v[1];
vec[2]=v[2];
return (*this);
}

Vector3 &Vector3::operator= (const float *f)
{
vec[0]=f[0];
vec[1]=f[1];
vec[2]=f[2];
return (*this);
}

Vector3 &Vector3::operator= (const double *d)
{
vec[0]=(float)d[0];
vec[1]=(float)d[1];
vec[2]=(float)d[2];
return (*this);
}

Vector3 &Vector3::operator+=(const Vector3 &v)
{
vec[0]+=v[0];
vec[1]+=v[1];
vec[2]+=v[2];
return (*this);
}

Vector3 &Vector3::operator-=(const Vector3 &v)
{
vec[0]-=v[0];
vec[1]-=v[1];
vec[2]-=v[2];
return (*this);
}

float Vector3::operator*(const Vector3 &v) const
{
return vec[0]*v[0] + vec[1]*v[1] * vec[2]*v[2];
}

Vector3 &Vector3::operator*=(const float &f)
{
vec[0]*=f;
vec[1]*=f;
vec[2]*=f;
return(*this);
}

Vector3 Vector3::operator-() const
{
return Vector3(-vec[0], -vec[1], -vec[2]);
}

float * Vector3::operator *()
{
return vec;
}

Vector3 Vector3::operator*(const float s) const
{
Vector3 tmp;

tmp[0]=vec[0]*s;
tmp[1]=vec[1]*s;
tmp[2]=vec[2]*s;

return tmp;
}

Vector3 Vector3::operator+(const Vector3 &v) const
{
Vector3 tmp;

tmp[0]=vec[0]+v[0];
tmp[1]=vec[1]+v[1];
tmp[2]=vec[2]+v[2];

return tmp;
}

Vector3 Vector3::operator-(const Vector3 &v) const
{
Vector3 tmp;

tmp[0]=vec[0]-v[0];
tmp[1]=vec[1]-v[1];
tmp[2]=vec[2]-v[2];

return tmp;
}


Vector3 Vector3::cross(const Vector3 &v)
{
// Perform cross product

Vector3 tmp;

tmp[0]=vec[1]*v[2]-vec[2]*v[1];
tmp[1]=vec[2]*v[0]-vec[0]*v[2];
tmp[2]=vec[0]*v[1]-vec[1]*v[0];

return tmp;
}

void Vector3::LinearInterp(Vector3 &v1, Vector3 &v2, float t)
{
vec[0] = v1[0]*(1-t) + v2[0]*t;
vec[1] = v1[1]*(1-t) + v2[1]*t;
vec[2] = v1[2]*(1-t) + v2[2]*t;
}


void Vector3::scale(const float &f)
{
vec[0]*=f;
vec[1]*=f;
vec[2]*=f;
}

void Vector3::scale(const Vector3 &v)
{
vec[0]*=v[0];
vec[1]*=v[1];
vec[2]*=v[2];
}

void Vector3::normalize()
{
float mag=(float)sqrt((vec[0]*vec[0])+(vec[1]*vec[1])+(vec[2]*vec[2]));
if(mag==0.0f) return;

vec[0]=vec[0]/mag;
vec[1]=vec[1]/mag;
vec[2]=vec[2]/mag;
}

void Vector3::abs()
{
vec[0]=fabs(vec[0]);
vec[1]=fabs(vec[1]);
vec[2]=fabs(vec[2]);
}
float Vector3::dotprod(const Vector3 &v) const
{
return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
}

float Vector3::dist(const Vector3 &v) const
{
float dx, dy, dz;
dx=vec[0]-v[0];
dy=vec[1]-v[1];
dz=vec[2]-v[2];
return (float)sqrt(dx*dx+dy*dy+dz*dz);
}

float Vector3::length() const
{
return (float)sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
}

A few of these functions could probably stand to be inlined, I'm just too lazy to get around to it.

The key to making a useful Vector class in my opinion is to supply a healthy set of constructors and overloaded operators to make vector construction and arithmetic simple. That, and a few basic operations (length, cross product, dot product, normalize, etc...) are pretty much all you really need. There are probably other operations you could add to the class as needed.



Golem
Blender--The Gimp--Python--Lua--SDL
Nethack--Crawl--ADOM--Angband--Dungeondweller


[edited by - VertexNormal on March 19, 2004 11:40:37 AM]

Share this post


Link to post
Share on other sites
Overloaded operators are convient but they are not as fast as using just functions. For exmaple if you had something like...

CVector3 CVector3::operator +(const CVector3 &v)
{
return CVector3(x + v.x, y + v.y, z + v.z);
}

compared to...

void CVector3::Add(const CVector3 &v1, const CVector3 &v2)
{
x = v1.x + v2.x;
y = v1.y + v2.y;
z = v1.z + v2.z;
}

The first function, an overloaded operator, is slow because first you have to run the + function, then the constructor of the object being return, and then the function for the overloaded =. Causing a few extra function overhead calls. Running the second function you only have the add function overhead. Nothing more. This will not matter if you do this a few times per frame but if you do it hundreds or thousands of times per frame, it adds up. This holds true from my experience when doing character animation and interpolating between points of 2 key frames. In my vector classes I have both. That way I can use the faster one during important parts of whatever I am using it with. Sending address of vectors like we did is also faster than sending the whole object.

Also your constructors if done like this for example...

CVector3::CVector3() : x(0), y(0), z(0)
{
}


CVector3::CVector3(float X, float Y, float Z) : x(X), y(Y), z(Z)
{
}

(etc...)

Is faster than doing it the way you have. Also for my classes I use a union of a float array (float v[3]) and 3 floats x, y, z. That way I can also use both (for example CVector3 vec; vec.x = 1; vec.v[0] = 1; would be the same thing) I recommend the game programming gems books, they are really helpful with optimizations and things of that nature.

[edited by - playa_151 on March 19, 2004 2:34:13 PM]

Share this post


Link to post
Share on other sites
You know there are tons of open source 3d engines around (even in java) that have this in them... google is very useful for this type of thing... try idx3d

Share this post


Link to post
Share on other sites
quote:
Original post by playa_151
The first function, an overloaded operator, is slow because first you have to run the + function, then the constructor of the object being return, and then the function for the overloaded =. Causing a few extra function overhead calls. Running the second function you only have the add function overhead. Nothing more. This will not matter if you do this a few times per frame but if you do it hundreds or thousands of times per frame, it adds up. This holds true from my experience when doing character animation and interpolating between points of 2 key frames. In my vector classes I have both. That way I can use the faster one during important parts of whatever I am using it with. Sending address of vectors like we did is also faster than sending the whole object.


First of all, I believe that binary operators should be friend functions, I''m not completely sure why though. Second, playa151, you forgot to take into account compiler optimizations. Returning a temporary object like that allows for RVO. And how does your point about it being faster make any sense? In your second case, you''re still going to have to construct an object anyway, plus an overloaded operator is still a function, just like your Vector3::Add() function. Besides, isn''t it more intuitive to call "v = v1 + v2" rather than "v.Add( v1, v2 )", which is the whole point of overloaded operators?

quote:
Original post by playa_151
Also your constructors if done like this for example...

CVector3::CVector3() : x(0), y(0), z(0)
{
}


Yes, it''s true that that''s the "correct" way of doing things, but with PODs that aren''t initialized, it''s the same as assigning them values in the constructor. It''s a good practice, but not necessary for something like a float.

Share this post


Link to post
Share on other sites

#ifndef _template_math_header_
#define _template_math_header_
#include <cmath>
#include <iostream>
/*********************************Matrix***************************************/

template <typename T, unsigned int rows, unsigned int columns> class Matrix
{
public:
T mat[rows*columns];

inline Matrix() { ; };

inline Matrix(const Matrix<Matrix<T, rows, columns>, 1, 1> &M)
{
for(unsigned int i = 0; i < rows*columns; ++i)
mat[i] = M.mat[0].mat[i];
}

inline Matrix(T *pointer) { setValues(pointer); }

inline Matrix(T *pointer, unsigned int fieldWidth, unsigned int x_offset, unsigned int y_offset)
{ setValues(pointer, fieldWidth, x_offset, y_offset); }

inline void setValues(T *pointer)
{
if(!pointer)
for(unsigned int i = 0; i < rows*columns; ++i)
mat[i] = 0;
else
for(unsigned int i = 0; i < rows*columns; ++i)
mat[i] = pointer[i];
}

inline void setValues(T *pointer, unsigned int fieldWidth, unsigned int x_offset, unsigned int y_offset)
{
for(unsigned int i = 0; i < rows; ++i)
for(unsigned int j = 0; j < columns; ++j)
mat[i*columns+j] = pointer[ (y_offset+i)*fieldWidth + x_offset+j ];
}

inline Matrix<T, rows, columns> inverse()
{
if( rows != columns )
return 0;

T t = determinant();
if( t == 0 )
return 0;

Matrix<T,rows,columns> inv;

if( rows == 2 )
{
T _matrix[4] = { mat[3], -mat[2], -mat[1], mat[0] };
inv.setValues(_matrix);
}

else if( rows == 3 )
{
T foo[9];
foo[0] = mat[3+1]*mat[3+3+2] - mat[3+2]*mat[3+3+1];
foo[3] = mat[3+2]*mat[3+3+0] - mat[3+0]*mat[3+3+2];
foo[6] = mat[3+0]*mat[3+3+1] - mat[3+3]*mat[3+1];

foo[1] = mat[3+3+1]*mat[0+2] - mat[3+3+2]*mat[0+1];
foo[4] = mat[3+3+2]*mat[0+0] - mat[3+3+0]*mat[0+2];
foo[7] = mat[3+3+0]*mat[0+1] - mat[3+3+1]*mat[0+0];

foo[2] = mat[0+1]*mat[3+2] - mat[3+1]*mat[0+2];
foo[5] = mat[0+2]*mat[3+0] - mat[3+2]*mat[0+0];
foo[8] = mat[0+0]*mat[3+1] - mat[3+0]*mat[0+1];

inv.setValues(foo);
}

inv *= 1/t;
return inv;
}

inline T determinant( void )
{
if ( rows != columns )
return 0;
if ( rows == 2 )
return mat[0]*mat[3] - mat[1]*mat[2];


T t=0;
for( unsigned int i = 0; i < rows; ++i )
{
T u = mat[i], v = mat[i];

for( unsigned int j = 1; j < rows; ++j )
{
unsigned int index = (i+j >= rows)? ((i+j)-rows) : (i+j);
u *= mat[ j*rows + index ];
}

for( unsigned int j = 1; j < rows; ++j )
{
unsigned int b = (i + j >= rows)? i+j-rows : i+j;
unsigned int a = rows-j;
v*=mat[a*rows+b];
}
t += u-v;
}
return t;
}

inline Matrix<T, columns, rows> transpose()
{
Matrix<T, columns, rows> m2;

for(unsigned int i = 0; i < rows; ++i )
for(unsigned int j = 0; j < columns; ++j)
m2[i*columns + j] = mat[j*columns + i];

return m2;
}

inline void normalize()
{
for( unsigned int i = 0; i < columns; ++i )
{
T t = 0;
for( unsigned int j = 0; j < rows; ++j )
t += mat[j*columns + i]*mat[j*columns + i];
t = 1/sqrt(t);
for( unsigned int j = 0; j < rows; ++j )
mat[j*columns + i] *= t;
}
}

inline void RowNormalize()
{
for(unsigned int i = 0; i < rows; ++i)
{
T t = 0;
for( unsigned int j = 0; j < columns; ++j )
t += mat[i*columns + j]*mat[i*columns + j];
t = 1/sqrt(t);
for( unsigned int j = 0; j < columns; ++j )
mat[ i*columns + j ] *= t;
}
}

inline unsigned int getColumnCount(void) { return columns; }
inline unsigned int getRowCount(void) { return rows; }

inline T& operator [] (unsigned int i) { return mat[i]; }
};

template<typename a_type, unsigned int rows, unsigned int columns>
inline Matrix<a_type, rows, columns> operator + (Matrix<a_type, rows, columns> &a, float b )
{
Matrix<a_type, rows, columns> M;
for(unsigned int i = 0; i < rows*columns; ++i)
M[i] = a[i] + b;
return M;
}

template<typename a_type, unsigned int rows, unsigned int columns>
inline Matrix<a_type, rows, columns> operator + ( float b, Matrix<a_type, rows, columns> &a )
{
Matrix<a_type, rows, columns> M;
for(unsigned int i = 0; i < rows*columns; ++i)
M[i] = a[i] + b;
return M;
}

template<typename type, unsigned int rows, unsigned int columns>
Matrix<type, rows, columns> operator + ( Matrix<type, rows, columns> M1, Matrix<type, rows, columns> M2)
{
Matrix<type, rows, columns> M;
for(unsigned int i = 0; i < rows*columns; ++i)
M[i] = M1[i] + M2[i];
return M;
}

template<typename a_type, unsigned int rows, unsigned int columns>
inline Matrix<a_type, rows, columns> operator - ( float b, Matrix<a_type, rows, columns> &a )
{
Matrix<a_type, rows, columns> M;
for(unsigned int i = 0; i < rows*columns; ++i)
M[i] = a[i] - b;
return M;
}

template<typename type, unsigned int rows, unsigned int columns>
Matrix<type, rows, columns> operator - ( Matrix<type, rows, columns> &M1, Matrix<type, rows, columns> M2)
{
Matrix<type, rows, columns> M;
for(unsigned int i = 0; i < rows*columns; ++i)
M[i] = M1[i] - M2[i];
return M;
}

template<typename m_type, unsigned int rows, unsigned int columns>
inline Matrix<m_type, rows, columns> operator * (Matrix<m_type, rows, columns> m, float s )
{
Matrix<m_type, rows, columns> M;
for(unsigned int i = 0; i < rows*columns; ++i)
M[i] = m[i] * s;
return M;
}

template<typename m_type, unsigned int rows, unsigned int columns>
inline Matrix<m_type, rows, columns> operator * (float s, Matrix<m_type, rows, columns> m)
{
Matrix<m_type, rows, columns> M;
for(unsigned int i = 0; i < rows*columns; ++i)
M[i] = m[i] * s;
return M;
}

template<typename m_type, unsigned int rows, unsigned int columns>
inline Matrix<m_type, rows, columns> operator / (Matrix<m_type, rows, columns> &M, float s)
{
Matrix<m_type, rows, columns> m;
for(unsigned int i = 0; i < rows*columns; ++i)
m[i] /= s;
return m;
}

template<typename m_type, unsigned int rows, unsigned int columns>
inline void operator += (Matrix<m_type, rows, columns> &m, float s)
{
for(unsigned int i = 0; i < rows*columns; ++i)
m[i] += s;
}

template<typename type, unsigned int rows, unsigned int columns>
void operator += ( Matrix<type, rows, columns> &M1, Matrix<type, rows, columns> M2)
{
for(unsigned int i = 0; i < rows*columns; ++i)
M1[i] = M1[i] + M2[i];
}

template<typename m_type, unsigned int rows, unsigned int columns>
inline void operator *= (Matrix<m_type, rows, columns> &m, float s )
{
for(unsigned int i = 0; i < rows*columns; ++i)
m[i] *= s;
}

template<typename m_type, unsigned int rows, unsigned int columns>
inline void operator /= (Matrix<m_type, rows, columns> &m, float s )
{
for(unsigned int i = 0; i < rows*columns; ++i)
m[i] /= s;
}

template <typename type, typename a_type, typename b_type, unsigned int a_rows, unsigned int a_columns_b_rows, unsigned int b_columns>
inline Matrix<type, a_rows, b_columns> matrix_multi(Matrix<a_type,a_rows,a_columns_b_rows> &a, Matrix<b_type,a_columns_b_rows,b_columns> &b)
{
Matrix<type, a_rows, b_columns> result;

for( unsigned int i = 0; i < a_rows; ++i)
{
for( unsigned int j = 0; j < b_columns; ++j)
{
type t = a[i*a_columns_b_rows]*b[j];
for( unsigned int k = 1; k < a_columns_b_rows; ++k)
t += a[i*a_columns_b_rows + k]*b[k*b_columns + j];

result[i*b_columns+j] = t;
}
}

return result;
}

template <typename type, unsigned int a_rows, unsigned int a_columns_b_rows, unsigned int b_columns>
inline Matrix<type, a_rows, b_columns> operator * (Matrix<type, a_rows,a_columns_b_rows> &a, Matrix<type,a_columns_b_rows,b_columns> &b)
{
Matrix<type, a_rows, b_columns> result;

for( unsigned int i = 0; i < a_rows; ++i)
{
for( unsigned int j = 0; j < b_columns; ++j)
{
type t = a[i*a_columns_b_rows]*b[j];
for( unsigned int k = 1; k < a_columns_b_rows; ++k)
t += a[i*a_columns_b_rows + k]*b[k*b_columns + j];

result[i*b_columns+j] = t;
}
}

return result;
}

template<typename type, typename a_type, typename b_type, unsigned int rows, unsigned int columns>
inline Matrix<type, rows, columns> matrix_add( Matrix<a_type, rows, columns> &M1, Matrix<b_type, rows, columns> &M2)
{
Matrix<type, rows, columns> M;
for(unsigned int i = 0; i < rows*columns; ++i)
M[i] = M1[i] + M2[i];
return M;
}

template <typename t, unsigned int rows, unsigned int cols>
inline void operator << ( std::ostream &out, Matrix<t,rows,cols> m )
{
for( unsigned int i = 0; i < cols; ++i )
{
for( unsigned int j = 0; j < rows; ++j )
{
out<<m[i*cols + j]<< " ";
}
out<<"\n";
}
}

template <typename t, unsigned int rows, unsigned int cols>
inline Matrix<t,rows,cols> operator - ( Matrix<t,rows,cols> &M )
{
Matrix<t,rows,cols> m = M;
for( unsigned int i = 0; i < rows; ++i )
m[i] = -M[i];

return m;
}

/******************************Vector******************************************/

template<typename T, unsigned int dimensions> class Vector : public Matrix<T, dimensions, 1>
{
public:

inline Vector() { ; }

inline Vector( const int &i )
{
for(unsigned int iter = 0; iter < dimensions; ++iter)
mat[iter] = i;
}

inline Vector( T x1, T x2=0, T x3=0, T x4=0, T x5=0, T x6=0, T x7=0, T x8=0)
{
mat[0] = x1;
if( dimensions > 1 ) mat[1] = x2;
if( dimensions > 2 ) mat[2] = x3;
if( dimensions > 3 ) mat[3] = x4;
if( dimensions > 4 ) mat[4] = x5;
if( dimensions > 5 ) mat[5] = x6;
if( dimensions > 6 ) mat[6] = x7;
if( dimensions > 7 ) mat[7] = x8;
if( dimensions > 8 )
for(unsigned int i = 8; i < dimensions; ++i)
mat[i] = (T)0;
}

inline Vector(const Matrix<Matrix<T, dimensions, 1>, 1, 1> &M)
{
for(unsigned int i = 0; i < dimensions; ++i)
mat[i] = M.mat[0].mat[i];
}

inline Vector(const Matrix<Vector<T, dimensions>, 1, 1> &M)
{
for(unsigned int i = 0; i < dimensions; ++i)
mat[i] = M.mat[0].mat[i];
}

inline Vector(const Matrix<T, dimensions, 1> &M)
{
for(unsigned int i = 0; i < dimensions; ++i)
mat[i] = M.mat[i];
}

inline Vector( T *pointer) { setValues(pointer); }

T length(void)
{
T foo = mat[0]*mat[0];
for(unsigned int i = 1; i < dimensions; ++i)
foo += mat[i]*mat[i];
return sqrt(foo);
}

Vector<T, dimensions> unit_vector(void)
{
Vector<T, dimensions> v = *this;
v.normalize();
return v;
}
T& operator [] ( unsigned int i ) { return mat[i]; }
};

template<typename T, unsigned int dimensions> T dotProduct(Vector<T, dimensions> v, Vector<T, dimensions> w)
{
T dot = v[0]*w[0];
for(unsigned int i = 1; i < dimensions; ++i)
dot += v[i]*w[i];
return dot;
}

template<typename T> Vector<T, 3> crossProduct ( Vector<T, 3> v1, Vector<T, 3> v2 )
{
Vector<T, 3> v3;
v3[0] = v1[1]*v2[2] - v1[2]*v2[1];
v3[1] = v1[2]*v2[0] - v1[0]*v2[2];
v3[2] = v1[0]*v2[1] - v1[1]*v2[0];
return v3;
}

template<typename T> Vector<T, 2> perp_operator(Vector<T, 2> v)
{
return Vector<T, 2>(-v[1], v[0]);
}

template<typename T> T perp_product(Vector<T, 2> v, Vector<T, 2> w)
{
return v[0]*w[1] - v[1]*w[0];
}

template<typename T, unsigned int dimensions>
Vector<T, dimensions> operator * (Vector<T, dimensions> v, Vector<T, dimensions> w)
{
Vector<T, dimensions> vec;
for(unsigned int i = 0; i < dimensions; ++i)
vec[i] = v[i]*w[i];
return vec;
}

/*******************************Row Vector*************************************/

template <typename T, unsigned int dimensions> class RowVector : public Matrix<T, 1, dimensions>
{
public:
inline RowVector() { ; }

inline RowVector( const int &i )
{
for(unsigned int iter = 0; iter < dimensions; ++iter)
mat[iter] = i;
}

inline RowVector( T x1, T x2=0, T x3=0, T x4=0, T x5=0, T x6=0, T x7=0, T x8=0)
{
mat[0] = x1;
if( dimensions > 0 ) mat[1] = x2;
if( dimensions > 1 ) mat[2] = x3;
if( dimensions > 2 ) mat[3] = x4;
if( dimensions > 3 ) mat[4] = x5;
if( dimensions > 4 ) mat[5] = x6;
if( dimensions > 5 ) mat[6] = x7;
if( dimensions > 6 ) mat[7] = x8;
if( dimensions > 7 )
for(unsigned int i = 8; i < dimensions; ++i)
mat[i] = (T)0;
}

inline RowVector(const Matrix<Matrix<T, 1, dimensions>, 1, 1> &M)
{
for(unsigned int i = 0; i < dimensions; ++i)
mat[i] = M.mat[0].mat[i];
}

inline RowVector(const Matrix<RowVector<T, dimensions>, 1, 1> &M)
{
for(unsigned int i = 0; i < dimensions; ++i)
mat[i] = M.mat[0].mat[i];
}

inline RowVector(const Matrix<T, 1, dimensions> &M)
{
for(unsigned int i = 0; i < dimensions; ++i)
mat[i] = M.mat[i];
}

inline RowVector( T *pointer) { setValues(pointer); }
};

/***********************************plane**************************************/

template<typename T, unsigned int dimensions> class Plane
{
private:
Vector<T, dimensions> n, p;
T d;
public:
inline Plane( Vector<T, dimensions> normal, Vector<T, dimensions> point)
{
n = normal.unit_vector();
p = point;
d = dotProduct(n, p);
}
inline Plane( Vector<T, dimensions> normal, T d)
{
n = normal;
this->d = d;
p = normal * d;
}

inline T distance( Vector<T, dimensions> x )
{
return dotProduct( x, n ) - d;
}
inline Vector<T, dimensions> line_intersection( Vector<T, dimensions> p0, Vector<T, dimensions> dir )
{
T foo = dotProduct( n, dir);
if( foo == 0 )
return 0;
T bar = -dotProduct( n, p0 - p ) / foo;
return p0 + bar*dir;
}
};

#endif


teh mighty template code has returned...

Share this post


Link to post
Share on other sites