Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/effects/cloud_effect.cc @ 8059

Last change on this file since 8059 was 7810, checked in by bensch, 18 years ago

orxonox/trunk: merged the Weather effects back here

File size: 6.3 KB
RevLine 
[7679]1/*
[7768]2        orxonox - the future of 3D-vertical-scrollers
[7679]3
[7768]4        Copyright (C) 2004 orx
[7679]5
[7768]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.
[7679]10
11### File Specific:
[7768]12        main-programmer: hdavid, amaechler
[7679]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"
[7784]21//#include "graphics_engine.h"
[7795]22#include <math.h>
[7679]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);
[7784]50
51        LoadParam(root, "animSpeed", this, CloudEffect, setCloudAnimation);
52
[7679]53}
54
55
56bool CloudEffect::init()
57{
[7784]58        // default values
59        this->cloudAnimTimeStep = 0;
[7768]60
[7784]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);
[7768]65
[7784]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        }
[7679]73}
74
75bool CloudEffect::activate()
76{
[7768]77        PRINTF(0)( "Activating CloudEffect\n");
[7784]78        if (this->cloudAnimTimeStep == 0) {
79                for (int i = 0; i < 32*32; i++)
80                        cloudMap32_c[i] = cloudMap32_a[i];
[7768]81
[7784]82                CloudEffect::overlapOctaves();
83                CloudEffect::expFilter();
84                CloudEffect::genCloudTexture();
85        }
86}
[7768]87
[7784]88bool CloudEffect::deactivate()
89{
90        PRINTF(0)("Deactivating CloudEffect\n");
91}
92
93void CloudEffect::genCloudTexture() {
94        for(int i=0; i<256; i++)
[7768]95                for(int j=0; j<256; j++) 
96                {
[7784]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;
[7768]101                }
102
[7784]103        glGenTextures(2, &texID[0]);
[7782]104        glBindTexture(GL_TEXTURE_2D, texID[0]);
[7784]105        gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, 256, 256, GL_RGB, GL_UNSIGNED_BYTE, cloudTexture);
[7679]106}
107
[7784]108void CloudEffect::calcAnimMap(float timer) {
[7679]109
[7784]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
[7679]113}
114
[7768]115void CloudEffect::draw() const
116{
117        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
118
[7782]119        glPushMatrix();
[7768]120        glEnable(GL_TEXTURE_2D);
121
[7782]122        glBindTexture(GL_TEXTURE_2D, texID[0]);
[7768]123
[7784]124        // FIXME : Bind this to the sky - how do I do this?
[7768]125        glBegin(GL_QUADS);
[7782]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
[7768]130        glEnd(); 
131
132        glPopMatrix();
133}
134
[7679]135void CloudEffect::tick (float dt)
136{
[7784]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        }
[7768]154}
[7679]155
[7768]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);
[7679]165}
[7768]166
167/*
168        Set noise for the 32*32 noise map:
169*/
[7784]170void CloudEffect::genNoiseMap(float  *map)
[7768]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
[7784]201                        map[((x-1)*32) + (y-1)] = center + sides + corners;
[7768]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*/
[7784]231void CloudEffect::overlapOctaves()
[7768]232{
233        for (int x=0; x<256*256; x++)
234        {
[7784]235                cloudMap256[x] = 0;
[7768]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                        {
[7795]242                                float scale = 1 / pow(2.0f, (float) 3-octave);
[7784]243                                float noise = CloudEffect::interpolate(x*scale, y*scale , cloudMap32_c);
[7768]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
[7795]247                                cloudMap256[(y*256) + x] += noise / pow(2.0f, (float) octave);
[7768]248                        }
249}
250
251
252/*
253        Filter the noise with exponential function
254*/
[7784]255void CloudEffect::expFilter()
[7768]256{
257        float cover = 20.0f;
258        float sharpness = 0.95f;
259
260        for (int x=0; x<256*256; x++)
261        {
[7784]262                float c = cloudMap256[x] - (255.0f-cover);
[7768]263                if (c<0)     c = 0;
[7784]264                cloudMap256[x] = 255.0f - ((float)(pow(sharpness, c))*255.0f);
[7768]265        }
266}
[7784]267
268
Note: See TracBrowser for help on using the repository browser.