Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3747 was 3737, checked in by dave, 20 years ago

branches/shadows:Das ganze droht nicht fertig zu werden bis Freitag, Erkenntnisse wachsen jedoch:)

File size: 8.7 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()
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    glClearDepth(1);
67    glDepthFunc(GL_LEQUAL);
68    glTexGenfv(GL_S,GL_EYE_PLANE,plane_s);
69    glTexGenfv(GL_T,GL_EYE_PLANE,plane_t);
70    glTexGenfv(GL_R,GL_EYE_PLANE,plane_r);
71    glTexGenfv(GL_Q,GL_EYE_PLANE,plane_q);
72    glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
73    glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
74    glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
75    glTexGeni(GL_Q,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
76   
77    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
78    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
79    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE_EXT);
80    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE_EXT);
81    glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,SIZE,SIZE,0,GL_RGB,GL_UNSIGNED_BYTE,NULL);
82
83    this->ground_id=glGenLists(1);
84    glNewList(this->ground_id,GL_COMPILE);
85   
86    setGround();
87   
88    glEndList();
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   
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    glClearColor(1,1,1,1);
111    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
112    glMatrixMode(GL_PROJECTION);
113    glLoadIdentity();
114    glOrtho(-4.2,4.2,-4.2,4.2,-100,100);
115    glMatrixMode(GL_MODELVIEW);
116    glLoadIdentity();
117   
118    gluLookAt(this->lightPos[0],this->lightPos[1],this->lightPos[2],this->playerPos[0],this->playerPos[1],this->playerPos[2],0,0,1);
119   
120    glColor3f(.1,.1,.1);
121    glTranslatef(this->playerPos[0],this->playerPos[1],this->playerPos[2]);
122    //die Variable angle ist im Player.h als public definiert!!! deshalb kann
123    //von hier aus darauf zugegriffen werden
124    glRotatef(this->playerangle->angle,1.0,0.0,0.0);
125   
126    //Lighting has to be disabled for the shadow to become nice black respectively grey (color(.1,.1,.1))
127    glDisable(GL_LIGHTING);
128    glCallList(this->player_id);
129    glEnable(GL_LIGHTING);
130   
131    glColor3f(1,1,1);
132   
133    glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,SIZE,SIZE);
134    //glReadPixels(0,0,SIZE,SIZE,GL_RGB,GL_UNSIGNED_BYTE,this->image);
135    //blur(this->image,SIZE);
136    //glTexSubImage2D(GL_TEXTURE_2D,0,0,0,SIZE,SIZE,GL_RGB,GL_UNSIGNED_BYTE,this->image);
137   
138    glDisable(GL_SCISSOR_TEST);
139    glViewport(0,0,400,300); //Achtung: hier Aufloesung von Orxonox einstellen!
140     
141   
142   
143}
144
145
146/**
147    brief updatePosition is used in the same kind as for skysphere, because
148    the light has got a static orientation(parallel light), we have to always
149    add the same relative coordinates being 0,10,19 to the players position
150    in order to receive the lightPosition. This is needed to calculate the Shadow!!
151
152*/
153
154void Shadow::updatePosition(float x,float y,float z)
155{
156    this->playerPos[0]=x;
157    this->playerPos[1]=y;
158    this->playerPos[2]=z;
159   
160    this->lightPos[0]=this->playerPos[0];
161    this->lightPos[1]=this->playerPos[1]+10;
162    this->lightPos[2]=this->playerPos[2]+19;
163
164   
165}
166
167/**
168    brief takes the ground data from the world.cc class and passes it to shadow.cc
169
170*/
171
172void Shadow::setGround()
173{
174   
175   
176    glBegin(GL_QUADS);
177    for(int i=0;i<100;i+=1)
178        for(int j=0;j<80;j+=1)
179            {
180            glNormal3f(normal_vectors[i][j].x,normal_vectors[i][j].y,normal_vectors[i][j].z);
181            glTexCoord2f(0.0f,0.0f);
182            glVertex3f(vertexes[0][i][j].x,vertexes[0][i][j].y,vertexes[0][i][j].z);
183            glNormal3f(normal_vectors[i+1][j].x,normal_vectors[i+1][j].y,normal_vectors[i+1][j].z);
184            glTexCoord2f(1.0f,0.0f);
185            glVertex3f(vertexes[1][i][j].x,vertexes[1][i][j].y,vertexes[1][i][j].z);
186            glNormal3f(normal_vectors[i+1][j+1].x,normal_vectors[i+1][j+1].y,normal_vectors[i+1][j+1].z);
187            glTexCoord2f(1.0f,1.0f);
188            glVertex3f(vertexes[2][i][j].x,vertexes[2][i][j].y,vertexes[2][i][j].z);
189            glNormal3f(normal_vectors[i][j+1].x,normal_vectors[i][j+1].y,normal_vectors[i][j+1].z);
190            glTexCoord2f(0.0f,1.0f);
191            glVertex3f(vertexes[3][i][j].x,vertexes[3][i][j].y,vertexes[3][i][j].z);
192            }
193    glEnd();
194       
195
196
197
198}
199
200void Shadow::setNormal(Vector a,int i,int j)
201{
202    normal_vectors[i][j]=a;
203
204}
205
206void Shadow::setVertexNum(Vector a,int i,int j,int num)
207{
208    vertexes[num][i][j]=a;
209
210}
211/**
212
213    brief m_inverse simply inverses the *m matrix and stores the result back
214    to *out. This is needed further down in the draw() method
215
216
217*/
218
219void Shadow::m_inverse(const float *m,float *out)
220{
221    float det;
222    det=  m[0]*m[5]*m[10];
223    det+= m[4]*m[9]*m[2];
224    det+= m[8]*m[1]*m[6];
225    det-= m[8]*m[5]*m[2];
226    det-= m[4]*m[1]*m[10];
227    det-= m[0]*m[9]*m[6];
228   
229    if(det!= 0.0)
230        det=1.0/det;
231    out[0]=  (m[5]*m[10]-m[9]*m[6])*det;
232    out[1]= -(m[1]*m[10]-m[9]*m[2])*det;
233    out[2]=  (m[1]*m[6]-m[5]*m[2])*det;
234    out[3]= 0.0;
235    out[4]= -(m[4]*m[10]-m[8]*m[6])*det;
236    out[5]=  (m[0]*m[10]-m[8]*m[2])*det;
237    out[6]= -(m[0]*m[6]-m[4]*m[2])*det;
238    out[7]= 0.0;
239    out[8]=  (m[4]*m[9]-m[8]*m[5])*det;
240    out[9]= -(m[0]*m[9]-m[8]*m[1])*det;
241    out[10]= (m[0]*m[5]-m[4]*m[1])*det;
242    out[11]= 0.0;
243    out[12]=- (m[12]*out[0]+m[13]*out[4]+m[14]*out[8]);
244    out[13]=- (m[12]*out[1]+m[13]*out[5]+m[14]*out[9]);
245    out[14]=- (m[12]*out[2]+m[13]*out[6]+m[14]*out[10]);
246    out[15]= 1.0;
247
248
249}
250
251/**
252    brief Method draw() is called after each tick() from the world.cc class
253*/
254
255void Shadow::draw()
256{
257    float m[16],im[16];
258   
259    createShadow();
260    //glClearColor(0,0,0,0);
261    //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
262    glMatrixMode(GL_PROJECTION);
263    glLoadIdentity();
264    gluPerspective(45,4.0/3.0,.5,100);
265    glMatrixMode(GL_MODELVIEW);
266    glLoadIdentity();
267   
268   
269   
270    glEnable(GL_TEXTURE_GEN_S);
271    glEnable(GL_TEXTURE_GEN_T);
272    glEnable(GL_TEXTURE_GEN_R);
273    glEnable(GL_TEXTURE_GEN_Q);
274    glGetFloatv(GL_MODELVIEW_MATRIX,m);
275    m_inverse(m,im);
276    glMatrixMode(GL_TEXTURE);
277    glLoadIdentity();
278    glTranslatef(-.5,.5,0);
279    glScalef(0.3,0.3,1.0);
280    glOrtho(-1,1,-1,1,-1,1);
281   
282    gluLookAt(this->lightPos[0],this->lightPos[1],this->lightPos[2],this->playerPos[0],this->playerPos[1],this->playerPos[2],0,0,1);
283   
284    glMultMatrixf(im);
285    glEnable(GL_TEXTURE_2D),
286    glBindTexture(GL_TEXTURE_2D,this->shadow_id);
287    glEnable(GL_BLEND);
288    glBlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
289    glCallList(this->ground_id);
290    glDisable(GL_BLEND);
291    glDisable(GL_TEXTURE_2D);
292   
293    glLoadIdentity();
294    glMatrixMode(GL_MODELVIEW);
295    glDisable(GL_TEXTURE_GEN_S);
296    glDisable(GL_TEXTURE_GEN_T);
297    glDisable(GL_TEXTURE_GEN_R);
298    glDisable(GL_TEXTURE_GEN_Q);
299   
300   
301   
302}
303
304
305
306/**
307    \don't ask me how this works, but it adds a blur effect to the shadow
308    \for it doesn't look that edgy
309   
310*/
311void Shadow::blur(unsigned char *in,int size)
312{
313    int x,y,sum,size3=size*3;
314    unsigned char *out,*inp,*outp;
315    out = (unsigned char *)malloc(size * size * 3);
316    memset(out,255,size *size *3);
317   
318    inp=in+size3;
319    outp=out+size3;
320    for(y=1;y<size-1;y++){
321        inp+=3;
322        outp+=3;
323        for(x=1;x<size-1;x++){
324            sum=inp[-size3-3]+ inp[-size3] + inp[-size3+3]+
325            inp[-3]+inp[0]+inp[3]+
326            inp[size3-3]+inp[size3]+inp[size3+3];
327            sum/=9;
328            inp+=3;
329            *outp++ =sum;
330            *outp++ =sum;
331            *outp++ =sum;
332        }
333        inp+=3;
334        outp+=3;
335    }
336   
337    memcpy(in,out,size*size*3);
338    free(out);
339       
340           
341   
342
343
344}
345
346
Note: See TracBrowser for help on using the repository browser.