Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/new_class_id/src/world_entities/weather_effects/cloud_effect.cc @ 9821

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

Shaders now fully support the ResourceShader Paradigm

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