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 "GroundFog.h"
00023 #include "CaelumExceptions.h"
00024 #include "InternalUtilities.h"
00025
00026 namespace Caelum
00027 {
00028 const Ogre::String GroundFog::DEFAULT_PASS_NAME = "CaelumGroundFog";
00029
00030 GroundFog::GroundFog(
00031 Ogre::SceneManager *sceneMgr,
00032 Ogre::SceneNode *caelumRootNode,
00033 const Ogre::String &domeMaterialName,
00034 const Ogre::String &domeEntityName):
00035 mScene(sceneMgr)
00036 {
00037 Ogre::String uniqueSuffix = InternalUtilities::pointerToString (this);
00038
00039 mDomeMaterial.reset(InternalUtilities::checkLoadMaterialClone (domeMaterialName, domeMaterialName + uniqueSuffix));
00040 mDomeParams.setup(mDomeMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters());
00041
00042
00043
00044
00045 mDomeEntity.reset (mScene->createEntity (domeEntityName, Ogre::SceneManager::PT_SPHERE));
00046 mDomeEntity->setMaterialName (mDomeMaterial->getName ());
00047 mDomeEntity->setCastShadows (false);
00048 mDomeEntity->setRenderQueueGroup (CAELUM_RENDER_QUEUE_GROUND_FOG);
00049 sceneMgr->getRenderQueue()->getQueueGroup(CAELUM_RENDER_QUEUE_GROUND_FOG)->setShadowsEnabled(false);
00050
00051
00052 mDomeNode.reset (caelumRootNode->createChildSceneNode ());
00053 mDomeNode->attachObject (mDomeEntity.get());
00054
00055
00056 mDensity = 0.1;
00057 mVerticalDecay = 0.2;
00058 mGroundLevel = 5;
00059 mFogColour = Ogre::ColourValue::Black;
00060
00061 forceUpdate();
00062 }
00063
00064 GroundFog::~GroundFog() {
00065
00066 setDensity(0);
00067 }
00068
00069 GroundFog::PassSet& GroundFog::getPasses() {
00070 return mPasses;
00071 }
00072
00073 const GroundFog::PassSet& GroundFog::getPasses() const {
00074 return mPasses;
00075 }
00076
00077 void GroundFog::findFogPassesByName (const Ogre::String& passName) {
00078 Ogre::MaterialManager *matManager = Ogre::MaterialManager::getSingletonPtr();
00079 Ogre::MaterialManager::ResourceMapIterator matIt = matManager->getResourceIterator();
00080 while (matIt.hasMoreElements()) {
00081 Ogre::MaterialPtr mat = matIt.getNext();
00082 Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator();
00083 while (techIt.hasMoreElements()) {
00084 Ogre::Technique *tech = techIt.getNext();
00085 Ogre::Technique::PassIterator passIt = tech->getPassIterator();
00086 while (passIt.hasMoreElements()) {
00087 Ogre::Pass *pass = passIt.getNext();
00088 if (pass->getName() == passName) {
00089 mPasses.insert(pass);
00090 }
00091 }
00092 }
00093 }
00094 forceUpdate();
00095 }
00096
00097 void GroundFog::setDensity (Ogre::Real density) {
00098 if (Ogre::Math::Abs(mDensity - density) > 0.000001) {
00099 for (PassFogParamsVector::const_iterator it = mPassFogParams.begin(), end = mPassFogParams.end(); it != end; ++it) {
00100 it->fogDensity.set(it->fpParams, density);
00101 }
00102 mDensity = density;
00103 }
00104 updateSkyFogging();
00105 }
00106
00107 Ogre::Real GroundFog::getDensity () const {
00108 return mDensity;
00109 }
00110
00111 void GroundFog::setColour (const Ogre::ColourValue &colour) {
00112 bool different =
00113 Ogre::Math::Abs(mFogColour.r - colour.r) > 0.001 ||
00114 Ogre::Math::Abs(mFogColour.g - colour.g) > 0.001 ||
00115 Ogre::Math::Abs(mFogColour.b - colour.b) > 0.001 ||
00116 Ogre::Math::Abs(mFogColour.a - colour.a) > 0.001;
00117 if (different) {
00118 for (PassFogParamsVector::const_iterator it = mPassFogParams.begin(), end = mPassFogParams.end(); it != end; ++it) {
00119 it->fogColour.set(it->fpParams, colour);
00120 }
00121 mFogColour = colour;
00122 }
00123 updateSkyFogging();
00124 }
00125
00126 const Ogre::ColourValue GroundFog::getColour () const {
00127 return mFogColour;
00128 }
00129
00130 void GroundFog::setVerticalDecay (Ogre::Real verticalDecay) {
00131 if (Ogre::Math::Abs(mVerticalDecay - verticalDecay) > 0.000001) {
00132 for (PassFogParamsVector::const_iterator it = mPassFogParams.begin(), end = mPassFogParams.end(); it != end; ++it) {
00133 it->fogVerticalDecay.set(it->fpParams, verticalDecay);
00134 }
00135 mVerticalDecay = verticalDecay;
00136 }
00137 updateSkyFogging();
00138 }
00139
00140 Ogre::Real GroundFog::getVerticalDecay () const {
00141 return mVerticalDecay;
00142 }
00143
00144 void GroundFog::setGroundLevel (Ogre::Real groundLevel) {
00145 if (Ogre::Math::Abs(mGroundLevel - groundLevel) > 0.000001) {
00146 for (PassFogParamsVector::const_iterator it = mPassFogParams.begin(), end = mPassFogParams.end(); it != end; ++it) {
00147 it->fogGroundLevel.set(it->fpParams, groundLevel);
00148 }
00149 mGroundLevel = groundLevel;
00150 }
00151 updateSkyFogging();
00152 }
00153
00154 Ogre::Real GroundFog::getGroundLevel () const {
00155 return mGroundLevel;
00156 }
00157
00158 void GroundFog::updateSkyFogging() {
00159 mDomeParams.fogDensity.set(mDomeParams.fpParams, mDensity);
00160 mDomeParams.fogVerticalDecay.set(mDomeParams.fpParams, mVerticalDecay);
00161 mDomeParams.fogGroundLevel.set(mDomeParams.fpParams, mGroundLevel);
00162 mDomeParams.fogColour.set(mDomeParams.fpParams, mFogColour);
00163 }
00164
00165 void GroundFog::forceUpdate ()
00166 {
00167 updatePassFogParams();
00168 for (PassFogParamsVector::const_iterator it = mPassFogParams.begin(), end = mPassFogParams.end(); it != end; ++it) {
00169 const PassFogParams& params = *it;
00170 params.fogDensity.set(params.fpParams, mDensity);
00171 params.fogVerticalDecay.set(params.fpParams, mVerticalDecay);
00172 params.fogGroundLevel.set(params.fpParams, mGroundLevel);
00173 params.fogColour.set(params.fpParams, mFogColour);
00174 }
00175 updateSkyFogging();
00176 }
00177
00178 void GroundFog::updatePassFogParams ()
00179 {
00180 mPassFogParams.clear();
00181 for (PassSet::const_iterator it = mPasses.begin(), end = mPasses.end(); it != end; ++it) {
00182 mPassFogParams.push_back(PassFogParams((*it)->getFragmentProgramParameters()));
00183 }
00184 std::sort(mPassFogParams.begin(), mPassFogParams.end(), PassFogParams::lessThanByParams);
00185 std::unique(mPassFogParams.begin(), mPassFogParams.end(), PassFogParams::equalByParams);
00186 }
00187
00188 void GroundFog::FogParamsBase::setup(Ogre::GpuProgramParametersSharedPtr fpParams) {
00189 this->fpParams = fpParams;
00190 fogDensity.bind(fpParams, "fogDensity");
00191 fogVerticalDecay.bind(fpParams, "fogVerticalDecay");
00192 fogGroundLevel.bind(fpParams, "fogGroundLevel");
00193 fogColour.bind(fpParams, "fogColour");
00194 }
00195
00196 void GroundFog::DomeFogParams::setup(Ogre::GpuProgramParametersSharedPtr fpParams) {
00197 FogParamsBase::setup(fpParams);
00198 cameraHeight.bind(fpParams, "cameraHeight");
00199 }
00200
00201 void GroundFog::notifyCameraChanged (Ogre::Camera *cam)
00202 {
00203 CameraBoundElement::notifyCameraChanged (cam);
00204
00205
00206 float cameraHeight = cam->getDerivedPosition().dotProduct(mDomeNode->_getDerivedOrientation() * Ogre::Vector3::UNIT_Y);
00207 mDomeParams.cameraHeight.set(mDomeParams.fpParams, cameraHeight);
00208 }
00209
00210 void GroundFog::setFarRadius (Ogre::Real radius)
00211 {
00212 CameraBoundElement::setFarRadius(radius);
00213
00214 mDomeNode->setScale(Ogre::Vector3::UNIT_SCALE * radius / 50.0);
00215 }
00216 }