Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

branches/atmospheric_engine: cloud hacking

File size: 5.9 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
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
52
53bool CloudEffect::init()
54{
55        //Default values
56
57        CloudEffect::setNoise(map32);
58
59}
60
61bool CloudEffect::activate()
62{
63        PRINTF(0)( "Activating CloudEffect\n");
64
65        //Our cloud function 
66        CloudEffect::overlapOctaves(map32, map256);
67        CloudEffect::expFilter(map256);
68
69        for(int i=0; i<256; i++)         //Set cloud color value to temporary array
70                for(int j=0; j<256; j++) 
71                {
72                        float color = map256[i*256+j]; 
73                        texture[i][j][0] = color;
74                        texture[i][j][1] = color;
75                        texture[i][j][2] = color;
76                }
77
78                /* for(int n=0; n<256; n++) {
79                        for(int i=0; i<256; i++)
80                                PRINTF(0)("%f ", map256[n*i]);
81                        PRINTF(0)("\n");
82                } */
83
84        unsigned int ID;                 //Generate an ID for texture binding
85        glGenTextures(1, &ID);           //Texture binding
86        glBindTexture(GL_TEXTURE_2D, ID);
87
88        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
89        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
90        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
91        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
92       
93        gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, 256, 256, GL_RGB, GL_UNSIGNED_BYTE, texture);
94
95}
96
97
98bool CloudEffect::deactivate()
99{
100        PRINTF(0)("Deactivating CloudEffect\n");
101}
102
103void CloudEffect::draw() const
104{
105        glPushAttrib(GL_ENABLE_BIT);
106        glEnable(GL_TEXTURE_2D);
107        glMatrixMode(GL_MODELVIEW);
108        glPushMatrix();
109
110        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
111
112        glEnable(GL_TEXTURE_2D);
113
114        //glLoadIdentity();
115
116        //glMatrixMode(GL_TEXTURE);        //Let's move the clouds from left to right
117        //static float x;   
118        //x+=0.01f;
119        //glTranslatef(x,0,0);
120
121        glBegin(GL_QUADS);
122                // Front Face
123                glTexCoord2f(0.0f, 0.0f); glVertex3f(-100.0f, -100.0f,  100.0f);        // Bottom Left Of The Texture and Quad
124                glTexCoord2f(1.0f, 0.0f); glVertex3f( 100.0f, -100.0f,  100.0f);        // Bottom Right Of The Texture and Quad
125                glTexCoord2f(1.0f, 1.0f); glVertex3f( 100.0f,  100.0f,  100.0f);        // Top Right Of The Texture and Quad
126                glTexCoord2f(0.0f, 1.0f); glVertex3f(-100.0f,  100.0f,  100.0f);        // Top Left Of The Texture and Quad
127        glEnd(); 
128
129        glPopMatrix();
130        glPopAttrib();
131
132}
133
134void CloudEffect::tick (float dt)
135{
136}
137
138/*
139        Random noise generator
140*/
141float CloudEffect::noise(int x, int y, int random)
142{
143                int n = x + y * 57 + random * 131;
144                n = (n<<13) ^ n;
145                return (1.0f - ( (n * (n * n * 15731 + 789221) +
146                                                1376312589)&0x7fffffff)* 0.000000000931322574615478515625f);
147}
148
149/*
150        Set noise for the 32*32 noise map:
151*/
152void CloudEffect::setNoise(float  *map)
153{
154        float temp[34][34];
155
156/* We declare a temporary array to make our function cleaner. Why does the array hold 34*34 elements instead of 32*32? This is because we will need extra elements for side and corner mirroring, as we shall see soon. */
157
158        int random = rand() % 5000;
159
160        for (int y = 1; y < 33; y++)
161                for (int x = 1; x < 33; x++)
162                        temp[x][y] = 128.0f + CloudEffect::noise(x,  y,  random) * 128.0f;
163
164        // Seamless cloud
165        for (int x=1; x<33; x++)
166        {
167                temp[0][x] = temp[32][x];
168                temp[33][x] = temp[1][x];
169                temp[x][0] = temp[x][32];
170                temp[x][33] = temp[x][1];
171        }
172        temp[0][0] = temp[32][32];
173        temp[33][33] = temp[1][1];
174        temp[0][33] = temp[32][1];
175        temp[33][0] = temp[1][32];
176
177        // We mirror the side and corner elements so our final cloud will be seamless without any ugly borders showing.
178        for (int y=1; y<33; y++)
179                for (int x=1; x<33; x++)
180                {
181                        float center = temp[x][y]/4.0f;
182                        float sides = (temp[x+1][y] + temp[x-1][y] + temp[x][y+1] + temp[x][y-1])/8.0f;
183                        float corners = (temp[x+1][y+1] + temp[x+1][y-1] + temp[x-1][y+1] + temp[x-1][y-1])/16.0f;
184
185                        map32[((x-1)*32) + (y-1)] = center + sides + corners;
186                }
187}
188
189/*
190        Interpolation - average the value of each pixel value with that of its neighbors' values.
191*/
192float CloudEffect::interpolate(float x, float y, float  *map)
193{
194        int Xint = (int)x;
195        int Yint = (int)y;
196
197        float Xfrac = x - Xint;
198        float Yfrac = y - Yint;
199
200        int X0 = Xint % 32;
201        int Y0 = Yint % 32;
202        int X1 = (Xint + 1) % 32;
203        int Y1 = (Yint + 1) % 32;
204
205        float bot = map[X0*32 + Y0] + Xfrac * (map[X1*32 + Y0] - map[X0*32 + Y0]);
206        float top = map[X0*32 + Y1] + Xfrac * (map[X1*32 +  Y1] - map[X0*32 + Y1]);
207
208        return (bot + Yfrac * (top - bot));
209}
210
211
212/*
213        Octaves are overlapped together to give cloud more turbulence. We will use four octaves for our cloud.
214*/
215void CloudEffect::overlapOctaves(float  *map32, float  *map256)
216{
217        for (int x=0; x<256*256; x++)
218        {
219                map256[x] = 0;
220        }
221
222        for (int octave=0; octave<4; octave++)
223                for (int x=0; x<256; x++)
224                        for (int y=0; y<256; y++)
225                        {
226                                float scale = 1 / pow(2, 3-octave);
227                                float noise = CloudEffect::interpolate(x*scale, y*scale , map32);
228
229                                //The octaves are added together with the proper weight factors.
230                                //You could replace pow(2, i) with 1<<i for faster computation
231                                map256[(y*256) + x] += noise / pow(2, octave);
232                        }
233}
234
235
236/*
237        Filter the noise with exponential function
238*/
239void CloudEffect::expFilter(float  *map)
240{
241        float cover = 20.0f;
242        float sharpness = 0.95f;
243
244        for (int x=0; x<256*256; x++)
245        {
246                float c = map[x] - (255.0f-cover);
247                if (c<0)     c = 0;
248                map[x] = 255.0f - ((float)(pow(sharpness, c))*255.0f);
249        }
250}
Note: See TracBrowser for help on using the repository browser.