Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/atmospheric_engine/src/lib/graphics/effects/cloud_effect.cc @ 8734

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

branches/atmospheric_engine:

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