Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

branches/mountain_lake

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