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 "LayeredClouds.h"
00023 #include "CaelumExceptions.h"
00024 #include "ImageHelper.h"
00025
00026 namespace caelum
00027 {
00030 inline Ogre::Vector3 extend(Ogre::Vector2 vec)
00031 {
00032 return Ogre::Vector3(vec.x, vec.y, 0);
00033 }
00034 }
00035
00036 namespace caelum
00037 {
00038 LayeredClouds::LayeredClouds
00039 (
00040 Ogre::SceneManager* sceneMgr,
00041 Ogre::SceneNode *caelumRootNode,
00042 const Ogre::String &resourceGroupName,
00043 const Ogre::String &materialName,
00044 const Ogre::String &meshName,
00045 const Ogre::String &entityName
00046 ):
00047 mCloudCoverLookup(0),
00048 mSceneMgr(sceneMgr)
00049 {
00050 mMaterial = Ogre::MaterialManager::getSingleton().getByName(materialName);
00051 mMaterial = mMaterial->clone(materialName + Ogre::StringConverter::toString((size_t)this));
00052 mMaterial->load();
00053 if (mMaterial->getBestTechnique() == 0) {
00054 throw new UnsupportedException (0, "Layered cloud material not supported.",
00055 "LayeredClouds", "LayeredClouds.cpp", -1);
00056 }
00057 mShadersEnabled = mMaterial->getBestTechnique()->getPass(0)->isProgrammable();
00058
00059 if(mShadersEnabled) {
00060 getFpParams()->setIgnoreMissingParams(true);
00061 getVpParams()->setIgnoreMissingParams(true);
00062 }
00063
00064
00065
00066 if (Ogre::MeshManager::getSingleton ().getByName (meshName).isNull ()) {
00067 Ogre::Plane plane = Ogre::Plane(Ogre::Vector3::NEGATIVE_UNIT_Y, -0.1);
00068 Ogre::MeshManager::getSingleton ().createCurvedPlane(
00069 meshName, resourceGroupName, plane, 2, 2, .4, 64, 64,
00070 false, 1, 1, 1, Ogre::Vector3::UNIT_Z);
00071 }
00072
00073 mSceneMgr->getRenderQueue()->getQueueGroup(CAELUM_RENDER_QUEUE_CLOUDS)->setShadowsEnabled(false);
00074
00075
00076 mEntity = mSceneMgr->createEntity(entityName, meshName);
00077 mEntity->setMaterialName(mMaterial->getName());
00078 mEntity->setCastShadows(false);
00079 mEntity->setRenderQueueGroup (CAELUM_RENDER_QUEUE_CLOUDS);
00080
00081 mNode = caelumRootNode->createChildSceneNode ();
00082 mNode->attachObject (mEntity);
00083
00084
00085 assert(mCloudCoverLookup.get() == 0);
00086 setCloudCoverLookup("CloudCoverLookup.png");
00087 setCloudCover(0.5);
00088 setCloudMassOffset(Ogre::Vector2(0, 0));
00089 setCloudDetailOffset(Ogre::Vector2(0, 0));
00090
00091 setAnimating(true);
00092 setCloudMassBlend(0.5);
00093 setCloudBlendTime(100);
00094 setCloudSpeed(Ogre::Vector2(0, 0));
00095 }
00096
00097 LayeredClouds::~LayeredClouds() {
00098 mNode->detachObject(mEntity);
00099 mSceneMgr->destroyEntity(mEntity);
00100 mEntity = 0;
00101 static_cast<Ogre::SceneNode*>(mNode->getParent())->
00102 removeAndDestroyChild(mNode->getName());
00103 mNode = 0;
00104 mSceneMgr = 0;
00105 Ogre::MaterialManager::getSingletonPtr()->remove(mMaterial->getHandle());
00106 }
00107
00108 void LayeredClouds::notifyCameraChanged (Ogre::Camera *cam) {
00109 CameraBoundElement::notifyCameraChanged (cam);
00110 }
00111
00112 void LayeredClouds::setFarRadius (Ogre::Real radius) {
00113 CameraBoundElement::setFarRadius (radius);
00114 mNode->setScale (Ogre::Vector3::UNIT_SCALE * radius);
00115 }
00116
00117 Ogre::GpuProgramParametersSharedPtr LayeredClouds::getVpParams() {
00118 return mMaterial->getBestTechnique()->getPass(0)->getVertexProgramParameters();
00119 }
00120
00121 Ogre::GpuProgramParametersSharedPtr LayeredClouds::getFpParams() {
00122 return mMaterial->getBestTechnique()->getPass(0)->getFragmentProgramParameters();
00123 }
00124
00125 Ogre::TextureUnitState* LayeredClouds::getTUS(unsigned short num) {
00126 return mMaterial->getBestTechnique()->getPass(0)->getTextureUnitState(num);
00127 }
00128
00129 void LayeredClouds::update(Ogre::Real timePassed,
00130 const Ogre::Vector3 &sunDirection,
00131 const Ogre::ColourValue &sunColour,
00132 const Ogre::ColourValue &fogColour)
00133 {
00134
00135 setSunDirection(sunDirection);
00136 setSunColour(sunColour);
00137 setFogColour(fogColour);
00138
00139 if (isAnimating()) {
00140
00141 setCloudMassOffset(getCloudMassOffset() + timePassed * getCloudSpeed());
00142 setCloudDetailOffset(getCloudDetailOffset() - timePassed * getCloudSpeed());
00143
00144
00145 double blend = getCloudMassBlend();
00146 blend += timePassed / getCloudBlendTime();
00147 blend = fmod(blend, 1);
00148 if (blend < 0) {
00149 blend = 1 - blend;
00150 }
00151 setCloudMassBlend(blend);
00152 }
00153 }
00154
00155 bool LayeredClouds::isAnimating () const {
00156 return mAnimating;
00157 }
00158
00159 void LayeredClouds::setAnimating (bool animating) {
00160 mAnimating = animating;
00161 }
00162
00163 void LayeredClouds::setCloudSpeed(const Ogre::Vector2 &cloudSpeed) {
00164 mCloudSpeed = cloudSpeed;
00165 }
00166
00167 Ogre::Vector2 LayeredClouds::getCloudSpeed() const {
00168 return mCloudSpeed;
00169 }
00170
00171 void LayeredClouds::setCloudBlendTime(const Ogre::Real cloudBlendTime) {
00172 static const Ogre::String animTextures1[4] = {
00173 "noise1.png", "noise2.png", "noise3.png", "noise4.png"
00174 };
00175 static const Ogre::String animTextures2[4] = {
00176 "noise2.png", "noise3.png", "noise4.png", "noise1.png"
00177 };
00178
00179 Ogre::Pass* pass = mMaterial->getBestTechnique()->getPass(0);
00180 pass->getTextureUnitState(0)->setAnimatedTextureName(animTextures1, 4, cloudBlendTime * 4);
00181 pass->getTextureUnitState(1)->setAnimatedTextureName(animTextures2, 4, cloudBlendTime * 4);
00182 setCloudMassBlend(0);
00183 mCloudBlendTime = cloudBlendTime;
00184 }
00185
00186 Ogre::Real LayeredClouds::getCloudBlendTime() const {
00187 return mCloudBlendTime;
00188 }
00189
00190 void LayeredClouds::setSunDirection(const Ogre::Vector3 &sunDirection) {
00191 if(mShadersEnabled) {
00192 getVpParams()->setNamedConstant("sunDirection", sunDirection);
00193 }
00194 }
00195
00196 void LayeredClouds::setSunColour(const Ogre::ColourValue &sunColour) {
00197 if(mShadersEnabled) {
00198 getFpParams()->setNamedConstant("sunColour", sunColour);
00199 }
00200 }
00201
00202 void LayeredClouds::setFogColour(const Ogre::ColourValue &fogColour) {
00203 if(mShadersEnabled) {
00204 getFpParams()->setNamedConstant("fogColour", fogColour);
00205 }
00206 }
00207
00208 void LayeredClouds::setCloudMassOffset(const Ogre::Vector2 &cloudMassOffset) {
00209 mCloudMassOffset = cloudMassOffset;
00210 if(mShadersEnabled) {
00211 getFpParams()->setNamedConstant("cloudMassOffset", extend(cloudMassOffset));
00212 } else {
00213 getTUS(0)->setTextureScroll(cloudMassOffset.x, cloudMassOffset.y);
00214 getTUS(1)->setTextureScroll(cloudMassOffset.x, cloudMassOffset.y);
00215 }
00216 }
00217
00218 Ogre::Vector2 LayeredClouds::getCloudMassOffset() const {
00219 return mCloudMassOffset;
00220 }
00221
00222 void LayeredClouds::setCloudMassBlend(const Ogre::Real cloudMassBlend) {
00223 mCloudMassBlend = cloudMassBlend;
00224 if(mShadersEnabled) {
00225 getFpParams()->setNamedConstant("cloudMassBlend", cloudMassBlend);
00226 } else {
00227 getTUS(1)->setColourOperationEx(Ogre::LBX_BLEND_MANUAL, Ogre::LBS_TEXTURE, Ogre::LBS_CURRENT, Ogre::ColourValue::White, Ogre::ColourValue::White, cloudMassBlend);
00228 }
00229 }
00230
00231 Ogre::Real LayeredClouds::getCloudMassBlend() const {
00232 return mCloudMassBlend;
00233 }
00234
00235 void LayeredClouds::setCloudDetailOffset(const Ogre::Vector2 &cloudDetailOffset) {
00236 mCloudDetailOffset = cloudDetailOffset;
00237 if(mShadersEnabled) {
00238 getFpParams()->setNamedConstant("cloudDetailOffset", extend(cloudDetailOffset));
00239 }
00240 }
00241
00242 Ogre::Vector2 LayeredClouds::getCloudDetailOffset() const {
00243 return mCloudDetailOffset;
00244 }
00245
00246 void LayeredClouds::setCloudCover(const Ogre::Real cloudCover) {
00247 mCloudCover = cloudCover;
00248
00249 if(mShadersEnabled) {
00250 float cloudCoverageThreshold = 0;
00251 if (mCloudCoverLookup.get() != 0) {
00252 cloudCoverageThreshold = getInterpolatedColour(cloudCover, 1, mCloudCoverLookup.get(), false).r;
00253 } else {
00254 cloudCoverageThreshold = 1 - cloudCover;
00255 }
00256 getFpParams()->setNamedConstant("cloudCoverageThreshold", cloudCoverageThreshold);
00257 }
00258 else {
00259 getTUS(2)->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, Ogre::ColourValue(cloudCover, cloudCover, cloudCover));
00260 }
00261 }
00262
00263 Ogre::Real LayeredClouds::getCloudCover() const {
00264 return mCloudCover;
00265 }
00266
00267 void LayeredClouds::setCloudCoverLookup (const Ogre::String& fileName) {
00268 mCloudCoverLookup.reset(0);
00269 mCloudCoverLookup.reset(new Ogre::Image());
00270 mCloudCoverLookup->load (fileName, RESOURCE_GROUP_NAME);
00271 }
00272
00273 void LayeredClouds::disableCloudCoverLookup () {
00274 mCloudCoverLookup.reset(0);
00275 }
00276 }