forked from teamnwah/openmw-tes3coop
		
	Merge branch 'master' into minimap
Conflicts: apps/openmw/mwscript/docs/vmformat.txt apps/openmw/mwworld/world.cpp
This commit is contained in:
		
						commit
						521b9eec6c
					
				
					 41 changed files with 3642 additions and 64 deletions
				
			
		| 
						 | 
				
			
			@ -181,6 +181,7 @@ ENDIF(WIN32)
 | 
			
		|||
ENDIF(OGRE_STATIC)
 | 
			
		||||
include_directories("."
 | 
			
		||||
    ${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OGRE_PLUGIN_INCLUDE_DIRS}
 | 
			
		||||
    ${OGRE_Terrain_INCLUDE_DIR}
 | 
			
		||||
    ${OIS_INCLUDE_DIRS} ${Boost_INCLUDE_DIR}
 | 
			
		||||
    ${PLATFORM_INCLUDE_DIR}
 | 
			
		||||
    ${MYGUI_INCLUDE_DIRS}
 | 
			
		||||
| 
						 | 
				
			
			@ -200,6 +201,7 @@ if(APPLE)
 | 
			
		|||
                          "Plugin_ParticleFX")
 | 
			
		||||
endif(APPLE)
 | 
			
		||||
 | 
			
		||||
add_subdirectory( files/)
 | 
			
		||||
add_subdirectory( files/mygui )
 | 
			
		||||
 | 
			
		||||
# Specify build paths
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER})
 | 
			
		|||
 | 
			
		||||
add_openmw_dir (mwrender
 | 
			
		||||
    renderingmanager debugging sky player animation npcanimation creatureanimation actors objects
 | 
			
		||||
    renderinginterface localmap
 | 
			
		||||
    renderinginterface localmap water terrain terrainmaterial
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
add_openmw_dir (mwinput
 | 
			
		||||
| 
						 | 
				
			
			@ -82,6 +82,7 @@ add_definitions(${SOUND_DEFINE})
 | 
			
		|||
 | 
			
		||||
target_link_libraries(openmw
 | 
			
		||||
    ${OGRE_LIBRARIES}
 | 
			
		||||
    ${OGRE_Terrain_LIBRARY}
 | 
			
		||||
    ${OGRE_STATIC_PLUGINS}
 | 
			
		||||
    ${OIS_LIBRARIES}
 | 
			
		||||
    ${Boost_LIBRARIES}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -315,7 +315,11 @@ void OMW::Engine::go()
 | 
			
		|||
 | 
			
		||||
    // This has to be added BEFORE MyGUI is initialized, as it needs
 | 
			
		||||
    // to find core.xml here.
 | 
			
		||||
 | 
			
		||||
    //addResourcesDirectory(mResDir);
 | 
			
		||||
   
 | 
			
		||||
    addResourcesDirectory(mResDir / "mygui");
 | 
			
		||||
    addResourcesDirectory(mResDir / "water");
 | 
			
		||||
 | 
			
		||||
    // Create the window
 | 
			
		||||
    mOgre->createWindow("OpenMW");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,9 +43,6 @@ DialogueWindow::DialogueWindow(WindowManager& parWindowManager,MWWorld::Environm
 | 
			
		|||
    // Centre dialog
 | 
			
		||||
    center();
 | 
			
		||||
 | 
			
		||||
    //WindowManager *wm = environment.mWindowManager;
 | 
			
		||||
    setText("NpcName", "Name of character");
 | 
			
		||||
 | 
			
		||||
    //History view
 | 
			
		||||
    getWidget(history, "History");
 | 
			
		||||
    history->setOverflowToTheLeft(true);
 | 
			
		||||
| 
						 | 
				
			
			@ -116,7 +113,8 @@ void DialogueWindow::onSelectTopic(MyGUI::ListBox* _sender, size_t _index)
 | 
			
		|||
 | 
			
		||||
void DialogueWindow::startDialogue(std::string npcName)
 | 
			
		||||
{
 | 
			
		||||
    setText("NpcName", npcName);
 | 
			
		||||
    static_cast<MyGUI::Window*>(mMainWidget)->setCaption(npcName);
 | 
			
		||||
    adjustWindowCaption();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DialogueWindow::setKeywords(std::list<std::string> keyWords)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -371,7 +371,6 @@ void WindowManager::updateSkillArea()
 | 
			
		|||
 | 
			
		||||
void WindowManager::removeDialog(OEngine::GUI::Layout*dialog)
 | 
			
		||||
{
 | 
			
		||||
    std::cout << "dialogue a la poubelle";
 | 
			
		||||
    assert(dialog);
 | 
			
		||||
    if (!dialog)
 | 
			
		||||
        return;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,12 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
 | 
			
		|||
:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0), mDebugging(engine)
 | 
			
		||||
{
 | 
			
		||||
    mRendering.createScene("PlayerCam", 55, 5);
 | 
			
		||||
    mTerrainManager = new TerrainManager(mRendering.getScene(),
 | 
			
		||||
                                         environment);
 | 
			
		||||
 | 
			
		||||
    //The fog type must be set before any terrain objects are created as if the
 | 
			
		||||
    //fog type is set to FOG_NONE then the initially created terrain won't have any fog
 | 
			
		||||
    configureFog(1, ColourValue(1,1,1));
 | 
			
		||||
 | 
			
		||||
    // Set default mipmap level (NB some APIs ignore this)
 | 
			
		||||
    TextureManager::getSingleton().setDefaultNumMipmaps(5);
 | 
			
		||||
| 
						 | 
				
			
			@ -53,6 +59,10 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
 | 
			
		|||
    //mSkyManager = 0;
 | 
			
		||||
    mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera(), &environment);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    mWater = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode);
 | 
			
		||||
    mSun = 0;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -64,6 +74,7 @@ RenderingManager::~RenderingManager ()
 | 
			
		|||
    //TODO: destroy mSun?
 | 
			
		||||
    delete mPlayer;
 | 
			
		||||
    delete mSkyManager;
 | 
			
		||||
    delete mTerrainManager;
 | 
			
		||||
    delete mLocalMap;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -88,14 +99,33 @@ OEngine::Render::Fader* RenderingManager::getFader()
 | 
			
		|||
    return mRendering.getFader();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingManager::removeCell (MWWorld::Ptr::CellStore *store){
 | 
			
		||||
void RenderingManager::removeCell (MWWorld::Ptr::CellStore *store)
 | 
			
		||||
{
 | 
			
		||||
    mObjects.removeCell(store);
 | 
			
		||||
    mActors.removeCell(store);
 | 
			
		||||
    if (store->cell->isExterior())
 | 
			
		||||
      mTerrainManager->cellRemoved(store);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingManager::removeWater ()
 | 
			
		||||
{
 | 
			
		||||
    if(mWater){
 | 
			
		||||
        delete mWater;
 | 
			
		||||
        mWater = 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingManager::toggleWater()
 | 
			
		||||
{
 | 
			
		||||
    if (mWater)
 | 
			
		||||
        mWater->toggle();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingManager::cellAdded (MWWorld::Ptr::CellStore *store)
 | 
			
		||||
{
 | 
			
		||||
    mObjects.buildStaticGeometry (*store);
 | 
			
		||||
    if (store->cell->isExterior())
 | 
			
		||||
      mTerrainManager->cellAdded(store);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingManager::addObject (const MWWorld::Ptr& ptr){
 | 
			
		||||
| 
						 | 
				
			
			@ -142,6 +172,27 @@ void RenderingManager::update (float duration){
 | 
			
		|||
    mRendering.update(duration);
 | 
			
		||||
 | 
			
		||||
    mLocalMap->updatePlayer( mRendering.getCamera()->getRealPosition(), mRendering.getCamera()->getRealDirection() );
 | 
			
		||||
 | 
			
		||||
    checkUnderwater();
 | 
			
		||||
}
 | 
			
		||||
void RenderingManager::waterAdded (MWWorld::Ptr::CellStore *store){
 | 
			
		||||
    if(store->cell->data.flags & store->cell->HasWater){
 | 
			
		||||
        if(mWater == 0)
 | 
			
		||||
            mWater = new MWRender::Water(mRendering.getCamera(), store->cell);
 | 
			
		||||
        else
 | 
			
		||||
            mWater->changeCell(store->cell);
 | 
			
		||||
        //else
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        removeWater();
 | 
			
		||||
   
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingManager::setWaterHeight(const float height)
 | 
			
		||||
{
 | 
			
		||||
    if (mWater)
 | 
			
		||||
        mWater->setHeight(height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingManager::skyEnable ()
 | 
			
		||||
| 
						 | 
				
			
			@ -236,17 +287,17 @@ void RenderingManager::setAmbientMode()
 | 
			
		|||
  {
 | 
			
		||||
    case 0:
 | 
			
		||||
 | 
			
		||||
      mRendering.getScene()->setAmbientLight(mAmbientColor);
 | 
			
		||||
      setAmbientColour(mAmbientColor);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 1:
 | 
			
		||||
 | 
			
		||||
      mRendering.getScene()->setAmbientLight(0.7f*mAmbientColor + 0.3f*ColourValue(1,1,1));
 | 
			
		||||
      setAmbientColour(0.7f*mAmbientColor + 0.3f*ColourValue(1,1,1));
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case 2:
 | 
			
		||||
 | 
			
		||||
      mRendering.getScene()->setAmbientLight(ColourValue(1,1,1));
 | 
			
		||||
      setAmbientColour(ColourValue(1,1,1));
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -286,6 +337,11 @@ void RenderingManager::toggleLight()
 | 
			
		|||
 | 
			
		||||
  setAmbientMode();
 | 
			
		||||
}
 | 
			
		||||
void RenderingManager::checkUnderwater(){
 | 
			
		||||
    if(mWater){
 | 
			
		||||
         mWater->checkUnderwater( mRendering.getCamera()->getRealPosition().y );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingManager::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName,
 | 
			
		||||
     int mode, int number)
 | 
			
		||||
| 
						 | 
				
			
			@ -301,11 +357,13 @@ void RenderingManager::skipAnimation (const MWWorld::Ptr& ptr)
 | 
			
		|||
void RenderingManager::setSunColour(const Ogre::ColourValue& colour)
 | 
			
		||||
{
 | 
			
		||||
    mSun->setDiffuseColour(colour);
 | 
			
		||||
    mTerrainManager->setDiffuse(colour);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingManager::setAmbientColour(const Ogre::ColourValue& colour)
 | 
			
		||||
{
 | 
			
		||||
    mRendering.getScene()->setAmbientLight(colour);
 | 
			
		||||
    mTerrainManager->setAmbient(colour);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RenderingManager::sunEnable()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
#include "sky.hpp"
 | 
			
		||||
#include "terrain.hpp"
 | 
			
		||||
#include "debugging.hpp"
 | 
			
		||||
 | 
			
		||||
#include "../mwworld/class.hpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -24,6 +25,7 @@
 | 
			
		|||
#include "objects.hpp"
 | 
			
		||||
#include "actors.hpp"
 | 
			
		||||
#include "player.hpp"
 | 
			
		||||
#include "water.hpp"
 | 
			
		||||
#include "localmap.hpp"
 | 
			
		||||
 | 
			
		||||
namespace Ogre
 | 
			
		||||
| 
						 | 
				
			
			@ -59,6 +61,8 @@ class RenderingManager: private RenderingInterface {
 | 
			
		|||
    RenderingManager(OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment);
 | 
			
		||||
    virtual ~RenderingManager();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    virtual MWRender::Player& getPlayer(); /// \todo move this to private again as soon as
 | 
			
		||||
                                            /// MWWorld::Player has been rewritten to not need access
 | 
			
		||||
                                            /// to internal details of the rendering system anymore
 | 
			
		||||
| 
						 | 
				
			
			@ -75,6 +79,9 @@ class RenderingManager: private RenderingInterface {
 | 
			
		|||
    /// \todo this function should be removed later. Instead the rendering subsystems should track
 | 
			
		||||
    /// when rebatching is needed and update automatically at the end of each frame.
 | 
			
		||||
    void cellAdded (MWWorld::Ptr::CellStore *store);
 | 
			
		||||
    void waterAdded(MWWorld::Ptr::CellStore *store);
 | 
			
		||||
 | 
			
		||||
    void removeWater();
 | 
			
		||||
 | 
			
		||||
    void preCellChange (MWWorld::Ptr::CellStore* store);
 | 
			
		||||
    ///< this event is fired immediately before changing cell
 | 
			
		||||
| 
						 | 
				
			
			@ -86,6 +93,10 @@ class RenderingManager: private RenderingInterface {
 | 
			
		|||
    void scaleObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& scale);
 | 
			
		||||
    void rotateObject (const MWWorld::Ptr& ptr, const::Ogre::Quaternion& orientation);
 | 
			
		||||
 | 
			
		||||
    void checkUnderwater();
 | 
			
		||||
    void setWaterHeight(const float height);
 | 
			
		||||
    void toggleWater();
 | 
			
		||||
 | 
			
		||||
    /// \param store Cell the object was in previously (\a ptr has already been updated to the new cell).
 | 
			
		||||
    void moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Vector3& position, MWWorld::Ptr::CellStore *store);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -134,6 +145,10 @@ class RenderingManager: private RenderingInterface {
 | 
			
		|||
 | 
			
		||||
    SkyManager* mSkyManager;
 | 
			
		||||
 | 
			
		||||
    MWRender::Water *mWater;
 | 
			
		||||
 | 
			
		||||
    TerrainManager* mTerrainManager;
 | 
			
		||||
 | 
			
		||||
    OEngine::Render::OgreRenderer &mRendering;
 | 
			
		||||
 | 
			
		||||
    MWRender::Objects mObjects;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										510
									
								
								apps/openmw/mwrender/terrain.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										510
									
								
								apps/openmw/mwrender/terrain.cpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,510 @@
 | 
			
		|||
#include <OgreTerrain.h>
 | 
			
		||||
#include <OgreTerrainGroup.h>
 | 
			
		||||
#include <boost/lexical_cast.hpp>
 | 
			
		||||
 | 
			
		||||
#include "../mwworld/world.hpp"
 | 
			
		||||
 | 
			
		||||
#include "terrainmaterial.hpp"
 | 
			
		||||
#include "terrain.hpp"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
using namespace Ogre;
 | 
			
		||||
 | 
			
		||||
namespace MWRender
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
    TerrainManager::TerrainManager(Ogre::SceneManager* mgr, const MWWorld::Environment& evn) :
 | 
			
		||||
        mEnvironment(evn), mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize))
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        TerrainMaterialGeneratorPtr matGen;
 | 
			
		||||
        TerrainMaterialGeneratorB* matGenP = new TerrainMaterialGeneratorB();
 | 
			
		||||
        matGen.bind(matGenP);
 | 
			
		||||
        mTerrainGlobals.setDefaultMaterialGenerator(matGen);
 | 
			
		||||
 | 
			
		||||
        TerrainMaterialGenerator::Profile* const activeProfile =
 | 
			
		||||
            mTerrainGlobals.getDefaultMaterialGenerator()
 | 
			
		||||
                           ->getActiveProfile();
 | 
			
		||||
        mActiveProfile = static_cast<TerrainMaterialGeneratorB::SM2Profile*>(activeProfile);
 | 
			
		||||
 | 
			
		||||
        //The pixel error should be as high as possible without it being noticed
 | 
			
		||||
        //as it governs how fast mesh quality decreases.
 | 
			
		||||
        mTerrainGlobals.setMaxPixelError(8);
 | 
			
		||||
 | 
			
		||||
        mTerrainGlobals.setLayerBlendMapSize(32);
 | 
			
		||||
        mTerrainGlobals.setDefaultGlobalColourMapSize(65);
 | 
			
		||||
 | 
			
		||||
        //10 (default) didn't seem to be quite enough
 | 
			
		||||
        mTerrainGlobals.setSkirtSize(128);
 | 
			
		||||
 | 
			
		||||
        //due to the sudden flick between composite and non composite textures,
 | 
			
		||||
        //this seemed the distance where it wasn't too noticeable
 | 
			
		||||
        mTerrainGlobals.setCompositeMapDistance(mWorldSize*2);
 | 
			
		||||
 | 
			
		||||
        mActiveProfile->setLightmapEnabled(false);
 | 
			
		||||
        mActiveProfile->setLayerSpecularMappingEnabled(false);
 | 
			
		||||
        mActiveProfile->setLayerNormalMappingEnabled(false);
 | 
			
		||||
        mActiveProfile->setLayerParallaxMappingEnabled(false);
 | 
			
		||||
        mActiveProfile->setReceiveDynamicShadowsEnabled(false);
 | 
			
		||||
 | 
			
		||||
        //composite maps lead to a drastic reduction in loading time so are
 | 
			
		||||
        //disabled
 | 
			
		||||
        mActiveProfile->setCompositeMapEnabled(false);
 | 
			
		||||
 | 
			
		||||
        mTerrainGroup.setOrigin(Vector3(mWorldSize/2,
 | 
			
		||||
                                         0,
 | 
			
		||||
                                         -mWorldSize/2));
 | 
			
		||||
 | 
			
		||||
        Terrain::ImportData& importSettings = mTerrainGroup.getDefaultImportSettings();
 | 
			
		||||
 | 
			
		||||
        importSettings.inputBias    = 0;
 | 
			
		||||
        importSettings.terrainSize  = mLandSize;
 | 
			
		||||
        importSettings.worldSize    = mWorldSize;
 | 
			
		||||
        importSettings.minBatchSize = 9;
 | 
			
		||||
        importSettings.maxBatchSize = mLandSize;
 | 
			
		||||
 | 
			
		||||
        importSettings.deleteInputData = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
    TerrainManager::~TerrainManager()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
    void TerrainManager::setDiffuse(const ColourValue& diffuse)
 | 
			
		||||
    {
 | 
			
		||||
        mTerrainGlobals.setCompositeMapDiffuse(diffuse);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
    void TerrainManager::setAmbient(const ColourValue& ambient)
 | 
			
		||||
    {
 | 
			
		||||
        mTerrainGlobals.setCompositeMapAmbient(ambient);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
    void TerrainManager::cellAdded(MWWorld::Ptr::CellStore *store)
 | 
			
		||||
    {
 | 
			
		||||
        const int cellX = store->cell->getGridX();
 | 
			
		||||
        const int cellY = store->cell->getGridY();
 | 
			
		||||
 | 
			
		||||
        ESM::Land* land = mEnvironment.mWorld->getStore().lands.search(cellX, cellY);
 | 
			
		||||
        if ( land != NULL )
 | 
			
		||||
        {
 | 
			
		||||
            land->loadData();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //split the cell terrain into four segments
 | 
			
		||||
        const int numTextures = ESM::Land::LAND_TEXTURE_SIZE/2;
 | 
			
		||||
 | 
			
		||||
        for ( int x = 0; x < 2; x++ )
 | 
			
		||||
        {
 | 
			
		||||
            for ( int y = 0; y < 2; y++ )
 | 
			
		||||
            {
 | 
			
		||||
                Terrain::ImportData terrainData =
 | 
			
		||||
                    mTerrainGroup.getDefaultImportSettings();
 | 
			
		||||
 | 
			
		||||
                const int terrainX = cellX * 2 + x;
 | 
			
		||||
                const int terrainY = cellY * 2 + y;
 | 
			
		||||
 | 
			
		||||
                //it makes far more sense to reallocate the memory here,
 | 
			
		||||
                //and let Ogre deal with it due to the issues with deleting
 | 
			
		||||
                //it at the wrong time if using threads (Which Terrain does)
 | 
			
		||||
                terrainData.inputFloat = OGRE_ALLOC_T(float,
 | 
			
		||||
                                                      mLandSize*mLandSize,
 | 
			
		||||
                                                      MEMCATEGORY_GEOMETRY);
 | 
			
		||||
 | 
			
		||||
                if ( land != NULL )
 | 
			
		||||
                {
 | 
			
		||||
                    //copy the height data row by row
 | 
			
		||||
                    for ( int terrainCopyY = 0; terrainCopyY < mLandSize; terrainCopyY++ )
 | 
			
		||||
                    {
 | 
			
		||||
                                               //the offset of the current segment
 | 
			
		||||
                        const size_t yOffset = y * (mLandSize-1) * ESM::Land::LAND_SIZE +
 | 
			
		||||
                                               //offset of the row
 | 
			
		||||
                                               terrainCopyY * ESM::Land::LAND_SIZE;
 | 
			
		||||
                        const size_t xOffset = x * (mLandSize-1);
 | 
			
		||||
 | 
			
		||||
                        memcpy(&terrainData.inputFloat[terrainCopyY*mLandSize],
 | 
			
		||||
                               &land->landData->heights[yOffset + xOffset],
 | 
			
		||||
                               mLandSize*sizeof(float));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    memset(terrainData.inputFloat, 0, mLandSize*mLandSize*sizeof(float));
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                std::map<uint16_t, int> indexes;
 | 
			
		||||
                initTerrainTextures(&terrainData, cellX, cellY,
 | 
			
		||||
                                    x * numTextures, y * numTextures,
 | 
			
		||||
                                    numTextures, indexes);
 | 
			
		||||
 | 
			
		||||
                if (mTerrainGroup.getTerrain(terrainX, terrainY) == NULL)
 | 
			
		||||
                {
 | 
			
		||||
                    mTerrainGroup.defineTerrain(terrainX, terrainY, &terrainData);
 | 
			
		||||
 | 
			
		||||
                    mTerrainGroup.loadTerrain(terrainX, terrainY, true);
 | 
			
		||||
 | 
			
		||||
                    Terrain* terrain = mTerrainGroup.getTerrain(terrainX, terrainY);
 | 
			
		||||
                    initTerrainBlendMaps(terrain,
 | 
			
		||||
                                         cellX, cellY,
 | 
			
		||||
                                         x * numTextures, y * numTextures,
 | 
			
		||||
                                         numTextures,
 | 
			
		||||
                                         indexes);
 | 
			
		||||
 | 
			
		||||
                    if ( land && land->landData->usingColours )
 | 
			
		||||
                    {
 | 
			
		||||
                        // disable or enable global colour map (depends on available vertex colours)
 | 
			
		||||
                        mActiveProfile->setGlobalColourMapEnabled(true);
 | 
			
		||||
                        TexturePtr vertex = getVertexColours(land,
 | 
			
		||||
                                                             cellX, cellY,
 | 
			
		||||
                                                             x*(mLandSize-1),
 | 
			
		||||
                                                             y*(mLandSize-1),
 | 
			
		||||
                                                             mLandSize);
 | 
			
		||||
 | 
			
		||||
                        //this is a hack to get around the fact that Ogre seems to
 | 
			
		||||
                        //corrupt the global colour map leading to rendering errors
 | 
			
		||||
                        MaterialPtr mat = terrain->getMaterial();
 | 
			
		||||
                        mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName( vertex->getName() );
 | 
			
		||||
                        //mat = terrain->_getCompositeMapMaterial();
 | 
			
		||||
                        //mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName( vertex->getName() );
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        mActiveProfile->setGlobalColourMapEnabled(false);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        mTerrainGroup.freeTemporaryResources();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
    void TerrainManager::cellRemoved(MWWorld::Ptr::CellStore *store)
 | 
			
		||||
    {
 | 
			
		||||
        for ( int x = 0; x < 2; x++ )
 | 
			
		||||
        {
 | 
			
		||||
            for ( int y = 0; y < 2; y++ )
 | 
			
		||||
            {
 | 
			
		||||
                mTerrainGroup.unloadTerrain(store->cell->getGridX() * 2 + x,
 | 
			
		||||
                                            store->cell->getGridY() * 2 + y);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
    void TerrainManager::initTerrainTextures(Terrain::ImportData* terrainData,
 | 
			
		||||
                                             int cellX, int cellY,
 | 
			
		||||
                                             int fromX, int fromY, int size,
 | 
			
		||||
                                             std::map<uint16_t, int>& indexes)
 | 
			
		||||
    {
 | 
			
		||||
        assert(terrainData != NULL && "Must have valid terrain data");
 | 
			
		||||
        assert(fromX >= 0 && fromY >= 0 &&
 | 
			
		||||
               "Can't get a terrain texture on terrain outside the current cell");
 | 
			
		||||
        assert(fromX+size <= ESM::Land::LAND_TEXTURE_SIZE &&
 | 
			
		||||
               fromY+size <= ESM::Land::LAND_TEXTURE_SIZE &&
 | 
			
		||||
               "Can't get a terrain texture on terrain outside the current cell");
 | 
			
		||||
 | 
			
		||||
        //this ensures that the ltex indexes are sorted (or retrived as sorted
 | 
			
		||||
        //which simplifies shading between cells).
 | 
			
		||||
        //
 | 
			
		||||
        //If we don't sort the ltex indexes, the splatting order may differ between
 | 
			
		||||
        //cells which may lead to inconsistent results when shading between cells
 | 
			
		||||
        std::set<uint16_t> ltexIndexes;
 | 
			
		||||
        for ( int y = fromY - 1; y < fromY + size + 1; y++ )
 | 
			
		||||
        {
 | 
			
		||||
            for ( int x = fromX - 1; x < fromX + size + 1; x++ )
 | 
			
		||||
            {
 | 
			
		||||
                ltexIndexes.insert(getLtexIndexAt(cellX, cellY, x, y));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //there is one texture that we want to use as a base (i.e. it won't have
 | 
			
		||||
        //a blend map). This holds the ltex index of that base texture so that
 | 
			
		||||
        //we know not to include it in the output map
 | 
			
		||||
        int baseTexture = -1;
 | 
			
		||||
        for ( std::set<uint16_t>::iterator iter = ltexIndexes.begin();
 | 
			
		||||
              iter != ltexIndexes.end();
 | 
			
		||||
              ++iter )
 | 
			
		||||
        {
 | 
			
		||||
            const uint16_t ltexIndex = *iter;
 | 
			
		||||
            //this is the base texture, so we can ignore this at present
 | 
			
		||||
            if ( ltexIndex == baseTexture )
 | 
			
		||||
            {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const std::map<uint16_t, int>::const_iterator it = indexes.find(ltexIndex);
 | 
			
		||||
 | 
			
		||||
            if ( it == indexes.end() )
 | 
			
		||||
            {
 | 
			
		||||
                //NB: All vtex ids are +1 compared to the ltex ids
 | 
			
		||||
 | 
			
		||||
                assert( (int)mEnvironment.mWorld->getStore().landTexts.getSize() >= (int)ltexIndex - 1 &&
 | 
			
		||||
                       "LAND.VTEX must be within the bounds of the LTEX array");
 | 
			
		||||
 | 
			
		||||
                std::string texture;
 | 
			
		||||
                if ( ltexIndex == 0 )
 | 
			
		||||
                {
 | 
			
		||||
                    texture = "_land_default.dds";
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    texture = mEnvironment.mWorld->getStore().landTexts.search(ltexIndex-1)->texture;
 | 
			
		||||
                    //TODO this is needed due to MWs messed up texture handling
 | 
			
		||||
                    texture = texture.substr(0, texture.rfind(".")) + ".dds";
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                const size_t position = terrainData->layerList.size();
 | 
			
		||||
                terrainData->layerList.push_back(Terrain::LayerInstance());
 | 
			
		||||
 | 
			
		||||
                terrainData->layerList[position].worldSize = 256;
 | 
			
		||||
                terrainData->layerList[position].textureNames.push_back("textures\\" + texture);
 | 
			
		||||
 | 
			
		||||
                if ( baseTexture == -1 )
 | 
			
		||||
                {
 | 
			
		||||
                    baseTexture = ltexIndex;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    indexes[ltexIndex] = position;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
    void TerrainManager::initTerrainBlendMaps(Terrain* terrain,
 | 
			
		||||
                                              int cellX, int cellY,
 | 
			
		||||
                                              int fromX, int fromY, int size,
 | 
			
		||||
                                              const std::map<uint16_t, int>& indexes)
 | 
			
		||||
    {
 | 
			
		||||
        assert(terrain != NULL && "Must have valid terrain");
 | 
			
		||||
        assert(fromX >= 0 && fromY >= 0 &&
 | 
			
		||||
               "Can't get a terrain texture on terrain outside the current cell");
 | 
			
		||||
        assert(fromX+size <= ESM::Land::LAND_TEXTURE_SIZE &&
 | 
			
		||||
               fromY+size <= ESM::Land::LAND_TEXTURE_SIZE &&
 | 
			
		||||
               "Can't get a terrain texture on terrain outside the current cell");
 | 
			
		||||
 | 
			
		||||
        //size must be a power of 2 as we do divisions with a power of 2 number
 | 
			
		||||
        //that need to result in an integer for correct splatting
 | 
			
		||||
        assert( (size & (size - 1)) == 0 && "Size must be a power of 2");
 | 
			
		||||
 | 
			
		||||
        const int blendMapSize = terrain->getLayerBlendMapSize();
 | 
			
		||||
        const int splatSize    = blendMapSize / size;
 | 
			
		||||
 | 
			
		||||
        //zero out every map
 | 
			
		||||
        std::map<uint16_t, int>::const_iterator iter;
 | 
			
		||||
        for ( iter = indexes.begin(); iter != indexes.end(); ++iter )
 | 
			
		||||
        {
 | 
			
		||||
            float* pBlend = terrain->getLayerBlendMap(iter->second)
 | 
			
		||||
                                   ->getBlendPointer();
 | 
			
		||||
            memset(pBlend, 0, sizeof(float) * blendMapSize * blendMapSize);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //covert the ltex data into a set of blend maps
 | 
			
		||||
        for ( int texY = fromY - 1; texY < fromY + size + 1; texY++ )
 | 
			
		||||
        {
 | 
			
		||||
            for ( int texX = fromX - 1; texX < fromX + size + 1; texX++ )
 | 
			
		||||
            {
 | 
			
		||||
                const uint16_t ltexIndex = getLtexIndexAt(cellX, cellY, texX, texY);
 | 
			
		||||
 | 
			
		||||
                //check if it is the base texture (which isn't in the map) and
 | 
			
		||||
                //if it is don't bother altering the blend map for it
 | 
			
		||||
                if ( indexes.find(ltexIndex) == indexes.end() )
 | 
			
		||||
                {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                //while texX is the splat index relative to the entire cell,
 | 
			
		||||
                //relX is relative to the current segment we are splatting
 | 
			
		||||
                const int relX = texX - fromX;
 | 
			
		||||
                const int relY = texY - fromY;
 | 
			
		||||
 | 
			
		||||
                const int layerIndex = indexes.find(ltexIndex)->second;
 | 
			
		||||
 | 
			
		||||
                float* const pBlend = terrain->getLayerBlendMap(layerIndex)
 | 
			
		||||
                                             ->getBlendPointer();
 | 
			
		||||
 | 
			
		||||
                for ( int y = -1; y < splatSize + 1; y++ )
 | 
			
		||||
                {
 | 
			
		||||
                    for ( int x = -1; x < splatSize + 1; x++ )
 | 
			
		||||
                    {
 | 
			
		||||
 | 
			
		||||
                        //Note: Y is reversed
 | 
			
		||||
                        const int splatY = blendMapSize - 1 - relY * splatSize - y;
 | 
			
		||||
                        const int splatX = relX * splatSize + x;
 | 
			
		||||
 | 
			
		||||
                        if ( splatX >= 0 && splatX < blendMapSize &&
 | 
			
		||||
                             splatY >= 0 && splatY < blendMapSize )
 | 
			
		||||
                        {
 | 
			
		||||
                            const int index = (splatY)*blendMapSize + splatX;
 | 
			
		||||
 | 
			
		||||
                            if ( y >= 0 && y < splatSize &&
 | 
			
		||||
                                 x >= 0 && x < splatSize )
 | 
			
		||||
                            {
 | 
			
		||||
                                pBlend[index] = 1;
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
                            {
 | 
			
		||||
                                //this provides a transition shading but also
 | 
			
		||||
                                //rounds off the corners slightly
 | 
			
		||||
                                pBlend[index] = std::min(1.0f, pBlend[index] + 0.5f);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for ( int i = 1; i < terrain->getLayerCount(); i++ )
 | 
			
		||||
        {
 | 
			
		||||
             TerrainLayerBlendMap* blend = terrain->getLayerBlendMap(i);
 | 
			
		||||
             blend->dirty();
 | 
			
		||||
             blend->update();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
    int TerrainManager::getLtexIndexAt(int cellX, int cellY,
 | 
			
		||||
                                       int x, int y)
 | 
			
		||||
    {
 | 
			
		||||
        //check texture index falls within the 9 cell bounds
 | 
			
		||||
        //as this function can't cope with anything above that
 | 
			
		||||
        assert(x >= -ESM::Land::LAND_TEXTURE_SIZE &&
 | 
			
		||||
               y >= -ESM::Land::LAND_TEXTURE_SIZE &&
 | 
			
		||||
               "Trying to get land textures that are out of bounds");
 | 
			
		||||
 | 
			
		||||
        assert(x < 2*ESM::Land::LAND_TEXTURE_SIZE &&
 | 
			
		||||
               y < 2*ESM::Land::LAND_TEXTURE_SIZE &&
 | 
			
		||||
               "Trying to get land textures that are out of bounds");
 | 
			
		||||
 | 
			
		||||
        if ( x < 0 )
 | 
			
		||||
        {
 | 
			
		||||
            cellX--;
 | 
			
		||||
            x += ESM::Land::LAND_TEXTURE_SIZE;
 | 
			
		||||
        }
 | 
			
		||||
        else if ( x >= ESM::Land::LAND_TEXTURE_SIZE )
 | 
			
		||||
        {
 | 
			
		||||
            cellX++;
 | 
			
		||||
            x -= ESM::Land::LAND_TEXTURE_SIZE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ( y < 0 )
 | 
			
		||||
        {
 | 
			
		||||
            cellY--;
 | 
			
		||||
            y += ESM::Land::LAND_TEXTURE_SIZE;
 | 
			
		||||
        }
 | 
			
		||||
        else if ( y >= ESM::Land::LAND_TEXTURE_SIZE )
 | 
			
		||||
        {
 | 
			
		||||
            cellY++;
 | 
			
		||||
            y -= ESM::Land::LAND_TEXTURE_SIZE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        ESM::Land* land = mEnvironment.mWorld->getStore().lands.search(cellX, cellY);
 | 
			
		||||
        if ( land != NULL )
 | 
			
		||||
        {
 | 
			
		||||
            land->loadData();
 | 
			
		||||
            return land->landData
 | 
			
		||||
                       ->textures[y * ESM::Land::LAND_TEXTURE_SIZE + x];
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //----------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
    TexturePtr TerrainManager::getVertexColours(ESM::Land* land,
 | 
			
		||||
                                                int cellX, int cellY,
 | 
			
		||||
                                                int fromX, int fromY, int size)
 | 
			
		||||
    {
 | 
			
		||||
        TextureManager* const texMgr = TextureManager::getSingletonPtr();
 | 
			
		||||
 | 
			
		||||
        const std::string colourTextureName = "VtexColours_" +
 | 
			
		||||
                                              boost::lexical_cast<std::string>(cellX) +
 | 
			
		||||
                                              "_" +
 | 
			
		||||
                                              boost::lexical_cast<std::string>(cellY) +
 | 
			
		||||
                                              "_" +
 | 
			
		||||
                                              boost::lexical_cast<std::string>(fromX) +
 | 
			
		||||
                                              "_" +
 | 
			
		||||
                                              boost::lexical_cast<std::string>(fromY);
 | 
			
		||||
 | 
			
		||||
        TexturePtr tex = texMgr->getByName(colourTextureName);
 | 
			
		||||
        if ( !tex.isNull() )
 | 
			
		||||
        {
 | 
			
		||||
            return tex;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        tex = texMgr->createManual(colourTextureName,
 | 
			
		||||
                                   ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
 | 
			
		||||
                                   TEX_TYPE_2D, size, size, 0, PF_BYTE_BGR);
 | 
			
		||||
 | 
			
		||||
        HardwarePixelBufferSharedPtr pixelBuffer = tex->getBuffer();
 | 
			
		||||
 | 
			
		||||
        pixelBuffer->lock(HardwareBuffer::HBL_DISCARD);
 | 
			
		||||
        const PixelBox& pixelBox = pixelBuffer->getCurrentLock();
 | 
			
		||||
 | 
			
		||||
        uint8* pDest = static_cast<uint8*>(pixelBox.data);
 | 
			
		||||
 | 
			
		||||
        if ( land != NULL )
 | 
			
		||||
        {
 | 
			
		||||
            const char* const colours = land->landData->colours;
 | 
			
		||||
            for ( int y = 0; y < size; y++ )
 | 
			
		||||
            {
 | 
			
		||||
                for ( int x = 0; x < size; x++ )
 | 
			
		||||
                {
 | 
			
		||||
                    const size_t colourOffset = (y+fromY)*3*65 + (x+fromX)*3;
 | 
			
		||||
 | 
			
		||||
                    assert( colourOffset < 65*65*3 &&
 | 
			
		||||
                            "Colour offset is out of the expected bounds of record" );
 | 
			
		||||
 | 
			
		||||
                    const unsigned char r = colours[colourOffset + 0];
 | 
			
		||||
                    const unsigned char g = colours[colourOffset + 1];
 | 
			
		||||
                    const unsigned char b = colours[colourOffset + 2];
 | 
			
		||||
 | 
			
		||||
                    //as is the case elsewhere we need to flip the y
 | 
			
		||||
                    const size_t imageOffset = (size - 1 - y)*size*4 + x*4;
 | 
			
		||||
                    pDest[imageOffset + 0] = b;
 | 
			
		||||
                    pDest[imageOffset + 1] = g;
 | 
			
		||||
                    pDest[imageOffset + 2] = r;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            for ( int y = 0; y < size; y++ )
 | 
			
		||||
            {
 | 
			
		||||
                for ( int x = 0; x < size; x++ )
 | 
			
		||||
                {
 | 
			
		||||
                    for ( int k = 0; k < 3; k++ )
 | 
			
		||||
                    {
 | 
			
		||||
                        *pDest++ = 0;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        pixelBuffer->unlock();
 | 
			
		||||
 | 
			
		||||
        return tex;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										117
									
								
								apps/openmw/mwrender/terrain.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								apps/openmw/mwrender/terrain.hpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,117 @@
 | 
			
		|||
#ifndef _GAME_RENDER_TERRAIN_H
 | 
			
		||||
#define _GAME_RENDER_TERRAIN_H
 | 
			
		||||
 | 
			
		||||
#include <OgreTerrain.h>
 | 
			
		||||
#include <OgreTerrainGroup.h>
 | 
			
		||||
#include "terrainmaterial.hpp"
 | 
			
		||||
 | 
			
		||||
#include "../mwworld/ptr.hpp"
 | 
			
		||||
 | 
			
		||||
namespace Ogre{
 | 
			
		||||
    class SceneManager;
 | 
			
		||||
    class TerrainGroup;
 | 
			
		||||
    class TerrainGlobalOptions;
 | 
			
		||||
    class Terrain;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace MWRender{
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Implements the Morrowind terrain using the Ogre Terrain Component
 | 
			
		||||
     *
 | 
			
		||||
     * Each terrain cell is split into four blocks as this leads to an increase
 | 
			
		||||
     * in performance and means we don't hit splat limits quite as much
 | 
			
		||||
     */
 | 
			
		||||
    class TerrainManager{
 | 
			
		||||
    public:
 | 
			
		||||
        TerrainManager(Ogre::SceneManager* mgr, const MWWorld::Environment& env);
 | 
			
		||||
        virtual ~TerrainManager();
 | 
			
		||||
 | 
			
		||||
        void setDiffuse(const Ogre::ColourValue& diffuse);
 | 
			
		||||
        void setAmbient(const Ogre::ColourValue& ambient);
 | 
			
		||||
 | 
			
		||||
        void cellAdded(MWWorld::Ptr::CellStore* store);
 | 
			
		||||
        void cellRemoved(MWWorld::Ptr::CellStore* store);
 | 
			
		||||
    private:
 | 
			
		||||
        Ogre::TerrainGlobalOptions mTerrainGlobals;
 | 
			
		||||
        Ogre::TerrainGroup mTerrainGroup;
 | 
			
		||||
 | 
			
		||||
        const MWWorld::Environment& mEnvironment;
 | 
			
		||||
 | 
			
		||||
        Ogre::TerrainMaterialGeneratorB::SM2Profile* mActiveProfile;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * The length in verticies of a single terrain block.
 | 
			
		||||
         */
 | 
			
		||||
        static const int mLandSize = (ESM::Land::LAND_SIZE - 1)/2 + 1;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * The length in game units of a single terrain block.
 | 
			
		||||
         */
 | 
			
		||||
        static const int mWorldSize = ESM::Land::REAL_SIZE/2;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Setups up the list of textures for part of a cell, using indexes as
 | 
			
		||||
         * an output to create a mapping of MW LtexIndex to the relevant terrain
 | 
			
		||||
         * layer
 | 
			
		||||
         *
 | 
			
		||||
         * @param terrainData the terrain data to setup the textures for
 | 
			
		||||
         * @param cellX the coord of the cell
 | 
			
		||||
         * @param cellY the coord of the cell
 | 
			
		||||
         * @param fromX the ltex index in the current cell to start making the texture from
 | 
			
		||||
         * @param fromY the ltex index in the current cell to start making the texture from
 | 
			
		||||
         * @param size the size (number of splats) to get
 | 
			
		||||
         * @param indexes a mapping of ltex index to the terrain texture layer that
 | 
			
		||||
         *          can be used by initTerrainBlendMaps
 | 
			
		||||
         */
 | 
			
		||||
        void initTerrainTextures(Ogre::Terrain::ImportData* terrainData,
 | 
			
		||||
                                 int cellX, int cellY,
 | 
			
		||||
                                 int fromX, int fromY, int size,
 | 
			
		||||
                                 std::map<uint16_t, int>& indexes);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Creates the blend (splatting maps) for the given terrain from the ltex data.
 | 
			
		||||
         *
 | 
			
		||||
         * @param terrain the terrain object for the current cell
 | 
			
		||||
         * @param cellX the coord of the cell
 | 
			
		||||
         * @param cellY the coord of the cell
 | 
			
		||||
         * @param fromX the ltex index in the current cell to start making the texture from
 | 
			
		||||
         * @param fromY the ltex index in the current cell to start making the texture from
 | 
			
		||||
         * @param size the size (number of splats) to get
 | 
			
		||||
         * @param indexes the mapping of ltex to blend map produced by initTerrainTextures
 | 
			
		||||
         */
 | 
			
		||||
        void initTerrainBlendMaps(Ogre::Terrain* terrain,
 | 
			
		||||
                                  int cellX, int cellY,
 | 
			
		||||
                                  int fromX, int fromY, int size,
 | 
			
		||||
                                  const std::map<uint16_t, int>& indexes);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Gets a LTEX index at the given point, assuming the current cell
 | 
			
		||||
         * starts at (0,0). This supports getting values from the surrounding
 | 
			
		||||
         * cells so negative x, y is acceptable
 | 
			
		||||
         *
 | 
			
		||||
         * @param cellX the coord of the cell
 | 
			
		||||
         * @param cellY the coord of the cell
 | 
			
		||||
         * @param x, y the splat position of the ltex index to get relative to the
 | 
			
		||||
         *             first splat of the current cell
 | 
			
		||||
         */
 | 
			
		||||
        int getLtexIndexAt(int cellX, int cellY, int x, int y);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Due to the fact that Ogre terrain doesn't support vertex colours
 | 
			
		||||
         * we have to generate them manually
 | 
			
		||||
         *
 | 
			
		||||
         * @param cellX the coord of the cell
 | 
			
		||||
         * @param cellY the coord of the cell
 | 
			
		||||
         * @param fromX the *vertex* index in the current cell to start making texture from
 | 
			
		||||
         * @param fromY the *vertex* index in the current cell to start making the texture from
 | 
			
		||||
         * @param size the size (number of vertexes) to get
 | 
			
		||||
         */
 | 
			
		||||
        Ogre::TexturePtr getVertexColours(ESM::Land* land,
 | 
			
		||||
                                          int cellX, int cellY,
 | 
			
		||||
                                          int fromX, int fromY, int size);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // _GAME_RENDER_TERRAIN_H
 | 
			
		||||
							
								
								
									
										1741
									
								
								apps/openmw/mwrender/terrainmaterial.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1741
									
								
								apps/openmw/mwrender/terrainmaterial.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										266
									
								
								apps/openmw/mwrender/terrainmaterial.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										266
									
								
								apps/openmw/mwrender/terrainmaterial.hpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,266 @@
 | 
			
		|||
/*
 | 
			
		||||
-----------------------------------------------------------------------------
 | 
			
		||||
This source file is part of OGRE
 | 
			
		||||
(Object-oriented Graphics Rendering Engine)
 | 
			
		||||
For the latest info, see http://www.ogre3d.org/
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2000-2011 Torus Knot Software Ltd
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in
 | 
			
		||||
all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
THE SOFTWARE.
 | 
			
		||||
-----------------------------------------------------------------------------
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef __Ogre_TerrainMaterialGeneratorB_H__
 | 
			
		||||
#define __Ogre_TerrainMaterialGeneratorB_H__
 | 
			
		||||
 | 
			
		||||
#include "OgreTerrainPrerequisites.h"
 | 
			
		||||
#include "OgreTerrainMaterialGenerator.h"
 | 
			
		||||
#include "OgreGpuProgramParams.h"
 | 
			
		||||
 | 
			
		||||
namespace Ogre
 | 
			
		||||
{
 | 
			
		||||
	class PSSMShadowCameraSetup;
 | 
			
		||||
 | 
			
		||||
	/** \addtogroup Optional Components
 | 
			
		||||
	*  @{
 | 
			
		||||
	*/
 | 
			
		||||
	/** \addtogroup Terrain
 | 
			
		||||
	*  Some details on the terrain component
 | 
			
		||||
	*  @{
 | 
			
		||||
	*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	/** A TerrainMaterialGenerator which can cope with normal mapped, specular mapped
 | 
			
		||||
		terrain. 
 | 
			
		||||
		@note Requires the Cg plugin to render correctly
 | 
			
		||||
	*/
 | 
			
		||||
	class _OgreTerrainExport TerrainMaterialGeneratorB : public TerrainMaterialGenerator
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
		TerrainMaterialGeneratorB();
 | 
			
		||||
		~TerrainMaterialGeneratorB();
 | 
			
		||||
 | 
			
		||||
		/** Shader model 2 profile target. 
 | 
			
		||||
		*/
 | 
			
		||||
		class _OgreTerrainExport SM2Profile : public TerrainMaterialGenerator::Profile
 | 
			
		||||
		{
 | 
			
		||||
		public:
 | 
			
		||||
			SM2Profile(TerrainMaterialGenerator* parent, const String& name, const String& desc);
 | 
			
		||||
			~SM2Profile();
 | 
			
		||||
 | 
			
		||||
            bool isVertexCompressionSupported() const {return false;}
 | 
			
		||||
            
 | 
			
		||||
			MaterialPtr generate(const Terrain* terrain);
 | 
			
		||||
			MaterialPtr generateForCompositeMap(const Terrain* terrain);
 | 
			
		||||
			uint8 getMaxLayers(const Terrain* terrain) const;
 | 
			
		||||
			void updateParams(const MaterialPtr& mat, const Terrain* terrain);
 | 
			
		||||
			void updateParamsForCompositeMap(const MaterialPtr& mat, const Terrain* terrain);
 | 
			
		||||
			void requestOptions(Terrain* terrain);
 | 
			
		||||
 | 
			
		||||
			/** Whether to support normal mapping per layer in the shader (default true). 
 | 
			
		||||
			*/
 | 
			
		||||
			bool isLayerNormalMappingEnabled() const  { return mLayerNormalMappingEnabled; }
 | 
			
		||||
			/** Whether to support normal mapping per layer in the shader (default true). 
 | 
			
		||||
			*/
 | 
			
		||||
			void setLayerNormalMappingEnabled(bool enabled);
 | 
			
		||||
			/** Whether to support parallax mapping per layer in the shader (default true). 
 | 
			
		||||
			*/
 | 
			
		||||
			bool isLayerParallaxMappingEnabled() const  { return mLayerParallaxMappingEnabled; }
 | 
			
		||||
			/** Whether to support parallax mapping per layer in the shader (default true). 
 | 
			
		||||
			*/
 | 
			
		||||
			void setLayerParallaxMappingEnabled(bool enabled);
 | 
			
		||||
			/** Whether to support specular mapping per layer in the shader (default true). 
 | 
			
		||||
			*/
 | 
			
		||||
			bool isLayerSpecularMappingEnabled() const  { return mLayerSpecularMappingEnabled; }
 | 
			
		||||
			/** Whether to support specular mapping per layer in the shader (default true). 
 | 
			
		||||
			*/
 | 
			
		||||
			void setLayerSpecularMappingEnabled(bool enabled);
 | 
			
		||||
			/** Whether to support a global colour map over the terrain in the shader,
 | 
			
		||||
				if it's present (default true). 
 | 
			
		||||
			*/
 | 
			
		||||
			bool isGlobalColourMapEnabled() const  { return mGlobalColourMapEnabled; }
 | 
			
		||||
			/** Whether to support a global colour map over the terrain in the shader,
 | 
			
		||||
			if it's present (default true). 
 | 
			
		||||
			*/
 | 
			
		||||
			void setGlobalColourMapEnabled(bool enabled);
 | 
			
		||||
			/** Whether to support a light map over the terrain in the shader,
 | 
			
		||||
			if it's present (default true). 
 | 
			
		||||
			*/
 | 
			
		||||
			bool isLightmapEnabled() const  { return mLightmapEnabled; }
 | 
			
		||||
			/** Whether to support a light map over the terrain in the shader,
 | 
			
		||||
			if it's present (default true). 
 | 
			
		||||
			*/
 | 
			
		||||
			void setLightmapEnabled(bool enabled);
 | 
			
		||||
			/** Whether to use the composite map to provide a lower LOD technique
 | 
			
		||||
				in the distance (default true). 
 | 
			
		||||
			*/
 | 
			
		||||
			bool isCompositeMapEnabled() const  { return mCompositeMapEnabled; }
 | 
			
		||||
			/** Whether to use the composite map to provide a lower LOD technique
 | 
			
		||||
			in the distance (default true). 
 | 
			
		||||
			*/
 | 
			
		||||
			void setCompositeMapEnabled(bool enabled);
 | 
			
		||||
			/** Whether to support dynamic texture shadows received from other 
 | 
			
		||||
				objects, on the terrain (default true). 
 | 
			
		||||
			*/
 | 
			
		||||
			bool getReceiveDynamicShadowsEnabled() const  { return mReceiveDynamicShadows; }
 | 
			
		||||
			/** Whether to support dynamic texture shadows received from other 
 | 
			
		||||
			objects, on the terrain (default true). 
 | 
			
		||||
			*/
 | 
			
		||||
			void setReceiveDynamicShadowsEnabled(bool enabled);
 | 
			
		||||
 | 
			
		||||
			/** Whether to use PSSM support dynamic texture shadows, and if so the 
 | 
			
		||||
				settings to use (default 0). 
 | 
			
		||||
			*/
 | 
			
		||||
			void setReceiveDynamicShadowsPSSM(PSSMShadowCameraSetup* pssmSettings);
 | 
			
		||||
			/** Whether to use PSSM support dynamic texture shadows, and if so the 
 | 
			
		||||
			settings to use (default 0). 
 | 
			
		||||
			*/
 | 
			
		||||
			PSSMShadowCameraSetup* getReceiveDynamicShadowsPSSM() const { return mPSSM; }
 | 
			
		||||
			/** Whether to use depth shadows (default false). 
 | 
			
		||||
			*/
 | 
			
		||||
			void setReceiveDynamicShadowsDepth(bool enabled);
 | 
			
		||||
			/** Whether to use depth shadows (default false). 
 | 
			
		||||
			*/
 | 
			
		||||
			bool getReceiveDynamicShadowsDepth() const { return mDepthShadows; }
 | 
			
		||||
			/** Whether to use shadows on low LOD material rendering (when using composite map) (default false). 
 | 
			
		||||
			*/
 | 
			
		||||
			void setReceiveDynamicShadowsLowLod(bool enabled);
 | 
			
		||||
			/** Whether to use shadows on low LOD material rendering (when using composite map) (default false). 
 | 
			
		||||
			*/
 | 
			
		||||
			bool getReceiveDynamicShadowsLowLod() const { return mLowLodShadows; }
 | 
			
		||||
 | 
			
		||||
                        int getNumberOfLightsSupported() const;
 | 
			
		||||
 | 
			
		||||
			/// Internal
 | 
			
		||||
			bool _isSM3Available() const { return mSM3Available; }
 | 
			
		||||
		
 | 
			
		||||
		protected:
 | 
			
		||||
 | 
			
		||||
			enum TechniqueType
 | 
			
		||||
			{
 | 
			
		||||
				HIGH_LOD, 
 | 
			
		||||
				LOW_LOD, 
 | 
			
		||||
				RENDER_COMPOSITE_MAP
 | 
			
		||||
			};
 | 
			
		||||
			void addTechnique(const MaterialPtr& mat, const Terrain* terrain, TechniqueType tt);
 | 
			
		||||
 | 
			
		||||
			/// Interface definition for helper class to generate shaders
 | 
			
		||||
			class _OgreTerrainExport ShaderHelper : public TerrainAlloc
 | 
			
		||||
			{
 | 
			
		||||
			public:
 | 
			
		||||
				ShaderHelper() {}
 | 
			
		||||
				virtual ~ShaderHelper() {}
 | 
			
		||||
				virtual HighLevelGpuProgramPtr generateVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
 | 
			
		||||
				virtual HighLevelGpuProgramPtr generateFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
 | 
			
		||||
				virtual void updateParams(const SM2Profile* prof, const MaterialPtr& mat, const Terrain* terrain, bool compositeMap);
 | 
			
		||||
			protected:
 | 
			
		||||
				virtual String getVertexProgramName(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
 | 
			
		||||
				virtual String getFragmentProgramName(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
 | 
			
		||||
				virtual HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) = 0;
 | 
			
		||||
				virtual HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) = 0;
 | 
			
		||||
				virtual void generateVertexProgramSource(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream);
 | 
			
		||||
				virtual void generateFragmentProgramSource(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream);
 | 
			
		||||
				virtual void generateVpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) = 0;
 | 
			
		||||
				virtual void generateFpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) = 0;
 | 
			
		||||
				virtual void generateVpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream) = 0;
 | 
			
		||||
				virtual void generateFpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream) = 0;
 | 
			
		||||
				virtual void generateVpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) = 0;
 | 
			
		||||
				virtual void generateFpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) = 0;
 | 
			
		||||
				virtual void defaultVpParams(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog);
 | 
			
		||||
				virtual void defaultFpParams(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog);
 | 
			
		||||
				virtual void updateVpParams(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const GpuProgramParametersSharedPtr& params);
 | 
			
		||||
				virtual void updateFpParams(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const GpuProgramParametersSharedPtr& params);
 | 
			
		||||
				static String getChannel(uint idx);
 | 
			
		||||
 | 
			
		||||
				size_t mShadowSamplerStartHi;
 | 
			
		||||
				size_t mShadowSamplerStartLo;
 | 
			
		||||
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			/// Utility class to help with generating shaders for Cg / HLSL.
 | 
			
		||||
			class _OgreTerrainExport ShaderHelperCg : public ShaderHelper
 | 
			
		||||
			{
 | 
			
		||||
			protected:
 | 
			
		||||
				HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
 | 
			
		||||
				HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
 | 
			
		||||
				void generateVpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream);
 | 
			
		||||
				void generateFpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream);
 | 
			
		||||
				void generateVpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream);
 | 
			
		||||
				void generateFpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream);
 | 
			
		||||
				void generateVpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream);
 | 
			
		||||
				void generateFpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream);
 | 
			
		||||
				uint generateVpDynamicShadowsParams(uint texCoordStart, const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream);
 | 
			
		||||
				void generateVpDynamicShadows(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream);
 | 
			
		||||
				void generateFpDynamicShadowsHelpers(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream);
 | 
			
		||||
				void generateFpDynamicShadowsParams(uint* texCoord, uint* sampler, const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream);
 | 
			
		||||
				void generateFpDynamicShadows(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream);
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			class _OgreTerrainExport ShaderHelperHLSL : public ShaderHelperCg
 | 
			
		||||
			{
 | 
			
		||||
			protected:
 | 
			
		||||
				HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
 | 
			
		||||
				HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			/// Utility class to help with generating shaders for GLSL.
 | 
			
		||||
			class _OgreTerrainExport ShaderHelperGLSL : public ShaderHelper
 | 
			
		||||
			{
 | 
			
		||||
			protected:
 | 
			
		||||
				HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
 | 
			
		||||
				HighLevelGpuProgramPtr createFragmentProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
 | 
			
		||||
				void generateVpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) {}
 | 
			
		||||
				void generateFpHeader(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) {}
 | 
			
		||||
				void generateVpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream) {}
 | 
			
		||||
				void generateFpLayer(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, uint layer, StringUtil::StrStreamType& outStream) {}
 | 
			
		||||
				void generateVpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) {}
 | 
			
		||||
				void generateFpFooter(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream) {}
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			ShaderHelper* mShaderGen;
 | 
			
		||||
			bool mLayerNormalMappingEnabled;
 | 
			
		||||
			bool mLayerParallaxMappingEnabled;
 | 
			
		||||
			bool mLayerSpecularMappingEnabled;
 | 
			
		||||
			bool mGlobalColourMapEnabled;
 | 
			
		||||
			bool mLightmapEnabled;
 | 
			
		||||
			bool mCompositeMapEnabled;
 | 
			
		||||
			bool mReceiveDynamicShadows;
 | 
			
		||||
			PSSMShadowCameraSetup* mPSSM;
 | 
			
		||||
			bool mDepthShadows;
 | 
			
		||||
			bool mLowLodShadows;
 | 
			
		||||
			bool mSM3Available;
 | 
			
		||||
 | 
			
		||||
			bool isShadowingEnabled(TechniqueType tt, const Terrain* terrain) const;
 | 
			
		||||
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	/** @} */
 | 
			
		||||
	/** @} */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										95
									
								
								apps/openmw/mwrender/water.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								apps/openmw/mwrender/water.cpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,95 @@
 | 
			
		|||
#include "water.hpp"
 | 
			
		||||
 | 
			
		||||
namespace MWRender
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
Water::Water (Ogre::Camera *camera, const ESM::Cell* cell) :
 | 
			
		||||
    mCamera (camera), mViewport (camera->getViewport()), mSceneManager (camera->getSceneManager()),
 | 
			
		||||
    mIsUnderwater(false)
 | 
			
		||||
{
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        Ogre::CompositorManager::getSingleton().addCompositor(mViewport, "Water", -1);
 | 
			
		||||
        Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Water", false);
 | 
			
		||||
    } catch(...) {}
 | 
			
		||||
 | 
			
		||||
    mTop = cell->water;
 | 
			
		||||
 | 
			
		||||
    mIsUnderwater = false;
 | 
			
		||||
 | 
			
		||||
    mWaterPlane = Ogre::Plane(Ogre::Vector3::UNIT_Y, 0);
 | 
			
		||||
 | 
			
		||||
    Ogre::MeshManager::getSingleton().createPlane("water", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,  mWaterPlane, CELL_SIZE*5, CELL_SIZE * 5, 10, 10, true, 1, 3,5, Ogre::Vector3::UNIT_Z);
 | 
			
		||||
 | 
			
		||||
    mWater = mSceneManager->createEntity("water");
 | 
			
		||||
 | 
			
		||||
    mWater->setMaterialName("Examples/Water0");
 | 
			
		||||
 | 
			
		||||
    mWaterNode = mSceneManager->getRootSceneNode()->createChildSceneNode();
 | 
			
		||||
    mWaterNode->setPosition(0, mTop, 0);
 | 
			
		||||
 | 
			
		||||
    if(!(cell->data.flags & cell->Interior))
 | 
			
		||||
    {
 | 
			
		||||
        mWaterNode->setPosition(getSceneNodeCoordinates(cell->data.gridX, cell->data.gridY));
 | 
			
		||||
    }
 | 
			
		||||
    mWaterNode->attachObject(mWater);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Water::~Water()
 | 
			
		||||
{
 | 
			
		||||
    Ogre::MeshManager::getSingleton().remove("water");
 | 
			
		||||
 | 
			
		||||
    mWaterNode->detachObject(mWater);
 | 
			
		||||
    mSceneManager->destroyEntity(mWater);
 | 
			
		||||
    mSceneManager->destroySceneNode(mWaterNode);
 | 
			
		||||
 | 
			
		||||
    Ogre::CompositorManager::getSingleton().removeCompositorChain(mViewport);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Water::changeCell(const ESM::Cell* cell)
 | 
			
		||||
{
 | 
			
		||||
    mTop = cell->water;
 | 
			
		||||
 | 
			
		||||
    if(!(cell->data.flags & cell->Interior))
 | 
			
		||||
        mWaterNode->setPosition(getSceneNodeCoordinates(cell->data.gridX, cell->data.gridY));
 | 
			
		||||
    else
 | 
			
		||||
        setHeight(mTop);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Water::setHeight(const float height)
 | 
			
		||||
{
 | 
			
		||||
    mTop = height;
 | 
			
		||||
    mWaterNode->setPosition(0, height, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Water::toggle()
 | 
			
		||||
{
 | 
			
		||||
    mWater->setVisible(!mWater->getVisible());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Water::checkUnderwater(float y)
 | 
			
		||||
{
 | 
			
		||||
    if ((mIsUnderwater && y > mTop) || !mWater->isVisible())
 | 
			
		||||
    {
 | 
			
		||||
        try {
 | 
			
		||||
            Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Water", false);
 | 
			
		||||
        } catch(...) {}
 | 
			
		||||
        mIsUnderwater = false;
 | 
			
		||||
    } 
 | 
			
		||||
 | 
			
		||||
    if (!mIsUnderwater && y < mTop && mWater->isVisible())
 | 
			
		||||
    {
 | 
			
		||||
        try {
 | 
			
		||||
            Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Water", true);
 | 
			
		||||
        } catch(...) {}
 | 
			
		||||
        mIsUnderwater = true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Ogre::Vector3 Water::getSceneNodeCoordinates(int gridX, int gridY)
 | 
			
		||||
{
 | 
			
		||||
    return Ogre::Vector3(gridX * CELL_SIZE + (CELL_SIZE / 2), mTop, -gridY * CELL_SIZE - (CELL_SIZE / 2));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace
 | 
			
		||||
							
								
								
									
										40
									
								
								apps/openmw/mwrender/water.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								apps/openmw/mwrender/water.hpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
#ifndef GAME_MWRENDER_WATER_H
 | 
			
		||||
#define GAME_MWRENDER_WATER_H
 | 
			
		||||
 | 
			
		||||
#include <Ogre.h>
 | 
			
		||||
#include <components/esm/loadcell.hpp>
 | 
			
		||||
 | 
			
		||||
namespace MWRender {
 | 
			
		||||
 | 
			
		||||
    /// Water rendering 	
 | 
			
		||||
    class Water : Ogre::RenderTargetListener, Ogre::Camera::Listener
 | 
			
		||||
    {
 | 
			
		||||
        static const int CELL_SIZE = 8192;
 | 
			
		||||
        Ogre::Camera *mCamera;
 | 
			
		||||
        Ogre::SceneManager *mSceneManager;
 | 
			
		||||
        Ogre::Viewport *mViewport;
 | 
			
		||||
 | 
			
		||||
        Ogre::Plane mWaterPlane;
 | 
			
		||||
        Ogre::SceneNode *mWaterNode;
 | 
			
		||||
        Ogre::Entity *mWater;
 | 
			
		||||
 | 
			
		||||
        bool mIsUnderwater;
 | 
			
		||||
        int mTop;
 | 
			
		||||
 | 
			
		||||
        Ogre::Vector3 getSceneNodeCoordinates(int gridX, int gridY);
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        Water (Ogre::Camera *camera, const ESM::Cell* cell);
 | 
			
		||||
        ~Water();
 | 
			
		||||
 | 
			
		||||
        void toggle();
 | 
			
		||||
 | 
			
		||||
        void checkUnderwater(float y);
 | 
			
		||||
        void changeCell(const ESM::Cell* cell);
 | 
			
		||||
        void setHeight(const float height);
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -133,11 +133,70 @@ namespace MWScript
 | 
			
		|||
                }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class OpGetWaterLevel : public Interpreter::Opcode0
 | 
			
		||||
        {
 | 
			
		||||
            public:
 | 
			
		||||
 | 
			
		||||
                virtual void execute (Interpreter::Runtime& runtime)
 | 
			
		||||
                {
 | 
			
		||||
                    InterpreterContext& context
 | 
			
		||||
                        = static_cast<InterpreterContext&> (runtime.getContext());
 | 
			
		||||
 | 
			
		||||
                    MWWorld::Ptr::CellStore *cell = context.getWorld().getPlayer().getPlayer().getCell();
 | 
			
		||||
                    runtime.push (cell->mWaterLevel);
 | 
			
		||||
                }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class OpSetWaterLevel : public Interpreter::Opcode0
 | 
			
		||||
        {
 | 
			
		||||
            public:
 | 
			
		||||
 | 
			
		||||
                virtual void execute (Interpreter::Runtime& runtime)
 | 
			
		||||
                {
 | 
			
		||||
                    InterpreterContext& context
 | 
			
		||||
                        = static_cast<InterpreterContext&> (runtime.getContext());
 | 
			
		||||
 | 
			
		||||
                    Interpreter::Type_Float level = runtime[0].mFloat;
 | 
			
		||||
 | 
			
		||||
                    MWWorld::Ptr::CellStore *cell = context.getWorld().getPlayer().getPlayer().getCell();
 | 
			
		||||
 | 
			
		||||
                    if (!(cell->cell->data.flags & ESM::Cell::Interior))
 | 
			
		||||
                        throw std::runtime_error("Can't set water level in exterior cell");
 | 
			
		||||
 | 
			
		||||
                    cell->mWaterLevel = level;
 | 
			
		||||
                    context.getEnvironment().mWorld->setWaterHeight(cell->mWaterLevel);
 | 
			
		||||
                }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class OpModWaterLevel : public Interpreter::Opcode0
 | 
			
		||||
        {
 | 
			
		||||
            public:
 | 
			
		||||
 | 
			
		||||
                virtual void execute (Interpreter::Runtime& runtime)
 | 
			
		||||
                {
 | 
			
		||||
                    InterpreterContext& context
 | 
			
		||||
                        = static_cast<InterpreterContext&> (runtime.getContext());
 | 
			
		||||
 | 
			
		||||
                    Interpreter::Type_Float level = runtime[0].mFloat;
 | 
			
		||||
 | 
			
		||||
                    MWWorld::Ptr::CellStore *cell = context.getWorld().getPlayer().getPlayer().getCell();
 | 
			
		||||
 | 
			
		||||
                    if (!(cell->cell->data.flags & ESM::Cell::Interior))
 | 
			
		||||
                        throw std::runtime_error("Can't set water level in exterior cell");
 | 
			
		||||
                    
 | 
			
		||||
                    cell->mWaterLevel +=level;
 | 
			
		||||
                    context.getEnvironment().mWorld->setWaterHeight(cell->mWaterLevel);
 | 
			
		||||
                }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        const int opcodeCellChanged = 0x2000000;
 | 
			
		||||
        const int opcodeCOC = 0x2000026;
 | 
			
		||||
        const int opcodeCOE = 0x200008e;
 | 
			
		||||
        const int opcodeGetInterior = 0x2000131;
 | 
			
		||||
        const int opcodeGetPCCell = 0x2000136;
 | 
			
		||||
        const int opcodeGetWaterLevel = 0x2000141;
 | 
			
		||||
        const int opcodeSetWaterLevel = 0x2000142;
 | 
			
		||||
        const int opcodeModWaterLevel = 0x2000143;
 | 
			
		||||
 | 
			
		||||
        void registerExtensions (Compiler::Extensions& extensions)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -146,8 +205,11 @@ namespace MWScript
 | 
			
		|||
            extensions.registerInstruction ("centeroncell", "S", opcodeCOC);
 | 
			
		||||
            extensions.registerInstruction ("coe", "ll", opcodeCOE);
 | 
			
		||||
            extensions.registerInstruction ("centeronexterior", "ll", opcodeCOE);
 | 
			
		||||
            extensions.registerInstruction ("setwaterlevel", "f", opcodeSetWaterLevel);
 | 
			
		||||
            extensions.registerInstruction ("modwaterlevel", "f", opcodeModWaterLevel);
 | 
			
		||||
            extensions.registerFunction ("getinterior", 'l', "", opcodeGetInterior);
 | 
			
		||||
            extensions.registerFunction ("getpccell", 'l', "c", opcodeGetPCCell);
 | 
			
		||||
            extensions.registerFunction ("getwaterlevel", 'f', "", opcodeGetWaterLevel);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void installOpcodes (Interpreter::Interpreter& interpreter)
 | 
			
		||||
| 
						 | 
				
			
			@ -157,6 +219,9 @@ namespace MWScript
 | 
			
		|||
            interpreter.installSegment5 (opcodeCOE, new OpCOE);
 | 
			
		||||
            interpreter.installSegment5 (opcodeGetInterior, new OpGetInterior);
 | 
			
		||||
            interpreter.installSegment5 (opcodeGetPCCell, new OpGetPCCell);
 | 
			
		||||
            interpreter.installSegment5 (opcodeGetWaterLevel, new OpGetWaterLevel);
 | 
			
		||||
            interpreter.installSegment5 (opcodeSetWaterLevel, new OpSetWaterLevel);
 | 
			
		||||
            interpreter.installSegment5 (opcodeModWaterLevel, new OpModWaterLevel);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -123,5 +123,9 @@ op 0x200013d: FadeOut
 | 
			
		|||
op 0x200013e: FadeTo
 | 
			
		||||
op 0x200013f: GetCurrentWeather
 | 
			
		||||
op 0x2000140: ChangeWeather
 | 
			
		||||
op 0x2000141: GetWaterLevel
 | 
			
		||||
op 0x2000142: SetWaterLevel
 | 
			
		||||
op 0x2000143: ModWaterLevel
 | 
			
		||||
op 0x2000144: ToggleWater, twa
 | 
			
		||||
op 0x2000145: ToggleFogOfWar (tfow)
 | 
			
		||||
opcodes 0x2000146-0x3ffffff unused
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -175,6 +175,19 @@ namespace MWScript
 | 
			
		|||
                }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        class OpToggleWater : public Interpreter::Opcode0
 | 
			
		||||
        {
 | 
			
		||||
            public:
 | 
			
		||||
 | 
			
		||||
                virtual void execute (Interpreter::Runtime& runtime)
 | 
			
		||||
                {
 | 
			
		||||
                    InterpreterContext& context =
 | 
			
		||||
                        static_cast<InterpreterContext&> (runtime.getContext());
 | 
			
		||||
 | 
			
		||||
                    context.getWorld().toggleWater();
 | 
			
		||||
                }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        const int opcodeXBox = 0x200000c;
 | 
			
		||||
        const int opcodeOnActivate = 0x200000d;
 | 
			
		||||
        const int opcodeActivate = 0x2000075;
 | 
			
		||||
| 
						 | 
				
			
			@ -187,6 +200,7 @@ namespace MWScript
 | 
			
		|||
        const int opcodeFadeIn = 0x200013c;
 | 
			
		||||
        const int opcodeFadeOut = 0x200013d;
 | 
			
		||||
        const int opcodeFadeTo = 0x200013e;
 | 
			
		||||
        const int opcodeToggleWater = 0x2000144;
 | 
			
		||||
 | 
			
		||||
        void registerExtensions (Compiler::Extensions& extensions)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -204,6 +218,8 @@ namespace MWScript
 | 
			
		|||
            extensions.registerInstruction ("fadein", "f", opcodeFadeIn);
 | 
			
		||||
            extensions.registerInstruction ("fadeout", "f", opcodeFadeOut);
 | 
			
		||||
            extensions.registerInstruction ("fadeto", "ff", opcodeFadeTo);
 | 
			
		||||
            extensions.registerInstruction ("togglewater", "", opcodeToggleWater);
 | 
			
		||||
            extensions.registerInstruction ("twa", "", opcodeToggleWater);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void installOpcodes (Interpreter::Interpreter& interpreter)
 | 
			
		||||
| 
						 | 
				
			
			@ -220,6 +236,7 @@ namespace MWScript
 | 
			
		|||
            interpreter.installSegment5 (opcodeFadeIn, new OpFadeIn);
 | 
			
		||||
            interpreter.installSegment5 (opcodeFadeOut, new OpFadeOut);
 | 
			
		||||
            interpreter.installSegment5 (opcodeFadeTo, new OpFadeTo);
 | 
			
		||||
            interpreter.installSegment5 (opcodeToggleWater, new OpToggleWater);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -441,12 +441,34 @@ void OpenAL_Output::init(const std::string &devname)
 | 
			
		|||
    try
 | 
			
		||||
    {
 | 
			
		||||
        ALCuint maxtotal = std::min<ALCuint>(maxmono+maxstereo, 256);
 | 
			
		||||
        for(size_t i = 0;i < maxtotal;i++)
 | 
			
		||||
        if (maxtotal == 0) // workaround for broken implementations
 | 
			
		||||
        {
 | 
			
		||||
            ALuint src = 0;
 | 
			
		||||
            alGenSources(1, &src);
 | 
			
		||||
            throwALerror();
 | 
			
		||||
            mFreeSources.push_back(src);
 | 
			
		||||
            maxtotal = 256;
 | 
			
		||||
            bool stop = false;
 | 
			
		||||
            for(size_t i = 0;i < maxtotal && !stop;i++) // generate source until error returned
 | 
			
		||||
            {
 | 
			
		||||
                ALuint src = 0;
 | 
			
		||||
                alGenSources(1, &src);
 | 
			
		||||
                ALenum err = alGetError();
 | 
			
		||||
                if(err != AL_NO_ERROR)
 | 
			
		||||
                {
 | 
			
		||||
                    stop = true;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    mFreeSources.push_back(src);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else // normal case
 | 
			
		||||
        {
 | 
			
		||||
            for(size_t i = 0;i < maxtotal;i++)
 | 
			
		||||
            {
 | 
			
		||||
                ALuint src = 0;
 | 
			
		||||
                alGenSources(1, &src);
 | 
			
		||||
                throwALerror();
 | 
			
		||||
                mFreeSources.push_back(src);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    catch(std::exception &e)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,9 +54,11 @@ void insertCellRefList(MWRender::RenderingManager& rendering, MWWorld::Environme
 | 
			
		|||
 | 
			
		||||
namespace MWWorld
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    void Scene::update (float duration){
 | 
			
		||||
        mRendering.update (duration);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Scene::unloadCell (CellStoreCollection::iterator iter)
 | 
			
		||||
    {
 | 
			
		||||
        std::cout << "Unloading cell\n";
 | 
			
		||||
| 
						 | 
				
			
			@ -79,6 +81,7 @@ namespace MWWorld
 | 
			
		|||
                mPhysics->removeObject (node->getName());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		mRendering.removeCell(*iter);
 | 
			
		||||
		//mPhysics->removeObject("Unnamed_43");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -88,6 +91,7 @@ namespace MWWorld
 | 
			
		|||
		mActiveCells.erase(*iter);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Scene::loadCell (Ptr::CellStore *cell)
 | 
			
		||||
| 
						 | 
				
			
			@ -101,7 +105,7 @@ namespace MWWorld
 | 
			
		|||
            mActiveCells.insert(cell);
 | 
			
		||||
       if(result.second){
 | 
			
		||||
              insertCell(*cell, mEnvironment);
 | 
			
		||||
               mRendering.cellAdded (cell);
 | 
			
		||||
              mRendering.cellAdded(cell);
 | 
			
		||||
               mRendering.configureAmbient(*cell);
 | 
			
		||||
               mRendering.requestMap(cell);
 | 
			
		||||
               mRendering.configureAmbient(*cell);
 | 
			
		||||
| 
						 | 
				
			
			@ -192,6 +196,7 @@ namespace MWWorld
 | 
			
		|||
 | 
			
		||||
        mCurrentCell = *iter;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // adjust player
 | 
			
		||||
        playerCellChange (mWorld->getExterior(X, Y), position, adjustPlayerPos);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -199,6 +204,7 @@ namespace MWWorld
 | 
			
		|||
        mWorld->adjustSky();
 | 
			
		||||
 | 
			
		||||
        mCellChanged = true;
 | 
			
		||||
        mRendering.waterAdded(mCurrentCell);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //We need the ogre renderer and a scene node.
 | 
			
		||||
| 
						 | 
				
			
			@ -239,6 +245,7 @@ namespace MWWorld
 | 
			
		|||
 | 
			
		||||
        loadCell (cell);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // adjust player
 | 
			
		||||
        mCurrentCell = cell;
 | 
			
		||||
        playerCellChange (cell, position);
 | 
			
		||||
| 
						 | 
				
			
			@ -250,6 +257,8 @@ namespace MWWorld
 | 
			
		|||
        mWorld->adjustSky();
 | 
			
		||||
 | 
			
		||||
        mCellChanged = true;
 | 
			
		||||
 | 
			
		||||
        mRendering.waterAdded(cell);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Scene::changeToExteriorCell (const ESM::Position& position)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -531,9 +531,10 @@ namespace MWWorld
 | 
			
		|||
        ptr.getRefData().getPosition().pos[0] = x;
 | 
			
		||||
        ptr.getRefData().getPosition().pos[1] = y;
 | 
			
		||||
        ptr.getRefData().getPosition().pos[2] = z;
 | 
			
		||||
 | 
			
		||||
        if (ptr==mPlayer->getPlayer())
 | 
			
		||||
        {
 | 
			
		||||
            //std::cout << "X:" <<   ptr.getRefData().getPosition().pos[0] << " Z: "  << ptr.getRefData().getPosition().pos[1] << "\n";
 | 
			
		||||
            
 | 
			
		||||
            Ptr::CellStore *currentCell = mWorldScene->getCurrentCell();
 | 
			
		||||
            if (currentCell)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -766,4 +767,15 @@ namespace MWWorld
 | 
			
		|||
        Vector2 d = Vector2(dir.x, dir.z);
 | 
			
		||||
        return d;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void World::setWaterHeight(const float height)
 | 
			
		||||
    {
 | 
			
		||||
        mRendering->setWaterHeight(height);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void World::toggleWater()
 | 
			
		||||
    {
 | 
			
		||||
        mRendering->toggleWater();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -113,6 +113,9 @@ namespace MWWorld
 | 
			
		|||
 | 
			
		||||
            Ptr::CellStore *getInterior (const std::string& name);
 | 
			
		||||
 | 
			
		||||
            void setWaterHeight(const float height);
 | 
			
		||||
            void toggleWater();
 | 
			
		||||
            
 | 
			
		||||
            void adjustSky();
 | 
			
		||||
 | 
			
		||||
            MWWorld::Player& getPlayer();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,8 +21,13 @@ void Cell::load(ESMReader &esm)
 | 
			
		|||
    if (data.flags & Interior)
 | 
			
		||||
    {
 | 
			
		||||
        // Interior cells
 | 
			
		||||
 | 
			
		||||
        if (esm.isNextSub("INTV") || esm.isNextSub("WHGT"))
 | 
			
		||||
        if (esm.isNextSub("INTV"))
 | 
			
		||||
        {
 | 
			
		||||
            int waterl;
 | 
			
		||||
            esm.getHT(waterl);
 | 
			
		||||
            water = (float) waterl;
 | 
			
		||||
        }
 | 
			
		||||
        else if (esm.isNextSub("WHGT"))
 | 
			
		||||
            esm.getHT(water);
 | 
			
		||||
 | 
			
		||||
        // Quasi-exterior cells have a region (which determines the
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -114,11 +114,26 @@ struct Cell
 | 
			
		|||
  ESM_Context context; // File position
 | 
			
		||||
  DATAstruct data;
 | 
			
		||||
  AMBIstruct ambi;
 | 
			
		||||
  int water; // Water level
 | 
			
		||||
  float water; // Water level
 | 
			
		||||
  int mapColor;
 | 
			
		||||
 | 
			
		||||
  void load(ESMReader &esm);
 | 
			
		||||
 | 
			
		||||
  bool isExterior() const
 | 
			
		||||
  {
 | 
			
		||||
      return !(data.flags & Interior);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int getGridX() const
 | 
			
		||||
  {
 | 
			
		||||
      return data.gridX;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int getGridY() const
 | 
			
		||||
  {
 | 
			
		||||
      return data.gridY;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Restore the given reader to the stored position. Will try to open
 | 
			
		||||
  // the file matching the stored file name. If you want to read from
 | 
			
		||||
  // somewhere other than the file system, you need to pre-open the
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,8 @@ namespace ESM
 | 
			
		|||
{
 | 
			
		||||
void Land::load(ESMReader &esm)
 | 
			
		||||
{
 | 
			
		||||
    mEsm = &esm;
 | 
			
		||||
 | 
			
		||||
    // Get the grid location
 | 
			
		||||
    esm.getSubNameIs("INTV");
 | 
			
		||||
    esm.getSubHeaderIs(8);
 | 
			
		||||
| 
						 | 
				
			
			@ -19,14 +21,117 @@ void Land::load(ESMReader &esm)
 | 
			
		|||
    int cnt = 0;
 | 
			
		||||
 | 
			
		||||
    // Skip these here. Load the actual data when the cell is loaded.
 | 
			
		||||
    if(esm.isNextSub("VNML")) {esm.skipHSubSize(12675);cnt++;}
 | 
			
		||||
    if(esm.isNextSub("VHGT")) {esm.skipHSubSize(4232);cnt++;}
 | 
			
		||||
    if(esm.isNextSub("WNAM")) esm.skipHSubSize(81);
 | 
			
		||||
    if(esm.isNextSub("VCLR")) esm.skipHSubSize(12675);
 | 
			
		||||
    if(esm.isNextSub("VTEX")) {esm.skipHSubSize(512);cnt++;}
 | 
			
		||||
    if (esm.isNextSub("VNML"))
 | 
			
		||||
    {
 | 
			
		||||
        esm.skipHSubSize(12675);
 | 
			
		||||
        cnt++;
 | 
			
		||||
    }
 | 
			
		||||
    if (esm.isNextSub("VHGT"))
 | 
			
		||||
    {
 | 
			
		||||
        esm.skipHSubSize(4232);
 | 
			
		||||
        cnt++;
 | 
			
		||||
    }
 | 
			
		||||
    if (esm.isNextSub("WNAM"))
 | 
			
		||||
    {
 | 
			
		||||
        esm.skipHSubSize(81);
 | 
			
		||||
    }
 | 
			
		||||
    if (esm.isNextSub("VCLR"))
 | 
			
		||||
    {
 | 
			
		||||
        esm.skipHSubSize(12675);
 | 
			
		||||
    }
 | 
			
		||||
    if (esm.isNextSub("VTEX"))
 | 
			
		||||
    {
 | 
			
		||||
        esm.skipHSubSize(512);
 | 
			
		||||
        cnt++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // We need all three of VNML, VHGT and VTEX in order to use the
 | 
			
		||||
    // landscape.
 | 
			
		||||
    hasData = (cnt == 3);
 | 
			
		||||
 | 
			
		||||
    dataLoaded = false;
 | 
			
		||||
    landData = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Land::loadData()
 | 
			
		||||
{
 | 
			
		||||
    if (dataLoaded)
 | 
			
		||||
    {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    landData = new LandData;
 | 
			
		||||
 | 
			
		||||
    if (hasData)
 | 
			
		||||
    {
 | 
			
		||||
        mEsm->restoreContext(context);
 | 
			
		||||
 | 
			
		||||
        //esm.getHNExact(landData->normals, sizeof(VNML), "VNML");
 | 
			
		||||
        if (mEsm->isNextSub("VNML"))
 | 
			
		||||
        {
 | 
			
		||||
            mEsm->skipHSubSize(12675);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        VHGT rawHeights;
 | 
			
		||||
 | 
			
		||||
        mEsm->getHNExact(&rawHeights, sizeof(VHGT), "VHGT");
 | 
			
		||||
        int currentHeightOffset = rawHeights.heightOffset;
 | 
			
		||||
        for (int y = 0; y < LAND_SIZE; y++)
 | 
			
		||||
        {
 | 
			
		||||
            currentHeightOffset += rawHeights.heightData[y * LAND_SIZE];
 | 
			
		||||
            landData->heights[y * LAND_SIZE] = currentHeightOffset * HEIGHT_SCALE;
 | 
			
		||||
 | 
			
		||||
            int tempOffset = currentHeightOffset;
 | 
			
		||||
            for (int x = 1; x < LAND_SIZE; x++)
 | 
			
		||||
            {
 | 
			
		||||
                tempOffset += rawHeights.heightData[y * LAND_SIZE + x];
 | 
			
		||||
                landData->heights[x + y * LAND_SIZE] = tempOffset * HEIGHT_SCALE;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (mEsm->isNextSub("WNAM"))
 | 
			
		||||
        {
 | 
			
		||||
            mEsm->skipHSubSize(81);
 | 
			
		||||
        }
 | 
			
		||||
        if (mEsm->isNextSub("VCLR"))
 | 
			
		||||
        {
 | 
			
		||||
            landData->usingColours = true;
 | 
			
		||||
            mEsm->getHExact(&landData->colours, 3*LAND_NUM_VERTS);
 | 
			
		||||
        }else{
 | 
			
		||||
            landData->usingColours = false;
 | 
			
		||||
        }
 | 
			
		||||
        //TODO fix magic numbers
 | 
			
		||||
        uint16_t vtex[512];
 | 
			
		||||
        mEsm->getHNExact(&vtex, 512, "VTEX");
 | 
			
		||||
 | 
			
		||||
        int readPos = 0; //bit ugly, but it works
 | 
			
		||||
        for ( int y1 = 0; y1 < 4; y1++ )
 | 
			
		||||
            for ( int x1 = 0; x1 < 4; x1++ )
 | 
			
		||||
                for ( int y2 = 0; y2 < 4; y2++)
 | 
			
		||||
                    for ( int x2 = 0; x2 < 4; x2++ )
 | 
			
		||||
                        landData->textures[(y1*4+y2)*16+(x1*4+x2)] = vtex[readPos++];
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        landData->usingColours = false;
 | 
			
		||||
        memset(&landData->textures, 0, 512 * sizeof(uint16_t));
 | 
			
		||||
        for (int i = 0; i < LAND_NUM_VERTS; i++)
 | 
			
		||||
        {
 | 
			
		||||
            landData->heights[i] = -256.0f * HEIGHT_SCALE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dataLoaded = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Land::unloadData()
 | 
			
		||||
{
 | 
			
		||||
    if (dataLoaded)
 | 
			
		||||
    {
 | 
			
		||||
        delete landData;
 | 
			
		||||
        landData = NULL;
 | 
			
		||||
        dataLoaded = false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,11 +17,66 @@ struct Land
 | 
			
		|||
 | 
			
		||||
    // File context. This allows the ESM reader to be 'reset' to this
 | 
			
		||||
    // location later when we are ready to load the full data set.
 | 
			
		||||
    ESMReader* mEsm;
 | 
			
		||||
    ESM_Context context;
 | 
			
		||||
 | 
			
		||||
    bool hasData;
 | 
			
		||||
 | 
			
		||||
    bool dataLoaded;
 | 
			
		||||
 | 
			
		||||
    // number of vertices per side
 | 
			
		||||
    static const int LAND_SIZE = 65;
 | 
			
		||||
 | 
			
		||||
    // cell terrain size in world coords
 | 
			
		||||
    static const int REAL_SIZE = 8192;
 | 
			
		||||
 | 
			
		||||
    // total number of vertices
 | 
			
		||||
    static const int LAND_NUM_VERTS = LAND_SIZE * LAND_SIZE;
 | 
			
		||||
 | 
			
		||||
    static const int HEIGHT_SCALE = 8;
 | 
			
		||||
 | 
			
		||||
    //number of textures per side of land
 | 
			
		||||
    static const int LAND_TEXTURE_SIZE = 16;
 | 
			
		||||
 | 
			
		||||
    //total number of textures per land
 | 
			
		||||
    static const int LAND_NUM_TEXTURES = LAND_TEXTURE_SIZE * LAND_TEXTURE_SIZE;
 | 
			
		||||
 | 
			
		||||
#pragma pack(push,1)
 | 
			
		||||
    struct VHGT
 | 
			
		||||
    {
 | 
			
		||||
        float heightOffset;
 | 
			
		||||
        int8_t heightData[LAND_NUM_VERTS];
 | 
			
		||||
        short unknown1;
 | 
			
		||||
        char unknown2;
 | 
			
		||||
    };
 | 
			
		||||
#pragma pack(pop)
 | 
			
		||||
 | 
			
		||||
    typedef uint8_t VNML[LAND_NUM_VERTS * 3];
 | 
			
		||||
 | 
			
		||||
    struct LandData
 | 
			
		||||
    {
 | 
			
		||||
        float heightOffset;
 | 
			
		||||
        float heights[LAND_NUM_VERTS];
 | 
			
		||||
        //float normals[LAND_NUM_VERTS * 3];
 | 
			
		||||
        uint16_t textures[LAND_NUM_TEXTURES];
 | 
			
		||||
 | 
			
		||||
        bool usingColours;
 | 
			
		||||
        char colours[3 * LAND_NUM_VERTS];
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    LandData *landData;
 | 
			
		||||
 | 
			
		||||
    void load(ESMReader &esm);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Actually loads data
 | 
			
		||||
     */
 | 
			
		||||
    void loadData();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Frees memory allocated for land data
 | 
			
		||||
     */
 | 
			
		||||
    void unloadData();
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -95,12 +95,17 @@ namespace ESMS
 | 
			
		|||
        State_Unloaded, State_Preloaded, State_Loaded
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    CellStore (const ESM::Cell *cell_) : cell (cell_), mState (State_Unloaded) {}
 | 
			
		||||
    CellStore (const ESM::Cell *cell_) : cell (cell_), mState (State_Unloaded)
 | 
			
		||||
    {
 | 
			
		||||
        mWaterLevel = cell->water;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const ESM::Cell *cell;
 | 
			
		||||
    State mState;
 | 
			
		||||
    std::vector<std::string> mIds;
 | 
			
		||||
 | 
			
		||||
    float mWaterLevel;
 | 
			
		||||
 | 
			
		||||
    // Lists for each individual object type
 | 
			
		||||
    CellRefList<Activator, D>         activators;
 | 
			
		||||
    CellRefList<Potion, D>            potions;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -201,15 +201,21 @@ namespace ESMS
 | 
			
		|||
 | 
			
		||||
    // TODO: For multiple ESM/ESP files we need one list per file.
 | 
			
		||||
    std::vector<LandTexture> ltex;
 | 
			
		||||
    int count;
 | 
			
		||||
 | 
			
		||||
    LTexList() : count(0)
 | 
			
		||||
    LTexList()
 | 
			
		||||
    {
 | 
			
		||||
      // More than enough to hold Morrowind.esm.
 | 
			
		||||
      ltex.reserve(128);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int getSize() { return count; }
 | 
			
		||||
    const LandTexture* search(size_t index) const
 | 
			
		||||
    {
 | 
			
		||||
        assert(index < ltex.size());
 | 
			
		||||
        return <ex.at(index);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int getSize() { return ltex.size(); }
 | 
			
		||||
    int getSize() const { return ltex.size(); }
 | 
			
		||||
 | 
			
		||||
    virtual void listIdentifier (std::vector<std::string>& identifier) const {}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -233,12 +239,18 @@ namespace ESMS
 | 
			
		|||
   */
 | 
			
		||||
  struct LandList : RecList
 | 
			
		||||
  {
 | 
			
		||||
    virtual ~LandList() {}
 | 
			
		||||
    virtual ~LandList()
 | 
			
		||||
    {
 | 
			
		||||
      for ( LandMap::iterator itr = lands.begin(); itr != lands.end(); ++itr )
 | 
			
		||||
      {
 | 
			
		||||
          delete itr->second;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Map containing all landscapes
 | 
			
		||||
    typedef std::map<int, Land*> LandsCol;
 | 
			
		||||
    typedef std::map<int, LandsCol> Lands;
 | 
			
		||||
    Lands lands;
 | 
			
		||||
    typedef std::pair<int, int> LandCoord;
 | 
			
		||||
    typedef std::map<LandCoord, Land*> LandMap;
 | 
			
		||||
    LandMap lands;
 | 
			
		||||
 | 
			
		||||
    int count;
 | 
			
		||||
    LandList() : count(0) {}
 | 
			
		||||
| 
						 | 
				
			
			@ -247,17 +259,15 @@ namespace ESMS
 | 
			
		|||
    virtual void listIdentifier (std::vector<std::string>& identifier) const {}
 | 
			
		||||
 | 
			
		||||
    // Find land for the given coordinates. Return null if no data.
 | 
			
		||||
    const Land *search(int x, int y) const
 | 
			
		||||
    Land *search(int x, int y) const
 | 
			
		||||
    {
 | 
			
		||||
      Lands::const_iterator it = lands.find(x);
 | 
			
		||||
      if(it==lands.end())
 | 
			
		||||
      LandMap::const_iterator itr = lands.find(std::make_pair<int, int>(x, y));
 | 
			
		||||
      if ( itr == lands.end() )
 | 
			
		||||
      {
 | 
			
		||||
        return NULL;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      LandsCol::const_iterator it2 = it->second.find(y);
 | 
			
		||||
      if(it2 == it->second.end())
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
      return it2->second;
 | 
			
		||||
      return itr->second;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void load(ESMReader &esm, const std::string &id)
 | 
			
		||||
| 
						 | 
				
			
			@ -266,11 +276,11 @@ namespace ESMS
 | 
			
		|||
 | 
			
		||||
      // Create the structure and load it. This actually skips the
 | 
			
		||||
      // landscape data and remembers the file position for later.
 | 
			
		||||
      Land *land = new Land;
 | 
			
		||||
      Land *land = new Land();
 | 
			
		||||
      land->load(esm);
 | 
			
		||||
 | 
			
		||||
      // Store the structure
 | 
			
		||||
      lands[land->X][land->Y] = land;
 | 
			
		||||
      lands[std::make_pair<int, int>(land->X, land->Y)] = land;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -116,7 +116,7 @@ namespace ESMS
 | 
			
		|||
      recLists[REC_GLOB] = &globals;
 | 
			
		||||
      recLists[REC_GMST] = &gameSettings;
 | 
			
		||||
      recLists[REC_INGR] = &ingreds;
 | 
			
		||||
      //recLists[REC_LAND] = &lands;
 | 
			
		||||
      recLists[REC_LAND] = &lands;
 | 
			
		||||
      recLists[REC_LEVC] = &creatureLists;
 | 
			
		||||
      recLists[REC_LEVI] = &itemLists;
 | 
			
		||||
      recLists[REC_LIGH] = &lights;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								files/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								files/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
project(resources)
 | 
			
		||||
 | 
			
		||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/caustic_0.png "${OpenMW_BINARY_DIR}/resources/water/caustic_0.png" COPYONLY) 
 | 
			
		||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/Example_Fresnel.cg "${OpenMW_BINARY_DIR}/resources/water/Example_Fresnel.cg" COPYONLY) 
 | 
			
		||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/Example_FresnelPS.asm "${OpenMW_BINARY_DIR}/resources/water/Example_FresnelPS.asm" COPYONLY) 
 | 
			
		||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/GlassFP.cg "${OpenMW_BINARY_DIR}/resources/water/GlassFP.cg" COPYONLY) 
 | 
			
		||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/GlassVP.cg "${OpenMW_BINARY_DIR}/resources/water/GlassVP.cg" COPYONLY) 
 | 
			
		||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/perlinvolume.dds "${OpenMW_BINARY_DIR}/resources/water/perlinvolume.dds" COPYONLY) 
 | 
			
		||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/Water02.jpg "${OpenMW_BINARY_DIR}/resources/water/Water02.jpg" COPYONLY) 
 | 
			
		||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/water.compositor "${OpenMW_BINARY_DIR}/resources/water/water.compositor" COPYONLY)
 | 
			
		||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/waves2.dds "${OpenMW_BINARY_DIR}/resources/water/waves2.dds" COPYONLY)
 | 
			
		||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/Examples-Water.material "${OpenMW_BINARY_DIR}/resources/water/Examples-Water.material" COPYONLY)
 | 
			
		||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/WaterNormal1.tga "${OpenMW_BINARY_DIR}/resources/water/WaterNormal1.tga" COPYONLY)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,34 +1,29 @@
 | 
			
		|||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
 | 
			
		||||
<MyGUI type="Layout">
 | 
			
		||||
    <Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 588 433" name="_Main">
 | 
			
		||||
        <!-- HEADER -->
 | 
			
		||||
        <Widget type="TextBox" skin="HeaderText" position="0 0 588 18" name="NpcName" align="ALIGN_LEFT ALIGN_TOP">
 | 
			
		||||
            <Property key="Caption" value="Name"/>
 | 
			
		||||
            <Property key="TextAlign" value="ALIGN_CENTER"/>
 | 
			
		||||
        </Widget>
 | 
			
		||||
    <Widget type="Window" skin="MW_Window" layer="Windows" position="0 0 588 433" name="_Main">
 | 
			
		||||
 | 
			
		||||
        <!-- The Dialogue history -->
 | 
			
		||||
        <Widget type="DialogueHistory" skin="MW_TextBoxEdit" position="8 39 400 375" name="History"  align="ALIGN_LEFT ALIGN_TOP STRETCH">
 | 
			
		||||
        <Widget type="DialogueHistory" skin="MW_TextBoxEdit" position="8 8 415 381" name="History"  align="ALIGN_LEFT ALIGN_TOP ALIGN_STRETCH">
 | 
			
		||||
            <Property key="Static" value="true"/>
 | 
			
		||||
            <Property key="WordWrap" value="true"/>
 | 
			
		||||
            <Property key="MultiLine" value="1" />
 | 
			
		||||
            <Property key="VisibleVScroll" value="1" />
 | 
			
		||||
            <!-- invisible box for receiving mouse events -->
 | 
			
		||||
            <Widget type="Widget" skin="" position="0 0 400 375" name="EventBox" align="ALIGN_LEFT ALIGN_TOP STRETCH"/>
 | 
			
		||||
            <Widget type="Widget" skin="" position="0 0 400 375" name="EventBox" align="ALIGN_LEFT ALIGN_TOP ALIGN_STRETCH"/>
 | 
			
		||||
        </Widget>
 | 
			
		||||
 | 
			
		||||
		<!-- The disposition bar-->
 | 
			
		||||
        <Widget type="ProgressBar" skin="MW_EnergyBar_Blue" position="432 39 132 18"
 | 
			
		||||
        <Widget type="ProgressBar" skin="MW_EnergyBar_Blue" position="432 8 132 18"
 | 
			
		||||
            align="Right Top" name="Disposition">
 | 
			
		||||
			<Widget type="EditBox" skin="MW_DispositionEdit" position_real = "0.25 0 0.5 1" name = "DispositionText"/>
 | 
			
		||||
		</Widget>
 | 
			
		||||
        <!-- The list of topics -->
 | 
			
		||||
        <Widget type="ListBox" skin="MW_List" position="432 62 132 318" name="TopicsList">
 | 
			
		||||
        <Widget type="ListBox" skin="MW_List" position="432 31 132 328" name="TopicsList" align="Right VStretch">
 | 
			
		||||
        </Widget>
 | 
			
		||||
 | 
			
		||||
        <!-- The Goodbye button -->
 | 
			
		||||
        <Widget type="Button" skin="MW_Button" position="432 387 132 23" name="ByeButton">
 | 
			
		||||
        <Widget type="Button" skin="MW_Button" position="432 366 132 23" name="ByeButton" align="Right Bottom">
 | 
			
		||||
            <Property key="Caption" value="Goodbye"/>
 | 
			
		||||
        </Widget>
 | 
			
		||||
    </Widget>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -294,7 +294,7 @@
 | 
			
		|||
        <Property key="TextAlign" value = "ALIGN_CENTER" />
 | 
			
		||||
        <Property key="TextColour" value = "0.8 0.8 0.8" />
 | 
			
		||||
 | 
			
		||||
        <Child type="Widget" skin="DialogBG" offset = "4 4 248 46" align = "ALIGN_STRETCH" name = "Client"/>
 | 
			
		||||
        <Child type="Widget" skin="BlackBG" offset = "4 4 248 46" align = "ALIGN_STRETCH" name = "Client"/>
 | 
			
		||||
 | 
			
		||||
        <!-- Outer borders -->
 | 
			
		||||
        <Child type="Widget" skin="DB_T" offset="4 0 248 4" align="ALIGN_TOP ALIGN_HSTRETCH" name="Border">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										116
									
								
								files/water/Example_Fresnel.cg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								files/water/Example_Fresnel.cg
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,116 @@
 | 
			
		|||
// Vertex program for fresnel reflections / refractions
 | 
			
		||||
void main_vp(
 | 
			
		||||
		float4 pos			: POSITION,
 | 
			
		||||
		float4 normal		: NORMAL,
 | 
			
		||||
		float2 tex			: TEXCOORD0,
 | 
			
		||||
		
 | 
			
		||||
		out float4 oPos		: POSITION,
 | 
			
		||||
		out float3 noiseCoord : TEXCOORD0,
 | 
			
		||||
		out float4 projectionCoord : TEXCOORD1,
 | 
			
		||||
		out float3 oEyeDir : TEXCOORD2, 
 | 
			
		||||
		out float3 oNormal : TEXCOORD3, 
 | 
			
		||||
 | 
			
		||||
		uniform float4x4 worldViewProjMatrix,
 | 
			
		||||
		uniform float3 eyePosition, // object space
 | 
			
		||||
		uniform float timeVal,
 | 
			
		||||
		uniform float scale,  // the amount to scale the noise texture by
 | 
			
		||||
		uniform float scroll, // the amount by which to scroll the noise
 | 
			
		||||
		uniform float noise  // the noise perturb as a factor of the  time
 | 
			
		||||
		)
 | 
			
		||||
{
 | 
			
		||||
	oPos = mul(worldViewProjMatrix, pos);
 | 
			
		||||
	// Projective texture coordinates, adjust for mapping
 | 
			
		||||
	float4x4 scalemat = float4x4(0.5,   0,   0, 0.5, 
 | 
			
		||||
	                               0,-0.5,   0, 0.5,
 | 
			
		||||
								   0,   0, 0.5, 0.5,
 | 
			
		||||
								   0,   0,   0,   1);
 | 
			
		||||
	projectionCoord = mul(scalemat, oPos);
 | 
			
		||||
	// Noise map coords
 | 
			
		||||
	noiseCoord.xy = (tex + (timeVal * scroll)) * scale;
 | 
			
		||||
	noiseCoord.z = noise * timeVal;
 | 
			
		||||
 | 
			
		||||
	oEyeDir = normalize(pos.xyz - eyePosition); 
 | 
			
		||||
	oNormal = normal.rgb; 
 | 
			
		||||
	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Fragment program for distorting a texture using a 3D noise texture
 | 
			
		||||
void main_fp(
 | 
			
		||||
		float3 noiseCoord			: TEXCOORD0,
 | 
			
		||||
		float4 projectionCoord		: TEXCOORD1,
 | 
			
		||||
		float3 eyeDir				: TEXCOORD2,
 | 
			
		||||
		float3 normal				: TEXCOORD3,
 | 
			
		||||
		
 | 
			
		||||
		out float4 col		: COLOR,
 | 
			
		||||
		
 | 
			
		||||
		uniform float4 tintColour,
 | 
			
		||||
		uniform float noiseScale, 
 | 
			
		||||
		uniform float fresnelBias,
 | 
			
		||||
		uniform float fresnelScale,
 | 
			
		||||
		uniform float fresnelPower,
 | 
			
		||||
		uniform sampler2D waterTex : register(s0),
 | 
			
		||||
		uniform sampler2D noiseMap : register(s1),
 | 
			
		||||
		uniform sampler2D reflectMap : register(s2),
 | 
			
		||||
		uniform sampler2D refractMap : register(s3)
 | 
			
		||||
		)
 | 
			
		||||
{
 | 
			
		||||
	// Do the tex projection manually so we can distort _after_
 | 
			
		||||
	float2 final = projectionCoord.xy / projectionCoord.w;
 | 
			
		||||
 | 
			
		||||
	// Noise
 | 
			
		||||
	float3 noiseNormal = (tex2D(noiseMap, (noiseCoord.xy / 5)).rgb - 0.5).rbg * noiseScale;
 | 
			
		||||
	final += noiseNormal.xz;
 | 
			
		||||
 | 
			
		||||
	// Fresnel
 | 
			
		||||
	//normal = normalize(normal + noiseNormal.xz);
 | 
			
		||||
	float fresnel = fresnelBias + fresnelScale * pow(1 + dot(eyeDir, normal), fresnelPower);
 | 
			
		||||
 | 
			
		||||
	// Reflection / refraction
 | 
			
		||||
	float4 reflectionColour = tex2D(reflectMap, final);
 | 
			
		||||
	float4 refractionColour = tex2D(refractMap, final) + tintColour;
 | 
			
		||||
 | 
			
		||||
	// Final colour
 | 
			
		||||
	col = lerp(refractionColour, reflectionColour, fresnel) * tex2D(waterTex, noiseNormal) / 3 ;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Old version to match ATI PS 1.3 implementation
 | 
			
		||||
void main_vp_old(
 | 
			
		||||
		float4 pos			: POSITION,
 | 
			
		||||
		float4 normal		: NORMAL,
 | 
			
		||||
		float2 tex			: TEXCOORD0,
 | 
			
		||||
		
 | 
			
		||||
		out float4 oPos		: POSITION,
 | 
			
		||||
		out float fresnel   : COLOR,
 | 
			
		||||
		out float3 noiseCoord : TEXCOORD0,
 | 
			
		||||
		out float4 projectionCoord : TEXCOORD1,
 | 
			
		||||
 | 
			
		||||
		uniform float4x4 worldViewProjMatrix,
 | 
			
		||||
		uniform float3 eyePosition, // object space
 | 
			
		||||
		uniform float fresnelBias,
 | 
			
		||||
		uniform float fresnelScale,
 | 
			
		||||
		uniform float fresnelPower,
 | 
			
		||||
		uniform float timeVal,
 | 
			
		||||
		uniform float scale,  // the amount to scale the noise texture by
 | 
			
		||||
		uniform float scroll, // the amount by which to scroll the noise
 | 
			
		||||
		uniform float noise  // the noise perturb as a factor of the  time
 | 
			
		||||
		)
 | 
			
		||||
{
 | 
			
		||||
	oPos = mul(worldViewProjMatrix, pos);
 | 
			
		||||
	// Projective texture coordinates, adjust for mapping
 | 
			
		||||
	float4x4 scalemat = float4x4(0.5,   0,   0, 0.5, 
 | 
			
		||||
	                               0,-0.5,   0, 0.5,
 | 
			
		||||
								   0,   0, 0.5, 0.5,
 | 
			
		||||
								   0,   0,   0,   1);
 | 
			
		||||
	projectionCoord = mul(scalemat, oPos);
 | 
			
		||||
	// Noise map coords
 | 
			
		||||
	noiseCoord.xy = (tex + (timeVal * scroll)) * scale;
 | 
			
		||||
	noiseCoord.z = noise * timeVal;
 | 
			
		||||
 | 
			
		||||
	// calc fresnel factor (reflection coefficient)
 | 
			
		||||
	float3 eyeDir = normalize(pos.xyz - eyePosition);
 | 
			
		||||
	fresnel = fresnelBias + fresnelScale * pow(1 + dot(eyeDir, normal), fresnelPower);
 | 
			
		||||
	
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										72
									
								
								files/water/Example_FresnelPS.asm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								files/water/Example_FresnelPS.asm
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
ps.1.4
 | 
			
		||||
  // conversion from Cg generated ARB_fragment_program to ps.1.4 by NFZ
 | 
			
		||||
  // command line args: -profile arbfp1 -entry main_fp
 | 
			
		||||
  // program main_fp
 | 
			
		||||
  // c0 : distortionRange
 | 
			
		||||
  // c1 : tintColour
 | 
			
		||||
  // testure 0 : noiseMap
 | 
			
		||||
  // texture 1 : reflectMap
 | 
			
		||||
  // texture 2 : refractMap
 | 
			
		||||
  // v0.x : fresnel 
 | 
			
		||||
  // t0.xyz : noiseCoord
 | 
			
		||||
  // t1.xyw : projectionCoord 
 | 
			
		||||
 | 
			
		||||
def c2, 2, 1, 0, 0
 | 
			
		||||
 | 
			
		||||
  // Cg:	distort.x = tex3D(noiseMap, noiseCoord).x;
 | 
			
		||||
  // arbfp1:	TEX R0.x, fragment.texcoord[0], texture[0], 3D;
 | 
			
		||||
  // sample noise map using noiseCoord in TEX unit 0 
 | 
			
		||||
 | 
			
		||||
texld r0, t0.xyz
 | 
			
		||||
 | 
			
		||||
  // get projected texture coordinates from TEX coord 1
 | 
			
		||||
  // will be used in phase 2
 | 
			
		||||
 | 
			
		||||
texcrd r1.xy, t1_dw.xyw
 | 
			
		||||
mov r1.z, c2.y
 | 
			
		||||
 | 
			
		||||
  // Cg:	distort.y = tex3D(noiseMap, noiseCoord + yoffset).x;
 | 
			
		||||
  // arbfp1:	ADD R1.xyz, fragment.texcoord[0], c1;
 | 
			
		||||
  // arbfp1:	TEX R1.x, R1, texture[0], 3D;
 | 
			
		||||
  // arbfp1:	MOV R0.y, R1.x;
 | 
			
		||||
 | 
			
		||||
  // Cg:	distort = (distort * 2 - 1) * distortionRange;
 | 
			
		||||
  // arbfp1:	MAD R0.xy, R0, c0.x, -c0.y;
 | 
			
		||||
  // arbfp1:	MUL R0.xy, R0, u0.x;
 | 
			
		||||
  // (distort * 2 - 1) same as 2*(distort -.5) so use _bx2
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // Cg:	final = projectionCoord.xy / projectionCoord.w;
 | 
			
		||||
  // Cg:	final += distort;
 | 
			
		||||
  // arbfp1:	RCP R0.w, fragment.texcoord[1].w;
 | 
			
		||||
  // arbfp1:	MAD R0.xy, fragment.texcoord[1], R0.w, R0;
 | 
			
		||||
  // 	final = (distort *  projectionCoord.w) + projectionCoord.xy
 | 
			
		||||
  // for ps.1.4 have to re-arrange things a bit to perturb projected texture coordinates
 | 
			
		||||
 | 
			
		||||
mad r0.xyz, r0_bx2, c0.x, r1
 | 
			
		||||
 | 
			
		||||
phase
 | 
			
		||||
 | 
			
		||||
  // do dependant texture reads
 | 
			
		||||
  // Cg:	reflectionColour = tex2D(reflectMap, final);
 | 
			
		||||
  // arbfp1:	TEX R0, R0, texture[1], 2D;
 | 
			
		||||
  // sampe reflectMap using dependant read : texunit 1 
 | 
			
		||||
 | 
			
		||||
texld r1, r0.xyz
 | 
			
		||||
 | 
			
		||||
  // Cg:	refractionColour = tex2D(refractMap, final) + tintColour;
 | 
			
		||||
  // arbfp1:	TEX R1, R0, texture[2], 2D;
 | 
			
		||||
  // sample refractMap : texunit 2 
 | 
			
		||||
 | 
			
		||||
texld r2, r0.xyz
 | 
			
		||||
 | 
			
		||||
  // adding tintColour that is in global c1
 | 
			
		||||
  // arbfp1:	ADD R1, R1, u1;
 | 
			
		||||
 | 
			
		||||
add r2, r2, c1
 | 
			
		||||
 | 
			
		||||
  // Cg:	col = lerp(refractionColour, reflectionColour, fresnel);
 | 
			
		||||
  // arbfp1:	ADD R0, R0, -R1;
 | 
			
		||||
  // arbfp1:	MAD result.color, fragment.color.primary.x, R0, R1;
 | 
			
		||||
 | 
			
		||||
lrp r0, v0.x, r1, r2
 | 
			
		||||
							
								
								
									
										149
									
								
								files/water/Examples-Water.material
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								files/water/Examples-Water.material
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,149 @@
 | 
			
		|||
 | 
			
		||||
vertex_program Water/GlassVP cg
 | 
			
		||||
{
 | 
			
		||||
	source GlassVP.cg
 | 
			
		||||
	entry_point glass_vp
 | 
			
		||||
	profiles vs_1_1 arbvp1
 | 
			
		||||
 | 
			
		||||
	default_params 
 | 
			
		||||
	{
 | 
			
		||||
		param_named_auto worldViewProj worldviewproj_matrix
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
fragment_program Water/GlassFP cg
 | 
			
		||||
{
 | 
			
		||||
	source GlassFP.cg
 | 
			
		||||
	entry_point main_ps
 | 
			
		||||
	profiles ps_2_0 arbfp1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
material Water/Compositor
 | 
			
		||||
{
 | 
			
		||||
	technique
 | 
			
		||||
	{
 | 
			
		||||
		pass
 | 
			
		||||
		{
 | 
			
		||||
			depth_check off
 | 
			
		||||
			vertex_program_ref Water/GlassVP
 | 
			
		||||
			{
 | 
			
		||||
				param_named_auto timeVal time 0.25
 | 
			
		||||
				param_named scale float 0.1
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			fragment_program_ref Water/GlassFP
 | 
			
		||||
			{
 | 
			
		||||
				param_named tintColour float4 0 0.35 0.35 1
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			texture_unit RT
 | 
			
		||||
			{
 | 
			
		||||
			        tex_coord_set 0
 | 
			
		||||
				tex_address_mode clamp
 | 
			
		||||
				filtering linear linear linear
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			texture_unit
 | 
			
		||||
			{
 | 
			
		||||
				texture WaterNormal1.tga 2d
 | 
			
		||||
                		tex_coord_set 1
 | 
			
		||||
				//tex_address_mode clamp
 | 
			
		||||
				filtering linear linear linear
 | 
			
		||||
			}
 | 
			
		||||
			texture_unit
 | 
			
		||||
			{
 | 
			
		||||
				texture caustic_0.png 2d
 | 
			
		||||
                		tex_coord_set 2
 | 
			
		||||
				//tex_address_mode clamp
 | 
			
		||||
				filtering linear linear linear
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
vertex_program Water/RefractReflectVP cg
 | 
			
		||||
{
 | 
			
		||||
	source Example_Fresnel.cg
 | 
			
		||||
	entry_point main_vp
 | 
			
		||||
	profiles vs_1_1 arbvp1
 | 
			
		||||
}
 | 
			
		||||
vertex_program Water/RefractReflectVPold cg
 | 
			
		||||
{
 | 
			
		||||
	source Example_Fresnel.cg
 | 
			
		||||
	entry_point main_vp_old
 | 
			
		||||
	profiles vs_1_1 arbvp1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fragment_program Water/RefractReflectFP cg
 | 
			
		||||
{
 | 
			
		||||
	source Example_Fresnel.cg
 | 
			
		||||
	entry_point main_fp
 | 
			
		||||
	// sorry, ps_1_1 and fp20 can't do this
 | 
			
		||||
	profiles ps_2_0 arbfp1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fragment_program Water/RefractReflectPS asm
 | 
			
		||||
{
 | 
			
		||||
	source Example_FresnelPS.asm
 | 
			
		||||
	// sorry, only for ps_1_4 :)
 | 
			
		||||
	syntax ps_1_4
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
material Examples/Water0
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	technique
 | 
			
		||||
	{
 | 
			
		||||
		pass 
 | 
			
		||||
		{
 | 
			
		||||
			//
 | 
			
		||||
       			
 | 
			
		||||
			depth_write off
 | 
			
		||||
			vertex_program_ref Water/RefractReflectVP
 | 
			
		||||
			{
 | 
			
		||||
				param_named_auto worldViewProjMatrix worldviewproj_matrix
 | 
			
		||||
				param_named_auto eyePosition camera_position_object_space
 | 
			
		||||
				param_named_auto timeVal time 0.15
 | 
			
		||||
				param_named scroll float 1  
 | 
			
		||||
				param_named scale float 1 
 | 
			
		||||
				param_named noise float 1 
 | 
			
		||||
				// scroll and noisePos will need updating per frame
 | 
			
		||||
			}
 | 
			
		||||
			fragment_program_ref Water/RefractReflectFP
 | 
			
		||||
			{
 | 
			
		||||
				param_named fresnelBias float -0.1 
 | 
			
		||||
				param_named fresnelScale float 0.8 
 | 
			
		||||
				param_named fresnelPower float 20  
 | 
			
		||||
				param_named tintColour float4 1 1 1 1
 | 
			
		||||
				param_named noiseScale float 0.05 
 | 
			
		||||
			}
 | 
			
		||||
			// Water
 | 
			
		||||
			scene_blend alpha_blend
 | 
			
		||||
			texture_unit
 | 
			
		||||
			{
 | 
			
		||||
				
 | 
			
		||||
				// Water texture
 | 
			
		||||
				texture Water02.jpg
 | 
			
		||||
				// min / mag filtering, no mip
 | 
			
		||||
				filtering linear linear none
 | 
			
		||||
				alpha_op_ex source1 src_manual src_current 0.9
 | 
			
		||||
				
 | 
			
		||||
			}
 | 
			
		||||
			// Noise
 | 
			
		||||
			texture_unit
 | 
			
		||||
			{
 | 
			
		||||
				alpha_op_ex source1 src_manual src_current 0.9
 | 
			
		||||
				// Perlin noise volume
 | 
			
		||||
				texture waves2.dds
 | 
			
		||||
				// min / mag filtering, no mip
 | 
			
		||||
				filtering linear linear none
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
		
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
			
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										15
									
								
								files/water/GlassFP.cg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								files/water/GlassFP.cg
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
sampler RT : register(s0);
 | 
			
		||||
sampler NormalMap : register(s1);
 | 
			
		||||
sampler CausticMap : register(s2);
 | 
			
		||||
 | 
			
		||||
float4 main_ps(float2 iTexCoord : TEXCOORD0,
 | 
			
		||||
       	       float3 noiseCoord : TEXCOORD1,
 | 
			
		||||
       	       uniform float4 tintColour) : COLOR
 | 
			
		||||
{
 | 
			
		||||
	float4 normal = tex2D(NormalMap, noiseCoord);
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	return tex2D(RT, iTexCoord + normal.xy * 0.05) +
 | 
			
		||||
	       (tex2D(CausticMap, noiseCoord) / 5) +
 | 
			
		||||
	       tintColour ;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								files/water/GlassVP.cg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								files/water/GlassVP.cg
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
void glass_vp
 | 
			
		||||
(
 | 
			
		||||
    in float4 inPos : POSITION,
 | 
			
		||||
 | 
			
		||||
    out float4 pos : POSITION,
 | 
			
		||||
    out float2 uv0 : TEXCOORD0,
 | 
			
		||||
    out float4 noiseCoord : TEXCOORD1,
 | 
			
		||||
 | 
			
		||||
    uniform float4x4 worldViewProj,
 | 
			
		||||
    uniform float timeVal,
 | 
			
		||||
    uniform float scale
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    // Use standardise transform, so work accord with render system specific (RS depth, requires texture flipping, etc)
 | 
			
		||||
    pos = mul(worldViewProj, inPos);
 | 
			
		||||
 | 
			
		||||
    // The input positions adjusted by texel offsets, so clean up inaccuracies
 | 
			
		||||
    inPos.xy = sign(inPos.xy);
 | 
			
		||||
 | 
			
		||||
    // Convert to image-space
 | 
			
		||||
    uv0 = (float2(inPos.x, -inPos.y) + 1.0f) * 0.5f;
 | 
			
		||||
    noiseCoord = (pos + timeVal) * scale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								files/water/Water02.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								files/water/Water02.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 182 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								files/water/WaterNormal1.tga
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								files/water/WaterNormal1.tga
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 192 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								files/water/caustic_0.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								files/water/caustic_0.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 34 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								files/water/perlinvolume.dds
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								files/water/perlinvolume.dds
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										21
									
								
								files/water/water.compositor
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								files/water/water.compositor
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
compositor Water
 | 
			
		||||
{
 | 
			
		||||
    technique
 | 
			
		||||
    {
 | 
			
		||||
        texture rt0 target_width target_height PF_R8G8B8
 | 
			
		||||
 | 
			
		||||
        target rt0 { input previous }
 | 
			
		||||
 | 
			
		||||
        target_output
 | 
			
		||||
        {
 | 
			
		||||
            // Start with clear output
 | 
			
		||||
            input none
 | 
			
		||||
 | 
			
		||||
            pass render_quad
 | 
			
		||||
            {
 | 
			
		||||
                material Water/Compositor
 | 
			
		||||
                input 0 rt0
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}			
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								files/water/waves2.dds
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								files/water/waves2.dds
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Loading…
	
		Reference in a new issue