Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 8799 was 8793, checked in by patrick, 18 years ago

trunk: merged the weather engine branche to the trunk

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