This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| Simple Untrained Neural Net Class Submitted by

I've been unable to leave neural nets alone ever since i saw fups tutorial*. I dont really know why, maybe its one of the few chances i get to combine my degree (genetics) with my passion (coding). This cotd came about when i got some pretty animated patterns, using untrained neural nets to render colored heightmaps (using tristrips in OpenGL) and decided to share it. The neural net class will become a library (for my own/other peoples non-com use), so i am interested in comments on the class design, more so perhaps than the implementation. But please bare in mind that this is a work in progress by a hobby coder :) One unusual aspect of the neural nets currently created by this class is the function they use sin as the response function instead of the usual sigmoidal response (fup explains sigmoidal response and its usage in his tut).

    float Neuron::Calc(float *inputs)
    {
    	float out = 0;

    	//add up all (weight * input) pairs
    	for (int x=0;x<num_inputs;x++)
    		out += weights[x] * inputs[x];

    	//sigmoid reponse curve (broken)
    	//return ( 1 / (sig_response + (float)exp( - (out / 10) )) );

    	//sinus response curve
    	return sinf( out / sig_response);
    }

I think it is this sinus reposonse that gives these neural nets the properties that make them graph pretty patterns. I am hoping to test some net controlled AI (simple navigation) to make sure that the sinus response is appropriate for other uses than silly patterns. Feel free to try out the sigmoidal response, but i havent managed to get it to produce usefull results yet (the net doesn't generate enough varied output using sigmoidal output) The code is a VC5(yuk) workspace containing 3 demo projects of how to use the class. It requires glut libraries and headers which are not included. The source code is released under GNU, so dont be afraid. Comments welcome, Matt Barnett
gunther@dial.pipex.com Refs: * Neural Networks in plain english (by fup)
http://www.btinternet.com/~fup/nnt1.html

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/myerror.h] - (1,719 bytes)

    /*=======================================

    	cMyError::Header File

    	By Matt Barnett;

    	Description: Simple error reporting.

    	Usage:

    		cMyError cMyError1;

    		//quiet error printf()
    		cMyError1.Error("vertex number %i is %s",vertex,stringproblem);

    		//message box and printf()
    		//same as FatalError(); except it doesnt look so intimidating
    		cMyError1.AlertError("feature not supported %s",stringfeature);

    		//call this to report a fatal error
    		//just before you exit(-1);
    		cMyError1.FatalError("Couldnt find file %s",stringlostfile);
    		exit(-1);

    =======================================*/

    #ifndef		_MYERROR_CLASS_H
    #define		_MYERROR_CLASS_H

    #include	<windows.h>							//comment for non Win32 platforms

    #include	<cstdio>							//for printf

    //#define VERBOSE_CREATION						//class debug

    class cMyError
    {
    	public:

    		cMyError();											//constructor
    		~cMyError();										//destructon

    		void FatalError(const char *strString, ...);		//MessageBox and printf()
    		void AlertError(const char *strString, ...);		//exactly the same as FatalError (except title)
    		void Error(const char *strString, ...);				//printf()
    		void Alert(const char *strString, ...);
    		void Log(const char *strString, ...);

    		static void isFlowHere(const char *filename, int linenumber)
    		{
    			printf("Program flow reached %s %i\n",filename,linenumber);
    		}

    		//static bool logall;
    };

    //macros are shouted and they use a ; so the usage is ...
    //
    //	CMYERROR_ISFLOWHERE
    //  and not CMYERROR_ISFLOWHERE;
    //
    //which helps make it clear that its a macro we're calling
    //

    #define CMYERROR_ISFLOWHERE cMyError::isFlowHere(__FILE__,__LINE__);

    #endif

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/myerror.cpp] - (5,097 bytes)

    /*=======================================

    	cMyError::Implementation

    	*See header file for more information

    	By Matt Barnett;

    =======================================*/

    #include "myerror.h"
    #include "leakdetect.h"

    /*=======================================
    cMyError::Constructor
    =======================================*/

    cMyError::cMyError()
    {
    #ifdef VERBOSE_CREATION
    	printf("cMyError::Constructor::Empty\n");
    #endif
    }

    /*=======================================
    cMyError::Destructor
    =======================================*/

    cMyError::~cMyError()
    {

    #ifdef VERBOSE_CREATION
    	printf("cMyError::Destructor::Empty\n");
    #endif

    }

    /*=========================================================
    void cMyError::FatalError()
    ==========================================================*/

    void cMyError::FatalError(const char *strString, ...)
    {
    	char		strText[256];				// This will hold our text to display
    	va_list		argumentPtr;				// This will hold the pointer to the argument list
    	float		unitLength=0.0f;			// This will store the length of the 3D Font in unit length

    	if (strString == NULL)					// Check if a string was given
    		return;								// Don't render anything then

    	va_start(argumentPtr, strString);			// Parse the arguments out of the string
    	vsprintf(strText, strString, argumentPtr);	// Now add the arguments into the full string
    	va_end(argumentPtr);						// This resets and frees the pointer to the argument list.

    	MessageBox(NULL,strText,"Fatal Error!!!",MB_OK|MB_ICONSTOP);
    	printf("FATAL ERROR: %s\n",strText);
    }

    /*=========================================================
    void cMyError::AlertError()
    ==========================================================*/

    void cMyError::AlertError(const char *strString, ...)
    {
    	char		strText[256];				// This will hold our text to display
    	va_list		argumentPtr;				// This will hold the pointer to the argument list
    	float		unitLength=0.0f;			// This will store the length of the 3D Font in unit length

    	if (strString == NULL)					// Check if a string was given
    		return;								// Don't render anything then

    	va_start(argumentPtr, strString);			// Parse the arguments out of the string
    	vsprintf(strText, strString, argumentPtr);	// Now add the arguments into the full string
    	va_end(argumentPtr);						// This resets and frees the pointer to the argument list.

    	MessageBox(NULL,strText,"Non fatal error!",MB_OK|MB_ICONEXCLAMATION);
    	printf("ERROR(loud): %s\n",strText);
    }

    /*=========================================================
    void cMyError::Error()
    ==========================================================*/

    void cMyError::Error(const char *strString, ...)
    {
    	char		strText[256];				// This will hold our text to display
    	va_list		argumentPtr;				// This will hold the pointer to the argument list
    	float		unitLength=0.0f;			// This will store the length of the 3D Font in unit length

    	if (strString == NULL)					// Check if a string was given
    		return;								// Don't render anything then

    	va_start(argumentPtr, strString);			// Parse the arguments out of the string
    	vsprintf(strText, strString, argumentPtr);	// Now add the arguments into the full string
    	va_end(argumentPtr);						// This resets and frees the pointer to the argument list.

    	printf("ERROR(quiet): %s\n",strText);
    }

    /*=========================================================
    void cMyError::Alert()
    ==========================================================*/

    void cMyError::Alert(const char *strString, ...)
    {
    	char		strText[256];				// This will hold our text to display
    	va_list		argumentPtr;				// This will hold the pointer to the argument list
    	float		unitLength=0.0f;			// This will store the length of the 3D Font in unit length

    	if (strString == NULL)					// Check if a string was given
    		return;								// Don't render anything then

    	va_start(argumentPtr, strString);			// Parse the arguments out of the string
    	vsprintf(strText, strString, argumentPtr);	// Now add the arguments into the full string
    	va_end(argumentPtr);						// This resets and frees the pointer to the argument list.

    	MessageBox(NULL,strText,"Information",MB_OK);
    	printf("Alert(loud): %s\n",strText);
    }
    /*=========================================================
    void cMyError::Log()
    ==========================================================*/

    void cMyError::Log(const char *strString, ...)
    {
    	char		strText[256];				// This will hold our text to display
    	va_list		argumentPtr;				// This will hold the pointer to the argument list
    	float		unitLength=0.0f;			// This will store the length of the 3D Font in unit length

    	if (strString == NULL)					// Check if a string was given
    		return;								// Don't render anything then

    	va_start(argumentPtr, strString);			// Parse the arguments out of the string
    	vsprintf(strText, strString, argumentPtr);	// Now add the arguments into the full string
    	va_end(argumentPtr);						// This resets and frees the pointer to the argument list.

    	printf("Log: %s\n",strText);
    }

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/leakdetect.h] - (1,200 bytes)

    /*=======================================

    	Memory leak detection header file

    =======================================*/

    //#define LEAKDBG

    #ifdef LEAKDBG
    	#define _CRTDBG_MAP_ALLOC
    		#include <stdlib.h>
    		#include <crtdbg.h>
    #endif

    #ifdef LEAKDBG
      #define meMalloc(s)       _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
      #define meCalloc(c, s)    _calloc_dbg(c, s, _NORMAL_BLOCK, __FILE__, __LINE__)
      #define meRealloc(p, s)   _realloc_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__)
      #define meExpand(p, s)    _expand_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__)
      #define meFree(p)         _free_dbg(p, _NORMAL_BLOCK)
      #define meMemSize(p)      _msize_dbg(p, _NORMAL_BLOCK)

      #define meNew new(_NORMAL_BLOCK, __FILE__, __LINE__)
      #define meDelete delete

      // Set to dump leaks at the program exit.
      #define meInitMemoryCheck() \
        _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF)

    #else
      #define meMalloc malloc
      #define meCalloc calloc
      #define meRealloc realloc
      #define meExpand _expand
      #define meFree free
      #define meMemSize _msize

      #define meNew new
      #define meDelete delete

      #define meInitMemoryCheck()

    #endif

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/demos/matnn/testapp1/glut_test1.cpp] - (6,062 bytes)

    /*---------------------------------------------

    	MatNN library : Test App 1 (cpp)

    		* This is not an terrain poly pushing demo.

    		This shows a silly brainwave of the neural
    		net. The nets are totally untrained (random weights).

    		The neural net (in this example) has 3 input neurons
    		that take the x / y position of a 2d grid and the time/ticks
    		returned by GetTickCount(); It has 3 outputs = RGB color which
    		is also used as a height.

    		We/me/i graph the response of the the net over a small 2d plane
    		of x/y values, at a specific time (using GetTickCount() ) to create
    		a pretty swirly jaggy heightmap thingy (tm)

    		keys : r = random neural net
    			   a = decrease response
    			   d = increase response

    	By Matt Barnett

    		(see References)	* See matnn.h for more information

    ---------------------------------------------*/

    //basic glut and math stuff for camera etc

    #include <ctime>
    #include <cstdio>
    #include <windows.h>
    #include <GL/glut.h>

    #include "../../../imath/imath.h"
    #include "../../../matnn/matnn.h"

    GLfloat grey[] = {0.2,0.2,0.2,1.0};
    GLfloat above_origin[] = {0.0,0.0,3.0,1.0};
    GLfloat white[] = {1.0,1.0,1.0,1.0};
    GLfloat	shiny[] = {50.0};

    #define WINDOW_SIZE			1024		//
    #define	SCALE_MOTION		100			//scale down by

    int x,y,mx,my,xs,ys;

    int oldmx = 0;
    int oldmy = 0;

    enum modetype { MODE_ROTATE,MODE_MOVE,MODE_CAM };
    modetype mode;
    iquaternion4 camquat;

    //globals for testing here

    using MatLayeredNeuralNetLib::NeuralNet;
    float resp = 0.45f;
    float inputs[3];
    float outputs[3];

    //change the number of hidden layers
    //(number of inputs, number of outputs, number of neurons in hidden layers, number of hidden layers)
    NeuralNet n1(3,3,4,3,inputs,outputs);

    //------------------------

    void drawaxes()
    {
      glDisable(GL_LIGHTING);

      glBegin(GL_LINES);
      glColor3f(1.0,0.0,0.0);glVertex3f(-0.5,0.0,0.0);glVertex3f(1.2,0.0,0.0);
      glColor3f(0.0,1.0,0.0);glVertex3f(0.0,-0.5,0.0);glVertex3f(0.0,1.2,0.0);
      glColor3f(0.0,0.0,1.0);glVertex3f(0.0,0.0,-0.5);glVertex3f(0.0,0.0,1.2);
      glEnd();
    }

    void display(void)
    {
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    	glMatrixMode(GL_MODELVIEW);
    	glLoadIdentity();

    	imatrix16 rm(camquat);
    	glTranslatef(0.0,0.0,-0.8);
    	glMultMatrixf(rm.m);

    	//instert drawing here

    	float floorsize = 1.5;

    	//if you want more tri-strips then decrease this value
    	float floorstep = 0.025f;

    	float i,j;

    	float fftime = (float)GetTickCount() / 1500;

    	glPushMatrix();
    	glTranslatef((float)-floorsize/2,(float)-floorsize/2,0.0);

    	for (i=0;i<floorsize;i+=floorstep)
    	{
    		glBegin(GL_TRIANGLE_STRIP);
    		for (j=0;j<floorsize;j+=floorstep)
    		{

    				inputs[0] = j;
    				inputs[1] = i;
    				inputs[2] = fftime;
    				n1.RunNN();

    				glColor3f(outputs[0],outputs[1],outputs[2]);			//rem this out and try one of the below
    				//glVertex3f(i,j,outputs[2] / 9.0 )
    				//glVertex3f(i,j,0.0f);
    				glVertex3f(i,j,(outputs[0]+outputs[1]+outputs[2]) / 35.0f);

    				inputs[0] = j+floorstep;
    				inputs[1] = i+floorstep;
    				inputs[2] = fftime;
    				n1.RunNN();

    				glColor3f(outputs[0],outputs[1],outputs[2]);			//rem this out and try one of the below (chose the same as above)
    				//glVertex3f(i+floorstep,j+floorstep,outputs[2] / 9.0 );
    				//glVertex3f(i+floorstep,j+floorstep,0.0f);
    				glVertex3f(i+floorstep,j+floorstep,(outputs[0]+outputs[1]+outputs[2])  / 35.0f);

    		}
    		glEnd();
    	}

    	drawaxes();
    	glPopMatrix();

    	glPopMatrix();
    	glutSwapBuffers();
    	glutPostRedisplay();
    }

    void reshape(int w, int h)
    {
      glViewport(0,0,(GLsizei) w,(GLsizei) h);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective(90,(float)w/h,0.01,100.0);
    }

    void motion(int x, int y)
    {
    	mx = x;my = y;

    	xs = mx - oldmx;
    	ys = oldmy - my;

    	oldmx = mx;
    	oldmy = my;

    	iquaternion4 multquat;

    	if (mode == MODE_ROTATE)
    	{

    	}
    	else if (mode == MODE_MOVE)
    	{

    	}
    	else if (mode == MODE_CAM)
    	{
    		multquat.makeEulerRotation( ivector3( (float)ys/SCALE_MOTION,-(float)xs/SCALE_MOTION,0.0 ) );
    		camquat.multiply(multquat);
    	}
    }

    void mouse(int button,int state,int x,int y)
    {
    	oldmx = x;
    	oldmy = y;

    	if (button == GLUT_LEFT_BUTTON)
    		mode = MODE_ROTATE;

    	if (button == GLUT_RIGHT_BUTTON)
    		mode = MODE_MOVE;

    	if (button == GLUT_MIDDLE_BUTTON)
    		mode = MODE_CAM;
    }

    void init(void)
    {

    	srand( (unsigned)time( NULL ) );

    	glEnable(GL_DEPTH_TEST);
    	//glEnable(GL_LIGHTING);
    	//glEnable(GL_LIGHT0);
    	//glLightfv(GL_LIGHT0,GL_POSITION,above_origin);

    	//glEnable(GL_BLEND);
    	//glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

    	//glMaterialfv(GL_FRONT,GL_DIFFUSE,grey);
    	//glMaterialfv(GL_FRONT,GL_SPECULAR,white);
    	//glMaterialfv(GL_FRONT,GL_SHININESS,shiny);

    	//glEnable(GL_POLYGON_OFFSET_FILL);
    	//glPolygonOffset(0.1,0.1);
    	//glDepthFunc(GL_LEQUAL);
    	//glEnable(GL_DEPTH_TEST);
    	//glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    	//glEnable(GL_BLEND);
    	//glEnable(GL_POLYGON_SMOOTH);
    	//glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
    	glPointSize(2.0f);

    	inputs[0] = 0;
    	inputs[1] = 0;

    	n1.SetResponse(resp);
    }

    void key(GLubyte key, int x, int y)
    {
      switch (key)
        {
    			case 'a':resp -= 0.05f;printf("response %f\n",resp);n1.SetResponse(resp);
    			break;

    			case 'd':resp += 0.05f;printf("response %f\n",resp);n1.SetResponse(resp);

    			break;

    			case 'r':im_random_seed_time();n1.Randomize();

    			break;

    			case '1':

    			break;

    			case '!':

    			break;

    			case 'l':

    			break;

    			case 'q':exit(0);
    			break;
        }

    }

    int main(int argc, char **argv)
    {

    	meInitMemoryCheck();

    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    	glutInitWindowSize(WINDOW_SIZE,WINDOW_SIZE);
    	glutInitWindowPosition(100,10);
    	glutCreateWindow("Matts test");

    	glutDisplayFunc(display);
    	glutReshapeFunc(reshape);
    	glutKeyboardFunc(key);
    	glutMotionFunc(motion);
    	glutMouseFunc(mouse);

    	init();
    	glutMainLoop();

    	return 0;
    }

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/demos/matnn/testapp1/glut_test2.cpp] - (5,270 bytes)

    /*---------------------------------------------

    	MatNN library : Test App 2 (cpp)

    		This one uses a neural net to control the position and color
    		of some opengl points (large pointsize).

    		I guess this could be used to control a bunch of blended particles
    		in an interesting way.

    		keys : r = random neural net
    			   a = decrease response
    			   d = increase response

    	By Matt Barnett

    		(see References)	* See matnn.h for more information

    ---------------------------------------------*/

    //basic glut and math stuff for camera etc

    #include <ctime>
    #include <cstdio>
    #include <windows.h>
    #include <GL/glut.h>

    #include "../../../imath/imath.h"
    #include "../../../matnn/matnn.h"

    GLfloat grey[] = {0.2,0.2,0.2,1.0};
    GLfloat above_origin[] = {0.0,0.0,3.0,1.0};
    GLfloat white[] = {1.0,1.0,1.0,1.0};
    GLfloat	shiny[] = {50.0};

    #define WINDOW_SIZE			1024		//
    #define	SCALE_MOTION		100			//scale down by

    int x,y,mx,my,xs,ys;
    int oldmx = 0;
    int oldmy = 0;

    enum modetype { MODE_ROTATE,MODE_MOVE,MODE_CAM };
    modetype mode;
    iquaternion4 camquat;

    //globals for testing here

    using MatLayeredNeuralNetLib::NeuralNet;
    float resp = 1.0f;
    float inputs[6];
    float outputs[6];
    NeuralNet n1(6,6,6,2,inputs,outputs);

    //------------------------

    void drawaxes()
    {
      glDisable(GL_LIGHTING);

      glBegin(GL_LINES);
      glColor3f(1.0,0.0,0.0);glVertex3f(-0.5,0.0,0.0);glVertex3f(1.2,0.0,0.0);
      glColor3f(0.0,1.0,0.0);glVertex3f(0.0,-0.5,0.0);glVertex3f(0.0,1.2,0.0);
      glColor3f(0.0,0.0,1.0);glVertex3f(0.0,0.0,-0.5);glVertex3f(0.0,0.0,1.2);
      glEnd();
    }

    void display(void)
    {
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    	glMatrixMode(GL_MODELVIEW);
    	glLoadIdentity();

    	imatrix16 rm(camquat);
    	glTranslatef(0.0,0.0,-1.7);
    	glMultMatrixf(rm.m);

    	//instert drawing here

    	float floorsize = 1.5;
    	float floorstep = 0.25f;
    	float i,j,k,l,m;

    	float fftime = (float)GetTickCount() / 1000;
    	//float bp1 = 0.0;
    	//float bp2 = 1.0;
    	//float bp3 = 0.0;

    	glPushMatrix();
    	glTranslatef((float)-floorsize/2,(float)-floorsize/2,0.0);
    	glBegin(GL_POINTS);
    	for (i=0;i<floorsize;i+=floorstep)
    	{
    		for (j=0;j<floorsize;j+=floorstep)
    		{
    			for (k=0;k<floorsize;k+=floorstep)
    			{
    				for (l=0;l<floorsize;l+=floorstep)
    				{
    				//	for (m=0;m<floorsize;m+=floorstep)
    				//	{
    						inputs[0] = j;
    						inputs[1] = i;
    						inputs[2] = k;
    						inputs[3] = l;
    						inputs[4] = 0.0;
    						inputs[5] = fftime;
    						n1.RunNN();

    						glColor3f(outputs[0],outputs[1],outputs[2]);
    						glVertex3f(outputs[3],outputs[4],outputs[5]);
    				//	}
    				}
    			}
    		}

    	}
    	glEnd();

    	drawaxes();
    	glPopMatrix();

    	glPopMatrix();
    	glutSwapBuffers();
    	glutPostRedisplay();
    }

    void reshape(int w, int h)
    {
      glViewport(0,0,(GLsizei) w,(GLsizei) h);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective(90,(float)w/h,0.01,100.0);
    }

    void motion(int x, int y)
    {
    	mx = x;my = y;

    	xs = mx - oldmx;
    	ys = oldmy - my;

    	oldmx = mx;
    	oldmy = my;

    	iquaternion4 multquat;

    	if (mode == MODE_ROTATE)
    	{

    	}
    	else if (mode == MODE_MOVE)
    	{

    	}
    	else if (mode == MODE_CAM)
    	{
    		multquat.makeEulerRotation( ivector3( (float)ys/SCALE_MOTION,-(float)xs/SCALE_MOTION,0.0 ) );
    		camquat.multiply(multquat);
    	}
    }

    void mouse(int button,int state,int x,int y)
    {
    	oldmx = x;
    	oldmy = y;

    	if (button == GLUT_LEFT_BUTTON)
    		mode = MODE_ROTATE;

    	if (button == GLUT_RIGHT_BUTTON)
    		mode = MODE_MOVE;

    	if (button == GLUT_MIDDLE_BUTTON)
    		mode = MODE_CAM;
    }

    void init(void)
    {

    	srand( (unsigned)time( NULL ) );

    	glEnable(GL_DEPTH_TEST);
    	//glEnable(GL_LIGHTING);
    	//glEnable(GL_LIGHT0);
    	//glLightfv(GL_LIGHT0,GL_POSITION,above_origin);

    	//glEnable(GL_BLEND);
    	//glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

    	//glMaterialfv(GL_FRONT,GL_DIFFUSE,grey);
    	//glMaterialfv(GL_FRONT,GL_SPECULAR,white);
    	//glMaterialfv(GL_FRONT,GL_SHININESS,shiny);

    	//glEnable(GL_POLYGON_OFFSET_FILL);
    	//glPolygonOffset(0.1,0.1);
    	//glDepthFunc(GL_LEQUAL);
    	//glEnable(GL_DEPTH_TEST);
    	//glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    	//glEnable(GL_BLEND);
    	//glEnable(GL_POLYGON_SMOOTH);
    	//glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
    	glPointSize(15.0f);
    	printf("%f",log(100) );

    	inputs[0] = 0;
    	inputs[1] = 0;

    	n1.SetResponse(resp);
    }

    void key(GLubyte key, int x, int y)
    {
      switch (key)
        {
    			case 'a':resp -= 0.05f;printf("response %f\n",resp);n1.SetResponse(resp);
    			break;

    			case 'd':resp += 0.05f;printf("response %f\n",resp);n1.SetResponse(resp);

    			break;

    			case 'r':im_random_seed_time();n1.Randomize();

    			break;

    			case '1':

    			break;

    			case '!':

    			break;

    			case 'l':

    			break;

    			case 'q':exit(0);
    			break;
        }

    }

    int main(int argc, char **argv)
    {
    	meInitMemoryCheck();

    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    	glutInitWindowSize(WINDOW_SIZE,WINDOW_SIZE);
    	glutInitWindowPosition(100,10);
    	glutCreateWindow("Matts test");

    	glutDisplayFunc(display);
    	glutReshapeFunc(reshape);
    	glutKeyboardFunc(key);
    	glutMotionFunc(motion);
    	glutMouseFunc(mouse);

    	init();
    	glutMainLoop();

    	return 0;
    }

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/demos/matnn/testapp1/glut_test4.cpp] - (5,992 bytes)

    /*---------------------------------------------

    	MatNN library : Test App 4 (cpp)

    		This shows the copy constructor working.
    		(4 different instances of a net are drawn,
    		that were created by copy constructors)

    		It will show the assignment operator
    		working aswell, when/if i decide its right
    		to assign neural nets.

    		keys : r = random neural nets
    			   a = decrease response
    			   d = increase response

    	By Matt Barnett

    		(see References)	* See matnn.h for more information

    ---------------------------------------------*/

    //basic glut and math stuff for camera etc

    #include <ctime>
    #include <cstdio>
    #include <windows.h>
    #include <GL/glut.h>

    #include "../../../imath/imath.h"
    #include "../../../matnn/matnn.h"

    GLfloat grey[] = {0.2,0.2,0.2,1.0};
    GLfloat above_origin[] = {0.0,0.0,3.0,1.0};
    GLfloat white[] = {1.0,1.0,1.0,1.0};
    GLfloat	shiny[] = {50.0};

    #define WINDOW_SIZE			1024		//
    #define	SCALE_MOTION		100			//scale down by

    int x,y,mx,my,xs,ys;
    int oldmx = 0;
    int oldmy = 0;

    enum modetype { MODE_ROTATE,MODE_MOVE,MODE_CAM };
    modetype mode;
    iquaternion4 camquat;

    //globals for testing here

    using MatLayeredNeuralNetLib::NeuralNet;
    float resp = 1.0f;
    float inputs[6];
    float outputs[3];

    NeuralNet *n0 = meNew NeuralNet(6,3,4,5,inputs,outputs);	//on the heap, so that we can delete it showing that n1 is copyied properly (no crosslinks)
    NeuralNet n1 = *n0;											//calls the copy ctor , (allowed)

    //------------------------

    void drawaxes()
    {
      glDisable(GL_LIGHTING);

      glBegin(GL_LINES);
      glColor3f(1.0,0.0,0.0);glVertex3f(-0.5,0.0,0.0);glVertex3f(1.2,0.0,0.0);
      glColor3f(0.0,1.0,0.0);glVertex3f(0.0,-0.5,0.0);glVertex3f(0.0,1.2,0.0);
      glColor3f(0.0,0.0,1.0);glVertex3f(0.0,0.0,-0.5);glVertex3f(0.0,0.0,1.2);
      glEnd();
    }

    void DrawBrainWave(NeuralNet &in,float floorsize,float floorstep,int x,int y)
    {

    	float i,j;

    	float fftime = (float)GetTickCount() / 1500;
    	float bp1 = 0.0;
    	float bp2 = 1.0;
    	float bp3 = 0.0;

    	glPushMatrix();
    	glTranslatef((float)x,(float)y,0.0);

    	for (i=0;i<floorsize;i+=floorstep)
    	{
    		glBegin(GL_TRIANGLE_STRIP);
    		for (j=0;j<floorsize;j+=floorstep)
    		{

    				inputs[0] = j;
    				inputs[1] = i;
    				inputs[2] = fftime;
    				inputs[3] = bp1;
    				inputs[4] = bp2;
    				inputs[5] = bp3;
    				in.RunNN();

    				glColor3f(outputs[0],outputs[1],outputs[2]);
    				glVertex3f(i,j,outputs[2]);

    				inputs[0] = j+floorstep;
    				inputs[1] = i+floorstep;
    				inputs[2] = fftime;

    				inputs[3] = bp1;
    				inputs[4] = bp2;
    				inputs[5] = bp3;
    				in.RunNN();

    				glColor3f(outputs[0],outputs[1],outputs[2]);
    				glVertex3f(i+floorstep,j+floorstep,outputs[2]);
    		}
    		glEnd();
    	}

    	drawaxes();
    	glPopMatrix();
    }

    void display(void)
    {
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    	glMatrixMode(GL_MODELVIEW);
    	glLoadIdentity();

    	imatrix16 rm(camquat);
    	glTranslatef(0.0,0.0,-3.0);
    	glMultMatrixf(rm.m);

    	glTranslatef((float)-1,(float)-1,0.0);

    	//instert drawing here
    	DrawBrainWave(n1,1.5f,0.08f,0,0);
    	DrawBrainWave(n2,1.5f,0.08f,2,2);
    	DrawBrainWave(n3,1.5f,0.08f,0,2);
    	DrawBrainWave(n4,1.5f,0.08f,2,0);

    	glutSwapBuffers();
    	glutPostRedisplay();
    }

    void reshape(int w, int h)
    {
      glViewport(0,0,(GLsizei) w,(GLsizei) h);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective(90,(float)w/h,0.01,100.0);
    }

    void motion(int x, int y)
    {
    	mx = x;my = y;

    	xs = mx - oldmx;
    	ys = oldmy - my;

    	oldmx = mx;
    	oldmy = my;

    	iquaternion4 multquat;

    	if (mode == MODE_ROTATE)
    	{

    	}
    	else if (mode == MODE_MOVE)
    	{

    	}
    	else if (mode == MODE_CAM)
    	{
    		multquat.makeEulerRotation( ivector3( (float)ys/SCALE_MOTION,-(float)xs/SCALE_MOTION,0.0 ) );
    		camquat.multiply(multquat);
    	}
    }

    void mouse(int button,int state,int x,int y)
    {
    	oldmx = x;
    	oldmy = y;

    	if (button == GLUT_LEFT_BUTTON)
    		mode = MODE_ROTATE;

    	if (button == GLUT_RIGHT_BUTTON)
    		mode = MODE_MOVE;

    	if (button == GLUT_MIDDLE_BUTTON)
    		mode = MODE_CAM;
    }

    void init(void)
    {

    	srand( (unsigned)time( NULL ) );

    	glEnable(GL_DEPTH_TEST);
    	//glEnable(GL_LIGHTING);
    	//glEnable(GL_LIGHT0);
    	//glLightfv(GL_LIGHT0,GL_POSITION,above_origin);

    	//glEnable(GL_BLEND);
    	//glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

    	//glMaterialfv(GL_FRONT,GL_DIFFUSE,grey);
    	//glMaterialfv(GL_FRONT,GL_SPECULAR,white);
    	//glMaterialfv(GL_FRONT,GL_SHININESS,shiny);

    	//glEnable(GL_POLYGON_OFFSET_FILL);
    	//glPolygonOffset(0.1,0.1);
    	//glDepthFunc(GL_LEQUAL);
    	//glEnable(GL_DEPTH_TEST);
    	//glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    	//glEnable(GL_BLEND);
    	//glEnable(GL_POLYGON_SMOOTH);
    	//glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);

    	//here we delete n2

    	meDelete n0;

    	glPointSize(4.0f);

    	//wont compile (not allowed)
    	//n1 = n2;

    	inputs[0] = 0;
    	inputs[1] = 0;

    	//n1.SetResponse(resp);
    }

    void key(GLubyte key, int x, int y)
    {
      switch (key)
        {
    			case 'a':resp -= 0.05f;printf("response %f\n",resp);n1.SetResponse(resp);n2.SetResponse(resp);n3.SetResponse(resp);n4.SetResponse(resp);
    			break;

    			case 'd':resp += 0.05f;printf("response %f\n",resp);n1.SetResponse(resp);n2.SetResponse(resp);n3.SetResponse(resp);n4.SetResponse(resp);

    			break;

    			case 'r':im_random_seed_time();n1.Randomize();n2.Randomize();n3.Randomize();n4.Randomize();

    			break;

    			case '1':

    			break;

    			case '!':

    			break;

    			case 'l':

    			break;

    			case 'q':exit(0);
    			break;
        }

    }

    int main(int argc, char **argv)
    {
    	meInitMemoryCheck();

    	glutInit(&argc, argv);
    	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    	glutInitWindowSize(WINDOW_SIZE,WINDOW_SIZE);
    	glutInitWindowPosition(100,10);
    	glutCreateWindow("Matts test");

    	glutDisplayFunc(display);
    	glutReshapeFunc(reshape);
    	glutKeyboardFunc(key);
    	glutMotionFunc(motion);
    	glutMouseFunc(mouse);

    	init();
    	glutMainLoop();

    	return 0;
    }

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/matnn/matnn_neuron.h] - (2,158 bytes)

    /*---------------------------------------------

    	MatNN library

    	By Matt Barnett
    		(see References)

    	-----------
    	description
    	-----------

    		This file just keeps some ugly private NeuralNet
    		classes out of the main header

    	------------
    	classes
    	------------

    		Neuron
    		NeuronLayer

    	------------
    	class design
    	------------

    	-----------
    	References:
    	-----------

    		* See matnn.h.

    ---------------------------------------------*/

    //-------- headers etc -------
    //----------------------------

    #ifndef MATNN_NEURON_H_HEADER_132424623254
    #define MATNN_NEURON_H_HEADER_132424623254

    //----------------------------
    //----------------------------

    namespace MatLayeredNeuralNetLib
    {
    	//private class for neurons (clients cant mess with neurons)
    	class Neuron
    	{
    		friend class NeuronLayer;

    		private:

    			Neuron(Neuron ©);				//copy
    			Neuron &operator=(Neuron &rhs);		//assign

    			Neuron(int in_inputs,float &in_sig_response);
    			~Neuron();

    			inline float Calc(float *inputs);
    			void RandomizeWeights();
    			inline void Mutate(float chance,float extent);

    			float *weights;						//array of weights, owned by this neuron
    			int num_inputs;
    			float &sig_response;
    	};

    	//private class for neuron layers (clients cant mess with layers)
    	class NeuronLayer
    	{
    		friend class NeuralNet;
    		friend class TrainableNeuralNet;

    		private:

    			NeuronLayer(NeuronLayer ©);				//copy
    			NeuronLayer &operator=(NeuronLayer &rhs);	//assign

    			NeuronLayer(int in_neurons,int in_num_inputs,float *finputs);
    			~NeuronLayer();

    			inline void RunLayer();
    			void Randomize();
    			inline int Mutate(float chance,float extent);

    			inline float GetOutput(int neuron_index)			 { return output[neuron_index]; }
    			inline void  SetResponse(float in_sig_response)		 { sig_response = in_sig_response; }

    			int num_neurons;
    			float *input;					//float array pointer (points to parent layers outputs);
    			float *output;					//float array pointer (owned by this layer)
    			Neuron **neurons;				//array of pointers to neurons
    			float sig_response;
    	};
    }

    #endif

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/matnn/matnn.h] - (5,490 bytes)

    /*---------------------------------------------

    	MatNN library

    	By Matt Barnett
    		(see References)

    	-----------
    	usage
    	-----------

    		I find that this is the section that i most often
    		look for in other peoples docs, and neglect in my own.

    		Look at the examples for usage comments, or examin
    		the public interface.

    	-----------
    	description
    	-----------

    		This is not really a library yet, but its designed so it
    		can be extended (hence the namespace) , and is as general as possible.

    		The Neural Net Specification
    		(this is the same as the this library's
    		pre-cursor, my other nn classes)

    		* Neurons are made in layers

    			input  layer  (any number of neurons)
    			hidden layers (each has the same number of neurons)
    			output layer  (any number of neurons)

    		* Each layer (starting with the input layer) uses its neurons
    		  to calculate the outputs for all the neurons in this layer.
    		  This is stored in an array which the subsequent layer "knows".

    		* The inital layer has no neuon inputs, this is where the input
    		  from the "environment" enters the net. The input layer
    		  has a pointer to inputs that are specified by the client

    	-----------
    	portability
    	-----------

    		* Depends on imath.h (see imath.h) (needs OpenGL, this is bad for a class a general as this)
    		* Error messages need windows, hack the error class to support non windows
    		* Neural nets are written to text files for easy editing and portability

    	------------
    	class goals
    	------------

    		NeuralNet : Serves as a base class for more specific neural nets (basic neural net function)
    					Will not contain any code for training/adjustment of the net.

    	------------
    	class design
    	------------

    		The design is such that, the net class constructs itself
    		appropriatly for the given parameters and is then ready to
    		run.  This helps keep the rest of the interface small.

    		Neural nets are written to a formatted text file for storage.
    		This makes it easy to understand / edit and should make it
    		more portable. (ie no struct size depenence)

    		* No consideration given to const/non const neural nets/neurons/layers	( YET ! )
    		* There is no default constructor.

    		* Class design leaves some bounds checking to the client !!!!!!!

    		  (s/he simply has to stay within the bounds of his own arrays and be able
    		   to remeber/work out the size of the array, (only once) )

    	-----------
    	References:
    	-----------

    		* See imath.h, myerror.h

    ---------------------------------------------*/

    //-------- headers etc -------
    //----------------------------

    #ifndef MATNN_MAIN_H_HEADER_012023254
    #define MATNN_MAIN_H_HEADER_012023254

    #include "../leakdetect.h"

    #include <iostream>

    //using std::cout;
    //using std::endl;

    #include <math.h>						//fpu maths
    #include <cassert>						//assert
    //#include <windows.h>					//opengl needs windows (comment for non WIN32 platforms)
    //#include <gl/gl.h>

    #include "matnn_neuron.h"
    #include "../imath/imath.h"
    #include "../myerror.h"

    //----------------------------
    //----------------------------

    //these limits are quite arbitrary
    //just to prevent the user making an insane
    //net just to test the memory handling (which isnt that hot)

    #define MATNN_MAX_HIDDEN_LAYERS		256				//256 seems a reasonable limit for these
    #define MATNN_MAX_IN_NEURONS		256				//
    #define MATNN_MAX_OUT_NEURONS		256				//
    #define MATNN_MAX_HIDDEN_NEURONS	256				//

    namespace MatLayeredNeuralNetLib
    {
    	class NeuralNet
    	{
    		//neural net public interface

    		public:

    			//the client is responsible for storage of input & output arrays
    			//but they only need to be set once, and then the you change the input
    			//just be fiddling the array.

    			NeuralNet(NeuralNet ©);				//copy
    			NeuralNet &operator=(NeuralNet &rhs);	//assign

    			NeuralNet(int in_neurons,int out_neurons,int hidden_neurons,int hidden_layers,float *in_finput,float *in_foutput);
    			~NeuralNet();

    			void RunNN();												//runs the neural net
    			void SetResponse(float in_sig_response);					//alters the response constant for all neurons and layers in the net
    			void SetInputOutput(float *in_finput,float *in_foutput);	//alters input/output arrays (null checking)
    			void Randomize();											//dangerous to call on a trained net (it totally randomises weights to -1.0 + 1.0)

    		protected:

    			int num_input_neurons;
    			int num_output_neurons;
    			int num_hidden_neurons;
    			int num_hidden_layers;

    			NeuronLayer	*input_layer;				//will point to the first layer
    			NeuronLayer	*output_layer;				//will point to the last layer
    			NeuronLayer	**parray_hidden_layers;		//an array of pointers for the hidden layers

    		private:
    			float *input;
    			float *output;

    			float sig_response;
    	};

    	class TrainableNeuralNet : public NeuralNet
    	{
    		public:

    			TrainableNeuralNet(int in_neurons,int out_neurons,int hidden_neurons,int hidden_layers,float *in_finput,float *in_foutput) : NeuralNet(in_neurons,out_neurons,hidden_neurons,hidden_layers,in_finput,in_foutput) {}
    			~TrainableNeuralNet() {}

    			int Mutate(float mutation_chance,float mutation_extent);		//returns the number of mutations that occured
    			//ref or copy?
    			//TrainableNeuralNet Clone()
    			//TrainableNeuralNet Cross(TrainableNeuralNet &mate)
    			//void Merge()
    	};

    }

    #endif

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/matnn/matnn.cpp] - (10,226 bytes)

    /*---------------------------------------------

    	MatNN library : Implementation (cpp)

    		* See Header file for more information

    	By Matt Barnett
    		(see References)

    ---------------------------------------------*/

    #include "matnn.h"

    //----------------------------
    //----------------------------
    using MatLayeredNeuralNetLib::Neuron;
    using MatLayeredNeuralNetLib::NeuronLayer;
    using MatLayeredNeuralNetLib::NeuralNet;
    using MatLayeredNeuralNetLib::TrainableNeuralNet;

    //the constructors look a bit nasty because a reference to
    //the response variable/constant is passed down by the NeuralNet
    //owner class (this allows one copy per NeuralNet , and when it changes
    //there is no need to update each neuron/layer copy)

    //
    //	MatNN::Neuron
    //

    //do not copy neurons
    //Neuron::Neuron(Neuron ©)
    //{
    //}
    //Neuron &Neuron::operator=(Neuron &rhs)
    //{
    //
    //	return *this;
    //}

    Neuron::Neuron(int in_inputs,float &in_sig_response) : sig_response(in_sig_response)
    {
    	num_inputs = in_inputs;

    	//inputs = 0;
    	//inputs = meNew Neuron * [num_inputs];

    	weights = 0;
    	weights = meNew float [num_inputs];

    	RandomizeWeights();
    }

    void Neuron::RandomizeWeights()
    {
    	//randomize each weight 0.0f - 1.0f
    	for (int i=0;i<num_inputs;i++)
    	{
    		weights[i] = RANDOM_CLAMP;
    	}
    }

    void Neuron::Mutate(float chance,float extent)
    {
    	//mutate one of my weights by +/- extent
    	//int i = RANDOM_NUM * num_inputs;
    	//weights[i] += RANDOM_CLAMP * extent;

    	//mutate any/some/all neuron weights
    	for (int i=0;i<num_inputs;i++)
    		if (RANDOM_NUM < chance) weights[i] += RANDOM_CLAMP * extent;
    }

    float Neuron::Calc(float *inputs)
    {
    	float out = 0;
    	for (int x=0;x<num_inputs;x++)
    	{
    		out += weights[x] * inputs[x];

    	}

    	//sigmoid reponse curve
    	//return ( 1 / (sig_response + (float)exp( - (out / 10) )) );

    	//sinus response curve
    	return im_sin( out / sig_response);
    }

    Neuron::~Neuron()
    {
    	//cleanup
    	meDelete [] weights;weights = 0;
    }

    //
    //	MatNN::NeuronLayer
    //

    NeuronLayer::NeuronLayer(NeuronLayer ©)
    {
    	num_neurons = copy.num_neurons;

    	//cannot be assigned yet!!
    	//this must be fixed by the caller
    	input = 0;

    	output = 0;
    	output = meNew float [num_neurons];
    	neurons = 0;
    	neurons = meNew Neuron * [num_neurons];

    	//same number of neurons as previous layer
    	for (int i=0;i<num_neurons;i++)
    	{
    		//create neurons
    		neurons[i] = 0;
    		neurons[i] = meNew Neuron(copy.neurons[0]->num_inputs,sig_response);		//one float input for each neuron in the environmental/input layer

    		//copy over the weights from copy
    		memcpy( neurons[i]->weights,copy.neurons[i]->weights,sizeof(float) * copy.neurons[0]->num_inputs );
    	}
    }

    //No =
    //NeuronLayer &NeuronLayer::operator=(NeuronLayer &rhs)
    //{
    //
    //	return *this;
    //}

    NeuronLayer::NeuronLayer(int in_neurons,int in_num_inputs,float *finputs)
    {
    	num_neurons = in_neurons;

    	input = 0;
    	input = finputs;

    	output = 0;
    	output = meNew float [num_neurons];
    	neurons = 0;
    	neurons = meNew Neuron * [num_neurons];

    	for (int i=0;i<num_neurons;i++)
    	{
    		neurons[i] = 0;
    		neurons[i] = meNew Neuron(in_num_inputs,sig_response);		//one float input for each neuron in the environmental/input layer
    	}

    	if (!input)
    	{
    		printf("NeuronLayer::NeuronLayer() no input array specified!\n");
    		exit(0);
    	}
    }

    NeuronLayer::~NeuronLayer()
    {
    	meDelete [] output;
    	output = 0;

    	for (int i=0;i<num_neurons;i++)
    	{
    		meDelete neurons[i];
    		neurons[i] = 0;
    	}

    	meDelete [] neurons;
    	neurons = 0;
    }

    void NeuronLayer::RunLayer()
    {
    	for (int x = 0;x<num_neurons;x++)
    	{
    		output[x] = neurons[x]->Calc(input);
    	}
    }

    void NeuronLayer::Randomize()
    {
    	for (int x = 0;x<num_neurons;x++)
    		neurons[x]->RandomizeWeights();
    }

    int NeuronLayer::Mutate(float chance,float extent)
    {
    	int mutated = 0;

    	//if chance, then mutate
    	for (int x = 0;x<num_neurons;x++)
    	{
    		if (RANDOM_NUM < chance)
    		{
    			neurons[x]->Mutate(chance,extent);
    			mutated++;
    		}
    	}

    	return mutated;
    }

    //
    //	MatNN::NeuralNet
    //

    NeuralNet::NeuralNet(int in_neurons,int out_neurons,int hidden_neurons,int hidden_layers,float *in_finput,float *in_foutput)
    {
    	Sleep(30);
    	im_random_seed_time();

    	//sanity checks first
    	if (num_hidden_layers < 0 || num_hidden_layers > MATNN_MAX_HIDDEN_LAYERS)
    	{
    		cMyError e;e.FatalError("hidden_layers must be  0 => < = %i!",MATNN_MAX_HIDDEN_LAYERS);
    		exit(EXIT_FAILURE);
    	}

    	if (in_neurons < 0 || in_neurons > MATNN_MAX_IN_NEURONS)
    	{
    		cMyError e;e.FatalError("in_neurons must be  0 => < = %i!",MATNN_MAX_IN_NEURONS);
    		exit(EXIT_FAILURE);
    	}

    	if (out_neurons < 0 || out_neurons > MATNN_MAX_OUT_NEURONS)
    	{
    		cMyError e;e.FatalError("out_neurons must be  0 => < = %i!",MATNN_MAX_OUT_NEURONS);
    		exit(EXIT_FAILURE);
    	}

    	if (hidden_neurons < 0 || hidden_neurons > MATNN_MAX_HIDDEN_NEURONS)
    	{
    		cMyError e;e.FatalError("hidden_neurons must be  0 => < = %i!",MATNN_MAX_HIDDEN_NEURONS);
    		exit(EXIT_FAILURE);
    	}

    	//get input & output pointers
    	input = in_finput;
    	output = in_foutput;

    	//grap those parameters
    	num_input_neurons = in_neurons;
    	num_output_neurons = out_neurons;
    	num_hidden_neurons = hidden_neurons;
    	num_hidden_layers = hidden_layers;

    	//null em
    	input_layer = 0;
    	output_layer = 0;
    	parray_hidden_layers = 0;

    	//create input layer
    	input_layer = meNew NeuronLayer(num_input_neurons,num_input_neurons,input);

    	//an array of pointers to hidden layers
    	if (num_hidden_layers)
    	{
    		parray_hidden_layers = meNew NeuronLayer * [num_hidden_layers];
    		if (!parray_hidden_layers)
    		{
    			cMyError e;e.FatalError("Could not allocate %i hidden layers!",num_hidden_layers);

    			meDelete input_layer;

    			exit(EXIT_FAILURE);
    		}
    	}

    	//null each one and create it
    	for (int i=0;i<num_hidden_layers;i++)
    	{
    		parray_hidden_layers[i] = 0;

    		if (i == 0)
    			parray_hidden_layers[i] = meNew NeuronLayer(num_hidden_neurons, input_layer->num_neurons,input_layer->output);
    		else
    			parray_hidden_layers[i] = meNew NeuronLayer(num_hidden_neurons, parray_hidden_layers[i - 1]->num_neurons , parray_hidden_layers[i - 1]->output);
    	}

    	//output layer attached to last hidden layer
    	//or to input layer (special case)
    	if (num_hidden_layers == 0)
    		output_layer = meNew NeuronLayer(num_output_neurons , input_layer->num_neurons , input_layer->output);
    	else
    		output_layer = meNew NeuronLayer(num_output_neurons , parray_hidden_layers[num_hidden_layers - 1]->num_neurons , parray_hidden_layers[num_hidden_layers - 1]->output);

    	//anything reasonable is ok here
    	//as long as the net has been constructed
    	SetResponse(1.0f);

    }

    //No =
    //NeuralNet &NeuralNet::operator=(NeuralNet &rhs)
    //{
    //	return *this;
    //}

    NeuralNet::NeuralNet(NeuralNet ©)
    {
    	//starting with the simple stuff

    	sig_response = copy.sig_response;
    	num_input_neurons = copy.num_input_neurons;
    	num_output_neurons = copy.num_input_neurons;
    	num_hidden_neurons = copy.num_hidden_neurons;
    	num_hidden_layers = copy.num_hidden_layers;

    	//null layers
    	input_layer = 0;
    	output_layer = 0;
    	parray_hidden_layers = 0;

    	//get input & output pointers
    	//its assumed that users want copied
    	//nets to share input & output pointer
    	//(this is the most obvious behaviour i think)

    	input = copy.input;
    	output = copy.output;

    	//after copying layers
    	//we must fix the input pointer to the new net

    	//create input layer as copy
    	input_layer = meNew NeuronLayer(*copy.input_layer);
    	input_layer->input = input;

    	//an array of pointers to hidden layers
    	parray_hidden_layers = meNew NeuronLayer * [num_hidden_layers];
    	//null each one and create it as copy
    	for (int i=0;i<num_hidden_layers;i++)
    	{
    		parray_hidden_layers[i] = 0;
    		parray_hidden_layers[i] = meNew NeuronLayer(*copy.parray_hidden_layers[i]);

    		if (i == 0)
    			parray_hidden_layers[i]->input = input_layer->output;
    		else
    		{
    			parray_hidden_layers[i]->input = parray_hidden_layers[i - 1]->output;
    		}
    	}
    	//output layer attached to last hidden layer(?? or input layer ??) as copy
    	output_layer = meNew NeuronLayer(*copy.output_layer);

    	if (num_hidden_layers == 0)
    		output_layer->input = input_layer->output;
    	else
    		output_layer->input = parray_hidden_layers[num_hidden_layers - 1]->output;

    	SetResponse(copy.sig_response);

    	//that should do it
    }

    NeuralNet::~NeuralNet()
    {
    	//cleanup
    	meDelete input_layer;input_layer = 0;
    	meDelete output_layer;output_layer = 0;

    	//cleanup an array of pointers to allocated layers

    	for (int i=0;i<num_hidden_layers;i++)
    	{
    		meDelete parray_hidden_layers[i];
    		parray_hidden_layers[i] = 0;
    	}

    	meDelete [] parray_hidden_layers;
    	parray_hidden_layers = 0;
    }

    void NeuralNet::RunNN()
    {
    	//run each layer
    	input_layer->RunLayer();
    	for (int i=0;i<num_hidden_layers;i++)
    		parray_hidden_layers[i]->RunLayer();

    	output_layer->RunLayer();

    	//copy output from last layer
    	for (i=0;i<num_output_neurons;i++)
    		output[i] = output_layer->GetOutput(i);
    }

    void NeuralNet::SetResponse(float in_sig_response)
    {
    	sig_response = in_sig_response;
    	input_layer->SetResponse(in_sig_response);
    	for (int i=0;i<num_hidden_layers;i++)
    		parray_hidden_layers[i]->SetResponse(in_sig_response);
    	output_layer->SetResponse(in_sig_response);
    }

    void NeuralNet::SetInputOutput(float *in_finput,float *in_foutput)
    {
    	if (!in_finput || !in_foutput)
    	{
    		cMyError e;e.AlertError("SetInputOutput(), dont pass null pointers!!");return;
    	}
    	input = in_finput;output = in_foutput;
    }

    void NeuralNet::Randomize()
    {
    	input_layer->Randomize();
    	for (int i=0;i<num_hidden_layers;i++)
    	{
    		parray_hidden_layers[i]->Randomize();
    	}
    	output_layer->Randomize();
    }

    //
    //	MatNN::TrainableNeuralNet
    //

    int TrainableNeuralNet::Mutate(float chance,float extent)
    {
    	int mutated = 0;

    	mutated += input_layer->Mutate(chance,extent);
    	for (int i=0;i<num_hidden_layers;i++)
    	{
    		mutated += parray_hidden_layers[i]->Mutate(chance,extent);
    	}
    	mutated += output_layer->Mutate(chance,extent);

    	return mutated;
    }

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/imath/imath_mq.h] - (13,443 bytes)

    /*-----------------------------------------------------------------------

    	Inline Math library : Matrix and Quaternion implementation

    	* See imath.h for more information

    	By Matt Barnett
    		(see References in imath.h)

    ------------------------------------------------------------------------*/

    #ifndef _IMATH_MQ_IMP_HEADER_4778097634
    #define _IMATH_MQ_IMP_HEADER_4778097634

    //----------------------------
    //----------------------------

    class iquaternion4
    {
    	public:

    		//quaternion data (w,x,y,z)
    		union
    		{
    			float q[4];
    			struct { float w, x, y, z; };
    		};

    		//-------------- operators ---
    		//----------------------------
    		inline float operator[](int subscript)
    		{
    			assert( subscript < 4 && subscript >= 0 );
    			return q[subscript];
    		}

    		//assignment
    		inline const iquaternion4 &operator=(const iquaternion4 &right)
    		{
    			if (&right != this) {				//check for self assign
    				w = right.w;
    				x = right.x;					//copy right to left
    				y = right.y;
    				z = right.z;
    			}
    			return *this;						//enables x = y = z
    		}

    		//----------------------------
    		//----------------------------

    		//------- construction etc ---
    		//----------------------------

    		//default ctor
    		inline iquaternion4()
    		{
    			makeMultiplicationIdentity();
    		}

    		//ctor
    		inline iquaternion4(float setw,float setx,float sety,float setz)
    		{
    			set(setw,setx,sety,setz);
    		}

    		//ctor
    		inline iquaternion4(float angle,ivector3 &axis)
    		{
    			makeAngleAxisRotation(angle,axis);
    		}

    		//ctor
    		explicit inline iquaternion4(ivector3 &euler)
    		{
    			makeEulerRotation(euler);
    		}

    		//dtor(unnessesary)
    		inline ~iquaternion4()
    		{
    		}

    		//----------------------------
    		//----------------------------

    		//--------- void functions ---
    		//----------------------------
    		inline void set(float setw,float setx,float sety,float setz)
    		{
    			w = setw;
    			x =	setx;
    			y = sety;
    			z = setz;
    		}

    		//dumps the quaternion componets
    		inline const void cdump(const char *caption)
    		{
    			cout << caption << w << " " << x << " " << y << " " << z << endl;
    		}

    		//theroy (identity quaternion)
    		//
    		//There are two identity quaternions.
    		//In this context, we only use the one that multiplies with another quaternion
    		//to give the same quaternion ( the multiplication identity )

    		inline void makeMultiplicationIdentity()
    		{
    			q[0] = 1.0;		//w
    			q[1] = 0.0;		//x
    			q[2] = 0.0;		//y
    			q[3] = 0.0;		//z
    		}

    		//from Ref 5. (* See imath.h)
    		//(http://gamedev.net/reference/articles/article1691.asp#Q53)
    		//Qr = Q1.Q2 = ( w1.w2 - v1.v2, w1.v2 + w2.v1 + v1 x v2 )
    		//
    		//where v1 = (x,y,z) of Q1
    		//	w1 = (w)     of Q1
    		//	v2 = (x,y,z) of Q2
    		//	w2 = (w)     of Q2
    		//
    	    //and both . and x are the standard vector dot and cross products.
    		//its easy(ish) to follow that the multiply function
    		//doesnt chane the quaternion if multiply is the  identity
    		inline void multiply(const iquaternion4 &multiply)
    		{
    			iquaternion4 temp;
    			temp.x = ((w * multiply.x) + (x * multiply.w) + (y * multiply.z) - (z * multiply.y));

    			//for multiply == identity quaternion
    			//x = 1 * x + 0 * w + 0 * y + 0 * z;
    			//x = x

    			temp.y = ((w * multiply.y) - (x * multiply.z) + (y * multiply.w) + (z * multiply.x));
    			temp.z = ((w * multiply.z) + (x * multiply.y) - (y * multiply.x) + (z * multiply.w));
    			temp.w = ((w * multiply.w) - (x * multiply.x) - (y * multiply.y) - (z * multiply.z));
    			*this = temp;
    		}

    		inline void makeAngleAxisRotation(float angle,ivector3 &axis)
    		{
    			const float hangle(angle * 0.5f);
    			const float sina(im_sin(hangle) );
    			x = (axis.x * sina);
    			y = (axis.y * sina);
    			z = (axis.z * sina);
    			w = cos(hangle);
    		}

    		//from Ref 5. (* See imath.h)
    		//(more or less unchanged from what that articles has)
    		//(http://gamedev.net/reference/articles/article1691.asp#Q60)
    			//" The following more or less comes from:
    			//  http://vered.rose.utoronto.ca/people/david_dir/GEMS/GEMS.html "

    		inline void makeEulerRotation(ivector3 &angles)
    		{
    			//Pitch->X axis, Yaw->Y axis, Roll->Z axis

    			const float sinPitch(im_sin(angles.y*0.5f));
    			const float cosPitch(im_cos(angles.y*0.5f));

    			const float sinYaw(im_sin(angles.z*0.5f));
    			const float cosYaw(im_cos(angles.z*0.5f));

    			const float sinRoll(im_sin(angles.x*0.5f));
    			const float cosRoll(im_cos(angles.x*0.5f));
    			const float cosPitch_cosYaw(cosPitch*cosYaw);
    			const float sinPitch_sinYaw(sinPitch*sinYaw);

    			x = sinRoll * cosPitch_cosYaw   - cosRoll * sinPitch_sinYaw;
    			y = cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw;
    			z = cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw;
    			w = cosRoll * cosPitch_cosYaw   + sinRoll * sinPitch_sinYaw;
    		}

    		//this is the alternative
    		//multiplying euler angles in the correct order
    		//i _think_ that the above is simply a re-arrangment
    		//but i think the ordering here is wrong or somthing
    		//(whatever, the above works the way i want and this doesnt)

    		//
    		//inline void makeEulerRotation(ivector3 &angles)
    		//{
    		//	iquaternion4 qx( im_cos(angles.x/2),im_sin(angles.x/2),0,0 );
    		//	iquaternion4 qy( im_cos(angles.y/2),0,im_sin(angles.y/2),0 );
    		//	iquaternion4 qz( im_cos(angles.z/2),0,0,im_sin(angles.z/2) );
    		//	qx.multiply ( qy );
    		//	qx.multiply ( qz );
    		//	*this = qx;
    		//}
    		//

    		//----------------------------
    		//----------------------------

    		//-------------- functions ---
    		//----------------------------

    		//well this seems to draw the expected vector
    		//but its easier to extract the basis from the
    		//matrix, since the quat is converted to one in the
    		//end
    		const ivector3 &direction()
    		{
    			ivector3 out;
    			out.x = 2.0f * ( x * z - w * y );
    			out.y = 2.0f * ( y * z + w * x );
    			out.z = 1.0f - 2.0f * ( x * x - y * y );

    			out.normalise();
    			return out;
    		}

    		inline float dot(const iquaternion4 &right)
    		{
    			return ( (x * right.x) + (y * right.y) +
    					 (z * right.z) + (w * right.w) );
    		}
    		inline float lengthsqr()
    		{
    			return dot(*this);
    		}
    		inline float length()
    		{
    			return sqrt( lengthsqr() );
    		}

    		//just like a vector ( UNTESTED )
    		inline void normalise()
    		{
    			const float leng(length() );
    			x /= leng;
    			y /= leng;
    			z /= leng;
    			w /= leng;
    		}

    		//?? inline iquaternion4 &lerp(iquaternion4 &other,float t);
    		//?? inline iquaternion4 &slerp(iquaternion4 &other,float t);
    		//?? inline void invert(iquaternion4 &multiply);

    		//----------------------------
    		//----------------------------
    };

    //-------------- imatrix16 -----------------------------------------------------------
    //
    //  ---------------------------------
    //  Row and clomn major format issues
    //  ---------------------------------
    //
    //	Currently, this is an OpenGL freindly matrix
    //  class.  Direct3D stores matricies in a different
    //  order to OpenGL, and this would need to be accounted
    //  for if Direct3D was used.  Also, an engine might need
    //  to use both formats if it supports both APIs.  This is
    //  why i have differed implementing this feature untill i
    //  know how to get it right.
    //
    //

    //matrix in colomn major format (consistant with opengl)
    //
    //		eg { m[0] m[4] m[8]  m[12]
    //		 	 m[1] m[5] m[9]  m[13]
    //			 m[2] m[6] m[10] m[14]
    //			 m[3] m[7] m[11] m[15] }
    //

    //note: it would be cool to have a union for the matrix data allowing sensible names
    //      for different parts of the matrix.  For instance, the first 3x3 block represents
    //      the rotation in the form of the orthonormal basis axes. The matrix also stores scaling etc.
    //
    //	    somthing like...
    //
    //
    //		union
    //		{
    //			float m[16];
    //			struct { float col0[4],col1[4],col2[4],col3[4]; };
    //
    //		};
    //
    //---------------------------------------------------------------------------------

    class imatrix16
    {
    	public:

    		//------- construction etc ---
    		//----------------------------
    		float m[16];																						//matrix data
    		inline imatrix16()										 { makeIdentity(); }						//ctor
    		inline imatrix16(iplane4 &cast_floor,ivector3 lightpos)  { makeProjection(cast_floor,lightpos); }	//ctor
    		explicit inline imatrix16(iquaternion4 &createfrom)		 { makefromQuaternion(createfrom); }		//ctor

    		inline ~imatrix16()	{}																			//dtor(unnessesary)
    		//----------------------------
    		//----------------------------

    		//--------- void functions ---
    		//----------------------------

    		//dumps the matrix componets
    		inline const void cdump(const char *caption)
    		{
    			cout << caption << " row major\n";

    			cout << caption << " row 1 " << m[0] << " " << m[1] << " " << m[2] << " " << m[3] << endl;
    			cout << caption << " row 2 " << m[4] << " " << m[5] << " " << m[6] << " " << m[7] << endl;
    			cout << caption << " row 3 " << m[8] << " " << m[9] << " " << m[10] << " " << m[11] << endl;
    			cout << caption << " row 4 " << m[2] << " " << m[13] << " " << m[14] << " " << m[15] << endl;

    			cout << caption << " col major\n";

    			cout << caption << " col 1 " << m[0] << " " << m[4] << " " << m[8] << " " << m[12] << endl;
    			cout << caption << " col 2 " << m[1] << " " << m[5] << " " << m[9] << " " << m[13] << endl;
    			cout << caption << " col 3 " << m[2] << " " << m[6] << " " << m[10] << " " << m[14] << endl;
    			cout << caption << " col 4 " << m[3] << " " << m[7] << " " << m[11] << " " << m[15] << endl << endl;
    		}

    		//inline void invert
    		//inline void transpose
    		inline void makeIdentity()
    		{
    			m[0] = 1.0;
    			m[1] = 0.0;
    			m[2] = 0.0;
    			m[3] = 0.0;

    			m[4] = 0.0;
    			m[5] = 1.0;
    			m[6] = 0.0;
    			m[7] = 0.0;

    			m[8] = 0.0;
    			m[9] = 0.0;
    			m[10] = 1.0;
    			m[11] = 0.0;

    			//last right hand colomn
    			m[12] = 0.0;
    			m[13] = 0.0;
    			m[14] = 0.0;
    			m[15] = 1.0;
    		}

    		//this makes a projection matrix
    		//which can be fed into a graphics API
    		//
    		//is by no means perfect as a shadow/projection
    		//matrix (still a work in progress)

    		//from http://www.sgi.com/software/opengl/advanced96/node46.html
    		inline void makeProjection(iplane4 &cast_floor,ivector3 &light_pos)
    		{
    			float light_posw = 0.0;							//0.0?

    			float dot = cast_floor.norm.x * light_pos.x +
    					    cast_floor.norm.y * light_pos.y +
    						cast_floor.norm.z * light_pos.z +
    						cast_floor.d * light_posw;

    			m[0] = dot - light_pos.x * cast_floor.norm.x;
    			m[1] = 0.0 - light_pos.y * cast_floor.norm.x;
    			m[2] = 0.0 - light_pos.z * cast_floor.norm.x;
    			m[3] = 0.0 - light_posw  * cast_floor.norm.x;

    			m[4] = 0.0 - light_pos.x * cast_floor.norm.y;
    			m[5] = dot - light_pos.y * cast_floor.norm.y;
    			m[6] = 0.0 - light_pos.z * cast_floor.norm.y;
    			m[7] = 0.0 - light_posw  * cast_floor.norm.y;

    			m[8 ] = 0.0 - light_pos.x * cast_floor.norm.z;
    			m[9 ] = 0.0 - light_pos.y * cast_floor.norm.z;
    			m[10] = dot - light_pos.z * cast_floor.norm.z;
    			m[11] = 0.0 - light_posw  * cast_floor.norm.z;

    			m[12] = 0.0 - light_pos.x * cast_floor.d;
    			m[13] = 0.0 - light_pos.y * cast_floor.d;
    			m[14] = 0.0 - light_pos.z * cast_floor.d;
    			m[15] = dot - light_posw  * cast_floor.d;
    		}

    		//from gametutorials.net (see ref 6)
    		inline void makefromQuaternion(iquaternion4 &q)
    		{

    			// First row
    			m[ 0] = 1.0f - 2.0f * ( q.y * q.y + q.z * q.z );
    			m[ 1] = 2.0f * ( q.x * q.y - q.w * q.z );
    			m[ 2] = 2.0f * ( q.x * q.z + q.w * q.y );
    			m[ 3] = 0.0f;

    			// Second row
    			m[ 4] = 2.0f * ( q.x * q.y + q.w * q.z );
    			m[ 5] = 1.0f - 2.0f * ( q.x * q.x + q.z * q.z );
    			m[ 6] = 2.0f * ( q.y * q.z - q.w * q.x );
    			m[ 7] = 0.0f;

    			// Third row
    			m[ 8] = 2.0f * ( q.x * q.z - q.w * q.y );
    			m[ 9] = 2.0f * ( q.y * q.z + q.w * q.x );
    			m[10] = 1.0f - 2.0f * ( q.x * q.x + q.y * q.y );
    			m[11] = 0.0f;

    			// Fourth row
    			m[12] = 0;
    			m[13] = 0;
    			m[14] = 0;
    			m[15] = 1.0f;
    		}

    		//this functions could be avoided by
    		//providing better access to the matrix's
    		//internal values
    		//based on theroy (Q5 of matrix FAQ) (see ref 5)
    		inline ibasis9 &getBasis()
    		{
    			//prepare the basis based on the matrix
    			ivector3 xa( m[0],m[1],m[2] );
    			ivector3 ya( m[4],m[5],m[6] );
    			ivector3 za( m[8],m[9],m[10] );
    			//make it and return it
    			ibasis9 out(xa,ya,za);

    			return out;
    		}

    		//
    		void multiply_vectors(ivector3 *vector_array,int num_vectors)
    		{
    			assert(vector_array);
    			assert(num_vectors == 1);

    			ivector3 out;
    			out.x = m[0] * vector_array->x + m[4] * vector_array->y + m[8] * vector_array->z;
    			out.y = m[1] * vector_array->x + m[5] * vector_array->y + m[9] * vector_array->z;
    			out.z = m[2] * vector_array->x + m[6] * vector_array->y + m[10] * vector_array->z;
    			*vector_array = out;
    		}

    		//??? inline void makePerspectiveProjection() {}
    		//??? inline void makeOrthographicProjection() {}
    		//??? inline void makeEulerRotation(float angle, ivector3 &axis) {}
    		//??? inline void makeAngleAxisRotation(float angle, ivector3 &axis) {}

    		//----------------------------
    		//----------------------------
    };

    #endif

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/imath/imath_lut.h] - (8,920 bytes)

    /*-----------------------------------------------------------------------

    	Inline Math library : Lookup table implementation

    	* See imath.h for more information

    	By Matt Barnett
    		(see References in imath.h)

    ------------------------------------------------------------------------*/

    #ifndef _IMATH_LUT_IMP_HEADER_223457642
    #define _IMATH_LUT_IMP_HEADER_223457642

    //------- float_lookuptable ------------------------------------
    //
    //	Before i begin.. Yes, i know that the c++
    //  standard library has a lookup table template class.
    //
    //
    //  This is a simple generic lookup table(lut) class
    //  for functions that return a single float
    //	and take a single float parameter
    //	(GPG2 see ref 2) has a better lookuptable)
    //
    //	this works well for sinf etc
    //
    //.	With bounds checking its quite a bit slower.
    //	Without it, i think a lookup maybe amount to
    //	only a few cycles (WRONG!, in retrospect, see asm anal),
    //  because looking up consists of
    //	an inline (no fuction call) function
    //	which performs a single divide, and
    //  uses the clever real2int to get an int
    //	to index the array with
    //
    //  ------ design notes -----
    //
    //  i decided to forgo inheritance
    //
    //  (it would be nice to have a base class
    //   lookuptable and inhert specific
    //	 table types)
    //
    //  templates would probably be a good idea
    //
    //  (but an int indexing table would be
    //   quite different than a float "indexing"
    //   one, and could be faster, so the template
    //   would have to account for that)
    //
    //	In the end decided to make this a simple class
    //  with inlined functions specific to functions of
    //	the form
    //
    //  float somefunction(float someparam);
    //
    //	becomes...
    //
    //  float somelut.lookup(someparam);
    //
    //  The other lut class, is specifically
    //  for generating random numbers and is
    //  pretty much hard-coded to that effect.
    //
    //  ---------- performance notes ---------------
    //  --------------------------------------------
    //
    //	*test yourself using test_speed(int);
    //	*test in both Debug and Release modes
    //    (only take Release mode seriously, but
    //		its usefull to see the difference between
    //			debug & release)
    //
    //
    //	Debug mode is still faster than parent functions
    //	which are them selves slower than in Release mode.
    //
    //  faster than parent tri functions
    //  generally slower for sqrtf
    //  faster than on-the fly random number generation
    //		(not yet suited to rng, which really
    //		 deserves its own lut class)
    //
    //  --------------------------------------------

    //  ---------- mem usage notes ---------------
    //  ------------------------------------------
    //
    //100 floats	400bytes			//maybe for some stuff
    //1000 floats = 4k					//vagly accurate
    //10000 floats = 40k etc			//pretty accurate
    //
    //	Need more accuracy?
    //  (fix class before using more samples)
    //
    //	1)
    //
    //	I've made that the upper limit for the number of
    //	samples. Not due to memory usage but processor
    //  cache usage. (im guessing here, from accumlated knowledge)
    //	We want to be sure that the whole table fits in the cache
    //  so that its really fast. (this afik occurs automagically)
    //	If the table is to big, the chances are that the processor
    //  will thrash the table. Much like a gfx card will thrash textures
    //  between system/texture memory if the application tries to use to
    //  much texture memory.

    //  ------------------------------------------

    //if you want a quick report when a lookup table constructs then define FLUT_VERBOSE
    //if you want to remove the construction message, rem FLUT_VERBOSE out

    #define FLUT_VERBOSE

    class float_lookuptable
    {
    	public:

    	//constructor provides everything
    	float_lookuptable(int innumsamples,float instart,float inend,float (*function)(float) )
    	{
    		//store the pointer to the function for testing later

    		parentfunction = function;
    		num_samples = innumsamples;

    		if (innumsamples > 10000)
    		{
    			printf("float_lookuptable::float_lookuptable() num_samples > 10000!! rtfm\n");
    			exit(0);
    		}

    		start = instart;
    		end = inend;
    		samples = 0;
    		samples = meNew float [num_samples];
    		assert(samples);

    		//may as well fabs() to be sure we get a positive
    		//delta (as this is precalc
    		float diff = fabs(end - start);
    		delta = diff / (float)(num_samples);

    		float x = start;

    		#ifdef FLUT_VERBOSE
    			printf("float_lookuptable( start(%f),end(%f),delta(%f),num(%i) )\n",start,end,delta,num_samples);
    		#endif

    		for (int i = 0; i < num_samples; i++)
    		{
    			//assert(index < num_samples);

    			x = start + (diff * (float)i / (num_samples) );
    			samples[i] = (*parentfunction)(x);
    		}
    	}

    	//looks up like the function
    	inline float lookup(float lookup_what) const
    	{
    		lookup_what /= delta;
    		int il = im_real2int(lookup_what);		//fast
    		//int il = (int)lookup_what ;			//doesnt seem any slower

    		//we only need to check the index is safe
    		//to access the array.  These are faster
    		//than comparing floats
    		// (we could use a smaller precision index
    		//  and possibly gain more speed)

    		//was previously this line (which caused the assertion(il < num_samples) to fail (+3v!L />U|\|7i/\/\3 3/>/>0z)
    		//while (il >= num_samples) il -= num_samples;
    		while (il >= num_samples) il -= num_samples;
    		while (il < 0) il += num_samples;

    		assert(il >= 0);
    		assert(il < num_samples);

    		return samples[il];
    	}

    	void test_speed(int test_samples) const
    	{
    		printf("\n\ntesting speed\n\n");

    		//i think as long as we do enough samples
    		//it will be an ok test

    		long before,after,deltatime;

    		float some_number = two_pi/1.23456789;		//get an angle
    		float out;									//temp to store output of function
    		int x = 0;									//counter

    		before = GetTickCount();					//time before

    		for (x=0;x<test_samples;x++)				//do the test
    			out = lookup(some_number);

    		after = GetTickCount();						//time after
    		deltatime = after - before;					//delta

    		printf("lookup(%f) x %i = (%f) in %i msec\n",some_number,samples,out,deltatime);

    		before = GetTickCount();					//time before

    		for (x=0;x<test_samples;x++)				//do the test
    			out = parentfunction(some_number);

    		after = GetTickCount();						//time after
    		deltatime = after - before;					//delta

    		printf("parentfunction(%f) x %i = (%f) in %i msec\n",some_number,samples,out,deltatime);
    	}

    	~float_lookuptable()
    	{
    		meDelete [] samples;
    	}

    	private:
    			float *samples;
    			int num_samples;
    			float start,end;
    			float delta;
    			float (*parentfunction)(float);

    	//no assignment or copy kids
    	operator=(float_lookuptable &);
    	float_lookuptable(float_lookuptable &);
    };

    //-------------------------------------
    //hard coded random number lookup table
    //-------------------------------------

    //note: this is slower in debug mode than
    //      rand();
    //
    //      but in release mode it beats rand()
    //      however, because rand()  is so fast
    //      its probably not worth the memory

    //quick prototype
    void im_random_seed_time();

    class float_random_lookuptable
    {
    	public:
    		float_random_lookuptable(int numsamples)
    		{
    			//seed the generator
    			im_random_seed_time();

    			//class general
    			num_samples = numsamples;
    			current_index = 0;

    			//alloc memory
    			samples = 0;
    			samples = meNew float [num_samples];
    			assert(samples);

    			//fill the array
    			for (int x=0;x<num_samples;x++)
    			{
    				samples[x] = ((float)rand()/(RAND_MAX+1));
    			}

    		}
    		~float_random_lookuptable()
    		{
    			meDelete [] samples;
    		}

    		inline float lookup_random_num()
    		{
    			return samples[current_index];

    			current_index++;

    			//loop around again
    			if (current_index > num_samples) current_index = 0;

    		}

    		//not const becauase it calls lookup_random_num
    		void test_speed(int test_samples)
    		{
    			printf("\n\ntesting speed\n\n");

    			//i think as long as we do enough samples
    			//it will be an ok test

    			long before,after,deltatime;

    			float out;									//temp to store output of function
    			int x = 0;									//counter

    			before = GetTickCount();					//time before

    			for (x=0;x<test_samples;x++)				//do the test
    				out = lookup_random_num();

    			after = GetTickCount();						//time after
    			deltatime = after - before;					//delta

    			printf("lookup_random_num() x %i = %i msec\n",test_samples,deltatime);

    			before = GetTickCount();					//time before

    			for (x=0;x<test_samples;x++)				//do the test
    				out = ((float)rand()/(RAND_MAX+1));

    			after = GetTickCount();						//time after
    			deltatime = after - before;					//delta

    			printf("((float)rand()/(RAND_MAX+1)) x %i = %i msec\n",test_samples,deltatime);
    		}

    	private:
    		int num_samples,current_index;
    		float *samples;
    };

    #endif

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/imath/imath.h] - (5,274 bytes)

    /*---------------------------------------------

    	Inline Math library
    	(imath , im_)

    	By Matt Barnett
    		(see References)

    	-----------
    	portability
    	-----------

    		exclusivly uses the internal float datatype throughout
    		and precision and portability are dependent on that.

    	------------
    	classes
    	------------

    		ivector3
    		ibasis9
    		imatrix16
    		iquaternion4
    		iray6
    		iplane4
    		ibox3

      	----------------
    	other components
    	----------------

    		* float constants collection

    		* lookup table class (for functions such as sin/cos/tan/acos etc)
    		* random number lookup table class

    		* interfaces to generalise common math functions

    			im_random_num()			//uses lookup tables
    			im_random_clamp()
    			im_sin()				//uses lookup tables
    			im_cos()				//uses lookup tables
    			im_acos()
    			im_tan()				//uses lookup tables
    			im_sqrt()

      	-------------------------------
    	external components [optional]
    	-------------------------------

    		ibox3
    		(closly intergrated with imath)

    	------------
    	class design
    	------------

    		imath.h					//include this file
    		imath.cpp				//add this file to project
    		imath.lib?				//or link to this?

    		this file, imath.h sould include the files

    		imath_vmq.h				//vector mathrix and quats all together
    		imath_trace.h			//rays and planes together
    		imath_box.h				//bounding boxes
    		imath_lut.h				//lookup tables

    		* All functions are inlined (the i stands for inline) ( this should be optimal, ie: the compilier chooses )

    		* Operators are generally not implemented using member functions calls.  This is deliberate.  Member function
    		  calls quite specifically operate on an object, and operators act between them.

    		* Integral types are passed/returned by value
    		  math objects are passed/returned by reference where appropriate

    		* All members are public (for core classes). Classes are
    		  designed to mimic integral types(hmm, dont that too seriously).

    	-----------
    	References:		( INCOMPLETE )
    	-----------

    		 1. PI constants from windows calculator :)
    			Allthough you cant store such an accurate PI very easily
    			its worth noting that wincalc will give pi to 21 decimal places.

    		 2. Game Programming Gems 2
    		 3. Elemetry Linear Algebra
    		 4. Real2Int function By Sree (* See imath_real2int.h )
    		 5. www.gametutorials.com	  (specifically the quaternion example, great site)
    		 6. matrix & quaternion FAQ	  (everything about m's and q's)
    		 7. Effective C++ 2e		  (great book)
    		 8. flipcode http://www.flipcode.com/cgi-bin/msg.cgi?showThread=00002476&forum=general&id=-1
    		    (angle between 2 vectors thread) Paul Hope's angle code

    ---------------------------------------------*/

    //-------- headers etc -------
    //----------------------------

    #ifndef _IMATH_MAIN_H_HEADER_069389570
    #define _IMATH_MAIN_H_HEADER_069389570

    #include "../leakdetect.h"

    #include <iostream>

    using std::cout;
    using std::endl;

    #include <math.h>						//fpu maths
    #include <cassert>						//assert
    #include <windows.h>					//opengl needs windows (comment for non WIN32 platforms)
    #include <gl/gl.h>						//opengl for drawing vectors etc (minimal, not important)

    #include "../myerror.h"

    //----------------------------
    //----------------------------

    //----------------------------
    //----------------------------

    //alias/type/macro your favorites
    #define		RANDOM_NUM							im_random_num()
    #define		RANDOM_CLAMP						im_random_clamp()

    //macroed settings
    #define		_IVECTOR3_VERBOSE_NORMALISE_FAIL_

    //----------------------------
    //----------------------------

    //----------------------------
    //----------------------------

    class ivector3;
    class float_lookuptable;

    //----------------------------
    //----------------------------

    //---- constants -------------------
    //
    // see imath.cpp for
    // constant definitions and comments
    //----------------------------------

    extern const float  cnf_epsilon;			//"small" value (considered 0)
    extern const float			 pi;
    extern const float		half_pi;
    extern const float		 two_pi;
    extern const float _pi_over_180;
    extern const float _180_over_pi;

    //extern const ivector3 xaxis;
    //extern const ivector3 yaxis;
    //extern const ivector3 zaxis;
    //extern const ivector3 zero;

    //extern const ivector3 red;
    //extern const ivector3 green;
    //extern const ivector3 blue;
    //extern const ivector3 black;

    //extern const ivector3 cyan;
    //extern const ivector3 magenta;
    //extern const ivector3 yellow;

    extern const float_lookuptable sintable;
    extern const float_lookuptable costable;
    extern const float_lookuptable tantable;

    //----------------------------
    //----------------------------

    //-- imath component headers --
    //-----------------------------

    #include "imath_real2int.h"		//need first by lut
    #include "imath_lut.h"			//lookup tables
    #include "imath_core.h"			//trig, sqrt,  etc

    #include "imath_vector.h"		//vector is needed by trace
    #include "imath_trace.h"		//trace is needed by matrix
    #include "imath_mq.h"			//matrix and quaternion

    #include "imath_box.h"			//bounding boxess

    //----------------------------
    //----------------------------

    #endif

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/imath/imath.cpp] - (2,097 bytes)

    /*---------------------------------------------

    	Inline Math library : Constants implementation (cpp)
    	(imath , im_)

    	* See Header file for more information

    	By Matt Barnett
    		(see References)

    ---------------------------------------------*/

    #include "imath.h"

    //---- float constants --------
    //-----------------------------

    //data ranges (according to msvc help)
    //a 4 byte float can hold 7 digits
    //an 8 byte double can hold 15 digits
    //a long double (10 bytes) can hold 19 digits

    //hence all constants match the precision
    //of the the type that stores them

    const float cnf_epsilon(0.0001f);			//"small" value (considered 0)

    //pi constants
    //precalced often used pi values

    //theroy (radians)
    //
    //  half_pi radians = 90 degrees
    //  pi radians      = 180 degrees
    //  two_pi radians  = 360 degeres

    const float			 pi(3.141592f);			//(* See ref 1)
    const float		half_pi(1.570796f);			//(* See ref 1)
    const float		 two_pi(6.283185f);			//(* See ref 1)
    const float _pi_over_180(0.0174532f);
    const float _180_over_pi(57.295779f);

    //----------------------------
    //----------------------------

    //------ ivector3 constants -----
    //-------------------------------

    extern const ivector3 xaxis(1.0,0.0,0.0);
    extern const ivector3 yaxis(0.0,1.0,0.0);
    extern const ivector3 zaxis(0.0,0.0,1.0);
    extern const ivector3 zero (0.0,0.0,0.0);

    //a few colors
    extern const ivector3 red  (1.0,0.0,0.0);
    extern const ivector3 green(0.0,1.0,0.0);
    extern const ivector3 blue (0.0,0.0,1.0);
    extern const ivector3 black(0.0,0.0,0.0);

    extern const ivector3 cyan   (0.0,1.0,1.0);
    extern const ivector3 magenta(1.0,0.0,1.0);
    extern const ivector3 yellow (1.0,1.0,0.0);

    //----------------------------
    //----------------------------

    //-- lookup table constants --
    //----------------------------

    const float_lookuptable	sintable(5000,0,two_pi,&sinf);
    const float_lookuptable	costable(5000,0,two_pi,&cosf);
    const float_lookuptable	tantable(5000,0,two_pi,&tanf);

    //----------------------------
    //----------------------------

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/imath/imath_core.h] - (2,551 bytes)

    /*-----------------------------------------------------------------------

    	Inline Math library : Non member function implementation

    	* See imath.h for more information

    	By Matt Barnett
    		(see References in imath.h)

    ------------------------------------------------------------------------*/

    //-------- headers etc -------
    //----------------------------

    #ifndef _IMATH_CORE_IMP_HEADER_354766003
    #define _IMATH_CORE_IMP_HEADER_354766003

    //--- non member functions ---
    //----------------------------
    //
    // some may seem silly stuff like
    //
    // inline float im_sin(float angle) { return sinf(angle) }
    // inline float im_sqrt(float val)  { return sqrtf(val)  }
    //
    // this are interfaces so that these functions can be replaced
    // with more efficient versions. (trig functions are replaced with
    // lookup tables)
    //

    //theroy (degrees & radians)
    //
    //to avoid confusion it is best _NOT_ to convert angle measures.
    //Sick with radians untill conversion to degrees is ABSOLUTELY nessesary
    //(try not to store degrees, throw them away if appropriate)

    //converts radians to degrees
    inline float im_r2d(float angle)
    {
    	return 	(angle * _180_over_pi);
    }

    //converts degrees to radians
    inline float im_d2r(float angle)
    {
    	return	(angle * _pi_over_180);
    }

    //random number generation
    //seed with the generator (custom seed
    inline void im_random_seed(unsigned int seed)
    {
    	srand( seed );
    }
    //seed with time
    inline void im_random_seed_time()
    {
    	im_random_seed( GetTickCount() );
    }

    //random number retrival functions
    //returns a float between 0 & 1

    inline float im_random_num()
    {
    	return ((float)rand()/(RAND_MAX+1));
    }

    //all based on im_random_num
    inline float im_random_num(float range)   { return im_random_num() * range;}		//returns a float between 0 & range
    inline float im_random_clamp()			  { return -1 + im_random_num() * 2;  }		//returns a float in the range -1.0f -> + 1.0f
    inline float im_random_clamp(float range) { return im_random_clamp() * range; }		//returns a float between -range & +range

    //sqrt
    inline float im_sqrt(float in)
    {
    	return sqrtf(in);
    }

    inline float im_sin(float in)
    {
    	//return sinf(in);
    	return sintable.lookup(in);
    }

    inline float im_cos(float in)
    {
    	//return cosf(in);
    	return costable.lookup(in);
    }

    inline float im_acos(float in)
    {
    	return acosf(in);
    }

    inline float im_tan(float in)
    {
    	//return tanf(in);
    	return tantable.lookup(in);
    }

    //----------------------------
    //----------------------------

    #endif

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/imath/imath_real2int.h] - (2,762 bytes)

    /*-----------------------------------------------------------------------

    	Inline Math library : Real to Integer conversion by Sree

    	* See imath.h for more information

    	By Matt Barnett
    		(see References in imath.h)

    ------------------------------------------------------------------------*/

    #ifndef _IMATH_REAL2INT_IMP_HEADER_156858806791
    #define _IMATH_REAL2INT_IMP_HEADER_156858806791

    // Float/Double -> Int
    //
    // By Sree
    //
    //  (from web article)
    //	Sree's Real2Int
    //
    //	There are quite a few ways to fix this. One of the best general conversion utilities I have is one
    //	that Sree Kotay wrote. It's only safe to use when your FPU is in double-precision mode, so you have
    //	to be careful about it if you're switching precision like above. It'll basically return '0' all the
    //	time if you're in single precision.
    //
    //	--- notes by matt ---
    //  Somthing is wierd here
    //  My lut class attempts to switch to single precision mode
    //  but this function must still be working, or (i think) the
    //  core im_ functions would all fall down.
    //
    //	(I've recently discovered that this discussion bears a lot of resemblance to Chris Hecker's article
    //	on the topic, so be sure to read that if you can't figure out what I'm saying.)
    //	This function is basically an ANSI C compliant conversion -- it always chops, always does the right thing,
    //	for positive or negative inputs.
    //
    //

    //-- performace notes by matt --
    //
    // the blurb states that (int)somefloat casts
    // are very slow.  My lookup table class
    // didnt seem to show that(the cast was no slower that this function),
    // but i have left this function in, and the class uses it.
    // (i guess it may be noticable for doubles (which i am avoiding)
    // flipcode threads have also mentioned (somewhere) float->int
    // conversions as being slow.
    //

    typedef double lreal;
    typedef float  real;
    typedef unsigned long uint32;
    typedef long int32;

    const lreal _double2fixmagic = 68719476736.0*1.5;     //2^36 * 1.5,  (52-_shiftamt=36) uses limited precisicion to floor
    const int32 _shiftamt        = 16;                    //16.16 fixed point representation,

    #if BigEndian_
    	#define iexp_				0
    	#define iman_				1
    #else
    	#define iexp_				1
    	#define iman_				0
    #endif //BigEndian_

    //--------------------
    // im_real2int(double)
    //--------------------
    inline int32 im_real2int(lreal val)
    {
    #if DEFAULT_CONVERSION
    	return val;
    #else
    	val		= val + _double2fixmagic;
    	return ((int32*)&val)[iman_] >> _shiftamt;
    #endif
    }

    //-------------------
    // im_real2int(float)
    //-------------------
    inline int32 im_real2int(real val)
    {
    #if DEFAULT_CONVERSION
    	return val;
    #else
    	return im_real2int ((lreal)val);
    #endif
    }

    #endif

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/imath/imath_box.h] - (4,894 bytes)

    /*-----------------------------------------------------------------------

    	Inline Math library : Bounding box implementation (header)

    	* See imath.h for more information

    	By Matt Barnett
    		(see References in imath.h)

    ------------------------------------------------------------------------*/

    /*------------------------------------------------------------------------------------

    	ibox3 class

    	------------
    	Description
    	------------

    	Bounding box class based for imath library

    	This class performs intersection testing, not "collision detection".

    	(collisions and intersections are similar, and you need intersections
    	 to implement collisions)

    	-------
    	General
    	-------

    		Everything is public in this class (like the other imath components)
    		This class has some non inlined functions

    	Orientation
    	-----------

    		To orient the bbox simply fiddle with
    		the quaternion

    		eg:		iquaternion4 somerotation;

    				//create somerotation with a suitable rotation

    				object.GetQuaternion().multiply(somerotation);

    ---------------------------------------------*/

    #ifndef _IBOX3_HEADER_
    #define _IBOX3_HEADER_

    //#define _IBOX3_TESTWITH_TEAPOT

    #ifdef _IBOX3_TESTWITH_TEAPOT
    	#include <gl/glut.h>
    #else
    	#include <gl/gl.h>
    	#include <gl/glu.h>
    #endif

    class ibox3
    {
    	public:

    		//assigning

    		const ibox3 &operator=(const ibox3 &rhs)
    		{
    			center = rhs.center;
    			extents = rhs.extents;
    			pos = rhs.pos;
    			quat = rhs.quat;
    			bas = rhs.bas;

    			return *this;
    		}

    		//------- construction etc ---
    		//----------------------------

    		//constructor
    		ibox3()
    		{
    			center = zero;
    			extents.set(0.01f,0.01f,0.01f);
    		}

    		//default constructor
    		ibox3(ivector3 &cextents,ivector3 &rotationcenter)
    		{
    			center = rotationcenter;
    			extents = cextents;
    		}

    		//copy constructor
    		ibox3(const ibox3 ©)
    		{
    			center = copy.center;
    			extents = copy.extents;
    			pos = copy.pos;
    			quat = copy.quat;
    			bas = copy.bas;
    		}

    		//destructor
    		~ibox3()
    		{

    		}

    		//----------------------------
    		//----------------------------

    		//------ public attributes ---
    		//----------------------------

    		//you can only change pos/angles directly
    		//position, or center of box

    		ivector3		pos;		//position of box
    		imatrix16		rm;			//rotation matrix (made from quaternion as nessesary)
    		iquaternion4	quat;		//

    		//dont fuck with the basis outside this class (copy)
    		inline ibasis9 getBasis()
    		{
    			return bas;
    		}
    		//ditto for extents(copy)
    		inline ivector3 getExtents()
    		{
    			return extents;
    		}
    		//ditto for center(copy)
    		inline ivector3 getCenter()
    		{
    			return center;
    		}

    		//----------------------------
    		//----------------------------

    		const bool intersect(const ibox3 &b) const;

    		//===========================================
    		//inline bool intersectSphere(const ibox3 &b) const
    		//
    		//	true for bounding sphere collision detection
    		//	between this and b.  optimised to no sqrts.
    		//
    		//
    		//	when inlined this give as big speedup
    		//  when we need to call it alot of times
    		//  (its an quick exit from collision)
    		//============================================*/
    		//const bool intersectSphere(const ibox3 &b) const;

    		inline bool intersectSphere(const ibox3 &b) const
    		{

    			//float aradsqr =					killed tempories
    			//float bradsqr =
    			//float radsqr = aradsqr + bradsqr;

    			//float arad = extents.length();
    			//float brad = b.extents.length();
    			//float rad = arad + brad;

    			ivector3 areal = pos;
    			ivector3 breal = b.pos;

    			ivector3 temp;

    			//because bas can be anything
    			//there doesnt seem to be a
    			//good way to simplfy here

    			temp = bas.x;temp.multiply(center.x);areal.add(temp);
    			temp = bas.y;temp.multiply(center.y);areal.add(temp);
    			temp = bas.z;temp.multiply(center.z);areal.add(temp);

    			temp = b.bas.x;temp.multiply(b.center.x);breal.add(temp);
    			temp = b.bas.y;temp.multiply(b.center.y);breal.add(temp);
    			temp = b.bas.z;temp.multiply(b.center.z);breal.add(temp);

    			temp = breal - areal;

    			//as with most of my maths, i dont know why we must *2
    			//here. its because the two lengthsqr's on the one side are
    			//too small
    			if ( temp.lengthsqr() < (extents.lengthsqr() + b.extents.lengthsqr() ) *2 )
    				return true;
    			else
    				return false;

    		}

    		const void gldraw();			//draws the oobb (bounding box) (shows what will/should be intersected with)
    		const void gldrawSphere();		//draws the bounding sphere

    		const void update()
    		{
    			rm.makefromQuaternion(quat);
    			bas = rm.getBasis();
    		}

    		protected:

    			ibasis9			bas;		//ortho basis
    			ivector3		extents;	//the extents of the box are constant
    			ivector3		center;		//center offset
    };

    #endif

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/imath/imath_box.cpp] - (8,873 bytes)

    /*-----------------------------------------------------------------------

    	Inline Math library : Bounding box implementation (cpp)

    	* See imath_box.h for more information

    	By Matt Barnett
    		(see References in imath.h)

    ------------------------------------------------------------------------*/

    #include "imath.h"

    /*===========================================
    const void ibox3::gldrawSphere()

    //very dirty way of display the box
    ============================================*/

    const void ibox3::gldrawSphere()
    {
    	GLUquadricObj* qobj;
    	qobj = gluNewQuadric();

    	gluQuadricDrawStyle(qobj,GLU_SILHOUETTE);

    	ivector3 areal = pos;
    	ivector3 temp;

    	temp = bas.x;temp.multiply(center.x);areal.add(temp);
    	temp = bas.y;temp.multiply(center.y);areal.add(temp);
    	temp = bas.z;temp.multiply(center.z);areal.add(temp);

    	glPushMatrix();

    		glTranslatef(areal.x,areal.y,areal.z);
    		gluSphere(qobj, extents.length() ,9,9);

    	glPopMatrix();

    	gluDeleteQuadric(qobj);
    }

    /*===========================================
    const void ibox3::gldraw()

    //very dirty way of display the box
    ============================================*/
    const void ibox3::gldraw()
    {
    	//pos.gldraw();

    	//draw the box

    	ivector3 h,l;

    	h.add(extents);
    	l.subtract(extents);

    	//could do my own rotation around it
    	//from here.

    	glPushMatrix();

    		glTranslatef(pos.x,pos.y,pos.z);

    		update();

    		//push and add the quaternion matrix
    		glPushMatrix();

    			glMultMatrixf(rm.m);

    				glTranslatef(center.x,center.y,center.z);

    //draw test object here
    #ifdef _IBOX3_TESTWITH_TEAPOT
    					glEnable(GL_LIGHTING);
    					glRotatef(90,1.0,0.0,0.0);
    //draw test object here
    					glDisable(GL_LIGHTING);
    #endif
    					glDisable(GL_TEXTURE_2D);

    					//draw the bow
    					glBegin(GL_LINE_LOOP);							//top loop
     						glVertex3f(h.v[0],h.v[1],h.v[2]);
    						glVertex3f(l.v[0],h.v[1],h.v[2]);
    						glVertex3f(l.v[0],l.v[1],h.v[2]);
    						glVertex3f(h.v[0],l.v[1],h.v[2]);
    					glEnd();
    					glBegin(GL_LINE_LOOP);							//bottom loop
    						glVertex3f(h.v[0],h.v[1],l.v[2]);
    						glVertex3f(l.v[0],h.v[1],l.v[2]);
    						glVertex3f(l.v[0],l.v[1],l.v[2]);
    						glVertex3f(h.v[0],l.v[1],l.v[2]);
    					glEnd();
    					glBegin(GL_LINES);									//the lines inbetween the loops
    						glVertex3f(h.v[0],h.v[1],h.v[2]);glVertex3f(h.v[0],h.v[1],l.v[2]);
    						glVertex3f(l.v[0],h.v[1],h.v[2]);glVertex3f(l.v[0],h.v[1],l.v[2]);
    						glVertex3f(l.v[0],l.v[1],h.v[2]);glVertex3f(l.v[0],l.v[1],l.v[2]);
    						glVertex3f(h.v[0],l.v[1],h.v[2]);glVertex3f(h.v[0],l.v[1],l.v[2]);
    					glEnd();

    					glBegin(GL_LINES);
    						glColor3f(1.0f,0.0,0.0);glVertex3f(-0.5f,0.0,0.0);glVertex3f(1.2f,0.0,0.0);
    						glColor3f(0.0,1.0f,0.0);glVertex3f(0.0,-0.5f,0.0);glVertex3f(0.0,1.2f,0.0);
    						glColor3f(0.0,0.0,1.0f);glVertex3f(0.0,0.0,-0.5f);glVertex3f(0.0,0.0,1.2f);
    					glEnd();

    		glPopMatrix();

    		//pop off the quat matrix
    		//and draw the basis

    		bas.gldraw();

    		glBegin(GL_LINES);
    			glColor3f(1.0f,0.0,0.0);glVertex3f(-0.5f,0.0,0.0);glVertex3f(1.2f,0.0,0.0);
    			glColor3f(0.0,1.0f,0.0);glVertex3f(0.0,-0.5f,0.0);glVertex3f(0.0,1.2f,0.0);
    			glColor3f(0.0,0.0,1.0f);glVertex3f(0.0,0.0,-0.5f);glVertex3f(0.0,0.0,1.2f);
    		glEnd();
    	glPopMatrix();

    }

    /*===========================================
    const bool ibox3::intersect(const ibox3 &b)

    	true for bounding box collision detection
    	between this and b

        (seperating axis test based on
    	 gamasutra article)
    ============================================*/

    const bool ibox3::intersect(const ibox3 &b) const
    {

    	//<mat2002>

    	//mat2002 added offset for center
    	//
    	//we must pass the real center to the intersect test, adjusted for the pivot/center
    	//to do this, we need to transform the position by the center with respect to the basis
    	//(this just means moving it from its position to its center along its basis)

    	ivector3 areal = pos;
    	ivector3 breal = b.pos;

    	ivector3 temp;

    	temp = bas.x;temp.multiply(center.x);areal.add(temp);
    	temp = bas.y;temp.multiply(center.y);areal.add(temp);
    	temp = bas.z;temp.multiply(center.z);areal.add(temp);

    	temp = b.bas.x;temp.multiply(b.center.x);breal.add(temp);
    	temp = b.bas.y;temp.multiply(b.center.y);breal.add(temp);
    	temp = b.bas.z;temp.multiply(b.center.z);breal.add(temp);

    	//works without centers
    	//ivector3 areal = (pos);
    	//ivector3 breal = (b.pos);

    	ivector3 v =  breal - areal;								//translation, in parent frame
    	ivector3 T( bas.x.dot(v),bas.y.dot(v),bas.z.dot(v) );		//translation in A's frame

    	float R[3][3];												//rotation matrix
    	float ra,rb,t;

    	int i,k;

    	//calculate rotation matrix R[][]
    	R[0][0] = bas.x.dot(b.bas.x);
    	R[0][1] = bas.x.dot(b.bas.y);
    	R[0][2] = bas.x.dot(b.bas.z);

    	R[1][0] = bas.y.dot(b.bas.x);
    	R[1][1] = bas.y.dot(b.bas.y);
    	R[1][2] = bas.y.dot(b.bas.z);

    	R[2][0] = bas.z.dot(b.bas.x);
    	R[2][1] = bas.z.dot(b.bas.y);
    	R[2][2] = bas.z.dot(b.bas.z);

    //	for (i=0;i<3;i++)
    //		for (k=0;k<3;k++)
    //			printf("R[%i][%i] %f\n",i,k,R[i][k]);

    	//a's basis vectors
    	for (i=0;i<3;i++)
    	{
    		ra = extents[i];
    		//ra = extents[i];     //mat2002

    		rb = b.extents[0] * fabs(R[i][0]) + b.extents[1] * fabs(R[i][1]) + b.extents[2] * fabs(R[i][2]);
    		t = fabs(T[i]);
    		if (t > ra + rb)
    		{
    			#ifdef VERBOSE_SEPERATION
    				printf("a basis %i seperates a and b\n",i);
    			#endif

    			return false;
    		}
    	}

    	//safe to here

    	//b's basis vectors
    	for (k=0;k<3;k++)
    	{
    		ra = extents[0] * fabs(R[0][k]) + extents[1] * fabs(R[1][k]) + extents[2] * fabs(R[2][k]);
    		rb = b.extents[k];
    		t = fabs(T[0] * R[0][k] + T[1] * R[1][k] + T[2] * R[2][k]);
    		if (t > ra + rb)
    		{
    			#ifdef VERBOSE_SEPERATION
    				printf("b basis %i seperates a and b\n",k);
    			#endif

    			return false;
    		}
    	}

    	//9 cross products

    	//all the a0s

    	ra = extents[1] * fabs(R[2][0]) + extents[2] * fabs(R[1][0]);
    	rb = b.extents[1] * fabs(R[0][2]) + b.extents[2] * fabs(R[0][1]);
    	t = fabs(T[2] * R[1][0] - T[1] * R[2][0]);
    	if (t > ra + rb)
    	{
    		#ifdef VERBOSE_SEPERATION
    			printf("a0*b0 seperates a and b\n",k);
    		#endif

    		return false;
    	}
    	ra = extents[1] * fabs(R[2][1]) + extents[2] * fabs(R[1][1]);
    	rb = b.extents[0] * fabs(R[0][2]) + b.extents[2] * fabs(R[0][0]);
    	t = fabs(T[2] * R[1][1] - T[1] * R[2][1]);
    	if (t > ra + rb)
    	{

    		#ifdef VERBOSE_SEPERATION
    			printf("a0*b1 seperates a and b\n",k);
    		#endif

    		return false;
    	}

    	ra = extents[1] * fabs(R[2][2]) + extents[2] * fabs(R[1][2]);
    	rb = b.extents[0] * fabs(R[0][1]) + b.extents[1] * fabs(R[0][0]);
    	t = fabs(T[2] * R[1][2] - T[1] * R[2][2]);
    	if (t > ra + rb)
    	{

    		#ifdef VERBOSE_SEPERATION
    			printf("a0*b2 seperates a and b\n",k);
    		#endif

    		return false;
    	}

    	//all the a1s

    	ra = extents[0] * fabs(R[2][0]) + extents[2] * fabs(R[0][0]);
    	rb = b.extents[1] * fabs(R[1][2]) + b.extents[2] * fabs(R[1][1]);
    	t = fabs(T[0] * R[2][0] - T[2] * R[0][0]);
    	if (t > ra + rb)
    	{

    		#ifdef VERBOSE_SEPERATION
    			printf("a1*b0 seperates a and b\n",k);
    		#endif

    		return false;
    	}

    	ra = extents[0] * fabs(R[2][1]) + extents[2] * fabs(R[0][1]);
    	rb = b.extents[0] * fabs(R[1][2]) + b.extents[2] * fabs(R[1][0]);
    	t = fabs(T[0] * R[2][1] - T[2] * R[0][1]);
    	if (t > ra + rb)
    	{
    		#ifdef VERBOSE_SEPERATION
    			printf("a1*b1 seperates a and b\n",k);
    		#endif

    		return false;
    	}

    	ra = extents[0] * fabs(R[2][2]) + extents[2] * fabs(R[0][2]);
    	rb = b.extents[0] * fabs(R[1][1]) + b.extents[1] * fabs(R[1][0]);
    	t = fabs(T[0] * R[2][2] - T[2] * R[0][2]);
    	if (t > ra + rb)
    	{
    		#ifdef VERBOSE_SEPERATION
    			printf("a1*b2 seperates a and b\n",k);
    		#endif

    		return false;
    	}

    	//all the a2s

    	ra = extents[0] * fabs(R[1][0]) + extents[1] * fabs(R[0][0]);
    	rb = b.extents[1] * fabs(R[2][2]) + b.extents[2] * fabs(R[2][1]);
    	t = fabs(T[1] * R[0][0] - T[0] * R[1][0]);
    	if (t > ra + rb)
    	{
    		#ifdef VERBOSE_SEPERATION
    			printf("a2*b0 seperates a and b\n",k);
    		#endif

    		return false;
    	}

    	ra = extents[0] * fabs(R[1][1]) + extents[1] * fabs(R[0][1]);
    	rb = b.extents[0] * fabs(R[2][2]) + b.extents[2] * fabs(R[2][0]);
    	t = fabs(T[1] * R[0][1] - T[0] * R[1][1]);
    	if (t > ra + rb)
    	{
    		#ifdef VERBOSE_SEPERATION
    			printf("a2*b1 seperates a and b\n",k);
    		#endif

    		return false;
    	}

    	ra = extents[0] * fabs(R[1][2]) + extents[1] * fabs(R[0][2]);
    	rb = b.extents[0] * fabs(R[2][1]) + b.extents[1] * fabs(R[2][0]);
    	t = fabs(T[1] * R[0][2] - T[0] * R[1][2]);
    	if (t > ra + rb)
    	{
    		#ifdef VERBOSE_SEPERATION
    			printf("a2*b2 seperates a and b\n",k);
    		#endif

    		return false;
    	}

    	//disturbed laughter
    	return true;
    }

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/imath/imath_trace.h] - (7,147 bytes)

    /*-----------------------------------------------------------------------

    	Inline Math library : Ray and Plane implementation

    	* See imath.h for more information

    	By Matt Barnett
    		(see References in imath.h)

    ------------------------------------------------------------------------*/

    #ifndef _IMATH_TRACE_IMP_HEADER_529081235
    #define _IMATH_TRACE_IMP_HEADER_529081235

    /*---------------------------------------------

    	Raytracing/linetracing and collision detection

    	iray6
    	iplane6

    	-------
    	classes
    	-------

    		iray6
    		iplane6

    	------
    	design
    	------

    		* a ray is defined a point(position) and a normalised vector(direction)
    		* a plane is defined as abcd

    ---------------------------------------------*/

    //-------------- iplane4 ------------
    //	plane class
    //------------------------------------

    class iplane4
    {
    	public:

    		ivector3 norm;
    		float d;

    		//-------------- operators ---
    		//----------------------------
    	    //return types according to Effective C++ 2e (see ref 8)

    		//assignment
    		inline const iplane4 &operator=(const iplane4 &right)
    		{
    			if (&right != this) {				//check for self assign
    				norm = right.norm;				//copy right to left
    				d = right.d;
    			}
    			return *this;						//enables x = y = z
    		}

    		//----------------------------
    		//----------------------------

    		//------- construction etc ---
    		//----------------------------

    		//inlined ctor
    		inline iplane4()
    		{
    			//no need here
    			//vectors construct themselves adequetly
    		}

    		//inlined ctor
    		inline iplane4(const float in_d,const ivector3 &in_norm)
    		{
    			norm = in_norm;
    			d = in_d;
    		}

    		//inlined dtor(unnessesary)
    		inline ~iplane4()
    		{}

    		//----------------------------
    		//----------------------------

    		//--------- functions --------
    		//----------------------------
    		//sets components

    		//dumps the componets (debug aid)
    		inline void cdump(const char *caption)  const
    		{
    			norm.cdump("iplane4 norm = ");
    			printf("iplane4 d = %f\n",d);
    		}

    		//draw's the plane (debug aid)
    		//plane extend to infinity,
    		//so the client decideds how far that is (length)
    		//(not optimised for drawing lots of planes, which may be needed later)

    		//creates a quad from the plane's normal
    		//much like a particle is generated7
    		inline void gldraw(float length,ivector3 rgbcolor)
    		{
    			//some good practice at vector math here

    			//we need to create an up vector and a left vector
    			//from the normal of the plane

    			//both are perpendicular to the norm, so crossproducts
    			//are an easy way to do this (allthought there may
    			//be a faster solution)

    			//create any vector perp to the normal
    			//(the operand xaxis could be any vector)
    			ivector3 left = norm.cross(xaxis);
    			left.normalise();

    			//the up vector needs to be perp to both the norm and the left vector
    			ivector3 up =  norm.cross(left);
    			up.normalise();

    			//size it according to length param
    			left.multiply(length);
    			up.multiply(length);

    			//pos is a point on the plane
    			ivector3 pos = (norm * d);
    			ivector3 temp = pos;

    			glDisable(GL_LIGHTING);

    			glBegin(GL_LINES);

    				glColor3fv(red.v);

    				pos.glplot();temp = pos + norm;
    				temp.glplot();

    				glColor3fv(cyan.v);

    				pos.glplot();temp = pos + left;
    				temp.glplot();

    				glColor3fv(yellow.v);

    				pos.glplot();temp = pos + up;
    				temp.glplot();

    			glEnd();

    			glColor3fv(rgbcolor.v);

    			glBegin(GL_QUADS);
    				glVertex3f(pos.x + left.x + up.x,pos.y + left.y + up.y,pos.z + left.z + up.z);
    				glVertex3f(pos.x - left.x + up.x,pos.y - left.y + up.y,pos.z - left.z + up.z);
    				glVertex3f(pos.x - left.x - up.x,pos.y - left.y - up.y,pos.z - left.z - up.z);
    				glVertex3f(pos.x + left.x - up.x,pos.y + left.y - up.y,pos.z + left.z - up.z);
    			glEnd();

    		}

    		//----------------------------
    		//----------------------------

    };

    //-------------- iray ------------
    //
    //	ray class
    //------------------------------------

    class iray6
    {
    	public:

    		ivector3 pos;		//treated as a position
    		ivector3 dir;		//treated as a direction (magnitude represents light/strength?)

    		//-------------- operators ---
    		//----------------------------
    	    //return types according to Effective C++ 2e (see ref 8)

    		//assignment
    		//the comilier should be able to generate this (its only member copy)
    		inline const iray6 &operator=(const iray6 &right)
    		{
    			if (&right != this) {				//check for self assign
    				dir = right.dir;				//copy right to left
    				pos = right.pos;
    			}
    			return *this;						//enables x = y = z
    		}

    		//----------------------------
    		//----------------------------

    		//------- construction etc ---
    		//----------------------------

    		//inlined ctor
    		inline iray6()
    		{
    			pos.set(0,0,0);			//we'll start all rays at 0,0,0
    			dir.set(0,0,1.0);		//pointing up in the air
    		}

    		//inlined ctor(initalises to pos,dir)
    		inline iray6(const ivector3 &in_pos,const ivector3 &in_dir)
    		{
    			pos = in_pos;
    			dir = in_dir;
    		}

    		//inlined cpy ctor
    		//the comilier generates this (its only member copy)

    		//inlined dtor(unnessesary)
    		inline ~iray6()
    		{}

    		//----------------------------
    		//----------------------------

    		//--------- functions --------
    		//----------------------------

    		inline float intersect(class iplane4 &with)
    		{

    			float cosAlpha = dir.dot( with.norm );		//dot product of ray's direction vector (normalised) and plane's normal vector (normalised)

    			ivector3 diff = (with.norm * with.d) - pos;				//vector from plane origin to ray origin
    			float deltaD = diff.dot(with.norm);				//dot product of above and plane's normal

    			//deltaD is the length of the shortest line to the point

    			return deltaD/cosAlpha;
    		}

    		//dumps the componets (debug aid)
    		inline void cdump(const char *caption)  const
    		{
    			pos.cdump("ray pos = ");
    			dir.cdump("ray dir = ");
    		}

    		//draw's the ray (debug aid)
    		//rays extend to infinity,
    		//so the client decideds how far that is (length)

    		//(not optimised for drawing lots of rays, which may be needed later)
    		inline void gldraw(float length,const ivector3 &startcol,const ivector3 &endcol) const
    		{
    			ivector3 endpos = dir;

    			endpos.multiply(length);
    			endpos.add(pos);

    			glDisable(GL_LIGHTING);
    			//glDisable(GL_BLEND);
    			glDisable(GL_TEXTURE_2D);
    			glBegin(GL_LINES);
    				glColor3fv(startcol.v);
    				pos.glplot();
    				glColor3fv(endcol.v);
    				endpos.glplot();
    			glEnd();
    		}

    		inline void gldraw(float length) const
    		{
    			ivector3 endpos = dir;
    			endpos.multiply(length);
    			endpos.add(pos);
    			glDisable(GL_LIGHTING);
    			glBegin(GL_LINES);
    				pos.glplot();
    				endpos.glplot();
    			glEnd();
    		}

    		//----------------------------
    		//----------------------------

    };

    #endif

Currently browsing [matnn_cotd.zip] (123,598 bytes) - [matnn_cotd/code/imath/imath_vector.h] - (10,827 bytes)

    /*-----------------------------------------------------------------------

    	Inline Math library : Vector Matrix and Quaternion implementation

    	* See imath.h for more information

    	By Matt Barnett
    		(see References in imath.h)

    ------------------------------------------------------------------------*/

    #ifndef _IMATH_V_IMP_HEADER_4778097634v
    #define _IMATH_V_IMP_HEADER_4778097634v

    //-------------- ivector3 ------------
    //
    //  simple 3d vector with 3 components
    //	(there is no 2d version, use this)
    //------------------------------------

    //enum for auto constructing some vector types
    //if you want to contruct a random vector
    //or  and random normalised vector etc.
    enum ivector3_constructor_enum { IVECTOR3_RANDOM , IVECTOR3_RANDOM_NORM };

    class ivector3
    {
    	public:

    		//three floats are the data
    		union
    		{
    			float v[3];
    			struct { float x, y, z; };
    		};

    		//-------------- operators ---
    		//----------------------------
    	    //return types according to Effective C++ 2e (see ref 8)

    		inline const ivector3 operator-(const ivector3 &right) const
    		{
    			return ivector3(x - right.x,y - right.y,z - right.z);
    		}
    		inline const ivector3 operator+(const ivector3 &right) const
    		{
    			return ivector3(x + right.x,y + right.y,z + right.z);
    		}

    		inline const ivector3 operator*(const ivector3 &right) const
    		{
    			return ivector3(x * right.x,y * right.y,z * right.z);
    		}
    		inline const ivector3 operator/(const ivector3 &right) const
    		{
    			return ivector3(x / right.x,y / right.y,z / right.z);
    		}

    		inline const ivector3 operator*(const float scalar) const
    		{
    			return ivector3(x * scalar,y * scalar,z * scalar);
    		}
    		inline const ivector3 operator/(const float scalar) const
    		{
    			return ivector3(x / scalar,y / scalar,z / scalar);
    		}

    		//void operators
    		inline void operator-=(const ivector3 &right)
    		{
    			subtract(right);
    		}
    		inline void operator+=(const ivector3 &right)
    		{
    			add(right);
    		}

    		//assignment
    		inline ivector3 &operator=(const ivector3 &right)
    		{
    			if (&right != this) {				//check for self assign
    				x = right.x;					//copy right to left
    				y = right.y;
    				z = right.z;
    			}
    			return *this;						//enables x = y = z
    		}

    		inline float operator[](int subscript) const
    		{
    			assert( subscript < 3 && subscript >= 0 );
    			return v[subscript];
    		}
    		//----------------------------
    		//----------------------------

    		//------- construction etc ---
    		//----------------------------

    		//inlined ctor(initalises to 0,0,0)
    		inline ivector3()
    		{
    			set(0,0,0);
    		}

    		//inlined ctor(initalises to x,y,z)
    		inline ivector3(const float setx,const float sety,const float setz)
    		{
    			set(setx,sety,setz);
    		}

    		//ctor for a random normalised vector
    		explicit inline ivector3(ivector3_constructor_enum inv_ce)
    		{
    			if (inv_ce == IVECTOR3_RANDOM_NORM)
    			{
    				randomize(1.0);
    				normalise();
    			}
    			else if (inv_ce == IVECTOR3_RANDOM)
    				randomize(1.0);
    		}

    		//inlined dtor(unnessesary)
    		inline ~ivector3()
    		{}
    		//----------------------------
    		//----------------------------

    		//--------- void functions ---
    		//----------------------------
    		//sets vector components

    		inline void set(const float setx,const float sety,const float setz)
    		{
    			x = setx;
    			y = sety;
    			z = setz;
    		}

    		//sets z == 0
    		inline void make2d()
    		{
    			z = 0;
    		}

    		//dumps the vectors componets (debug aid)
    		inline void cdump(const char *caption)  const
    		{
    			cout << caption << x << " " << y << " " << z << endl;
    		}

    		//draw O -> vector (debug aid)
    		inline void gldraw() const
    		{
    			glDisable(GL_LIGHTING);
    			glBegin(GL_LINES);
    			glVertex3f(0.0,0.0,0.0);
    			glVertex3fv(v);
    			glEnd();
    		}
    		//plot the vector (debug aid)
    		inline void glplot() const
    		{
    			glVertex3fv(v);
    		}

    		//multiplies this by scalar
    		inline void multiply(const float scalar)
    		{
    			x *= scalar;
    			y *= scalar;
    			z *= scalar;
    		}

    		//multiplies this by multiply
    		inline void multiply(const ivector3 &multiply)
    		{
    			x *= multiply.x;
    			y *= multiply.y;
    			z *= multiply.z;
    		}

    		//divides this by scalar
        	inline void divide(const float scalar)
    		{
    			x /= scalar;
    			y /= scalar;
    			z /= scalar;
    		}

    		//divides this by divide
        	inline void divide(const ivector3 ÷)
    		{
    			x /= divide.x;
    			y /= divide.y;
    			z /= divide.z;
    		}

    		//adds add to this
    		inline void add(const ivector3 &add)
    		{
    			x += add.x;
    			y += add.y;
    			z += add.z;
    		}

    		//subtracts subtract from this
    		inline void subtract(const ivector3 &subtract)
    		{
    			x -= subtract.x;
    			y -= subtract.y;
    			z -= subtract.z;
    		}

    		//multiplies this by matrix multiply
    		//inline void multiply(imatrix16 &multiply)
    		//{
    		//
    		//}

    		//normalise
    		inline void normalise()
    		{
    			const float n = length();
    			if (!n)
    			{
    				#ifdef _IVECTOR3_VERBOSE_NORMALISE_FAIL_
    					printf("ivector3::MATH_ERROR ( normalise failed(), length = 0 )\n");
    					cdump("vector ");
    				#endif

    				return;
    			}

    			x /= n;
    			y /= n;
    			z /= n;
    		}

    		//randomises each component
    		inline void randomize(float range)
    		{
    			x = im_random_clamp(range);
    			y = im_random_clamp(range);
    			z = im_random_clamp(range);
    		}

    		//makes "this" the normal of the three vectors
    		inline void makeTriangleNormal(const ivector3 &a,const ivector3 &b,const ivector3 &c)
    		{
    			ivector3 ab,ac;

    			ab = b - a;
    			ac = c - a;

    			ivector3 cross = ab.cross(ac);
    			cross.normalise();

    			*this = cross;

    		}
    		//----------------------------
    		//----------------------------

    		//-------------- functions ---
    		//----------------------------
    		//crossproduct
    		inline const ivector3 &cross(const ivector3 &in) const
    		{
    			ivector3 out;
    			out.x = y*in.z - z*in.y;
    			out.y = z*in.x - x*in.z;
    			out.z = x*in.y - y*in.x;
    			return out;
    		}

    		//length/norm
    		inline float length() const
    		{
    			float a = (x*x)+(y*y)+(z*z);

    			if (a <= 0)
    			{
    				#ifdef _IVECTOR3_VERBOSE_LENGTH_FAIL_
    					printf("ivector3::MATH_ERROR ( length failed, x*x+y*y+z*z <= 0 )\n");
    					cdump("vector ");
    					printf("x*x+y*y+z*z = %f\n",a);
    				#endif

    				return 0;
    			}

    			return im_sqrt(a);
    		}

    		//length/norm
    		inline float lengthsqr() const
    		{
    			float a = (x*x)+(y*y)+(z*z);

    			if (a <= 0)
    			{
    				#ifdef _IVECTOR3_VERBOSE_LENGTH_FAIL_
    					printf("ivector3::MATH_ERROR ( length failed, x*x+y*y+z*z <= 0 )\n");
    					cdump("vector ");
    					printf("x*x+y*y+z*z = %f\n",a);
    				#endif

    				return 0;
    			}

    			return a;
    		}

    		//dotproduct
    		inline float dot(const ivector3 &in) const
    		{
    			return x*in.x + y*in.y + z*in.z;
    		}

    		//angle between this and in
    		//
    		//inline float angle(const ivector3 &in) const
    		//{
    		//	float tdotin,theta;
    		//
    		//	tdotin = dot(in);								//dot product
    		//
    		//	float li;
    		//	li = in.length();
    		//
    		//	theta = tdotin / (length() * li);				//lengths
    		//	theta = (float)im_acos(theta);					//inverse im_cos
    		//
    		//	return theta;									//return theta in radians
    		//}

    		inline float cangle(const ivector3 &in) const
    		{
    			return ( x*in.x + y*in.y + z*in.z ) / ( (length() )*(in.length() ) );
    		}

    		//matrix based angle axis rotation (radians)
    		//matrix isnt stored
    		//usefull to rotate a point/vector about an axis
    		inline void rotate(const float angle,const ivector3 &axis)
    		{
    			//componets of rotation axis
    			//float a = axis.x;
    			//float b = axis.y;
    			//float c = axis.z;

    			//get the matrix
    			float f1cos,fasin,fbsin,fcsin;

    			//fcos = im_cos(angle);		//im_cos of angle
    			//fsin = im_sin(angle);		//im_sin of angle

    			f1cos = (1 - im_cos(angle) );			//1 - im_cos of angle

    			fasin = (axis.x * im_sin(angle) );			//a * im_sin of angle
    			fbsin = (axis.y * im_sin(angle) );			//b * im_sin of angle
    			fcsin = (axis.z * im_sin(angle) );			//c * im_sin of angle

    			//m[0] = a*a*f1cos + fcos;
    			//m[1] = a*b*f1cos - fcsin;
    			//m[2] = a*c*f1cos + fbsin;

    			//m[3] = a*b*f1cos + fcsin;
    			//m[4] = b*b*f1cos + fcos;
    			//m[5] = b*c*f1cos - fasin;

    			//m[6] = a*c*f1cos - fbsin;
    			//m[7] = b*c*f1cos + fasin;
    			//m[8] = c*c*f1cos + fcos;

    			ivector3 out;

    			out.x = x * (axis.x * axis.x * f1cos + im_cos(angle) )  + y * (axis.x * axis.y * f1cos - fcsin) + z * (axis.x * axis.z * f1cos + fbsin);
    			out.y = x * (axis.x * axis.y * f1cos + fcsin) + y * (axis.y * axis.y * f1cos + im_cos(angle) ) + z * (axis.y * axis.z * f1cos - fasin);
    			out.z = x * (axis.x * axis.z * f1cos - fbsin) + y * (axis.y * axis.z * f1cos + fasin) + z * (axis.z * axis.z * f1cos + im_cos(angle) );

    			x = out.x;
    			y = out.y;
    			z = out.z;

    		}
    		//----------------------------
    		//----------------------------
    };

    //------ ivector3 constants -----
    //-------------------------------

    const ivector3 xaxis(1.0,0.0,0.0);
    const ivector3 yaxis(0.0,1.0,0.0);
    const ivector3 zaxis(0.0,0.0,1.0);
    const ivector3 zero (0.0,0.0,0.0);

    //a few colors
    const ivector3 red  (1.0,0.0,0.0);
    const ivector3 green(0.0,1.0,0.0);
    const ivector3 blue (0.0,0.0,1.0);
    const ivector3 black(0.0,0.0,0.0);

    const ivector3 cyan   (0.0,1.0,1.0);
    const ivector3 magenta(1.0,0.0,1.0);
    const ivector3 yellow (1.0,1.0,0.0);

    //----------------------------
    //----------------------------

    //-------------- ibasis9 ------
    //
    // just for storing and drawing
    // orthonominal(??) bases or axes
    //
    // there is no clever shit here making
    // sure that the vectors remain perpendicular
    // this is just for storage of 3 vectors.

    class ibasis9
    {
    	public:

    		//three vectors are the data
    		ivector3 x,y,z;

    		ibasis9::ibasis9(const ivector3 &inx,const ivector3 &iny,const ivector3 &inz)
    		{
    			x = inx;
    			y = iny;
    			z = inz;
    		}

    		ibasis9::ibasis9()
    		{
    			x = xaxis;
    			y = yaxis;
    			z = zaxis;
    		}

    		//just normalises each vector to save some typing
    		inline void normalise()
    		{
    			x.normalise();
    			y.normalise();
    			z.normalise();
    		}

    		//draws the basis (debug aid)
    		inline void gldraw() const
    		{
    			glDisable(GL_LIGHTING);
    			glBegin(GL_LINES);
    			glColor3fv(cyan.v);   glVertex3fv(zero.v);glVertex3fv(x.v);
    			glColor3fv(magenta.v);glVertex3fv(zero.v);glVertex3fv(y.v);
    			glColor3fv(yellow.v); glVertex3fv(zero.v);glVertex3fv(z.v);
    			glEnd();
    		}
    };

    //----------------------------
    //----------------------------

    #endif

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.