Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/mountain_lake/src/lib/graphics/effects/cloud_effect.cc @ 9106

Last change on this file since 9106 was 9028, checked in by amaechler, 19 years ago


File size: 12.7 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  INSPIRED BY http://www.codesampler.com/usersrc/usersrc_6.htm#oglu_sky_dome_shader
15*/
16
17#include "cloud_effect.h"
18
19#include "util/loading/load_param.h"
20#include "util/loading/factory.h"
21#include "util/loading/resource_manager.h"
22
23#include "material.h"
24#include "state.h"
25#include "p_node.h"
26#include "shader.h"
27#include "shell_command.h"
28#include "t_animation.h"
29#include "script_class.h"
30
31#include "parser/tinyxml/tinyxml.h"
32
33Vector    CloudEffect::cloudColor;
34Vector    CloudEffect::skyColor;
35Vector    CloudEffect::newCloudColor;
36Vector    CloudEffect::newSkyColor;
37
38bool      CloudEffect::fadeSky;
39bool      CloudEffect::fadeCloud;
40float     CloudEffect::fadeTime;
41
42using namespace std;
43
44SHELL_COMMAND(activate, CloudEffect, activateCloud);
45SHELL_COMMAND(deactivate, CloudEffect, deactivateCloud);
46SHELL_COMMAND(skyColor, CloudEffect, shellSkyColor);
47SHELL_COMMAND(cloudColor, CloudEffect, shellCloudColor);
48
49
50CREATE_SCRIPTABLE_CLASS(CloudEffect, CL_CLOUD_EFFECT,
51                        addMethod("skyColor", ExecutorLua4<CloudEffect,float,float,float,float>(&CloudEffect::shellSkyColor))
52                        ->addMethod("cloudColor", ExecutorLua4<CloudEffect,float,float,float,float>(&CloudEffect::shellCloudColor))
53                       );
54
55
56CREATE_FACTORY(CloudEffect, CL_CLOUD_EFFECT);
57
58CloudEffect::CloudEffect(const TiXmlElement* root) {
59    this->setClassID(CL_CLOUD_EFFECT, "CloudEffect");
60
61    this->init();
62
63    if (root != NULL)
64        this->loadParams(root);
65
66    if(cloudActivate)
67        this->activate();
68}
69
70CloudEffect::~CloudEffect() {
71    this->deactivate();
72
73    if (glIsTexture(noise3DTexName))
74        glDeleteTextures(1, &noise3DTexName);
75
76    delete shader;
77}
78
79
80void CloudEffect::init() {
81    PRINTF(0)("Initializing CloudEffect\n");
82
83    // default values
84    this->offsetZ = 0;
85    this->animationSpeed = 2;
86    this->scale = 0.0004f;
87    this->atmosphericRadius = 4000;
88    this->planetRadius = 1500;
89    this->divs = 15;
90    fadeSky = false;
91    fadeCloud = false;
92
93
94    skyColor = Vector(0.0f, 0.0f, 0.8f);
95    cloudColor = Vector(0.8f, 0.8f, 0.8f);
96    newSkyColor = skyColor;
97    newCloudColor = cloudColor;
98
99    this->noise3DTexSize = 128;
100    this->noise3DTexName = 0;
101
102    this->make3DNoiseTexture();
103
104    glGenTextures(1, &noise3DTexName);
105    glBindTexture(GL_TEXTURE_3D, noise3DTexName);
106
107    glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
108    glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
109    glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
110    glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
111    glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
112
113    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA,
114                 noise3DTexSize, noise3DTexSize, noise3DTexSize,
115                 0, GL_RGBA, GL_UNSIGNED_BYTE, noise3DTexPtr);
116
117    this->skydome = new Skydome();
118    this->skydome->setTexture(noise3DTexName);
119
120    this->shader = new Shader(ResourceManager::getInstance()->getDataDir() + "/shaders/cloud.vert",
121                              ResourceManager::getInstance()->getDataDir() + "/shaders/cloud.frag");
122
123    this->shader->activateShader();
124
125    Shader::Uniform(shader, "Noise").set(0);
126
127    this->offset = new Shader::Uniform(shader, "Offset");
128    this->skycolor = new Shader::Uniform(shader, "SkyColor");
129    this->cloudcolor = new Shader::Uniform(shader, "CloudColor");
130
131    this->shader->deactivateShader();
132
133    this->skydome->setShader(shader);
134}
135
136
137void CloudEffect::loadParams(const TiXmlElement* root) {
138    WeatherEffect::loadParams(root);
139
140    LoadParam(root, "speed", this, CloudEffect, setAnimationSpeed);
141    LoadParam(root, "scale", this, CloudEffect, setCloudScale);
142    LoadParam(root, "cloudcolor", this, CloudEffect, setCloudColor);
143    LoadParam(root, "skycolor", this, CloudEffect, setSkyColor);
144
145    LoadParam(root, "planetRadius", this, CloudEffect, setPlanetRadius);
146    LoadParam(root, "atmosphericRadius", this, CloudEffect, setAtmosphericRadius);
147    LoadParam(root, "divisions", this, CloudEffect, setDivisions);
148
149    LOAD_PARAM_START_CYCLE(root, element);
150    {
151        LoadParam_CYCLE(element, "option", this, CloudEffect, setCloudOption);
152    }
153    LOAD_PARAM_END_CYCLE(element);
154}
155
156
157void CloudEffect::activate() {
158    PRINTF(0)( "Activating\n");
159
160    // Can only be set after the loadParams call
161    this->shader->activateShader();
162    Shader::Uniform(shader, "Scale").set(this->scale);
163    this->skycolor->set
164    (skyColor.x, skyColor.y, skyColor.z);
165    this->cloudcolor->set
166    (cloudColor.x, cloudColor.y, cloudColor.z);
167    this->shader->deactivateShader();
168
169    this->skydome->generateSkyPlane(this->divs, this->planetRadius, this->atmosphericRadius, 1, 1);
170    this->skydome->activate();
171
172    this->cloudActivate = true;
173}
174
175void CloudEffect::deactivate() {
176    PRINTF(0)("Deactivating CloudEffect\n");
177
178    this->skydome->deactivate();
179    this->cloudActivate = false;
180}
181
182void CloudEffect::draw() const {}
183
184void CloudEffect::tick (float dt) {
185
186    if (this->cloudActivate) {
187
188        this->offsetZ += 0.05 * dt * this->animationSpeed;
189
190        this->shader->activateShader();
191        this->offset->set
192        (0.0f, 0.0f, offsetZ);
193
194        if(cloudColor != newCloudColor) {
195
196            if(fadeCloud) {
197
198                this->cloudColorFadeX = new tAnimation<CloudEffect>(this, &CloudEffect::setColorCloudX);
199                this->cloudColorFadeX->setInfinity(ANIM_INF_CONSTANT);
200                this->cloudColorFadeY = new tAnimation<CloudEffect>(this, &CloudEffect::setColorCloudY);
201                this->cloudColorFadeY->setInfinity(ANIM_INF_CONSTANT);
202                this->cloudColorFadeZ = new tAnimation<CloudEffect>(this, &CloudEffect::setColorCloudZ);
203                this->cloudColorFadeZ->setInfinity(ANIM_INF_CONSTANT);
204
205                this->cloudColorFadeX->addKeyFrame(cloudColor.x, fadeTime, ANIM_LINEAR);
206                this->cloudColorFadeX->addKeyFrame(newCloudColor.x, 0, ANIM_LINEAR);
207
208                this->cloudColorFadeY->addKeyFrame(cloudColor.y, fadeTime, ANIM_LINEAR);
209                this->cloudColorFadeY->addKeyFrame(newCloudColor.y, 0, ANIM_LINEAR);
210
211                this->cloudColorFadeZ->addKeyFrame(cloudColor.z, fadeTime, ANIM_LINEAR);
212                this->cloudColorFadeZ->addKeyFrame(newCloudColor.z, 0, ANIM_LINEAR);
213
214                fadeCloud = false;
215
216                this->cloudColorFadeX->replay();
217                this->cloudColorFadeY->replay();
218                this->cloudColorFadeZ->replay();
219            }
220
221            this->cloudcolor->set
222            (this->cloudColor.x, this->cloudColor.y, this->cloudColor.z);
223        }
224
225        if(skyColor != newSkyColor) {
226
227            if(fadeSky) {
228
229                this->skyColorFadeX = new tAnimation<CloudEffect>(this, &CloudEffect::setColorSkyX);
230                this->skyColorFadeX->setInfinity(ANIM_INF_CONSTANT);
231                this->skyColorFadeY = new tAnimation<CloudEffect>(this, &CloudEffect::setColorSkyY);
232                this->skyColorFadeY->setInfinity(ANIM_INF_CONSTANT);
233                this->skyColorFadeZ = new tAnimation<CloudEffect>(this, &CloudEffect::setColorSkyZ);
234                this->skyColorFadeZ->setInfinity(ANIM_INF_CONSTANT);
235
236                this->skyColorFadeX->addKeyFrame(skyColor.x, fadeTime, ANIM_LINEAR);
237                this->skyColorFadeX->addKeyFrame(newSkyColor.x, 0, ANIM_LINEAR);
238
239                this->skyColorFadeY->addKeyFrame(skyColor.y, fadeTime, ANIM_LINEAR);
240                this->skyColorFadeY->addKeyFrame(newSkyColor.y, 0, ANIM_LINEAR);
241
242                this->skyColorFadeZ->addKeyFrame(skyColor.z, fadeTime, ANIM_LINEAR);
243                this->skyColorFadeZ->addKeyFrame(newSkyColor.z, 0, ANIM_LINEAR);
244
245                fadeSky = false;
246
247                this->skyColorFadeX->replay();
248                this->skyColorFadeY->replay();
249                this->skyColorFadeZ->replay();
250            }
251
252            this->skycolor->set
253            (this->skyColor.x, this->skyColor.y, this->skyColor.z);
254        }
255
256        this->shader->deactivateShader();
257    }
258}
259
260
261void CloudEffect::setColorSkyX(float color) {
262    skyColor.x = color;
263}
264void CloudEffect::setColorSkyY(float color) {
265    skyColor.y = color;
266}
267void CloudEffect::setColorSkyZ(float color) {
268    skyColor.z = color;
269}
270void CloudEffect::setColorCloudX(float color) {
271    cloudColor.x = color;
272}
273void CloudEffect::setColorCloudY(float color) {
274    cloudColor.y = color;
275}
276void CloudEffect::setColorCloudZ(float color) {
277    cloudColor.z = color;
278}
279
280void CloudEffect::changeSkyColor(Vector color, float time) {
281    newSkyColor = color;
282    fadeSky = true;
283    fadeTime = time;
284}
285
286
287void CloudEffect::changeCloudColor(Vector color, float time) {
288    newCloudColor = color;
289    fadeCloud = true;
290    fadeTime = time;
291}
292
293void CloudEffect::shellSkyColor(float colorX, float colorY, float colorZ, float time) {
294    changeSkyColor( Vector(colorX, colorY, colorZ), time);
295}
296
297void CloudEffect::shellCloudColor(float colorX, float colorY, float colorZ, float time) {
298    changeCloudColor( Vector(colorX, colorY, colorZ), time);
299}
300
301
302
303void CloudEffect::make3DNoiseTexture() {
304    int f, i, j, k, inc;
305    int startFrequency = 4;
306    int numOctaves = 4;
307    double ni[3];
308    double inci, incj, inck;
309    int frequency = startFrequency;
310    GLubyte *ptr;
311    double amp = 0.5;
312
313    if ((noise3DTexPtr = (GLubyte *) malloc(noise3DTexSize *
314                                            noise3DTexSize *
315                                            noise3DTexSize * 4)) == NULL)
316        PRINTF(0)("ERROR: Could not allocate 3D noise texture\n");
317
318    for (f=0, inc=0; f < numOctaves;
319            ++f, frequency *= 2, ++inc, amp *= 0.5) {
320        SetNoiseFrequency(frequency);
321        ptr = noise3DTexPtr;
322        ni[0] = ni[1] = ni[2] = 0;
323
324        inci = 1.0 / (noise3DTexSize / frequency);
325        for (i=0; i<noise3DTexSize; ++i, ni[0] += inci) {
326            incj = 1.0 / (noise3DTexSize / frequency);
327            for (j=0; j<noise3DTexSize; ++j, ni[1] += incj) {
328                inck = 1.0 / (noise3DTexSize / frequency);
329                for (k=0; k<noise3DTexSize; ++k, ni[2] += inck, ptr+= 4) {
330                    *(ptr+inc) = (GLubyte) (((noise3(ni)+1.0) * amp)*128.0);
331                }
332            }
333        }
334    }
335}
336
337void CloudEffect::initNoise() {
338    int i, j, k;
339
340    srand(30757);
341    for (i = 0 ; i < B ; i++) {
342        p[i] = i;
343        g1[i] = (double)((rand() % (B + B)) - B) / B;
344
345        for (j = 0 ; j < 2 ; j++)
346            g2[i][j] = (double)((rand() % (B + B)) - B) / B;
347        normalize2(g2[i]);
348
349        for (j = 0 ; j < 3 ; j++)
350            g3[i][j] = (double)((rand() % (B + B)) - B) / B;
351        normalize3(g3[i]);
352    }
353
354    while (--i) {
355        k = p[i];
356        p[i] = p[j = rand() % B];
357        p[j] = k;
358    }
359
360    for (i = 0 ; i < B + 2 ; i++) {
361        p[B + i] = p[i];
362        g1[B + i] = g1[i];
363        for (j = 0 ; j < 2 ; j++)
364            g2[B + i][j] = g2[i][j];
365        for (j = 0 ; j < 3 ; j++)
366            g3[B + i][j] = g3[i][j];
367    }
368}
369
370void CloudEffect::SetNoiseFrequency( int frequency) {
371    start = 1;
372    B = frequency;
373    BM = B-1;
374}
375
376double CloudEffect::noise3( double vec[3]) {
377    int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
378    double rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
379    int i, j;
380
381    if (start) {
382        start = 0;
383        initNoise();
384    }
385
386    setup(0, bx0,bx1, rx0,rx1);
387    setup(1, by0,by1, ry0,ry1);
388    setup(2, bz0,bz1, rz0,rz1);
389
390    i = p[ bx0 ];
391    j = p[ bx1 ];
392
393    b00 = p[ i + by0 ];
394    b10 = p[ j + by0 ];
395    b01 = p[ i + by1 ];
396    b11 = p[ j + by1 ];
397
398    t  = s_curve(rx0);
399    sy = s_curve(ry0);
400    sz = s_curve(rz0);
401
402    q = g3[ b00 + bz0 ] ;
403    u = at3(rx0,ry0,rz0);
404    q = g3[ b10 + bz0 ] ;
405    v = at3(rx1,ry0,rz0);
406    a = lerp(t, u, v);
407
408    q = g3[ b01 + bz0 ] ;
409    u = at3(rx0,ry1,rz0);
410    q = g3[ b11 + bz0 ] ;
411    v = at3(rx1,ry1,rz0);
412    b = lerp(t, u, v);
413
414    c = lerp(sy, a, b);
415
416    q = g3[ b00 + bz1 ] ;
417    u = at3(rx0,ry0,rz1);
418    q = g3[ b10 + bz1 ] ;
419    v = at3(rx1,ry0,rz1);
420    a = lerp(t, u, v);
421
422    q = g3[ b01 + bz1 ] ;
423    u = at3(rx0,ry1,rz1);
424    q = g3[ b11 + bz1 ] ;
425    v = at3(rx1,ry1,rz1);
426    b = lerp(t, u, v);
427
428    d = lerp(sy, a, b);
429
430    return lerp(sz, c, d);
431}
432
433void CloudEffect::normalize2( double v[2]) {
434    double s;
435
436    s = sqrt(v[0] * v[0] + v[1] * v[1]);
437    v[0] = v[0] / s;
438    v[1] = v[1] / s;
439}
440
441void CloudEffect::normalize3( double v[3]) {
442    double s;
443
444    s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
445    v[0] = v[0] / s;
446    v[1] = v[1] / s;
447    v[2] = v[2] / s;
448}
449
Note: See TracBrowser for help on using the repository browser.