Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 8837 was 8837, checked in by hdavid, 18 years ago

branches/mountain_lake: fading sky/cloud colors works, RainEffect::stopRaining is a bit buggy

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