libGDN project details!

Started by
169 comments, last by CpMan 20 years ago
CpMan: I was going to talk to you about standarized types ...
but Fruny beat me to it
I''ll write a basic vector, matrix thing (also to show off style)..

yeah - I was going to talk about inheritance on the IO system, but *sigh* fruny beat me to it again..

IO system should be runtime polymorphism anyway.

Also: I also think that people didnt'' understand the caps thing. we really mean..

  class SomeClass {private:int SomeVariable;public:void DoSomething();};void SomeClass::DoSomething() {    int i,j,k;    int var, blah, zaasss;    double some_d;    SomeOtherClass some_class;    // we don''t really care, so long the public interface     // follows the style...}  
Advertisement
Wow....people actually read the thing, at least some of it.....

Gamedev for learning.
libGDN for putting it all together.
VSEDebug Visual Studio.NET Add-In. Enhances debugging in ways never thought possible.
OK, the CVS Repository is up, working on the math base now.

Gamedev for learning.
libGDN for putting it all together.
VSEDebug Visual Studio.NET Add-In. Enhances debugging in ways never thought possible.
You could even parameterize the dimensionality of a vector in a template

cu,
Prefect
Widelands - laid back, free software strategy
ssshhhhhh...

but I have...and I''ve put in loop unrolling and ET as well
should be pretty damn fast..
and it''s fun to code!
well, back to matrix class...a little more difficult


ok. fine. a lot more
Having already written a vector class that does exactly this, I might as well post it here. However, be warned, it is written for *speed*, not understanding. On VC6,7 and GCC2.9.5,3.2+ generally all the operations are done without use of temporaries.

So you can write something like this:

  Vector<float,3> v1(5,4,4);float blah[3] = {0,1,2};Vector<float,3> v2(blah);Vector<float,3> v3;cout << "v1: " << v1 << endl;cout << "v2: " << v2 << endl;v3 = v1 + v2 - (v2/4);cout << "v3: " << v3 << endl;  

and that statement will be optimized extremely well without extraneous temporaries, etc.

Class follows here:

  namespace mathLib{	#define inline __forceinline 	// Vector class	template <class vecType,u32 vecSize>	class Vector	{		vecType m_vals[vecSize];	public:		typedef Vector<vecType,vecSize> myVec;		inline Vector()		{		}				inline Vector(const myVec &vector)		{			*this = vector;		}				inline Vector(const vecType vector[vecSize])		{			*this = vector;		}		inline Vector(const vecType t1,					  const vecType t2 = 0,					  const vecType t3 = 0,					  const vecType t4 = 0)		{			if (vecSize > 0) m_vals[0] = t1;			if (vecSize > 1) m_vals[1] = t2;			if (vecSize > 2) m_vals[2] = t3;			if (vecSize > 3) m_vals[3] = t4;		}				inline const vecType operator[](int pos) const		{			return m_vals[pos];		}				inline vecType &operator[](int pos)		{			return m_vals[pos];		}				template<class T>		struct assignment		{			template<u32 I,class R>			struct recurse			{				enum { COUNTER = I+1 };				static inline void Assign(myVec &V,const T &A)				{					V[I] = A[I];					recurse<COUNTER,int>::Assign(V,A);				}			};			template<> struct recurse<vecSize,int>			{				static inline void Assign(myVec &V,const T &A) { }			};			static inline void Assign(myVec &V,const T &A)			{				recurse<0,int>::Assign(V,A);			}		};		inline myVec &operator=(const myVec &vector)		{			if (this != &vector)			{				assignment<myVec>::Assign(*this,vector);			}			return *this;		}				struct assignmentArray		{			template<u32 I,class R>			struct recurse			{				enum { COUNTER = I+1 };				static inline void Assign(myVec &V,const vecType A[vecSize])				{					V[I] = A[I];					recurse<COUNTER,int>::Assign(V,A);				}			};			template<> struct recurse<vecSize,int>			{				static inline void Assign(myVec &V,const vecType A[vecSize]) { }			};			static inline void Assign(myVec &V,const vecType A[vecSize])			{				recurse<0,int>::Assign(V,A);			}		};		inline myVec &operator=(const vecType vector[vecSize])		{			assignmentArray::Assign(*this,vector);			return *this;		}		struct addition		{			template<u32 I,class R>			struct recurse			{				enum { COUNTER = I+1 };				static inline void Assign(myVec &V,const myVec &A,const myVec &B)				{					V[I] = A[I] + B[I];					recurse<COUNTER,int>::Assign(V,A,B);				}			};			template<> struct recurse<vecSize,int>			{				static inline void Assign(myVec &V,const myVec &A,const myVec &B) { }			};			static inline void Assign(myVec &V,const myVec &A,const myVec &B)			{				recurse<0,int>::Assign(V,A,B);			}		};		inline myVec operator+(const myVec &vector) const		{			myVec tmp;			addition::Assign(tmp,*this,vector);			return tmp;		}		inline myVec &operator+=(const myVec &vector)		{			addition::Assign(*this,*this,vector);			return *this;		}		struct subtraction		{			template<u32 I,class R>			struct recurse			{				enum { COUNTER = I+1 };				static inline void Assign(myVec &V,const myVec &A,const myVec &B)				{					V[I] = A[I] - B[I];					recurse<COUNTER,int>::Assign(V,A,B);				}			};			template<> struct recurse<vecSize,int>			{				static inline void Assign(myVec &V,const myVec &A,const myVec &B) { }			};			static inline void Assign(myVec &V,const myVec &A,const myVec &B)			{				recurse<0,int>::Assign(V,A,B);			}		};		inline myVec operator-(const myVec &vector) const		{			myVec tmp;			subtraction::Assign(tmp,*this,vector);			return tmp;		}		inline myVec &operator-=(const myVec &vector)		{			subtraction::Assign(*this,*this,vector);			return *this;		}		struct multiplication		{			template<u32 I,class R>			struct recurse			{				enum { COUNTER = I+1 };				static inline void Assign(myVec &V,const myVec &A,const vecType value)				{					V[I] = A[I] * value;					recurse<COUNTER,int>::Assign(V,A,value);				}			};			template<> struct recurse<vecSize,int>			{				static inline void Assign(myVec &V,const myVec &A,const vecType value) { }			};			static inline void Assign(myVec &V,const myVec &A,const vecType value)			{				recurse<0,int>::Assign(V,A,value);			}		};		inline myVec operator*(const vecType value) const		{			myVec tmp;			multiplication::Assign(tmp,*this,value);			return tmp;		}		inline myVec &operator*=(const vecType value)		{			multiplication::Assign(*this,*this,value);			return *this;		}		struct division		{			template<u32 I,class R>			struct recurse			{				enum { COUNTER = I+1 };				static inline void Assign(myVec &V,const myVec &A,const vecType value)				{					V[I] = A[I] / value;					recurse<COUNTER,int>::Assign(V,A,value);				}			};			template<> struct recurse<vecSize,int>			{				static inline void Assign(myVec &V,const myVec &A,const vecType value) { }			};			static inline void Assign(myVec &V,const myVec &A,const vecType value)			{				recurse<0,int>::Assign(V,A,value);			}		};		inline myVec operator/(const vecType value) const		{			myVec tmp;			division::Assign(tmp,*this,value);			return tmp;		}		inline myVec &operator/=(const vecType value)		{			division::Assign(*this,*this,value);			return *this;		}		struct dotProduct		{			template<u32 I,class R>			struct recurse			{				enum { COUNTER = I+1 };				static inline vecType Assign(const myVec &A,const myVec &B)				{					return 						A[I] * B[I] +						recurse<COUNTER,int>::Assign(A,B);				}			};			template<> struct recurse<vecSize,int>			{				static inline vecType Assign(const myVec &A,const myVec &B)				{					return 0;				}			};			static inline vecType Assign(const myVec &A,const myVec &B)			{				return recurse<0,int>::Assign(A,B);			}		};		inline vecType Dot(const myVec vector) const		{			return dotProduct::Assign(*this,vector);		}		inline Vector<vecType,3> Cross(const Vector<vecType,3> vector) const		{			myVec tmp;			tmp[0] = m_vals[1] * vector[2] - m_vals[2] * vector[1];			tmp[1] = m_vals[2] * vector[0] - m_vals[0] * vector[2];			tmp[2] = m_vals[0] * vector[1] - m_vals[1] * vector[0];			return tmp;		}		inline vecType Length() const		{			return (vecType)sqrt(dotProduct::Assign(*this,*this));		}		inline myVec Normalize() const		{			myVec tmp;			vecType length = 1 / Length();			multiplication::Assign(tmp,*this,length);			return tmp;		}	};		#undef inline};  
quote:
You could even parameterize the dimensionality of a vector in a template

I specifically didn''t do that, because I wanted direct access to .x, .y, .z and .w members (for readability). There might be some sneaky way to achieve that with templates, but I was lazy and you now how they say, keep it simple stupid...

Believe it or not...that''s what risingdragon has written so far, parameterization of the vector size. Yann L has a point though...it will make messy code if things can''t be accessed easily though .x.y.z.w, What are your opinions rd. I''d say go with 3 templated vector types..2,3, and 4 components...unless....What about keeping the existing class, then defining 3 "custom types" of 2 3 and 4 components based on this class...ie

template struct Vector3 {
public: Vector Vec;

//map Vec[0][1][2] to x,y and z
stdtype x,y,z;
//then on any operation, reset x,y,z.

TGhis would be slow though. It would be better to just overload the -> operator. That seems like a good idea to me. What does everyone think. It''s not a major change and doesn''t limit flexibility.


Gamedev for learning.
libGDN for putting it all together.
VSEDebug Visual Studio.NET Add-In. Enhances debugging in ways never thought possible.
That''s a good point Yann L.
Well, well, well: Premandrake that is good code..
I''m thinking why should I finish off implementing all those operators when you''ve already done it?

I''m thinking of using your code if that''s okay. You''ll get credit of course, for that part of it...I''m just going to put the namespaces in the overall GDN namespace, standarize the caps and naming, is all basically.

I await your approval
In the meantime, I''m going to take up Yann L''s challenge and see if I can get me some .x, .y, and .z''s...
Here we go. I've made a test program showing off how to make .x, .y, and .z's appear in the vector class depending on template paramater:

    #include <stdlib.h>#include <iostream>template <class T, std::size_t Dim> class vec_helper {	public:		vec_helper(T data[Dim]) {}};template <class T> class vec_helper<T,2>{	public:		vec_helper(T data[2]) : x(data[0]), y(data[1]) {}				T& x;		T& y;};template <class T> class vec_helper<T,3>{	public:		vec_helper(T data[3]) : x(data[0]), y(data[1]), z(data[2]) {}				T& x;		T& y;		T& z;};template <class T, std::size_t Dim> class vec : public vec_helper<T,Dim> {	public:		vec() : vec_helper<T,Dim>(data) {}		T& operator[](std::size_t i) {			return data[i];		}	private:		T data[Dim];};using namespace std; int main() {	vec<float,2> test;	test[0] = 1;	test[1] = 1.5;	cout << test[0] << " " << test[1] << endl;	cout << test.x << " " << test.y << endl;	test.x = 2;	test.y = 4;	cout << test[0] << " " << test[1] << endl;	cout << test.x << " " << test.y << endl;	vec<float,3> test2;	test2[0] = 1;	test2[1] = 1.5;	test2[2] = 3;	cout << test2[0] << " " << test2[1] << " " << test2[2] << endl;	cout << test2.x << " " << test2.y <<" " << test2.z << endl;	test2.x = 2;	test2.y = 4;	test2.z = 5;	cout << test2[0] << " " << test2[1] << " " << test2[2] << endl;	cout << test2.x << " " << test2.y << " " << test2.z << endl;//	cout <<  test.z;//	FAILS! .z member doesn't exist in test, which is a vec<float,2>	system("PAUSE");	return 0;}    


This prints out:
1 1.5
1 1.5
2 4
2 4
1 1.5 3
1 1.5 3
2 4 5
2 4 5
Press any key to continue . . .

and of course, if users wish to have a .x, .y, .z, and .w members for a 4 dim vector they merely need to specialize the template vec_help.

BTW: names, caps, etc are not libGDN standard. This is a quick hack.

EDIT: fixed Dim variable in specializations...
-----------------------------
Gamedev for learning.
libGDN for putting it all together.

[edited by - risingdragon3 on November 2, 2002 2:19:59 AM]

This topic is closed to new replies.

Advertisement