Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/atmospheric_engine/src/lib/graphics/effects/cloud_effect.cc @ 7795

Last change on this file since 7795 was 7795, checked in by amaechler, 18 years ago

branches/atmospheric_engine: cloud tardis bugfix

File size: 6.3 KB
Line 
1/*
2        orxonox - the future of 3D-vertical-scrollers
3
4        Copyright (C) 2004 orx
5
6        This program is free software; you can redistribute it and/or modify
7        it under the terms of the GNU General Public License as published by
8        the Free Software Foundation; either version 2, or (at your option)
9        any later version.
10
11### File Specific:
12        main-programmer: hdavid, amaechler
13*/
14
15#include "cloud_effect.h"
16
17#include "util/loading/load_param.h"
18#include "util/loading/factory.h"
19
20#include "glincl.h"
21//#include "graphics_engine.h"
22#include <math.h>
23
24#include "parser/tinyxml/tinyxml.h"
25
26using namespace std;
27
28CREATE_FACTORY(CloudEffect, CL_CLOUD_EFFECT);
29
30CloudEffect::CloudEffect(const TiXmlElement* root)
31{
32        this->setClassID(CL_CLOUD_EFFECT, "CloudEffect");
33
34        this->init();
35
36        if (root != NULL)
37                this->loadParams(root);
38
39        this->activate();
40}
41
42CloudEffect::~CloudEffect()
43{
44        this->deactivate();
45}
46
47void CloudEffect::loadParams(const TiXmlElement* root)
48{
49        WeatherEffect::loadParams(root);
50
51        LoadParam(root, "animSpeed", this, CloudEffect, setCloudAnimation);
52
53}
54
55
56bool CloudEffect::init()
57{
58        // default values
59        this->cloudAnimTimeStep = 0;
60
61        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
62        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
63        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
64        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
65
66        // Generate noise map a
67        CloudEffect::genNoiseMap(cloudMap32_a);
68       
69        if (this->cloudAnimTimeStep > 0) {
70                // Generate noise map b
71                CloudEffect::genNoiseMap(cloudMap32_b);
72        }
73}
74
75bool CloudEffect::activate()
76{
77        PRINTF(0)( "Activating CloudEffect\n");
78        if (this->cloudAnimTimeStep == 0) {
79                for (int i = 0; i < 32*32; i++)
80                        cloudMap32_c[i] = cloudMap32_a[i];
81
82                CloudEffect::overlapOctaves();
83                CloudEffect::expFilter();
84                CloudEffect::genCloudTexture();
85        }
86}
87
88bool CloudEffect::deactivate()
89{
90        PRINTF(0)("Deactivating CloudEffect\n");
91}
92
93void CloudEffect::genCloudTexture() {
94        for(int i=0; i<256; i++)
95                for(int j=0; j<256; j++) 
96                {
97                        float color = cloudMap256[i*256+j]; 
98                        cloudTexture[i][j][0] = (char) color;
99                        cloudTexture[i][j][1] = (char) color;
100                        cloudTexture[i][j][2] = (char) color;
101                }
102
103        glGenTextures(2, &texID[0]);
104        glBindTexture(GL_TEXTURE_2D, texID[0]);
105        gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, 256, 256, GL_RGB, GL_UNSIGNED_BYTE, cloudTexture);
106}
107
108void CloudEffect::calcAnimMap(float timer) {
109
110        for (int x=0; x<32*32; x++)
111                cloudMap32_c[x] = (cloudMap32_a[x] * ((this->cloudAnimTimeStep - timer) / this->cloudAnimTimeStep)) + (cloudMap32_b[x] * (timer / this->cloudAnimTimeStep));
112
113}
114
115void CloudEffect::draw() const
116{
117        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
118
119        glPushMatrix();
120        glEnable(GL_TEXTURE_2D);
121
122        glBindTexture(GL_TEXTURE_2D, texID[0]);
123
124        // FIXME : Bind this to the sky - how do I do this?
125        glBegin(GL_QUADS);
126                glTexCoord2f(0.0f, 0.0f); glVertex3f(20, 20,  60);      // Bottom Left Of The Texture and Quad
127                glTexCoord2f(1.0f, 0.0f); glVertex3f(60, 20,  60);      // Bottom Right Of The Texture and Quad
128                glTexCoord2f(1.0f, 1.0f); glVertex3f(60, 60,  60);      // Top Right Of The Texture and Quad
129                glTexCoord2f(0.0f, 1.0f); glVertex3f(20, 60,  60);      // Top Left Of The Texture and Quad
130        glEnd(); 
131
132        glPopMatrix();
133}
134
135void CloudEffect::tick (float dt)
136{
137        if (this->cloudAnimTimeStep > 0) {
138                if (timer >= this->cloudAnimTimeStep) {
139                        timer -= this->cloudAnimTimeStep;
140                        for (int i = 0; i < 32*32; i++)
141                                cloudMap32_a[i] = cloudMap32_b[i];
142                        CloudEffect::genNoiseMap(cloudMap32_b);
143                }
144
145                //map32anim = (map32a * (10 - timer)) + (map32b * timer);
146                CloudEffect::calcAnimMap(timer);
147
148                CloudEffect::overlapOctaves();
149                CloudEffect::expFilter();
150                CloudEffect::genCloudTexture();
151
152                timer += dt;
153        }
154}
155
156/*
157        Random noise generator
158*/
159float CloudEffect::noise(int x, int y, int random)
160{
161                int n = x + y * 57 + random * 131;
162                n = (n<<13) ^ n;
163                return (1.0f - ( (n * (n * n * 15731 + 789221) +
164                                                1376312589)&0x7fffffff)* 0.000000000931322574615478515625f);
165}
166
167/*
168        Set noise for the 32*32 noise map:
169*/
170void CloudEffect::genNoiseMap(float  *map)
171{
172        float temp[34][34];
173
174        int random = rand() % 5000;
175
176        for (int y = 1; y < 33; y++)
177                for (int x = 1; x < 33; x++)
178                        temp[x][y] = 128.0f + CloudEffect::noise(x,  y,  random) * 128.0f;
179
180        // Seamless cloud
181        for (int x=1; x<33; x++)
182        {
183                temp[0][x] = temp[32][x];
184                temp[33][x] = temp[1][x];
185                temp[x][0] = temp[x][32];
186                temp[x][33] = temp[x][1];
187        }
188        temp[0][0] = temp[32][32];
189        temp[33][33] = temp[1][1];
190        temp[0][33] = temp[32][1];
191        temp[33][0] = temp[1][32];
192
193        // We mirror the side and corner elements so our final cloud will be seamless without any ugly borders showing.
194        for (int y=1; y<33; y++)
195                for (int x=1; x<33; x++)
196                {
197                        float center = temp[x][y]/4.0f;
198                        float sides = (temp[x+1][y] + temp[x-1][y] + temp[x][y+1] + temp[x][y-1])/8.0f;
199                        float corners = (temp[x+1][y+1] + temp[x+1][y-1] + temp[x-1][y+1] + temp[x-1][y-1])/16.0f;
200
201                        map[((x-1)*32) + (y-1)] = center + sides + corners;
202                }
203}
204
205/*
206        Interpolation - average the value of each pixel value with that of its neighbors' values.
207*/
208float CloudEffect::interpolate(float x, float y, float  *map)
209{
210        int Xint = (int)x;
211        int Yint = (int)y;
212
213        float Xfrac = x - Xint;
214        float Yfrac = y - Yint;
215
216        int X0 = Xint % 32;
217        int Y0 = Yint % 32;
218        int X1 = (Xint + 1) % 32;
219        int Y1 = (Yint + 1) % 32;
220
221        float bot = map[X0*32 + Y0] + Xfrac * (map[X1*32 + Y0] - map[X0*32 + Y0]);
222        float top = map[X0*32 + Y1] + Xfrac * (map[X1*32 +  Y1] - map[X0*32 + Y1]);
223
224        return (bot + Yfrac * (top - bot));
225}
226
227
228/*
229        Octaves are overlapped together to give cloud more turbulence. We will use four octaves for our cloud.
230*/
231void CloudEffect::overlapOctaves()
232{
233        for (int x=0; x<256*256; x++)
234        {
235                cloudMap256[x] = 0;
236        }
237
238        for (int octave=0; octave<4; octave++)
239                for (int x=0; x<256; x++)
240                        for (int y=0; y<256; y++)
241                        {
242                                float scale = 1 / pow(2.0f, (float) 3-octave);
243                                float noise = CloudEffect::interpolate(x*scale, y*scale , cloudMap32_c);
244
245                                //The octaves are added together with the proper weight factors.
246                                //You could replace pow(2, i) with 1<<i for faster computation
247                                cloudMap256[(y*256) + x] += noise / pow(2.0f, (float) octave);
248                        }
249}
250
251
252/*
253        Filter the noise with exponential function
254*/
255void CloudEffect::expFilter()
256{
257        float cover = 20.0f;
258        float sharpness = 0.95f;
259
260        for (int x=0; x<256*256; x++)
261        {
262                float c = cloudMap256[x] - (255.0f-cover);
263                if (c<0)     c = 0;
264                cloudMap256[x] = 255.0f - ((float)(pow(sharpness, c))*255.0f);
265        }
266}
267
268
Note: See TracBrowser for help on using the repository browser.