Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/shadows/src/shadow.cc @ 3861

Last change on this file since 3861 was 3861, checked in by dave, 19 years ago

branches/shadows:nicht ueberraschen lassen von der weissen Farbe, ist debugphase, und von dem her einfach mal eine Zwischenspeicherung

File size: 8.0 KB
Line 
1
2/*
3
4    orxonox - the future of 3D-vertical scrollers
5   
6    Copyright (C) 2004 orx
7   
8    This program is free software; you can redistribute it and/or modify it
9    under the terms of the GNU General Public License as published by the Free
10    Software Foundation; either version 2, or (at your option) any later version.
11   
12    ### File Specific:
13    main-programmer: David Gruetter
14    co-programmer: ...
15   
16   
17    Created by Dave, in this file shadow will be implemented in a quite sexy and
18    fast way, with a lot of opengl-code, to keep it fast! The origin of the code
19    comes form an example at www.frustum.org, slitly different although, so that
20    it works with Orxonox:)
21   
22    */
23   
24#include "importer/material.h"
25#include "stdincl.h"
26#include <stdio.h>
27#include <stdarg.h>
28#include <malloc.h>
29#include <math.h>
30#include "shadow.h"
31#include "vector.h"
32
33
34#define SIZE    128
35#define GL_CLAMP_TO_EDGE_EXT 0x812F
36
37using namespace std;
38
39/**
40   \brief default Constructor
41*/
42
43Shadow::Shadow(OBJModel* player,Player* playerangle)
44{
45    this->player=player;
46    this->playerangle=playerangle;
47}
48
49
50/**
51    \brief default destructor
52*/
53
54Shadow::~Shadow()
55{
56}
57
58void Shadow::init(GLuint ground_id_imported)
59{
60   
61    float plane_s[] ={1.0f,0.0f,0.0f,0.0f};
62    float plane_t[] ={0.0f,1.0f,0.0f,0.0f};
63    float plane_r[] ={0.0f,0.0f,1.0f,0.0f};
64    float plane_q[] ={0.0f,0.0f,0.0f,1.0f};
65   
66   
67    this->mat=new Material("Ground");
68    this->mat->setDiffuseMap("../data/pictures/ground.tga");
69    this->mat->setIllum(3);
70   
71    glClearDepth(1);
72    glDepthFunc(GL_LEQUAL);
73    glTexGenfv(GL_S,GL_EYE_PLANE,plane_s);
74    glTexGenfv(GL_T,GL_EYE_PLANE,plane_t);
75    glTexGenfv(GL_R,GL_EYE_PLANE,plane_r);
76    glTexGenfv(GL_Q,GL_EYE_PLANE,plane_q);
77    glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
78    glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
79    glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
80    glTexGeni(GL_Q,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
81   
82    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
83    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
84    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
85    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
86    glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,SIZE,SIZE,0,GL_RGB,GL_UNSIGNED_BYTE,NULL);
87
88   
89   
90    this->player_id=glGenLists(1);
91    glNewList(this->player_id,GL_COMPILE);
92   
93    this->player->draw();
94   
95    glEndList();   
96   
97    this->image=(unsigned char*)malloc(SIZE*SIZE*4);
98    this->ground_id=ground_id_imported;
99
100}
101
102
103void Shadow::createShadow()
104{
105    glViewport(0,0,SIZE,SIZE);
106    glScissor(0,0,SIZE,SIZE);
107    glEnable(GL_SCISSOR_TEST);
108    glBindTexture(GL_TEXTURE_2D,this->shadow_id);
109   
110   
111    float m[16],m2[16]; 
112    glClearColor(1,1,1,1);
113    //glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
114   
115    glMatrixMode(GL_PROJECTION);
116    glGetFloatv(GL_PROJECTION_MATRIX,m);
117    glLoadIdentity();
118    glOrtho(-4.2,4.2,-4.2,4.2,-100,100);
119    glMatrixMode(GL_MODELVIEW);
120    glGetFloatv(GL_MODELVIEW_MATRIX,m2);
121    glLoadIdentity();
122   
123    gluLookAt(this->lightPos[0],this->lightPos[1],this->lightPos[2],this->playerPos[0],this->playerPos[1],this->playerPos[2],0,0,1);
124   
125    glColor3f(.1,.1,.1);
126    glTranslatef(this->playerPos[0],this->playerPos[1],this->playerPos[2]);
127    //die Variable angle ist im Player.h als public definiert!!! deshalb kann
128    //von hier aus darauf zugegriffen werden
129    glRotatef(this->playerangle->angle,1.0,0.0,0.0);
130   
131    //Lighting has to be disabled for the shadow to become nice black respectively grey (color(.1,.1,.1))
132    glDisable(GL_LIGHTING);
133    glCallList(this->player_id);
134    glEnable(GL_LIGHTING);
135    glColor3f(1,1,1);
136   
137   
138   
139    glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,SIZE,SIZE);
140    //glReadPixels(0,0,SIZE,SIZE,GL_RGB,GL_UNSIGNED_BYTE,this->image);
141    //blur(this->image,SIZE);
142    //glTexSubImage2D(GL_TEXTURE_2D,30,30,30,SIZE,SIZE,GL_RGB,GL_UNSIGNED_BYTE,this->image);
143   
144    glDisable(GL_SCISSOR_TEST);
145    glViewport(0,0,1024,768); //Achtung: hier Aufloesung von Orxonox einstellen!
146   
147    //Die oben veraenderten und zwischengespeicherten werte wieder herstellen!
148    glMatrixMode(GL_PROJECTION);
149    glLoadIdentity();
150    glMultMatrixf(m);
151    glMatrixMode(GL_MODELVIEW);
152    glLoadIdentity();
153    glMultMatrixf(m2); 
154 
155}
156
157void Shadow::draw()
158{
159    float m[16],im[16];
160   
161    createShadow();
162    //glClearColor(0,0,0,1);
163    //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
164    //glMatrixMode(GL_PROJECTION);
165    //glLoadIdentity();
166    //gluPerspective(45,4.0/3.0,.5,100);
167    //glMatrixMode(GL_MODELVIEW);
168    //glLoadIdentity();
169       
170    //this->mat->select();
171    //glCallList(this->ground_id);
172   
173    glDisable(GL_TEXTURE_2D);
174       
175    /*shadow*/
176    glEnable(GL_TEXTURE_GEN_S);
177    glEnable(GL_TEXTURE_GEN_T);
178    glEnable(GL_TEXTURE_GEN_R);
179    glEnable(GL_TEXTURE_GEN_Q);
180    glGetFloatv(GL_MODELVIEW_MATRIX,m);
181    m_inverse(m,im);
182    glMatrixMode(GL_TEXTURE);
183    glLoadIdentity();
184    glTranslatef(1.5,.5,0);
185    glScalef(.5f,1.0,.5f);
186    glOrtho(-1,1,-1,1,-100,100);
187   
188    gluLookAt(this->lightPos[0],this->lightPos[1],this->lightPos[2],this->playerPos[0],this->playerPos[1],this->playerPos[2],0,0,1);
189   
190    glMultMatrixf(im);
191    glEnable(GL_TEXTURE_2D);
192    glBindTexture(GL_TEXTURE_2D,this->shadow_id);
193    glEnable(GL_BLEND);
194    glBlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
195    glCallList(this->ground_id);
196    glDisable(GL_BLEND);
197    //glDisable(GL_TEXTURE_2D);
198   
199    //glLoadIdentity();
200    glMatrixMode(GL_MODELVIEW);
201    glDisable(GL_TEXTURE_GEN_S);
202    glDisable(GL_TEXTURE_GEN_T);
203    glDisable(GL_TEXTURE_GEN_R);
204    glDisable(GL_TEXTURE_GEN_Q);
205   
206
207   
208   
209   
210}
211
212/**
213    brief updatePosition is used in the same kind as for skysphere, because
214    the light has got a static orientation(parallel light), we have to always
215    add the same relative coordinates being 0,10,19 to the players position
216    in order to receive the lightPosition. This is needed to calculate the Shadow!!
217
218*/
219
220void Shadow::updatePosition(float x,float y,float z)
221{
222    this->playerPos[0]=x;
223    this->playerPos[1]=y;
224    this->playerPos[2]=z;
225   
226    this->lightPos[0]=this->playerPos[0];
227    this->lightPos[1]=this->playerPos[1]+10;
228    this->lightPos[2]=this->playerPos[2]+19;
229
230   
231}
232
233
234
235
236
237/**
238
239    brief m_inverse simply inverses the *m matrix and stores the result back
240    to *out. This is needed further down in the draw() method
241
242
243*/
244
245void Shadow::m_inverse(const float *m,float *out)
246{
247    float det;
248    det=  m[0]*m[5]*m[10];
249    det+= m[4]*m[9]*m[2];
250    det+= m[8]*m[1]*m[6];
251    det-= m[8]*m[5]*m[2];
252    det-= m[4]*m[1]*m[10];
253    det-= m[0]*m[9]*m[6];
254   
255    if(det!= 0.0)
256        det=1.0/det;
257    out[0]=  (m[5]*m[10]-m[9]*m[6])*det;
258    out[1]= -(m[1]*m[10]-m[9]*m[2])*det;
259    out[2]=  (m[1]*m[6]-m[5]*m[2])*det;
260    out[3]= 0.0;
261    out[4]= -(m[4]*m[10]-m[8]*m[6])*det;
262    out[5]=  (m[0]*m[10]-m[8]*m[2])*det;
263    out[6]= -(m[0]*m[6]-m[4]*m[2])*det;
264    out[7]= 0.0;
265    out[8]=  (m[4]*m[9]-m[8]*m[5])*det;
266    out[9]= -(m[0]*m[9]-m[8]*m[1])*det;
267    out[10]= (m[0]*m[5]-m[4]*m[1])*det;
268    out[11]= 0.0;
269    out[12]=- (m[12]*out[0]+m[13]*out[4]+m[14]*out[8]);
270    out[13]=- (m[12]*out[1]+m[13]*out[5]+m[14]*out[9]);
271    out[14]=- (m[12]*out[2]+m[13]*out[6]+m[14]*out[10]);
272    out[15]= 1.0;
273
274
275}
276
277/**
278    brief Method draw() is called after each tick() from the world.cc class
279*/
280
281
282
283
284/**
285    \don't ask me how this works, but it adds a blur effect to the shadow
286    \for it doesn't look that edgy
287   
288*/
289void Shadow::blur(unsigned char *in,int size)
290{
291    int x,y,sum,size3=size*3;
292    unsigned char *out,*inp,*outp;
293    out = (unsigned char *)malloc(size * size * 3);
294    memset(out,255,size *size *3);
295   
296    inp=in+size3;
297    outp=out+size3;
298    for(y=1;y<size-1;y++){
299        inp+=3;
300        outp+=3;
301        for(x=1;x<size-1;x++){
302            sum=inp[-size3-3]+ inp[-size3] + inp[-size3+3]+
303            inp[-3]+inp[0]+inp[3]+
304            inp[size3-3]+inp[size3]+inp[size3+3];
305            sum/=9;
306            inp+=3;
307            *outp++ =sum;
308            *outp++ =sum;
309            *outp++ =sum;
310        }
311        inp+=3;
312        outp+=3;
313    }
314   
315    memcpy(in,out,size*size*3);
316    free(out);
317       
318           
319   
320
321
322}
323
324
Note: See TracBrowser for help on using the repository browser.