Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3767 was 3760, checked in by dave, 20 years ago

branches/shadows: chaos, aber kommt der loesung naeher

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