Caelum
FlatCloudLayer.cpp
1 /*
2 This file is part of Caelum.
3 See http://www.ogre3d.org/wiki/index.php/Caelum
4 
5 Copyright (c) 2008 Caelum team. See Contributors.txt for details.
6 
7 Caelum is free software: you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Caelum is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Lesser General Public License for more details.
16 
17 You should have received a copy of the GNU Lesser General Public License
18 along with Caelum. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include "CaelumPrecompiled.h"
22 #include "FlatCloudLayer.h"
23 #include "CaelumExceptions.h"
24 #include "InternalUtilities.h"
25 
26 namespace Caelum
27 {
28  FlatCloudLayer::FlatCloudLayer(
29  Ogre::SceneManager *sceneMgr,
30  Ogre::SceneNode *cloudRoot)
31  {
32  Ogre::String uniqueSuffix = InternalUtilities::pointerToString(this);
33 
34  // Clone material
35  mMaterial.reset(InternalUtilities::checkLoadMaterialClone ("CaelumLayeredClouds", "Caelum/FlatCloudLayer/Material" + uniqueSuffix));
36 
37  mParams.setup(
38  mMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters(),
39  mMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters());
40 
41  // Create the scene node.
42  mSceneMgr = sceneMgr;
43  mNode.reset(cloudRoot->createChildSceneNode());
44  mNode->setPosition(Ogre::Vector3(0, 0, 0));
45 
46  // Noise texture names are fixed.
47  mNoiseTextureNames.clear();
48  mNoiseTextureNames.push_back("noise1.dds");
49  mNoiseTextureNames.push_back("noise2.dds");
50  mNoiseTextureNames.push_back("noise3.dds");
51  mNoiseTextureNames.push_back("noise4.dds");
52 
53  // Invalid; will reset on first opportunity.
54  mCurrentTextureIndex = -1;
55 
56  // By default height is 0; the user is expected to change this.
57  setHeight(0);
58 
59  // Reset parameters. This is relied upon to initialize most fields.
60  this->reset();
61 
62  // Ensure geometry; don't wait for first update.
63  this->_ensureGeometry();
64  }
65 
66  FlatCloudLayer::~FlatCloudLayer()
67  {
68  mSceneMgr = 0;
69 
70  // Rely on PrivatePtr for everything interesting.
71  }
72 
74  mMeshDirty = true;
75  }
76 
78  {
79  if (!mMeshDirty) {
80  return;
81  }
82 
83  // Generate unique names based on pointer.
84  Ogre::String uniqueId = Ogre::StringConverter::toString((size_t)this);
85  Ogre::String planeMeshName = "Caelum/FlatCloudLayer/Plane/" + uniqueId;
86  Ogre::String entityName = "Caelum/FlatCloudLayer/Entity/" + uniqueId;
87 
88  // Cleanup first. Entity references mesh so it must be destroyed first.
89  mEntity.reset();
90  mMesh.reset();
91 
92  /*
93  Ogre::LogManager::getSingleton().logMessage(
94  "Creating cloud layer mesh " +
95  Ogre::StringConverter::toString(mMeshWidthSegments) + "x" +
96  Ogre::StringConverter::toString(mMeshHeightSegments) + " segments");
97  */
98 
99  // Recreate mesh.
100  Ogre::Plane meshPlane(
101  Ogre::Vector3(1, 1, 0),
102  Ogre::Vector3(1, 1, 1),
103  Ogre::Vector3(0, 1, 1));
104  mMesh.reset(Ogre::MeshManager::getSingleton().createPlane(
105  planeMeshName, Caelum::RESOURCE_GROUP_NAME, meshPlane,
106  mMeshWidth, mMeshHeight,
107  mMeshWidthSegments, mMeshHeightSegments,
108  false, 1,
109  1.0f, 1.0f,
110  Ogre::Vector3::UNIT_X));
111 
112  // Recreate entity.
113  mEntity.reset(mSceneMgr->createEntity(entityName, mMesh->getName()));
114  mEntity->setMaterialName(mMaterial->getName());
115 
116  // Reattach entity.
117  mNode->attachObject(mEntity.get());
118 
119  // Mark done.
120  mMeshDirty = false;
121  }
122 
124  Real meshWidth, Real meshHeight,
125  int meshWidthSegments, int meshHeightSegments)
126  {
127  bool invalidate =
128  (mMeshWidthSegments != meshWidthSegments) ||
129  (mMeshHeightSegments != meshHeightSegments) ||
130  (abs(mMeshWidth - meshWidth) > 0.001) ||
131  (abs(mMeshHeight - meshHeight) > 0.001);
132  mMeshWidth = meshWidth;
133  mMeshHeight = meshHeight;
134  mMeshWidthSegments = meshWidthSegments;
135  mMeshHeightSegments = meshHeightSegments;
136  if (invalidate) {
138  }
139  }
140 
142  {
144  setMeshParameters(10000000, 10000000, 10, 10);
145 
146  assert (mCloudCoverLookup.get() == 0);
147  setCloudCoverLookup ("CloudCoverLookup.png");
148  setCloudCover (0.3);
150 
151  setCloudMassOffset (Ogre::Vector2(0, 0));
152  setCloudDetailOffset (Ogre::Vector2(0, 0));
153  setCloudBlendTime (3600 * 24);
154  setCloudBlendPos (0.5);
155 
156  setCloudSpeed (Ogre::Vector2(0.000005, -0.000009));
157 
158  setCloudUVFactor (150);
159  setHeightRedFactor (100000);
160 
161  setFadeDistances (10000, 140000);
162  setFadeDistMeasurementVector (Ogre::Vector3(0, 1, 1));
163 
164  setSunDirection (Ogre::Vector3::UNIT_Y);
165  setFogColour (Ogre::ColourValue::Black);
166  setSunLightColour (Ogre::ColourValue::White);
167  setSunSphereColour (Ogre::ColourValue::White);
168  }
169 
171  Ogre::Real timePassed,
172  const Ogre::Vector3 &sunDirection,
173  const Ogre::ColourValue &sunLightColour,
174  const Ogre::ColourValue &fogColour,
175  const Ogre::ColourValue &sunSphereColour)
176  {
177  // Advance animation
178  advanceAnimation (timePassed);
179 
180  // Set parameters.
181  setSunDirection (sunDirection);
182  setSunLightColour (sunLightColour);
183  setSunSphereColour (sunSphereColour);
184  setFogColour (fogColour);
185 
186  this->_ensureGeometry();
187 
189  }
190 
192  {
193  if (!mEntity.isNull()) {
194  mEntity->setVisible (getCloudCover () > this->getCloudCoverVisibilityThreshold ());
195  }
196  }
197 
198  void FlatCloudLayer::advanceAnimation (Ogre::Real timePassed)
199  {
200  // Move clouds.
201  setCloudMassOffset(mCloudMassOffset + timePassed * mCloudSpeed);
202  setCloudDetailOffset(mCloudDetailOffset - timePassed * mCloudSpeed);
203 
204  // Animate cloud blending.
205  setCloudBlendPos (getCloudBlendPos () + timePassed / mCloudBlendTime);
206  }
207 
208  void FlatCloudLayer::Params::setup(Ogre::GpuProgramParametersSharedPtr vpParams, Ogre::GpuProgramParametersSharedPtr fpParams)
209  {
210  this->vpParams = vpParams;
211  this->fpParams = fpParams;
212  cloudCoverageThreshold.bind(fpParams, "cloudCoverageThreshold");
213  cloudMassOffset.bind(fpParams, "cloudMassOffset");
214  cloudDetailOffset.bind(fpParams, "cloudDetailOffset");
215  cloudMassBlend.bind(fpParams, "cloudMassBlend");
216  vpSunDirection.bind(vpParams, "sunDirection");
217  fpSunDirection.bind(fpParams, "sunDirection");
218  sunLightColour.bind(fpParams, "sunLightColour");
219  sunSphereColour.bind(fpParams, "sunSphereColour");
220  fogColour.bind(fpParams, "fogColour");
221  layerHeight.bind(fpParams, "layerHeight");
222  cloudUVFactor.bind(fpParams, "cloudUVFactor");
223  heightRedFactor.bind(fpParams, "heightRedFactor");
224  nearFadeDist.bind(fpParams, "nearFadeDist");
225  farFadeDist.bind(fpParams, "farFadeDist");
226  fadeDistMeasurementVector.bind(fpParams, "fadeDistMeasurementVector");
227  }
228 
229  void FlatCloudLayer::setCloudCoverLookup (const Ogre::String& fileName) {
230  mCloudCoverLookup.reset(0);
231  mCloudCoverLookup.reset(new Ogre::Image());
232  mCloudCoverLookup->load(fileName, RESOURCE_GROUP_NAME);
233 
234  mCloudCoverLookupFileName = fileName;
235  }
236 
238  mCloudCoverLookup.reset (0);
239  mCloudCoverLookupFileName.clear ();
240  }
241 
242  const Ogre::String FlatCloudLayer::getCloudCoverLookupFileName () const {
243  return mCloudCoverLookupFileName;
244  }
245 
247  mCloudCoverVisibilityThreshold = value;
249  }
250 
251  void FlatCloudLayer::setCloudCover(const Ogre::Real cloudCover) {
252  mCloudCover = cloudCover;
253  float cloudCoverageThreshold = 0;
254  if (mCloudCoverLookup.get() != 0) {
255  cloudCoverageThreshold = InternalUtilities::getInterpolatedColour(cloudCover, 1, mCloudCoverLookup.get(), false).r;
256  } else {
257  cloudCoverageThreshold = 1 - cloudCover;
258  }
259  mParams.cloudCoverageThreshold.set(mParams.fpParams, cloudCoverageThreshold);
261  }
262 
263  void FlatCloudLayer::setCloudMassOffset(const Ogre::Vector2 &cloudMassOffset) {
264  mCloudMassOffset = cloudMassOffset;
265  mParams.cloudMassOffset.set(mParams.fpParams, Ogre::Vector3(cloudMassOffset.x,cloudMassOffset.y,0));
266  }
267 
268  void FlatCloudLayer::setCloudDetailOffset(const Ogre::Vector2 &cloudDetailOffset) {
269  mCloudDetailOffset = cloudDetailOffset;
270  mParams.cloudDetailOffset.set(mParams.fpParams, Ogre::Vector3(cloudDetailOffset.x,cloudDetailOffset.y,0));
271  }
272 
273  void FlatCloudLayer::setCloudBlendTime(const Ogre::Real value) {
274  mCloudBlendTime = value;
275  }
276 
277  Ogre::Real FlatCloudLayer::getCloudBlendTime () const {
278  return mCloudBlendTime;
279  }
280 
281  void FlatCloudLayer::setCloudBlendPos (const Ogre::Real value)
282  {
283  mCloudBlendPos = value;
284  int textureCount = static_cast<int>(mNoiseTextureNames.size());
285 
286  // Convert to int and bring to [0, textureCount)
287  int currentTextureIndex = static_cast<int>(floor(mCloudBlendPos));
288  currentTextureIndex = ((currentTextureIndex % textureCount) + textureCount) % textureCount;
289  assert(0 <= currentTextureIndex);
290  assert(currentTextureIndex < textureCount);
291 
292  // Check if we have to change textures.
293  if (currentTextureIndex != mCurrentTextureIndex) {
294  String texture1 = mNoiseTextureNames[currentTextureIndex];
295  String texture2 = mNoiseTextureNames[(currentTextureIndex + 1) % textureCount];
296  //Ogre::LogManager::getSingleton ().logMessage (
297  // "Caelum: Switching cloud layer textures to " + texture1 + " and " + texture2);
298  Ogre::Pass* pass = mMaterial->getBestTechnique()->getPass(0);
299  pass->getTextureUnitState(0)->setTextureName(texture1);
300  pass->getTextureUnitState(1)->setTextureName(texture2);
301  mCurrentTextureIndex = currentTextureIndex;
302  }
303 
304  Ogre::Real cloudMassBlend = fmod(mCloudBlendPos, 1);
305  mParams.cloudMassBlend.set(mParams.fpParams, cloudMassBlend);
306  }
307 
308  Ogre::Real FlatCloudLayer::getCloudBlendPos () const {
309  return mCloudBlendPos;
310  }
311 
312  void FlatCloudLayer::setCloudSpeed (const Ogre::Vector2 &cloudSpeed) {
313  mCloudSpeed = cloudSpeed;
314  }
315 
316  void FlatCloudLayer::setSunDirection (const Ogre::Vector3 &sunDirection) {
317  mSunDirection = sunDirection;
318  mParams.vpSunDirection.set(mParams.vpParams, sunDirection);
319  mParams.fpSunDirection.set(mParams.fpParams, sunDirection);
320  }
321 
322  void FlatCloudLayer::setSunLightColour (const Ogre::ColourValue &sunLightColour) {
323  mParams.sunLightColour.set(mParams.fpParams, mSunLightColour = sunLightColour);
324  }
325 
326  void FlatCloudLayer::setSunSphereColour (const Ogre::ColourValue &sunSphereColour) {
327  mParams.sunSphereColour.set(mParams.fpParams, mSunSphereColour = sunSphereColour);
328  }
329 
330  void FlatCloudLayer::setFogColour (const Ogre::ColourValue &fogColour) {
331  mParams.fogColour.set(mParams.fpParams, mFogColour = fogColour);
332  }
333 
334  const Ogre::Vector3 FlatCloudLayer::getSunDirection () const {
335  return mSunDirection;
336  }
337 
338  const Ogre::ColourValue FlatCloudLayer::getSunLightColour () const {
339  return mSunLightColour;
340  }
341 
342  const Ogre::ColourValue FlatCloudLayer::getSunSphereColour () const {
343  return mSunSphereColour;
344  }
345 
346  const Ogre::ColourValue FlatCloudLayer::getFogColour () const {
347  return mFogColour;
348  }
349 
350  void FlatCloudLayer::setHeight(Ogre::Real height) {
351  mNode->setPosition(Ogre::Vector3(0, height, 0));
352  mHeight = height;
353  mParams.layerHeight.set(mParams.fpParams, mHeight);
354  }
355 
356  Ogre::Real FlatCloudLayer::getHeight() const {
357  return mHeight;
358  }
359 
360  void FlatCloudLayer::setCloudUVFactor (const Ogre::Real value) {
361  mParams.cloudUVFactor.set(mParams.fpParams, mCloudUVFactor = value);
362  }
363 
364  void FlatCloudLayer::setHeightRedFactor (const Ogre::Real value) {
365  mParams.heightRedFactor.set(mParams.fpParams, mHeightRedFactor = value);
366  }
367 
368  void FlatCloudLayer::setFadeDistances (const Ogre::Real nearValue, const Ogre::Real farValue) {
369  setNearFadeDist (nearValue);
370  setFarFadeDist (farValue);
371  }
372 
373  void FlatCloudLayer::setNearFadeDist (const Ogre::Real value) {
374  mParams.nearFadeDist.set(mParams.fpParams, mNearFadeDist = value);
375  }
376 
377  void FlatCloudLayer::setFarFadeDist (const Ogre::Real value) {
378  mParams.farFadeDist.set(mParams.fpParams, mFarFadeDist = value);
379  }
380 
381  void FlatCloudLayer::setFadeDistMeasurementVector (const Ogre::Vector3& value) {
382  mParams.fadeDistMeasurementVector.set(mParams.fpParams, mFadeDistMeasurementVector = value);
383  }
384 }
void setCloudBlendPos(const Ogre::Real value)
Set the current blending position; between noise textures.
void setFadeDistMeasurementVector(const Ogre::Vector3 &value)
Set on which components is the fade distance measured.
Ogre::Real getCloudBlendPos() const
void setCloudCoverLookup(const Ogre::String &fileName)
Set the image used to lookup the cloud coverage threshold.
void update(Ogre::Real timePassed, const Ogre::Vector3 &sunDirection, const Ogre::ColourValue &sunLightColour, const Ogre::ColourValue &fogColour, const Ogre::ColourValue &sunSphereColour)
Update function called each frame from above.
void setFarFadeDist(const Ogre::Real value)
Set only far fade distance (see setFadeDistances).
Ogre::Real getCloudBlendTime() const
Gets the time it takes to blend two cloud shaped together, in seconds.
void setHeight(Ogre::Real height)
Set the height of the cloud layer.
static const Ogre::String pointerToString(void *pointer)
Quickly format a pointer as a string; in hex.
static Ogre::MaterialPtr checkLoadMaterialClone(const Ogre::String &originalName, const Ogre::String &cloneName)
Creates a private clone of a material from a script.
Ogre::Real getHeight() const
Get the height of the cloud layer.
void _updateVisibilityThreshold()
Enforce setCloudCoverVisibilityThreshold.
Ogre::Real getCloudCover() const
Gets the current cloud cover.
void disableCloudCoverLookup()
Disable any cloud cover lookup.
void setCloudBlendTime(const Ogre::Real value)
Sets the time it takes to blend two cloud shaped together, in seconds.
void setCloudCoverVisibilityThreshold(const Ogre::Real value)
Set cloud cover visiblity threshold.
static Ogre::ColourValue getInterpolatedColour(float fx, float fy, Ogre::Image *img, bool wrapX=true)
Gets the interpolated colour between two pixels from an image.
const Ogre::String getCloudCoverLookupFileName() const
Get the filename of the cloud cover lookup image.
bool isNull() const
Check if this is null.
Definition: PrivatePtr.h:142
void setCloudCover(const Ogre::Real cloudCover)
Sets cloud cover, between 0 (completely clear) and 1 (completely covered)
Ogre::Real getCloudCoverVisibilityThreshold() const
Get cloud cover visiblity threshold.
void advanceAnimation(Ogre::Real timePassed)
Advance cloud animation (the time part of FlatCloudLayer::update).
static const String RESOURCE_GROUP_NAME
Resource group name for caelum resources.
void setNearFadeDist(const Ogre::Real value)
Set only near fade distance (see setFadeDistances).
void _invalidateGeometry()
Regenerate the plane mesh and recreate entity.
void reset(const InnerPointerType &newInner=TraitsT::getNullValue())
Change the inner value.
Definition: PrivatePtr.h:94
void reset()
Reset most tweak settings to their default values.
void setCloudSpeed(const Ogre::Vector2 &cloudSpeed)
Sets cloud movement speed.
void setHeightRedFactor(const Ogre::Real value)
High-altitude clouds are tinted red in the evening.
void _ensureGeometry()
Regenerate the plane mesh and recreate entity.
void setCloudUVFactor(const Ogre::Real value)
Cloud texture coordinates are multiplied with this.
void setFadeDistances(Ogre::Real nearValue, Ogre::Real farValue)
Cloud fade distances.
Caelum namespace.
Definition: Astronomy.cpp:24
void setMeshParameters(Real meshWidth, Real meshHeight, int meshWidthSegments, int meshHeightSegments)
Reset all mesh parameters.