/* orxonox - the future of 3D-vertical scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: David Gruetter co-programmer: ... Created by Dave, in this file shadow will be implemented in a quite sexy and fast way, with a lot of opengl-code, to keep it fast! The origin of the code comes form an example at www.frustum.org, slitly different although, so that it works with Orxonox:) */ #include "importer/material.h" #include "stdincl.h" #include #include #include #include #include "shadow.h" #define SIZE 128 #define GL_CLAMP_TO_EDGE_EXT 0x812F using namespace std; /** \brief default Constructor */ Shadow::Shadow(Model* player,float* groundVertexes) { this->player=player; } /** \brief default destructor */ Shadow::~Shadow() { } void Shadow::init() { float plane_s[] ={1.0f,0.0f,0.0f,0.0f}; float plane_t[] ={0.0f,1.0f,0.0f,0.0f}; float plane_r[] ={0.0f,0.0f,1.0f,0.0f}; float plane_q[] ={0.0f,0.0f,0.0f,1.0f}; glClearDepth(1); glDepthFunc(GL_LEQUAL); glTexGenfv(GL_S,GL_EYE_PLANE,plane_s); glTexGenfv(GL_T,GL_EYE_PLANE,plane_t); glTexGenfv(GL_R,GL_EYE_PLANE,plane_r); glTexGenfv(GL_Q,GL_EYE_PLANE,plane_q); glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR); glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR); glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR); glTexGeni(GL_Q,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE_EXT); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE_EXT); glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,SIZE,SIZE,0,GL_RGB,GL_UNSIGNED_BYTE,NULL); this->ground_id=glGenLists(1); glNewList(this->ground_id,GL_COMPILE); //blabla glEndList(); this->player_id=glGenLists(1); glNewList(this->player_id,GL_COMPILE); //blabla glEndList(); this->image=(unsigned char*)malloc(SIZE*SIZE*4); //this->player_id=newList {glNormalefv;glVertex3fv} //this->ground_id=newList {glTexCoord2fv;glNormal3fv;glVertex3fv} //lightPos[] blabla } void Shadow::createShadow() { glViewport(0,0,SIZE,SIZE); glScissor(0,0,SIZE,SIZE); glEnable(GL_SCISSOR_TEST); glBindTexture(GL_TEXTURE_2D,this->shadow_id); glClearColor(1,1,1,1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1,1,-1,1,-100,100); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //gluLookAt(light0,light1,light2,player0,player1,player2,0,0,1); glColor3f(.4,.4,.4); //glTranslatef(player0,player1,player2); glCallList(this->player_id); glColor3f(1,1,1); glReadPixels(0,0,SIZE,SIZE,GL_RGB,GL_UNSIGNED_BYTE,this->image); blur(this->image,SIZE); glTexSubImage2D(GL_TEXTURE_2D,0,0,0,SIZE,SIZE,GL_RGB,GL_UNSIGNED_BYTE,this->image); glDisable(GL_SCISSOR_TEST); glViewport(0,0,1024,768); //Achtung: hier Aufloesung von Orxonox einstellen! } void Shadow::m_inverse(const float *m,float *out) { float det; det=m[0]*m[5]*m[10]; det+= m[4]*m[9]*m[2]; det+= m[8]*m[1]*m[6]; det-= m[8]*m[5]*m[2]; det-= m[4]*m[1]*m[10]; det-= m[0]*m[9]*m[6]; } void Shadow::draw() { float m[16],im[16]; createShadow(); glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45,4.0/3.0,.5,100); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //gluLookAt(camera0,camera1,camera2,player0,player1,player2,0,0,1); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glEnable(GL_TEXTURE_GEN_R); glEnable(GL_TEXTURE_GEN_Q); glGetFloatv(GL_MODELVIEW_MATRIX,m); } /** \don't ask me how this works, but it adds a blur effect to the shadow \for it doesn't look that edgy */ void Shadow::blur(unsigned char *in,int size) { int x,y,sum,size3=size*3; unsigned char *out,*inp,*outp; out = (unsigned char *)malloc(size * size * 3); memset(out,255,size *size *3); inp=in+size3; outp=out+size3; for(y=1;y