00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "CaelumPrecompiled.h"
00022 #include "FlatCloudLayer.h"
00023 #include "CaelumExceptions.h"
00024 #include "InternalUtilities.h"
00025
00026 namespace Caelum
00027 {
00028 FlatCloudLayer::FlatCloudLayer(
00029 Ogre::SceneManager *sceneMgr,
00030 Ogre::SceneNode *cloudRoot)
00031 {
00032 Ogre::String uniqueSuffix = InternalUtilities::pointerToString(this);
00033
00034
00035 mMaterial.reset(InternalUtilities::checkLoadMaterialClone ("CaelumLayeredClouds", "Caelum/FlatCloudLayer/Material" + uniqueSuffix));
00036
00037 mParams.setup(
00038 mMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters(),
00039 mMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters());
00040
00041
00042 mSceneMgr = sceneMgr;
00043 mNode.reset(cloudRoot->createChildSceneNode());
00044 mNode->setPosition(Ogre::Vector3(0, 0, 0));
00045
00046
00047 mNoiseTextureNames.clear();
00048 mNoiseTextureNames.push_back("noise1.dds");
00049 mNoiseTextureNames.push_back("noise2.dds");
00050 mNoiseTextureNames.push_back("noise3.dds");
00051 mNoiseTextureNames.push_back("noise4.dds");
00052
00053
00054 mCurrentTextureIndex = -1;
00055
00056
00057 setHeight(0);
00058
00059
00060 this->reset();
00061
00062
00063 this->_ensureGeometry();
00064 }
00065
00066 FlatCloudLayer::~FlatCloudLayer()
00067 {
00068 mSceneMgr = 0;
00069
00070
00071 }
00072
00073 void FlatCloudLayer::_invalidateGeometry () {
00074 mMeshDirty = true;
00075 }
00076
00077 void FlatCloudLayer::_ensureGeometry ()
00078 {
00079 if (!mMeshDirty) {
00080 return;
00081 }
00082
00083
00084 Ogre::String uniqueId = Ogre::StringConverter::toString((size_t)this);
00085 Ogre::String planeMeshName = "Caelum/FlatCloudLayer/Plane/" + uniqueId;
00086 Ogre::String entityName = "Caelum/FlatCloudLayer/Entity/" + uniqueId;
00087
00088
00089 mEntity.reset();
00090 mMesh.reset();
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 Ogre::Plane meshPlane(
00101 Ogre::Vector3(1, 1, 0),
00102 Ogre::Vector3(1, 1, 1),
00103 Ogre::Vector3(0, 1, 1));
00104 mMesh.reset(Ogre::MeshManager::getSingleton().createPlane(
00105 planeMeshName, Caelum::RESOURCE_GROUP_NAME, meshPlane,
00106 mMeshWidth, mMeshHeight,
00107 mMeshWidthSegments, mMeshHeightSegments,
00108 false, 1,
00109 1.0f, 1.0f,
00110 Ogre::Vector3::UNIT_X));
00111
00112
00113 mEntity.reset(mSceneMgr->createEntity(entityName, mMesh->getName()));
00114 mEntity->setMaterialName(mMaterial->getName());
00115
00116
00117 mNode->attachObject(mEntity.get());
00118
00119
00120 mMeshDirty = false;
00121 }
00122
00123 void FlatCloudLayer::setMeshParameters (
00124 Real meshWidth, Real meshHeight,
00125 int meshWidthSegments, int meshHeightSegments)
00126 {
00127 bool invalidate =
00128 (mMeshWidthSegments != meshWidthSegments) ||
00129 (mMeshHeightSegments != meshHeightSegments) ||
00130 (abs(mMeshWidth - meshWidth) > 0.001) ||
00131 (abs(mMeshHeight - meshHeight) > 0.001);
00132 mMeshWidth = meshWidth;
00133 mMeshHeight = meshHeight;
00134 mMeshWidthSegments = meshWidthSegments;
00135 mMeshHeightSegments = meshHeightSegments;
00136 if (invalidate) {
00137 _invalidateGeometry();
00138 }
00139 }
00140
00141 void FlatCloudLayer::reset()
00142 {
00143 _invalidateGeometry ();
00144 setMeshParameters(10000000, 10000000, 10, 10);
00145
00146 assert (mCloudCoverLookup.get() == 0);
00147 setCloudCoverLookup ("CloudCoverLookup.png");
00148 setCloudCover (0.3);
00149 setCloudCoverVisibilityThreshold (0.001);
00150
00151 setCloudMassOffset (Ogre::Vector2(0, 0));
00152 setCloudDetailOffset (Ogre::Vector2(0, 0));
00153 setCloudBlendTime (3600 * 24);
00154 setCloudBlendPos (0.5);
00155
00156 setCloudSpeed (Ogre::Vector2(0.000005, -0.000009));
00157
00158 setCloudUVFactor (150);
00159 setHeightRedFactor (100000);
00160
00161 setFadeDistances (10000, 140000);
00162 setFadeDistMeasurementVector (Ogre::Vector3(0, 1, 1));
00163
00164 setSunDirection (Ogre::Vector3::UNIT_Y);
00165 setFogColour (Ogre::ColourValue::Black);
00166 setSunLightColour (Ogre::ColourValue::White);
00167 setSunSphereColour (Ogre::ColourValue::White);
00168 }
00169
00170 void FlatCloudLayer::update (
00171 Ogre::Real timePassed,
00172 const Ogre::Vector3 &sunDirection,
00173 const Ogre::ColourValue &sunLightColour,
00174 const Ogre::ColourValue &fogColour,
00175 const Ogre::ColourValue &sunSphereColour)
00176 {
00177
00178 advanceAnimation (timePassed);
00179
00180
00181 setSunDirection (sunDirection);
00182 setSunLightColour (sunLightColour);
00183 setSunSphereColour (sunSphereColour);
00184 setFogColour (fogColour);
00185
00186 this->_ensureGeometry();
00187
00188 this->_updateVisibilityThreshold();
00189 }
00190
00191 void FlatCloudLayer::_updateVisibilityThreshold ()
00192 {
00193 if (!mEntity.isNull()) {
00194 mEntity->setVisible (getCloudCover () > this->getCloudCoverVisibilityThreshold ());
00195 }
00196 }
00197
00198 void FlatCloudLayer::advanceAnimation (Ogre::Real timePassed)
00199 {
00200
00201 setCloudMassOffset(mCloudMassOffset + timePassed * mCloudSpeed);
00202 setCloudDetailOffset(mCloudDetailOffset - timePassed * mCloudSpeed);
00203
00204
00205 setCloudBlendPos (getCloudBlendPos () + timePassed / mCloudBlendTime);
00206 }
00207
00208 void FlatCloudLayer::Params::setup(Ogre::GpuProgramParametersSharedPtr vpParams, Ogre::GpuProgramParametersSharedPtr fpParams)
00209 {
00210 this->vpParams = vpParams;
00211 this->fpParams = fpParams;
00212 cloudCoverageThreshold.bind(fpParams, "cloudCoverageThreshold");
00213 cloudMassOffset.bind(fpParams, "cloudMassOffset");
00214 cloudDetailOffset.bind(fpParams, "cloudDetailOffset");
00215 cloudMassBlend.bind(fpParams, "cloudMassBlend");
00216 vpSunDirection.bind(vpParams, "sunDirection");
00217 fpSunDirection.bind(fpParams, "sunDirection");
00218 sunLightColour.bind(fpParams, "sunLightColour");
00219 sunSphereColour.bind(fpParams, "sunSphereColour");
00220 fogColour.bind(fpParams, "fogColour");
00221 layerHeight.bind(fpParams, "layerHeight");
00222 cloudUVFactor.bind(fpParams, "cloudUVFactor");
00223 heightRedFactor.bind(fpParams, "heightRedFactor");
00224 nearFadeDist.bind(fpParams, "nearFadeDist");
00225 farFadeDist.bind(fpParams, "farFadeDist");
00226 fadeDistMeasurementVector.bind(fpParams, "fadeDistMeasurementVector");
00227 }
00228
00229 void FlatCloudLayer::setCloudCoverLookup (const Ogre::String& fileName) {
00230 mCloudCoverLookup.reset(0);
00231 mCloudCoverLookup.reset(new Ogre::Image());
00232 mCloudCoverLookup->load(fileName, RESOURCE_GROUP_NAME);
00233
00234 mCloudCoverLookupFileName = fileName;
00235 }
00236
00237 void FlatCloudLayer::disableCloudCoverLookup () {
00238 mCloudCoverLookup.reset (0);
00239 mCloudCoverLookupFileName.clear ();
00240 }
00241
00242 const Ogre::String FlatCloudLayer::getCloudCoverLookupFileName () const {
00243 return mCloudCoverLookupFileName;
00244 }
00245
00246 void FlatCloudLayer::setCloudCoverVisibilityThreshold(const Ogre::Real value) {
00247 mCloudCoverVisibilityThreshold = value;
00248 _updateVisibilityThreshold();
00249 }
00250
00251 void FlatCloudLayer::setCloudCover(const Ogre::Real cloudCover) {
00252 mCloudCover = cloudCover;
00253 float cloudCoverageThreshold = 0;
00254 if (mCloudCoverLookup.get() != 0) {
00255 cloudCoverageThreshold = InternalUtilities::getInterpolatedColour(cloudCover, 1, mCloudCoverLookup.get(), false).r;
00256 } else {
00257 cloudCoverageThreshold = 1 - cloudCover;
00258 }
00259 mParams.cloudCoverageThreshold.set(mParams.fpParams, cloudCoverageThreshold);
00260 _updateVisibilityThreshold();
00261 }
00262
00263 void FlatCloudLayer::setCloudMassOffset(const Ogre::Vector2 &cloudMassOffset) {
00264 mCloudMassOffset = cloudMassOffset;
00265 mParams.cloudMassOffset.set(mParams.fpParams, Ogre::Vector3(cloudMassOffset.x,cloudMassOffset.y,0));
00266 }
00267
00268 void FlatCloudLayer::setCloudDetailOffset(const Ogre::Vector2 &cloudDetailOffset) {
00269 mCloudDetailOffset = cloudDetailOffset;
00270 mParams.cloudDetailOffset.set(mParams.fpParams, Ogre::Vector3(cloudDetailOffset.x,cloudDetailOffset.y,0));
00271 }
00272
00273 void FlatCloudLayer::setCloudBlendTime(const Ogre::Real value) {
00274 mCloudBlendTime = value;
00275 }
00276
00277 Ogre::Real FlatCloudLayer::getCloudBlendTime () const {
00278 return mCloudBlendTime;
00279 }
00280
00281 void FlatCloudLayer::setCloudBlendPos (const Ogre::Real value)
00282 {
00283 mCloudBlendPos = value;
00284 int textureCount = static_cast<int>(mNoiseTextureNames.size());
00285
00286
00287 int currentTextureIndex = static_cast<int>(floor(mCloudBlendPos));
00288 currentTextureIndex = ((currentTextureIndex % textureCount) + textureCount) % textureCount;
00289 assert(0 <= currentTextureIndex);
00290 assert(currentTextureIndex < textureCount);
00291
00292
00293 if (currentTextureIndex != mCurrentTextureIndex) {
00294 String texture1 = mNoiseTextureNames[currentTextureIndex];
00295 String texture2 = mNoiseTextureNames[(currentTextureIndex + 1) % textureCount];
00296
00297
00298 Ogre::Pass* pass = mMaterial->getBestTechnique()->getPass(0);
00299 pass->getTextureUnitState(0)->setTextureName(texture1);
00300 pass->getTextureUnitState(1)->setTextureName(texture2);
00301 mCurrentTextureIndex = currentTextureIndex;
00302 }
00303
00304 Ogre::Real cloudMassBlend = fmod(mCloudBlendPos, 1);
00305 mParams.cloudMassBlend.set(mParams.fpParams, cloudMassBlend);
00306 }
00307
00308 Ogre::Real FlatCloudLayer::getCloudBlendPos () const {
00309 return mCloudBlendPos;
00310 }
00311
00312 void FlatCloudLayer::setCloudSpeed (const Ogre::Vector2 &cloudSpeed) {
00313 mCloudSpeed = cloudSpeed;
00314 }
00315
00316 void FlatCloudLayer::setSunDirection (const Ogre::Vector3 &sunDirection) {
00317 mSunDirection = sunDirection;
00318 mParams.vpSunDirection.set(mParams.vpParams, sunDirection);
00319 mParams.fpSunDirection.set(mParams.fpParams, sunDirection);
00320 }
00321
00322 void FlatCloudLayer::setSunLightColour (const Ogre::ColourValue &sunLightColour) {
00323 mParams.sunLightColour.set(mParams.fpParams, mSunLightColour = sunLightColour);
00324 }
00325
00326 void FlatCloudLayer::setSunSphereColour (const Ogre::ColourValue &sunSphereColour) {
00327 mParams.sunSphereColour.set(mParams.fpParams, mSunSphereColour = sunSphereColour);
00328 }
00329
00330 void FlatCloudLayer::setFogColour (const Ogre::ColourValue &fogColour) {
00331 mParams.fogColour.set(mParams.fpParams, mFogColour = fogColour);
00332 }
00333
00334 const Ogre::Vector3 FlatCloudLayer::getSunDirection () const {
00335 return mSunDirection;
00336 }
00337
00338 const Ogre::ColourValue FlatCloudLayer::getSunLightColour () const {
00339 return mSunLightColour;
00340 }
00341
00342 const Ogre::ColourValue FlatCloudLayer::getSunSphereColour () const {
00343 return mSunSphereColour;
00344 }
00345
00346 const Ogre::ColourValue FlatCloudLayer::getFogColour () const {
00347 return mFogColour;
00348 }
00349
00350 void FlatCloudLayer::setHeight(Ogre::Real height) {
00351 mNode->setPosition(Ogre::Vector3(0, height, 0));
00352 mHeight = height;
00353 mParams.layerHeight.set(mParams.fpParams, mHeight);
00354 }
00355
00356 Ogre::Real FlatCloudLayer::getHeight() const {
00357 return mHeight;
00358 }
00359
00360 void FlatCloudLayer::setCloudUVFactor (const Ogre::Real value) {
00361 mParams.cloudUVFactor.set(mParams.fpParams, mCloudUVFactor = value);
00362 }
00363
00364 void FlatCloudLayer::setHeightRedFactor (const Ogre::Real value) {
00365 mParams.heightRedFactor.set(mParams.fpParams, mHeightRedFactor = value);
00366 }
00367
00368 void FlatCloudLayer::setFadeDistances (const Ogre::Real nearValue, const Ogre::Real farValue) {
00369 setNearFadeDist (nearValue);
00370 setFarFadeDist (farValue);
00371 }
00372
00373 void FlatCloudLayer::setNearFadeDist (const Ogre::Real value) {
00374 mParams.nearFadeDist.set(mParams.fpParams, mNearFadeDist = value);
00375 }
00376
00377 void FlatCloudLayer::setFarFadeDist (const Ogre::Real value) {
00378 mParams.farFadeDist.set(mParams.fpParams, mFarFadeDist = value);
00379 }
00380
00381 void FlatCloudLayer::setFadeDistMeasurementVector (const Ogre::Vector3& value) {
00382 mParams.fadeDistMeasurementVector.set(mParams.fpParams, mFadeDistMeasurementVector = value);
00383 }
00384 }