Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9152 was 9112, checked in by bensch, 18 years ago

merged the mountain-lake back here

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