Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/world_entities/weather_effects/cloud_effect.cc @ 10059

Last change on this file since 10059 was 10034, checked in by rennerc, 18 years ago

fix for segfault with ati r300 driver

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