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
00025 namespace Caelum
00026 {
00027 FlatCloudLayer::FlatCloudLayer(
00028 Ogre::SceneManager *sceneMgr,
00029 Ogre::SceneNode *cloudRoot)
00030 {
00031 Ogre::String uniqueId = Ogre::StringConverter::toString((size_t)this);
00032 Ogre::String materialName = "Caelum/FlatCloudLayer/Material/" + uniqueId;
00033
00034
00035 Ogre::MaterialPtr originalMaterial = Ogre::MaterialManager::getSingleton ().getByName ("CaelumLayeredClouds");
00036 if (originalMaterial.isNull ()) {
00037 CAELUM_THROW_UNSUPPORTED_EXCEPTION (
00038 "Can't find material resource \"CaelumLayeredClouds\"",
00039 "FlatCloudLayer");
00040 }
00041 mMaterial.reset(originalMaterial->clone (materialName));
00042 mMaterial->load ();
00043 if (mMaterial->getBestTechnique () == 0) {
00044 CAELUM_THROW_UNSUPPORTED_EXCEPTION (
00045 "Can't load flat cloud layer material: " + mMaterial->getUnsupportedTechniquesExplanation(),
00046 "FlatCloudLayer");
00047 }
00048
00049
00050 getFpParams()->setIgnoreMissingParams(true);
00051 getVpParams()->setIgnoreMissingParams(true);
00052
00053
00054 mSceneMgr = sceneMgr;
00055 mNode.reset(cloudRoot->createChildSceneNode());
00056 mNode->setPosition(Ogre::Vector3(0, 0, 0));
00057
00058
00059 mNoiseTextureNames.clear();
00060 mNoiseTextureNames.push_back("noise1.dds");
00061 mNoiseTextureNames.push_back("noise2.dds");
00062 mNoiseTextureNames.push_back("noise3.dds");
00063 mNoiseTextureNames.push_back("noise4.dds");
00064
00065
00066 mCurrentTextureIndex = -1;
00067
00068
00069 setHeight(0);
00070
00071
00072 this->reset();
00073
00074
00075 this->_ensureGeometry();
00076 }
00077
00078 FlatCloudLayer::~FlatCloudLayer()
00079 {
00080 mSceneMgr = 0;
00081
00082
00083 }
00084
00085 void FlatCloudLayer::_invalidateGeometry () {
00086 mMeshDirty = true;
00087 }
00088
00089 void FlatCloudLayer::_ensureGeometry ()
00090 {
00091 if (!mMeshDirty) {
00092 return;
00093 }
00094
00095
00096 Ogre::String uniqueId = Ogre::StringConverter::toString((size_t)this);
00097 Ogre::String planeMeshName = "Caelum/FlatCloudLayer/Plane/" + uniqueId;
00098 Ogre::String entityName = "Caelum/FlatCloudLayer/Entity/" + uniqueId;
00099
00100
00101 mEntity.reset();
00102 mMesh.reset();
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 Ogre::Plane meshPlane(
00113 Ogre::Vector3(1, 1, 0),
00114 Ogre::Vector3(1, 1, 1),
00115 Ogre::Vector3(0, 1, 1));
00116 mMesh.reset(Ogre::MeshManager::getSingleton().createPlane(
00117 planeMeshName, Caelum::RESOURCE_GROUP_NAME, meshPlane,
00118 mMeshWidth, mMeshHeight,
00119 mMeshWidthSegments, mMeshHeightSegments,
00120 false, 1,
00121 1.0f, 1.0f,
00122 Ogre::Vector3::UNIT_X));
00123
00124
00125 mEntity.reset(mSceneMgr->createEntity(entityName, mMesh->getName()));
00126 mEntity->setMaterialName(mMaterial->getName());
00127
00128
00129 mNode->attachObject(mEntity.get());
00130
00131
00132 mMeshDirty = false;
00133 }
00134
00135 void FlatCloudLayer::setMeshParameters (
00136 Real meshWidth, Real meshHeight,
00137 int meshWidthSegments, int meshHeightSegments)
00138 {
00139 bool invalidate =
00140 (mMeshWidthSegments != meshWidthSegments) ||
00141 (mMeshHeightSegments != meshHeightSegments) ||
00142 (abs(mMeshWidth - meshWidth) > 0.001) ||
00143 (abs(mMeshHeight - meshHeight) > 0.001);
00144 mMeshWidth = meshWidth;
00145 mMeshHeight = meshHeight;
00146 mMeshWidthSegments = meshWidthSegments;
00147 mMeshHeightSegments = meshHeightSegments;
00148 if (invalidate) {
00149 _invalidateGeometry();
00150 }
00151 }
00152
00153 void FlatCloudLayer::reset()
00154 {
00155 _invalidateGeometry ();
00156 setMeshParameters(10000000, 10000000, 10, 10);
00157
00158 assert (mCloudCoverLookup.get() == 0);
00159 setCloudCoverLookup ("CloudCoverLookup.png");
00160 setCloudCover (0.3);
00161
00162 setCloudMassOffset (Ogre::Vector2(0, 0));
00163 setCloudDetailOffset (Ogre::Vector2(0, 0));
00164 setCloudBlendTime (3600 * 24);
00165 setCloudBlendPos (0.5);
00166
00167 setCloudSpeed (Ogre::Vector2(0.000005, -0.000009));
00168
00169 setCloudUVFactor (150);
00170 setHeightRedFactor (100000);
00171
00172 setFadeDistances (10000, 140000);
00173 }
00174
00175 void FlatCloudLayer::update (
00176 Ogre::Real timePassed,
00177 const Ogre::Vector3 &sunDirection,
00178 const Ogre::ColourValue &sunLightColour,
00179 const Ogre::ColourValue &fogColour,
00180 const Ogre::ColourValue &sunSphereColour)
00181 {
00182
00183 setSunDirection(sunDirection);
00184 setSunLightColour(sunLightColour);
00185 setSunSphereColour(sunSphereColour);
00186 setFogColour(fogColour);
00187
00188
00189 setCloudMassOffset(mCloudMassOffset + timePassed * mCloudSpeed);
00190 setCloudDetailOffset(mCloudDetailOffset - timePassed * mCloudSpeed);
00191
00192
00193 setCloudBlendPos (getCloudBlendPos () + timePassed / mCloudBlendTime);
00194
00195 this->_ensureGeometry();
00196 }
00197
00198 Ogre::GpuProgramParametersSharedPtr FlatCloudLayer::getVpParams() {
00199 return mMaterial->getBestTechnique()->getPass(0)->getVertexProgramParameters();
00200 }
00201
00202 Ogre::GpuProgramParametersSharedPtr FlatCloudLayer::getFpParams() {
00203 return mMaterial->getBestTechnique()->getPass(0)->getFragmentProgramParameters();
00204 }
00205
00206 void FlatCloudLayer::setCloudCoverLookup (const Ogre::String& fileName) {
00207 mCloudCoverLookup.reset(0);
00208 mCloudCoverLookup.reset(new Ogre::Image());
00209 mCloudCoverLookup->load(fileName, RESOURCE_GROUP_NAME);
00210 }
00211
00212 void FlatCloudLayer::setCloudCover(const Ogre::Real cloudCover) {
00213 mCloudCover = cloudCover;
00214 float cloudCoverageThreshold = 0;
00215 if (mCloudCoverLookup.get() != 0) {
00216 cloudCoverageThreshold = getInterpolatedColour(cloudCover, 1, mCloudCoverLookup.get(), false).r;
00217 } else {
00218 cloudCoverageThreshold = 1 - cloudCover;
00219 }
00220 getFpParams()->setNamedConstant("cloudCoverageThreshold", cloudCoverageThreshold);
00221 }
00222
00223 void FlatCloudLayer::setCloudMassOffset(const Ogre::Vector2 &cloudMassOffset) {
00224 mCloudMassOffset = cloudMassOffset;
00225 getFpParams()->setNamedConstant("cloudMassOffset", Ogre::Vector3(cloudMassOffset.x,cloudMassOffset.y,0));
00226 }
00227
00228 void FlatCloudLayer::setCloudDetailOffset(const Ogre::Vector2 &cloudDetailOffset) {
00229 mCloudDetailOffset = cloudDetailOffset;
00230 getFpParams()->setNamedConstant("cloudDetailOffset", Ogre::Vector3(cloudDetailOffset.x,cloudDetailOffset.y,0));
00231 }
00232
00233 void FlatCloudLayer::setCloudBlendTime(const Ogre::Real value) {
00234 mCloudBlendTime = value;
00235 }
00236
00237 Ogre::Real FlatCloudLayer::getCloudBlendTime () const {
00238 return mCloudBlendTime;
00239 }
00240
00241 void FlatCloudLayer::setCloudBlendPos (const Ogre::Real value)
00242 {
00243 mCloudBlendPos = value;
00244 int textureCount = static_cast<int>(mNoiseTextureNames.size());
00245
00246
00247 int currentTextureIndex = static_cast<int>(floor(mCloudBlendPos));
00248 currentTextureIndex = ((currentTextureIndex % textureCount) + textureCount) % textureCount;
00249 assert(0 <= currentTextureIndex);
00250 assert(currentTextureIndex < textureCount);
00251
00252
00253 if (currentTextureIndex != mCurrentTextureIndex) {
00254 String texture1 = mNoiseTextureNames[currentTextureIndex];
00255 String texture2 = mNoiseTextureNames[(currentTextureIndex + 1) % textureCount];
00256
00257
00258 Ogre::Pass* pass = mMaterial->getBestTechnique()->getPass(0);
00259 pass->getTextureUnitState(0)->setTextureName(texture1);
00260 pass->getTextureUnitState(1)->setTextureName(texture2);
00261 mCurrentTextureIndex = currentTextureIndex;
00262 }
00263
00264 Ogre::Real cloudMassBlend = fmod(mCloudBlendPos, 1);
00265 getFpParams()->setNamedConstant("cloudMassBlend", cloudMassBlend);
00266 }
00267
00268 Ogre::Real FlatCloudLayer::getCloudBlendPos () const {
00269 return mCloudBlendPos;
00270 }
00271
00272 void FlatCloudLayer::setCloudSpeed(const Ogre::Vector2 &cloudSpeed) {
00273 mCloudSpeed = cloudSpeed;
00274 }
00275
00276 void FlatCloudLayer::setSunDirection(const Ogre::Vector3 &sunDirection) {
00277 getVpParams()->setNamedConstant("sunDirection", sunDirection);
00278 getFpParams()->setNamedConstant("sunDirection", sunDirection);
00279 }
00280
00281 void FlatCloudLayer::setSunLightColour(const Ogre::ColourValue &sunLightColour) {
00282 getFpParams()->setNamedConstant("sunLightColour", sunLightColour);
00283 }
00284
00285 void FlatCloudLayer::setSunSphereColour(const Ogre::ColourValue &sunSphereColour) {
00286 getFpParams()->setNamedConstant("sunSphereColour", sunSphereColour);
00287 }
00288
00289 void FlatCloudLayer::setFogColour(const Ogre::ColourValue &fogColour) {
00290 getFpParams()->setNamedConstant("fogColour", fogColour);
00291 }
00292
00293 void FlatCloudLayer::setHeight(Ogre::Real height) {
00294 mNode->setPosition(Ogre::Vector3(0, height, 0));
00295 mHeight = height;
00296 getFpParams()->setNamedConstant("layerHeight", mHeight);
00297 }
00298
00299 Ogre::Real FlatCloudLayer::getHeight() const {
00300 return mHeight;
00301 }
00302
00303 void FlatCloudLayer::setCloudUVFactor (const Ogre::Real value) {
00304 getFpParams()->setNamedConstant("cloudUVFactor", mCloudUVFactor = value);
00305 }
00306
00307 void FlatCloudLayer::setHeightRedFactor (const Ogre::Real value) {
00308 getFpParams()->setNamedConstant("heightRedFactor", mHeightRedFactor = value);
00309 }
00310
00311 void FlatCloudLayer::setFadeDistances (const Ogre::Real nearValue, const Ogre::Real farValue) {
00312 setNearFadeDist (nearValue);
00313 setFarFadeDist (farValue);
00314 }
00315
00316 void FlatCloudLayer::setNearFadeDist (const Ogre::Real value) {
00317 getFpParams()->setNamedConstant("nearFadeDist", mNearFadeDist = value);
00318 }
00319
00320 void FlatCloudLayer::setFarFadeDist (const Ogre::Real value) {
00321 getFpParams()->setNamedConstant("farFadeDist", mFarFadeDist = value);
00322 }
00323 }