Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

branches/atmospheric_engine: TODO update

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