Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 4616 was 4170, checked in by dave, 20 years ago

branches/shadow/src:der Boden hat nicht mehr so komische Farben

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