├── .gitignore ├── Agent.cpp ├── Agent.h ├── CMakeLists.txt ├── DWRAONBrain.cpp ├── DWRAONBrain.h ├── GLView.cpp ├── GLView.h ├── README.markdown ├── README.txt ├── View.cpp ├── View.h ├── World.cpp ├── World.h ├── changes.txt ├── config.h.in ├── glut.h ├── glut32.dll ├── glut32.lib ├── helpers.h ├── main.cpp ├── report.txt ├── settings.h ├── vmath.cpp └── vmath.h /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.swp* 3 | *.kdev4 4 | Debug/ 5 | Release/ 6 | build/ 7 | -------------------------------------------------------------------------------- /Agent.cpp: -------------------------------------------------------------------------------- 1 | #include "Agent.h" 2 | 3 | #include "settings.h" 4 | #include "helpers.h" 5 | #include 6 | #include 7 | #include 8 | #include "DWRAONBrain.h" 9 | using namespace std; 10 | Agent::Agent() 11 | { 12 | pos= Vector2f(randf(0,conf::WIDTH),randf(0,conf::HEIGHT)); 13 | angle= randf(-M_PI,M_PI); 14 | health= 1.0+randf(0,0.1); 15 | age=0; 16 | spikeLength=0; 17 | red= 0; 18 | gre= 0; 19 | blu= 0; 20 | w1=0; 21 | w2=0; 22 | soundmul=1; 23 | give=0; 24 | clockf1= randf(5,100); 25 | clockf2= randf(5,100); 26 | boost=false; 27 | indicator=0; 28 | gencount=0; 29 | selectflag=0; 30 | ir=0; 31 | ig=0; 32 | ib=0; 33 | hybrid= false; 34 | herbivore= randf(0,1); 35 | repcounter= herbivore*randf(conf::REPRATEH-0.1,conf::REPRATEH+0.1) + (1-herbivore)*randf(conf::REPRATEC-0.1,conf::REPRATEC+0.1); 36 | 37 | id=0; 38 | 39 | MUTRATE1= 0.003; 40 | MUTRATE2= 0.05; 41 | 42 | in.resize(INPUTSIZE, 0); 43 | out.resize(OUTPUTSIZE, 0); 44 | } 45 | 46 | void Agent::printSelf() 47 | { 48 | printf("Agent age=%i\n", age); 49 | for (int i=0;ipos + fb + Vector2f(randf(-conf::BOTRADIUS*2,conf::BOTRADIUS*2), randf(-conf::BOTRADIUS*2,conf::BOTRADIUS*2)); 75 | if (a2.pos.x<0) a2.pos.x= conf::WIDTH+a2.pos.x; 76 | if (a2.pos.x>=conf::WIDTH) a2.pos.x= a2.pos.x-conf::WIDTH; 77 | if (a2.pos.y<0) a2.pos.y= conf::HEIGHT+a2.pos.y; 78 | if (a2.pos.y>=conf::HEIGHT) a2.pos.y= a2.pos.y-conf::HEIGHT; 79 | 80 | a2.gencount= this->gencount+1; 81 | a2.repcounter= a2.herbivore*randf(conf::REPRATEH-0.1,conf::REPRATEH+0.1) + (1-a2.herbivore)*randf(conf::REPRATEC-0.1,conf::REPRATEC+0.1); 82 | 83 | //noisy attribute passing 84 | a2.MUTRATE1= this->MUTRATE1; 85 | a2.MUTRATE2= this->MUTRATE2; 86 | if (randf(0,1)<0.2) a2.MUTRATE1= randn(this->MUTRATE1, conf::METAMUTRATE1); 87 | if (randf(0,1)<0.2) a2.MUTRATE2= randn(this->MUTRATE2, conf::METAMUTRATE2); 88 | if (this->MUTRATE1<0.001) this->MUTRATE1= 0.001; 89 | if (this->MUTRATE2<0.02) this->MUTRATE2= 0.02; 90 | a2.herbivore= cap(randn(this->herbivore, MR2*4)); 91 | if (randf(0,1)brain; 98 | a2.brain.mutate(MR,MR2); 99 | 100 | return a2; 101 | 102 | } 103 | 104 | Agent Agent::crossover(const Agent& other) 105 | { 106 | //this could be made faster by returning a pointer 107 | //instead of returning by value 108 | Agent anew; 109 | anew.hybrid=true; //set this non-default flag 110 | anew.gencount= this->gencount; 111 | if (other.gencountclockf1 : other.clockf1; 115 | anew.clockf2= randf(0,1)<0.5 ? this->clockf2 : other.clockf2; 116 | anew.herbivore= randf(0,1)<0.5 ? this->herbivore : other.herbivore; 117 | anew.MUTRATE1= randf(0,1)<0.5 ? this->MUTRATE1 : other.MUTRATE1; 118 | anew.MUTRATE2= randf(0,1)<0.5 ? this->MUTRATE2 : other.MUTRATE2; 119 | 120 | anew.brain= this->brain.crossover(other.brain); 121 | 122 | return anew; 123 | } 124 | -------------------------------------------------------------------------------- /Agent.h: -------------------------------------------------------------------------------- 1 | #ifndef AGENT_H 2 | #define AGENT_H 3 | 4 | #include "DWRAONBrain.h" 5 | #include "vmath.h" 6 | 7 | #include 8 | #include 9 | 10 | class Agent 11 | { 12 | 13 | public: 14 | Agent(); 15 | 16 | 17 | void printSelf(); 18 | //for drawing purposes 19 | void initEvent(float size, float r, float g, float b); 20 | 21 | void tick(); 22 | Agent reproduce(float MR, float MR2); 23 | Agent crossover(const Agent &other); 24 | 25 | Vector2f pos; 26 | 27 | float health; //in [0,2]. I cant remember why. 28 | float angle; //of the bot 29 | 30 | float red; 31 | float gre; 32 | float blu; 33 | 34 | float w1; //wheel speeds 35 | float w2; 36 | bool boost; //is this agent boosting 37 | 38 | float spikeLength; 39 | int age; 40 | 41 | std::vector in; //input: 2 eyes, sensors for R,G,B,proximity each, then Sound, Smell, Health 42 | std::vector out; //output: Left, Right, R, G, B, SPIKE 43 | 44 | float repcounter; //when repcounter gets to 0, this bot reproduces 45 | int gencount; //generation counter 46 | bool hybrid; //is this agent result of crossover? 47 | float clockf1, clockf2; //the frequencies of the two clocks of this bot 48 | float soundmul; //sound multiplier of this bot. It can scream, or be very sneaky. This is actually always set to output 8 49 | //variables for drawing purposes 50 | float indicator; 51 | float ir;float ig;float ib; //indicator colors 52 | int selectflag; //is this agent selected? 53 | float dfood; //what is change in health of this agent due to giving/receiving? 54 | 55 | float give; //is this agent attempting to give food to other agent? 56 | 57 | int id; 58 | 59 | //inhereted stuff 60 | float herbivore; //is this agent a herbivore? between 0 and 1 61 | float MUTRATE1; //how often do mutations occur? 62 | float MUTRATE2; //how significant are they? 63 | 64 | DWRAONBrain brain; //THE BRAIN!!!! 65 | 66 | //will store the mutations that this agent has from its parent 67 | //can be used to tune the mutation rate 68 | std::vector mutations; 69 | }; 70 | 71 | #endif // AGENT_H 72 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(scriptbots) 2 | cmake_minimum_required(VERSION 2.8) 3 | find_package(OpenGL REQUIRED) 4 | find_package(GLUT REQUIRED) 5 | 6 | if (WIN32 AND NOT GLUT_FOUND) 7 | find_library(GLUT32_LIBRARY NAMES glut32 PATHS ${CMAKE_CURRENT_SOURCE_DIR}) 8 | SET (LOCAL_GLUT32 1) 9 | endif() 10 | 11 | find_package(OpenMP) 12 | 13 | if (OPENMP_FOUND) 14 | SET (HAVE_OPENMP 1) 15 | SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 16 | SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 17 | endif() 18 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) 19 | 20 | include_directories(${CMAKE_CURRENT_BINARY_DIR} ${OPENGL_INCLUDE_DIRS} ${GLUT_INCLUDE_DIRS}) 21 | 22 | set( SB_SRCS 23 | View.cpp 24 | GLView.cpp 25 | main.cpp 26 | DWRAONBrain.cpp 27 | Agent.cpp 28 | World.cpp 29 | vmath.cpp ) 30 | 31 | add_executable(scriptbots ${SB_SRCS}) 32 | 33 | if (WIN32 AND NOT GLUT_FOUND) 34 | target_link_libraries(scriptbots ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${GLUT32_LIBRARY}) 35 | else() 36 | target_link_libraries(scriptbots ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES}) 37 | endif() 38 | 39 | # copy glut32.dll to the output dirs 40 | # not sure how msvc could be true and win32 not, but just in case.. 41 | if (MSVC AND WIN32 AND NOT GLUT_FOUND) 42 | file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/Debug) 43 | file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/Release) 44 | file(COPY glut32.dll DESTINATION ${PROJECT_BINARY_DIR}/Debug) 45 | file(COPY glut32.dll DESTINATION ${PROJECT_BINARY_DIR}/Release) 46 | endif() 47 | 48 | -------------------------------------------------------------------------------- /DWRAONBrain.cpp: -------------------------------------------------------------------------------- 1 | #include "DWRAONBrain.h" 2 | using namespace std; 3 | 4 | 5 | Box::Box() 6 | { 7 | 8 | w.resize(CONNS,0); 9 | id.resize(CONNS,0); 10 | notted.resize(CONNS,0); 11 | 12 | //constructor 13 | for (int i=0;i0.5)?(0):(1); 21 | kp= randf(0.8,1); 22 | bias= randf(-1,1); 23 | 24 | out=0; 25 | target=0; 26 | } 27 | 28 | DWRAONBrain::DWRAONBrain() 29 | { 30 | 31 | //constructor 32 | for (int i=0;i& in, vector< float >& out) 80 | { 81 | 82 | //do a single tick of the brain 83 | 84 | //take first few boxes and set their out to in[]. 85 | for (int i=0;itype==0) { 94 | 95 | //AND NODE 96 | float res=1; 97 | for (int j=0;jid[j]; 99 | float val= boxes[idx].out; 100 | if (abox->notted[j]) val= 1-val; 101 | //res= res * pow(val, abox->w[j]); 102 | res= res * val; 103 | } 104 | res*= abox->bias; 105 | abox->target= res; 106 | 107 | } else { 108 | 109 | //OR NODE 110 | float res=0; 111 | for (int j=0;jid[j]; 113 | float val= boxes[idx].out; 114 | if (abox->notted[j]) val= 1-val; 115 | res= res + val*abox->w[j]; 116 | } 117 | res+= abox->bias; 118 | abox->target= res; 119 | } 120 | 121 | //clamp target 122 | if (abox->target<0) abox->target=0; 123 | if (abox->target>1) abox->target=1; 124 | } 125 | 126 | //make all boxes go a bit toward target 127 | for (int i=INPUTSIZE;iout =abox->out + (abox->target-abox->out)*abox->kp; 130 | } 131 | 132 | //finally set out[] to the last few boxes output 133 | for (int i=0;i1) boxes[j].kp=1; 151 | // a2.mutations.push_back("kp jiggled\n"); 152 | } 153 | 154 | if (randf(0,1)boxes[i].bias : other.boxes[i].bias; 190 | newbrain.boxes[i].kp= randf(0,1)<0.5 ? this->boxes[i].kp : other.boxes[i].kp; 191 | newbrain.boxes[i].type= randf(0,1)<0.5 ? this->boxes[i].type : other.boxes[i].type; 192 | 193 | for (int j=0;jboxes[i].id[j] : other.boxes[i].id[j]; 195 | newbrain.boxes[i].notted[j] = randf(0,1)<0.5 ? this->boxes[i].notted[j] : other.boxes[i].notted[j]; 196 | newbrain.boxes[i].w[j] = randf(0,1)<0.5 ? this->boxes[i].w[j] : other.boxes[i].w[j]; 197 | } 198 | } 199 | return newbrain; 200 | } 201 | 202 | -------------------------------------------------------------------------------- /DWRAONBrain.h: -------------------------------------------------------------------------------- 1 | #ifndef DWRAONBRAIN_H 2 | #define DWRAONBRAIN_H 3 | 4 | #include "settings.h" 5 | #include "helpers.h" 6 | 7 | #include 8 | 9 | #define INPUTSIZE 20 10 | #define OUTPUTSIZE 9 11 | 12 | #define BRAINSIZE 100 13 | #define CONNS 3 14 | 15 | 16 | class Box { 17 | public: 18 | 19 | Box(); 20 | 21 | //props 22 | int type; //0: AND, 1:OR 23 | float kp; //kp: damping strength 24 | std::vector w; //weight of each connecting box (in [0,inf] 25 | std::vector id; //id in boxes[] of the connecting box 26 | /* changed from to because vector doesn't 27 | have true random access, and thus slows the simulation to a crawl. 28 | http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=98 29 | It still stores boolean values at the cost of space overhead, 30 | but with a significant speed improvement. 31 | */ 32 | std::vector notted; //is this input notted before coming in? 33 | float bias; 34 | 35 | //state variables 36 | float target; //target value this node is going toward 37 | float out; //current output, and history. 0 is farthest back. -1 is latest 38 | 39 | 40 | }; 41 | /** 42 | * Damped Weighted Recurrent AND/OR Network 43 | */ 44 | class DWRAONBrain 45 | { 46 | public: 47 | 48 | std::vector boxes; 49 | 50 | DWRAONBrain(); 51 | DWRAONBrain(const DWRAONBrain &other); 52 | virtual DWRAONBrain& operator=(const DWRAONBrain& other); 53 | 54 | void tick(std::vector& in, std::vector& out); 55 | void mutate(float MR, float MR2); 56 | DWRAONBrain crossover( const DWRAONBrain &other ); 57 | private: 58 | void init(); 59 | }; 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /GLView.cpp: -------------------------------------------------------------------------------- 1 | #include "GLView.h" 2 | #include 3 | #include "config.h" 4 | #ifdef LOCAL_GLUT32 5 | #include "glut.h" 6 | #else 7 | #include 8 | #endif 9 | 10 | #include 11 | 12 | void gl_processNormalKeys(unsigned char key, int x, int y) 13 | { 14 | GLVIEW->processNormalKeys(key, x, y); 15 | } 16 | void gl_changeSize(int w, int h) 17 | { 18 | GLVIEW->changeSize(w,h); 19 | } 20 | void gl_handleIdle() 21 | { 22 | GLVIEW->handleIdle(); 23 | } 24 | void gl_processMouse(int button, int state, int x, int y) 25 | { 26 | GLVIEW->processMouse(button, state, x, y); 27 | } 28 | void gl_processMouseActiveMotion(int x, int y) 29 | { 30 | GLVIEW->processMouseActiveMotion(x,y); 31 | } 32 | void gl_renderScene() 33 | { 34 | GLVIEW->renderScene(); 35 | } 36 | 37 | 38 | void RenderString(float x, float y, void *font, const char* string, float r, float g, float b) 39 | { 40 | glColor3f(r,g,b); 41 | glRasterPos2f(x, y); 42 | int len = (int) strlen(string); 43 | for (int i = 0; i < len; i++) 44 | glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, string[i]); 45 | } 46 | 47 | void drawCircle(float x, float y, float r) { 48 | float n; 49 | for (int k=0;k<17;k++) { 50 | n = k*(M_PI/8); 51 | glVertex3f(x+r*sin(n),y+r*cos(n),0); 52 | } 53 | } 54 | 55 | 56 | GLView::GLView(World *s) : 57 | world(world), 58 | paused(false), 59 | draw(true), 60 | skipdraw(1), 61 | drawfood(true), 62 | modcounter(0), 63 | frames(0), 64 | lastUpdate(0) 65 | { 66 | 67 | } 68 | 69 | GLView::~GLView() 70 | { 71 | 72 | } 73 | void GLView::changeSize(int w, int h) 74 | { 75 | // Reset the coordinate system before modifying 76 | glMatrixMode(GL_PROJECTION); 77 | glLoadIdentity(); 78 | glOrtho(0,conf::WWIDTH,conf::WHEIGHT,0,0,1); 79 | } 80 | 81 | // class UnderMousePredicate { 82 | // UnderMousePredicate(int x, int y) : X(x), Y(y) {} 83 | // 84 | // bool operator()(Agent a) { 85 | // float mind=1e10; 86 | // float d; 87 | // d= pow(X-a.pos.x,2)+pow(Y-a.pos.y,2); 88 | // if (dreset(); 131 | printf("Agents reset\n"); 132 | } else if (key=='p') { 133 | //pause 134 | paused= !paused; 135 | } else if (key=='d') { 136 | //drawing 137 | draw= !draw; 138 | } else if (key==43) { 139 | //+ 140 | skipdraw++; 141 | 142 | } else if (key==45) { 143 | //- 144 | skipdraw--; 145 | } else if (key=='f') { 146 | drawfood=!drawfood; 147 | } else if (key=='c') { 148 | world->setClosed( !world->isClosed() ); 149 | printf("Environemt closed now= %b\n",world->isClosed()); 150 | } else { 151 | printf("Unknown key pressed: %i\n", key); 152 | } 153 | } 154 | 155 | void GLView::handleIdle() 156 | { 157 | modcounter++; 158 | if (!paused) world->update(); 159 | 160 | //show FPS 161 | int currentTime = glutGet( GLUT_ELAPSED_TIME ); 162 | frames++; 163 | if ((currentTime - lastUpdate) >= 1000) { 164 | std::pair num_herbs_carns = world->numHerbCarnivores(); 165 | sprintf( buf, "FPS: %d NumAgents: %d Carnivors: %d Herbivors: %d Epoch: %d", frames, world->numAgents(), num_herbs_carns.second, num_herbs_carns.first, world->epoch() ); 166 | glutSetWindowTitle( buf ); 167 | frames = 0; 168 | lastUpdate = currentTime; 169 | } 170 | if (skipdraw<=0 && draw) { 171 | clock_t endwait; 172 | float mult=-0.005*(skipdraw-1); //ugly, ah well 173 | endwait = clock () + mult * CLOCKS_PER_SEC ; 174 | while (clock() < endwait) {} 175 | } 176 | 177 | if (draw) { 178 | if (skipdraw>0) { 179 | if (modcounter%skipdraw==0) renderScene(); //increase fps by skipping drawing 180 | } 181 | else renderScene(); //we will decrease fps by waiting using clocks 182 | } 183 | 184 | } 185 | 186 | void GLView::renderScene() 187 | { 188 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 189 | glPushMatrix(); 190 | 191 | world->draw(this, drawfood); 192 | 193 | glPopMatrix(); 194 | glutSwapBuffers(); 195 | } 196 | 197 | void GLView::drawAgent(const Agent& agent) 198 | { 199 | float n; 200 | float r= conf::BOTRADIUS; 201 | float rp= conf::BOTRADIUS+2; 202 | //handle selected agent 203 | if (agent.selectflag>0) { 204 | 205 | //draw selection 206 | glBegin(GL_POLYGON); 207 | glColor3f(1,1,0); 208 | drawCircle(agent.pos.x, agent.pos.y, conf::BOTRADIUS+5); 209 | glEnd(); 210 | 211 | glPushMatrix(); 212 | glTranslatef(agent.pos.x-80,agent.pos.y+20,0); 213 | //draw inputs, outputs 214 | float col; 215 | float yy=15; 216 | float xx=15; 217 | float ss=16; 218 | glBegin(GL_QUADS); 219 | for (int j=0;j0) glColor3f(0,mag,0); //draw boost as green outline 263 | else glColor3f(mag,0,0); 264 | for (int k=0;k<17;k++){ 265 | n = k*(M_PI/8); 266 | glVertex3f(agent.pos.x+rp*sin(n),agent.pos.y+rp*cos(n),0); 267 | n = (k+1)*(M_PI/8); 268 | glVertex3f(agent.pos.x+rp*sin(n),agent.pos.y+rp*cos(n),0); 269 | } 270 | glEnd(); 271 | } 272 | 273 | //TODO Fix event drawing 274 | //draw indicator of this agent... used for various events 275 | // if (agent.indicator>0) { 276 | // glBegin(GL_POLYGON); 277 | // glColor3f(agent.ir,agent.ig,agent.ib); 278 | // drawCircle(agent.pos.x, agent.pos.y, conf::BOTRADIUS+((int)agent.indicator)); 279 | // glEnd(); 280 | // agent.indicator-=1; 281 | // } 282 | 283 | //viewcone of this agent 284 | glBegin(GL_LINES); 285 | //and view cones 286 | glColor3f(0.5,0.5,0.5); 287 | for (int j=-2;j<3;j++) { 288 | if (j==0)continue; 289 | glVertex3f(agent.pos.x,agent.pos.y,0); 290 | glVertex3f(agent.pos.x+(conf::BOTRADIUS*4)*cos(agent.angle+j*M_PI/8),agent.pos.y+(conf::BOTRADIUS*4)*sin(agent.angle+j*M_PI/8),0); 291 | } 292 | //and eye to the back 293 | glVertex3f(agent.pos.x,agent.pos.y,0); 294 | glVertex3f(agent.pos.x+(conf::BOTRADIUS*1.5)*cos(agent.angle+M_PI+3*M_PI/16),agent.pos.y+(conf::BOTRADIUS*1.5)*sin(agent.angle+M_PI+3*M_PI/16),0); 295 | glVertex3f(agent.pos.x,agent.pos.y,0); 296 | glVertex3f(agent.pos.x+(conf::BOTRADIUS*1.5)*cos(agent.angle+M_PI-3*M_PI/16),agent.pos.y+(conf::BOTRADIUS*1.5)*sin(agent.angle+M_PI-3*M_PI/16),0); 297 | glEnd(); 298 | 299 | glBegin(GL_POLYGON); //body 300 | glColor3f(agent.red,agent.gre,agent.blu); 301 | drawCircle(agent.pos.x, agent.pos.y, conf::BOTRADIUS); 302 | glEnd(); 303 | 304 | glBegin(GL_LINES); 305 | //outline 306 | if (agent.boost) glColor3f(0.8,0,0); //draw boost as green outline 307 | else glColor3f(0,0,0); 308 | 309 | for (int k=0;k<17;k++) 310 | { 311 | n = k*(M_PI/8); 312 | glVertex3f(agent.pos.x+r*sin(n),agent.pos.y+r*cos(n),0); 313 | n = (k+1)*(M_PI/8); 314 | glVertex3f(agent.pos.x+r*sin(n),agent.pos.y+r*cos(n),0); 315 | } 316 | //and spike 317 | glColor3f(0.5,0,0); 318 | glVertex3f(agent.pos.x,agent.pos.y,0); 319 | glVertex3f(agent.pos.x+(3*r*agent.spikeLength)*cos(agent.angle),agent.pos.y+(3*r*agent.spikeLength)*sin(agent.angle),0); 320 | glEnd(); 321 | 322 | //and health 323 | int xo=18; 324 | int yo=-15; 325 | glBegin(GL_QUADS); 326 | //black background 327 | glColor3f(0,0,0); 328 | glVertex3f(agent.pos.x+xo,agent.pos.y+yo,0); 329 | glVertex3f(agent.pos.x+xo+5,agent.pos.y+yo,0); 330 | glVertex3f(agent.pos.x+xo+5,agent.pos.y+yo+40,0); 331 | glVertex3f(agent.pos.x+xo,agent.pos.y+yo+40,0); 332 | 333 | //health 334 | glColor3f(0,0.8,0); 335 | glVertex3f(agent.pos.x+xo,agent.pos.y+yo+20*(2-agent.health),0); 336 | glVertex3f(agent.pos.x+xo+5,agent.pos.y+yo+20*(2-agent.health),0); 337 | glVertex3f(agent.pos.x+xo+5,agent.pos.y+yo+40,0); 338 | glVertex3f(agent.pos.x+xo,agent.pos.y+yo+40,0); 339 | 340 | //if this is a hybrid, we want to put a marker down 341 | if (agent.hybrid) { 342 | glColor3f(0,0,0.8); 343 | glVertex3f(agent.pos.x+xo+6,agent.pos.y+yo,0); 344 | glVertex3f(agent.pos.x+xo+12,agent.pos.y+yo,0); 345 | glVertex3f(agent.pos.x+xo+12,agent.pos.y+yo+10,0); 346 | glVertex3f(agent.pos.x+xo+6,agent.pos.y+yo+10,0); 347 | } 348 | 349 | glColor3f(1-agent.herbivore,agent.herbivore,0); 350 | glVertex3f(agent.pos.x+xo+6,agent.pos.y+yo+12,0); 351 | glVertex3f(agent.pos.x+xo+12,agent.pos.y+yo+12,0); 352 | glVertex3f(agent.pos.x+xo+12,agent.pos.y+yo+22,0); 353 | glVertex3f(agent.pos.x+xo+6,agent.pos.y+yo+22,0); 354 | 355 | //how much sound is this bot making? 356 | glColor3f(agent.soundmul,agent.soundmul,agent.soundmul); 357 | glVertex3f(agent.pos.x+xo+6,agent.pos.y+yo+24,0); 358 | glVertex3f(agent.pos.x+xo+12,agent.pos.y+yo+24,0); 359 | glVertex3f(agent.pos.x+xo+12,agent.pos.y+yo+34,0); 360 | glVertex3f(agent.pos.x+xo+6,agent.pos.y+yo+34,0); 361 | 362 | //draw giving/receiving 363 | if (agent.dfood!=0) { 364 | 365 | float mag=cap(abs(agent.dfood)/conf::FOODTRANSFER/3); 366 | if (agent.dfood>0) glColor3f(0,mag,0); //draw boost as green outline 367 | else glColor3f(mag,0,0); 368 | glVertex3f(agent.pos.x+xo+6,agent.pos.y+yo+36,0); 369 | glVertex3f(agent.pos.x+xo+12,agent.pos.y+yo+36,0); 370 | glVertex3f(agent.pos.x+xo+12,agent.pos.y+yo+46,0); 371 | glVertex3f(agent.pos.x+xo+6,agent.pos.y+yo+46,0); 372 | } 373 | 374 | 375 | glEnd(); 376 | 377 | //print stats 378 | //generation count 379 | sprintf(buf2, "%i", agent.gencount); 380 | RenderString(agent.pos.x-conf::BOTRADIUS*1.5, agent.pos.y+conf::BOTRADIUS*1.8, GLUT_BITMAP_TIMES_ROMAN_24, buf2, 0.0f, 0.0f, 0.0f); 381 | //age 382 | sprintf(buf2, "%i", agent.age); 383 | RenderString(agent.pos.x-conf::BOTRADIUS*1.5, agent.pos.y+conf::BOTRADIUS*1.8+12, GLUT_BITMAP_TIMES_ROMAN_24, buf2, 0.0f, 0.0f, 0.0f); 384 | 385 | //health 386 | sprintf(buf2, "%.2f", agent.health); 387 | RenderString(agent.pos.x-conf::BOTRADIUS*1.5, agent.pos.y+conf::BOTRADIUS*1.8+24, GLUT_BITMAP_TIMES_ROMAN_24, buf2, 0.0f, 0.0f, 0.0f); 388 | 389 | //repcounter 390 | sprintf(buf2, "%.2f", agent.repcounter); 391 | RenderString(agent.pos.x-conf::BOTRADIUS*1.5, agent.pos.y+conf::BOTRADIUS*1.8+36, GLUT_BITMAP_TIMES_ROMAN_24, buf2, 0.0f, 0.0f, 0.0f); 392 | } 393 | 394 | void GLView::drawFood(int x, int y, float quantity) 395 | { 396 | //draw food 397 | if (drawfood) { 398 | glBegin(GL_QUADS); 399 | glColor3f(0.9-quantity,0.9-quantity,1.0-quantity); 400 | glVertex3f(x*conf::CZ,y*conf::CZ,0); 401 | glVertex3f(x*conf::CZ+conf::CZ,y*conf::CZ,0); 402 | glVertex3f(x*conf::CZ+conf::CZ,y*conf::CZ+conf::CZ,0); 403 | glVertex3f(x*conf::CZ,y*conf::CZ+conf::CZ,0); 404 | glEnd(); 405 | } 406 | } 407 | 408 | void GLView::setWorld(World* w) 409 | { 410 | world = w; 411 | } 412 | -------------------------------------------------------------------------------- /GLView.h: -------------------------------------------------------------------------------- 1 | #ifndef GLVIEW_H 2 | #define GLVIEW_H 3 | 4 | 5 | #include "View.h" 6 | #include "World.h" 7 | 8 | class GLView; 9 | 10 | extern GLView* GLVIEW; 11 | 12 | void gl_processNormalKeys(unsigned char key, int x, int y); 13 | void gl_processMouse(int button, int state, int x, int y); 14 | void gl_processMouseActiveMotion(int x, int y); 15 | void gl_changeSize(int w, int h); 16 | void gl_handleIdle(); 17 | void gl_renderScene(); 18 | 19 | class GLView : public View 20 | { 21 | 22 | public: 23 | GLView(World* w); 24 | virtual ~GLView(); 25 | 26 | virtual void drawAgent(const Agent &a); 27 | virtual void drawFood(int x, int y, float quantity); 28 | 29 | void setWorld(World* w); 30 | 31 | //GLUT functions 32 | void processNormalKeys(unsigned char key, int x, int y); 33 | void processMouse(int button, int state, int x, int y); 34 | void processMouseActiveMotion(int x, int y); 35 | void changeSize(int w, int h); 36 | void handleIdle(); 37 | void renderScene(); 38 | 39 | private: 40 | 41 | World *world; 42 | bool paused; 43 | bool draw; 44 | int skipdraw; 45 | bool drawfood; 46 | char buf[100]; 47 | char buf2[10]; 48 | int modcounter; 49 | int lastUpdate; 50 | int frames; 51 | 52 | }; 53 | 54 | #endif // GLVIEW_H 55 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | SCRIPTBOTS 2 | ========== 3 | * Author: Andrej Karpathy 4 | * License: Do whatever you want with this code 5 | 6 | Project website: 7 | (https://sites.google.com/site/scriptbotsevo/home) 8 | 9 | Mailing List / Forum: 10 | (http://groups.google.com/group/scriptbots/topics) 11 | 12 | Older project website (just in case): 13 | (http://code.google.com/p/scriptbots/) 14 | 15 | BUILDING 16 | --------- 17 | 18 | To compile scriptbots you will need: 19 | 20 | * CMake >= 2.8 (http://www.cmake.org/cmake/resources/software.html) 21 | * OpenGL and GLUT (http://www.opengl.org/resources/libraries/glut/) 22 | * * Linux: freeglut (http://freeglut.sourceforge.net/) 23 | 24 | It will use OpenMP to speed up everything, in case you have multicore cpu. 25 | 26 | If you are on Ubuntu (or debian) you can install all the dependencies with: 27 | 28 | $ apt-get install cmake build-essential libopenmpi-dev libglut32-dev libxi-dev libxmu-dev 29 | 30 | To build ScriptBots on Linux: 31 | 32 | $ cd path/to/source 33 | $ mkdir build 34 | $ cd build 35 | $ cmake ../ # this is the equiv of ./configure 36 | $ make 37 | 38 | To execute ScriptBots simply type the following in the build directory: 39 | 40 | $ ./scriptbots 41 | 42 | For Windows: 43 | 44 | Follow basically the same steps, but after running cmake open up the VS solution (.sln) file it generates and compile the project from VS. 45 | 46 | 47 | USAGE 48 | ------ 49 | 50 | Follow the above instructions to compile then run the program. 51 | 52 | Hit 'd' to make it go MUCH FASTER (and not draw). Speed can also be controlled with + and -. 53 | 54 | 55 | QUESTIONS COMMENTS are best posted at the google group, available on project site 56 | or contact me at andrej.karpathy@gmail.com 57 | 58 | Contributors: 59 | 60 | * Casey Link 61 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | SCRIPTBOTS 2 | Author: Andrej Karpathy 3 | License: Do whatever you want with this code 4 | 5 | Project website: 6 | https://sites.google.com/site/scriptbotsevo/home 7 | 8 | Older project website (just in case) 9 | http://code.google.com/p/scriptbots/ 10 | 11 | ------------------------------------------------------ 12 | BUILDING: 13 | 14 | To compile scriptbots you will need: 15 | * CMake >= 2.8 (http://www.cmake.org/cmake/resources/software.html) 16 | * OpenGL and GLUT (http://www.opengl.org/resources/libraries/glut/) 17 | * * Linux: freeglut (http://freeglut.sourceforge.net/) 18 | 19 | Can use OpenMP to speed up everything, in case you have multicore cpu 20 | 21 | If you are on Ubuntu (or debian) you can install all the dependencies with: 22 | $ apt-get install cmake build-essential libopenmpi-dev libglut32-dev libxi-dev libxmu-dev 23 | 24 | To build ScriptBots on Linux: 25 | $ cd path/to/source 26 | $ mkdir build 27 | $ cd build 28 | $ cmake ../ # this is the equiv of ./configure 29 | $ make 30 | 31 | To execute ScriptBots simply type the following in the build directory: 32 | $ ./scriptbots 33 | 34 | For Windows: 35 | Follow basically the same steps, but after running cmake open up the VS solution (.sln) file it generates and compile the project from VS. 36 | 37 | 38 | --------------------------------------------------------- 39 | USAGE: 40 | 41 | Follow the above instructions to compile then run the program. Hit 'd' to make it go MUCH FASTER (and not draw). Speed can also be controlled with + and -. 42 | 43 | 44 | --------------------------------------------------------- 45 | QUESTIONS COMMENTS are best posted at the google group, available on project site 46 | or contact me at andrej.karpathy@gmail.com 47 | 48 | Contributors: 49 | Casey Link 50 | -------------------------------------------------------------------------------- /View.cpp: -------------------------------------------------------------------------------- 1 | #include "View.h" 2 | 3 | -------------------------------------------------------------------------------- /View.h: -------------------------------------------------------------------------------- 1 | #ifndef VIEW_H 2 | #define VIEW_H 3 | 4 | #include "Agent.h" 5 | class View 6 | { 7 | public: 8 | virtual void drawAgent(const Agent &a) = 0; 9 | virtual void drawFood(int x, int y, float quantity) = 0; 10 | }; 11 | 12 | #endif // VIEW_H 13 | -------------------------------------------------------------------------------- /World.cpp: -------------------------------------------------------------------------------- 1 | #include "World.h" 2 | 3 | #include 4 | 5 | #include "settings.h" 6 | #include "helpers.h" 7 | #include "vmath.h" 8 | 9 | using namespace std; 10 | 11 | World::World() : 12 | modcounter(0), 13 | current_epoch(0), 14 | idcounter(0), 15 | FW(conf::WIDTH/conf::CZ), 16 | FH(conf::HEIGHT/conf::CZ), 17 | CLOSED(false) 18 | { 19 | addRandomBots(conf::NUMBOTS); 20 | //inititalize food layer 21 | 22 | for (int x=0;x=10000) { 42 | modcounter=0; 43 | current_epoch++; 44 | } 45 | if (modcounter%conf::FOODADDFREQ==0) { 46 | fx=randi(0,FW); 47 | fy=randi(0,FH); 48 | food[fx][fy]= conf::FOODMAX; 49 | } 50 | 51 | //give input to every agent. Sets in[] array 52 | setInputs(); 53 | 54 | //brains tick. computes in[] -> out[] 55 | brainsTick(); 56 | 57 | //read output and process consequences of bots on environment. requires out[] 58 | processOutputs(); 59 | 60 | //process bots: health and deaths 61 | for (int i=0;i0) { 83 | float d= (agents[i].pos-agents[j].pos).length(); 84 | if (d0) { 90 | //distribute its food evenly 91 | for (int j=0;j0 && agents[j].herbivore<0.7) { 93 | float d= (agents[i].pos-agents[j].pos).length(); 94 | if (d2) agents[j].health=2; //cap it! 98 | agents[j].initEvent(30,1,1,1); //white means they ate! nice 99 | } 100 | } 101 | } 102 | } 103 | 104 | } 105 | } 106 | vector::iterator iter= agents.begin(); 107 | while (iter != agents.end()) { 108 | if (iter->health <=0) { 109 | iter= agents.erase(iter); 110 | } else { 111 | ++iter; 112 | } 113 | } 114 | 115 | //handle reproduction 116 | for (int i=0;i0.65) { //agent is healthy and is ready to reproduce 118 | //agents[i].health= 0.8; //the agent is left vulnerable and weak, a bit 119 | reproduce(i, agents[i].MUTRATE1, agents[i].MUTRATE2); //this adds conf::BABIES new agents to agents[] 120 | agents[i].repcounter= agents[i].herbivore*randf(conf::REPRATEH-0.1,conf::REPRATEH+0.1) + (1-agents[i].herbivore)*randf(conf::REPRATEC-0.1,conf::REPRATEC+0.1); 121 | } 122 | } 123 | 124 | //environment tick 125 | for (int x=0;xconf::FOODMAX)food[x][y]=conf::FOODMAX; //cap at conf::FOODMAX 129 | } 130 | } 131 | 132 | //add new agents, if environment isn't closed 133 | if (!CLOSED) { 134 | //make sure environment is always populated with at least NUMBOTS bots 135 | if (agents.size()in[11]= cap(a->health/2); //divide by 2 since health is in [0,2] 163 | 164 | //FOOD 165 | int cx= (int) a->pos.x/conf::CZ; 166 | int cy= (int) a->pos.y/conf::CZ; 167 | a->in[4]= food[cx][cy]/conf::FOODMAX; 168 | 169 | //SOUND SMELL EYES 170 | float p1,r1,g1,b1,p2,r2,g2,b2,p3,r3,g3,b3; 171 | p1=0; 172 | r1=0; 173 | g1=0; 174 | b1=0; 175 | p2=0; 176 | r2=0; 177 | g2=0; 178 | b2=0; 179 | p3=0; 180 | r3=0; 181 | g3=0; 182 | b3=0; 183 | float soaccum=0; 184 | float smaccum=0; 185 | float hearaccum=0; 186 | 187 | //BLOOD ESTIMATOR 188 | float blood= 0; 189 | 190 | for (int j=0;jpos.xpos.x-conf::DIST || a->pos.x>a2->pos.x+conf::DIST 195 | || a->pos.y>a2->pos.y+conf::DIST || a->pos.ypos.y-conf::DIST) continue; 196 | 197 | float d= (a->pos-a2->pos).length(); 198 | 199 | if (dw1),fabs(a2->w2))); 206 | 207 | //hearing. Listening to other agents 208 | hearaccum+= a2->soundmul*(conf::DIST-d)/conf::DIST; 209 | 210 | float ang= (a2->pos- a->pos).get_angle(); //current angle between bots 211 | 212 | //left and right eyes 213 | float leyeangle= a->angle - PI8; 214 | float reyeangle= a->angle + PI8; 215 | float backangle= a->angle + M_PI; 216 | float forwangle= a->angle; 217 | if (leyeangle<-M_PI) leyeangle+= 2*M_PI; 218 | if (reyeangle>M_PI) reyeangle-= 2*M_PI; 219 | if (backangle>M_PI) backangle-= 2*M_PI; 220 | float diff1= leyeangle- ang; 221 | if (fabs(diff1)>M_PI) diff1= 2*M_PI- fabs(diff1); 222 | diff1= fabs(diff1); 223 | float diff2= reyeangle- ang; 224 | if (fabs(diff2)>M_PI) diff2= 2*M_PI- fabs(diff2); 225 | diff2= fabs(diff2); 226 | float diff3= backangle- ang; 227 | if (fabs(diff3)>M_PI) diff3= 2*M_PI- fabs(diff3); 228 | diff3= fabs(diff3); 229 | float diff4= forwangle- ang; 230 | if (fabs(forwangle)>M_PI) diff4= 2*M_PI- fabs(forwangle); 231 | diff4= fabs(diff4); 232 | 233 | if (diff1red; 239 | g1 += mul1*a2->gre; 240 | b1 += mul1*a2->blu; 241 | } 242 | 243 | if (diff2red; 249 | g2 += mul2*a2->gre; 250 | b2 += mul2*a2->blu; 251 | } 252 | 253 | if (diff3red; 259 | g3 += mul3*a2->gre; 260 | b3 += mul3*a2->blu; 261 | } 262 | 263 | if (diff4in[0]= cap(p1); 273 | a->in[1]= cap(r1); 274 | a->in[2]= cap(g1); 275 | a->in[3]= cap(b1); 276 | a->in[5]= cap(p2); 277 | a->in[6]= cap(r2); 278 | a->in[7]= cap(g2); 279 | a->in[8]= cap(b2); 280 | a->in[9]= cap(soaccum); 281 | a->in[10]= cap(smaccum); 282 | a->in[12]= cap(p3); 283 | a->in[13]= cap(r3); 284 | a->in[14]= cap(g3); 285 | a->in[15]= cap(b3); 286 | a->in[16]= abs(sin(modcounter/a->clockf1)); 287 | a->in[17]= abs(sin(modcounter/a->clockf2)); 288 | a->in[18]= cap(hearaccum); 289 | a->in[19]= cap(blood); 290 | } 291 | } 292 | 293 | void World::processOutputs() 294 | { 295 | //assign meaning 296 | //LEFT RIGHT R G B SPIKE BOOST SOUND_MULTIPLIER GIVING 297 | // 0 1 2 3 4 5 6 7 8 298 | for (int i=0;ired= a->out[2]; 302 | a->gre= a->out[3]; 303 | a->blu= a->out[4]; 304 | a->w1= a->out[0]; //-(2*a->out[0]-1); 305 | a->w2= a->out[1]; //-(2*a->out[1]-1); 306 | a->boost= a->out[6]>0.5; 307 | a->soundmul= a->out[7]; 308 | a->give= a->out[8]; 309 | 310 | //spike length should slowly tend towards out[5] 311 | float g= a->out[5]; 312 | if (a->spikeLengthspikeLength+=conf::SPIKESPEED; 314 | else if (a->spikeLength>g) 315 | a->spikeLength= g; //its easy to retract spike, just hard to put it up 316 | } 317 | 318 | //move bots 319 | //#pragma omp parallel for 320 | for (int i=0;iangle + M_PI/2); 325 | 326 | Vector2f w1p= a->pos+ v; //wheel positions 327 | Vector2f w2p= a->pos- v; 328 | 329 | float BW1= conf::BOTSPEED*a->w1; 330 | float BW2= conf::BOTSPEED*a->w2; 331 | if (a->boost) { 332 | BW1=BW1*conf::BOOSTSIZEMULT; 333 | } 334 | if (a->boost) { 335 | BW2=BW2*conf::BOOSTSIZEMULT; 336 | } 337 | 338 | //move bots 339 | Vector2f vv= w2p- a->pos; 340 | vv.rotate(-BW1); 341 | a->pos= w2p-vv; 342 | a->angle -= BW1; 343 | if (a->angle<-M_PI) a->angle= M_PI - (-M_PI-a->angle); 344 | vv= a->pos - w1p; 345 | vv.rotate(BW2); 346 | a->pos= w1p+vv; 347 | a->angle += BW2; 348 | if (a->angle>M_PI) a->angle= -M_PI + (a->angle-M_PI); 349 | 350 | //wrap around the map 351 | if (a->pos.x<0) a->pos.x= conf::WIDTH+a->pos.x; 352 | if (a->pos.x>=conf::WIDTH) a->pos.x= a->pos.x-conf::WIDTH; 353 | if (a->pos.y<0) a->pos.y= conf::HEIGHT+a->pos.y; 354 | if (a->pos.y>=conf::HEIGHT) a->pos.y= a->pos.y-conf::HEIGHT; 355 | } 356 | 357 | //process food intake for herbivors 358 | for (int i=0;i0 && agents[i].health<2) { 364 | //agent eats the food 365 | float itk=min(f,conf::FOODINTAKE); 366 | float speedmul= (1-(abs(agents[i].w1)+abs(agents[i].w2))/2)/2 + 0.5; 367 | itk= itk*agents[i].herbivore*agents[i].herbivore*speedmul; //herbivores gain more from ground food 368 | agents[i].health+= itk; 369 | agents[i].repcounter -= 3*itk; 370 | food[cx][cy]-= min(f,conf::FOODWASTE); 371 | } 372 | } 373 | 374 | //process giving and receiving of food 375 | for (int i=0;i0.5) { 380 | for (int j=0;j2) agents[i].health=2; //cap health at 2 414 | agents[i].spikeLength= 0; //retract spike back down 415 | 416 | agents[i].initEvent(40*DMG,1,1,0); //yellow event means bot has spiked other bot. nice! 417 | 418 | Vector2f v2(1,0); 419 | v2.rotate(agents[j].angle); 420 | float adiff= v.angle_between(v2); 421 | if (fabs(adiff) agents[i1].age && randf(0,1)<0.1) { 459 | i1= i; 460 | } 461 | if (agents[i].age > agents[i2].age && randf(0,1)<0.1 && i!=i1) { 462 | i2= i; 463 | } 464 | } 465 | 466 | Agent* a1= &agents[i1]; 467 | Agent* a2= &agents[i2]; 468 | 469 | 470 | //cross brains 471 | Agent anew = a1->crossover(*a2); 472 | 473 | 474 | //maybe do mutation here? I dont know. So far its only crossover 475 | anew.id= idcounter; 476 | idcounter++; 477 | agents.push_back(anew); 478 | } 479 | 480 | void World::reproduce(int ai, float MR, float MR2) 481 | { 482 | if (randf(0,1)<0.04) MR= MR*randf(1, 10); 483 | if (randf(0,1)<0.04) MR2= MR2*randf(1, 10); 484 | 485 | agents[ai].initEvent(30,0,0.8,0); //green event means agent reproduced. 486 | for (int i=0;iid, a2.id); //1 marks the event: child is born 497 | //fclose(fp); 498 | } 499 | } 500 | 501 | void World::writeReport() 502 | { 503 | //TODO fix reporting 504 | //save all kinds of nice data stuff 505 | // int numherb=0; 506 | // int numcarn=0; 507 | // int topcarn=0; 508 | // int topherb=0; 509 | // for(int i=0;i0.5) numherb++; 511 | // else numcarn++; 512 | // 513 | // if(agents[i].herbivore>0.5 && agents[i].gencount>topherb) topherb= agents[i].gencount; 514 | // if(agents[i].herbivore<0.5 && agents[i].gencount>topcarn) topcarn= agents[i].gencount; 515 | // } 516 | // 517 | // FILE* fp = fopen("report.txt", "a"); 518 | // fprintf(fp, "%i %i %i %i\n", numherb, numcarn, topcarn, topherb); 519 | // fclose(fp); 520 | } 521 | 522 | 523 | void World::reset() 524 | { 525 | agents.clear(); 526 | addRandomBots(conf::NUMBOTS); 527 | } 528 | 529 | void World::setClosed(bool close) 530 | { 531 | CLOSED = close; 532 | } 533 | 534 | bool World::isClosed() const 535 | { 536 | return CLOSED; 537 | } 538 | 539 | 540 | void World::draw(View* view, bool drawfood) 541 | { 542 | if(drawfood) { 543 | for(int i=0;idrawFood(i,j,f); 547 | } 548 | } 549 | } 550 | vector::const_iterator it; 551 | for ( it = agents.begin(); it != agents.end(); ++it) { 552 | view->drawAgent(*it); 553 | } 554 | 555 | } 556 | 557 | std::pair< int,int > World::numHerbCarnivores() const 558 | { 559 | int numherb=0; 560 | int numcarn=0; 561 | for (int i=0;i0.5) numherb++; 563 | else numcarn++; 564 | } 565 | 566 | return std::pair(numherb,numcarn); 567 | } 568 | 569 | int World::numAgents() const 570 | { 571 | return agents.size(); 572 | } 573 | 574 | int World::epoch() const 575 | { 576 | return current_epoch; 577 | } 578 | 579 | -------------------------------------------------------------------------------- /World.h: -------------------------------------------------------------------------------- 1 | #ifndef WORLD_H 2 | #define WORLD_H 3 | 4 | #include "View.h" 5 | #include "Agent.h" 6 | #include "settings.h" 7 | #include 8 | class World 9 | { 10 | public: 11 | World(); 12 | ~World(); 13 | 14 | void update(); 15 | void reset(); 16 | 17 | void draw(View* view, bool drawfood); 18 | 19 | bool isClosed() const; 20 | void setClosed(bool close); 21 | 22 | /** 23 | * Returns the number of herbivores and 24 | * carnivores in the world. 25 | * first : num herbs 26 | * second : num carns 27 | */ 28 | std::pair numHerbCarnivores() const; 29 | 30 | int numAgents() const; 31 | int epoch() const; 32 | 33 | private: 34 | void setInputs(); 35 | void processOutputs(); 36 | void brainsTick(); //takes in[] to out[] for every agent 37 | 38 | void writeReport(); 39 | 40 | void reproduce(int ai, float MR, float MR2); 41 | void addNewByCrossover(); 42 | void addRandomBots(int num); 43 | 44 | int modcounter; 45 | int current_epoch; 46 | int idcounter; 47 | 48 | std::vector agents; 49 | 50 | // food 51 | int FW; 52 | int FH; 53 | int fx; 54 | int fy; 55 | float food[conf::WIDTH/conf::CZ][conf::HEIGHT/conf::CZ]; 56 | bool CLOSED; //if environment is closed, then no random bots are added per time interval 57 | }; 58 | 59 | #endif // WORLD_H 60 | -------------------------------------------------------------------------------- /changes.txt: -------------------------------------------------------------------------------- 1 | (current) 2 | 3 | - Fixed compilation issues on Linux 4 | - Ported to CMake build system 5 | 6 | v1.2 changes (released 19 January 2011): 7 | 8 | - New Brain: DWRAON (Damped Weighted Recurrent AND/OR Network). This is better due to more continuous behavior than the old, discrete, rule based system. 9 | - No dichotomy of herbivore/carnivore. There is a stomach specialization variable between 0,1. At 0, specialized to process plants, at 1, meat. This trait is inherited and undergoes mutation. This also supports emergence of omnivores, which can process both, to a lesser degree. 10 | - Meat food is now only allocated when a creature dies, as opposed to when it is injured. It is distributed evenly to all nearby creatures when the kill occurs. This leads more clearly to emergence of hunting packs. 11 | - Ability to judge health of an organism in front was added. I think of it something as a blood sensor. Essentially, it fires if something wounded is ahead. This can make agents become selective when hunting. 12 | - More sensors were added: Two clock neurons that have time-varying activity at a some frequency that can be inherited. This is useful for introducing base activity into the brain, and also for giving agents a simple way to keep track of time, and do something at regular intervals. 13 | - Also, a hearing sensor was added that directly simulates sound. Agents can now shout at each other, but probably lack the capacity to temporally parse a shouting stream and create anything that resembles a non-trivial language. 14 | - Sound generator actuator was added, which simulates creating sound and corresponds to shouting. 15 | - Ability to share food was added. An agent can choose to give up its food to organisms around it. This potentially enables emergence of altruism: When a bot is too high in health, it may sense that there is one of its kind ahead that needs food, and choose to give it up. 16 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | #cmakedefine HAVE_OPENMP 2 | #cmakedefine LOCAL_GLUT32 3 | -------------------------------------------------------------------------------- /glut.h: -------------------------------------------------------------------------------- 1 | #ifndef __glut_h__ 2 | #define __glut_h__ 3 | 4 | /* Copyright (c) Mark J. Kilgard, 1994, 1995, 1996, 1998. */ 5 | 6 | /* This program is freely distributable without licensing fees and is 7 | provided without guarantee or warrantee expressed or implied. This 8 | program is -not- in the public domain. */ 9 | 10 | #if defined(_WIN32) 11 | 12 | /* GLUT 3.7 now tries to avoid including 13 | to avoid name space pollution, but Win32's 14 | needs APIENTRY and WINGDIAPI defined properly. */ 15 | # if 0 16 | # define WIN32_LEAN_AND_MEAN 17 | # include 18 | # else 19 | /* XXX This is from Win32's */ 20 | # ifndef APIENTRY 21 | # define GLUT_APIENTRY_DEFINED 22 | # if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) 23 | # define APIENTRY __stdcall 24 | # else 25 | # define APIENTRY 26 | # endif 27 | # endif 28 | /* XXX This is from Win32's */ 29 | # ifndef CALLBACK 30 | # if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) 31 | # define CALLBACK __stdcall 32 | # else 33 | # define CALLBACK 34 | # endif 35 | # endif 36 | /* XXX This is from Win32's and */ 37 | # ifndef WINGDIAPI 38 | # define GLUT_WINGDIAPI_DEFINED 39 | # define WINGDIAPI __declspec(dllimport) 40 | # endif 41 | /* XXX This is from Win32's */ 42 | # ifndef _WCHAR_T_DEFINED 43 | typedef unsigned short wchar_t; 44 | # define _WCHAR_T_DEFINED 45 | # endif 46 | # endif 47 | 48 | #pragma comment (lib, "winmm.lib") /* link with Windows MultiMedia lib */ 49 | #pragma comment (lib, "opengl32.lib") /* link with Microsoft OpenGL lib */ 50 | #pragma comment (lib, "glu32.lib") /* link with OpenGL Utility lib */ 51 | #pragma comment (lib, "glut32.lib") /* link with Win32 GLUT lib */ 52 | 53 | #pragma warning (disable:4244) /* Disable bogus conversion warnings. */ 54 | #pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */ 55 | 56 | #endif 57 | 58 | #include 59 | #include 60 | 61 | /* define APIENTRY and CALLBACK to null string if we aren't on Win32 */ 62 | #if !defined(_WIN32) 63 | #define APIENTRY 64 | #define GLUT_APIENTRY_DEFINED 65 | #define CALLBACK 66 | #endif 67 | 68 | #ifdef __cplusplus 69 | extern "C" { 70 | #endif 71 | 72 | /** 73 | GLUT API revision history: 74 | 75 | GLUT_API_VERSION is updated to reflect incompatible GLUT 76 | API changes (interface changes, semantic changes, deletions, 77 | or additions). 78 | 79 | GLUT_API_VERSION=1 First public release of GLUT. 11/29/94 80 | 81 | GLUT_API_VERSION=2 Added support for OpenGL/GLX multisampling, 82 | extension. Supports new input devices like tablet, dial and button 83 | box, and Spaceball. Easy to query OpenGL extensions. 84 | 85 | GLUT_API_VERSION=3 glutMenuStatus added. 86 | 87 | GLUT_API_VERSION=4 glutInitDisplayString, glutWarpPointer, 88 | glutBitmapLength, glutStrokeLength, glutWindowStatusFunc, dynamic 89 | video resize subAPI, glutPostWindowRedisplay, glutKeyboardUpFunc, 90 | glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat, 91 | glutJoystickFunc, glutForceJoystickFunc (NOT FINALIZED!). 92 | **/ 93 | #ifndef GLUT_API_VERSION /* allow this to be overriden */ 94 | #define GLUT_API_VERSION 3 95 | #endif 96 | 97 | /** 98 | GLUT implementation revision history: 99 | 100 | GLUT_XLIB_IMPLEMENTATION is updated to reflect both GLUT 101 | API revisions and implementation revisions (ie, bug fixes). 102 | 103 | GLUT_XLIB_IMPLEMENTATION=1 mjk's first public release of 104 | GLUT Xlib-based implementation. 11/29/94 105 | 106 | GLUT_XLIB_IMPLEMENTATION=2 mjk's second public release of 107 | GLUT Xlib-based implementation providing GLUT version 2 108 | interfaces. 109 | 110 | GLUT_XLIB_IMPLEMENTATION=3 mjk's GLUT 2.2 images. 4/17/95 111 | 112 | GLUT_XLIB_IMPLEMENTATION=4 mjk's GLUT 2.3 images. 6/?/95 113 | 114 | GLUT_XLIB_IMPLEMENTATION=5 mjk's GLUT 3.0 images. 10/?/95 115 | 116 | GLUT_XLIB_IMPLEMENTATION=7 mjk's GLUT 3.1+ with glutWarpPoitner. 7/24/96 117 | 118 | GLUT_XLIB_IMPLEMENTATION=8 mjk's GLUT 3.1+ with glutWarpPoitner 119 | and video resize. 1/3/97 120 | 121 | GLUT_XLIB_IMPLEMENTATION=9 mjk's GLUT 3.4 release with early GLUT 4 routines. 122 | 123 | GLUT_XLIB_IMPLEMENTATION=11 Mesa 2.5's GLUT 3.6 release. 124 | 125 | GLUT_XLIB_IMPLEMENTATION=12 mjk's GLUT 3.6 release with early GLUT 4 routines + signal handling. 126 | 127 | GLUT_XLIB_IMPLEMENTATION=13 mjk's GLUT 3.7 release with GameGLUT support. 128 | **/ 129 | #ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */ 130 | #define GLUT_XLIB_IMPLEMENTATION 13 131 | #endif 132 | 133 | /* Display mode bit masks. */ 134 | #define GLUT_RGB 0 135 | #define GLUT_RGBA GLUT_RGB 136 | #define GLUT_INDEX 1 137 | #define GLUT_SINGLE 0 138 | #define GLUT_DOUBLE 2 139 | #define GLUT_ACCUM 4 140 | #define GLUT_ALPHA 8 141 | #define GLUT_DEPTH 16 142 | #define GLUT_STENCIL 32 143 | #if (GLUT_API_VERSION >= 2) 144 | #define GLUT_MULTISAMPLE 128 145 | #define GLUT_STEREO 256 146 | #endif 147 | #if (GLUT_API_VERSION >= 3) 148 | #define GLUT_LUMINANCE 512 149 | #endif 150 | 151 | /* Mouse buttons. */ 152 | #define GLUT_LEFT_BUTTON 0 153 | #define GLUT_MIDDLE_BUTTON 1 154 | #define GLUT_RIGHT_BUTTON 2 155 | 156 | /* Mouse button state. */ 157 | #define GLUT_DOWN 0 158 | #define GLUT_UP 1 159 | 160 | #if (GLUT_API_VERSION >= 2) 161 | /* function keys */ 162 | #define GLUT_KEY_F1 1 163 | #define GLUT_KEY_F2 2 164 | #define GLUT_KEY_F3 3 165 | #define GLUT_KEY_F4 4 166 | #define GLUT_KEY_F5 5 167 | #define GLUT_KEY_F6 6 168 | #define GLUT_KEY_F7 7 169 | #define GLUT_KEY_F8 8 170 | #define GLUT_KEY_F9 9 171 | #define GLUT_KEY_F10 10 172 | #define GLUT_KEY_F11 11 173 | #define GLUT_KEY_F12 12 174 | /* directional keys */ 175 | #define GLUT_KEY_LEFT 100 176 | #define GLUT_KEY_UP 101 177 | #define GLUT_KEY_RIGHT 102 178 | #define GLUT_KEY_DOWN 103 179 | #define GLUT_KEY_PAGE_UP 104 180 | #define GLUT_KEY_PAGE_DOWN 105 181 | #define GLUT_KEY_HOME 106 182 | #define GLUT_KEY_END 107 183 | #define GLUT_KEY_INSERT 108 184 | #endif 185 | 186 | /* Entry/exit state. */ 187 | #define GLUT_LEFT 0 188 | #define GLUT_ENTERED 1 189 | 190 | /* Menu usage state. */ 191 | #define GLUT_MENU_NOT_IN_USE 0 192 | #define GLUT_MENU_IN_USE 1 193 | 194 | /* Visibility state. */ 195 | #define GLUT_NOT_VISIBLE 0 196 | #define GLUT_VISIBLE 1 197 | 198 | /* Window status state. */ 199 | #define GLUT_HIDDEN 0 200 | #define GLUT_FULLY_RETAINED 1 201 | #define GLUT_PARTIALLY_RETAINED 2 202 | #define GLUT_FULLY_COVERED 3 203 | 204 | /* Color index component selection values. */ 205 | #define GLUT_RED 0 206 | #define GLUT_GREEN 1 207 | #define GLUT_BLUE 2 208 | 209 | /* Layers for use. */ 210 | #define GLUT_NORMAL 0 211 | #define GLUT_OVERLAY 1 212 | 213 | #if defined(_WIN32) 214 | /* Stroke font constants (use these in GLUT program). */ 215 | #define GLUT_STROKE_ROMAN ((void*)0) 216 | #define GLUT_STROKE_MONO_ROMAN ((void*)1) 217 | 218 | /* Bitmap font constants (use these in GLUT program). */ 219 | #define GLUT_BITMAP_9_BY_15 ((void*)2) 220 | #define GLUT_BITMAP_8_BY_13 ((void*)3) 221 | #define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4) 222 | #define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5) 223 | #if (GLUT_API_VERSION >= 3) 224 | #define GLUT_BITMAP_HELVETICA_10 ((void*)6) 225 | #define GLUT_BITMAP_HELVETICA_12 ((void*)7) 226 | #define GLUT_BITMAP_HELVETICA_18 ((void*)8) 227 | #endif 228 | #else 229 | /* Stroke font opaque addresses (use constants instead in source code). */ 230 | extern void *glutStrokeRoman; 231 | extern void *glutStrokeMonoRoman; 232 | 233 | /* Stroke font constants (use these in GLUT program). */ 234 | #define GLUT_STROKE_ROMAN (&glutStrokeRoman) 235 | #define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman) 236 | 237 | /* Bitmap font opaque addresses (use constants instead in source code). */ 238 | extern void *glutBitmap9By15; 239 | extern void *glutBitmap8By13; 240 | extern void *glutBitmapTimesRoman10; 241 | extern void *glutBitmapTimesRoman24; 242 | extern void *glutBitmapHelvetica10; 243 | extern void *glutBitmapHelvetica12; 244 | extern void *glutBitmapHelvetica18; 245 | 246 | /* Bitmap font constants (use these in GLUT program). */ 247 | #define GLUT_BITMAP_9_BY_15 (&glutBitmap9By15) 248 | #define GLUT_BITMAP_8_BY_13 (&glutBitmap8By13) 249 | #define GLUT_BITMAP_TIMES_ROMAN_10 (&glutBitmapTimesRoman10) 250 | #define GLUT_BITMAP_TIMES_ROMAN_24 (&glutBitmapTimesRoman24) 251 | #if (GLUT_API_VERSION >= 3) 252 | #define GLUT_BITMAP_HELVETICA_10 (&glutBitmapHelvetica10) 253 | #define GLUT_BITMAP_HELVETICA_12 (&glutBitmapHelvetica12) 254 | #define GLUT_BITMAP_HELVETICA_18 (&glutBitmapHelvetica18) 255 | #endif 256 | #endif 257 | 258 | /* glutGet parameters. */ 259 | #define GLUT_WINDOW_X 100 260 | #define GLUT_WINDOW_Y 101 261 | #define GLUT_WINDOW_WIDTH 102 262 | #define GLUT_WINDOW_HEIGHT 103 263 | #define GLUT_WINDOW_BUFFER_SIZE 104 264 | #define GLUT_WINDOW_STENCIL_SIZE 105 265 | #define GLUT_WINDOW_DEPTH_SIZE 106 266 | #define GLUT_WINDOW_RED_SIZE 107 267 | #define GLUT_WINDOW_GREEN_SIZE 108 268 | #define GLUT_WINDOW_BLUE_SIZE 109 269 | #define GLUT_WINDOW_ALPHA_SIZE 110 270 | #define GLUT_WINDOW_ACCUM_RED_SIZE 111 271 | #define GLUT_WINDOW_ACCUM_GREEN_SIZE 112 272 | #define GLUT_WINDOW_ACCUM_BLUE_SIZE 113 273 | #define GLUT_WINDOW_ACCUM_ALPHA_SIZE 114 274 | #define GLUT_WINDOW_DOUBLEBUFFER 115 275 | #define GLUT_WINDOW_RGBA 116 276 | #define GLUT_WINDOW_PARENT 117 277 | #define GLUT_WINDOW_NUM_CHILDREN 118 278 | #define GLUT_WINDOW_COLORMAP_SIZE 119 279 | #if (GLUT_API_VERSION >= 2) 280 | #define GLUT_WINDOW_NUM_SAMPLES 120 281 | #define GLUT_WINDOW_STEREO 121 282 | #endif 283 | #if (GLUT_API_VERSION >= 3) 284 | #define GLUT_WINDOW_CURSOR 122 285 | #endif 286 | #define GLUT_SCREEN_WIDTH 200 287 | #define GLUT_SCREEN_HEIGHT 201 288 | #define GLUT_SCREEN_WIDTH_MM 202 289 | #define GLUT_SCREEN_HEIGHT_MM 203 290 | #define GLUT_MENU_NUM_ITEMS 300 291 | #define GLUT_DISPLAY_MODE_POSSIBLE 400 292 | #define GLUT_INIT_WINDOW_X 500 293 | #define GLUT_INIT_WINDOW_Y 501 294 | #define GLUT_INIT_WINDOW_WIDTH 502 295 | #define GLUT_INIT_WINDOW_HEIGHT 503 296 | #define GLUT_INIT_DISPLAY_MODE 504 297 | #if (GLUT_API_VERSION >= 2) 298 | #define GLUT_ELAPSED_TIME 700 299 | #endif 300 | #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) 301 | #define GLUT_WINDOW_FORMAT_ID 123 302 | #endif 303 | 304 | #if (GLUT_API_VERSION >= 2) 305 | /* glutDeviceGet parameters. */ 306 | #define GLUT_HAS_KEYBOARD 600 307 | #define GLUT_HAS_MOUSE 601 308 | #define GLUT_HAS_SPACEBALL 602 309 | #define GLUT_HAS_DIAL_AND_BUTTON_BOX 603 310 | #define GLUT_HAS_TABLET 604 311 | #define GLUT_NUM_MOUSE_BUTTONS 605 312 | #define GLUT_NUM_SPACEBALL_BUTTONS 606 313 | #define GLUT_NUM_BUTTON_BOX_BUTTONS 607 314 | #define GLUT_NUM_DIALS 608 315 | #define GLUT_NUM_TABLET_BUTTONS 609 316 | #endif 317 | #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) 318 | #define GLUT_DEVICE_IGNORE_KEY_REPEAT 610 319 | #define GLUT_DEVICE_KEY_REPEAT 611 320 | #define GLUT_HAS_JOYSTICK 612 321 | #define GLUT_OWNS_JOYSTICK 613 322 | #define GLUT_JOYSTICK_BUTTONS 614 323 | #define GLUT_JOYSTICK_AXES 615 324 | #define GLUT_JOYSTICK_POLL_RATE 616 325 | #endif 326 | 327 | #if (GLUT_API_VERSION >= 3) 328 | /* glutLayerGet parameters. */ 329 | #define GLUT_OVERLAY_POSSIBLE 800 330 | #define GLUT_LAYER_IN_USE 801 331 | #define GLUT_HAS_OVERLAY 802 332 | #define GLUT_TRANSPARENT_INDEX 803 333 | #define GLUT_NORMAL_DAMAGED 804 334 | #define GLUT_OVERLAY_DAMAGED 805 335 | 336 | #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) 337 | /* glutVideoResizeGet parameters. */ 338 | #define GLUT_VIDEO_RESIZE_POSSIBLE 900 339 | #define GLUT_VIDEO_RESIZE_IN_USE 901 340 | #define GLUT_VIDEO_RESIZE_X_DELTA 902 341 | #define GLUT_VIDEO_RESIZE_Y_DELTA 903 342 | #define GLUT_VIDEO_RESIZE_WIDTH_DELTA 904 343 | #define GLUT_VIDEO_RESIZE_HEIGHT_DELTA 905 344 | #define GLUT_VIDEO_RESIZE_X 906 345 | #define GLUT_VIDEO_RESIZE_Y 907 346 | #define GLUT_VIDEO_RESIZE_WIDTH 908 347 | #define GLUT_VIDEO_RESIZE_HEIGHT 909 348 | #endif 349 | 350 | /* glutUseLayer parameters. */ 351 | #define GLUT_NORMAL 0 352 | #define GLUT_OVERLAY 1 353 | 354 | /* glutGetModifiers return mask. */ 355 | #define GLUT_ACTIVE_SHIFT 1 356 | #define GLUT_ACTIVE_CTRL 2 357 | #define GLUT_ACTIVE_ALT 4 358 | 359 | /* glutSetCursor parameters. */ 360 | /* Basic arrows. */ 361 | #define GLUT_CURSOR_RIGHT_ARROW 0 362 | #define GLUT_CURSOR_LEFT_ARROW 1 363 | /* Symbolic cursor shapes. */ 364 | #define GLUT_CURSOR_INFO 2 365 | #define GLUT_CURSOR_DESTROY 3 366 | #define GLUT_CURSOR_HELP 4 367 | #define GLUT_CURSOR_CYCLE 5 368 | #define GLUT_CURSOR_SPRAY 6 369 | #define GLUT_CURSOR_WAIT 7 370 | #define GLUT_CURSOR_TEXT 8 371 | #define GLUT_CURSOR_CROSSHAIR 9 372 | /* Directional cursors. */ 373 | #define GLUT_CURSOR_UP_DOWN 10 374 | #define GLUT_CURSOR_LEFT_RIGHT 11 375 | /* Sizing cursors. */ 376 | #define GLUT_CURSOR_TOP_SIDE 12 377 | #define GLUT_CURSOR_BOTTOM_SIDE 13 378 | #define GLUT_CURSOR_LEFT_SIDE 14 379 | #define GLUT_CURSOR_RIGHT_SIDE 15 380 | #define GLUT_CURSOR_TOP_LEFT_CORNER 16 381 | #define GLUT_CURSOR_TOP_RIGHT_CORNER 17 382 | #define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 18 383 | #define GLUT_CURSOR_BOTTOM_LEFT_CORNER 19 384 | /* Inherit from parent window. */ 385 | #define GLUT_CURSOR_INHERIT 100 386 | /* Blank cursor. */ 387 | #define GLUT_CURSOR_NONE 101 388 | /* Fullscreen crosshair (if available). */ 389 | #define GLUT_CURSOR_FULL_CROSSHAIR 102 390 | #endif 391 | 392 | /* GLUT initialization sub-API. */ 393 | extern void APIENTRY glutInit(int *argcp, char **argv); 394 | extern void APIENTRY glutInitDisplayMode(unsigned int mode); 395 | #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) 396 | extern void APIENTRY glutInitDisplayString(const char *string); 397 | #endif 398 | extern void APIENTRY glutInitWindowPosition(int x, int y); 399 | extern void APIENTRY glutInitWindowSize(int width, int height); 400 | extern void APIENTRY glutMainLoop(void); 401 | 402 | /* GLUT window sub-API. */ 403 | extern int APIENTRY glutCreateWindow(const char *title); 404 | extern int APIENTRY glutCreateSubWindow(int win, int x, int y, int width, int height); 405 | extern void APIENTRY glutDestroyWindow(int win); 406 | extern void APIENTRY glutPostRedisplay(void); 407 | #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) 408 | extern void APIENTRY glutPostWindowRedisplay(int win); 409 | #endif 410 | extern void APIENTRY glutSwapBuffers(void); 411 | extern int APIENTRY glutGetWindow(void); 412 | extern void APIENTRY glutSetWindow(int win); 413 | extern void APIENTRY glutSetWindowTitle(const char *title); 414 | extern void APIENTRY glutSetIconTitle(const char *title); 415 | extern void APIENTRY glutPositionWindow(int x, int y); 416 | extern void APIENTRY glutReshapeWindow(int width, int height); 417 | extern void APIENTRY glutPopWindow(void); 418 | extern void APIENTRY glutPushWindow(void); 419 | extern void APIENTRY glutIconifyWindow(void); 420 | extern void APIENTRY glutShowWindow(void); 421 | extern void APIENTRY glutHideWindow(void); 422 | #if (GLUT_API_VERSION >= 3) 423 | extern void APIENTRY glutFullScreen(void); 424 | extern void APIENTRY glutSetCursor(int cursor); 425 | #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) 426 | extern void APIENTRY glutWarpPointer(int x, int y); 427 | #endif 428 | 429 | /* GLUT overlay sub-API. */ 430 | extern void APIENTRY glutEstablishOverlay(void); 431 | extern void APIENTRY glutRemoveOverlay(void); 432 | extern void APIENTRY glutUseLayer(GLenum layer); 433 | extern void APIENTRY glutPostOverlayRedisplay(void); 434 | #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) 435 | extern void APIENTRY glutPostWindowOverlayRedisplay(int win); 436 | #endif 437 | extern void APIENTRY glutShowOverlay(void); 438 | extern void APIENTRY glutHideOverlay(void); 439 | #endif 440 | 441 | /* GLUT menu sub-API. */ 442 | extern int APIENTRY glutCreateMenu(void (*)(int)); 443 | extern void APIENTRY glutDestroyMenu(int menu); 444 | extern int APIENTRY glutGetMenu(void); 445 | extern void APIENTRY glutSetMenu(int menu); 446 | extern void APIENTRY glutAddMenuEntry(const char *label, int value); 447 | extern void APIENTRY glutAddSubMenu(const char *label, int submenu); 448 | extern void APIENTRY glutChangeToMenuEntry(int item, const char *label, int value); 449 | extern void APIENTRY glutChangeToSubMenu(int item, const char *label, int submenu); 450 | extern void APIENTRY glutRemoveMenuItem(int item); 451 | extern void APIENTRY glutAttachMenu(int button); 452 | extern void APIENTRY glutDetachMenu(int button); 453 | 454 | /* GLUT window callback sub-API. */ 455 | extern void APIENTRY glutDisplayFunc(void (*func)(void)); 456 | extern void APIENTRY glutReshapeFunc(void (*func)(int width, int height)); 457 | extern void APIENTRY glutKeyboardFunc(void (*func)(unsigned char key, int x, int y)); 458 | extern void APIENTRY glutMouseFunc(void (*func)(int button, int state, int x, int y)); 459 | extern void APIENTRY glutMotionFunc(void (*func)(int x, int y)); 460 | extern void APIENTRY glutPassiveMotionFunc(void (*func)(int x, int y)); 461 | extern void APIENTRY glutEntryFunc(void (*func)(int state)); 462 | extern void APIENTRY glutVisibilityFunc(void (*func)(int state)); 463 | extern void APIENTRY glutIdleFunc(void (*func)(void)); 464 | extern void APIENTRY glutTimerFunc(unsigned int millis, void (*func)(int value), int value); 465 | extern void APIENTRY glutMenuStateFunc(void (*func)(int state)); 466 | #if (GLUT_API_VERSION >= 2) 467 | extern void APIENTRY glutSpecialFunc(void (*func)(int key, int x, int y)); 468 | extern void APIENTRY glutSpaceballMotionFunc(void (*func)(int x, int y, int z)); 469 | extern void APIENTRY glutSpaceballRotateFunc(void (*func)(int x, int y, int z)); 470 | extern void APIENTRY glutSpaceballButtonFunc(void (*func)(int button, int state)); 471 | extern void APIENTRY glutButtonBoxFunc(void (*func)(int button, int state)); 472 | extern void APIENTRY glutDialsFunc(void (*func)(int dial, int value)); 473 | extern void APIENTRY glutTabletMotionFunc(void (*func)(int x, int y)); 474 | extern void APIENTRY glutTabletButtonFunc(void (*func)(int button, int state, int x, int y)); 475 | #if (GLUT_API_VERSION >= 3) 476 | extern void APIENTRY glutMenuStatusFunc(void (*func)(int status, int x, int y)); 477 | extern void APIENTRY glutOverlayDisplayFunc(void (*func)(void)); 478 | #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) 479 | extern void APIENTRY glutWindowStatusFunc(void (*func)(int state)); 480 | #endif 481 | #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) 482 | extern void APIENTRY glutKeyboardUpFunc(void (*func)(unsigned char key, int x, int y)); 483 | extern void APIENTRY glutSpecialUpFunc(void (*func)(int key, int x, int y)); 484 | extern void APIENTRY glutJoystickFunc(void (*func)(unsigned int buttonMask, int x, int y, int z), int pollInterval); 485 | #endif 486 | #endif 487 | #endif 488 | 489 | /* GLUT color index sub-API. */ 490 | extern void APIENTRY glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue); 491 | extern GLfloat APIENTRY glutGetColor(int ndx, int component); 492 | extern void APIENTRY glutCopyColormap(int win); 493 | 494 | /* GLUT state retrieval sub-API. */ 495 | extern int APIENTRY glutGet(GLenum type); 496 | extern int APIENTRY glutDeviceGet(GLenum type); 497 | #if (GLUT_API_VERSION >= 2) 498 | /* GLUT extension support sub-API */ 499 | extern int APIENTRY glutExtensionSupported(const char *name); 500 | #endif 501 | #if (GLUT_API_VERSION >= 3) 502 | extern int APIENTRY glutGetModifiers(void); 503 | extern int APIENTRY glutLayerGet(GLenum type); 504 | #endif 505 | 506 | /* GLUT font sub-API */ 507 | extern void APIENTRY glutBitmapCharacter(void *font, int character); 508 | extern int APIENTRY glutBitmapWidth(void *font, int character); 509 | extern void APIENTRY glutStrokeCharacter(void *font, int character); 510 | extern int APIENTRY glutStrokeWidth(void *font, int character); 511 | #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) 512 | extern int APIENTRY glutBitmapLength(void *font, const unsigned char *string); 513 | extern int APIENTRY glutStrokeLength(void *font, const unsigned char *string); 514 | #endif 515 | 516 | /* GLUT pre-built models sub-API */ 517 | extern void APIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks); 518 | extern void APIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); 519 | extern void APIENTRY glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); 520 | extern void APIENTRY glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); 521 | extern void APIENTRY glutWireCube(GLdouble size); 522 | extern void APIENTRY glutSolidCube(GLdouble size); 523 | extern void APIENTRY glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); 524 | extern void APIENTRY glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); 525 | extern void APIENTRY glutWireDodecahedron(void); 526 | extern void APIENTRY glutSolidDodecahedron(void); 527 | extern void APIENTRY glutWireTeapot(GLdouble size); 528 | extern void APIENTRY glutSolidTeapot(GLdouble size); 529 | extern void APIENTRY glutWireOctahedron(void); 530 | extern void APIENTRY glutSolidOctahedron(void); 531 | extern void APIENTRY glutWireTetrahedron(void); 532 | extern void APIENTRY glutSolidTetrahedron(void); 533 | extern void APIENTRY glutWireIcosahedron(void); 534 | extern void APIENTRY glutSolidIcosahedron(void); 535 | 536 | #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) 537 | /* GLUT video resize sub-API. */ 538 | extern int APIENTRY glutVideoResizeGet(GLenum param); 539 | extern void APIENTRY glutSetupVideoResizing(void); 540 | extern void APIENTRY glutStopVideoResizing(void); 541 | extern void APIENTRY glutVideoResize(int x, int y, int width, int height); 542 | extern void APIENTRY glutVideoPan(int x, int y, int width, int height); 543 | 544 | /* GLUT debugging sub-API. */ 545 | extern void APIENTRY glutReportErrors(void); 546 | #endif 547 | 548 | #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) 549 | /* GLUT device control sub-API. */ 550 | /* glutSetKeyRepeat modes. */ 551 | #define GLUT_KEY_REPEAT_OFF 0 552 | #define GLUT_KEY_REPEAT_ON 1 553 | #define GLUT_KEY_REPEAT_DEFAULT 2 554 | 555 | /* Joystick button masks. */ 556 | #define GLUT_JOYSTICK_BUTTON_A 1 557 | #define GLUT_JOYSTICK_BUTTON_B 2 558 | #define GLUT_JOYSTICK_BUTTON_C 4 559 | #define GLUT_JOYSTICK_BUTTON_D 8 560 | 561 | extern void APIENTRY glutIgnoreKeyRepeat(int ignore); 562 | extern void APIENTRY glutSetKeyRepeat(int repeatMode); 563 | extern void APIENTRY glutForceJoystickFunc(void); 564 | 565 | /* GLUT game mode sub-API. */ 566 | /* glutGameModeGet. */ 567 | #define GLUT_GAME_MODE_ACTIVE 0 568 | #define GLUT_GAME_MODE_POSSIBLE 1 569 | #define GLUT_GAME_MODE_WIDTH 2 570 | #define GLUT_GAME_MODE_HEIGHT 3 571 | #define GLUT_GAME_MODE_PIXEL_DEPTH 4 572 | #define GLUT_GAME_MODE_REFRESH_RATE 5 573 | #define GLUT_GAME_MODE_DISPLAY_CHANGED 6 574 | 575 | extern void APIENTRY glutGameModeString(const char *string); 576 | extern int APIENTRY glutEnterGameMode(void); 577 | extern void APIENTRY glutLeaveGameMode(void); 578 | extern int APIENTRY glutGameModeGet(GLenum mode); 579 | #endif 580 | 581 | #ifdef __cplusplus 582 | } 583 | 584 | #endif 585 | 586 | #ifdef GLUT_APIENTRY_DEFINED 587 | # undef GLUT_APIENTRY_DEFINED 588 | # undef APIENTRY 589 | #endif 590 | 591 | #ifdef GLUT_WINGDIAPI_DEFINED 592 | # undef GLUT_WINGDIAPI_DEFINED 593 | # undef WINGDIAPI 594 | #endif 595 | 596 | #endif /* __glut_h__ */ 597 | -------------------------------------------------------------------------------- /glut32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/scriptbots/80ae7e58b6b34bb742b8c157244491ed04a5e7b7/glut32.dll -------------------------------------------------------------------------------- /glut32.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramblurr/scriptbots/80ae7e58b6b34bb742b8c157244491ed04a5e7b7/glut32.lib -------------------------------------------------------------------------------- /helpers.h: -------------------------------------------------------------------------------- 1 | #ifndef HELPERS_H 2 | #define HELPERS_H 3 | #include 4 | #include 5 | //uniform random in [a,b) 6 | inline float randf(float a, float b){return ((b-a)*((float)rand()/RAND_MAX))+a;} 7 | 8 | //uniform random int in [a,b) 9 | inline int randi(int a, int b){return (rand()%(b-a))+a;} 10 | 11 | //normalvariate random N(mu, sigma) 12 | inline double randn(double mu, double sigma) { 13 | static bool deviateAvailable=false; // flag 14 | static float storedDeviate; // deviate from previous calculation 15 | double polar, rsquared, var1, var2; 16 | if (!deviateAvailable) { 17 | do { 18 | var1=2.0*( double(rand())/double(RAND_MAX) ) - 1.0; 19 | var2=2.0*( double(rand())/double(RAND_MAX) ) - 1.0; 20 | rsquared=var1*var1+var2*var2; 21 | } while ( rsquared>=1.0 || rsquared == 0.0); 22 | polar=sqrt(-2.0*log(rsquared)/rsquared); 23 | storedDeviate=var1*polar; 24 | deviateAvailable=true; 25 | return var2*polar*sigma + mu; 26 | } 27 | else { 28 | deviateAvailable=false; 29 | return storedDeviate*sigma + mu; 30 | } 31 | } 32 | 33 | //cap value between 0 and 1 34 | inline float cap(float a){ 35 | if (a<0) return 0; 36 | if (a>1) return 1; 37 | return a; 38 | } 39 | #endif -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "GLView.h" 2 | #include "World.h" 3 | #include 4 | #include "config.h" 5 | #ifdef LOCAL_GLUT32 6 | #include "glut.h" 7 | #else 8 | #include 9 | #endif 10 | 11 | #include 12 | 13 | 14 | GLView* GLVIEW = new GLView(0); 15 | int main(int argc, char **argv) { 16 | srand(time(0)); 17 | if (conf::WIDTH%conf::CZ!=0 || conf::HEIGHT%conf::CZ!=0) printf("CAREFUL! The cell size variable conf::CZ should divide evenly into both conf::WIDTH and conf::HEIGHT! It doesn't right now!"); 18 | printf("p= pause, d= toggle drawing (for faster computation), f= draw food too, += faster, -= slower"); 19 | 20 | World* world = new World(); 21 | GLVIEW->setWorld(world); 22 | 23 | //GLUT SETUP 24 | glutInit(&argc, argv); 25 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 26 | glutInitWindowPosition(30,30); 27 | glutInitWindowSize(conf::WWIDTH,conf::WHEIGHT); 28 | glutCreateWindow("TEST"); 29 | glClearColor(0.9f, 0.9f, 1.0f, 0.0f); 30 | glutDisplayFunc(gl_renderScene); 31 | glutIdleFunc(gl_handleIdle); 32 | glutReshapeFunc(gl_changeSize); 33 | 34 | glutKeyboardFunc(gl_processNormalKeys); 35 | glutMouseFunc(gl_processMouse); 36 | glutMotionFunc(gl_processMouseActiveMotion); 37 | 38 | glutMainLoop(); 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /report.txt: -------------------------------------------------------------------------------- 1 | 11 21 0 0 2 | 11 21 0 0 3 | 12 19 0 0 4 | 12 18 0 0 5 | 12 19 0 0 6 | 14 17 0 0 7 | 10 20 0 0 8 | 11 20 0 0 9 | 10 21 0 0 10 | 14 17 0 0 11 | 14 20 0 1 12 | 18 19 0 1 13 | 18 21 0 1 14 | 19 18 0 1 15 | 19 19 0 1 16 | 25 19 1 2 17 | 26 19 0 2 18 | 30 20 0 2 19 | 30 22 0 2 20 | 34 25 0 3 21 | 39 21 0 3 22 | 48 19 0 3 23 | 57 19 0 3 24 | 61 16 2 3 25 | 78 16 1 4 26 | 87 13 1 4 27 | 89 12 3 4 28 | 92 12 3 4 29 | 102 11 2 5 30 | 99 12 4 5 31 | 106 13 4 5 32 | 103 11 4 5 33 | 101 9 4 5 34 | 87 10 4 5 35 | 78 11 4 5 36 | 76 12 4 5 37 | 83 9 5 6 38 | 79 11 5 6 39 | 79 12 5 6 40 | 84 15 5 6 41 | 75 15 5 6 42 | 73 15 5 6 43 | 67 17 4 6 44 | 69 18 4 7 45 | 74 17 4 7 46 | 81 15 4 7 47 | 92 16 4 7 48 | 93 18 5 7 49 | 92 14 5 8 50 | 99 13 5 8 51 | 107 12 5 8 52 | 96 13 6 8 53 | 91 14 6 8 54 | 97 16 6 8 55 | 89 14 6 8 56 | 81 14 6 8 57 | 86 14 6 8 58 | 93 12 6 8 59 | 91 11 5 8 60 | 85 13 5 8 61 | 84 14 5 8 62 | 96 13 5 8 63 | 90 13 5 8 64 | 88 11 5 9 65 | 99 18 7 9 66 | 102 16 7 9 67 | 88 18 7 9 68 | 91 15 7 9 69 | 89 16 4 9 70 | 95 16 4 9 71 | 105 18 6 10 72 | 109 18 6 10 73 | 106 18 6 10 74 | 110 19 6 10 75 | 109 18 6 10 76 | 95 19 6 10 77 | 100 21 6 10 78 | 108 22 6 10 79 | 107 25 8 10 80 | 117 22 8 11 81 | 120 23 8 11 82 | 122 23 8 11 83 | 123 22 8 11 84 | 118 22 8 11 85 | 120 24 8 11 86 | 117 24 8 11 87 | 114 23 8 12 88 | 112 18 7 12 89 | 112 19 7 12 90 | 111 18 7 12 91 | 102 18 5 12 92 | 101 19 5 12 93 | 105 18 5 12 94 | 102 18 5 13 95 | 97 19 5 13 96 | 89 22 5 13 97 | 85 23 5 13 98 | 85 22 5 13 99 | 86 20 5 13 100 | 95 20 5 13 101 | 99 18 5 13 102 | 107 20 6 14 103 | 103 22 9 14 104 | 101 23 9 14 105 | 99 20 9 14 106 | 103 21 9 14 107 | 93 22 9 14 108 | 86 21 9 14 109 | 78 25 9 14 110 | 73 26 9 13 111 | 65 26 9 13 112 | 66 27 8 14 113 | 67 27 8 14 114 | 69 25 5 14 115 | 81 26 9 14 116 | 82 27 9 14 117 | 84 23 9 14 118 | 89 21 2 14 119 | 101 25 9 14 120 | 104 27 9 15 121 | 114 29 9 15 122 | 115 31 9 15 123 | 111 28 10 15 124 | 112 27 10 15 125 | 103 26 10 14 126 | 93 24 10 14 127 | 96 25 10 14 128 | 95 26 10 14 129 | 98 27 11 15 130 | 100 30 11 15 131 | 100 29 11 15 132 | 101 28 11 15 133 | 105 26 11 15 134 | 110 25 10 15 135 | 121 25 10 15 136 | 126 20 10 15 137 | 128 17 9 15 138 | 129 17 9 15 139 | 139 18 9 16 140 | 137 19 9 16 141 | 140 25 9 16 142 | 151 26 10 16 143 | 147 24 10 16 144 | 145 22 10 16 145 | 138 23 13 16 146 | 132 26 13 13 147 | -------------------------------------------------------------------------------- /settings.h: -------------------------------------------------------------------------------- 1 | #ifndef SETTINGS_H 2 | #define SETTINGS_H 3 | namespace conf { 4 | 5 | const int WIDTH = 1800; //width and height of simulation 6 | const int HEIGHT = 1000; 7 | const int WWIDTH = 1800; //window width and height 8 | const int WHEIGHT = 1000; 9 | 10 | const int CZ = 50; //cell size in pixels, for food squares. Should divide well into Width Height 11 | 12 | const int NUMBOTS=30; //initially, and minimally 13 | const float BOTRADIUS=10; //for drawing 14 | const float BOTSPEED= 0.1; 15 | const float SPIKESPEED= 0.005; //how quickly can attack spike go up? 16 | const float SPIKEMULT= 0.5; //essentially the strength of every spike impact 17 | const int BABIES=2; //number of babies per agent when they reproduce 18 | const float BOOSTSIZEMULT=2; //how much boost do agents get? when boost neuron is on 19 | const float REPRATEH=7; //reproduction rate for herbivors 20 | const float REPRATEC=7; //reproduction rate for carnivors 21 | 22 | const float DIST= 150; //how far can the eyes see on each bot? 23 | const float EYE_SENSITIVITY= 2; //how sensitive are the eyes? 24 | const float BLOOD_SENSITIVITY= 2; //how sensitive are blood sensors? 25 | const float METAMUTRATE1= 0.002; //what is the change in MUTRATE1 and 2 on reproduction? lol 26 | const float METAMUTRATE2= 0.05; 27 | 28 | const float FOODGROWTH= 0;//0.00001; //how quickly does food grow on a square? 29 | const float FOODINTAKE= 0.00325; //how much does every agent consume? 30 | const float FOODWASTE= 0.001; //how much food disapears if agent eats? 31 | const float FOODMAX= 0.5; //how much food per cell can there be at max? 32 | const int FOODADDFREQ= 30; //how often does random square get to full food? 33 | 34 | const float FOODTRANSFER= 0.001; //how much is transfered between two agents trading food? per iteration 35 | const float FOOD_SHARING_DISTANCE= 50; //how far away is food shared between bots? 36 | 37 | 38 | const float FOOD_DISTRIBUTION_RADIUS=100; //when bot is killed, how far is its body distributed? 39 | 40 | } 41 | #endif -------------------------------------------------------------------------------- /vmath.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * vmath, set of classes for computer graphics mathemtics. 3 | * Copyright (c) 2005-2006, Jan Bartipan < barzto at gmail dot com > 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * - Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * - Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in 14 | * the documentation and/or other materials provided with the 15 | * distribution. 16 | * - Neither the names of its contributors may be used to endorse or 17 | * promote products derived from this software without specific 18 | * prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 30 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "vmath.h" 35 | 36 | #ifdef VMATH_NAMESPACE 37 | namespace VMATH_NAMESPACE 38 | { 39 | #endif 40 | 41 | template class Vector2; 42 | template class Vector2; 43 | template class Vector3; 44 | template class Vector3; 45 | template class Vector4; 46 | template class Vector4; 47 | template class Matrix3; 48 | template class Matrix3; 49 | template class Matrix4; 50 | template class Matrix4; 51 | template class Quaternion; 52 | template class Quaternion; 53 | 54 | #ifdef VMATH_NAMESPACE 55 | } 56 | #endif 57 | -------------------------------------------------------------------------------- /vmath.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | /* 3 | * vmath, set of classes for computer graphics mathemtics. 4 | * Copyright (c) 2005-2009, Jan Bartipan < barzto at gmail dot com > 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * - Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * - Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in 15 | * the documentation and/or other materials provided with the 16 | * distribution. 17 | * - Neither the names of its contributors may be used to endorse or 18 | * promote products derived from this software without specific 19 | * prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 31 | * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | /** 36 | * @mainpage Vector mathemtics for computer graphics 37 | * 38 | * @section Features 39 | *
    40 | *
  • basic aritemetic operations - using operators
  • 41 | *
  • basic linear algebra operations - such as transpose, dot product, etc.
  • 42 | *
  • aliasis for vertex coordinates - it means: 43 | *
      44 |  *  Vector3f v;
      45 |  *  // use vertex coordinates
      46 |  *  v.x = 1; v.y = 2; v.z = -1;
      47 |  *
      48 |  *  // use texture coordinates
      49 |  *  v.s = 0; v.t = 1; v.u = 0.5;
      50 |  *  // use color coordinates
      51 |  *  v.r = 1; v.g = 0.5; v.b = 0;
      52 |  *    
    53 | *
  • 54 | *
  • conversion constructor and assign operators - so you can assign a value of Vector3<T1> type 55 | * to a variable of Vector3<T2> type for any convertable T1, T2 type pairs. In other words, you can do this: 56 | *
      57 |  *
      58 |  *  Vector3f f3; Vector3d d3 = f3;
      59 |  *  ...
      60 |  *  f3 = d3;
      61 |  *    
    62 | *
  • 63 | *
64 | */ 65 | 66 | 67 | 68 | #ifndef __vmath_Header_File__ 69 | #define __vmath_Header_File__ 70 | 71 | #include 72 | #include 73 | #include 74 | #include 75 | 76 | 77 | 78 | #ifdef VMATH_NAMESPACE 79 | namespace VMATH_NAMESPACE 80 | { 81 | #endif 82 | 83 | #ifndef M_PI 84 | #define M_PI 3.14159265358979323846 /* pi */ 85 | #endif 86 | 87 | #define DEG2RAD(x) ((x * M_PI) / 180.0) 88 | //#define EPSILON (4.37114e-07) 89 | 90 | const double epsilon = 4.37114e-05; 91 | #define EPSILON epsilon 92 | 93 | 94 | /** 95 | * Class for two dimensional vector. 96 | */ 97 | template 98 | class Vector2 99 | { 100 | public: 101 | union 102 | { 103 | /** 104 | * First element of vector, alias for X-coordinate. 105 | */ 106 | T x; 107 | 108 | /** 109 | * First element of vector, alias for S-coordinate. 110 | * For textures notation. 111 | */ 112 | T s; 113 | }; 114 | 115 | union 116 | { 117 | /** 118 | * Second element of vector, alias for Y-coordinate. 119 | */ 120 | T y; 121 | 122 | /** 123 | * Second element of vector, alias for T-coordinate. 124 | * For textures notation. 125 | */ 126 | T t; 127 | }; 128 | 129 | //----------------[ constructors ]-------------------------- 130 | /** 131 | * Creates and sets to (0,0) 132 | */ 133 | Vector2() : x(0),y(0) 134 | { } 135 | 136 | 137 | 138 | /** 139 | * Creates and sets to (x,y) 140 | * @param nx intial x-coordinate value 141 | * @param ny intial y-coordinate value 142 | */ 143 | Vector2(T nx, T ny) : x(nx), y(ny) 144 | { } 145 | 146 | 147 | /** 148 | * Copy constructor. 149 | * @param src Source of data for new created instace. 150 | */ 151 | Vector2(const Vector2& src) 152 | : x(src.x), y(src.y) 153 | { } 154 | 155 | 156 | /** 157 | * Copy casting constructor. 158 | * @param src Source of data for new created instace. 159 | */ 160 | template 161 | Vector2(const Vector2& src) 162 | : x(static_cast(src.x)), 163 | y(static_cast(src.y)) 164 | { } 165 | 166 | 167 | //----------------[ access operators ]------------------- 168 | /** 169 | * Copy casting operator 170 | * @param rhs Right hand side argument of binary operator. 171 | */ 172 | template 173 | Vector2& operator=(const Vector2& rhs) 174 | { 175 | x = static_cast(rhs.x); 176 | y = static_cast(rhs.y); 177 | return * this; 178 | } 179 | 180 | /** 181 | * Copy operator 182 | * @param rhs Right hand side argument of binary operator. 183 | */ 184 | Vector2& operator=(const Vector2& rhs) 185 | { 186 | x = rhs.x; 187 | y = rhs.y; 188 | return * this; 189 | } 190 | 191 | 192 | /** 193 | * Array access operator 194 | * @param n Array index 195 | * @return For n = 0, reference to x coordinate, else reference to y 196 | * y coordinate. 197 | */ 198 | T& operator[](int n) 199 | { 200 | assert(n >= 0 && n <= 1); 201 | if (0 == n) return x; 202 | else 203 | return y; 204 | } 205 | 206 | 207 | //---------------[ vector aritmetic operator ]-------------- 208 | /** 209 | * Addition operator 210 | * @param rhs Right hand side argument of binary operator. 211 | */ 212 | Vector2 operator+(const Vector2& rhs) const 213 | { 214 | return Vector2 (x + rhs.x, y + rhs.y); 215 | } 216 | 217 | /** 218 | * Substraction operator 219 | * @param rhs Right hand side argument of binary operator. 220 | */ 221 | Vector2 operator-(const Vector2& rhs) const 222 | { 223 | return Vector2 (x - rhs.x, y - rhs.y); 224 | } 225 | 226 | /** 227 | * Multiplication operator 228 | * @param rhs Right hand side argument of binary operator. 229 | */ 230 | Vector2 operator*(const Vector2& rhs) const 231 | { 232 | return Vector2 (x * rhs.x, y * rhs.y); 233 | } 234 | 235 | /** 236 | * Division operator 237 | * @param rhs Right hand side argument of binary operator. 238 | */ 239 | Vector2 operator/(const Vector2& rhs) const 240 | { 241 | return Vector2 (x / rhs.x, y / rhs.y); 242 | } 243 | 244 | /** 245 | * Addition operator 246 | * @param rhs Right hand side argument of binary operator. 247 | */ 248 | Vector2& operator+=(const Vector2& rhs) 249 | { 250 | x += rhs.x; 251 | y += rhs.y; 252 | return * this; 253 | } 254 | 255 | /** 256 | * Substraction operator 257 | * @param rhs Right hand side argument of binary operator. 258 | */ 259 | Vector2& operator-=(const Vector2& rhs) 260 | { 261 | x -= rhs.x; 262 | y -= rhs.y; 263 | return * this; 264 | } 265 | 266 | /** 267 | * Multiplication operator 268 | * @param rhs Right hand side argument of binary operator. 269 | */ 270 | Vector2& operator*=(const Vector2& rhs) 271 | { 272 | x *= rhs.x; 273 | y *= rhs.y; 274 | return * this; 275 | } 276 | 277 | /** 278 | * Division operator 279 | * @param rhs Right hand side argument of binary operator. 280 | */ 281 | Vector2& operator/=(const Vector2& rhs) 282 | { 283 | x /= rhs.x; 284 | y /= rhs.y; 285 | return * this; 286 | } 287 | 288 | //--------------[ scalar vector operator ]-------------------- 289 | /** 290 | * Addition operator 291 | * @param rhs Right hand side argument of binary operator. 292 | */ 293 | Vector2 operator+(T rhs) const 294 | { 295 | return Vector2 (x + rhs, y + rhs); 296 | } 297 | 298 | /** 299 | * Substraction operator 300 | * @param rhs Right hand side argument of binary operator. 301 | */ 302 | Vector2 operator-(T rhs) const 303 | { 304 | return Vector2 (x - rhs, y - rhs); 305 | } 306 | 307 | /** 308 | * Multiplication operator 309 | * @param rhs Right hand side argument of binary operator. 310 | */ 311 | Vector2 operator*(T rhs) const 312 | { 313 | return Vector2 (x * rhs, y * rhs); 314 | } 315 | 316 | /** 317 | * Division operator 318 | * @param rhs Right hand side argument of binary operator. 319 | */ 320 | Vector2 operator/(T rhs) const 321 | { 322 | return Vector2 (x / rhs, y / rhs); 323 | } 324 | 325 | /** 326 | * Addition operator 327 | * @param rhs Right hand side argument of binary operator. 328 | */ 329 | Vector2& operator+=(T rhs) 330 | { 331 | x += rhs; 332 | y += rhs; 333 | return * this; 334 | } 335 | 336 | /** 337 | * Substraction operator 338 | * @param rhs Right hand side argument of binary operator. 339 | */ 340 | Vector2& operator-=(T rhs) 341 | { 342 | x -= rhs; 343 | y -= rhs; 344 | return * this; 345 | } 346 | 347 | /** 348 | * Multiplication operator 349 | * @param rhs Right hand side argument of binary operator. 350 | */ 351 | Vector2& operator*=(T rhs) 352 | { 353 | x *= rhs; 354 | y *= rhs; 355 | return * this; 356 | } 357 | 358 | /** 359 | * Division operator 360 | * @param rhs Right hand side argument of binary operator. 361 | */ 362 | Vector2& operator/=(T rhs) 363 | { 364 | x /= rhs; 365 | y /= rhs; 366 | return * this; 367 | } 368 | 369 | //--------------[ equality operator ]------------------------ 370 | /** 371 | * Equality test operator 372 | * @param rhs Right hand side argument of binary operator. 373 | * @note Test of equality is based of threshold EPSILON value. To be two 374 | * values equal, must satisfy this condition | lws.x - rhs.y | < EPSILON, 375 | * same for y-coordinate. 376 | */ 377 | bool operator==(const Vector2& rhs) const 378 | { 379 | return (std::abs(x - rhs.x) < EPSILON) && (std::abs(y - rhs.y) < EPSILON); 380 | } 381 | 382 | 383 | /** 384 | * Inequality test operator 385 | * @param rhs Right hand side argument of binary operator. 386 | * @return not (lhs == rhs) :-P 387 | */ 388 | bool operator!=(const Vector2& rhs) const { return ! (*this == rhs); } 389 | 390 | //-------------[ unary operations ]-------------------------- 391 | /** 392 | * Unary negate operator 393 | * @return negated vector 394 | */ 395 | Vector2 operator-() const 396 | { 397 | return Vector2(-x, -y); 398 | } 399 | 400 | //-------------[ size operations ]--------------------------- 401 | /** 402 | * Get lenght of vector. 403 | * @return lenght of vector 404 | */ 405 | T length() const 406 | { 407 | return (T)std::sqrt(x * x + y * y); 408 | } 409 | 410 | /** 411 | * Normalize vector 412 | */ 413 | void normalize() 414 | { 415 | T s = length(); 416 | x /= s; 417 | y /= s; 418 | } 419 | 420 | /** 421 | * Return square of length. 422 | * @return lenght ^ 2 423 | * @note This method is faster then length(). For comparsion 424 | * of length of two vector can be used just this value, instead 425 | * of computionaly more expensive length() method. 426 | */ 427 | T lengthSq() const 428 | { 429 | return x * x + y * y; 430 | } 431 | 432 | //--------------[ misc. operations ]----------------------- 433 | /** 434 | * Linear interpolation of two vectors 435 | * @param fact Factor of interpolation. For translation from positon 436 | * of this vector to vector r, values of factor goes from 0.0 to 1.0. 437 | * @param r Second Vector for interpolation 438 | * @note Hovewer values of fact parameter are reasonable only in interval 439 | * [0.0 , 1.0], you can pass also values outside of this interval and you 440 | * can get result (extrapolation?) 441 | */ 442 | Vector2 lerp(T fact, const Vector2& r) const 443 | { 444 | return (*this) + (r - (*this)) * fact; 445 | } 446 | 447 | //added functions 448 | float get_angle() 449 | { 450 | if(x==0 && y==0) return 0; 451 | return atan2(y, x); 452 | } 453 | 454 | //rotate this angle by a counterclockwise 455 | void rotate(float a) 456 | { 457 | float c= cos(a); 458 | float s= sin(a); 459 | float x2= x*c - y*s; 460 | y= x*s + y*c; 461 | x= x2; 462 | } 463 | 464 | //return angle this angle makes with the other one 465 | float angle_between(const Vector2& other){ 466 | float cross= x*other.y - y*other.x; 467 | float dot= x*other.x + y*other.y; 468 | return atan2(cross,dot); 469 | } 470 | 471 | //-------------[ conversion ]----------------------------- 472 | /** 473 | * Conversion to pointer operator 474 | * @return Pointer to internaly stored (in managment of class Vector2) 475 | * used for passing Vector2 values to gl*2[fd] functions. 476 | */ 477 | operator T*(){ return (T*) this; } 478 | /** 479 | * Conversion to pointer operator 480 | * @return Constant Pointer to internaly stored (in managment of class Vector2) 481 | * used for passing Vector2 values to gl*2[fd] functions. 482 | */ 483 | operator const T*() const { return (const T*) this; } 484 | 485 | //-------------[ output operator ]------------------------ 486 | /** 487 | * Output to stream operator 488 | * @param lhs Left hand side argument of operator (commonly ostream instance). 489 | * @param rhs Right hand side argument of operator. 490 | * @return Left hand side argument - the ostream object passed to operator. 491 | */ 492 | friend std::ostream& operator<<(std::ostream& lhs, const Vector2& rhs) 493 | { 494 | lhs << "[" << rhs.x << "," << rhs.y << "]"; 495 | return lhs; 496 | } 497 | 498 | 499 | }; 500 | 501 | 502 | //-------------------------------------- 503 | // Typedef shortcuts for 2D vector 504 | //------------------------------------- 505 | /// Two dimensional Vector of floats 506 | typedef class Vector2 Vector2f; 507 | /// Two dimensional Vector of doubles 508 | typedef class Vector2 Vector2d; 509 | 510 | 511 | /** 512 | * Class for three dimensional vector. 513 | */ 514 | template 515 | class Vector3 516 | { 517 | public: 518 | //T x, y, z; 519 | union 520 | { 521 | /** 522 | * First element of vector, alias for X-coordinate. 523 | */ 524 | T x; 525 | 526 | /** 527 | * First element of vector, alias for S-coordinate. 528 | * For textures notation. 529 | */ 530 | T s; 531 | 532 | /** 533 | * First element of vector, alias for R-coordinate. 534 | * For color notation. 535 | */ 536 | T r; 537 | }; 538 | 539 | union 540 | { 541 | /** 542 | * Second element of vector, alias for Y-coordinate. 543 | */ 544 | T y; 545 | /** 546 | * Second element of vector, alias for T-coordinate. 547 | * For textures notation. 548 | */ 549 | T t; 550 | /** 551 | * Second element of vector, alias for G-coordinate. 552 | * For color notation. 553 | */ 554 | T g; 555 | }; 556 | 557 | union 558 | { 559 | /** 560 | * Third element of vector, alias for Z-coordinate. 561 | */ 562 | T z; 563 | 564 | /** 565 | * Third element of vector, alias for U-coordinate. 566 | * For textures notation. 567 | */ 568 | T u; 569 | /** 570 | * Third element of vector, alias for B-coordinate. 571 | * For color notation. 572 | */ 573 | T b; 574 | }; 575 | 576 | //----------------[ constructors ]-------------------------- 577 | /** 578 | * Creates and sets to (0,0,0) 579 | */ 580 | Vector3() : x(0),y(0),z(0) 581 | { } 582 | 583 | /** 584 | * Creates and sets to (x,y,z) 585 | * @param nx intial x-coordinate value 586 | * @param ny intial y-coordinate value 587 | * @param nz intial z-coordinate value 588 | */ 589 | Vector3(T nx, T ny, T nz) : x(nx),y(ny),z(nz) 590 | { } 591 | 592 | /** 593 | * Copy constructor. 594 | * @param src Source of data for new created Vector3 instance. 595 | */ 596 | Vector3(const Vector3& src) 597 | : x(src.x), y(src.y), z(src.z) 598 | {} 599 | 600 | /** 601 | * Copy casting constructor. 602 | * @param src Source of data for new created Vector3 instance. 603 | */ 604 | template 605 | Vector3(const Vector3& src) 606 | : x(static_cast(src.x)), 607 | y(static_cast(src.y)), 608 | z(static_cast(src.z)) 609 | {} 610 | 611 | 612 | //----------------[ access operators ]------------------- 613 | /** 614 | * Copy operator 615 | * @param rhs Right hand side argument of binary operator. 616 | */ 617 | Vector3 operator=(const Vector3& rhs) 618 | { 619 | x = rhs.x; 620 | y = rhs.y; 621 | z = rhs.z; 622 | return * this; 623 | } 624 | 625 | /** 626 | * Copy casting operator. 627 | * @param rhs Right hand side argument of binary operator. 628 | */ 629 | template 630 | Vector3 operator=(const Vector3& rhs) 631 | { 632 | x = static_cast(rhs.x); 633 | y = static_cast(rhs.y); 634 | z = static_cast(rhs.z); 635 | return * this; 636 | } 637 | 638 | /** 639 | * Array access operator 640 | * @param n Array index 641 | * @return For n = 0, reference to x coordinate, n = 1 642 | * reference to y, else reference to z 643 | * y coordinate. 644 | */ 645 | T & operator[](int n) 646 | { 647 | assert(n >= 0 && n <= 2); 648 | if (0 == n) return x; 649 | else if (1 == n) return y; 650 | else 651 | return z; 652 | } 653 | 654 | 655 | //---------------[ vector aritmetic operator ]-------------- 656 | /** 657 | * Addition operator 658 | * @param rhs Right hand side argument of binary operator. 659 | */ 660 | Vector3 operator+(const Vector3& rhs) const 661 | { 662 | return Vector3 (x + rhs.x, y + rhs.y, z + rhs.z); 663 | } 664 | 665 | /** 666 | * Substraction operator 667 | * @param rhs Right hand side argument of binary operator. 668 | */ 669 | Vector3 operator-(const Vector3& rhs) const 670 | { 671 | return Vector3 (x - rhs.x, y - rhs.y, z - rhs.z); 672 | } 673 | 674 | /** 675 | * Multiplication operator 676 | * @param rhs Right hand side argument of binary operator. 677 | */ 678 | Vector3 operator*(const Vector3& rhs) const 679 | { 680 | return Vector3 (x * rhs.x, y * rhs.y, z * rhs.z); 681 | } 682 | 683 | /** 684 | * Division operator 685 | * @param rhs Right hand side argument of binary operator. 686 | */ 687 | Vector3 operator/(const Vector3& rhs) const 688 | { 689 | return Vector3 (x / rhs.x, y / rhs.y, z / rhs.z); 690 | } 691 | 692 | /** 693 | * Addition operator 694 | * @param rhs Right hand side argument of binary operator. 695 | */ 696 | Vector3& operator+=(const Vector3& rhs) 697 | { 698 | x += rhs.x; 699 | y += rhs.y; 700 | z += rhs.z; 701 | return * this; 702 | } 703 | 704 | /** 705 | * Substraction operator 706 | * @param rhs Right hand side argument of binary operator. 707 | */ 708 | Vector3& operator-=(const Vector3& rhs) 709 | { 710 | x -= rhs.x; 711 | y -= rhs.y; 712 | z -= rhs.z; 713 | return * this; 714 | } 715 | 716 | /** 717 | * Multiplication operator 718 | * @param rhs Right hand side argument of binary operator. 719 | */ 720 | Vector3& operator*=(const Vector3& rhs) 721 | { 722 | x *= rhs.x; 723 | y *= rhs.y; 724 | z *= rhs.z; 725 | return * this; 726 | } 727 | 728 | /** 729 | * Division operator 730 | * @param rhs Right hand side argument of binary operator. 731 | */ 732 | Vector3& operator/=(const Vector3& rhs) 733 | { 734 | x /= rhs.x; 735 | y /= rhs.y; 736 | z /= rhs.z; 737 | return * this; 738 | } 739 | 740 | /** 741 | * Dot product of two vectors. 742 | * @param rhs Right hand side argument of binary operator. 743 | */ 744 | T dotProduct(const Vector3& rhs) const 745 | { 746 | return x * rhs.x + y * rhs.y + z * rhs.z; 747 | } 748 | 749 | /** 750 | * Cross product opertor 751 | * @param rhs Right hand side argument of binary operator. 752 | */ 753 | Vector3 crossProduct(const Vector3& rhs) const 754 | { 755 | return Vector3 (y * rhs.z - rhs.y * z, z * rhs.x - rhs.z * x, x * rhs.y - rhs.x * y); 756 | } 757 | 758 | 759 | //--------------[ scalar vector operator ]-------------------- 760 | /** 761 | * Addition operator 762 | * @param rhs Right hand side argument of binary operator. 763 | */ 764 | Vector3 operator+(T rhs) const 765 | { 766 | return Vector3 (x + rhs, y + rhs, z + rhs); 767 | } 768 | 769 | /** 770 | * Substraction operator 771 | * @param rhs Right hand side argument of binary operator. 772 | */ 773 | Vector3 operator-(T rhs) const 774 | { 775 | return Vector3 (x - rhs, y - rhs, z - rhs); 776 | } 777 | 778 | /** 779 | * Multiplication operator 780 | * @param rhs Right hand side argument of binary operator. 781 | */ 782 | Vector3 operator*(T rhs) const 783 | { 784 | return Vector3 (x * rhs, y * rhs, z * rhs); 785 | } 786 | 787 | /** 788 | * Division operator 789 | * @param rhs Right hand side argument of binary operator. 790 | */ 791 | Vector3 operator/(T rhs) const 792 | { 793 | return Vector3 (x / rhs, y / rhs, z / rhs); 794 | } 795 | 796 | /** 797 | * Addition operator 798 | * @param rhs Right hand side argument of binary operator. 799 | */ 800 | Vector3& operator+=(T rhs) 801 | { 802 | x += rhs; 803 | y += rhs; 804 | z += rhs; 805 | return * this; 806 | } 807 | 808 | /** 809 | * Substraction operator 810 | * @param rhs Right hand side argument of binary operator. 811 | */ 812 | Vector3& operator-=(T rhs) 813 | { 814 | x -= rhs; 815 | y -= rhs; 816 | z -= rhs; 817 | return * this; 818 | } 819 | 820 | /** 821 | * Multiplication operator 822 | * @param rhs Right hand side argument of binary operator. 823 | */ 824 | Vector3& operator*=(T rhs) 825 | { 826 | x *= rhs; 827 | y *= rhs; 828 | z *= rhs; 829 | return * this; 830 | } 831 | 832 | /** 833 | * Division operator 834 | * @param rhs Right hand side argument of binary operator. 835 | */ 836 | Vector3& operator/=(T rhs) 837 | { 838 | x /= rhs; 839 | y /= rhs; 840 | z /= rhs; 841 | return * this; 842 | } 843 | 844 | //--------------[ equiality operator ]------------------------ 845 | /** 846 | * Equality test operator 847 | * @param rhs Right hand side argument of binary operator. 848 | * @note Test of equality is based of threshold EPSILON value. To be two 849 | * values equal, must satisfy this condition | lws.x - rhs.y | < EPSILON, 850 | * same for y-coordinate, and z-coordinate. 851 | */ 852 | bool operator==(const Vector3& rhs) const 853 | { 854 | return std::fabs(x - rhs.x) < EPSILON 855 | && std::fabs(y - rhs.y) < EPSILON 856 | && std::fabs(z - rhs.z) < EPSILON; 857 | } 858 | 859 | /** 860 | * Inequality test operator 861 | * @param rhs Right hand side argument of binary operator. 862 | * @return not (lhs == rhs) :-P 863 | */ 864 | bool operator!=(const Vector3& rhs) const { return !(*this == rhs); } 865 | 866 | //-------------[ unary operations ]-------------------------- 867 | /** 868 | * Unary negate operator 869 | * @return negated vector 870 | */ 871 | Vector3 operator-() const 872 | { 873 | return Vector3(-x, -y, -z); 874 | } 875 | 876 | //-------------[ size operations ]--------------------------- 877 | /** 878 | * Get lenght of vector. 879 | * @return lenght of vector 880 | */ 881 | T length() const 882 | { 883 | return (T)std::sqrt(x * x + y * y + z * z); 884 | } 885 | 886 | /** 887 | * Return square of length. 888 | * @return lenght ^ 2 889 | * @note This method is faster then length(). For comparsion 890 | * of length of two vector can be used just this value, instead 891 | * of computionaly more expensive length() method. 892 | */ 893 | T lengthSq() const 894 | { 895 | return x * x + y * y + z * z; 896 | } 897 | 898 | /** 899 | * Normalize vector 900 | */ 901 | void normalize() 902 | { 903 | T s = length(); 904 | x /= s; 905 | y /= s; 906 | z /= s; 907 | } 908 | 909 | //------------[ other operations ]--------------------------- 910 | /** 911 | * Rotate vector around three axis. 912 | * @param ax Angle (in degrees) to be rotated around X-axis. 913 | * @param ay Angle (in degrees) to be rotated around Y-axis. 914 | * @param az Angle (in degrees) to be rotated around Z-axis. 915 | */ 916 | void rotate(T ax, T ay, T az) 917 | { 918 | T a = cos(DEG2RAD(ax)); 919 | T b = sin(DEG2RAD(ax)); 920 | T c = cos(DEG2RAD(ay)); 921 | T d = sin(DEG2RAD(ay)); 922 | T e = cos(DEG2RAD(az)); 923 | T f = sin(DEG2RAD(az)); 924 | T nx = c * e * x - c * f * y + d * z; 925 | T ny = (a * f + b * d * e) * x + (a * e - b * d * f) * y - b * c * z; 926 | T nz = (b * f - a * d * e) * x + (a * d * f + b * e) * y + a * c * z; 927 | x = nx; y = ny; z = nz; 928 | 929 | 930 | } 931 | 932 | /** 933 | * Linear interpolation of two vectors 934 | * @param fact Factor of interpolation. For translation from positon 935 | * of this vector to vector r, values of factor goes from 0.0 to 1.0. 936 | * @param r Second Vector for interpolation 937 | * @note Hovewer values of fact parameter are reasonable only in interval 938 | * [0.0 , 1.0], you can pass also values outside of this interval and you 939 | * can get result (extrapolation?) 940 | */ 941 | Vector3 lerp(T fact, const Vector3& r) const 942 | { 943 | return (*this) + (r - (*this)) * fact; 944 | } 945 | 946 | 947 | 948 | 949 | 950 | //-------------[ conversion ]----------------------------- 951 | 952 | /** 953 | * Conversion to pointer operator 954 | * @return Pointer to internaly stored (in managment of class Vector3) 955 | * used for passing Vector3 values to gl*3[fd] functions. 956 | */ 957 | operator T*(){ return (T*) this; } 958 | 959 | /** 960 | * Conversion to pointer operator 961 | * @return Constant Pointer to internaly stored (in managment of class Vector3) 962 | * used for passing Vector3 values to gl*3[fd] functions. 963 | */ 964 | operator const T*() const { return (const T*) this; } 965 | 966 | //-------------[ output operator ]------------------------ 967 | /** 968 | * Output to stream operator 969 | * @param lhs Left hand side argument of operator (commonly ostream instance). 970 | * @param rhs Right hand side argument of operator. 971 | * @return Left hand side argument - the ostream object passed to operator. 972 | */ 973 | friend std::ostream& operator<<(std::ostream& lhs, const Vector3 rhs) 974 | { 975 | lhs << "[" << rhs.x << "," << rhs.y << "," << rhs.z << "]"; 976 | return lhs; 977 | } 978 | 979 | }; 980 | 981 | 982 | /// Three dimensional Vector of floats 983 | typedef Vector3 Vector3f; 984 | /// Three dimensional Vector of doubles 985 | typedef Vector3 Vector3d; 986 | 987 | /** 988 | * Class for four dimensional vector. 989 | */ 990 | template 991 | class Vector4{ 992 | public: 993 | 994 | union 995 | { 996 | /** 997 | * First element of vector, alias for R-coordinate. 998 | * For color notation. 999 | */ 1000 | T r 1001 | /** 1002 | * First element of vector, alias for X-coordinate. 1003 | */; 1004 | T x; 1005 | }; 1006 | 1007 | union 1008 | { 1009 | /** 1010 | * Second element of vector, alias for G-coordinate. 1011 | * For color notation. 1012 | */ 1013 | T g; 1014 | /** 1015 | * Second element of vector, alias for Y-coordinate. 1016 | */ 1017 | T y; 1018 | }; 1019 | 1020 | union 1021 | { 1022 | /** 1023 | * Third element of vector, alias for B-coordinate. 1024 | * For color notation. 1025 | */ 1026 | T b; 1027 | /** 1028 | * Third element of vector, alias for Z-coordinate. 1029 | */ 1030 | T z; 1031 | }; 1032 | 1033 | union 1034 | { 1035 | /** 1036 | * Fourth element of vector, alias for A-coordinate. 1037 | * For color notation. This represnt aplha chanell 1038 | */ 1039 | T a; 1040 | /** 1041 | * First element of vector, alias for W-coordinate. 1042 | * @note For vectors (such as normals) should be set to 0.0 1043 | * For vertices should be set to 1.0 1044 | */ 1045 | T w; 1046 | }; 1047 | 1048 | //----------------[ constructors ]-------------------------- 1049 | /** 1050 | * Creates and sets to (0,0,0,0) 1051 | */ 1052 | Vector4() : x(0),y(0),z(0),w(0) 1053 | { } 1054 | 1055 | 1056 | /** 1057 | * Creates and sets to (x,y,z,z) 1058 | * @param nx intial x-coordinate value (R) 1059 | * @param ny intial y-coordinate value (G) 1060 | * @param nz intial z-coordinate value (B) 1061 | * @param nw intial w-coordinate value (Aplha) 1062 | */ 1063 | Vector4(T nx, T ny, T nz, T nw) : x(nx), y(ny), z(nz), w(nw) 1064 | { } 1065 | 1066 | /** 1067 | * Copy constructor. 1068 | * @param src Source of data for new created Vector4 instance. 1069 | */ 1070 | Vector4(const Vector4& src) 1071 | : x(src.x), y(src.y), z(src.z), w(src.w) 1072 | {} 1073 | 1074 | /** 1075 | * Copy casting constructor. 1076 | * @param src Source of data for new created Vector4 instance. 1077 | */ 1078 | template 1079 | Vector4(const Vector4& src) 1080 | : x(static_cast(src.x)), 1081 | y(static_cast(src.y)), 1082 | z(static_cast(src.z)), 1083 | w(static_cast(src.w)) 1084 | {} 1085 | 1086 | 1087 | //----------------[ access operators ]------------------- 1088 | /** 1089 | * Copy operator 1090 | * @param rhs Right hand side argument of binary operator. 1091 | */ 1092 | Vector4 operator=(const Vector4& rhs) 1093 | { 1094 | x = rhs.x; 1095 | y = rhs.y; 1096 | z = rhs.z; 1097 | w = rhs.w; 1098 | return * this; 1099 | } 1100 | 1101 | /** 1102 | * Copy casting operator 1103 | * @param rhs Right hand side argument of binary operator. 1104 | */ 1105 | template 1106 | Vector4 operator=(const Vector4& rhs) 1107 | { 1108 | x = static_cast(rhs.x); 1109 | y = static_cast(rhs.y); 1110 | z = static_cast(rhs.z); 1111 | w = static_cast(rhs.w); 1112 | return * this; 1113 | } 1114 | 1115 | 1116 | /** 1117 | * Array access operator 1118 | * @param n Array index 1119 | * @return For n = 0, reference to x coordinate, n = 1 1120 | * reference to y coordinate, n = 2 reference to z, 1121 | * else reference to w coordinate. 1122 | */ 1123 | T & operator[](int n) 1124 | { 1125 | assert(n >= 0 && n <= 3); 1126 | if (0 == n) return x; 1127 | else if (1 == n) return y; 1128 | else if (2 == n) return z; 1129 | else return w; 1130 | } 1131 | 1132 | 1133 | //---------------[ vector aritmetic operator ]-------------- 1134 | /** 1135 | * Addition operator 1136 | * @param rhs Right hand side argument of binary operator. 1137 | */ 1138 | Vector4 operator+(const Vector4& rhs) const 1139 | { 1140 | return Vector4 (x + rhs.x, y + rhs.y, z + rhs.z, w + rhs.w); 1141 | } 1142 | 1143 | /** 1144 | * Substraction operator 1145 | * @param rhs Right hand side argument of binary operator. 1146 | */ 1147 | Vector4 operator-(const Vector4& rhs) const 1148 | { 1149 | return Vector4 (x - rhs.x, y - rhs.y, z - rhs.z, w - rhs.w); 1150 | } 1151 | 1152 | /** 1153 | * Multiplication operator 1154 | * @param rhs Right hand side argument of binary operator. 1155 | */ 1156 | Vector4 operator*(const Vector4 rhs) const 1157 | { 1158 | return Vector4 (x * rhs.x, y * rhs.y, z * rhs.z, w * rhs.w); 1159 | } 1160 | 1161 | /** 1162 | * Division operator 1163 | * @param rhs Right hand side argument of binary operator. 1164 | */ 1165 | Vector4 operator/(const Vector4& rhs) const 1166 | { 1167 | return Vector4 (x / rhs.x, y / rhs.y, z / rhs.z, w / rhs.w); 1168 | } 1169 | 1170 | /** 1171 | * Addition operator 1172 | * @param rhs Right hand side argument of binary operator. 1173 | */ 1174 | Vector4& operator+=(const Vector4& rhs) 1175 | { 1176 | x += rhs.x; 1177 | y += rhs.y; 1178 | z += rhs.z; 1179 | w += rhs.w; 1180 | return * this; 1181 | } 1182 | 1183 | /** 1184 | * Substraction operator 1185 | * @param rhs Right hand side argument of binary operator. 1186 | */ 1187 | Vector4& operator-=(const Vector4& rhs) 1188 | { 1189 | x -= rhs.x; 1190 | y -= rhs.y; 1191 | z -= rhs.z; 1192 | w -= rhs.w; 1193 | return * this; 1194 | } 1195 | 1196 | /** 1197 | * Multiplication operator 1198 | * @param rhs Right hand side argument of binary operator. 1199 | */ 1200 | Vector4& operator*=(const Vector4& rhs) 1201 | { 1202 | x *= rhs.x; 1203 | y *= rhs.y; 1204 | z *= rhs.z; 1205 | w *= rhs.w; 1206 | return * this; 1207 | } 1208 | 1209 | /** 1210 | * Division operator 1211 | * @param rhs Right hand side argument of binary operator. 1212 | */ 1213 | Vector4& operator/=(const Vector4& rhs) 1214 | { 1215 | x /= rhs.x; 1216 | y /= rhs.y; 1217 | z /= rhs.z; 1218 | w /= rhs.w; 1219 | return * this; 1220 | } 1221 | 1222 | //--------------[ equiality operator ]------------------------ 1223 | /** 1224 | * Equality test operator 1225 | * @param rhs Right hand side argument of binary operator. 1226 | * @note Test of equality is based of threshold EPSILON value. To be two 1227 | * values equal, must satisfy this condition | lws.x - rhs.y | < EPSILON, 1228 | * same for y-coordinate, z-coordinate, and w-coordinate. 1229 | */ 1230 | bool operator==(const Vector4& rhs) const 1231 | { 1232 | return std::fabs(x - rhs.x) < EPSILON 1233 | && std::fabs(y - rhs.y) < EPSILON 1234 | && std::fabs(z - rhs.z) < EPSILON 1235 | && std::fabs(w - rhs.w) < EPSILON; 1236 | } 1237 | 1238 | 1239 | /** 1240 | * Inequality test operator 1241 | * @param rhs Right hand side argument of binary operator. 1242 | * @return not (lhs == rhs) :-P 1243 | */ 1244 | bool operator!=(const Vector4& rhs) const { return ! (*this == rhs); } 1245 | 1246 | //-------------[ unary operations ]-------------------------- 1247 | /** 1248 | * Unary negate operator 1249 | * @return negated vector 1250 | */ 1251 | Vector4 operator-() const 1252 | { 1253 | return Vector4(-x, -y, -z, -w); 1254 | } 1255 | 1256 | //--------------[ scalar vector operator ]-------------------- 1257 | 1258 | /** 1259 | * Addition operator 1260 | * @param rhs Right hand side argument of binary operator. 1261 | */ 1262 | Vector4 operator+(T rhs) const 1263 | { 1264 | return Vector4 (x + rhs, y + rhs, z + rhs, w + rhs); 1265 | } 1266 | 1267 | /** 1268 | * Substraction operator 1269 | * @param rhs Right hand side argument of binary operator. 1270 | */ 1271 | Vector4 operator-(T rhs) const 1272 | { 1273 | return Vector4 (x - rhs, y - rhs, z - rhs, w - rhs); 1274 | } 1275 | 1276 | /** 1277 | * Multiplication operator 1278 | * @param rhs Right hand side argument of binary operator. 1279 | */ 1280 | Vector4 operator*(T rhs) const 1281 | { 1282 | return Vector4 (x * rhs, y * rhs, z * rhs, w * rhs); 1283 | } 1284 | 1285 | /** 1286 | * Division operator 1287 | * @param rhs Right hand side argument of binary operator. 1288 | */ 1289 | Vector4 operator/(T rhs) const 1290 | { 1291 | return Vector4 (x / rhs, y / rhs, z / rhs, w / rhs); 1292 | } 1293 | 1294 | /** 1295 | * Addition operator 1296 | * @param rhs Right hand side argument of binary operator. 1297 | */ 1298 | Vector4& operator+=(T rhs) 1299 | { 1300 | x += rhs; 1301 | y += rhs; 1302 | z += rhs; 1303 | w += rhs; 1304 | return * this; 1305 | } 1306 | 1307 | /** 1308 | * Substraction operator 1309 | * @param rhs Right hand side argument of binary operator. 1310 | */ 1311 | Vector4& operator-=(T rhs) 1312 | { 1313 | x -= rhs; 1314 | y -= rhs; 1315 | z -= rhs; 1316 | w -= rhs; 1317 | return * this; 1318 | } 1319 | 1320 | /** 1321 | * Multiplication operator 1322 | * @param rhs Right hand side argument of binary operator. 1323 | */ 1324 | Vector4& operator*=(T rhs) 1325 | { 1326 | x *= rhs; 1327 | y *= rhs; 1328 | z *= rhs; 1329 | w *= rhs; 1330 | return * this; 1331 | } 1332 | 1333 | /** 1334 | * Division operator 1335 | * @param rhs Right hand side argument of binary operator. 1336 | */ 1337 | Vector4& operator/=(T rhs) 1338 | { 1339 | x /= rhs; 1340 | y /= rhs; 1341 | z /= rhs; 1342 | w /= rhs; 1343 | return * this; 1344 | } 1345 | 1346 | //-------------[ size operations ]--------------------------- 1347 | /** 1348 | * Get lenght of vector. 1349 | * @return lenght of vector 1350 | */ 1351 | T length() const 1352 | { 1353 | return (T)std::sqrt(x * x + y * y + z * z + w * w); 1354 | } 1355 | 1356 | /** 1357 | * Normalize vector 1358 | */ 1359 | void normalize() 1360 | { 1361 | T s = length(); 1362 | x /= s; 1363 | y /= s; 1364 | z /= s; 1365 | w /= s; 1366 | } 1367 | 1368 | /** 1369 | * Return square of length. 1370 | * @return lenght ^ 2 1371 | * @note This method is faster then length(). For comparsion 1372 | * of length of two vector can be used just this value, instead 1373 | * of computionaly more expensive length() method. 1374 | */ 1375 | T lengthSq() const 1376 | { 1377 | return x * x + y * y + z * z + w * w; 1378 | } 1379 | 1380 | //--------------[ misc. operations ]----------------------- 1381 | /** 1382 | * Linear interpolation of two vectors 1383 | * @param fact Factor of interpolation. For translation from positon 1384 | * of this vector to vector r, values of factor goes from 0.0 to 1.0. 1385 | * @param r Second Vector for interpolation 1386 | * @note Hovewer values of fact parameter are reasonable only in interval 1387 | * [0.0 , 1.0], you can pass also values outside of this interval and you 1388 | * can get result (extrapolation?) 1389 | */ 1390 | Vector4 lerp(T fact, const Vector4& r) const 1391 | { 1392 | return (*this) + (r - (*this)) * fact; 1393 | } 1394 | 1395 | 1396 | 1397 | 1398 | //-------------[ conversion ]----------------------------- 1399 | 1400 | /** 1401 | * Conversion to pointer operator 1402 | * @return Pointer to internaly stored (in managment of class Vector4) 1403 | * used for passing Vector4 values to gl*4[fd] functions. 1404 | */ 1405 | operator T*(){ return (T*) this; } 1406 | 1407 | 1408 | /** 1409 | * Conversion to pointer operator 1410 | * @return Constant Pointer to internaly stored (in managment of class Vector4) 1411 | * used for passing Vector4 values to gl*4[fd] functions. 1412 | */ 1413 | operator const T*() const { return (const T*) this; } 1414 | 1415 | //-------------[ output operator ]------------------------ 1416 | /** 1417 | * Output to stream operator 1418 | * @param lhs Left hand side argument of operator (commonly ostream instance). 1419 | * @param rhs Right hand side argument of operator. 1420 | * @return Left hand side argument - the ostream object passed to operator. 1421 | */ 1422 | friend std::ostream& operator<<(std::ostream& lhs, const Vector4& rhs) 1423 | { 1424 | lhs << "[" << rhs.x << "," << rhs.y << "," << rhs.z << "," << rhs.w << "]"; 1425 | return lhs; 1426 | } 1427 | }; 1428 | 1429 | /// Three dimensional Vector of floats 1430 | typedef Vector4 Vector4f; 1431 | /// Three dimensional Vector of doubles 1432 | typedef Vector4 Vector4d; 1433 | 1434 | 1435 | 1436 | 1437 | 1438 | /** 1439 | * Class for matrix 3x3. 1440 | * @note Data stored in this matrix are in column major order. 1441 | */ 1442 | template 1443 | class Matrix3 1444 | { 1445 | public: 1446 | /// Data stored in column major order 1447 | T data[9]; 1448 | 1449 | //--------------------------[ constructors ]------------------------------- 1450 | /** 1451 | * Creates identity matrix 1452 | */ 1453 | Matrix3() 1454 | { 1455 | for (int i = 0; i < 9; i++) 1456 | data[i] = (i % 4) ? 0 : 1; 1457 | } 1458 | 1459 | /** 1460 | * Copy matrix values from array (these data must be in column 1461 | * major order!) 1462 | */ 1463 | Matrix3(const T * dt) 1464 | { 1465 | std::memcpy(data, dt, sizeof(T) * 9); 1466 | } 1467 | 1468 | /** 1469 | * Copy constructor. 1470 | * @param src Data source for new created instance of Matrix3 1471 | */ 1472 | Matrix3(const Matrix3& src) 1473 | { 1474 | std::memcpy(data, src.data, sizeof(T) * 9); 1475 | } 1476 | 1477 | /** 1478 | * Copy casting constructor. 1479 | * @param src Data source for new created instance of Matrix3 1480 | */ 1481 | template 1482 | Matrix3(const Matrix3& src) 1483 | { 1484 | for (int i = 0; i < 9; i++) 1485 | { 1486 | data[i] = static_cast(src.data[i]); 1487 | } 1488 | } 1489 | 1490 | /** 1491 | * Resets matrix to be identity matrix 1492 | */ 1493 | void identity() 1494 | { 1495 | for (int i = 0; i < 9; i++) 1496 | data[i] = (i % 4) ? 0 : 1; 1497 | } 1498 | 1499 | 1500 | 1501 | /** 1502 | * Creates rotation matrix by rotation around axis. 1503 | * @param a Angle (in radians) of rotation around axis X. 1504 | * @param b Angle (in radians) of rotation around axis Y. 1505 | * @param c Angle (in radians) of rotation around axis Z. 1506 | */ 1507 | static Matrix3 createRotationAroundAxis(T a, T b, T c) 1508 | { 1509 | Matrix3 ma, mb, mc; 1510 | float ac = cos(a); 1511 | float as = sin(a); 1512 | float bc = cos(b); 1513 | float bs = sin(b); 1514 | float cc = cos(c); 1515 | float cs = sin(c); 1516 | 1517 | ma.at(1,1) = ac; 1518 | ma.at(2,1) = as; 1519 | ma.at(1,2) = -as; 1520 | ma.at(2,2) = ac; 1521 | 1522 | mb.at(0,0) = bc; 1523 | mb.at(2,0) = -bs; 1524 | mb.at(0,2) = bs; 1525 | mb.at(2,2) = bc; 1526 | 1527 | mc.at(0,0) = cc; 1528 | mc.at(1,0) = cs; 1529 | mc.at(0,1) = -cs; 1530 | mc.at(1,1) = cc; 1531 | 1532 | Matrix3 ret = ma * mb * mc; 1533 | return ret; 1534 | } 1535 | 1536 | /** 1537 | * Creates roation matrix from ODE Matrix. 1538 | */ 1539 | template 1540 | static Matrix3 fromOde(const It* mat) 1541 | { 1542 | Matrix3 ret; 1543 | for (int i = 0; i < 3; i++) 1544 | { 1545 | for (int j = 0; j < 3; j++) 1546 | { 1547 | ret.at(i,j) = static_cast(mat[j * 4 + i]); 1548 | } 1549 | } 1550 | return ret; 1551 | } 1552 | 1553 | 1554 | //---------------------[ equiality operators ]------------------------------ 1555 | /** 1556 | * Equality test operator 1557 | * @param rhs Right hand side argument of binary operator. 1558 | * @note Test of equality is based of threshold EPSILON value. To be two 1559 | * values equal, must satisfy this condition all elements of matrix 1560 | * | lws[i] - rhs[i] | < EPSILON, 1561 | * same for y-coordinate, z-coordinate, and w-coordinate. 1562 | */ 1563 | bool operator==(const Matrix3& rhs) const 1564 | { 1565 | for (int i = 0; i < 9; i++) 1566 | { 1567 | if (std::fabs(data[i] - rhs.data[i]) >= EPSILON) 1568 | return false; 1569 | } 1570 | return true; 1571 | } 1572 | 1573 | 1574 | /** 1575 | * Inequality test operator 1576 | * @param rhs Right hand side argument of binary operator. 1577 | * @return not (lhs == rhs) :-P 1578 | */ 1579 | bool operator!=(const Matrix3& rhs) const 1580 | { 1581 | return !(*this == rhs); 1582 | } 1583 | 1584 | 1585 | //---------------------[ access operators ]--------------------------------- 1586 | /** 1587 | * Get reference to element at postion (x,y). 1588 | * @param x Number of column (0..2) 1589 | * @param y Number of row (0..2) 1590 | */ 1591 | T& at(int x, int y) 1592 | { 1593 | assert(x >= 0 && x < 3); 1594 | assert(y >= 0 && y < 3); 1595 | return data[x * 3 + y]; 1596 | } 1597 | 1598 | /** 1599 | * Get constant reference to element at postion (x,y). 1600 | * @param x Number of column (0..2) 1601 | * @param y Number of row (0..2) 1602 | */ 1603 | const T& at(int x, int y) const 1604 | { 1605 | assert(x >= 0 && x < 3); 1606 | assert(y >= 0 && y < 3); 1607 | return data[x * 3 + y]; 1608 | } 1609 | 1610 | /** 1611 | * Copy operator 1612 | * @param rhs Right hand side argument of binary operator. 1613 | */ 1614 | Matrix3& operator=(const Matrix3& rhs) 1615 | { 1616 | std::memcpy(data, rhs.data, sizeof(T) * 9); 1617 | return * this; 1618 | } 1619 | 1620 | /** 1621 | * Copy casting operator 1622 | * @param rhs Right hand side argument of binary operator. 1623 | */ 1624 | template 1625 | Matrix3& operator=(const Matrix3& rhs) 1626 | { 1627 | for (int i = 0; i < 9; i++) 1628 | { 1629 | data[i] = static_cast(rhs.data[i]); 1630 | } 1631 | return * this; 1632 | } 1633 | 1634 | /** 1635 | * Copy operator 1636 | * @param rhs Right hand side argument of binary operator. 1637 | */ 1638 | Matrix3& operator=(const T* rhs) 1639 | { 1640 | std::memcpy(data, rhs, sizeof(T) * 9); 1641 | return * this; 1642 | } 1643 | 1644 | 1645 | /*Matrix3 & operator=(const double* m) 1646 | { 1647 | for (int i = 0; i < 9; i++) data[i] = (T)m[i]; 1648 | return * this; 1649 | }*/ 1650 | 1651 | //--------------------[ matrix with matrix operations ]--------------------- 1652 | /** 1653 | * Addition operator 1654 | * @param rhs Right hand side argument of binary operator. 1655 | */ 1656 | Matrix3 operator+(const Matrix3& rhs) const 1657 | { 1658 | Matrix3 ret; 1659 | for (int i = 0; i < 9; i++) 1660 | ret.data[i] = data[i] + rhs.data[i]; 1661 | return ret; 1662 | } 1663 | 1664 | /** 1665 | * Substraction operator 1666 | * @param rhs Right hand side argument of binary operator. 1667 | */ 1668 | Matrix3 operator-(const Matrix3& rhs) const 1669 | { 1670 | Matrix3 ret; 1671 | for (int i = 0; i < 9; i++) 1672 | ret.data[i] = data[i] - rhs.data[i]; 1673 | return ret; 1674 | } 1675 | 1676 | //--------------------[ matrix with scalar operations ]--------------------- 1677 | /** 1678 | * Addition operator 1679 | * @param rhs Right hand side argument of binary operator. 1680 | */ 1681 | Matrix3 operator+(T rhs) const 1682 | { 1683 | Matrix3 ret; 1684 | for (int i = 0; i < 9; i++) 1685 | ret.data[i] = data[i] + rhs; 1686 | return ret; 1687 | } 1688 | 1689 | /** 1690 | * Substraction operator 1691 | * @param rhs Right hand side argument of binary operator. 1692 | */ 1693 | Matrix3 operator-(T rhs) const 1694 | { 1695 | Matrix3 ret; 1696 | for (int i = 0; i < 9; i++) 1697 | ret.data[i] = data[i] - rhs; 1698 | return ret; 1699 | } 1700 | 1701 | /** 1702 | * Multiplication operator 1703 | * @param rhs Right hand side argument of binary operator. 1704 | */ 1705 | Matrix3 operator*(T rhs) const 1706 | { 1707 | Matrix3 ret; 1708 | for (int i = 0; i < 9; i++) 1709 | ret.data[i] = data[i] * rhs; 1710 | return ret; 1711 | } 1712 | 1713 | /** 1714 | * Division operator 1715 | * @param rhs Right hand side argument of binary operator. 1716 | */ 1717 | Matrix3 operator/(T rhs) const 1718 | { 1719 | Matrix3 ret; 1720 | for (int i = 0; i < 9; i++) 1721 | ret.data[i] = data[i] / rhs; 1722 | return ret; 1723 | } 1724 | 1725 | 1726 | //--------------------[ multiply operators ]-------------------------------- 1727 | /** 1728 | * Multiplication operator 1729 | * @param rhs Right hand side argument of binary operator. 1730 | */ 1731 | Vector3 operator*(const Vector3& rhs) const 1732 | { 1733 | return Vector3( 1734 | data[0] * rhs.x + data[3] * rhs.y + data[6] * rhs.z, 1735 | data[1] * rhs.x + data[4] * rhs.y + data[7] * rhs.z, 1736 | data[2] * rhs.x + data[5] * rhs.y + data[8] * rhs.z 1737 | ); 1738 | } 1739 | 1740 | /** 1741 | * Multiplication operator 1742 | * @param rhs Right hand side argument of binary operator. 1743 | */ 1744 | Matrix3 operator*(Matrix3 rhs) const 1745 | { 1746 | static Matrix3 w; 1747 | for (int i = 0; i < 3; i++) 1748 | { 1749 | for (int j = 0; j < 3; j++) 1750 | { 1751 | T n = 0; 1752 | for (int k = 0; k < 3; k++) n += rhs.at(i, k) * at(k, j); 1753 | w.at(i, j) = n; 1754 | } 1755 | } 1756 | return w; 1757 | 1758 | } 1759 | 1760 | 1761 | //---------------------------[ misc operations ]---------------------------- 1762 | /** 1763 | * Transpose matrix. 1764 | */ 1765 | Matrix3 transpose() 1766 | { 1767 | Matrix3 ret; 1768 | for (int i = 0; i < 3; i++) 1769 | { 1770 | for (int j = 0; j < 3; j++) 1771 | { 1772 | ret.at(i,j) = at(j,i); 1773 | } 1774 | } 1775 | return ret; 1776 | } 1777 | 1778 | /** 1779 | * Linear interpolation of two vectors 1780 | * @param fact Factor of interpolation. For translation from positon 1781 | * of this matrix (lhs) to matrix rhs, values of factor goes from 0.0 to 1.0. 1782 | * @param rhs Second Matrix for interpolation 1783 | * @note Hovewer values of fact parameter are reasonable only in interval 1784 | * [0.0 , 1.0], you can pass also values outside of this interval and you 1785 | * can get result (extrapolation?) 1786 | */ 1787 | Matrix3 lerp(T fact, const Matrix3& rhs) const 1788 | { 1789 | Matrix3 ret = (*this) + (rhs - (*this)) * fact; 1790 | return ret; 1791 | } 1792 | 1793 | 1794 | //-------------[ conversion ]----------------------------- 1795 | 1796 | /** 1797 | * Conversion to pointer operator 1798 | * @return Pointer to internaly stored (in managment of class Matrix3) 1799 | * used for passing Matrix3 values to gl*[fd]v functions. 1800 | */ 1801 | operator T*(){ return (T*) data; } 1802 | 1803 | /** 1804 | * Conversion to pointer operator 1805 | * @return Constant Pointer to internaly stored (in managment of class Matrix3) 1806 | * used for passing Matrix3 values to gl*[fd]v functions. 1807 | */ 1808 | operator const T*() const { return (const T*) data; } 1809 | 1810 | //----------[ output operator ]---------------------------- 1811 | /** 1812 | * Output to stream operator 1813 | * @param lhs Left hand side argument of operator (commonly ostream instance). 1814 | * @param rhs Right hand side argument of operator. 1815 | * @return Left hand side argument - the ostream object passed to operator. 1816 | */ 1817 | friend std::ostream& operator << (std::ostream& lhs, const Matrix3& rhs) 1818 | { 1819 | for (int i = 0; i < 3; i++) 1820 | { 1821 | lhs << "|\t"; 1822 | for (int j = 0; j < 3; j++) 1823 | { 1824 | lhs << rhs.at(j,i) << "\t"; 1825 | } 1826 | lhs << "|" << std::endl; 1827 | } 1828 | return lhs; 1829 | } 1830 | 1831 | }; 1832 | 1833 | /// Matrix 3x3 of floats 1834 | typedef Matrix3 Matrix3f; 1835 | /// Matrix 3x3 of doubles 1836 | typedef Matrix3 Matrix3d; 1837 | 1838 | 1839 | /** 1840 | * Class for matrix 4x4 1841 | * @note Data stored in this matrix are in column major order. 1842 | */ 1843 | template 1844 | class Matrix4 1845 | { 1846 | public: 1847 | /// Data stored in column major order 1848 | T data[16]; 1849 | 1850 | //--------------------------[ constructors ]------------------------------- 1851 | /** 1852 | *Creates identity matrix 1853 | */ 1854 | Matrix4() 1855 | { 1856 | for (int i = 0; i < 16; i++) 1857 | data[i] = (i % 5) ? 0 : 1; 1858 | } 1859 | 1860 | /** 1861 | * Copy matrix values from array (these data must be in column 1862 | * major order!) 1863 | */ 1864 | Matrix4(const T * dt) 1865 | { 1866 | std::memcpy(data, dt, sizeof(T) * 16); 1867 | } 1868 | 1869 | /** 1870 | * Copy constructor. 1871 | * @param src Data source for new created instance of Matrix4. 1872 | */ 1873 | Matrix4(const Matrix4& src) 1874 | { 1875 | std::memcpy(data, src.data, sizeof(T) * 16); 1876 | } 1877 | 1878 | /** 1879 | * Copy casting constructor. 1880 | * @param src Data source for new created instance of Matrix4. 1881 | */ 1882 | template 1883 | Matrix4(const Matrix4& src) 1884 | { 1885 | for (int i = 0; i < 16; i++) 1886 | { 1887 | data[i] = static_cast(src.data[i]); 1888 | } 1889 | } 1890 | 1891 | /** 1892 | * Resets matrix to be identity matrix 1893 | */ 1894 | void identity() 1895 | { 1896 | for (int i = 0; i < 16; i++) 1897 | data[i] = (i % 5) ? 0 : 1; 1898 | } 1899 | 1900 | 1901 | 1902 | /** 1903 | * Creates rotation matrix by rotation around axis. 1904 | * @param a Angle (in radians) of rotation around axis X. 1905 | * @param b Angle (in radians) of rotation around axis Y. 1906 | * @param c Angle (in radians) of rotation around axis Z. 1907 | */ 1908 | static Matrix4 createRotationAroundAxis(T a, T b, T c) 1909 | { 1910 | Matrix4 ma, mb, mc; 1911 | float ac = cos(a); 1912 | float as = sin(a); 1913 | float bc = cos(b); 1914 | float bs = sin(b); 1915 | float cc = cos(c); 1916 | float cs = sin(c); 1917 | 1918 | ma.at(1,1) = ac; 1919 | ma.at(2,1) = as; 1920 | ma.at(1,2) = -as; 1921 | ma.at(2,2) = ac; 1922 | 1923 | mb.at(0,0) = bc; 1924 | mb.at(2,0) = -bs; 1925 | mb.at(0,2) = bs; 1926 | mb.at(2,2) = bc; 1927 | 1928 | mc.at(0,0) = cc; 1929 | mc.at(1,0) = cs; 1930 | mc.at(0,1) = -cs; 1931 | mc.at(1,1) = cc; 1932 | 1933 | /*std::cout << "RotVec = " << a << "," << b << "," << c << std::endl; 1934 | std::cout << "Rx = " << std::endl << ma; 1935 | std::cout << "Ry = " << std::endl << mb; 1936 | std::cout << "Rz = " << std::endl << mc;*/ 1937 | 1938 | Matrix4 ret = ma * mb * mc; 1939 | //std::cout << "Result = " << std::endl << ma * (mb * mc); 1940 | 1941 | return ret; 1942 | } 1943 | 1944 | /// Creates translation matrix 1945 | /** 1946 | * Creates translation matrix. 1947 | * @param x X-direction translation 1948 | * @param y Y-direction translation 1949 | * @param z Z-direction translation 1950 | * @param w for W-coordinate translation (impictily set to 1) 1951 | */ 1952 | static Matrix4 createTranslation(T x, T y, T z, T w = 1) 1953 | { 1954 | Matrix4 ret; 1955 | ret.at(3,0) = x; 1956 | ret.at(3,1) = y; 1957 | ret.at(3,2) = z; 1958 | ret.at(3,3) = w; 1959 | 1960 | return ret; 1961 | } 1962 | 1963 | 1964 | //---------------------[ equiality operators ]------------------------------ 1965 | /** 1966 | * Equality test operator 1967 | * @param rhs Right hand side argument of binary operator. 1968 | * @note Test of equality is based of threshold EPSILON value. To be two 1969 | * values equal, must satisfy this condition all elements of matrix 1970 | * | lws[i] - rhs[i] | < EPSILON, 1971 | * same for y-coordinate, z-coordinate, and w-coordinate. 1972 | */ 1973 | bool operator==(const Matrix4& rhs) const 1974 | { 1975 | for (int i = 0; i < 16; i++) 1976 | { 1977 | if (std::fabs(data[i] - rhs.data[i]) >= EPSILON) 1978 | return false; 1979 | } 1980 | return true; 1981 | } 1982 | 1983 | /** 1984 | * Inequality test operator 1985 | * @param rhs Right hand side argument of binary operator. 1986 | * @return not (lhs == rhs) :-P 1987 | */ 1988 | bool operator!=(const Matrix4& rhs) const 1989 | { 1990 | return !(*this == rhs); 1991 | } 1992 | 1993 | 1994 | //---------------------[ access operators ]--------------------------------- 1995 | /** 1996 | * Get reference to element at postion (x,y). 1997 | * @param x Number of column (0..3) 1998 | * @param y Number of row (0..3) 1999 | */ 2000 | T& at(int x, int y) 2001 | { 2002 | assert(x >= 0 && x < 4); 2003 | assert(y >= 0 && y < 4); 2004 | return data[x * 4 + y]; 2005 | } 2006 | 2007 | /** 2008 | * Get constant reference to element at postion (x,y). 2009 | * @param x Number of column (0..3) 2010 | * @param y Number of row (0..3) 2011 | */ 2012 | const T& at(int x, int y) const 2013 | { 2014 | assert(x >= 0 && x < 4); 2015 | assert(y >= 0 && y < 4); 2016 | return data[x * 4 + y]; 2017 | } 2018 | 2019 | 2020 | /** 2021 | * Sets translation part of matrix. 2022 | * 2023 | * @param v Vector of translation to be set. 2024 | */ 2025 | void setTranslation(const Vector3& v) 2026 | { 2027 | at(3,0) = v.x; 2028 | at(3,1) = v.y; 2029 | at(3,2) = v.z; 2030 | at(3,3) = 1; 2031 | } 2032 | 2033 | Vector3 getTranslation() 2034 | { return Vector3(at(3,0),at(3,1),at(3,2)); } 2035 | 2036 | /** 2037 | * Sets roation part (matrix 3x3) of matrix. 2038 | * 2039 | * @param m Rotation part of matrix 2040 | */ 2041 | void setRotation(const Matrix3& m) 2042 | { 2043 | for (int i = 0; i < 3; i++) 2044 | { 2045 | for (int j = 0; j < 3; j++) 2046 | { 2047 | at(i,j) = m.at(i,j); 2048 | } 2049 | } 2050 | } 2051 | 2052 | 2053 | /** 2054 | * Copy operator 2055 | * @param rhs Right hand side argument of binary operator. 2056 | */ 2057 | Matrix4& operator=(const Matrix4& rhs) 2058 | { 2059 | std::memcpy(data, rhs.data, sizeof(T) * 16); 2060 | return * this; 2061 | } 2062 | 2063 | /** 2064 | * Copy casting operator 2065 | * @param rhs Right hand side argument of binary operator. 2066 | */ 2067 | template 2068 | Matrix4& operator=(const Matrix4& rhs) 2069 | { 2070 | for (int i = 0; i < 16; i++) 2071 | { 2072 | data[i] = static_cast(rhs.data[i]); 2073 | } 2074 | return * this; 2075 | } 2076 | 2077 | /** 2078 | * Copy operator 2079 | * @param rhs Right hand side argument of binary operator. 2080 | */ 2081 | Matrix4& operator=(const T* rhs) 2082 | { 2083 | std::memcpy(data, rhs, sizeof(T) * 16); 2084 | return * this; 2085 | } 2086 | 2087 | /*Matrix4 & operator=(const double* m) 2088 | { 2089 | for (int i = 0; i < 16; i++) data[i] = (T)m[i]; 2090 | return * this; 2091 | }*/ 2092 | 2093 | //--------------------[ matrix with matrix operations ]--------------------- 2094 | /** 2095 | * Addition operator 2096 | * @param rhs Right hand side argument of binary operator. 2097 | */ 2098 | Matrix4 operator+(const Matrix4& rhs) const 2099 | { 2100 | Matrix4 ret; 2101 | for (int i = 0; i < 16; i++) 2102 | ret.data[i] = data[i] + rhs.data[i]; 2103 | return ret; 2104 | } 2105 | 2106 | /** 2107 | * Substraction operator 2108 | * @param rhs Right hand side argument of binary operator. 2109 | */ 2110 | Matrix4 operator-(const Matrix4& rhs) const 2111 | { 2112 | Matrix4 ret; 2113 | for (int i = 0; i < 16; i++) 2114 | ret.data[i] = data[i] - rhs.data[i]; 2115 | return ret; 2116 | } 2117 | 2118 | //--------------------[ matrix with scalar operations ]--------------------- 2119 | /** 2120 | * Addition operator 2121 | * @param rhs Right hand side argument of binary operator. 2122 | */ 2123 | Matrix4 operator+(T rhs) const 2124 | { 2125 | Matrix4 ret; 2126 | for (int i = 0; i < 16; i++) 2127 | ret.data[i] = data[i] + rhs; 2128 | return ret; 2129 | } 2130 | 2131 | /** 2132 | * Substraction operator 2133 | * @param rhs Right hand side argument of binary operator. 2134 | */ 2135 | Matrix4 operator-(T rhs) const 2136 | { 2137 | Matrix4 ret; 2138 | for (int i = 0; i < 16; i++) 2139 | ret.data[i] = data[i] - rhs; 2140 | return ret; 2141 | } 2142 | 2143 | /** 2144 | * Multiplication operator 2145 | * @param rhs Right hand side argument of binary operator. 2146 | */ 2147 | Matrix4 operator*(T rhs) const 2148 | { 2149 | Matrix4 ret; 2150 | for (int i = 0; i < 16; i++) 2151 | ret.data[i] = data[i] * rhs; 2152 | return ret; 2153 | } 2154 | 2155 | /** 2156 | * Division operator 2157 | * @param rhs Right hand side argument of binary operator. 2158 | */ 2159 | Matrix4 operator/(T rhs) const 2160 | { 2161 | Matrix4 ret; 2162 | for (int i = 0; i < 16; i++) 2163 | ret.data[i] = data[i] / rhs; 2164 | return ret; 2165 | } 2166 | 2167 | 2168 | //--------------------[ multiply operators ]-------------------------------- 2169 | /** 2170 | * Multiplication operator 2171 | * @param rhs Right hand side argument of binary operator. 2172 | */ 2173 | Vector4 operator*(const Vector4& rhs) const 2174 | { 2175 | return Vector4( 2176 | data[0] * rhs.x + data[4] * rhs.y + data[8] * rhs.z + data[12] * rhs.w, 2177 | data[1] * rhs.x + data[5] * rhs.y + data[9] * rhs.z + data[13] * rhs.w, 2178 | data[2] * rhs.x + data[6] * rhs.y + data[10] * rhs.z + data[14] * rhs.w, 2179 | data[3] * rhs.x + data[7] * rhs.y + data[11] * rhs.z + data[15] * rhs.w 2180 | ); 2181 | 2182 | } 2183 | 2184 | /** 2185 | * Multiplication operator 2186 | * @param rhs Right hand side argument of binary operator. 2187 | */ 2188 | Vector3 operator*(const Vector3& rhs) const 2189 | { 2190 | return Vector3( 2191 | data[0] * rhs.x + data[4] * rhs.y + data[8] * rhs.z, 2192 | data[1] * rhs.x + data[5] * rhs.y + data[9] * rhs.z, 2193 | data[2] * rhs.x + data[6] * rhs.y + data[10] * rhs.z 2194 | ); 2195 | } 2196 | 2197 | /** 2198 | * Multiplication operator 2199 | * @param rhs Right hand side argument of binary operator. 2200 | */ 2201 | Matrix4 operator*(Matrix4 rhs) const 2202 | { 2203 | static Matrix4 w; 2204 | for (int i = 0; i < 4; i++) 2205 | { 2206 | for (int j = 0; j < 4; j++) 2207 | { 2208 | T n = 0; 2209 | for (int k = 0; k < 4; k++) n += rhs.at(i, k) * at(k, j); 2210 | w.at(i, j) = n; 2211 | } 2212 | } 2213 | return w; 2214 | 2215 | } 2216 | 2217 | 2218 | //---------------------------[ misc operations ]---------------------------- 2219 | 2220 | /** 2221 | * Computes determinant of matrix 2222 | * @return Determinant of matrix 2223 | * @note This function does 3 * 4 * 6 mul, 3 * 6 add. 2224 | */ 2225 | T det() 2226 | { 2227 | 2228 | return 2229 | + at(3,0) * at(2,1) * at(1,2) * at(0,3) 2230 | - at(2,0) * at(3,1) * at(1,2) * at(0,3) 2231 | - at(3,0) * at(1,1) * at(2,2) * at(0,3) 2232 | + at(1,0) * at(3,1) * at(2,2) * at(0,3) 2233 | 2234 | + at(2,0) * at(1,1) * at(3,2) * at(0,3) 2235 | - at(1,0) * at(2,1) * at(3,2) * at(0,3) 2236 | - at(3,0) * at(2,1) * at(0,2) * at(1,3) 2237 | + at(2,0) * at(3,1) * at(0,2) * at(1,3) 2238 | 2239 | + at(3,0) * at(0,1) * at(2,2) * at(1,3) 2240 | - at(0,0) * at(3,1) * at(2,2) * at(1,3) 2241 | - at(2,0) * at(0,1) * at(3,2) * at(1,3) 2242 | + at(0,0) * at(2,1) * at(3,2) * at(1,3) 2243 | 2244 | + at(3,0) * at(1,1) * at(0,2) * at(2,3) 2245 | - at(1,0) * at(3,1) * at(0,2) * at(2,3) 2246 | - at(3,0) * at(0,1) * at(1,2) * at(2,3) 2247 | + at(0,0) * at(3,1) * at(1,2) * at(2,3) 2248 | 2249 | + at(1,0) * at(0,1) * at(3,2) * at(2,3) 2250 | - at(0,0) * at(1,1) * at(3,2) * at(2,3) 2251 | - at(2,0) * at(1,1) * at(0,2) * at(3,3) 2252 | + at(1,0) * at(2,1) * at(0,2) * at(3,3) 2253 | 2254 | + at(2,0) * at(0,1) * at(1,2) * at(3,3) 2255 | - at(0,0) * at(2,1) * at(1,2) * at(3,3) 2256 | - at(1,0) * at(0,1) * at(2,2) * at(3,3) 2257 | + at(0,0) * at(1,1) * at(2,2) * at(3,3); 2258 | 2259 | 2260 | } 2261 | 2262 | 2263 | /** 2264 | * Computes inverse matrix 2265 | * @return Inverse matrix of this matrix. 2266 | * @note This is a little bit time consuming operation 2267 | * (16 * 6 * 3 mul, 16 * 5 add + det() + mul() functions) 2268 | */ 2269 | Matrix4 inverse() 2270 | { 2271 | Matrix4 ret; 2272 | 2273 | ret.at(0,0) = 2274 | + at(2,1) * at(3,2) * at(1,3) 2275 | - at(3,1) * at(2,2) * at(1,3) 2276 | + at(3,1) * at(1,2) * at(2,3) 2277 | - at(1,1) * at(3,2) * at(2,3) 2278 | - at(2,1) * at(1,2) * at(3,3) 2279 | + at(1,1) * at(2,2) * at(3,3); 2280 | 2281 | ret.at(1,0) = 2282 | + at(3,0) * at(2,2) * at(1,3) 2283 | - at(2,0) * at(3,2) * at(1,3) 2284 | - at(3,0) * at(1,2) * at(2,3) 2285 | + at(1,0) * at(3,2) * at(2,3) 2286 | + at(2,0) * at(1,2) * at(3,3) 2287 | - at(1,0) * at(2,2) * at(3,3); 2288 | 2289 | ret.at(2,0) = 2290 | + at(2,0) * at(3,1) * at(1,3) 2291 | - at(3,0) * at(2,1) * at(1,3) 2292 | + at(3,0) * at(1,1) * at(2,3) 2293 | - at(1,0) * at(3,1) * at(2,3) 2294 | - at(2,0) * at(1,1) * at(3,3) 2295 | + at(1,0) * at(2,1) * at(3,3); 2296 | 2297 | ret.at(3,0) = 2298 | + at(3,0) * at(2,1) * at(1,2) 2299 | - at(2,0) * at(3,1) * at(1,2) 2300 | - at(3,0) * at(1,1) * at(2,2) 2301 | + at(1,0) * at(3,1) * at(2,2) 2302 | + at(2,0) * at(1,1) * at(3,2) 2303 | - at(1,0) * at(2,1) * at(3,2); 2304 | 2305 | ret.at(0,1) = 2306 | + at(3,1) * at(2,2) * at(0,3) 2307 | - at(2,1) * at(3,2) * at(0,3) 2308 | - at(3,1) * at(0,2) * at(2,3) 2309 | + at(0,1) * at(3,2) * at(2,3) 2310 | + at(2,1) * at(0,2) * at(3,3) 2311 | - at(0,1) * at(2,2) * at(3,3); 2312 | 2313 | ret.at(1,1) = 2314 | + at(2,0) * at(3,2) * at(0,3) 2315 | - at(3,0) * at(2,2) * at(0,3) 2316 | + at(3,0) * at(0,2) * at(2,3) 2317 | - at(0,0) * at(3,2) * at(2,3) 2318 | - at(2,0) * at(0,2) * at(3,3) 2319 | + at(0,0) * at(2,2) * at(3,3); 2320 | 2321 | ret.at(2,1) = 2322 | + at(3,0) * at(2,1) * at(0,3) 2323 | - at(2,0) * at(3,1) * at(0,3) 2324 | - at(3,0) * at(0,1) * at(2,3) 2325 | + at(0,0) * at(3,1) * at(2,3) 2326 | + at(2,0) * at(0,1) * at(3,3) 2327 | - at(0,0) * at(2,1) * at(3,3); 2328 | 2329 | ret.at(3,1) = 2330 | + at(2,0) * at(3,1) * at(0,2) 2331 | - at(3,0) * at(2,1) * at(0,2) 2332 | + at(3,0) * at(0,1) * at(2,2) 2333 | - at(0,0) * at(3,1) * at(2,2) 2334 | - at(2,0) * at(0,1) * at(3,2) 2335 | + at(0,0) * at(2,1) * at(3,2); 2336 | 2337 | ret.at(0,2) = 2338 | + at(1,1) * at(3,2) * at(0,3) 2339 | - at(3,1) * at(1,2) * at(0,3) 2340 | + at(3,1) * at(0,2) * at(1,3) 2341 | - at(0,1) * at(3,2) * at(1,3) 2342 | - at(1,1) * at(0,2) * at(3,3) 2343 | + at(0,1) * at(1,2) * at(3,3); 2344 | 2345 | ret.at(1,2) = 2346 | + at(3,0) * at(1,2) * at(0,3) 2347 | - at(1,0) * at(3,2) * at(0,3) 2348 | - at(3,0) * at(0,2) * at(1,3) 2349 | + at(0,0) * at(3,2) * at(1,3) 2350 | + at(1,0) * at(0,2) * at(3,3) 2351 | - at(0,0) * at(1,2) * at(3,3); 2352 | 2353 | ret.at(2,2) = 2354 | + at(1,0) * at(3,1) * at(0,3) 2355 | - at(3,0) * at(1,1) * at(0,3) 2356 | + at(3,0) * at(0,1) * at(1,3) 2357 | - at(0,0) * at(3,1) * at(1,3) 2358 | - at(1,0) * at(0,1) * at(3,3) 2359 | + at(0,0) * at(1,1) * at(3,3); 2360 | 2361 | ret.at(3,2) = 2362 | + at(3,0) * at(1,1) * at(0,2) 2363 | - at(1,0) * at(3,1) * at(0,2) 2364 | - at(3,0) * at(0,1) * at(1,2) 2365 | + at(0,0) * at(3,1) * at(1,2) 2366 | + at(1,0) * at(0,1) * at(3,2) 2367 | - at(0,0) * at(1,1) * at(3,2); 2368 | 2369 | ret.at(0,3) = 2370 | + at(2,1) * at(1,2) * at(0,3) 2371 | - at(1,1) * at(2,2) * at(0,3) 2372 | - at(2,1) * at(0,2) * at(1,3) 2373 | + at(0,1) * at(2,2) * at(1,3) 2374 | + at(1,1) * at(0,2) * at(2,3) 2375 | - at(0,1) * at(1,2) * at(2,3); 2376 | 2377 | ret.at(1,3) = 2378 | + at(1,0) * at(2,2) * at(0,3) 2379 | - at(2,0) * at(1,2) * at(0,3) 2380 | + at(2,0) * at(0,2) * at(1,3) 2381 | - at(0,0) * at(2,2) * at(1,3) 2382 | - at(1,0) * at(0,2) * at(2,3) 2383 | + at(0,0) * at(1,2) * at(2,3); 2384 | 2385 | ret.at(2,3) = 2386 | + at(2,0) * at(1,1) * at(0,3) 2387 | - at(1,0) * at(2,1) * at(0,3) 2388 | - at(2,0) * at(0,1) * at(1,3) 2389 | + at(0,0) * at(2,1) * at(1,3) 2390 | + at(1,0) * at(0,1) * at(2,3) 2391 | - at(0,0) * at(1,1) * at(2,3); 2392 | 2393 | ret.at(3,3) = 2394 | + at(1,0) * at(2,1) * at(0,2) 2395 | - at(2,0) * at(1,1) * at(0,2) 2396 | + at(2,0) * at(0,1) * at(1,2) 2397 | - at(0,0) * at(2,1) * at(1,2) 2398 | - at(1,0) * at(0,1) * at(2,2) 2399 | + at(0,0) * at(1,1) * at(2,2); 2400 | 2401 | return ret * det(); 2402 | } 2403 | 2404 | 2405 | 2406 | /** 2407 | * Transpose matrix. 2408 | */ 2409 | Matrix4 transpose() 2410 | { 2411 | Matrix4 ret; 2412 | for (int i = 0; i < 4; i++) 2413 | { 2414 | for (int j = 0; j < 4; j++) 2415 | { 2416 | ret.at(i,j) = at(j,i); 2417 | } 2418 | } 2419 | return ret; 2420 | } 2421 | 2422 | /** 2423 | * Linear interpolation of two vectors 2424 | * @param fact Factor of interpolation. For translation from positon 2425 | * of this matrix (lhs) to matrix rhs, values of factor goes from 0.0 to 1.0. 2426 | * @param rhs Second Matrix for interpolation 2427 | * @note Hovewer values of fact parameter are reasonable only in interval 2428 | * [0.0 , 1.0], you can pass also values outside of this interval and you 2429 | * can get result (extrapolation?) 2430 | */ 2431 | Matrix4 lerp(T fact, const Matrix4& rhs) const 2432 | { 2433 | Matrix4 ret = (*this) + (rhs - (*this)) * fact; 2434 | return ret; 2435 | } 2436 | 2437 | 2438 | //-------------[ conversion ]----------------------------- 2439 | /** 2440 | * Conversion to pointer operator 2441 | * @return Pointer to internaly stored (in managment of class Matrix4) 2442 | * used for passing Matrix4 values to gl*[fd]v functions. 2443 | */ 2444 | operator T*(){ return (T*) data; } 2445 | 2446 | /** 2447 | * Conversion to pointer operator 2448 | * @return Constant Pointer to internaly stored (in managment of class Matrix4) 2449 | * used for passing Matrix4 values to gl*[fd]v functions. 2450 | */ 2451 | operator const T*() const { return (const T*) data; } 2452 | 2453 | //----------[ output operator ]---------------------------- 2454 | /** 2455 | * Output to stream operator 2456 | * @param lhs Left hand side argument of operator (commonly ostream instance). 2457 | * @param rhs Right hand side argument of operator. 2458 | * @return Left hand side argument - the ostream object passed to operator. 2459 | */ 2460 | friend std::ostream& operator << (std::ostream& lhs, const Matrix4& rhs) 2461 | { 2462 | for (int i = 0; i < 4; i++) 2463 | { 2464 | lhs << "|\t"; 2465 | for (int j = 0; j < 4; j++) 2466 | { 2467 | lhs << rhs.at(j,i) << "\t"; 2468 | } 2469 | lhs << "|" << std::endl; 2470 | } 2471 | return lhs; 2472 | } 2473 | 2474 | }; 2475 | 2476 | 2477 | /// Matrix 3x3 of floats 2478 | typedef Matrix4 Matrix4f; 2479 | /// Matrix 3x3 of doubles 2480 | typedef Matrix4 Matrix4d; 2481 | 2482 | 2483 | /** 2484 | * Quaternion class implementing some quaternion algebra operations. 2485 | * Quaternion is kind of complex number it consists of its real part (w) 2486 | * and its complex part v. This complex part has three elements, so we 2487 | * can express it as xi + yj + zk . Note that coordinates of (x,y,z) are 2488 | * hold inside v field. 2489 | */ 2490 | template 2491 | class Quaternion 2492 | { 2493 | public: 2494 | /** 2495 | * Real part of quaternion. 2496 | */ 2497 | T w; 2498 | /** 2499 | * Complex part of quaternion. 2500 | */ 2501 | Vector3 v; 2502 | 2503 | /** 2504 | * Quaternion constructor, sets quaternion to (0 + 0i + 0j + 0k). 2505 | */ 2506 | Quaternion(): w(0), v(0,0,0){} 2507 | 2508 | /** 2509 | * Copy constructor. 2510 | */ 2511 | Quaternion(const Quaternion& q): w(q.w), v(q.v){ } 2512 | 2513 | /** 2514 | * Copy casting constructor. 2515 | */ 2516 | template 2517 | Quaternion(const Quaternion& q) 2518 | : w(static_cast(q.w)), 2519 | v(q.v){ } 2520 | 2521 | 2522 | /** 2523 | * Creates quaternion object from real part w_ and complex part v_. 2524 | * @param w_ Real part of quaternion. 2525 | * @param v_ Complex part of quaternion (xi + yj + zk). 2526 | */ 2527 | Quaternion(T w_, const Vector3& v_): w(w_), v(v_){} 2528 | 2529 | /** 2530 | * Creates quaternion object from value (w_ + xi + yj + zk). 2531 | * @param w_ Real part of quaternion. 2532 | * @param x Complex cooeficinet for i complex constant. 2533 | * @param y Complex cooeficinet for j complex constant. 2534 | * @param z Complex cooeficinet for k complex constant. 2535 | */ 2536 | Quaternion(T w_, T x, T y, T z): w(w_), v(x,y,z){} 2537 | 2538 | /** 2539 | * Copy operator 2540 | * @param rhs Right hand side argument of binary operator. 2541 | */ 2542 | Quaternion& operator= (const Quaternion& rhs) 2543 | { 2544 | v = rhs.v; 2545 | w = rhs.w; 2546 | return *this; 2547 | } 2548 | 2549 | /** 2550 | * Copy convert operator 2551 | * @param rhs Right hand side argument of binary operator. 2552 | */ 2553 | template 2554 | Quaternion& operator= (const Quaternion& rhs) 2555 | { 2556 | v = rhs.v; 2557 | w = static_cast(rhs.w); 2558 | return *this; 2559 | } 2560 | 2561 | /** 2562 | * Addition operator 2563 | * @param rhs Right hand side argument of binary operator. 2564 | */ 2565 | Quaternion operator+ (const Quaternion& rhs) const 2566 | { 2567 | const Quaternion& lhs = *this; 2568 | return Quaternion(lhs.w + rhs.w, lhs.v + rhs.v); 2569 | } 2570 | 2571 | /** 2572 | * Multiplication operator 2573 | * @param rhs Right hand side argument of binary operator. 2574 | */ 2575 | Quaternion operator* (const Quaternion& rhs) const 2576 | { 2577 | const Quaternion& lhs = *this; 2578 | return Quaternion( 2579 | lhs.w * rhs.w - lhs.v.x * rhs.v.x - lhs.v.y * rhs.v.y - lhs.v.z * rhs.v.z, 2580 | lhs.w * rhs.v.x + lhs.v.x * rhs.w + lhs.v.y * rhs.v.z - lhs.v.z * rhs.v.y, 2581 | lhs.w * rhs.v.y - lhs.v.x * rhs.v.z + lhs.v.y * rhs.w + lhs.v.z * rhs.v.x, 2582 | lhs.w * rhs.v.z + lhs.v.x * rhs.v.y - lhs.v.y * rhs.v.x + lhs.v.z * rhs.w 2583 | ); 2584 | } 2585 | 2586 | /** 2587 | * Multiplication operator 2588 | * @param rhs Right hand side argument of binary operator. 2589 | */ 2590 | Quaternion operator* (T rhs) const 2591 | { 2592 | return Quaternion(w*rhs, v*rhs); 2593 | } 2594 | 2595 | /** 2596 | * Substraction operator 2597 | * @param rhs Right hand side argument of binary operator. 2598 | */ 2599 | Quaternion operator- (const Quaternion& rhs) const 2600 | { 2601 | const Quaternion& lhs = *this; 2602 | return Quaternion(lhs.w - rhs.w, lhs.v - rhs.v); 2603 | } 2604 | 2605 | /** 2606 | * Addition operator 2607 | * @param rhs Right hand side argument of binary operator. 2608 | */ 2609 | Quaternion& operator+= (const Quaternion& rhs) 2610 | { 2611 | w += rhs.w; 2612 | v += rhs.v; 2613 | return *this; 2614 | } 2615 | 2616 | /** 2617 | * Substraction operator 2618 | * @param rhs Right hand side argument of binary operator. 2619 | */ 2620 | Quaternion& operator-= (const Quaternion& rhs) 2621 | { 2622 | w -= rhs.w; 2623 | v -= rhs.v; 2624 | return *this; 2625 | } 2626 | 2627 | /** 2628 | * Multiplication operator 2629 | * @param rhs Right hand side argument of binary operator. 2630 | */ 2631 | Quaternion& operator*= (const Quaternion& rhs) 2632 | { 2633 | Quaternion q = (*this) * rhs; 2634 | v = q.v; 2635 | w = q.w; 2636 | return *this; 2637 | } 2638 | 2639 | /** 2640 | * Multiplication operator 2641 | * @param rhs Right hand side argument of binary operator. 2642 | */ 2643 | Quaternion& operator*= (T rhs) 2644 | { 2645 | w *= rhs; 2646 | v *= rhs; 2647 | return *this; 2648 | } 2649 | 2650 | /** 2651 | * Equality test operator 2652 | * @param rhs Right hand side argument of binary operator. 2653 | * @note Test of equality is based of threshold EPSILON value. To be two 2654 | * values equal, must satisfy this condition | lws - rhs | < EPSILON, 2655 | * for all quaternion coordinates. 2656 | */ 2657 | bool operator==(const Quaternion& rhs) const 2658 | { 2659 | const Quaternion& lhs = *this; 2660 | return (std::fabs(lhs.w - rhs.w) < EPSILON) && lhs.v == rhs.v; 2661 | } 2662 | 2663 | /** 2664 | * Inequality test operator 2665 | * @param rhs Right hand side argument of binary operator. 2666 | * @return not (lhs == rhs) :-P 2667 | */ 2668 | bool operator!=(const Quaternion& rhs) const { return ! (*this == rhs); } 2669 | 2670 | //-------------[ unary operations ]-------------------------- 2671 | /** 2672 | * Unary negate operator 2673 | * @return negated quaternion 2674 | */ 2675 | Quaternion operator-() const 2676 | { 2677 | return Quaternion(-w, -v); 2678 | } 2679 | 2680 | /** 2681 | * Unary conjugate operator 2682 | * @return conjugated quaternion 2683 | */ 2684 | Quaternion operator~() const 2685 | { 2686 | return Quaternion(w, -v); 2687 | } 2688 | 2689 | /** 2690 | * Get lenght of quaternion. 2691 | * @return Length of quaternion. 2692 | */ 2693 | T length() const 2694 | { 2695 | return (T)std::sqrt(w*w + v.lengthSq()); 2696 | } 2697 | 2698 | /** 2699 | * Return square of length. 2700 | * @return lenght ^ 2 2701 | * @note This method is faster then length(). For comparsion 2702 | * of length of two quaternion can be used just this value, instead 2703 | * of computionaly more expensive length() method. 2704 | */ 2705 | T lengthSq() const 2706 | { 2707 | return w * w + v.lengthSq(); 2708 | } 2709 | 2710 | 2711 | /** 2712 | * Normalize quaternion 2713 | */ 2714 | void normalize() 2715 | { 2716 | T len = length(); 2717 | w /= len; 2718 | v /= len; 2719 | } 2720 | 2721 | /** 2722 | * Creates quaternion for eulers angles. 2723 | * @param x Rotation around x axis (in degrees). 2724 | * @param y Rotation around y axis (in degrees). 2725 | * @param z Rotation around z axis (in degrees). 2726 | * @return Quaternion object representing transoformation. 2727 | */ 2728 | static Quaternion fromEulerAngles(T x, T y, T z) 2729 | { 2730 | Quaternion ret = fromAxisRot(Vector3(1,0,0), x) 2731 | * fromAxisRot(Vector3(0,1,0),y) * fromAxisRot(Vector3(0,0,1),z); 2732 | return ret; 2733 | } 2734 | 2735 | /** 2736 | * Creates quaternion as rotation around axis. 2737 | * @param axis Unit vector expressing axis of rotation. 2738 | * @param angleDeg Angle of rotation around axis (in degrees). 2739 | */ 2740 | static Quaternion fromAxisRot(Vector3 axis, float angleDeg) 2741 | { 2742 | double angleRad = DEG2RAD(angleDeg); 2743 | double sa2 = std::sin(angleRad/2); 2744 | double ca2 = std::cos(angleRad/2); 2745 | return Quaternion( ca2, axis * sa2); 2746 | } 2747 | 2748 | /** 2749 | * Converts quaternion into rotation matrix. 2750 | * @return Rotation matrix expresing this quaternion. 2751 | */ 2752 | Matrix3 rotMatrix() 2753 | { 2754 | Matrix3 ret; 2755 | 2756 | /*ret.at(0,0) = 1 - 2*v.y*v.y - 2*v.z*v.z; 2757 | ret.at(1,0) = 2*v.x*v.y - 2*w*v.z; 2758 | ret.at(2,0) = 2*v.x*v.z - 2*w*v.y; 2759 | 2760 | ret.at(0,1) = 2*v.x*v.y + 2*w*v.z; 2761 | ret.at(1,1) = 1 - 2*v.x*v.x - 2*v.z*v.z; 2762 | ret.at(2,1) = 2*v.y*v.z - 2*w*v.x; 2763 | 2764 | ret.at(0,2) = 2*v.x*v.z - 2*w*v.y; 2765 | ret.at(1,2) = 2*v.y*v.z + 2*w*v.x; 2766 | ret.at(2,2) = 1 - 2*v.x*v.x - 2*v.y*v.y;*/ 2767 | 2768 | T xx = v.x * v.x; 2769 | T xy = v.x * v.y; 2770 | T xz = v.x * v.z; 2771 | T xw = v.x * w; 2772 | 2773 | T yy = v.y * v.y; 2774 | T yz = v.y * v.z; 2775 | T yw = v.y * w; 2776 | 2777 | T zz = v.z * v.z; 2778 | T zw = v.z * w; 2779 | 2780 | ret.at(0,0) = 1 - 2 * (yy + zz); 2781 | ret.at(1,0) = 2 * (xy - zw); 2782 | ret.at(2,0) = 2 * (xz + yw); 2783 | 2784 | ret.at(0,1) = 2 * (xy + zw); 2785 | ret.at(1,1) = 1 - 2 * (xx + zz); 2786 | ret.at(2,1) = 2 * (yz - xw); 2787 | 2788 | ret.at(0,2) = 2 * (xz - yw); 2789 | ret.at(1,2) = 2 * (yz + xw); 2790 | ret.at(2,2) = 1 - 2 * (xx + yy); 2791 | 2792 | 2793 | return ret; 2794 | } 2795 | 2796 | /** 2797 | * Converts quaternion into transformation matrix. 2798 | * @note This method performs same operation as rotMatrix() 2799 | * conversion method. But returns Matrix of 4x4 elements. 2800 | * @return Transformation matrix expressing this quaternion. 2801 | */ 2802 | Matrix4 transform() 2803 | { 2804 | Matrix4 ret; 2805 | 2806 | T xx = v.x * v.x; 2807 | T xy = v.x * v.y; 2808 | T xz = v.x * v.z; 2809 | T xw = v.x * w; 2810 | 2811 | T yy = v.y * v.y; 2812 | T yz = v.y * v.z; 2813 | T yw = v.y * w; 2814 | 2815 | T zz = v.z * v.z; 2816 | T zw = v.z * w; 2817 | 2818 | ret.at(0,0) = 1 - 2 * (yy + zz); 2819 | ret.at(1,0) = 2 * (xy - zw); 2820 | ret.at(2,0) = 2 * (xz + yw); 2821 | ret.at(3,0) = 0; 2822 | 2823 | ret.at(0,1) = 2 * (xy + zw); 2824 | ret.at(1,1) = 1 - 2 * (xx + zz); 2825 | ret.at(2,1) = 2 * (yz - xw); 2826 | ret.at(3,1) = 0; 2827 | 2828 | ret.at(0,2) = 2 * (xz - yw); 2829 | ret.at(1,2) = 2 * (yz + xw); 2830 | ret.at(2,2) = 1 - 2 * (xx + yy); 2831 | ret.at(3,2) = 0; 2832 | 2833 | ret.at(0,3) = 0; 2834 | ret.at(1,3) = 0; 2835 | ret.at(2,3) = 0; 2836 | ret.at(3,3) = 1; 2837 | 2838 | return ret; 2839 | 2840 | } 2841 | 2842 | /** 2843 | * Linear interpolation of two quaternions 2844 | * @param fact Factor of interpolation. For translation from positon 2845 | * of this vector to quaternion rhs, values of factor goes from 0.0 to 1.0. 2846 | * @param rhs Second Quaternion for interpolation 2847 | * @note Hovewer values of fact parameter are reasonable only in interval 2848 | * [0.0 , 1.0], you can pass also values outside of this interval and you 2849 | * can get result (extrapolation?) 2850 | */ 2851 | Quaternion lerp(T fact, const Quaternion& rhs) const 2852 | { 2853 | return Quaternion((1-fact) * w + fact * rhs.w, v.lerp(fact, rhs.v)); 2854 | } 2855 | 2856 | /** 2857 | * Provides output to standard output stream. 2858 | */ 2859 | friend std::ostream& operator << (std::ostream& oss, const Quaternion& q) 2860 | { 2861 | oss << "Re: " << q.w << " Im: " << q.v; 2862 | return oss; 2863 | } 2864 | 2865 | /** 2866 | * Creates quaternion from transform matrix. 2867 | * 2868 | * @param m Transfrom matrix used to compute quaternion. 2869 | * @return Quaternion representing rotation of matrix m. 2870 | */ 2871 | static Quaternion fromMatrix(const Matrix4& m) 2872 | { 2873 | Quaternion q; 2874 | 2875 | T tr,s; 2876 | tr = m.at(0,0) + m.at(1,1) + m.at(2,2); 2877 | if (tr >= epsilon) 2878 | { 2879 | s = (T)sqrt(tr + 1); 2880 | q.w = 0.5 * s; 2881 | s = 0.5 / s; 2882 | 2883 | q.v.x = (m.at(1,2) - m.at(2,1)) * s; 2884 | q.v.y = (m.at(2,0) - m.at(0,2)) * s; 2885 | q.v.z = (m.at(0,1) - m.at(1,0)) * s; 2886 | } 2887 | else 2888 | { 2889 | T d0 = m.at(0,0); 2890 | T d1 = m.at(1,1); 2891 | T d2 = m.at(2,2); 2892 | 2893 | char bigIdx = (d0 > d1) ? ((d0 > d2)? 0 : 2) : ((d1 > d2) ? 1 : 2); 2894 | 2895 | if (bigIdx == 0) 2896 | { 2897 | s = (T)sqrt((d0 - (d1 + d2)) + 1); 2898 | 2899 | q.v.x = 0.5 * s; 2900 | s = 0.5 / s; 2901 | q.v.y = (m.at(1,0) + m.at(0,1)) * s; 2902 | q.v.z = (m.at(2,0) + m.at(0,2)) * s; 2903 | q.w = (m.at(1,2) - m.at(2,1)) * s; 2904 | } 2905 | else if (bigIdx == 1) 2906 | { 2907 | s = (T)sqrt(1 + d1 - (d0 + d2)); 2908 | q.v.y = 0.5 * s; 2909 | s = 0.5 / s; 2910 | q.v.z = (m.at(2,1) + m.at(1,2)) / s; 2911 | q.w = (m.at(2,0) - m.at(0,2)) / s; 2912 | q.v.x = (m.at(1,0) + m.at(0,1)) / s; 2913 | } 2914 | else 2915 | { 2916 | s = (T)sqrt(1 + d2 - (d0 + d1)); 2917 | q.v.z = 0.5 * s; 2918 | s = 0.5 / s; 2919 | q.w = (m.at(0,1) - m.at(1,0)) / s; 2920 | q.v.x = (m.at(2,0) + m.at(0,2)) / s; 2921 | q.v.y = (m.at(2,1) + m.at(1,2)) / s; 2922 | } 2923 | } 2924 | 2925 | return q; 2926 | } 2927 | 2928 | /** 2929 | * Creates quaternion from rotation matrix. 2930 | * 2931 | * @param m Rotation matrix used to compute quaternion. 2932 | * @return Quaternion representing rotation of matrix m. 2933 | */ 2934 | static Quaternion fromMatrix(const Matrix3& m) 2935 | { 2936 | Quaternion q; 2937 | 2938 | T tr,s; 2939 | tr = m.at(0,0) + m.at(1,1) + m.at(2,2); 2940 | // if trace is greater or equal then zero 2941 | if (tr >= epsilon) 2942 | { 2943 | s = (T)sqrt(tr + 1); 2944 | q.w = 0.5 * s; 2945 | s = 0.5 / s; 2946 | 2947 | q.v.x = (m.at(1,2) - m.at(2,1)) * s; 2948 | q.v.y = (m.at(2,0) - m.at(0,2)) * s; 2949 | q.v.z = (m.at(0,1) - m.at(1,0)) * s; 2950 | } 2951 | else 2952 | { 2953 | T d0 = m.at(0,0); 2954 | T d1 = m.at(1,1); 2955 | T d2 = m.at(2,2); 2956 | 2957 | // find greates diagonal number 2958 | char bigIdx = (d0 > d1) ? ((d0 > d2)? 0 : 2) : ((d1 > d2) ? 1 : 2); 2959 | 2960 | if (bigIdx == 0) 2961 | { 2962 | s = (T)sqrt((d0 - (d1 + d2)) + 1); 2963 | 2964 | q.v.x = 0.5 * s; 2965 | s = 0.5 / s; 2966 | q.v.y = (m.at(1,0) + m.at(0,1)) * s; 2967 | q.v.z = (m.at(2,0) + m.at(0,2)) * s; 2968 | q.w = (m.at(1,2) - m.at(2,1)) * s; 2969 | } 2970 | else if (bigIdx == 1) 2971 | { 2972 | s = (T)sqrt(1 + d1 - (d0 + d2)); 2973 | q.v.y = 0.5 * s; 2974 | s = 0.5 / s; 2975 | q.v.z = (m.at(2,1) + m.at(1,2)) / s; 2976 | q.w = (m.at(2,0) - m.at(0,2)) / s; 2977 | q.v.x = (m.at(1,0) + m.at(0,1)) / s; 2978 | } 2979 | else 2980 | { 2981 | s = (T)sqrt(1 + d2 - (d0 + d1)); 2982 | q.v.z = 0.5 * s; 2983 | s = 0.5 / s; 2984 | q.w = (m.at(0,1) - m.at(1,0)) / s; 2985 | q.v.x = (m.at(2,0) + m.at(0,2)) / s; 2986 | q.v.y = (m.at(2,1) + m.at(1,2)) / s; 2987 | } 2988 | } 2989 | 2990 | return q; 2991 | } 2992 | 2993 | /** 2994 | * Computes spherical interpolation between quaternions (this, q2) 2995 | * using coeficient of interpolation r (in [0, 1]). 2996 | * 2997 | * @param r The ratio of interpolation form this (r = 0) to q2 (r = 1). 2998 | * @param q2 Second quaternion for interpolation. 2999 | * @return Result of interpolation. 3000 | */ 3001 | Quaternion slerp(T r, const Quaternion& q2) const 3002 | { 3003 | Quaternion ret; 3004 | T cosTheta = w * q2.w + v.x * q2.v.x + v.y *q2.v.y + v.z * q2.v.z; 3005 | T theta = (T) acos(cosTheta); 3006 | if (fabs(theta) < epsilon) 3007 | { 3008 | ret = *this; 3009 | } 3010 | else 3011 | { 3012 | T sinTheta = (T)sqrt(1.0 - cosTheta * cosTheta); 3013 | if (fabs(sinTheta) < epsilon) 3014 | { 3015 | ret.w = 0.5 * w + 0.5 * q2.w; 3016 | ret.v = v.lerp(0.5, q2.v); 3017 | } 3018 | else 3019 | { 3020 | T rA = (T)sin((1.0 - r) * theta) / sinTheta; 3021 | T rB = (T)sin(r * theta) / sinTheta; 3022 | 3023 | ret.w = w * rA + q2.w * rB; 3024 | ret.v.x = v.x * rA + q2.v.x * rB; 3025 | ret.v.y = v.y * rA + q2.v.y * rB; 3026 | ret.v.z = v.z * rA + q2.v.z * rB; 3027 | } 3028 | } 3029 | return ret; 3030 | } 3031 | 3032 | 3033 | 3034 | }; 3035 | 3036 | typedef Quaternion Quatf; 3037 | typedef Quaternion Quatd; 3038 | 3039 | 3040 | 3041 | #ifdef VMATH_NAMESPACE 3042 | } 3043 | #endif 3044 | 3045 | #endif // __vmath_Header_File__ 3046 | 3047 | 3048 | --------------------------------------------------------------------------------