forked from teamnwah/openmw-tes3coop
Merge remote branch 'zini/master' into sound
This commit is contained in:
commit
31e2447275
74 changed files with 3461 additions and 627 deletions
|
@ -15,7 +15,7 @@ include (OpenMWMacros)
|
|||
# Version
|
||||
|
||||
set (OPENMW_VERSION_MAJOR 0)
|
||||
set (OPENMW_VERSION_MINOR 13)
|
||||
set (OPENMW_VERSION_MINOR 14)
|
||||
set (OPENMW_VERSION_RELEASE 0)
|
||||
|
||||
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
|
||||
|
@ -27,6 +27,11 @@ configure_file ("${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_
|
|||
option(MYGUI_STATIC "Link static build of Mygui into the binaries" FALSE)
|
||||
option(OGRE_STATIC "Link static build of Ogre and Ogre Plugins into the binaries" FALSE)
|
||||
|
||||
# Apps and tools
|
||||
option(BUILD_ESMTOOL "build ESM inspector" ON)
|
||||
option(BUILD_LAUNCHER "build Launcher" ON)
|
||||
option(BUILD_MWINIIMPORTER "build MWiniImporter" ON)
|
||||
|
||||
# Sound source selection
|
||||
option(USE_FFMPEG "use ffmpeg for sound" OFF)
|
||||
option(USE_AUDIERE "use audiere for sound" OFF)
|
||||
|
@ -97,6 +102,7 @@ set(OENGINE_OGRE
|
|||
${LIBDIR}/openengine/ogre/renderer.cpp
|
||||
${LIBDIR}/openengine/ogre/mouselook.cpp
|
||||
${LIBDIR}/openengine/ogre/fader.cpp
|
||||
${LIBDIR}/openengine/ogre/imagerotate.cpp
|
||||
)
|
||||
set(OENGINE_GUI
|
||||
${LIBDIR}/openengine/gui/events.cpp
|
||||
|
@ -116,6 +122,7 @@ set(OENGINE_BULLET
|
|||
${LIBDIR}/openengine/bullet/physic.hpp
|
||||
${LIBDIR}/openengine/bullet/BulletShapeLoader.cpp
|
||||
${LIBDIR}/openengine/bullet/BulletShapeLoader.h
|
||||
|
||||
)
|
||||
|
||||
set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI} ${OENGINE_BULLET})
|
||||
|
@ -227,6 +234,9 @@ endif (APPLE)
|
|||
configure_file(${OpenMW_SOURCE_DIR}/files/settings-default.cfg
|
||||
"${OpenMW_BINARY_DIR}/settings-default.cfg")
|
||||
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/transparency-overrides.cfg
|
||||
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg")
|
||||
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local
|
||||
"${OpenMW_BINARY_DIR}/openmw.cfg")
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg
|
||||
|
@ -240,6 +250,9 @@ endif (WIN32)
|
|||
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/plugins.cfg.linux
|
||||
"${OpenMW_BINARY_DIR}/plugins.cfg")
|
||||
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
|
||||
"${OpenMW_BINARY_DIR}/openmw.desktop")
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
|
@ -303,11 +316,12 @@ if(DPKG_PROGRAM)
|
|||
endif()
|
||||
|
||||
#Install icon and desktop file
|
||||
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/openmw.desktop" DESTINATION "share/applications/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "share/applications/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_SOURCE_DIR}/apps/launcher/resources/images/openmw.png" DESTINATION "share/pixmaps/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
|
||||
#Install global configuration files
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "../etc/openmw/" RENAME "openmw.cfg" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
|
||||
|
@ -347,7 +361,7 @@ if(WIN32)
|
|||
INSTALL(FILES ${files} DESTINATION ".")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg")
|
||||
INSTALL(FILES
|
||||
"${OpenMW_SOURCE_DIR}/readme.txt"
|
||||
"${OpenMW_SOURCE_DIR}/readme.txt"
|
||||
"${OpenMW_BINARY_DIR}/settings-default.cfg"
|
||||
DESTINATION ".")
|
||||
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".")
|
||||
|
@ -408,17 +422,14 @@ add_subdirectory (components)
|
|||
# Apps and tools
|
||||
add_subdirectory( apps/openmw )
|
||||
|
||||
option(BUILD_ESMTOOL "build ESM inspector" ON)
|
||||
if (BUILD_ESMTOOL)
|
||||
add_subdirectory( apps/esmtool )
|
||||
endif()
|
||||
|
||||
option(BUILD_LAUNCHER "build Launcher inspector" ON)
|
||||
if (BUILD_LAUNCHER)
|
||||
add_subdirectory( apps/launcher )
|
||||
endif()
|
||||
|
||||
option(BUILD_MWINIIMPORTER "build MWiniImporter inspector" ON)
|
||||
if (BUILD_MWINIIMPORTER)
|
||||
add_subdirectory( apps/mwiniimporter )
|
||||
endif()
|
||||
|
|
|
@ -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 occlusionquery terrain terrainmaterial water
|
||||
renderinginterface localmap occlusionquery terrain terrainmaterial water shadows shaderhelper
|
||||
)
|
||||
|
||||
add_openmw_dir (mwinput
|
||||
|
@ -25,7 +25,7 @@ add_openmw_dir (mwinput
|
|||
add_openmw_dir (mwgui
|
||||
layouts text_input widgets race class birth review window_manager console dialogue
|
||||
dialogue_history window_base stats_window messagebox journalwindow charactercreation
|
||||
map_window window_pinnable_base
|
||||
map_window window_pinnable_base cursorreplace
|
||||
)
|
||||
|
||||
add_openmw_dir (mwdialogue
|
||||
|
@ -55,7 +55,7 @@ add_openmw_dir (mwclass
|
|||
)
|
||||
|
||||
add_openmw_dir (mwmechanics
|
||||
mechanicsmanager stat creaturestats magiceffects movement actors drawstate
|
||||
mechanicsmanager stat creaturestats magiceffects movement actors drawstate spells
|
||||
)
|
||||
|
||||
# Main executable
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <components/files/fixedpath.hpp>
|
||||
#include <components/files/configurationmanager.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <components/nifoverrides/nifoverrides.hpp>
|
||||
|
||||
#include <components/nifbullet/bullet_nif_loader.hpp>
|
||||
#include <components/nifogre/ogre_nif_loader.hpp>
|
||||
|
@ -28,6 +29,7 @@
|
|||
#include "mwinput/inputmanager.hpp"
|
||||
|
||||
#include "mwgui/window_manager.hpp"
|
||||
#include "mwgui/cursorreplace.hpp"
|
||||
|
||||
#include "mwscript/scriptmanager.hpp"
|
||||
#include "mwscript/compilercontext.hpp"
|
||||
|
@ -349,6 +351,13 @@ void OMW::Engine::go()
|
|||
|
||||
mFpsLevel = settings.getInt("fps", "HUD");
|
||||
|
||||
// load nif overrides
|
||||
NifOverrides::Overrides nifOverrides;
|
||||
if (boost::filesystem::exists(mCfgMgr.getLocalPath().string() + "/transparency-overrides.cfg"))
|
||||
nifOverrides.loadTransparencyOverrides(mCfgMgr.getLocalPath().string() + "/transparency-overrides.cfg");
|
||||
else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg"))
|
||||
nifOverrides.loadTransparencyOverrides(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg");
|
||||
|
||||
mOgre->configure(!boost::filesystem::is_regular_file(mCfgMgr.getOgreConfigPath()),
|
||||
mCfgMgr.getOgreConfigPath().string(),
|
||||
mCfgMgr.getLogPath().string(),
|
||||
|
@ -362,12 +371,16 @@ void OMW::Engine::go()
|
|||
addResourcesDirectory(mResDir / "mygui");
|
||||
addResourcesDirectory(mResDir / "water");
|
||||
addResourcesDirectory(mResDir / "gbuffer");
|
||||
addResourcesDirectory(mResDir / "shadows");
|
||||
|
||||
// Create the window
|
||||
mOgre->createWindow("OpenMW");
|
||||
|
||||
loadBSA();
|
||||
|
||||
// cursor replacer (converts the cursor from the bsa so they can be used by mygui)
|
||||
MWGui::CursorReplace replacer;
|
||||
|
||||
// Create the world
|
||||
mEnvironment.mWorld = new MWWorld::World (*mOgre, mFileCollections, mMaster,
|
||||
mResDir, mNewGame, mEnvironment, mEncoding, mFallbackMap);
|
||||
|
|
|
@ -89,7 +89,7 @@ namespace MWClass
|
|||
|
||||
static const int sMapping[size][2] =
|
||||
{
|
||||
{ ESM::Clothing::Shirt, MWWorld::InventoryStore::Slot_Cuirass },
|
||||
{ ESM::Clothing::Shirt, MWWorld::InventoryStore::Slot_Shirt },
|
||||
{ ESM::Clothing::Belt, MWWorld::InventoryStore::Slot_Belt },
|
||||
{ ESM::Clothing::Robe, MWWorld::InventoryStore::Slot_Robe },
|
||||
{ ESM::Clothing::Pants, MWWorld::InventoryStore::Slot_Pants },
|
||||
|
|
|
@ -53,28 +53,40 @@ namespace MWClass
|
|||
// NPC stats
|
||||
if (!ref->base->faction.empty())
|
||||
{
|
||||
// TODO research how initial rank is stored. The information in loadnpc.hpp are at
|
||||
// best very unclear.
|
||||
data->mNpcStats.mFactionRank[ref->base->faction] = 0;
|
||||
if(ref->base->npdt52.gold != -10)
|
||||
{
|
||||
data->mNpcStats.mFactionRank[ref->base->faction] = (int)ref->base->npdt52.rank;
|
||||
}
|
||||
else
|
||||
{
|
||||
data->mNpcStats.mFactionRank[ref->base->faction] = (int)ref->base->npdt12.rank;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<27; ++i)
|
||||
data->mNpcStats.mSkill[i].setBase (ref->base->npdt52.skills[i]);
|
||||
if(ref->base->npdt52.gold != -10)
|
||||
{
|
||||
for (int i=0; i<27; ++i)
|
||||
data->mNpcStats.mSkill[i].setBase (ref->base->npdt52.skills[i]);
|
||||
|
||||
// creature stats
|
||||
data->mCreatureStats.mAttributes[0].set (ref->base->npdt52.strength);
|
||||
data->mCreatureStats.mAttributes[1].set (ref->base->npdt52.intelligence);
|
||||
data->mCreatureStats.mAttributes[2].set (ref->base->npdt52.willpower);
|
||||
data->mCreatureStats.mAttributes[3].set (ref->base->npdt52.agility);
|
||||
data->mCreatureStats.mAttributes[4].set (ref->base->npdt52.speed);
|
||||
data->mCreatureStats.mAttributes[5].set (ref->base->npdt52.endurance);
|
||||
data->mCreatureStats.mAttributes[6].set (ref->base->npdt52.personality);
|
||||
data->mCreatureStats.mAttributes[7].set (ref->base->npdt52.luck);
|
||||
data->mCreatureStats.mDynamic[0].set (ref->base->npdt52.health);
|
||||
data->mCreatureStats.mDynamic[1].set (ref->base->npdt52.mana);
|
||||
data->mCreatureStats.mDynamic[2].set (ref->base->npdt52.fatigue);
|
||||
// creature stats
|
||||
data->mCreatureStats.mAttributes[0].set (ref->base->npdt52.strength);
|
||||
data->mCreatureStats.mAttributes[1].set (ref->base->npdt52.intelligence);
|
||||
data->mCreatureStats.mAttributes[2].set (ref->base->npdt52.willpower);
|
||||
data->mCreatureStats.mAttributes[3].set (ref->base->npdt52.agility);
|
||||
data->mCreatureStats.mAttributes[4].set (ref->base->npdt52.speed);
|
||||
data->mCreatureStats.mAttributes[5].set (ref->base->npdt52.endurance);
|
||||
data->mCreatureStats.mAttributes[6].set (ref->base->npdt52.personality);
|
||||
data->mCreatureStats.mAttributes[7].set (ref->base->npdt52.luck);
|
||||
data->mCreatureStats.mDynamic[0].set (ref->base->npdt52.health);
|
||||
data->mCreatureStats.mDynamic[1].set (ref->base->npdt52.mana);
|
||||
data->mCreatureStats.mDynamic[2].set (ref->base->npdt52.fatigue);
|
||||
|
||||
data->mCreatureStats.mLevel = ref->base->npdt52.level;
|
||||
data->mCreatureStats.mLevel = ref->base->npdt52.level;
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO: do something with npdt12 maybe:p
|
||||
}
|
||||
|
||||
// \todo add initial container content
|
||||
|
||||
|
@ -93,7 +105,10 @@ namespace MWClass
|
|||
|
||||
void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
renderingInterface.getActors().insertNPC(ptr);
|
||||
|
||||
|
||||
renderingInterface.getActors().insertNPC(ptr, getInventoryStore(ptr));
|
||||
|
||||
}
|
||||
|
||||
void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
|
||||
|
@ -281,7 +296,7 @@ namespace MWClass
|
|||
void Npc::registerSelf()
|
||||
{
|
||||
boost::shared_ptr<Class> instance (new Npc);
|
||||
|
||||
std::cout << "class npc:" << typeid (ESM::NPC).name();
|
||||
registerClass (typeid (ESM::NPC).name(), instance);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,9 @@
|
|||
#include "../mwscript/interpretercontext.hpp"
|
||||
#include <components/compiler/scriptparser.hpp>
|
||||
|
||||
#include "../mwclass/npc.hpp"
|
||||
#include "../mwmechanics/npcstats.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string toLower (const std::string& name)
|
||||
|
@ -109,16 +112,15 @@ namespace
|
|||
switch (world.getGlobalVariableType (name))
|
||||
{
|
||||
case 's':
|
||||
|
||||
return selectCompare (comp, value, world.getGlobalVariable (name).mShort);
|
||||
return selectCompare (comp, world.getGlobalVariable (name).mShort, value);
|
||||
|
||||
case 'l':
|
||||
|
||||
return selectCompare (comp, value, world.getGlobalVariable (name).mLong);
|
||||
return selectCompare (comp, world.getGlobalVariable (name).mLong, value);
|
||||
|
||||
case 'f':
|
||||
|
||||
return selectCompare (comp, value, world.getGlobalVariable (name).mFloat);
|
||||
return selectCompare (comp, world.getGlobalVariable (name).mFloat, value);
|
||||
|
||||
case ' ':
|
||||
|
||||
|
@ -178,7 +180,17 @@ namespace MWDialogue
|
|||
break;
|
||||
|
||||
case 46://Same faction
|
||||
if(!selectCompare<int,int>(comp,0,select.i)) return false;
|
||||
{
|
||||
MWMechanics::NpcStats PCstats = MWWorld::Class::get(mEnvironment.mWorld->getPlayer().getPlayer()).getNpcStats(mEnvironment.mWorld->getPlayer().getPlayer());
|
||||
MWMechanics::NpcStats NPCstats = MWWorld::Class::get(actor).getNpcStats(actor);
|
||||
int sameFaction = 0;
|
||||
if(!NPCstats.mFactionRank.empty())
|
||||
{
|
||||
std::string NPCFaction = NPCstats.mFactionRank.begin()->first;
|
||||
if(PCstats.mFactionRank.find(NPCFaction) != PCstats.mFactionRank.end()) sameFaction = 1;
|
||||
}
|
||||
if(!selectCompare<int,int>(comp,sameFaction,select.i)) return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 48://Detected
|
||||
|
@ -190,7 +202,6 @@ namespace MWDialogue
|
|||
break;
|
||||
|
||||
case 50://choice
|
||||
|
||||
if(choice)
|
||||
{
|
||||
if(!selectCompare<int,int>(comp,mChoice,select.i)) return false;
|
||||
|
@ -270,7 +281,7 @@ namespace MWDialogue
|
|||
{
|
||||
case '1': // function
|
||||
|
||||
return true; // TODO implement functions
|
||||
return true; // Done elsewhere.
|
||||
|
||||
case '2': // global
|
||||
|
||||
|
@ -444,9 +455,6 @@ namespace MWDialogue
|
|||
if (toLower (info.actor)!=MWWorld::Class::get (actor).getId (actor))
|
||||
return false;
|
||||
|
||||
//PC Faction
|
||||
if(!info.pcFaction.empty()) return false;
|
||||
|
||||
//NPC race
|
||||
if (!info.race.empty())
|
||||
{
|
||||
|
@ -474,26 +482,37 @@ namespace MWDialogue
|
|||
//NPC faction
|
||||
if (!info.npcFaction.empty())
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
|
||||
|
||||
if (!cellRef)
|
||||
return false;
|
||||
|
||||
if (toLower (info.npcFaction)!=toLower (cellRef->base->faction))
|
||||
return false;
|
||||
|
||||
//check NPC rank
|
||||
if(cellRef->base->npdt52.gold != -10)
|
||||
//MWWorld::Class npcClass = MWWorld::Class::get(actor);
|
||||
MWMechanics::NpcStats stats = MWWorld::Class::get(actor).getNpcStats(actor);
|
||||
std::map<std::string,int>::iterator it = stats.mFactionRank.find(info.npcFaction);
|
||||
if(it!=stats.mFactionRank.end())
|
||||
{
|
||||
if(cellRef->base->npdt52.rank < info.data.rank) return false;
|
||||
//check rank
|
||||
if(it->second < (int)info.data.rank) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cellRef->base->npdt12.rank < info.data.rank) return false;
|
||||
//not in the faction
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO check player faction
|
||||
if(!info.pcFaction.empty())
|
||||
{
|
||||
MWMechanics::NpcStats stats = MWWorld::Class::get(mEnvironment.mWorld->getPlayer().getPlayer()).getNpcStats(mEnvironment.mWorld->getPlayer().getPlayer());
|
||||
std::map<std::string,int>::iterator it = stats.mFactionRank.find(info.pcFaction);
|
||||
if(it!=stats.mFactionRank.end())
|
||||
{
|
||||
//check rank
|
||||
if(it->second < (int)info.data.PCrank) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//not in the faction
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//check gender
|
||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* npc = actor.get<ESM::NPC>();
|
||||
|
@ -658,6 +677,7 @@ namespace MWDialogue
|
|||
|
||||
void DialogueManager::executeScript(std::string script)
|
||||
{
|
||||
std::cout << script;
|
||||
std::vector<Interpreter::Type_Code> code;
|
||||
if(compile(script,code))
|
||||
{
|
||||
|
@ -799,4 +819,19 @@ namespace MWDialogue
|
|||
mChoiceMap[question] = choice;
|
||||
mIsInChoice = true;
|
||||
}
|
||||
|
||||
std::string DialogueManager::getFaction()
|
||||
{
|
||||
std::string factionID("");
|
||||
MWMechanics::NpcStats stats = MWWorld::Class::get(mActor).getNpcStats(mActor);
|
||||
if(stats.mFactionRank.empty())
|
||||
{
|
||||
std::cout << "No faction for this actor!";
|
||||
}
|
||||
else
|
||||
{
|
||||
factionID = stats.mFactionRank.begin()->first;
|
||||
}
|
||||
return factionID;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,9 @@ namespace MWDialogue
|
|||
|
||||
void askQuestion(std::string question,int choice);
|
||||
|
||||
///get the faction of the actor you are talking with
|
||||
std::string getFaction();
|
||||
|
||||
//calbacks for the GUI
|
||||
void keywordSelected(std::string keyword);
|
||||
void goodbyeSelected();
|
||||
|
|
16
apps/openmw/mwgui/cursorreplace.cpp
Normal file
16
apps/openmw/mwgui/cursorreplace.cpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include "cursorreplace.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <openengine/ogre/imagerotate.hpp>
|
||||
|
||||
#include <OgreResourceGroupManager.h>
|
||||
#include <OgreRoot.h>
|
||||
|
||||
using namespace MWGui;
|
||||
|
||||
CursorReplace::CursorReplace()
|
||||
{
|
||||
OEngine::Render::ImageRotate::rotate("textures\\tx_cursormove.dds", "mwpointer_vresize.png", 90);
|
||||
OEngine::Render::ImageRotate::rotate("textures\\tx_cursormove.dds", "mwpointer_dresize1.png", -45);
|
||||
OEngine::Render::ImageRotate::rotate("textures\\tx_cursormove.dds", "mwpointer_dresize2.png", 45);
|
||||
}
|
16
apps/openmw/mwgui/cursorreplace.hpp
Normal file
16
apps/openmw/mwgui/cursorreplace.hpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef GAME_CURSORREPLACE_H
|
||||
#define GAME_CURSORREPLACE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
/// \brief MyGUI does not support rotating cursors, so we have to do it manually
|
||||
class CursorReplace
|
||||
{
|
||||
public:
|
||||
CursorReplace();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -67,17 +67,8 @@ HUD::HUD(int width, int height, int fpsLevel)
|
|||
|
||||
getWidget(crosshair, "Crosshair");
|
||||
|
||||
if ( fpsLevel == 2 ){
|
||||
getWidget(fpsbox, "FPSBoxAdv");
|
||||
fpsbox->setVisible(true);
|
||||
getWidget(fpscounter, "FPSCounterAdv");
|
||||
}else if ( fpsLevel == 1 ){
|
||||
getWidget(fpsbox, "FPSBox");
|
||||
fpsbox->setVisible(true);
|
||||
getWidget(fpscounter, "FPSCounter");
|
||||
}else{
|
||||
getWidget(fpscounter, "FPSCounter");
|
||||
}
|
||||
setFpsLevel(fpsLevel);
|
||||
|
||||
getWidget(trianglecounter, "TriangleCounter");
|
||||
getWidget(batchcounter, "BatchCounter");
|
||||
|
||||
|
@ -95,6 +86,28 @@ HUD::HUD(int width, int height, int fpsLevel)
|
|||
LocalMapBase::init(minimap, this);
|
||||
}
|
||||
|
||||
void HUD::setFpsLevel(int level)
|
||||
{
|
||||
MyGUI::Widget* fps;
|
||||
getWidget(fps, "FPSBoxAdv");
|
||||
fps->setVisible(false);
|
||||
getWidget(fps, "FPSBox");
|
||||
fps->setVisible(false);
|
||||
|
||||
if (level == 2)
|
||||
{
|
||||
getWidget(fpsbox, "FPSBoxAdv");
|
||||
fpsbox->setVisible(true);
|
||||
getWidget(fpscounter, "FPSCounterAdv");
|
||||
}
|
||||
else if (level == 1)
|
||||
{
|
||||
getWidget(fpsbox, "FPSBox");
|
||||
fpsbox->setVisible(true);
|
||||
getWidget(fpscounter, "FPSCounter");
|
||||
}
|
||||
}
|
||||
|
||||
void HUD::setFPS(float fps)
|
||||
{
|
||||
fpscounter->setCaption(boost::lexical_cast<std::string>((int)fps));
|
||||
|
|
|
@ -78,6 +78,7 @@ namespace MWGui
|
|||
void setPlayerPos(const float x, const float y);
|
||||
void setBottomLeftVisibility(bool hmsVisible, bool weapVisible, bool spellVisible);
|
||||
void setBottomRightVisibility(bool effectBoxVisible, bool minimapVisible);
|
||||
void setFpsLevel(const int level);
|
||||
|
||||
MyGUI::ProgressPtr health, magicka, stamina;
|
||||
MyGUI::Widget *weapBox, *spellBox;
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include "journalwindow.hpp"
|
||||
#include "charactercreation.hpp"
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
|
@ -472,3 +474,11 @@ void WindowManager::toggleFogOfWar()
|
|||
map->toggleFogOfWar();
|
||||
hud->toggleFogOfWar();
|
||||
}
|
||||
|
||||
int WindowManager::toggleFps()
|
||||
{
|
||||
showFPSLevel = (showFPSLevel+1)%3;
|
||||
hud->setFpsLevel(showFPSLevel);
|
||||
Settings::Manager::setInt("fps", "HUD", showFPSLevel);
|
||||
return showFPSLevel;
|
||||
}
|
||||
|
|
|
@ -158,7 +158,10 @@ namespace MWGui
|
|||
void setPlayerDir(const float x, const float y); ///< set player view direction in map space
|
||||
|
||||
void toggleFogOfWar();
|
||||
|
||||
|
||||
int toggleFps();
|
||||
///< toggle fps display @return resulting fps level
|
||||
|
||||
void setInteriorMapTexture(const int x, const int y);
|
||||
///< set the index of the map texture that should be used (for interiors)
|
||||
|
||||
|
|
|
@ -68,6 +68,8 @@ namespace MWInput
|
|||
A_ToggleWeapon,
|
||||
A_ToggleSpell,
|
||||
|
||||
A_ToggleFps, // Toggle FPS display (this is temporary)
|
||||
|
||||
A_LAST // Marker for the last item
|
||||
};
|
||||
|
||||
|
@ -88,6 +90,11 @@ namespace MWInput
|
|||
|
||||
/* InputImpl Methods */
|
||||
|
||||
void toggleFps()
|
||||
{
|
||||
windows.toggleFps();
|
||||
}
|
||||
|
||||
void toggleSpell()
|
||||
{
|
||||
DrawState state = player.getDrawState();
|
||||
|
@ -235,6 +242,8 @@ namespace MWInput
|
|||
"Draw Weapon");
|
||||
disp->funcs.bind(A_ToggleSpell,boost::bind(&InputImpl::toggleSpell,this),
|
||||
"Ready hands");
|
||||
disp->funcs.bind(A_ToggleFps, boost::bind(&InputImpl::toggleFps, this),
|
||||
"Toggle FPS display");
|
||||
// Add the exit listener
|
||||
ogre.getRoot()->addFrameListener(&exit);
|
||||
|
||||
|
@ -281,6 +290,7 @@ namespace MWInput
|
|||
disp->bind(A_ToggleWalk, KC_C);
|
||||
disp->bind(A_ToggleWeapon,KC_F);
|
||||
disp->bind(A_ToggleSpell,KC_R);
|
||||
disp->bind(A_ToggleFps, KC_F10);
|
||||
|
||||
// Key bindings for polled keys
|
||||
// NOTE: These keys are constantly being polled. Only add keys that must be checked each frame.
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "stat.hpp"
|
||||
#include "magiceffects.hpp"
|
||||
#include "spells.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
|
@ -14,7 +15,7 @@ namespace MWMechanics
|
|||
Stat<int> mAttributes[8];
|
||||
DynamicStat<int> mDynamic[3]; // health, magicka, fatigue
|
||||
int mLevel;
|
||||
std::set<std::string> mAbilities;
|
||||
Spells mSpells;
|
||||
MagicEffects mMagicEffects;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef GAME_MWMECHANICS_DRAWSTATE_H
|
||||
#define GAME_MWMECHANICS_DRAWSTATE_H
|
||||
|
||||
#undef DrawState
|
||||
|
||||
enum DrawState
|
||||
{
|
||||
DrawState_Weapon = 0,
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace MWMechanics
|
|||
|
||||
// reset
|
||||
creatureStats.mLevel = player->npdt52.level;
|
||||
creatureStats.mAbilities.clear();
|
||||
creatureStats.mSpells.clear();
|
||||
creatureStats.mMagicEffects = MagicEffects();
|
||||
|
||||
for (int i=0; i<27; ++i)
|
||||
|
@ -71,7 +71,7 @@ namespace MWMechanics
|
|||
for (std::vector<std::string>::const_iterator iter (race->powers.list.begin());
|
||||
iter!=race->powers.list.end(); ++iter)
|
||||
{
|
||||
insertSpell (*iter, ptr);
|
||||
creatureStats.mSpells.add (*iter);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ namespace MWMechanics
|
|||
for (std::vector<std::string>::const_iterator iter (sign->powers.list.begin());
|
||||
iter!=sign->powers.list.end(); ++iter)
|
||||
{
|
||||
insertSpell (*iter, ptr);
|
||||
creatureStats.mSpells.add (*iter);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,59 +159,14 @@ namespace MWMechanics
|
|||
creatureStats.mDynamic[i].setCurrent (creatureStats.mDynamic[i].getModified());
|
||||
}
|
||||
|
||||
void MechanicsManager::insertSpell (const std::string& id, MWWorld::Ptr& creature)
|
||||
{
|
||||
MWMechanics::CreatureStats& creatureStats =
|
||||
MWWorld::Class::get (creature).getCreatureStats (creature);
|
||||
|
||||
const ESM::Spell *spell = mEnvironment.mWorld->getStore().spells.find (id);
|
||||
|
||||
switch (spell->data.type)
|
||||
{
|
||||
case ESM::Spell::ST_Ability:
|
||||
|
||||
if (creatureStats.mAbilities.find (id)==creatureStats.mAbilities.end())
|
||||
{
|
||||
creatureStats.mAbilities.insert (id);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// TODO ST_SPELL, ST_Blight, ST_Disease, ST_Curse, ST_Power
|
||||
|
||||
default:
|
||||
|
||||
std::cout
|
||||
<< "adding unsupported spell type (" << spell->data.type
|
||||
<< ") to creature: " << id << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void MechanicsManager::adjustMagicEffects (MWWorld::Ptr& creature)
|
||||
{
|
||||
MWMechanics::CreatureStats& creatureStats =
|
||||
MWWorld::Class::get (creature).getCreatureStats (creature);
|
||||
|
||||
MagicEffects now;
|
||||
MagicEffects now = creatureStats.mSpells.getMagicEffects (mEnvironment);
|
||||
|
||||
for (std::set<std::string>::const_iterator iter (creatureStats.mAbilities.begin());
|
||||
iter!=creatureStats.mAbilities.end(); ++iter)
|
||||
{
|
||||
const ESM::Spell *spell = mEnvironment.mWorld->getStore().spells.find (*iter);
|
||||
|
||||
for (std::vector<ESM::ENAMstruct>::const_iterator iter = spell->effects.list.begin();
|
||||
iter!=spell->effects.list.end(); ++iter)
|
||||
{
|
||||
if (iter->range==0) // self
|
||||
{
|
||||
EffectParam param;
|
||||
param.mMagnitude = iter->magnMax; // TODO calculate magnitude
|
||||
now.add (EffectKey (*iter), param);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO add effects from other spell types, active spells and equipment
|
||||
/// \todo add effects from active spells and equipment
|
||||
|
||||
MagicEffects diff = MagicEffects::diff (creatureStats.mMagicEffects, now);
|
||||
|
||||
|
|
|
@ -37,8 +37,6 @@ namespace MWMechanics
|
|||
///< build player according to stored class/race/birthsign information. Will
|
||||
/// default to the values of the ESM::NPC object, if no explicit information is given.
|
||||
|
||||
void insertSpell (const std::string& id, MWWorld::Ptr& creature);
|
||||
|
||||
void adjustMagicEffects (MWWorld::Ptr& creature);
|
||||
|
||||
public:
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define GAME_MWMECHANICS_NPCSTATS_H
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "stat.hpp"
|
||||
#include "drawstate.hpp"
|
||||
|
@ -11,6 +12,10 @@ namespace MWMechanics
|
|||
/// \brief Additional stats for NPCs
|
||||
///
|
||||
/// For non-NPC-specific stats, see the CreatureStats struct.
|
||||
///
|
||||
/// \note For technical reasons the spell list and the currently selected spell is also handled by
|
||||
/// CreatureStats, even though they are actually NPC stats.
|
||||
|
||||
struct NpcStats
|
||||
{
|
||||
// NPCs other than the player can only have one faction. But for the sake of consistency
|
||||
|
|
81
apps/openmw/mwmechanics/spells.cpp
Normal file
81
apps/openmw/mwmechanics/spells.cpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
|
||||
#include "spells.hpp"
|
||||
|
||||
#include <components/esm/loadspel.hpp>
|
||||
|
||||
#include "../mwworld/environment.hpp"
|
||||
#include "../mwworld/world.hpp"
|
||||
|
||||
#include "magiceffects.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
void Spells::addSpell (const ESM::Spell *spell, MagicEffects& effects) const
|
||||
{
|
||||
for (std::vector<ESM::ENAMstruct>::const_iterator iter = spell->effects.list.begin();
|
||||
iter!=spell->effects.list.end(); ++iter)
|
||||
{
|
||||
EffectParam param;
|
||||
param.mMagnitude = iter->magnMax; /// \todo calculate magnitude
|
||||
effects.add (EffectKey (*iter), param);
|
||||
}
|
||||
}
|
||||
|
||||
Spells::TIterator Spells::begin() const
|
||||
{
|
||||
return mSpells.begin();
|
||||
}
|
||||
|
||||
Spells::TIterator Spells::end() const
|
||||
{
|
||||
return mSpells.end();
|
||||
}
|
||||
|
||||
void Spells::add (const std::string& spellId)
|
||||
{
|
||||
if (std::find (mSpells.begin(), mSpells.end(), spellId)!=mSpells.end())
|
||||
mSpells.push_back (spellId);
|
||||
}
|
||||
|
||||
void Spells::remove (const std::string& spellId)
|
||||
{
|
||||
TContainer::iterator iter = std::find (mSpells.begin(), mSpells.end(), spellId);
|
||||
|
||||
if (iter!=mSpells.end())
|
||||
mSpells.erase (iter);
|
||||
|
||||
if (spellId==mSelectedSpell)
|
||||
mSelectedSpell.clear();
|
||||
}
|
||||
|
||||
MagicEffects Spells::getMagicEffects (const MWWorld::Environment& environment) const
|
||||
{
|
||||
MagicEffects effects;
|
||||
|
||||
for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter)
|
||||
{
|
||||
const ESM::Spell *spell = environment.mWorld->getStore().spells.find (*iter);
|
||||
|
||||
if (spell->data.type==ESM::Spell::ST_Ability || spell->data.type==ESM::Spell::ST_Blight ||
|
||||
spell->data.type==ESM::Spell::ST_Disease || spell->data.type==ESM::Spell::ST_Curse)
|
||||
addSpell (spell, effects);
|
||||
}
|
||||
|
||||
return effects;
|
||||
}
|
||||
|
||||
void Spells::clear()
|
||||
{
|
||||
mSpells.clear();
|
||||
}
|
||||
|
||||
void Spells::setSelectedSpell (const std::string& spellId)
|
||||
{
|
||||
mSelectedSpell = spellId;
|
||||
}
|
||||
|
||||
const std::string Spells::getSelectedSpell() const
|
||||
{
|
||||
return mSelectedSpell;
|
||||
}
|
||||
}
|
66
apps/openmw/mwmechanics/spells.hpp
Normal file
66
apps/openmw/mwmechanics/spells.hpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
#ifndef GAME_MWMECHANICS_SPELLS_H
|
||||
#define GAME_MWMECHANICS_SPELLS_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct Spell;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
struct Environment;
|
||||
}
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
class MagicEffects;
|
||||
|
||||
/// \brief Spell list
|
||||
///
|
||||
/// This class manages known spells as well as abilities, powers and permanent negative effects like
|
||||
/// diseaes.
|
||||
class Spells
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::vector<std::string> TContainer;
|
||||
typedef TContainer::const_iterator TIterator;
|
||||
|
||||
private:
|
||||
|
||||
std::vector<std::string> mSpells;
|
||||
std::string mSelectedSpell;
|
||||
|
||||
void addSpell (const ESM::Spell *, MagicEffects& effects) const;
|
||||
|
||||
public:
|
||||
|
||||
TIterator begin() const;
|
||||
|
||||
TIterator end() const;
|
||||
|
||||
void add (const std::string& spell);
|
||||
///< Adding a spell that is already listed in *this is a no-op.
|
||||
|
||||
void remove (const std::string& spell);
|
||||
///< If the spell to be removed is the selected spell, the selected spell will be changed to
|
||||
/// no spell (empty string).
|
||||
|
||||
MagicEffects getMagicEffects (const MWWorld::Environment& environment) const;
|
||||
///< Return sum of magic effects resulting from abilities, blights, deseases and curses.
|
||||
|
||||
void clear();
|
||||
///< Remove all spells of al types.
|
||||
|
||||
void setSelectedSpell (const std::string& spellId);
|
||||
///< This function does not verify, if the spell is available.
|
||||
|
||||
const std::string getSelectedSpell() const;
|
||||
///< May return an empty string.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -20,10 +20,10 @@ Actors::~Actors(){
|
|||
void Actors::setMwRoot(Ogre::SceneNode* root){
|
||||
mMwRoot = root;
|
||||
}
|
||||
void Actors::insertNPC(const MWWorld::Ptr& ptr){
|
||||
void Actors::insertNPC(const MWWorld::Ptr& ptr, MWWorld::InventoryStore& inv){
|
||||
|
||||
insertBegin(ptr, true, true);
|
||||
NpcAnimation* anim = new MWRender::NpcAnimation(ptr, mEnvironment, mRend);
|
||||
NpcAnimation* anim = new MWRender::NpcAnimation(ptr, mEnvironment, mRend, inv);
|
||||
|
||||
mAllActors[ptr] = anim;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace MWRender{
|
|||
void setMwRoot(Ogre::SceneNode* root);
|
||||
void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_);
|
||||
void insertCreature (const MWWorld::Ptr& ptr);
|
||||
void insertNPC(const MWWorld::Ptr& ptr);
|
||||
void insertNPC(const MWWorld::Ptr& ptr, MWWorld::InventoryStore& inv);
|
||||
bool deleteObject (const MWWorld::Ptr& ptr);
|
||||
///< \return found?
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ namespace MWRender{
|
|||
, mRend(_rend)
|
||||
, mEnvironment(_env)
|
||||
, vecRotPos()
|
||||
, shapeparts()
|
||||
, time(0.0f)
|
||||
, startTime(0.0f)
|
||||
, stopTime(0.0f)
|
||||
|
@ -19,7 +18,6 @@ namespace MWRender{
|
|||
, shapeNumber(0)
|
||||
, shapeIndexI()
|
||||
, shapes(NULL)
|
||||
, entityparts()
|
||||
, transformations(NULL)
|
||||
, textmappings(NULL)
|
||||
, base(NULL)
|
||||
|
@ -305,8 +303,8 @@ namespace MWRender{
|
|||
|
||||
for(; boneSequenceIter != boneSequence.end(); boneSequenceIter++)
|
||||
{
|
||||
if(creaturemodel->getSkeleton()->hasBone(*boneSequenceIter)){
|
||||
Ogre::Bone *bonePtr = creaturemodel->getSkeleton()->getBone(*boneSequenceIter);
|
||||
if(skel->hasBone(*boneSequenceIter)){
|
||||
Ogre::Bone *bonePtr = skel->getBone(*boneSequenceIter);
|
||||
// Computes C = B + AxC*scale
|
||||
transmult = transmult + rotmult * bonePtr->getPosition();
|
||||
rotmult = rotmult * bonePtr->getOrientation();
|
||||
|
@ -430,14 +428,7 @@ namespace MWRender{
|
|||
//base->_updateAnimation();
|
||||
//base->_notifyMoved();
|
||||
|
||||
for(unsigned int i = 0; i < entityparts.size(); i++){
|
||||
//Ogre::SkeletonInstance* skel = entityparts[i]->getSkeleton();
|
||||
|
||||
//Ogre::Bone* b = skel->getRootBone();
|
||||
//b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3));//This is a trick
|
||||
|
||||
//entityparts[i]->getAllAnimationStates()->_notifyDirty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<Nif::NiKeyframeData>::iterator iter;
|
||||
|
|
|
@ -31,7 +31,7 @@ class Animation{
|
|||
|
||||
|
||||
|
||||
std::vector<std::vector<Nif::NiTriShapeCopy>* > shapeparts; //All the NiTriShape data that we need for animating an npc
|
||||
|
||||
|
||||
float time;
|
||||
float startTime;
|
||||
|
@ -48,7 +48,7 @@ class Animation{
|
|||
|
||||
//Ogre::SkeletonInstance* skel;
|
||||
std::vector<Nif::NiTriShapeCopy>* shapes; //All the NiTriShapeData for a creature
|
||||
std::vector<Ogre::Entity*> entityparts;
|
||||
|
||||
|
||||
|
||||
std::vector<Nif::NiKeyframeData>* transformations;
|
||||
|
|
|
@ -225,7 +225,9 @@ void LocalMap::render(const float x, const float y,
|
|||
vp->setShadowsEnabled(false);
|
||||
vp->setBackgroundColour(ColourValue(0, 0, 0));
|
||||
vp->setVisibilityMask(RV_Map);
|
||||
vp->setMaterialScheme("Map");
|
||||
|
||||
// use fallback techniques without shadows and without mrt
|
||||
vp->setMaterialScheme("Fallback");
|
||||
|
||||
rtt->update();
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "renderconst.hpp"
|
||||
|
||||
|
||||
|
||||
using namespace Ogre;
|
||||
using namespace NifOgre;
|
||||
namespace MWRender{
|
||||
|
@ -11,9 +12,49 @@ NpcAnimation::~NpcAnimation(){
|
|||
}
|
||||
|
||||
|
||||
NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,OEngine::Render::OgreRenderer& _rend): Animation(_env,_rend){
|
||||
NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv): Animation(_env,_rend), mStateID(-1), inv(_inv), timeToChange(0),
|
||||
robe(inv.end()), helmet(inv.end()), shirt(inv.end()),
|
||||
cuirass(inv.end()), greaves(inv.end()),
|
||||
leftpauldron(inv.end()), rightpauldron(inv.end()),
|
||||
boots(inv.end()),
|
||||
leftglove(inv.end()), rightglove(inv.end()), skirtiter(inv.end()),
|
||||
pants(inv.end()),
|
||||
lclavicle(0),
|
||||
rclavicle(0),
|
||||
rupperArm(0),
|
||||
lupperArm(0),
|
||||
rUpperLeg(0),
|
||||
lUpperLeg(0),
|
||||
lForearm(0),
|
||||
rForearm(0),
|
||||
lWrist(0),
|
||||
rWrist(0),
|
||||
rKnee(0),
|
||||
lKnee(0),
|
||||
neck(0),
|
||||
rAnkle(0),
|
||||
lAnkle(0),
|
||||
groin(0),
|
||||
lfoot(0),
|
||||
rfoot(0)
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
|
||||
ptr.get<ESM::NPC>();
|
||||
Ogre::Entity* blank = 0;
|
||||
std::vector<Nif::NiTriShapeCopy>* blankshape = 0;
|
||||
zero = std::make_pair(blank, blankshape);
|
||||
chest = std::make_pair(blank, blankshape);
|
||||
tail = std::make_pair(blank, blankshape);
|
||||
lBeastFoot = std::make_pair(blank, blankshape);
|
||||
rBeastFoot = std::make_pair(blank, blankshape);
|
||||
rhand = std::make_pair(blank, blankshape);
|
||||
lhand = std::make_pair(blank, blankshape);
|
||||
skirt = std::make_pair(blank, blankshape);
|
||||
for (int init = 0; init < 27; init++){
|
||||
partslots[init] = -1; //each slot is empty
|
||||
partpriorities[init] = 0;
|
||||
}
|
||||
|
||||
|
||||
//Part selection on last character of the file string
|
||||
// " Tri Chest
|
||||
|
@ -35,16 +76,21 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O
|
|||
|
||||
std::string hairID = ref->base->hair;
|
||||
std::string headID = ref->base->head;
|
||||
std::string npcName = ref->base->name;
|
||||
headModel = "meshes\\" +
|
||||
mEnvironment.mWorld->getStore().bodyParts.find(headID)->model;
|
||||
|
||||
hairModel = "meshes\\" +
|
||||
mEnvironment.mWorld->getStore().bodyParts.find(hairID)->model;
|
||||
npcName = ref->base->name;
|
||||
//ESMStore::Races r =
|
||||
const ESM::Race* race = mEnvironment.mWorld->getStore().races.find(ref->base->race);
|
||||
|
||||
|
||||
std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4);
|
||||
bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4);
|
||||
char secondtolast = bodyRaceID.at(bodyRaceID.length() - 2);
|
||||
bool female = tolower(secondtolast) == 'f';
|
||||
isFemale = tolower(secondtolast) == 'f';
|
||||
std::transform(bodyRaceID.begin(), bodyRaceID.end(), bodyRaceID.begin(), ::tolower);
|
||||
bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_";
|
||||
isBeast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_";
|
||||
|
||||
/*std::cout << "Race: " << ref->base->race ;
|
||||
if(female){
|
||||
|
@ -57,7 +103,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O
|
|||
|
||||
|
||||
std::string smodel = "meshes\\base_anim.nif";
|
||||
if(beast)
|
||||
if(isBeast)
|
||||
smodel = "meshes\\base_animkna.nif";
|
||||
|
||||
insert = ptr.getRefData().getBaseNode();
|
||||
|
@ -66,6 +112,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O
|
|||
NifOgre::NIFLoader::load(smodel);
|
||||
|
||||
base = mRend.getScene()->createEntity(smodel);
|
||||
|
||||
base->setVisibilityFlags(RV_Actors);
|
||||
bool transparent = false;
|
||||
for (unsigned int i=0; i<base->getNumSubEntities(); ++i)
|
||||
|
@ -87,6 +134,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O
|
|||
}
|
||||
base->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main);
|
||||
|
||||
|
||||
base->setSkipAnimationStateUpdate(true); //Magical line of code, this makes the bones
|
||||
//stay in the same place when we skipanim, or open a gui window
|
||||
|
||||
|
@ -105,168 +153,388 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O
|
|||
textmappings = NIFLoader::getSingletonPtr()->getTextIndices(smodel);
|
||||
insert->attachObject(base);
|
||||
|
||||
if(female)
|
||||
|
||||
if(isFemale)
|
||||
insert->scale(race->data.height.female, race->data.height.female, race->data.height.female);
|
||||
else
|
||||
insert->scale(race->data.height.male, race->data.height.male, race->data.height.male);
|
||||
std::string headModel = "meshes\\" +
|
||||
mEnvironment.mWorld->getStore().bodyParts.find(headID)->model;
|
||||
std::cout << "Inv" << inv.getStateId() << "\n";
|
||||
updateParts();
|
||||
|
||||
std::string hairModel = "meshes\\" +
|
||||
mEnvironment.mWorld->getStore().bodyParts.find(hairID)->model;
|
||||
const ESM::BodyPart *chest = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "chest");
|
||||
const ESM::BodyPart *upperleg = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper leg");
|
||||
const ESM::BodyPart *groin = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "groin");
|
||||
const ESM::BodyPart *arml = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper arm"); //We need two
|
||||
const ESM::BodyPart *neck = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "neck");
|
||||
const ESM::BodyPart *knee = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "knee");
|
||||
const ESM::BodyPart *ankle = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "ankle");
|
||||
const ESM::BodyPart *foot = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "foot");
|
||||
const ESM::BodyPart *feet = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "feet");
|
||||
const ESM::BodyPart *tail = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "tail");
|
||||
const ESM::BodyPart *wristl = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "wrist"); //We need two
|
||||
const ESM::BodyPart *forearml = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "forearm"); //We need two
|
||||
const ESM::BodyPart *handl = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "hand"); //We need two
|
||||
const ESM::BodyPart *hair = mEnvironment.mWorld->getStore().bodyParts.search(hairID);
|
||||
const ESM::BodyPart *head = mEnvironment.mWorld->getStore().bodyParts.search(headID);
|
||||
if(bodyRaceID == "b_n_argonian_f_")
|
||||
forearml = mEnvironment.mWorld->getStore().bodyParts.search ("b_n_argonian_m_forearm"); //We need two
|
||||
if(!handl)
|
||||
handl = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "hands");
|
||||
//const ESM::BodyPart* claviclel = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "clavicle");
|
||||
//const ESM::BodyPart* clavicler = claviclel;
|
||||
const ESM::BodyPart* handr = handl;
|
||||
const ESM::BodyPart* forearmr = forearml;
|
||||
const ESM::BodyPart* wristr = wristl;
|
||||
const ESM::BodyPart* armr = arml;
|
||||
}
|
||||
|
||||
void NpcAnimation::updateParts(){
|
||||
|
||||
bool apparelChanged = false;
|
||||
|
||||
|
||||
if(upperleg){
|
||||
insertBoundedPart("meshes\\" + upperleg->model + "*|", "Left Upper Leg");
|
||||
insertBoundedPart("meshes\\" + upperleg->model, "Right Upper Leg");
|
||||
|
||||
//inv.getSlot(MWWorld::InventoryStore::Slot_Robe);
|
||||
if(robe != inv.getSlot(MWWorld::InventoryStore::Slot_Robe)){
|
||||
//A robe was added or removed
|
||||
removePartGroup(MWWorld::InventoryStore::Slot_Robe);
|
||||
robe = inv.getSlot(MWWorld::InventoryStore::Slot_Robe);
|
||||
apparelChanged = true;
|
||||
}
|
||||
if(foot){
|
||||
if(bodyRaceID.compare("b_n_khajiit_m_") == 0)
|
||||
{
|
||||
feet = foot;
|
||||
}
|
||||
else
|
||||
{
|
||||
insertBoundedPart("meshes\\" + foot->model, "Right Foot");
|
||||
insertBoundedPart("meshes\\" + foot->model + "*|", "Left Foot");
|
||||
}
|
||||
if(skirtiter != inv.getSlot(MWWorld::InventoryStore::Slot_Skirt)){
|
||||
//A robe was added or removed
|
||||
removePartGroup(MWWorld::InventoryStore::Slot_Skirt);
|
||||
skirtiter = inv.getSlot(MWWorld::InventoryStore::Slot_Skirt);
|
||||
apparelChanged = true;
|
||||
}
|
||||
if(groin){
|
||||
insertBoundedPart("meshes\\" + groin->model, "Groin");
|
||||
}
|
||||
if(knee)
|
||||
{
|
||||
insertBoundedPart("meshes\\" + knee->model + "*|", "Left Knee"); //e
|
||||
insertBoundedPart("meshes\\" + knee->model, "Right Knee"); //e
|
||||
if(helmet != inv.getSlot(MWWorld::InventoryStore::Slot_Helmet)){
|
||||
apparelChanged = true;
|
||||
helmet = inv.getSlot(MWWorld::InventoryStore::Slot_Helmet);
|
||||
removePartGroup(MWWorld::InventoryStore::Slot_Helmet);
|
||||
|
||||
}
|
||||
if(ankle){
|
||||
|
||||
insertBoundedPart("meshes\\" + ankle->model + "*|", "Left Ankle"); //Ogre::Quaternion(Ogre::Radian(3.14 / 4), Ogre::Vector3(1, 0, 0)),blank); //1,0,0, blank);
|
||||
insertBoundedPart("meshes\\" + ankle->model, "Right Ankle");
|
||||
}
|
||||
if (armr){
|
||||
insertBoundedPart("meshes\\" + armr->model, "Right Upper Arm");
|
||||
}
|
||||
if(arml){
|
||||
insertBoundedPart("meshes\\" + arml->model + "*|", "Left Upper Arm");
|
||||
}
|
||||
|
||||
if (forearmr)
|
||||
{
|
||||
insertBoundedPart("meshes\\" + forearmr->model, "Right Forearm");
|
||||
}
|
||||
if(forearml)
|
||||
insertBoundedPart("meshes\\" + forearml->model + "*|", "Left Forearm");
|
||||
|
||||
if (wristr)
|
||||
{
|
||||
insertBoundedPart("meshes\\" + wristr->model, "Right Wrist");
|
||||
}
|
||||
|
||||
if(wristl)
|
||||
insertBoundedPart("meshes\\" + wristl->model + "*|", "Left Wrist");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*if(claviclel)
|
||||
insertBoundedPart("meshes\\" + claviclel->model + "*|", "Left Clavicle", base);
|
||||
if(clavicler)
|
||||
insertBoundedPart("meshes\\" + clavicler->model , "Right Clavicle", base);*/
|
||||
|
||||
if(neck)
|
||||
{
|
||||
insertBoundedPart("meshes\\" + neck->model, "Neck");
|
||||
}
|
||||
if(head)
|
||||
insertBoundedPart("meshes\\" + head->model, "Head");
|
||||
if(hair)
|
||||
insertBoundedPart("meshes\\" + hair->model, "Head");
|
||||
|
||||
if (chest){
|
||||
insertFreePart("meshes\\" + chest->model, ">\"", insert);
|
||||
|
||||
|
||||
}
|
||||
if (handr){
|
||||
insertFreePart("meshes\\" + handr->model , ">?", insert);
|
||||
|
||||
}
|
||||
if (handl){
|
||||
insertFreePart("meshes\\" + handl->model, ">>", insert);
|
||||
|
||||
}
|
||||
if(tail){
|
||||
insertFreePart("meshes\\" + tail->model, ">*", insert);
|
||||
}
|
||||
if(feet){
|
||||
std::string num = getUniqueID(feet->model);
|
||||
insertFreePart("meshes\\" + feet->model,"><", insert);
|
||||
insertFreePart("meshes\\" + feet->model,">:", insert);
|
||||
if(cuirass != inv.getSlot(MWWorld::InventoryStore::Slot_Cuirass)){
|
||||
cuirass = inv.getSlot(MWWorld::InventoryStore::Slot_Cuirass);
|
||||
removePartGroup(MWWorld::InventoryStore::Slot_Cuirass);
|
||||
apparelChanged = true;
|
||||
|
||||
}
|
||||
//originalpos = insert->_getWorldAABB().getCenter();
|
||||
//originalscenenode = insert->getPosition();
|
||||
if(greaves != inv.getSlot(MWWorld::InventoryStore::Slot_Greaves)){
|
||||
greaves = inv.getSlot(MWWorld::InventoryStore::Slot_Greaves);
|
||||
removePartGroup(MWWorld::InventoryStore::Slot_Greaves);
|
||||
apparelChanged = true;
|
||||
}
|
||||
if(leftpauldron != inv.getSlot(MWWorld::InventoryStore::Slot_LeftPauldron)){
|
||||
leftpauldron = inv.getSlot(MWWorld::InventoryStore::Slot_LeftPauldron);
|
||||
removePartGroup(MWWorld::InventoryStore::Slot_LeftPauldron);
|
||||
apparelChanged = true;
|
||||
|
||||
}
|
||||
if(rightpauldron != inv.getSlot(MWWorld::InventoryStore::Slot_RightPauldron)){
|
||||
rightpauldron = inv.getSlot(MWWorld::InventoryStore::Slot_RightPauldron);
|
||||
removePartGroup(MWWorld::InventoryStore::Slot_RightPauldron);
|
||||
apparelChanged = true;
|
||||
|
||||
}
|
||||
if(!isBeast && boots != inv.getSlot(MWWorld::InventoryStore::Slot_Boots)){
|
||||
boots = inv.getSlot(MWWorld::InventoryStore::Slot_Boots);
|
||||
removePartGroup(MWWorld::InventoryStore::Slot_Boots);
|
||||
apparelChanged = true;
|
||||
|
||||
}
|
||||
if(leftglove != inv.getSlot(MWWorld::InventoryStore::Slot_LeftGauntlet)){
|
||||
leftglove = inv.getSlot(MWWorld::InventoryStore::Slot_LeftGauntlet);
|
||||
removePartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet);
|
||||
apparelChanged = true;
|
||||
|
||||
}
|
||||
if(rightglove != inv.getSlot(MWWorld::InventoryStore::Slot_RightGauntlet)){
|
||||
rightglove = inv.getSlot(MWWorld::InventoryStore::Slot_RightGauntlet);
|
||||
removePartGroup(MWWorld::InventoryStore::Slot_RightGauntlet);
|
||||
apparelChanged = true;
|
||||
|
||||
}
|
||||
if(shirt != inv.getSlot(MWWorld::InventoryStore::Slot_Shirt)){
|
||||
shirt = inv.getSlot(MWWorld::InventoryStore::Slot_Shirt);
|
||||
removePartGroup(MWWorld::InventoryStore::Slot_Shirt);
|
||||
apparelChanged = true;
|
||||
|
||||
}
|
||||
if(pants != inv.getSlot(MWWorld::InventoryStore::Slot_Pants)){
|
||||
pants = inv.getSlot(MWWorld::InventoryStore::Slot_Pants);
|
||||
removePartGroup(MWWorld::InventoryStore::Slot_Pants);
|
||||
apparelChanged = true;
|
||||
|
||||
}
|
||||
|
||||
if(apparelChanged){
|
||||
if(robe != inv.end())
|
||||
{
|
||||
MWWorld::Ptr ptr = *robe;
|
||||
|
||||
const ESM::Clothing *clothes = (ptr.get<ESM::Clothing>())->base;
|
||||
std::vector<ESM::PartReference> parts = clothes->parts.parts;
|
||||
addPartGroup(MWWorld::InventoryStore::Slot_Robe, 5, parts);
|
||||
reserveIndividualPart(ESM::PRT_Groin, MWWorld::InventoryStore::Slot_Robe, 5);
|
||||
reserveIndividualPart(ESM::PRT_Skirt, MWWorld::InventoryStore::Slot_Robe, 5);
|
||||
reserveIndividualPart(ESM::PRT_RLeg, MWWorld::InventoryStore::Slot_Robe, 5);
|
||||
reserveIndividualPart(ESM::PRT_LLeg, MWWorld::InventoryStore::Slot_Robe, 5);
|
||||
reserveIndividualPart(ESM::PRT_RUpperarm, MWWorld::InventoryStore::Slot_Robe, 5);
|
||||
reserveIndividualPart(ESM::PRT_LUpperarm, MWWorld::InventoryStore::Slot_Robe, 5);
|
||||
reserveIndividualPart(ESM::PRT_RKnee, MWWorld::InventoryStore::Slot_Robe, 5);
|
||||
reserveIndividualPart(ESM::PRT_LKnee, MWWorld::InventoryStore::Slot_Robe, 5);
|
||||
reserveIndividualPart(ESM::PRT_RForearm, MWWorld::InventoryStore::Slot_Robe, 5);
|
||||
reserveIndividualPart(ESM::PRT_LForearm, MWWorld::InventoryStore::Slot_Robe, 5);
|
||||
reserveIndividualPart(ESM::PRT_RPauldron, MWWorld::InventoryStore::Slot_Robe, 5);
|
||||
reserveIndividualPart(ESM::PRT_LPauldron, MWWorld::InventoryStore::Slot_Robe, 5);
|
||||
}
|
||||
if(skirtiter != inv.end())
|
||||
{
|
||||
MWWorld::Ptr ptr = *skirtiter;
|
||||
|
||||
const ESM::Clothing *clothes = (ptr.get<ESM::Clothing>())->base;
|
||||
std::vector<ESM::PartReference> parts = clothes->parts.parts;
|
||||
addPartGroup(MWWorld::InventoryStore::Slot_Skirt, 4, parts);
|
||||
reserveIndividualPart(ESM::PRT_Groin, MWWorld::InventoryStore::Slot_Skirt, 4);
|
||||
reserveIndividualPart(ESM::PRT_RLeg, MWWorld::InventoryStore::Slot_Skirt, 4);
|
||||
reserveIndividualPart(ESM::PRT_LLeg, MWWorld::InventoryStore::Slot_Skirt, 4);
|
||||
}
|
||||
|
||||
if(helmet != inv.end()){
|
||||
removeIndividualPart(ESM::PRT_Hair);
|
||||
const ESM::Armor *armor = (helmet->get<ESM::Armor>())->base;
|
||||
std::vector<ESM::PartReference> parts = armor->parts.parts;
|
||||
addPartGroup(MWWorld::InventoryStore::Slot_Helmet, 3, parts);
|
||||
|
||||
}
|
||||
if(cuirass != inv.end()){
|
||||
const ESM::Armor *armor = (cuirass->get<ESM::Armor>())->base;
|
||||
std::vector<ESM::PartReference> parts = armor->parts.parts;
|
||||
addPartGroup(MWWorld::InventoryStore::Slot_Cuirass, 3, parts);
|
||||
|
||||
}
|
||||
if(greaves != inv.end()){
|
||||
const ESM::Armor *armor = (greaves->get<ESM::Armor>())->base;
|
||||
std::vector<ESM::PartReference> parts = armor->parts.parts;
|
||||
addPartGroup(MWWorld::InventoryStore::Slot_Greaves, 3, parts);
|
||||
|
||||
}
|
||||
|
||||
if(leftpauldron != inv.end()){
|
||||
const ESM::Armor *armor = (leftpauldron->get<ESM::Armor>())->base;
|
||||
std::vector<ESM::PartReference> parts = armor->parts.parts;
|
||||
addPartGroup(MWWorld::InventoryStore::Slot_LeftPauldron, 3, parts);
|
||||
|
||||
}
|
||||
if(rightpauldron != inv.end()){
|
||||
const ESM::Armor *armor = (rightpauldron->get<ESM::Armor>())->base;
|
||||
std::vector<ESM::PartReference> parts = armor->parts.parts;
|
||||
addPartGroup(MWWorld::InventoryStore::Slot_RightPauldron, 3, parts);
|
||||
|
||||
}
|
||||
if(!isBeast && boots != inv.end()){
|
||||
|
||||
if(boots->getTypeName() == typeid(ESM::Clothing).name()){
|
||||
const ESM::Clothing *clothes = (boots->get<ESM::Clothing>())->base;
|
||||
std::vector<ESM::PartReference> parts = clothes->parts.parts;
|
||||
addPartGroup(MWWorld::InventoryStore::Slot_Boots, 2, parts);
|
||||
}
|
||||
else if(boots->getTypeName() == typeid(ESM::Armor).name())
|
||||
{
|
||||
const ESM::Armor *armor = (boots->get<ESM::Armor>())->base;
|
||||
std::vector<ESM::PartReference> parts = armor->parts.parts;
|
||||
addPartGroup(MWWorld::InventoryStore::Slot_Boots, 3, parts);
|
||||
}
|
||||
|
||||
}
|
||||
if(leftglove != inv.end()){
|
||||
|
||||
if(leftglove->getTypeName() == typeid(ESM::Clothing).name()){
|
||||
const ESM::Clothing *clothes = (leftglove->get<ESM::Clothing>())->base;
|
||||
std::vector<ESM::PartReference> parts = clothes->parts.parts;
|
||||
addPartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet, 2, parts);
|
||||
}
|
||||
else
|
||||
{
|
||||
const ESM::Armor *armor = (leftglove->get<ESM::Armor>())->base;
|
||||
std::vector<ESM::PartReference> parts = armor->parts.parts;
|
||||
addPartGroup(MWWorld::InventoryStore::Slot_LeftGauntlet, 3, parts);
|
||||
}
|
||||
|
||||
}
|
||||
if(rightglove != inv.end()){
|
||||
|
||||
if(rightglove->getTypeName() == typeid(ESM::Clothing).name()){
|
||||
const ESM::Clothing *clothes = (rightglove->get<ESM::Clothing>())->base;
|
||||
std::vector<ESM::PartReference> parts = clothes->parts.parts;
|
||||
addPartGroup(MWWorld::InventoryStore::Slot_RightGauntlet, 2, parts);
|
||||
}
|
||||
else
|
||||
{
|
||||
const ESM::Armor *armor = (rightglove->get<ESM::Armor>())->base;
|
||||
std::vector<ESM::PartReference> parts = armor->parts.parts;
|
||||
addPartGroup(MWWorld::InventoryStore::Slot_RightGauntlet, 3, parts);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(shirt != inv.end()){
|
||||
const ESM::Clothing *clothes = (shirt->get<ESM::Clothing>())->base;
|
||||
std::vector<ESM::PartReference> parts = clothes->parts.parts;
|
||||
addPartGroup(MWWorld::InventoryStore::Slot_Shirt, 2, parts);
|
||||
}
|
||||
if(pants != inv.end()){
|
||||
const ESM::Clothing *clothes = (pants->get<ESM::Clothing>())->base;
|
||||
std::vector<ESM::PartReference> parts = clothes->parts.parts;
|
||||
addPartGroup(MWWorld::InventoryStore::Slot_Pants, 2, parts);
|
||||
}
|
||||
}
|
||||
|
||||
if(partpriorities[ESM::PRT_Head] < 1){
|
||||
addOrReplaceIndividualPart(ESM::PRT_Head, -1,1,headModel);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_Hair] < 1 && partpriorities[ESM::PRT_Head] <= 1){
|
||||
addOrReplaceIndividualPart(ESM::PRT_Hair, -1,1,hairModel);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_Neck] < 1){
|
||||
const ESM::BodyPart *neckPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "neck");
|
||||
if(neckPart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_Neck, -1,1,"meshes\\" + neckPart->model);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_Cuirass] < 1){
|
||||
const ESM::BodyPart *chestPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "chest");
|
||||
if(chestPart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_Cuirass, -1,1,"meshes\\" + chestPart->model);
|
||||
}
|
||||
|
||||
if(partpriorities[ESM::PRT_Groin] < 1){
|
||||
const ESM::BodyPart *groinPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "groin");
|
||||
if(groinPart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_Groin, -1,1,"meshes\\" + groinPart->model);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_RHand] < 1){
|
||||
const ESM::BodyPart *handPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "hand");
|
||||
if(!handPart)
|
||||
handPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "hands");
|
||||
if(handPart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_RHand, -1,1,"meshes\\" + handPart->model);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_LHand] < 1){
|
||||
const ESM::BodyPart *handPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "hand");
|
||||
if(!handPart)
|
||||
handPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "hands");
|
||||
if(handPart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_LHand, -1,1,"meshes\\" + handPart->model);
|
||||
}
|
||||
|
||||
if(partpriorities[ESM::PRT_RWrist] < 1){
|
||||
const ESM::BodyPart *wristPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "wrist");
|
||||
if(wristPart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_RWrist, -1,1,"meshes\\" + wristPart->model);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_LWrist] < 1){
|
||||
const ESM::BodyPart *wristPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "wrist");
|
||||
if(wristPart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_LWrist, -1,1,"meshes\\" + wristPart->model);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_RForearm] < 1){
|
||||
const ESM::BodyPart *forearmPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "forearm");
|
||||
if(bodyRaceID == "b_n_argonian_f_")
|
||||
forearmPart = mEnvironment.mWorld->getStore().bodyParts.search ("b_n_argonian_m_forearm");
|
||||
if(forearmPart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_RForearm, -1,1,"meshes\\" + forearmPart->model);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_LForearm] < 1){
|
||||
const ESM::BodyPart *forearmPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "forearm");
|
||||
if(bodyRaceID == "b_n_argonian_f_")
|
||||
forearmPart = mEnvironment.mWorld->getStore().bodyParts.search ("b_n_argonian_m_forearm");
|
||||
if(forearmPart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_LForearm, -1,1,"meshes\\" + forearmPart->model);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_RUpperarm] < 1){
|
||||
const ESM::BodyPart *armPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper arm");
|
||||
if(armPart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_RUpperarm, -1,1,"meshes\\" + armPart->model);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_LUpperarm] < 1){
|
||||
const ESM::BodyPart *armPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper arm");
|
||||
if(armPart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_LUpperarm, -1,1,"meshes\\" + armPart->model);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_RFoot] < 1){
|
||||
const ESM::BodyPart *footPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "foot");
|
||||
if(isBeast)
|
||||
footPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "feet");
|
||||
if(footPart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_RFoot, -1,1,"meshes\\" + footPart->model);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_LFoot] < 1){
|
||||
const ESM::BodyPart *footPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "foot");
|
||||
if(isBeast)
|
||||
footPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "feet");
|
||||
if(footPart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_LFoot, -1,1,"meshes\\" + footPart->model);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_RAnkle] < 1){
|
||||
const ESM::BodyPart *anklePart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "ankle");
|
||||
if(anklePart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_RAnkle, -1,1,"meshes\\" + anklePart->model);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_LAnkle] < 1){
|
||||
const ESM::BodyPart *anklePart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "ankle");
|
||||
if(anklePart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_LAnkle, -1,1,"meshes\\" + anklePart->model);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_RKnee] < 1){
|
||||
const ESM::BodyPart *kneePart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "knee");
|
||||
if(kneePart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_RKnee, -1,1,"meshes\\" + kneePart->model);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_LKnee] < 1){
|
||||
const ESM::BodyPart *kneePart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "knee");
|
||||
if(kneePart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_LKnee, -1,1,"meshes\\" + kneePart->model);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_RLeg] < 1){
|
||||
const ESM::BodyPart *legPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper leg");
|
||||
if(legPart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_RLeg, -1,1,"meshes\\" + legPart->model);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_LLeg] < 1){
|
||||
const ESM::BodyPart *legPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper leg");
|
||||
if(legPart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_LLeg, -1,1,"meshes\\" + legPart->model);
|
||||
}
|
||||
if(partpriorities[ESM::PRT_Tail] < 1){
|
||||
const ESM::BodyPart *tailPart = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "tail");
|
||||
if(tailPart)
|
||||
addOrReplaceIndividualPart(ESM::PRT_Tail, -1,1,"meshes\\" + tailPart->model);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Ogre::Entity* NpcAnimation::insertBoundedPart(const std::string &mesh, std::string bonename){
|
||||
|
||||
NIFLoader::load(mesh);
|
||||
Entity* ent = mRend.getScene()->createEntity(mesh);
|
||||
|
||||
base->attachObjectToBone(bonename, ent);
|
||||
return ent;
|
||||
NIFLoader::load(mesh);
|
||||
Ogre::Entity* part = mRend.getScene()->createEntity(mesh);
|
||||
part->setVisibilityFlags(RV_Actors);
|
||||
|
||||
base->attachObjectToBone(bonename, part);
|
||||
return part;
|
||||
}
|
||||
void NpcAnimation::insertFreePart(const std::string &mesh, const std::string suffix, Ogre::SceneNode* insert){
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> NpcAnimation::insertFreePart(const std::string &mesh, const std::string suffix){
|
||||
|
||||
std::string meshNumbered = mesh + getUniqueID(mesh + suffix) + suffix;
|
||||
NIFLoader::load(meshNumbered);
|
||||
|
||||
Ogre::Entity* ent = mRend.getScene()->createEntity(meshNumbered);
|
||||
Ogre::Entity* part = mRend.getScene()->createEntity(meshNumbered);
|
||||
part->setVisibilityFlags(RV_Actors);
|
||||
|
||||
|
||||
insert->attachObject(part);
|
||||
|
||||
|
||||
insert->attachObject(ent);
|
||||
entityparts.push_back(ent);
|
||||
shapes = ((NIFLoader::getSingletonPtr())->getShapes(mesh + "0000" + suffix));
|
||||
if(shapes){
|
||||
shapeparts.push_back(shapes);
|
||||
handleShapes(shapes, ent, base->getSkeleton());
|
||||
std::vector<Nif::NiTriShapeCopy>* shape = ((NIFLoader::getSingletonPtr())->getShapes(mesh + "0000" + suffix));
|
||||
if(shape){
|
||||
handleShapes(shape, part, base->getSkeleton());
|
||||
}
|
||||
|
||||
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> pair = std::make_pair(part, shape);
|
||||
return pair;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void NpcAnimation::runAnimation(float timepassed){
|
||||
|
||||
|
||||
if(timeToChange > .2){
|
||||
|
||||
timeToChange = 0;
|
||||
|
||||
updateParts();
|
||||
}
|
||||
|
||||
timeToChange += timepassed;
|
||||
|
||||
//1. Add the amount of time passed to time
|
||||
|
||||
//2. Handle the animation transforms dependent on time
|
||||
|
@ -284,23 +552,289 @@ void NpcAnimation::runAnimation(float timepassed){
|
|||
time = startTime + (time - stopTime);
|
||||
}
|
||||
|
||||
handleAnimationTransforms();
|
||||
handleAnimationTransforms();
|
||||
|
||||
|
||||
std::vector<std::vector<Nif::NiTriShapeCopy>*>::iterator shapepartsiter = shapeparts.begin();
|
||||
std::vector<Ogre::Entity*>::iterator entitypartsiter = entityparts.begin();
|
||||
while(shapepartsiter != shapeparts.end())
|
||||
{
|
||||
vecRotPos.clear();
|
||||
std::vector<Nif::NiTriShapeCopy>* shapes = *shapepartsiter;
|
||||
Ogre::Entity* theentity = *entitypartsiter;
|
||||
|
||||
|
||||
handleShapes(shapes, theentity, base->getSkeleton());
|
||||
shapepartsiter++;
|
||||
entitypartsiter++;
|
||||
if(lBeastFoot.first)
|
||||
handleShapes(lBeastFoot.second, lBeastFoot.first, base->getSkeleton());
|
||||
if(rBeastFoot.first)
|
||||
handleShapes(rBeastFoot.second, rBeastFoot.first, base->getSkeleton());
|
||||
if(chest.first)
|
||||
handleShapes(chest.second, chest.first, base->getSkeleton());
|
||||
if(tail.first)
|
||||
handleShapes(tail.second, tail.first, base->getSkeleton());
|
||||
if(skirt.first){
|
||||
handleShapes(skirt.second, skirt.first, base->getSkeleton());
|
||||
}
|
||||
if(lhand.first)
|
||||
handleShapes(lhand.second, lhand.first, base->getSkeleton());
|
||||
if(rhand.first)
|
||||
handleShapes(rhand.second, rhand.first, base->getSkeleton());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void NpcAnimation::removeIndividualPart(int type){
|
||||
partpriorities[type] = 0;
|
||||
partslots[type] = -1;
|
||||
|
||||
if(type == ESM::PRT_Head && head){ //0
|
||||
base->detachObjectFromBone(head);
|
||||
head = 0;
|
||||
}
|
||||
|
||||
else if(type == ESM::PRT_Hair && hair){//1
|
||||
base->detachObjectFromBone(hair);
|
||||
hair = 0;
|
||||
}
|
||||
else if(type == ESM::PRT_Neck && neck){//2
|
||||
base->detachObjectFromBone(neck);
|
||||
neck = 0;
|
||||
}
|
||||
else if(type == ESM::PRT_Cuirass && chest.first){//3
|
||||
insert->detachObject(chest.first);
|
||||
chest = zero;
|
||||
}
|
||||
else if(type == ESM::PRT_Groin && groin){//4
|
||||
base->detachObjectFromBone(groin);
|
||||
groin = 0;
|
||||
}
|
||||
else if(type == ESM::PRT_Skirt && skirt.first){//5
|
||||
insert->detachObject(skirt.first);
|
||||
skirt = zero;
|
||||
}
|
||||
else if(type == ESM::PRT_RHand && rhand.first){//6
|
||||
insert->detachObject(rhand.first);
|
||||
rhand = zero;
|
||||
}
|
||||
else if(type == ESM::PRT_LHand && lhand.first){//7
|
||||
insert->detachObject(lhand.first);
|
||||
lhand = zero;
|
||||
}
|
||||
else if(type == ESM::PRT_RWrist && rWrist){//8
|
||||
base->detachObjectFromBone(rWrist);
|
||||
rWrist = 0;
|
||||
}
|
||||
else if(type == ESM::PRT_LWrist && lWrist){//9
|
||||
base->detachObjectFromBone(lWrist);
|
||||
lWrist = 0;
|
||||
}
|
||||
else if(type == ESM::PRT_Shield){//10
|
||||
|
||||
}
|
||||
else if(type == ESM::PRT_RForearm && rForearm){//11
|
||||
base->detachObjectFromBone(rForearm);
|
||||
rForearm = 0;
|
||||
}
|
||||
else if(type == ESM::PRT_LForearm && lForearm){//12
|
||||
base->detachObjectFromBone(lForearm);
|
||||
lForearm = 0;
|
||||
}
|
||||
else if(type == ESM::PRT_RUpperarm && rupperArm){//13
|
||||
base->detachObjectFromBone(rupperArm);
|
||||
rupperArm = 0;
|
||||
}
|
||||
else if(type == ESM::PRT_LUpperarm && lupperArm){//14
|
||||
base->detachObjectFromBone(lupperArm);
|
||||
lupperArm = 0;
|
||||
}
|
||||
else if(type == ESM::PRT_RFoot){ //15
|
||||
if(rfoot){
|
||||
base->detachObjectFromBone(rfoot);
|
||||
rfoot = 0;
|
||||
}
|
||||
else if(rBeastFoot.first){
|
||||
insert->detachObject(rBeastFoot.first);
|
||||
rBeastFoot = zero;
|
||||
}
|
||||
}
|
||||
else if(type == ESM::PRT_LFoot){ //16
|
||||
if(lfoot){
|
||||
base->detachObjectFromBone(lfoot);
|
||||
lfoot = 0;
|
||||
}
|
||||
else if(lBeastFoot.first){
|
||||
insert->detachObject(lBeastFoot.first);
|
||||
lBeastFoot = zero;
|
||||
}
|
||||
}
|
||||
else if(type == ESM::PRT_RAnkle && rAnkle){ //17
|
||||
base->detachObjectFromBone(rAnkle);
|
||||
rAnkle = 0;
|
||||
}
|
||||
else if(type == ESM::PRT_LAnkle && lAnkle){ //18
|
||||
base->detachObjectFromBone(lAnkle);
|
||||
lAnkle = 0;
|
||||
}
|
||||
else if(type == ESM::PRT_RKnee && rKnee){ //19
|
||||
base->detachObjectFromBone(rKnee);
|
||||
rKnee = 0;
|
||||
}
|
||||
else if(type == ESM::PRT_LKnee && lKnee){ //20
|
||||
base->detachObjectFromBone(lKnee);
|
||||
lKnee = 0;
|
||||
}
|
||||
else if(type == ESM::PRT_RLeg && rUpperLeg){ //21
|
||||
base->detachObjectFromBone(rUpperLeg);
|
||||
rUpperLeg = 0;
|
||||
}
|
||||
else if(type == ESM::PRT_LLeg && lUpperLeg){ //22
|
||||
base->detachObjectFromBone(lUpperLeg);
|
||||
lUpperLeg = 0;
|
||||
}
|
||||
else if(type == ESM::PRT_RPauldron && rclavicle){ //23
|
||||
base->detachObjectFromBone(rclavicle);
|
||||
rclavicle = 0;
|
||||
}
|
||||
else if(type == ESM::PRT_LPauldron && lclavicle){ //24
|
||||
base->detachObjectFromBone(lclavicle);
|
||||
lclavicle = 0;
|
||||
}
|
||||
else if(type == ESM::PRT_Weapon){ //25
|
||||
|
||||
}
|
||||
else if(type == ESM::PRT_Tail && tail.first){ //26
|
||||
insert->detachObject(tail.first);
|
||||
tail = zero;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
void NpcAnimation::reserveIndividualPart(int type, int group, int priority){
|
||||
if(priority > partpriorities[type]){
|
||||
removeIndividualPart(type);
|
||||
partpriorities[type] = priority;
|
||||
partslots[type] = group;
|
||||
}
|
||||
}
|
||||
|
||||
void NpcAnimation::removePartGroup(int group){
|
||||
for(int i = 0; i < 27; i++){
|
||||
if(partslots[i] == group){
|
||||
removeIndividualPart(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority, const std::string &mesh){
|
||||
if(priority > partpriorities[type]){
|
||||
removeIndividualPart(type);
|
||||
partslots[type] = group;
|
||||
partpriorities[type] = priority;
|
||||
switch(type){
|
||||
case ESM::PRT_Head: //0
|
||||
head = insertBoundedPart(mesh, "Head");
|
||||
break;
|
||||
case ESM::PRT_Hair: //1
|
||||
hair = insertBoundedPart(mesh, "Head");
|
||||
break;
|
||||
case ESM::PRT_Neck: //2
|
||||
neck = insertBoundedPart(mesh, "Neck");
|
||||
break;
|
||||
case ESM::PRT_Cuirass: //3
|
||||
chest = insertFreePart(mesh, ":\"");
|
||||
break;
|
||||
case ESM::PRT_Groin: //4
|
||||
groin = insertBoundedPart(mesh, "Groin");
|
||||
break;
|
||||
case ESM::PRT_Skirt: //5
|
||||
skirt = insertFreePart(mesh, ":|");
|
||||
break;
|
||||
case ESM::PRT_RHand: //6
|
||||
rhand = insertFreePart(mesh, ":?");
|
||||
break;
|
||||
case ESM::PRT_LHand: //7
|
||||
lhand = insertFreePart(mesh, ":>");
|
||||
break;
|
||||
case ESM::PRT_RWrist: //8
|
||||
rWrist = insertBoundedPart(mesh, "Right Wrist");
|
||||
break;
|
||||
case ESM::PRT_LWrist: //9
|
||||
lWrist = insertBoundedPart(mesh + "*|", "Left Wrist");
|
||||
break;
|
||||
case ESM::PRT_Shield: //10
|
||||
break;
|
||||
case ESM::PRT_RForearm: //11
|
||||
rForearm = insertBoundedPart(mesh, "Right Forearm");
|
||||
break;
|
||||
case ESM::PRT_LForearm: //12
|
||||
lForearm = insertBoundedPart(mesh + "*|", "Left Forearm");
|
||||
break;
|
||||
case ESM::PRT_RUpperarm: //13
|
||||
rupperArm = insertBoundedPart(mesh, "Right Upper Arm");
|
||||
break;
|
||||
case ESM::PRT_LUpperarm: //14
|
||||
lupperArm = insertBoundedPart(mesh + "*|", "Left Upper Arm");
|
||||
break;
|
||||
case ESM::PRT_RFoot: //15
|
||||
if(isBeast)
|
||||
rBeastFoot = insertFreePart(mesh, ":<");
|
||||
else
|
||||
rfoot = insertBoundedPart(mesh, "Right Foot");
|
||||
break;
|
||||
case ESM::PRT_LFoot: //16
|
||||
if(isBeast)
|
||||
lBeastFoot = insertFreePart(mesh, "::");
|
||||
else
|
||||
lfoot = insertBoundedPart(mesh + "*|", "Left Foot");
|
||||
break;
|
||||
|
||||
case ESM::PRT_RAnkle: //17
|
||||
rAnkle = insertBoundedPart(mesh , "Right Ankle");
|
||||
break;
|
||||
case ESM::PRT_LAnkle: //18
|
||||
lAnkle = insertBoundedPart(mesh + "*|", "Left Ankle");
|
||||
break;
|
||||
case ESM::PRT_RKnee: //19
|
||||
rKnee = insertBoundedPart(mesh , "Right Knee");
|
||||
break;
|
||||
case ESM::PRT_LKnee: //20
|
||||
lKnee = insertBoundedPart(mesh + "*|", "Left Knee");
|
||||
break;
|
||||
case ESM::PRT_RLeg: //21
|
||||
rUpperLeg = insertBoundedPart(mesh, "Right Upper Leg");
|
||||
break;
|
||||
case ESM::PRT_LLeg: //22
|
||||
lUpperLeg = insertBoundedPart(mesh + "*|", "Left Upper Leg");
|
||||
break;
|
||||
case ESM::PRT_RPauldron: //23
|
||||
rclavicle = insertBoundedPart(mesh , "Right Clavicle");
|
||||
break;
|
||||
case ESM::PRT_LPauldron: //24
|
||||
lclavicle = insertBoundedPart(mesh + "*|", "Left Clavicle");
|
||||
break;
|
||||
case ESM::PRT_Weapon: //25
|
||||
break;
|
||||
case ESM::PRT_Tail: //26
|
||||
tail = insertFreePart(mesh, ":*");
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void NpcAnimation::addPartGroup(int group, int priority, std::vector<ESM::PartReference>& parts){
|
||||
for(std::size_t i = 0; i < parts.size(); i++)
|
||||
{
|
||||
ESM::PartReference part = parts[i];
|
||||
|
||||
const ESM::BodyPart *bodypart = 0;
|
||||
if(isFemale)
|
||||
bodypart = mEnvironment.mWorld->getStore().bodyParts.search (part.female);
|
||||
if(!bodypart)
|
||||
bodypart = mEnvironment.mWorld->getStore().bodyParts.search (part.male);
|
||||
if(bodypart)
|
||||
addOrReplaceIndividualPart(part.part, group,priority,"meshes\\" + bodypart->model);
|
||||
else
|
||||
reserveIndividualPart(part.part, group, priority);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,24 +6,95 @@
|
|||
#include <components/nif/property.hpp>
|
||||
#include <components/nif/controller.hpp>
|
||||
#include <components/nif/extra.hpp>
|
||||
#include <utility>
|
||||
|
||||
#include "../mwworld/refdata.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/environment.hpp"
|
||||
#include "components/nifogre/ogre_nif_loader.hpp"
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
#include "../mwclass/npc.hpp"
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
#include "components/esm/loadarmo.hpp"
|
||||
|
||||
namespace MWRender{
|
||||
|
||||
class NpcAnimation: public Animation{
|
||||
private:
|
||||
MWWorld::InventoryStore& inv;
|
||||
int mStateID;
|
||||
//Free Parts
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> chest;
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> skirt;
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> lhand;
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> rhand;
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> tail;
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> lBeastFoot;
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> rBeastFoot;
|
||||
|
||||
int partslots[27]; //Each part slot is taken by clothing, armor, or is empty
|
||||
int partpriorities[27];
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> zero;
|
||||
|
||||
|
||||
|
||||
//Bounded Parts
|
||||
Ogre::Entity* lclavicle;
|
||||
Ogre::Entity* rclavicle;
|
||||
Ogre::Entity* rupperArm;
|
||||
Ogre::Entity* lupperArm;
|
||||
Ogre::Entity* rUpperLeg;
|
||||
Ogre::Entity* lUpperLeg;
|
||||
Ogre::Entity* lForearm;
|
||||
Ogre::Entity* rForearm;
|
||||
Ogre::Entity* lWrist;
|
||||
Ogre::Entity* rWrist;
|
||||
Ogre::Entity* rKnee;
|
||||
Ogre::Entity* lKnee;
|
||||
Ogre::Entity* neck;
|
||||
Ogre::Entity* rAnkle;
|
||||
Ogre::Entity* lAnkle;
|
||||
Ogre::Entity* groin;
|
||||
Ogre::Entity* lfoot;
|
||||
Ogre::Entity* rfoot;
|
||||
Ogre::Entity* hair;
|
||||
Ogre::Entity* head;
|
||||
|
||||
|
||||
Ogre::SceneNode* insert;
|
||||
bool isBeast;
|
||||
bool isFemale;
|
||||
std::string headModel;
|
||||
std::string hairModel;
|
||||
std::string npcName;
|
||||
std::string bodyRaceID;
|
||||
float timeToChange;
|
||||
MWWorld::ContainerStoreIterator robe;
|
||||
MWWorld::ContainerStoreIterator helmet;
|
||||
MWWorld::ContainerStoreIterator shirt;
|
||||
MWWorld::ContainerStoreIterator cuirass;
|
||||
MWWorld::ContainerStoreIterator greaves;
|
||||
MWWorld::ContainerStoreIterator leftpauldron;
|
||||
MWWorld::ContainerStoreIterator rightpauldron;
|
||||
MWWorld::ContainerStoreIterator boots;
|
||||
MWWorld::ContainerStoreIterator pants;
|
||||
MWWorld::ContainerStoreIterator leftglove;
|
||||
MWWorld::ContainerStoreIterator rightglove;
|
||||
MWWorld::ContainerStoreIterator skirtiter;
|
||||
|
||||
public:
|
||||
NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend);
|
||||
NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv);
|
||||
virtual ~NpcAnimation();
|
||||
Ogre::Entity* insertBoundedPart(const std::string &mesh, std::string bonename);
|
||||
void insertFreePart(const std::string &mesh, const std::string suffix, Ogre::SceneNode* insert);
|
||||
std::pair<Ogre::Entity*, std::vector<Nif::NiTriShapeCopy>*> insertFreePart(const std::string &mesh, const std::string suffix);
|
||||
virtual void runAnimation(float timepassed);
|
||||
void updateParts();
|
||||
void removeIndividualPart(int type);
|
||||
void reserveIndividualPart(int type, int group, int priority);
|
||||
|
||||
bool addOrReplaceIndividualPart(int type, int group, int priority, const std::string &mesh);
|
||||
void removePartGroup(int group);
|
||||
void addPartGroup(int group, int priority, std::vector<ESM::PartReference>& parts);
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -193,6 +193,8 @@ void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
|
|||
|
||||
sg->setVisibilityFlags(small ? RV_StaticsSmall : RV_Statics);
|
||||
|
||||
sg->setCastShadows(true);
|
||||
|
||||
sg->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main);
|
||||
|
||||
mRenderer.getScene()->destroyEntity(ent);
|
||||
|
|
|
@ -60,6 +60,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
|
|||
mBBNodeReal = mRendering->getScene()->getRootSceneNode()->createChildSceneNode();
|
||||
|
||||
mBBQueryTotal = mRendering->getScene()->createBillboardSet(1);
|
||||
mBBQueryTotal->setCastShadows(false);
|
||||
mBBQueryTotal->setDefaultDimensions(150, 150);
|
||||
mBBQueryTotal->createBillboard(Vector3::ZERO);
|
||||
mBBQueryTotal->setMaterialName("QueryTotalPixels");
|
||||
|
@ -67,6 +68,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
|
|||
mBBNodeReal->attachObject(mBBQueryTotal);
|
||||
|
||||
mBBQueryVisible = mRendering->getScene()->createBillboardSet(1);
|
||||
mBBQueryVisible->setCastShadows(false);
|
||||
mBBQueryVisible->setDefaultDimensions(150, 150);
|
||||
mBBQueryVisible->createBillboard(Vector3::ZERO);
|
||||
mBBQueryVisible->setMaterialName("QueryVisiblePixels");
|
||||
|
@ -75,6 +77,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod
|
|||
|
||||
mBBQuerySingleObject = mRendering->getScene()->createBillboardSet(1);
|
||||
/// \todo ideally this should occupy exactly 1 pixel on the screen
|
||||
mBBQuerySingleObject->setCastShadows(false);
|
||||
mBBQuerySingleObject->setDefaultDimensions(0.003, 0.003);
|
||||
mBBQuerySingleObject->createBillboard(Vector3::ZERO);
|
||||
mBBQuerySingleObject->setMaterialName("QueryVisiblePixels");
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
#include <components/esm/loadstat.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "shadows.hpp"
|
||||
#include "shaderhelper.hpp"
|
||||
#include "localmap.hpp"
|
||||
#include "water.hpp"
|
||||
|
||||
using namespace MWRender;
|
||||
using namespace Ogre;
|
||||
|
@ -21,11 +25,9 @@ using namespace Ogre;
|
|||
namespace MWRender {
|
||||
|
||||
RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment)
|
||||
:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0)
|
||||
:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0), mSunEnabled(0)
|
||||
{
|
||||
mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5);
|
||||
mTerrainManager = new TerrainManager(mRendering.getScene(),
|
||||
environment);
|
||||
|
||||
mWater = 0;
|
||||
|
||||
|
@ -54,6 +56,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
|
|||
const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities();
|
||||
if (caps->getNumMultiRenderTargets() < 2)
|
||||
Settings::Manager::setBool("shader", "Water", false);
|
||||
if (!caps->isShaderProfileSupported("fp40") && !caps->isShaderProfileSupported("ps_4_0"))
|
||||
Settings::Manager::setBool("enabled", "Shadows", false);
|
||||
|
||||
// note that the order is important here
|
||||
if (useMRT())
|
||||
|
@ -86,6 +90,12 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
|
|||
Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode();
|
||||
cameraPitchNode->attachObject(mRendering.getCamera());
|
||||
|
||||
mShadows = new Shadows(&mRendering);
|
||||
mShaderHelper = new ShaderHelper(this);
|
||||
|
||||
mTerrainManager = new TerrainManager(mRendering.getScene(), this,
|
||||
environment);
|
||||
|
||||
//mSkyManager = 0;
|
||||
mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera(), &environment);
|
||||
|
||||
|
@ -100,7 +110,6 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
|
|||
|
||||
RenderingManager::~RenderingManager ()
|
||||
{
|
||||
//TODO: destroy mSun?
|
||||
delete mPlayer;
|
||||
delete mSkyManager;
|
||||
delete mDebugging;
|
||||
|
@ -412,6 +421,7 @@ void RenderingManager::skipAnimation (const MWWorld::Ptr& ptr)
|
|||
|
||||
void RenderingManager::setSunColour(const Ogre::ColourValue& colour)
|
||||
{
|
||||
if (!mSunEnabled) return;
|
||||
mSun->setDiffuseColour(colour);
|
||||
mSun->setSpecularColour(colour);
|
||||
mTerrainManager->setDiffuse(colour);
|
||||
|
@ -425,12 +435,21 @@ void RenderingManager::setAmbientColour(const Ogre::ColourValue& colour)
|
|||
|
||||
void RenderingManager::sunEnable()
|
||||
{
|
||||
if (mSun) mSun->setVisible(true);
|
||||
// Don't disable the light, as the shaders assume the first light to be directional.
|
||||
//if (mSun) mSun->setVisible(true);
|
||||
mSunEnabled = true;
|
||||
}
|
||||
|
||||
void RenderingManager::sunDisable()
|
||||
{
|
||||
if (mSun) mSun->setVisible(false);
|
||||
// Don't disable the light, as the shaders assume the first light to be directional.
|
||||
//if (mSun) mSun->setVisible(false);
|
||||
mSunEnabled = false;
|
||||
if (mSun)
|
||||
{
|
||||
mSun->setDiffuseColour(ColourValue(0,0,0));
|
||||
mSun->setSpecularColour(ColourValue(0,0,0));
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingManager::setSunDirection(const Ogre::Vector3& direction)
|
||||
|
@ -463,11 +482,13 @@ void RenderingManager::preCellChange(MWWorld::Ptr::CellStore* cell)
|
|||
void RenderingManager::disableLights()
|
||||
{
|
||||
mObjects.disableLights();
|
||||
sunDisable();
|
||||
}
|
||||
|
||||
void RenderingManager::enableLights()
|
||||
{
|
||||
mObjects.enableLights();
|
||||
sunEnable();
|
||||
}
|
||||
|
||||
const bool RenderingManager::useMRT()
|
||||
|
@ -475,4 +496,9 @@ const bool RenderingManager::useMRT()
|
|||
return Settings::Manager::getBool("shader", "Water");
|
||||
}
|
||||
|
||||
Shadows* RenderingManager::getShadows()
|
||||
{
|
||||
return mShadows;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
#include "objects.hpp"
|
||||
#include "actors.hpp"
|
||||
#include "player.hpp"
|
||||
#include "water.hpp"
|
||||
#include "localmap.hpp"
|
||||
#include "occlusionquery.hpp"
|
||||
|
||||
namespace Ogre
|
||||
|
@ -45,7 +43,10 @@ namespace MWWorld
|
|||
namespace MWRender
|
||||
{
|
||||
|
||||
|
||||
class Shadows;
|
||||
class ShaderHelper;
|
||||
class LocalMap;
|
||||
class Water;
|
||||
|
||||
class RenderingManager: private RenderingInterface {
|
||||
|
||||
|
@ -114,6 +115,8 @@ class RenderingManager: private RenderingInterface {
|
|||
bool occlusionQuerySupported() { return mOcclusionQuery->supported(); };
|
||||
OcclusionQuery* getOcclusionQuery() { return mOcclusionQuery; };
|
||||
|
||||
Shadows* getShadows();
|
||||
|
||||
void setGlare(bool glare);
|
||||
void skyEnable ();
|
||||
void skyDisable ();
|
||||
|
@ -149,6 +152,8 @@ class RenderingManager: private RenderingInterface {
|
|||
|
||||
void setAmbientMode();
|
||||
|
||||
bool mSunEnabled;
|
||||
|
||||
SkyManager* mSkyManager;
|
||||
|
||||
OcclusionQuery* mOcclusionQuery;
|
||||
|
@ -180,6 +185,10 @@ class RenderingManager: private RenderingInterface {
|
|||
MWRender::Debugging *mDebugging;
|
||||
|
||||
MWRender::LocalMap* mLocalMap;
|
||||
|
||||
MWRender::Shadows* mShadows;
|
||||
|
||||
MWRender::ShaderHelper* mShaderHelper;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
308
apps/openmw/mwrender/shaderhelper.cpp
Normal file
308
apps/openmw/mwrender/shaderhelper.cpp
Normal file
|
@ -0,0 +1,308 @@
|
|||
#include "shaderhelper.hpp"
|
||||
#include "renderingmanager.hpp"
|
||||
#include "shadows.hpp"
|
||||
|
||||
#include <OgreHighLevelGpuProgramManager.h>
|
||||
#include <OgreHighLevelGpuProgram.h>
|
||||
#include <OgreGpuProgramParams.h>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
using namespace Ogre;
|
||||
using namespace MWRender;
|
||||
|
||||
ShaderHelper::ShaderHelper(RenderingManager* rend)
|
||||
{
|
||||
mRendering = rend;
|
||||
applyShaders();
|
||||
}
|
||||
|
||||
void ShaderHelper::applyShaders()
|
||||
{
|
||||
if (!Settings::Manager::getBool("shaders", "Objects")) return;
|
||||
|
||||
bool mrt = RenderingManager::useMRT();
|
||||
bool shadows = Settings::Manager::getBool("enabled", "Shadows");
|
||||
bool split = Settings::Manager::getBool("split", "Shadows");
|
||||
|
||||
// shader for normal rendering
|
||||
createShader(mrt, shadows, split, "main");
|
||||
|
||||
// fallback shader without mrt and without shadows
|
||||
// (useful for reflection and for minimap)
|
||||
createShader(false, false, false, "main_fallback");
|
||||
}
|
||||
|
||||
void ShaderHelper::createShader(const bool mrt, const bool shadows, const bool split, const std::string& name)
|
||||
{
|
||||
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
||||
|
||||
const int numsplits = 3;
|
||||
|
||||
// the number of lights to support.
|
||||
// when rendering an object, OGRE automatically picks the lights that are
|
||||
// closest to the object being rendered. unfortunately this mechanism does
|
||||
// not work perfectly for objects batched together (they will all use the same
|
||||
// lights). to work around this, we are simply pushing the maximum number
|
||||
// of lights here in order to minimize disappearing lights.
|
||||
int num_lights = Settings::Manager::getInt("num lights", "Objects");
|
||||
|
||||
{
|
||||
// vertex
|
||||
HighLevelGpuProgramPtr vertex;
|
||||
if (!mgr.getByName(name+"_vp").isNull())
|
||||
mgr.remove(name+"_vp");
|
||||
|
||||
vertex = mgr.createProgram(name+"_vp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
"cg", GPT_VERTEX_PROGRAM);
|
||||
vertex->setParameter("profiles", "vs_4_0 vs_2_x vp40 arbvp1");
|
||||
vertex->setParameter("entry_point", "main_vp");
|
||||
StringUtil::StrStreamType outStream;
|
||||
outStream <<
|
||||
"void main_vp( \n"
|
||||
" float4 position : POSITION, \n"
|
||||
" float4 normal : NORMAL, \n"
|
||||
" float4 colour : COLOR, \n"
|
||||
" in float2 uv : TEXCOORD0, \n"
|
||||
" out float2 oUV : TEXCOORD0, \n"
|
||||
" out float4 oPosition : POSITION, \n"
|
||||
" out float4 oPositionObjSpace : TEXCOORD1, \n"
|
||||
" out float4 oNormal : TEXCOORD2, \n"
|
||||
" out float oDepth : TEXCOORD3, \n"
|
||||
" out float4 oVertexColour : TEXCOORD4, \n";
|
||||
if (shadows && !split) outStream <<
|
||||
" out float4 oLightSpacePos0 : TEXCOORD5, \n"
|
||||
" uniform float4x4 worldMatrix, \n"
|
||||
" uniform float4x4 texViewProjMatrix0, \n";
|
||||
else
|
||||
{
|
||||
for (int i=0; i<numsplits; ++i)
|
||||
{
|
||||
outStream <<
|
||||
" out float4 oLightSpacePos"<<i<<" : TEXCOORD"<<i+5<<", \n"
|
||||
" uniform float4x4 texViewProjMatrix"<<i<<", \n";
|
||||
}
|
||||
outStream <<
|
||||
" uniform float4x4 worldMatrix, \n";
|
||||
}
|
||||
outStream <<
|
||||
" uniform float4x4 worldViewProj \n"
|
||||
") \n"
|
||||
"{ \n"
|
||||
" oVertexColour = colour; \n"
|
||||
" oUV = uv; \n"
|
||||
" oNormal = normal; \n"
|
||||
" oPosition = mul( worldViewProj, position ); \n"
|
||||
" oDepth = oPosition.z; \n"
|
||||
" oPositionObjSpace = position; \n";
|
||||
if (shadows && !split) outStream <<
|
||||
" oLightSpacePos0 = mul(texViewProjMatrix0, mul(worldMatrix, position)); \n";
|
||||
else
|
||||
{
|
||||
outStream <<
|
||||
" float4 wPos = mul(worldMatrix, position); \n";
|
||||
for (int i=0; i<numsplits; ++i)
|
||||
{
|
||||
outStream <<
|
||||
" oLightSpacePos"<<i<<" = mul(texViewProjMatrix"<<i<<", wPos); \n";
|
||||
}
|
||||
}
|
||||
outStream <<
|
||||
"}";
|
||||
vertex->setSource(outStream.str());
|
||||
vertex->load();
|
||||
vertex->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
||||
if (shadows)
|
||||
{
|
||||
vertex->getDefaultParameters()->setNamedAutoConstant("worldMatrix", GpuProgramParameters::ACT_WORLD_MATRIX);
|
||||
if (!split)
|
||||
vertex->getDefaultParameters()->setNamedAutoConstant("texViewProjMatrix0", GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, 0);
|
||||
else
|
||||
{
|
||||
for (int i=0; i<numsplits; ++i)
|
||||
{
|
||||
vertex->getDefaultParameters()->setNamedAutoConstant("texViewProjMatrix"+StringConverter::toString(i), GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// fragment
|
||||
HighLevelGpuProgramPtr fragment;
|
||||
if (!mgr.getByName(name+"_fp").isNull())
|
||||
mgr.remove(name+"_fp");
|
||||
|
||||
fragment = mgr.createProgram(name+"_fp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
"cg", GPT_FRAGMENT_PROGRAM);
|
||||
fragment->setParameter("profiles", "ps_4_0 ps_2_x fp40 arbfp1");
|
||||
fragment->setParameter("entry_point", "main_fp");
|
||||
StringUtil::StrStreamType outStream;
|
||||
|
||||
if (shadows) outStream <<
|
||||
"float depthShadow(sampler2D shadowMap, float4 shadowMapPos, float2 offset) \n"
|
||||
"{ \n"
|
||||
" shadowMapPos /= shadowMapPos.w; \n"
|
||||
" float3 o = float3(offset.xy, -offset.x) * 0.3f; \n"
|
||||
" float c = (shadowMapPos.z <= tex2D(shadowMap, shadowMapPos.xy - o.xy).r) ? 1 : 0; // top left \n"
|
||||
" c += (shadowMapPos.z <= tex2D(shadowMap, shadowMapPos.xy + o.xy).r) ? 1 : 0; // bottom right \n"
|
||||
" c += (shadowMapPos.z <= tex2D(shadowMap, shadowMapPos.xy + o.zy).r) ? 1 : 0; // bottom left \n"
|
||||
" c += (shadowMapPos.z <= tex2D(shadowMap, shadowMapPos.xy - o.zy).r) ? 1 : 0; // top right \n"
|
||||
" return c / 4; \n"
|
||||
"} \n";
|
||||
|
||||
outStream <<
|
||||
"void main_fp( \n"
|
||||
" in float2 uv : TEXCOORD0, \n"
|
||||
" out float4 oColor : COLOR, \n"
|
||||
" uniform sampler2D texture : register(s0), \n"
|
||||
" float4 positionObjSpace : TEXCOORD1, \n"
|
||||
" float4 normal : TEXCOORD2, \n"
|
||||
" float iDepth : TEXCOORD3, \n"
|
||||
" float4 vertexColour : TEXCOORD4, \n"
|
||||
" uniform float4 fogColour, \n"
|
||||
" uniform float4 fogParams, \n";
|
||||
|
||||
if (shadows) outStream <<
|
||||
" uniform float4 shadowFar_fadeStart, \n";
|
||||
|
||||
if (shadows && !split) outStream <<
|
||||
" uniform sampler2D shadowMap : register(s1), \n"
|
||||
" float4 lightSpacePos0 : TEXCOORD5, \n"
|
||||
" uniform float4 invShadowmapSize0, \n";
|
||||
else
|
||||
{
|
||||
outStream <<
|
||||
" uniform float4 pssmSplitPoints, \n";
|
||||
for (int i=0; i<numsplits; ++i)
|
||||
{
|
||||
outStream <<
|
||||
" uniform sampler2D shadowMap"<<i<<" : register(s"<<i+1<<"), \n"
|
||||
" float4 lightSpacePos"<<i<<" : TEXCOORD"<<i+5<<", \n"
|
||||
" uniform float4 invShadowmapSize"<<i<<", \n";
|
||||
}
|
||||
}
|
||||
|
||||
if (mrt) outStream <<
|
||||
" out float4 oColor1 : COLOR1, \n"
|
||||
" uniform float far, \n";
|
||||
|
||||
for (int i=0; i<num_lights; ++i)
|
||||
{
|
||||
outStream <<
|
||||
" uniform float4 lightDiffuse"<<i<<", \n"
|
||||
" uniform float4 lightPositionObjSpace"<<i<<", \n"
|
||||
" uniform float4 lightAttenuation"<<i<<", \n";
|
||||
}
|
||||
outStream <<
|
||||
" uniform float4 lightAmbient, \n"
|
||||
" uniform float4 ambient, \n"
|
||||
" uniform float4 diffuse, \n"
|
||||
" uniform float4 emissive \n"
|
||||
") \n"
|
||||
"{ \n"
|
||||
" float4 tex = tex2D(texture, uv); \n"
|
||||
" float d; \n"
|
||||
" float attn; \n"
|
||||
" float3 lightDir; \n"
|
||||
" float3 lightColour = float3(0, 0, 0); \n";
|
||||
|
||||
for (int i=0; i<num_lights; ++i)
|
||||
{
|
||||
outStream <<
|
||||
" lightDir = lightPositionObjSpace"<<i<<".xyz - (positionObjSpace.xyz * lightPositionObjSpace"<<i<<".w); \n"
|
||||
|
||||
// pre-multiply light color with attenuation factor
|
||||
" d = length( lightDir ); \n"
|
||||
" attn = ( 1.0 / (( lightAttenuation"<<i<<".y ) + ( lightAttenuation"<<i<<".z * d ) + ( lightAttenuation"<<i<<".w * d * d ))); \n"
|
||||
" lightDiffuse"<<i<<" *= attn; \n";
|
||||
|
||||
if (i == 0 && shadows)
|
||||
{
|
||||
outStream <<
|
||||
" float shadow; \n";
|
||||
if (!split) outStream <<
|
||||
" shadow = depthShadow(shadowMap, lightSpacePos0, invShadowmapSize0.xy); \n";
|
||||
else
|
||||
{
|
||||
for (int j=0; j<numsplits; ++j)
|
||||
{
|
||||
std::string channel;
|
||||
if (j==0) channel = "x";
|
||||
else if (j==1) channel = "y";
|
||||
else if (j==2) channel = "z";
|
||||
|
||||
if (j==0)
|
||||
outStream << " if (iDepth <= pssmSplitPoints." << channel << ") \n";
|
||||
else if (j < numsplits - 1)
|
||||
outStream << " else if (iDepth <= pssmSplitPoints." << channel << ") \n";
|
||||
else
|
||||
outStream << " else \n";
|
||||
|
||||
outStream <<
|
||||
" { \n"
|
||||
" shadow = depthShadow(shadowMap" << j << ", lightSpacePos" << j << ", invShadowmapSize" << j << ".xy); \n"
|
||||
" } \n";
|
||||
}
|
||||
}
|
||||
outStream <<
|
||||
" float fadeRange = shadowFar_fadeStart.x - shadowFar_fadeStart.y; \n"
|
||||
" float fade = 1-((iDepth - shadowFar_fadeStart.y) / fadeRange); \n"
|
||||
" shadow = (iDepth > shadowFar_fadeStart.x) ? 1 : ((iDepth > shadowFar_fadeStart.y) ? 1-((1-shadow)*fade) : shadow); \n"
|
||||
" lightColour.xyz += shadow * lit(dot(normalize(lightDir), normalize(normal)), 0, 0).y * lightDiffuse"<<i<<".xyz;\n";
|
||||
}
|
||||
else outStream <<
|
||||
" lightColour.xyz += lit(dot(normalize(lightDir), normalize(normal)), 0, 0).y * lightDiffuse"<<i<<".xyz;\n";
|
||||
}
|
||||
|
||||
outStream <<
|
||||
" float3 lightingFinal = lightColour.xyz * diffuse.xyz * vertexColour.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n"
|
||||
" float fogValue = saturate((iDepth - fogParams.y) * fogParams.w); \n"
|
||||
" oColor.xyz = lerp(lightingFinal * tex.xyz, fogColour.xyz, fogValue); \n"
|
||||
" oColor.a = tex.a * diffuse.a * vertexColour.a; \n";
|
||||
|
||||
if (mrt) outStream <<
|
||||
" oColor1 = float4(iDepth / far, 0, 0, (oColor.a == 1)); \n"; // only write to MRT if alpha is 1
|
||||
|
||||
outStream <<
|
||||
"}";
|
||||
fragment->setSource(outStream.str());
|
||||
fragment->load();
|
||||
|
||||
for (int i=0; i<num_lights; ++i)
|
||||
{
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightPositionObjSpace"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, i);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightDiffuse"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, i);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightAttenuation"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_ATTENUATION, i);
|
||||
}
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_SURFACE_AMBIENT_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightAmbient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
|
||||
|
||||
if (shadows)
|
||||
{
|
||||
fragment->getDefaultParameters()->setNamedConstant("shadowFar_fadeStart", Vector4(mRendering->getShadows()->getShadowFar(), mRendering->getShadows()->getFadeStart()*mRendering->getShadows()->getShadowFar(), 0, 0));
|
||||
for (int i=0; i < (split ? numsplits : 1); ++i)
|
||||
{
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("invShadowmapSize" + StringConverter::toString(i), GpuProgramParameters::ACT_INVERSE_TEXTURE_SIZE, i+1);
|
||||
}
|
||||
if (split)
|
||||
{
|
||||
Vector4 splitPoints;
|
||||
const PSSMShadowCameraSetup::SplitPointList& splitPointList = mRendering->getShadows()->getPSSMSetup()->getSplitPoints();
|
||||
// Populate from split point 1, not 0, since split 0 isn't useful (usually 0)
|
||||
for (int i = 1; i < numsplits; ++i)
|
||||
{
|
||||
splitPoints[i-1] = splitPointList[i];
|
||||
}
|
||||
fragment->getDefaultParameters()->setNamedConstant("pssmSplitPoints", splitPoints);
|
||||
}
|
||||
}
|
||||
|
||||
if (mrt)
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("far", GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
|
||||
}
|
||||
}
|
29
apps/openmw/mwrender/shaderhelper.hpp
Normal file
29
apps/openmw/mwrender/shaderhelper.hpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef GAME_SHADERHELPER_H
|
||||
#define GAME_SHADERHELPER_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class RenderingManager;
|
||||
|
||||
///
|
||||
/// \brief manages the main shader
|
||||
///
|
||||
class ShaderHelper
|
||||
{
|
||||
public:
|
||||
ShaderHelper(RenderingManager* rend);
|
||||
|
||||
void applyShaders();
|
||||
///< apply new settings
|
||||
|
||||
private:
|
||||
RenderingManager* mRendering;
|
||||
|
||||
void createShader(const bool mrt, const bool shadows, const bool split, const std::string& name);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
173
apps/openmw/mwrender/shadows.cpp
Normal file
173
apps/openmw/mwrender/shadows.cpp
Normal file
|
@ -0,0 +1,173 @@
|
|||
#include "shadows.hpp"
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
|
||||
#include <OgreSceneManager.h>
|
||||
#include <OgreColourValue.h>
|
||||
#include <OgreShadowCameraSetupLiSPSM.h>
|
||||
#include <OgreShadowCameraSetupPSSM.h>
|
||||
#include <OgreHardwarePixelBuffer.h>
|
||||
|
||||
#include <OgreOverlayContainer.h>
|
||||
#include <OgreOverlayManager.h>
|
||||
|
||||
#include "renderconst.hpp"
|
||||
|
||||
using namespace Ogre;
|
||||
using namespace MWRender;
|
||||
|
||||
Shadows::Shadows(OEngine::Render::OgreRenderer* rend) :
|
||||
mShadowFar(1000), mFadeStart(0.9)
|
||||
{
|
||||
mRendering = rend;
|
||||
mSceneMgr = mRendering->getScene();
|
||||
recreate();
|
||||
}
|
||||
|
||||
void Shadows::recreate()
|
||||
{
|
||||
bool enabled = Settings::Manager::getBool("enabled", "Shadows");
|
||||
|
||||
// Split shadow maps are currently disabled because the terrain cannot cope with them
|
||||
// (Too many texture units) Solution would be a multi-pass terrain material
|
||||
bool split = Settings::Manager::getBool("split", "Shadows");
|
||||
//const bool split = false;
|
||||
|
||||
if (!enabled)
|
||||
{
|
||||
mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE);
|
||||
return;
|
||||
}
|
||||
|
||||
int texsize = Settings::Manager::getInt("texture size", "Shadows");
|
||||
mSceneMgr->setShadowTextureSize(texsize);
|
||||
|
||||
mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE_INTEGRATED);
|
||||
|
||||
// no point light shadows, i'm afraid. might revisit this with Deferred Shading
|
||||
mSceneMgr->setShadowTextureCountPerLightType(Light::LT_POINT, 0);
|
||||
|
||||
mSceneMgr->setShadowTextureCountPerLightType(Light::LT_DIRECTIONAL, split ? 3 : 1);
|
||||
mSceneMgr->setShadowTextureCount(split ? 3 : 1);
|
||||
|
||||
mSceneMgr->setShadowTextureSelfShadow(true);
|
||||
mSceneMgr->setShadowCasterRenderBackFaces(true);
|
||||
mSceneMgr->setShadowTextureCasterMaterial("depth_shadow_caster");
|
||||
mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT32_R);
|
||||
mSceneMgr->setShadowDirectionalLightExtrusionDistance(1000000);
|
||||
|
||||
mShadowFar = split ? Settings::Manager::getInt("split shadow distance", "Shadows") : Settings::Manager::getInt("shadow distance", "Shadows");
|
||||
mSceneMgr->setShadowFarDistance(mShadowFar);
|
||||
|
||||
mFadeStart = Settings::Manager::getFloat("fade start", "Shadows");
|
||||
|
||||
ShadowCameraSetupPtr shadowCameraSetup;
|
||||
if (split)
|
||||
{
|
||||
mPSSMSetup = new PSSMShadowCameraSetup();
|
||||
mPSSMSetup->setSplitPadding(5);
|
||||
mPSSMSetup->calculateSplitPoints(3, mRendering->getCamera()->getNearClipDistance(), mShadowFar);
|
||||
|
||||
const Real adjustFactors[3] = {64, 64, 64};
|
||||
for (int i=0; i < 3; ++i)
|
||||
{
|
||||
mPSSMSetup->setOptimalAdjustFactor(i, adjustFactors[i]);
|
||||
/*if (i==0)
|
||||
mSceneMgr->setShadowTextureConfig(i, texsize, texsize, Ogre::PF_FLOAT32_R);
|
||||
else if (i ==1)
|
||||
mSceneMgr->setShadowTextureConfig(i, texsize/2, texsize/2, Ogre::PF_FLOAT32_R);
|
||||
else if (i ==2)
|
||||
mSceneMgr->setShadowTextureConfig(i, texsize/4, texsize/4, Ogre::PF_FLOAT32_R);*/
|
||||
}
|
||||
|
||||
shadowCameraSetup = ShadowCameraSetupPtr(mPSSMSetup);
|
||||
}
|
||||
else
|
||||
{
|
||||
LiSPSMShadowCameraSetup* lispsmSetup = new LiSPSMShadowCameraSetup();
|
||||
lispsmSetup->setOptimalAdjustFactor(2);
|
||||
//lispsmSetup->setCameraLightDirectionThreshold(Degree(0));
|
||||
//lispsmSetup->setUseAggressiveFocusRegion(false);
|
||||
shadowCameraSetup = ShadowCameraSetupPtr(lispsmSetup);
|
||||
}
|
||||
mSceneMgr->setShadowCameraSetup(shadowCameraSetup);
|
||||
|
||||
// Set visibility mask for the shadow render textures
|
||||
int visibilityMask = RV_Actors * Settings::Manager::getBool("actor shadows", "Shadows")
|
||||
+ (RV_Statics + RV_StaticsSmall) * Settings::Manager::getBool("statics shadows", "Shadows")
|
||||
+ RV_Misc * Settings::Manager::getBool("misc shadows", "Shadows");
|
||||
|
||||
for (int i = 0; i < (split ? 3 : 1); ++i)
|
||||
{
|
||||
TexturePtr shadowTexture = mSceneMgr->getShadowTexture(i);
|
||||
Viewport* vp = shadowTexture->getBuffer()->getRenderTarget()->getViewport(0);
|
||||
vp->setVisibilityMask(visibilityMask);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// --------------------------- Debug overlays to display the content of shadow maps -----------------------------------
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
OverlayManager& mgr = OverlayManager::getSingleton();
|
||||
Overlay* overlay;
|
||||
|
||||
// destroy if already exists
|
||||
if (overlay = mgr.getByName("DebugOverlay"))
|
||||
mgr.destroy(overlay);
|
||||
|
||||
overlay = mgr.create("DebugOverlay");
|
||||
for (size_t i = 0; i < (split ? 3 : 1); ++i) {
|
||||
TexturePtr tex = mRendering->getScene()->getShadowTexture(i);
|
||||
|
||||
// Set up a debug panel to display the shadow
|
||||
|
||||
if (MaterialManager::getSingleton().resourceExists("Ogre/DebugTexture" + StringConverter::toString(i)))
|
||||
MaterialManager::getSingleton().remove("Ogre/DebugTexture" + StringConverter::toString(i));
|
||||
MaterialPtr debugMat = MaterialManager::getSingleton().create(
|
||||
"Ogre/DebugTexture" + StringConverter::toString(i),
|
||||
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||
|
||||
debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
|
||||
TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(tex->getName());
|
||||
t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
|
||||
|
||||
OverlayContainer* debugPanel;
|
||||
|
||||
// destroy container if exists
|
||||
try
|
||||
{
|
||||
if (debugPanel =
|
||||
static_cast<OverlayContainer*>(
|
||||
mgr.getOverlayElement("Ogre/DebugTexPanel" + StringConverter::toString(i)
|
||||
)))
|
||||
mgr.destroyOverlayElement(debugPanel);
|
||||
}
|
||||
catch (Ogre::Exception&) {}
|
||||
|
||||
debugPanel = (OverlayContainer*)
|
||||
(OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/DebugTexPanel" + StringConverter::toString(i)));
|
||||
debugPanel->_setPosition(0.8, i*0.25);
|
||||
debugPanel->_setDimensions(0.2, 0.24);
|
||||
debugPanel->setMaterialName(debugMat->getName());
|
||||
debugPanel->show();
|
||||
overlay->add2D(debugPanel);
|
||||
overlay->show();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
PSSMShadowCameraSetup* Shadows::getPSSMSetup()
|
||||
{
|
||||
return mPSSMSetup;
|
||||
}
|
||||
|
||||
float Shadows::getShadowFar() const
|
||||
{
|
||||
return mShadowFar;
|
||||
}
|
||||
|
||||
float Shadows::getFadeStart() const
|
||||
{
|
||||
return mFadeStart;
|
||||
}
|
39
apps/openmw/mwrender/shadows.hpp
Normal file
39
apps/openmw/mwrender/shadows.hpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
#ifndef GAME_SHADOWS_H
|
||||
#define GAME_SHADOWS_H
|
||||
|
||||
// forward declares
|
||||
namespace Ogre
|
||||
{
|
||||
class SceneManager;
|
||||
class PSSMShadowCameraSetup;
|
||||
}
|
||||
namespace OEngine{
|
||||
namespace Render{
|
||||
class OgreRenderer;
|
||||
}
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class Shadows
|
||||
{
|
||||
public:
|
||||
Shadows(OEngine::Render::OgreRenderer* rend);
|
||||
|
||||
void recreate();
|
||||
|
||||
Ogre::PSSMShadowCameraSetup* getPSSMSetup();
|
||||
float getShadowFar() const;
|
||||
float getFadeStart() const;
|
||||
|
||||
protected:
|
||||
OEngine::Render::OgreRenderer* mRendering;
|
||||
Ogre::SceneManager* mSceneMgr;
|
||||
|
||||
Ogre::PSSMShadowCameraSetup* mPSSMSetup;
|
||||
float mShadowFar;
|
||||
float mFadeStart;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -102,6 +102,7 @@ void BillboardObject::init(const String& textureName,
|
|||
mNode->setPosition(finalPosition);
|
||||
mNode->attachObject(mBBSet);
|
||||
mBBSet->createBillboard(0,0,0);
|
||||
mBBSet->setCastShadows(false);
|
||||
|
||||
mMaterial = MaterialManager::getSingleton().create("BillboardMaterial"+StringConverter::toString(bodyCount), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||
mMaterial->removeAllTechniques();
|
||||
|
@ -450,6 +451,7 @@ void SkyManager::create()
|
|||
Entity* night1_ent = mSceneMgr->createEntity("meshes\\sky_night_01.nif");
|
||||
night1_ent->setRenderQueueGroup(RQG_SkiesEarly+1);
|
||||
night1_ent->setVisibilityFlags(RV_Sky);
|
||||
night1_ent->setCastShadows(false);
|
||||
|
||||
mAtmosphereNight = mRootNode->createChildSceneNode();
|
||||
mAtmosphereNight->attachObject(night1_ent);
|
||||
|
@ -525,6 +527,7 @@ void SkyManager::create()
|
|||
// Atmosphere (day)
|
||||
mesh = NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif");
|
||||
Entity* atmosphere_ent = mSceneMgr->createEntity("meshes\\sky_atmosphere.nif");
|
||||
atmosphere_ent->setCastShadows(false);
|
||||
|
||||
ModVertexAlpha(atmosphere_ent, 0);
|
||||
|
||||
|
@ -596,6 +599,7 @@ void SkyManager::create()
|
|||
SceneNode* clouds_node = mRootNode->createChildSceneNode();
|
||||
clouds_node->attachObject(clouds_ent);
|
||||
mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial();
|
||||
clouds_ent->setCastShadows(false);
|
||||
|
||||
// Clouds vertex shader
|
||||
HighLevelGpuProgramPtr vshader2 = mgr.createProgram("Clouds_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
|
@ -677,6 +681,8 @@ void SkyManager::create()
|
|||
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("textures\\tx_sky_cloudy.dds");
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("");
|
||||
|
||||
mCreated = true;
|
||||
|
@ -766,12 +772,14 @@ void SkyManager::disable()
|
|||
|
||||
void SkyManager::setMoonColour (bool red)
|
||||
{
|
||||
if (!mCreated) return;
|
||||
mSecunda->setColour( red ? ColourValue(1.0, 0.0784, 0.0784)
|
||||
: ColourValue(1.0, 1.0, 1.0));
|
||||
}
|
||||
|
||||
void SkyManager::setCloudsOpacity(float opacity)
|
||||
{
|
||||
if (!mCreated) return;
|
||||
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("opacity", Real(opacity));
|
||||
}
|
||||
|
||||
|
@ -927,11 +935,13 @@ void SkyManager::setThunder(const float factor)
|
|||
|
||||
void SkyManager::setMasserFade(const float fade)
|
||||
{
|
||||
if (!mCreated) return;
|
||||
mMasser->setVisibility(fade);
|
||||
}
|
||||
|
||||
void SkyManager::setSecundaFade(const float fade)
|
||||
{
|
||||
if (!mCreated) return;
|
||||
mSecunda->setVisibility(fade);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
#include "terrainmaterial.hpp"
|
||||
#include "terrain.hpp"
|
||||
#include "renderconst.hpp"
|
||||
|
||||
#include "shadows.hpp"
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
using namespace Ogre;
|
||||
|
||||
|
@ -16,8 +17,8 @@ namespace MWRender
|
|||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
||||
TerrainManager::TerrainManager(Ogre::SceneManager* mgr, const MWWorld::Environment& evn) :
|
||||
mEnvironment(evn), mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize))
|
||||
TerrainManager::TerrainManager(Ogre::SceneManager* mgr, RenderingManager* rend, const MWWorld::Environment& evn) :
|
||||
mEnvironment(evn), mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize)), mRendering(rend)
|
||||
{
|
||||
|
||||
TerrainMaterialGeneratorPtr matGen;
|
||||
|
@ -48,9 +49,19 @@ namespace MWRender
|
|||
mActiveProfile->setLayerSpecularMappingEnabled(false);
|
||||
mActiveProfile->setLayerNormalMappingEnabled(false);
|
||||
mActiveProfile->setLayerParallaxMappingEnabled(false);
|
||||
mActiveProfile->setReceiveDynamicShadowsEnabled(false);
|
||||
|
||||
//composite maps lead to a drastic reduction in loading time so are
|
||||
bool shadows = Settings::Manager::getBool("enabled", "Shadows");
|
||||
mActiveProfile->setReceiveDynamicShadowsEnabled(shadows);
|
||||
mActiveProfile->setReceiveDynamicShadowsDepth(shadows);
|
||||
if (Settings::Manager::getBool("split", "Shadows"))
|
||||
mActiveProfile->setReceiveDynamicShadowsPSSM(mRendering->getShadows()->getPSSMSetup());
|
||||
else
|
||||
mActiveProfile->setReceiveDynamicShadowsPSSM(0);
|
||||
|
||||
mActiveProfile->setShadowFar(mRendering->getShadows()->getShadowFar());
|
||||
mActiveProfile->setShadowFadeStart(mRendering->getShadows()->getFadeStart());
|
||||
|
||||
//composite maps lead to a drastic increase in loading time so are
|
||||
//disabled
|
||||
mActiveProfile->setCompositeMapEnabled(false);
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace MWRender{
|
|||
*/
|
||||
class TerrainManager{
|
||||
public:
|
||||
TerrainManager(Ogre::SceneManager* mgr, const MWWorld::Environment& env);
|
||||
TerrainManager(Ogre::SceneManager* mgr, RenderingManager* rend, const MWWorld::Environment& env);
|
||||
virtual ~TerrainManager();
|
||||
|
||||
void setDiffuse(const Ogre::ColourValue& diffuse);
|
||||
|
@ -37,6 +37,7 @@ namespace MWRender{
|
|||
Ogre::TerrainGroup mTerrainGroup;
|
||||
|
||||
const MWWorld::Environment& mEnvironment;
|
||||
RenderingManager* mRendering;
|
||||
|
||||
Ogre::TerrainMaterialGeneratorB::SM2Profile* mActiveProfile;
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@ THE SOFTWARE.
|
|||
#include <components/settings/settings.hpp>
|
||||
#include "renderingmanager.hpp"
|
||||
|
||||
#undef far
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
//---------------------------------------------------------------------
|
||||
|
@ -86,6 +88,7 @@ namespace Ogre
|
|||
, mPSSM(0)
|
||||
, mDepthShadows(false)
|
||||
, mLowLodShadows(false)
|
||||
, mShadowFar(1300)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -102,6 +105,24 @@ namespace Ogre
|
|||
terrain->_setLightMapRequired(mLightmapEnabled, true);
|
||||
terrain->_setCompositeMapRequired(mCompositeMapEnabled);
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
void TerrainMaterialGeneratorB::SM2Profile::setShadowFar(float far)
|
||||
{
|
||||
if (mShadowFar != far)
|
||||
{
|
||||
mShadowFar = far;
|
||||
mParent->_markChanged();
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
void TerrainMaterialGeneratorB::SM2Profile::setShadowFadeStart(float fadestart)
|
||||
{
|
||||
if (mShadowFadeStart != fadestart)
|
||||
{
|
||||
mShadowFadeStart = fadestart;
|
||||
mParent->_markChanged();
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
void TerrainMaterialGeneratorB::SM2Profile::setLayerNormalMappingEnabled(bool enabled)
|
||||
{
|
||||
|
@ -462,6 +483,7 @@ namespace Ogre
|
|||
|
||||
StringUtil::StrStreamType sourceStr;
|
||||
generateFragmentProgramSource(prof, terrain, tt, sourceStr);
|
||||
|
||||
ret->setSource(sourceStr.str());
|
||||
ret->load();
|
||||
defaultFpParams(prof, terrain, tt, ret);
|
||||
|
@ -518,7 +540,6 @@ namespace Ogre
|
|||
params->setNamedAutoConstant("viewProjMatrix", GpuProgramParameters::ACT_VIEWPROJ_MATRIX);
|
||||
params->setNamedAutoConstant("lodMorph", GpuProgramParameters::ACT_CUSTOM,
|
||||
Terrain::LOD_MORPH_CUSTOM_PARAM);
|
||||
params->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
|
||||
|
||||
if (prof->isShadowingEnabled(tt, terrain))
|
||||
{
|
||||
|
@ -533,8 +554,8 @@ namespace Ogre
|
|||
GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, i);
|
||||
if (prof->getReceiveDynamicShadowsDepth())
|
||||
{
|
||||
params->setNamedAutoConstant("depthRange" + StringConverter::toString(i),
|
||||
GpuProgramParameters::ACT_SHADOW_SCENE_DEPTH_RANGE, i);
|
||||
//params->setNamedAutoConstant("depthRange" + StringConverter::toString(i),
|
||||
//GpuProgramParameters::ACT_SHADOW_SCENE_DEPTH_RANGE, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -554,7 +575,7 @@ namespace Ogre
|
|||
{
|
||||
params->setNamedAutoConstant("lightPosObjSpace"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, i);
|
||||
params->setNamedAutoConstant("lightDiffuseColour"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, i);
|
||||
if (prof->getNumberOfLightsSupported() > 1)
|
||||
if (i > 0)
|
||||
params->setNamedAutoConstant("lightAttenuation"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_ATTENUATION, i);
|
||||
//params->setNamedAutoConstant("lightSpecularColour"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR, i);
|
||||
}
|
||||
|
@ -564,9 +585,11 @@ namespace Ogre
|
|||
|
||||
params->setNamedAutoConstant("eyePosObjSpace", GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE);
|
||||
params->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR);
|
||||
params->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
|
||||
|
||||
if (prof->isShadowingEnabled(tt, terrain))
|
||||
{
|
||||
params->setNamedConstant("shadowFar_fadeStart", Vector4(prof->mShadowFar, prof->mShadowFadeStart * prof->mShadowFar, 0, 0));
|
||||
uint numTextures = 1;
|
||||
if (prof->getReceiveDynamicShadowsPSSM())
|
||||
{
|
||||
|
@ -732,7 +755,7 @@ namespace Ogre
|
|||
ret->unload();
|
||||
}
|
||||
|
||||
ret->setParameter("profiles", "vs_3_0 vs_2_0 arbvp1");
|
||||
ret->setParameter("profiles", "vs_3_0 vs_2_0 vp40 arbvp1");
|
||||
ret->setParameter("entry_point", "main_vp");
|
||||
|
||||
return ret;
|
||||
|
@ -794,7 +817,7 @@ namespace Ogre
|
|||
|
||||
uint texCoordSet = 1;
|
||||
outStream <<
|
||||
", out float4 oUVMisc : TEXCOORD" << texCoordSet++ <<" // xy = uv, z = camDepth\n";
|
||||
", out float4 oUVMisc : COLOR0 // xy = uv, z = camDepth\n";
|
||||
|
||||
// layer UV's premultiplied, packed as xy/zw
|
||||
uint numUVSets = numLayers / 2;
|
||||
|
@ -814,14 +837,6 @@ namespace Ogre
|
|||
outStream << ", out float2 lodInfo : TEXCOORD" << texCoordSet++ << "\n";
|
||||
}
|
||||
|
||||
bool fog = terrain->getSceneManager()->getFogMode() != FOG_NONE && tt != RENDER_COMPOSITE_MAP;
|
||||
if (fog)
|
||||
{
|
||||
outStream <<
|
||||
", uniform float4 fogParams\n"
|
||||
", out float fogVal : COLOR\n";
|
||||
}
|
||||
|
||||
if (prof->isShadowingEnabled(tt, terrain))
|
||||
{
|
||||
texCoordSet = generateVpDynamicShadowsParams(texCoordSet, prof, terrain, tt, outStream);
|
||||
|
@ -831,7 +846,7 @@ namespace Ogre
|
|||
if (texCoordSet > 8)
|
||||
{
|
||||
OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
|
||||
"Requested options require too many texture coordinate sets! Try reducing the number of layers.",
|
||||
"Requested options require too many texture coordinate sets! Try reducing the number of layers. requested: " + StringConverter::toString(texCoordSet),
|
||||
__FUNCTION__);
|
||||
}
|
||||
|
||||
|
@ -921,7 +936,7 @@ namespace Ogre
|
|||
|
||||
uint texCoordSet = 1;
|
||||
outStream <<
|
||||
"float4 uvMisc : TEXCOORD" << texCoordSet++ << ",\n";
|
||||
"float4 uvMisc : COLOR0,\n";
|
||||
|
||||
// UV's premultiplied, packed as xy/zw
|
||||
uint maxLayers = prof->getMaxLayers(terrain);
|
||||
|
@ -948,8 +963,8 @@ namespace Ogre
|
|||
if (fog)
|
||||
{
|
||||
outStream <<
|
||||
"uniform float3 fogColour, \n"
|
||||
"float fogVal : COLOR,\n";
|
||||
"uniform float4 fogParams, \n"
|
||||
"uniform float3 fogColour, \n";
|
||||
}
|
||||
|
||||
uint currentSamplerIdx = 0;
|
||||
|
@ -968,7 +983,7 @@ namespace Ogre
|
|||
//"uniform float3 lightSpecularColour"<<i<<",\n"
|
||||
;
|
||||
|
||||
if (prof->getNumberOfLightsSupported() > 1)
|
||||
if (i > 0)
|
||||
outStream <<
|
||||
"uniform float4 lightAttenuation"<<i<<",\n";
|
||||
|
||||
|
@ -1137,7 +1152,7 @@ namespace Ogre
|
|||
outStream << " float3 halfAngle"<<i<<" = normalize(lightDir"<<i<<" + eyeDir);\n"
|
||||
" float4 litRes"<<i<<" = lit(dot(normalize(lightDir"<<i<<"), normal), dot(halfAngle"<<i<<", normal), scaleBiasSpecular.z);\n";
|
||||
|
||||
if (prof->getNumberOfLightsSupported() > 1)
|
||||
if (i > 0)
|
||||
outStream <<
|
||||
// pre-multiply light color with attenuation factor
|
||||
"d = length( lightDir"<<i<<" ); \n"
|
||||
|
@ -1249,22 +1264,7 @@ namespace Ogre
|
|||
|
||||
outStream <<
|
||||
" // pass cam depth\n"
|
||||
" oUVMisc.z = oPos.z;\n";
|
||||
|
||||
bool fog = terrain->getSceneManager()->getFogMode() != FOG_NONE && tt != RENDER_COMPOSITE_MAP;
|
||||
if (fog)
|
||||
{
|
||||
if (terrain->getSceneManager()->getFogMode() == FOG_LINEAR)
|
||||
{
|
||||
outStream <<
|
||||
" fogVal = saturate((oPos.z - fogParams.y) * fogParams.w);\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
outStream <<
|
||||
" fogVal = saturate(1 / (exp(oPos.z * fogParams.x)));\n";
|
||||
}
|
||||
}
|
||||
" oPosObj.w = oPos.z;\n";
|
||||
|
||||
if (prof->isShadowingEnabled(tt, terrain))
|
||||
generateVpDynamicShadows(prof, terrain, tt, outStream);
|
||||
|
@ -1315,7 +1315,13 @@ namespace Ogre
|
|||
|
||||
// diffuse lighting
|
||||
for (int i=0; i<prof->getNumberOfLightsSupported(); ++i)
|
||||
{
|
||||
// shadows only for first light (directional)
|
||||
if (i==0)
|
||||
outStream << " outputCol.rgb += litRes"<<i<<".y * lightDiffuseColour"<<i<<" * diffuse * shadow;\n";
|
||||
else
|
||||
outStream << " outputCol.rgb += litRes"<<i<<".y * lightDiffuseColour"<<i<<" * diffuse;\n";
|
||||
}
|
||||
|
||||
// specular default
|
||||
if (!prof->isLayerSpecularMappingEnabled())
|
||||
|
@ -1343,6 +1349,16 @@ namespace Ogre
|
|||
bool fog = terrain->getSceneManager()->getFogMode() != FOG_NONE && tt != RENDER_COMPOSITE_MAP;
|
||||
if (fog)
|
||||
{
|
||||
if (terrain->getSceneManager()->getFogMode() == FOG_LINEAR)
|
||||
{
|
||||
outStream <<
|
||||
" float fogVal = saturate((position.w - fogParams.y) * fogParams.w);\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
outStream <<
|
||||
" float fogVal = saturate(1 / (exp(position.w * fogParams.x)));\n";
|
||||
}
|
||||
outStream << " outputCol.rgb = lerp(outputCol.rgb, fogColour, fogVal);\n";
|
||||
}
|
||||
|
||||
|
@ -1350,7 +1366,7 @@ namespace Ogre
|
|||
outStream << " oColor = outputCol;\n";
|
||||
|
||||
if (MWRender::RenderingManager::useMRT()) outStream <<
|
||||
" oColor1 = float4(uvMisc.z / far, 0, 0, 1); \n";
|
||||
" oColor1 = float4(position.w / far, 0, 0, 1); \n";
|
||||
|
||||
outStream
|
||||
<< "}\n";
|
||||
|
@ -1364,7 +1380,7 @@ namespace Ogre
|
|||
outStream <<
|
||||
"// Simple PCF \n"
|
||||
"// Number of samples in one dimension (square for total samples) \n"
|
||||
"#define NUM_SHADOW_SAMPLES_1D 2.0 \n"
|
||||
"#define NUM_SHADOW_SAMPLES_1D 1.0 \n"
|
||||
"#define SHADOW_FILTER_SCALE 1 \n"
|
||||
|
||||
"#define SHADOW_SAMPLES NUM_SHADOW_SAMPLES_1D*NUM_SHADOW_SAMPLES_1D \n"
|
||||
|
@ -1377,28 +1393,18 @@ namespace Ogre
|
|||
if (prof->getReceiveDynamicShadowsDepth())
|
||||
{
|
||||
outStream <<
|
||||
"float calcDepthShadow(sampler2D shadowMap, float4 uv, float invShadowMapSize) \n"
|
||||
"{ \n"
|
||||
" // 4-sample PCF \n"
|
||||
|
||||
" float shadow = 0.0; \n"
|
||||
" float offset = (NUM_SHADOW_SAMPLES_1D/2 - 0.5) * SHADOW_FILTER_SCALE; \n"
|
||||
" for (float y = -offset; y <= offset; y += SHADOW_FILTER_SCALE) \n"
|
||||
" for (float x = -offset; x <= offset; x += SHADOW_FILTER_SCALE) \n"
|
||||
" { \n"
|
||||
" float4 newUV = offsetSample(uv, float2(x, y), invShadowMapSize);\n"
|
||||
" // manually project and assign derivatives \n"
|
||||
" // to avoid gradient issues inside loops \n"
|
||||
" newUV = newUV / newUV.w; \n"
|
||||
" float depth = tex2D(shadowMap, newUV.xy, 1, 1).x; \n"
|
||||
" if (depth >= 1 || depth >= uv.z)\n"
|
||||
" shadow += 1.0;\n"
|
||||
" } \n"
|
||||
|
||||
" shadow /= SHADOW_SAMPLES; \n"
|
||||
|
||||
" return shadow; \n"
|
||||
"} \n";
|
||||
"float calcDepthShadow(sampler2D shadowMap, float4 shadowMapPos, float2 offset) \n"
|
||||
" { \n"
|
||||
" shadowMapPos = shadowMapPos / shadowMapPos.w; \n"
|
||||
" float2 uv = shadowMapPos.xy; \n"
|
||||
" float3 o = float3(offset, -offset.x) * 0.3f; \n"
|
||||
" // Note: We using 2x2 PCF. Good enough and is alot faster. \n"
|
||||
" float c = (shadowMapPos.z <= tex2D(shadowMap, uv.xy - o.xy).r) ? 1 : 0; // top left \n"
|
||||
" c += (shadowMapPos.z <= tex2D(shadowMap, uv.xy + o.xy).r) ? 1 : 0; // bottom right \n"
|
||||
" c += (shadowMapPos.z <= tex2D(shadowMap, uv.xy + o.zy).r) ? 1 : 0; // bottom left \n"
|
||||
" c += (shadowMapPos.z <= tex2D(shadowMap, uv.xy - o.zy).r) ? 1 : 0; // top right \n"
|
||||
" return c / 4; \n"
|
||||
" } \n";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1436,7 +1442,7 @@ namespace Ogre
|
|||
{
|
||||
outStream << "\n ";
|
||||
for (uint i = 0; i < numTextures; ++i)
|
||||
outStream << "float invShadowmapSize" << i << ", ";
|
||||
outStream << "float2 invShadowmapSize" << i << ", ";
|
||||
}
|
||||
outStream << "\n"
|
||||
" float4 pssmSplitPoints, float camDepth) \n"
|
||||
|
@ -1458,7 +1464,7 @@ namespace Ogre
|
|||
if (prof->getReceiveDynamicShadowsDepth())
|
||||
{
|
||||
outStream <<
|
||||
" shadow = calcDepthShadow(shadowMap" << i << ", lsPos" << i << ", invShadowmapSize" << i << "); \n";
|
||||
" shadow = calcDepthShadow(shadowMap" << i << ", lsPos" << i << ", invShadowmapSize" << i << ".xy); \n";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1520,8 +1526,8 @@ namespace Ogre
|
|||
if (prof->getReceiveDynamicShadowsDepth())
|
||||
{
|
||||
// make linear
|
||||
outStream <<
|
||||
"oLightSpacePos" << i << ".z = (oLightSpacePos" << i << ".z - depthRange" << i << ".x) * depthRange" << i << ".w;\n";
|
||||
//outStream <<
|
||||
// "oLightSpacePos" << i << ".z = (oLightSpacePos" << i << ".z - depthRange" << i << ".x) * depthRange" << i << ".w;\n";
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1538,6 +1544,8 @@ namespace Ogre
|
|||
|
||||
// in semantics & params
|
||||
uint numTextures = 1;
|
||||
outStream <<
|
||||
", uniform float4 shadowFar_fadeStart \n";
|
||||
if (prof->getReceiveDynamicShadowsPSSM())
|
||||
{
|
||||
numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
|
||||
|
@ -1554,7 +1562,7 @@ namespace Ogre
|
|||
if (prof->getReceiveDynamicShadowsDepth())
|
||||
{
|
||||
outStream <<
|
||||
", uniform float inverseShadowmapSize" << i << " \n";
|
||||
", uniform float4 inverseShadowmapSize" << i << " \n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1567,7 +1575,7 @@ namespace Ogre
|
|||
{
|
||||
uint numTextures = prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
|
||||
outStream <<
|
||||
" float camDepth = uvMisc.z;\n";
|
||||
" float camDepth = position.w;\n";
|
||||
|
||||
if (prof->getReceiveDynamicShadowsDepth())
|
||||
{
|
||||
|
@ -1589,7 +1597,7 @@ namespace Ogre
|
|||
{
|
||||
outStream << "\n ";
|
||||
for (uint i = 0; i < numTextures; ++i)
|
||||
outStream << "inverseShadowmapSize" << i << ", ";
|
||||
outStream << "inverseShadowmapSize" << i << ".xy, ";
|
||||
}
|
||||
outStream << "\n" <<
|
||||
" pssmSplitPoints, camDepth);\n";
|
||||
|
@ -1600,7 +1608,7 @@ namespace Ogre
|
|||
if (prof->getReceiveDynamicShadowsDepth())
|
||||
{
|
||||
outStream <<
|
||||
" float rtshadow = calcDepthShadow(shadowMap0, lightSpacePos0, inverseShadowmapSize0);";
|
||||
" float rtshadow = calcDepthShadow(shadowMap0, lightSpacePos0, inverseShadowmapSize0.xy);";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1609,7 +1617,11 @@ namespace Ogre
|
|||
}
|
||||
}
|
||||
|
||||
outStream <<
|
||||
outStream <<
|
||||
" float fadeRange = shadowFar_fadeStart.x - shadowFar_fadeStart.y; \n"
|
||||
" float fade = 1-((position.w - shadowFar_fadeStart.y) / fadeRange); \n"
|
||||
" rtshadow = (position.w > shadowFar_fadeStart.x) ? 1 : ((position.w > shadowFar_fadeStart.y) ? 1-((1-rtshadow)*fade) : rtshadow); \n"
|
||||
" rtshadow = (1-(1-rtshadow)*0.6); \n" // make the shadow a little less intensive
|
||||
" shadow = min(shadow, rtshadow);\n";
|
||||
|
||||
}
|
||||
|
|
|
@ -73,6 +73,9 @@ namespace Ogre
|
|||
void updateParamsForCompositeMap(const MaterialPtr& mat, const Terrain* terrain);
|
||||
void requestOptions(Terrain* terrain);
|
||||
|
||||
void setShadowFar(float far);
|
||||
void setShadowFadeStart(float fadestart);
|
||||
|
||||
/** Whether to support normal mapping per layer in the shader (default true).
|
||||
*/
|
||||
bool isLayerNormalMappingEnabled() const { return mLayerNormalMappingEnabled; }
|
||||
|
@ -245,6 +248,8 @@ namespace Ogre
|
|||
bool mDepthShadows;
|
||||
bool mLowLodShadows;
|
||||
bool mSM3Available;
|
||||
float mShadowFar;
|
||||
float mShadowFadeStart;
|
||||
|
||||
bool isShadowingEnabled(TechniqueType tt, const Terrain* terrain) const;
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace MWRender
|
|||
Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) :
|
||||
mCamera (camera), mViewport (camera->getViewport()), mSceneManager (camera->getSceneManager()),
|
||||
mIsUnderwater(false), mVisibilityFlags(0),
|
||||
mReflectionTarget(0), mActive(1)
|
||||
mReflectionTarget(0), mActive(1), mToggled(1)
|
||||
{
|
||||
mSky = sky;
|
||||
|
||||
|
@ -31,6 +31,7 @@ Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) :
|
|||
mWater = mSceneManager->createEntity("water");
|
||||
mWater->setVisibilityFlags(RV_Water);
|
||||
mWater->setRenderQueueGroup(RQG_Water);
|
||||
mWater->setCastShadows(false);
|
||||
|
||||
mVisibilityFlags = RV_Terrain * Settings::Manager::getBool("reflect terrain", "Water")
|
||||
+ RV_Statics * Settings::Manager::getBool("reflect statics", "Water")
|
||||
|
@ -42,6 +43,8 @@ Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) :
|
|||
mWaterNode = mSceneManager->getRootSceneNode()->createChildSceneNode();
|
||||
mWaterNode->setPosition(0, mTop, 0);
|
||||
|
||||
mReflectionCamera = mSceneManager->createCamera("ReflectionCamera");
|
||||
|
||||
if(!(cell->data.flags & cell->Interior))
|
||||
{
|
||||
mWaterNode->setPosition(getSceneNodeCoordinates(cell->data.gridX, cell->data.gridY));
|
||||
|
@ -51,17 +54,20 @@ Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) :
|
|||
// Create rendertarget for reflection
|
||||
int rttsize = Settings::Manager::getInt("rtt size", "Water");
|
||||
|
||||
TexturePtr tex;
|
||||
if (Settings::Manager::getBool("shader", "Water"))
|
||||
{
|
||||
TexturePtr tex = TextureManager::getSingleton().createManual("WaterReflection",
|
||||
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, rttsize, rttsize, 0, PF_R8G8B8, TU_RENDERTARGET);
|
||||
tex = TextureManager::getSingleton().createManual("WaterReflection",
|
||||
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, rttsize, rttsize, 0, PF_FLOAT16_RGBA, TU_RENDERTARGET);
|
||||
|
||||
RenderTarget* rtt = tex->getBuffer()->getRenderTarget();
|
||||
Viewport* vp = rtt->addViewport(mCamera);
|
||||
Viewport* vp = rtt->addViewport(mReflectionCamera);
|
||||
vp->setOverlaysEnabled(false);
|
||||
vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f));
|
||||
vp->setShadowsEnabled(false);
|
||||
vp->setVisibilityMask( mVisibilityFlags );
|
||||
// use fallback techniques without shadows and without mrt (currently not implemented for sky and terrain)
|
||||
//vp->setMaterialScheme("Fallback");
|
||||
rtt->addListener(this);
|
||||
rtt->setActive(true);
|
||||
|
||||
|
@ -74,13 +80,61 @@ Water::Water (Ogre::Camera *camera, SkyManager* sky, const ESM::Cell* cell) :
|
|||
mWater->setMaterial(mMaterial);
|
||||
|
||||
mUnderwaterEffect = Settings::Manager::getBool("underwater effect", "Water");
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// ---------------------------------- reflection debug overlay ----------------------------------
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
/*
|
||||
if (Settings::Manager::getBool("shader", "Water"))
|
||||
{
|
||||
OverlayManager& mgr = OverlayManager::getSingleton();
|
||||
Overlay* overlay;
|
||||
// destroy if already exists
|
||||
if (overlay = mgr.getByName("ReflectionDebugOverlay"))
|
||||
mgr.destroy(overlay);
|
||||
|
||||
overlay = mgr.create("ReflectionDebugOverlay");
|
||||
|
||||
if (MaterialManager::getSingleton().resourceExists("Ogre/ReflectionDebugTexture"))
|
||||
MaterialManager::getSingleton().remove("Ogre/ReflectionDebugTexture");
|
||||
MaterialPtr debugMat = MaterialManager::getSingleton().create(
|
||||
"Ogre/ReflectionDebugTexture",
|
||||
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||
|
||||
debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
|
||||
TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(tex->getName());
|
||||
t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
|
||||
|
||||
OverlayContainer* debugPanel;
|
||||
|
||||
// destroy container if exists
|
||||
try
|
||||
{
|
||||
if (debugPanel =
|
||||
static_cast<OverlayContainer*>(
|
||||
mgr.getOverlayElement("Ogre/ReflectionDebugTexPanel"
|
||||
)))
|
||||
mgr.destroyOverlayElement(debugPanel);
|
||||
}
|
||||
catch (Ogre::Exception&) {}
|
||||
|
||||
debugPanel = (OverlayContainer*)
|
||||
(OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/ReflectionDebugTexPanel"));
|
||||
debugPanel->_setPosition(0, 0.55);
|
||||
debugPanel->_setDimensions(0.3, 0.3);
|
||||
debugPanel->setMaterialName(debugMat->getName());
|
||||
debugPanel->show();
|
||||
overlay->add2D(debugPanel);
|
||||
overlay->show();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Water::setActive(bool active)
|
||||
{
|
||||
mActive = active;
|
||||
if (mReflectionTarget) mReflectionTarget->setActive(active && !mIsUnderwater);
|
||||
mWater->setVisible(active);
|
||||
updateVisible();
|
||||
}
|
||||
|
||||
Water::~Water()
|
||||
|
@ -112,8 +166,8 @@ void Water::setHeight(const float height)
|
|||
|
||||
void Water::toggle()
|
||||
{
|
||||
if (mActive)
|
||||
mWater->setVisible(!mWater->getVisible());
|
||||
mToggled = !mToggled;
|
||||
updateVisible();
|
||||
}
|
||||
|
||||
void Water::checkUnderwater(float y)
|
||||
|
@ -128,13 +182,10 @@ void Water::checkUnderwater(float y)
|
|||
if (pass->hasFragmentProgram() && pass->getFragmentProgramParameters()->_findNamedConstantDefinition("isUnderwater", false))
|
||||
pass->getFragmentProgramParameters()->setNamedConstant("isUnderwater", Real(0));
|
||||
|
||||
if (mReflectionTarget)
|
||||
mReflectionTarget->setActive(mActive);
|
||||
|
||||
mWater->setRenderQueueGroup(RQG_Water);
|
||||
|
||||
mIsUnderwater = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mIsUnderwater && y < mTop && mWater->isVisible() && mCamera->getPolygonMode() == Ogre::PM_SOLID)
|
||||
{
|
||||
|
@ -146,13 +197,12 @@ void Water::checkUnderwater(float y)
|
|||
if (pass->hasFragmentProgram() && pass->getFragmentProgramParameters()->_findNamedConstantDefinition("isUnderwater", false))
|
||||
pass->getFragmentProgramParameters()->setNamedConstant("isUnderwater", Real(1));
|
||||
|
||||
if (mReflectionTarget)
|
||||
mReflectionTarget->setActive(false);
|
||||
|
||||
mWater->setRenderQueueGroup(RQG_UnderWater);
|
||||
|
||||
mIsUnderwater = true;
|
||||
}
|
||||
|
||||
updateVisible();
|
||||
}
|
||||
|
||||
Vector3 Water::getSceneNodeCoordinates(int gridX, int gridY)
|
||||
|
@ -164,7 +214,12 @@ void Water::preRenderTargetUpdate(const RenderTargetEvent& evt)
|
|||
{
|
||||
if (evt.source == mReflectionTarget)
|
||||
{
|
||||
mWater->setVisible(false);
|
||||
mReflectionCamera->setOrientation(mCamera->getDerivedOrientation());
|
||||
mReflectionCamera->setPosition(mCamera->getDerivedPosition());
|
||||
mReflectionCamera->setNearClipDistance(mCamera->getNearClipDistance());
|
||||
mReflectionCamera->setFarClipDistance(mCamera->getFarClipDistance());
|
||||
mReflectionCamera->setAspectRatio(mCamera->getAspectRatio());
|
||||
mReflectionCamera->setFOVy(mCamera->getFOVy());
|
||||
|
||||
// Some messy code to get the skybox to show up at all
|
||||
// The problem here is that it gets clipped by the water plane
|
||||
|
@ -174,21 +229,19 @@ void Water::preRenderTargetUpdate(const RenderTargetEvent& evt)
|
|||
mSky->setSkyPosition(pos);
|
||||
mSky->scaleSky(mCamera->getFarClipDistance() / 1000.f);
|
||||
|
||||
mCamera->enableCustomNearClipPlane(Plane(Vector3::UNIT_Y, mTop));
|
||||
mCamera->enableReflection(Plane(Vector3::UNIT_Y, mTop));
|
||||
mReflectionCamera->enableCustomNearClipPlane(Plane(Vector3::UNIT_Y, mTop));
|
||||
mReflectionCamera->enableReflection(Plane(Vector3::UNIT_Y, mTop));
|
||||
}
|
||||
}
|
||||
|
||||
void Water::postRenderTargetUpdate(const RenderTargetEvent& evt)
|
||||
{
|
||||
mWater->setVisible(true);
|
||||
|
||||
if (evt.source == mReflectionTarget)
|
||||
{
|
||||
mSky->resetSkyPosition();
|
||||
mSky->scaleSky(1);
|
||||
mCamera->disableReflection();
|
||||
mCamera->disableCustomNearClipPlane();
|
||||
mReflectionCamera->disableCustomNearClipPlane();
|
||||
mReflectionCamera->disableReflection();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,4 +283,11 @@ void Water::setViewportBackground(const ColourValue& bg)
|
|||
mReflectionTarget->getViewport(0)->setBackgroundColour(bg);
|
||||
}
|
||||
|
||||
void Water::updateVisible()
|
||||
{
|
||||
mWater->setVisible(mToggled && mActive);
|
||||
if (mReflectionTarget)
|
||||
mReflectionTarget->setActive(mToggled && mActive && !mIsUnderwater);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace MWRender {
|
|||
|
||||
bool mIsUnderwater;
|
||||
bool mActive;
|
||||
bool mToggled;
|
||||
int mTop;
|
||||
|
||||
Ogre::Vector3 getSceneNodeCoordinates(int gridX, int gridY);
|
||||
|
@ -31,6 +32,7 @@ namespace MWRender {
|
|||
protected:
|
||||
void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt);
|
||||
void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt);
|
||||
void updateVisible();
|
||||
|
||||
SkyManager* mSky;
|
||||
|
||||
|
@ -39,6 +41,8 @@ namespace MWRender {
|
|||
void createMaterial();
|
||||
Ogre::MaterialPtr mMaterial;
|
||||
|
||||
Ogre::Camera* mReflectionCamera;
|
||||
|
||||
Ogre::RenderTarget* mReflectionTarget;
|
||||
|
||||
bool mUnderwaterEffect;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "../mwdialogue/dialoguemanager.hpp"
|
||||
|
||||
#include "interpretercontext.hpp"
|
||||
#include "ref.hpp"
|
||||
|
||||
namespace MWScript
|
||||
{
|
||||
|
@ -115,12 +116,27 @@ namespace MWScript
|
|||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpForceGreeting : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
context.getEnvironment().mDialogueManager->startDialogue (ptr);
|
||||
}
|
||||
};
|
||||
|
||||
const int opcodeJournal = 0x2000133;
|
||||
const int opcodeSetJournalIndex = 0x2000134;
|
||||
const int opcodeGetJournalIndex = 0x2000135;
|
||||
const int opcodeAddTopic = 0x200013a;
|
||||
const int opcodeChoice = 0x2000a;
|
||||
const int opcodeForceGreeting = 0x200014f;
|
||||
const int opcodeForceGreetingExplicit = 0x2000150;
|
||||
|
||||
void registerExtensions (Compiler::Extensions& extensions)
|
||||
{
|
||||
|
@ -129,6 +145,9 @@ namespace MWScript
|
|||
extensions.registerFunction ("getjournalindex", 'l', "c", opcodeGetJournalIndex);
|
||||
extensions.registerInstruction ("addtopic", "S" , opcodeAddTopic);
|
||||
extensions.registerInstruction ("choice", "/SlSlSlSlSlSlSlSlSlSlSlSlSlSlSlSl", opcodeChoice);
|
||||
extensions.registerInstruction("forcegreeting","",opcodeForceGreeting);
|
||||
extensions.registerInstruction("forcegreeting","",opcodeForceGreeting,
|
||||
opcodeForceGreetingExplicit);
|
||||
}
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||
|
@ -138,6 +157,8 @@ namespace MWScript
|
|||
interpreter.installSegment5 (opcodeGetJournalIndex, new OpGetJournalIndex);
|
||||
interpreter.installSegment5 (opcodeAddTopic, new OpAddTopic);
|
||||
interpreter.installSegment3 (opcodeChoice,new OpChoice);
|
||||
interpreter.installSegment5 (opcodeForceGreeting, new OpForceGreeting<ImplicitRef>);
|
||||
interpreter.installSegment5 (opcodeForceGreetingExplicit, new OpForceGreeting<ExplicitRef>);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,12 @@ op 0x20007: PlayAnim, explicit reference
|
|||
op 0x20008: LoopAnim
|
||||
op 0x20009: LoopAnim, explicit reference
|
||||
op 0x2000a: Choice
|
||||
opcodes 0x2000b-0x3ffff unused
|
||||
op 0x2000b: PCRaiseRank
|
||||
op 0x2000c: PCLowerRank
|
||||
op 0x2000d: PCJoinFaction
|
||||
op 0x2000e: PCGetRank implicit
|
||||
op 0x2000f: PCGetRank explicit
|
||||
opcodes 0x20010-0x3ffff unused
|
||||
|
||||
Segment 4:
|
||||
(not implemented yet)
|
||||
|
@ -129,4 +134,14 @@ op 0x2000143: ModWaterLevel
|
|||
op 0x2000144: ToggleWater, twa
|
||||
op 0x2000145: ToggleFogOfWar (tfow)
|
||||
op 0x2000146: TogglePathgrid
|
||||
opcodes 0x2000147-0x3ffffff unused
|
||||
op 0x2000147: AddSpell
|
||||
op 0x2000148: AddSpell, explicit reference
|
||||
op 0x2000149: RemoveSpell
|
||||
op 0x200014a: RemoveSpell, explicit reference
|
||||
op 0x200014b: GetSpell
|
||||
op 0x200014c: GetSpell, explicit reference
|
||||
op 0x200014d: ModDisposition
|
||||
op 0x200014e: ModDisposition, explicit reference
|
||||
op 0x200014f: ForceGreeting
|
||||
op 0x2000150: ForceGreeting, explicit reference
|
||||
opcodes 0x2000151-0x3ffffff unused
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include <components/interpreter/opcodes.hpp>
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/environment.hpp"
|
||||
#include "../mwworld/player.hpp"
|
||||
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
#include "../mwmechanics/npcstats.hpp"
|
||||
|
@ -15,6 +17,8 @@
|
|||
#include "interpretercontext.hpp"
|
||||
#include "ref.hpp"
|
||||
|
||||
#include "../mwdialogue/dialoguemanager.hpp"
|
||||
|
||||
namespace MWScript
|
||||
{
|
||||
namespace Stats
|
||||
|
@ -280,6 +284,220 @@ namespace MWScript
|
|||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpAddSpell : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
MWWorld::Class::get (ptr).getCreatureStats (ptr).mSpells.add (id);
|
||||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpRemoveSpell : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
MWWorld::Class::get (ptr).getCreatureStats (ptr).mSpells.remove (id);
|
||||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpGetSpell : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Integer value = 0;
|
||||
|
||||
for (MWMechanics::Spells::TIterator iter (
|
||||
MWWorld::Class::get (ptr).getCreatureStats (ptr).mSpells.begin());
|
||||
iter!=MWWorld::Class::get (ptr).getCreatureStats (ptr).mSpells.end(); ++iter)
|
||||
if (*iter==id)
|
||||
{
|
||||
value = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
runtime.push (value);
|
||||
}
|
||||
};
|
||||
|
||||
class OpPCJoinFaction : public Interpreter::Opcode1
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||
{
|
||||
std::string factionID = "";
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
if(arg0==0)
|
||||
{
|
||||
factionID = context.getEnvironment().mDialogueManager->getFaction();
|
||||
}
|
||||
else
|
||||
{
|
||||
factionID = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
}
|
||||
if(factionID != "")
|
||||
{
|
||||
MWWorld::Ptr player = context.getEnvironment().mWorld->getPlayer().getPlayer();
|
||||
if(MWWorld::Class::get(player).getNpcStats(player).mFactionRank.find(factionID) == MWWorld::Class::get(player).getNpcStats(player).mFactionRank.end())
|
||||
{
|
||||
MWWorld::Class::get(player).getNpcStats(player).mFactionRank[factionID] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class OpPCRaiseRank : public Interpreter::Opcode1
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||
{
|
||||
std::string factionID = "";
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
if(arg0==0)
|
||||
{
|
||||
factionID = context.getEnvironment().mDialogueManager->getFaction();
|
||||
}
|
||||
else
|
||||
{
|
||||
factionID = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
}
|
||||
if(factionID != "")
|
||||
{
|
||||
MWWorld::Ptr player = context.getEnvironment().mWorld->getPlayer().getPlayer();
|
||||
if(MWWorld::Class::get(player).getNpcStats(player).mFactionRank.find(factionID) == MWWorld::Class::get(player).getNpcStats(player).mFactionRank.end())
|
||||
{
|
||||
MWWorld::Class::get(player).getNpcStats(player).mFactionRank[factionID] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
MWWorld::Class::get(player).getNpcStats(player).mFactionRank[factionID] = MWWorld::Class::get(player).getNpcStats(player).mFactionRank[factionID] +1;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class OpPCLowerRank : public Interpreter::Opcode1
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||
{
|
||||
std::string factionID = "";
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
if(arg0==0)
|
||||
{
|
||||
factionID = context.getEnvironment().mDialogueManager->getFaction();
|
||||
}
|
||||
else
|
||||
{
|
||||
factionID = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
}
|
||||
if(factionID != "")
|
||||
{
|
||||
MWWorld::Ptr player = context.getEnvironment().mWorld->getPlayer().getPlayer();
|
||||
if(MWWorld::Class::get(player).getNpcStats(player).mFactionRank.find(factionID) != MWWorld::Class::get(player).getNpcStats(player).mFactionRank.end())
|
||||
{
|
||||
MWWorld::Class::get(player).getNpcStats(player).mFactionRank[factionID] = MWWorld::Class::get(player).getNpcStats(player).mFactionRank[factionID] -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpGetPCRank : public Interpreter::Opcode1
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
std::string factionID = "";
|
||||
if(arg0 >0)
|
||||
{
|
||||
factionID = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(MWWorld::Class::get(ptr).getNpcStats(ptr).mFactionRank.empty())
|
||||
{
|
||||
//throw exception?
|
||||
}
|
||||
else
|
||||
{
|
||||
factionID = MWWorld::Class::get(ptr).getNpcStats(ptr).mFactionRank.begin()->first;
|
||||
}
|
||||
}
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
MWWorld::Ptr player = context.getEnvironment().mWorld->getPlayer().getPlayer();
|
||||
if(factionID!="")
|
||||
{
|
||||
if(MWWorld::Class::get(player).getNpcStats(player).mFactionRank.find(factionID) != MWWorld::Class::get(player).getNpcStats(player).mFactionRank.end())
|
||||
{
|
||||
runtime.push(MWWorld::Class::get(player).getNpcStats(player).mFactionRank[factionID]);
|
||||
}
|
||||
else
|
||||
{
|
||||
runtime.push(-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
runtime.push(-1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpModDisposition : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
// Interpreter::Type_Integer value = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
/// \todo modify disposition towards the player
|
||||
}
|
||||
};
|
||||
|
||||
const int numberOfAttributes = 8;
|
||||
|
||||
const int opcodeGetAttribute = 0x2000027;
|
||||
|
@ -311,6 +529,21 @@ namespace MWScript
|
|||
const int opcodeModSkill = 0x20000fa;
|
||||
const int opcodeModSkillExplicit = 0x2000115;
|
||||
|
||||
const int opcodeAddSpell = 0x2000147;
|
||||
const int opcodeAddSpellExplicit = 0x2000148;
|
||||
const int opcodeRemoveSpell = 0x2000149;
|
||||
const int opcodeRemoveSpellExplicit = 0x200014a;
|
||||
const int opcodeGetSpell = 0x200014b;
|
||||
const int opcodeGetSpellExplicit = 0x200014c;
|
||||
|
||||
const int opcodePCRaiseRank = 0x2000b;
|
||||
const int opcodePCLowerRank = 0x2000c;
|
||||
const int opcodePCJoinFaction = 0x2000d;
|
||||
const int opcodeGetPCRank = 0x2000e;
|
||||
const int opcodeGetPCRankExplicit = 0x2000f;
|
||||
const int opcodeModDisposition = 0x200014d;
|
||||
const int opcodeModDispositionExplicit = 0x200014e;
|
||||
|
||||
void registerExtensions (Compiler::Extensions& extensions)
|
||||
{
|
||||
static const char *attributes[numberOfAttributes] =
|
||||
|
@ -381,6 +614,18 @@ namespace MWScript
|
|||
extensions.registerInstruction (mod + skills[i], "l",
|
||||
opcodeModSkill+i, opcodeModSkillExplicit+i);
|
||||
}
|
||||
|
||||
extensions.registerInstruction ("addspell", "c", opcodeAddSpell, opcodeAddSpellExplicit);
|
||||
extensions.registerInstruction ("removespell", "c", opcodeRemoveSpell,
|
||||
opcodeRemoveSpellExplicit);
|
||||
extensions.registerFunction ("getspell", 'l', "c", opcodeGetSpell, opcodeGetSpellExplicit);
|
||||
|
||||
extensions.registerInstruction("pcraiserank","/S",opcodePCRaiseRank);
|
||||
extensions.registerInstruction("pclowerrank","/S",opcodePCLowerRank);
|
||||
extensions.registerInstruction("pcjoinfaction","/S",opcodePCJoinFaction);
|
||||
extensions.registerInstruction("moddisposition","l",opcodeModDisposition,
|
||||
opcodeModDispositionExplicit);
|
||||
extensions.registerFunction("getpcrank",'l',"/S",opcodeGetPCRank,opcodeGetPCRankExplicit);
|
||||
}
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||
|
@ -436,6 +681,22 @@ namespace MWScript
|
|||
interpreter.installSegment5 (opcodeModSkill+i, new OpModSkill<ImplicitRef> (i));
|
||||
interpreter.installSegment5 (opcodeModSkillExplicit+i, new OpModSkill<ExplicitRef> (i));
|
||||
}
|
||||
|
||||
interpreter.installSegment5 (opcodeAddSpell, new OpAddSpell<ImplicitRef>);
|
||||
interpreter.installSegment5 (opcodeAddSpellExplicit, new OpAddSpell<ExplicitRef>);
|
||||
interpreter.installSegment5 (opcodeRemoveSpell, new OpRemoveSpell<ImplicitRef>);
|
||||
interpreter.installSegment5 (opcodeRemoveSpellExplicit,
|
||||
new OpRemoveSpell<ExplicitRef>);
|
||||
interpreter.installSegment5 (opcodeGetSpell, new OpGetSpell<ImplicitRef>);
|
||||
interpreter.installSegment5 (opcodeGetSpellExplicit, new OpGetSpell<ExplicitRef>);
|
||||
|
||||
interpreter.installSegment3(opcodePCRaiseRank,new OpPCRaiseRank);
|
||||
interpreter.installSegment3(opcodePCLowerRank,new OpPCLowerRank);
|
||||
interpreter.installSegment3(opcodePCJoinFaction,new OpPCJoinFaction);
|
||||
interpreter.installSegment5(opcodeModDisposition,new OpModDisposition<ImplicitRef>);
|
||||
interpreter.installSegment5(opcodeModDispositionExplicit,new OpModDisposition<ExplicitRef>);
|
||||
interpreter.installSegment3(opcodeGetPCRank,new OpGetPCRank<ImplicitRef>);
|
||||
interpreter.installSegment3(opcodeGetPCRankExplicit,new OpGetPCRank<ExplicitRef>);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite
|
|||
/// \todo restack item previously in this slot (if required)
|
||||
|
||||
/// \todo unstack item pointed to by iterator if required)
|
||||
|
||||
|
||||
mSlots[slot] = iterator;
|
||||
|
||||
flagAsModified();
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "OgreTextureManager.h"
|
||||
|
||||
|
||||
|
||||
using namespace Ogre;
|
||||
namespace MWWorld
|
||||
{
|
||||
|
@ -20,9 +21,11 @@ namespace MWWorld
|
|||
PhysicsSystem::PhysicsSystem(OEngine::Render::OgreRenderer &_rend) :
|
||||
mRender(_rend), mEngine(0), mFreeFly (true)
|
||||
{
|
||||
|
||||
// Create physics. shapeLoader is deleted by the physic engine
|
||||
NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader();
|
||||
mEngine = new OEngine::Physic::PhysicEngine(shapeLoader);
|
||||
|
||||
}
|
||||
|
||||
PhysicsSystem::~PhysicsSystem()
|
||||
|
@ -90,55 +93,78 @@ namespace MWWorld
|
|||
{
|
||||
//set the DebugRenderingMode. To disable it,set it to 0
|
||||
//eng->setDebugRenderingMode(1);
|
||||
|
||||
|
||||
|
||||
//set the walkdirection to 0 (no movement) for every actor)
|
||||
for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++)
|
||||
{
|
||||
OEngine::Physic::PhysicActor* act = it->second;
|
||||
act->setWalkDirection(btVector3(0,0,0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//playerphysics->ps.move_type = PM_NOCLIP;
|
||||
for (std::vector<std::pair<std::string, Ogre::Vector3> >::const_iterator iter (actors.begin());
|
||||
iter!=actors.end(); ++iter)
|
||||
{
|
||||
OEngine::Physic::PhysicActor* act = mEngine->getCharacter(iter->first);
|
||||
|
||||
//if(iter->first == "player")
|
||||
// std::cout << "This is player\n";
|
||||
//dirty stuff to get the camera orientation. Must be changed!
|
||||
|
||||
Ogre::SceneNode *sceneNode = mRender.getScene()->getSceneNode (iter->first);
|
||||
Ogre::Vector3 dir;
|
||||
Ogre::Node* yawNode = sceneNode->getChildIterator().getNext();
|
||||
Ogre::Node* pitchNode = yawNode->getChildIterator().getNext();
|
||||
Ogre::Quaternion yawQuat = yawNode->getOrientation();
|
||||
Ogre::Quaternion pitchQuat = pitchNode->getOrientation();
|
||||
Ogre::Quaternion both = yawQuat * pitchQuat;
|
||||
|
||||
|
||||
//playerphysics->ps.viewangles.z = both.getPitch().valueDegrees();
|
||||
|
||||
|
||||
if(mFreeFly)
|
||||
{
|
||||
Ogre::Quaternion yawQuat = yawNode->getOrientation();
|
||||
Ogre::Quaternion pitchQuat = pitchNode->getOrientation();
|
||||
|
||||
Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y);
|
||||
|
||||
|
||||
|
||||
|
||||
//std::cout << "Current angle" << yawQuat.getYaw().valueDegrees() - 90<< "\n";
|
||||
//playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees();
|
||||
//std::cout << "Pitch: " << yawQuat.getPitch() << "Yaw:" << yawQuat.getYaw() << "Roll: " << yawQuat.getRoll() << "\n";
|
||||
dir = 0.07*(yawQuat*pitchQuat*dir1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Ogre::Quaternion quat = yawNode->getOrientation();
|
||||
Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y);
|
||||
|
||||
|
||||
dir = 0.025*(quat*dir1);
|
||||
}
|
||||
|
||||
|
||||
//set the walk direction
|
||||
act->setWalkDirection(btVector3(dir.x,-dir.z,dir.y));
|
||||
}
|
||||
mEngine->stepSimulation(duration);
|
||||
|
||||
|
||||
std::vector< std::pair<std::string, Ogre::Vector3> > response;
|
||||
for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++)
|
||||
{
|
||||
btVector3 newPos = it->second->getPosition();
|
||||
|
||||
Ogre::Vector3 coord(newPos.x(), newPos.y(), newPos.z());
|
||||
|
||||
|
||||
response.push_back(std::pair<std::string, Ogre::Vector3>(it->first, coord));
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
void PhysicsSystem::addObject (const std::string& handle, const std::string& mesh,
|
||||
const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position)
|
||||
{
|
||||
|
|
|
@ -54,6 +54,7 @@ namespace MWWorld
|
|||
OEngine::Physic::PhysicEngine* mEngine;
|
||||
bool mFreeFly;
|
||||
|
||||
|
||||
PhysicsSystem (const PhysicsSystem&);
|
||||
PhysicsSystem& operator= (const PhysicsSystem&);
|
||||
};
|
||||
|
|
69
cmake/FindFreetype.cmake
Normal file
69
cmake/FindFreetype.cmake
Normal file
|
@ -0,0 +1,69 @@
|
|||
#-------------------------------------------------------------------
|
||||
# This file is part of the CMake build system for OGRE
|
||||
# (Object-oriented Graphics Rendering Engine)
|
||||
# For the latest info, see http://www.ogre3d.org/
|
||||
#
|
||||
# The contents of this file are placed in the public domain. Feel
|
||||
# free to make use of it in any way you like.
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
# - Try to find FreeType
|
||||
# Once done, this will define
|
||||
#
|
||||
# FREETYPE_FOUND - system has FreeType
|
||||
# FREETYPE_INCLUDE_DIRS - the FreeType include directories
|
||||
# FREETYPE_LIBRARIES - link these to use FreeType
|
||||
|
||||
include(FindPkgMacros)
|
||||
findpkg_begin(FREETYPE)
|
||||
|
||||
# Get path, convert backslashes as ${ENV_${var}}
|
||||
getenv_path(FREETYPE_HOME)
|
||||
|
||||
# construct search paths
|
||||
set(FREETYPE_PREFIX_PATH ${FREETYPE_HOME} ${ENV_FREETYPE_HOME})
|
||||
create_search_paths(FREETYPE)
|
||||
# redo search if prefix path changed
|
||||
clear_if_changed(FREETYPE_PREFIX_PATH
|
||||
FREETYPE_LIBRARY_FWK
|
||||
FREETYPE_LIBRARY_REL
|
||||
FREETYPE_LIBRARY_DBG
|
||||
FREETYPE_INCLUDE_DIR
|
||||
)
|
||||
|
||||
set(FREETYPE_LIBRARY_NAMES freetype2311 freetype239 freetype238 freetype235 freetype219 freetype)
|
||||
get_debug_names(FREETYPE_LIBRARY_NAMES)
|
||||
|
||||
use_pkgconfig(FREETYPE_PKGC freetype2)
|
||||
|
||||
# prefer static library over framework
|
||||
set(CMAKE_FIND_FRAMEWORK "LAST")
|
||||
|
||||
message(STATUS "CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}")
|
||||
findpkg_framework(FREETYPE)
|
||||
message(STATUS "CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}")
|
||||
|
||||
find_path(FREETYPE_INCLUDE_DIR NAMES freetype/freetype.h HINTS ${FREETYPE_INC_SEARCH_PATH} ${FREETYPE_PKGC_INCLUDE_DIRS} PATH_SUFFIXES freetype2)
|
||||
find_path(FREETYPE_FT2BUILD_INCLUDE_DIR NAMES ft2build.h HINTS ${FREETYPE_INC_SEARCH_PATH} ${FREETYPE_PKGC_INCLUDE_DIRS})
|
||||
|
||||
if (SYMBIAN)
|
||||
set(ORIGINAL_CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH})
|
||||
set(CMAKE_PREFIX_PATH ${CMAKE_SYSYEM_OUT_DIR})
|
||||
message(STATUS "Lib will be searched in Symbian out dir: ${CMAKE_SYSYEM_OUT_DIR}")
|
||||
endif (SYMBIAN)
|
||||
find_library(FREETYPE_LIBRARY_REL NAMES ${FREETYPE_LIBRARY_NAMES} HINTS ${FREETYPE_LIB_SEARCH_PATH} ${FREETYPE_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" release relwithdebinfo minsizerel)
|
||||
find_library(FREETYPE_LIBRARY_DBG NAMES ${FREETYPE_LIBRARY_NAMES_DBG} HINTS ${FREETYPE_LIB_SEARCH_PATH} ${FREETYPE_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" debug)
|
||||
if (SYMBIAN)
|
||||
set(CMAKE_PREFIX_PATH ${ORIGINAL_CMAKE_PREFIX_PATH})
|
||||
endif (SYMBIAN)
|
||||
|
||||
make_library_set(FREETYPE_LIBRARY)
|
||||
|
||||
findpkg_finish(FREETYPE)
|
||||
mark_as_advanced(FREETYPE_FT2BUILD_INCLUDE_DIR)
|
||||
if (NOT FREETYPE_FT2BUILD_INCLUDE_DIR STREQUAL FREETYPE_INCLUDE_DIR)
|
||||
set(FREETYPE_INCLUDE_DIRS ${FREETYPE_INCLUDE_DIRS} ${FREETYPE_FT2BUILD_INCLUDE_DIR})
|
||||
endif ()
|
||||
|
||||
# Reset framework finding
|
||||
set(CMAKE_FIND_FRAMEWORK "FIRST")
|
|
@ -82,37 +82,49 @@ findpkg_finish ( "MYGUI" )
|
|||
ELSE (WIN32) #Unix
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.4.7 FATAL_ERROR)
|
||||
FIND_PACKAGE(PkgConfig)
|
||||
IF(MYGUI_STATIC)
|
||||
PKG_SEARCH_MODULE(MYGUI MYGUIStatic MyGUIStatic)
|
||||
IF (MYGUI_INCLUDE_DIRS)
|
||||
SET(MYGUI_INCLUDE_DIRS ${MYGUI_INCLUDE_DIRS})
|
||||
SET(MYGUI_LIB_DIR ${MYGUI_LIBDIR})
|
||||
SET(MYGUI_LIBRARIES ${MYGUI_LIBRARIES} CACHE STRING "")
|
||||
SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform")
|
||||
ELSE (MYGUI_INCLUDE_DIRS)
|
||||
FIND_PATH(MYGUI_INCLUDE_DIRS MyGUI.h PATHS /usr/local/include /usr/include PATH_SUFFIXES MyGUI MYGUI)
|
||||
FIND_LIBRARY(MYGUI_LIBRARIES myguistatic PATHS /usr/lib /usr/local/lib)
|
||||
SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform")
|
||||
SET(MYGUI_LIB_DIR ${MYGUI_LIBRARIES})
|
||||
STRING(REGEX REPLACE "(.*)/.*" "\\1" MYGUI_LIB_DIR "${MYGUI_LIB_DIR}")
|
||||
STRING(REGEX REPLACE ".*/" "" MYGUI_LIBRARIES "${MYGUI_LIBRARIES}")
|
||||
ENDIF (MYGUI_INCLUDE_DIRS)
|
||||
ELSE(MYGUI_STATIC)
|
||||
PKG_SEARCH_MODULE(MYGUI MYGUI MyGUI)
|
||||
IF (MYGUI_INCLUDE_DIRS)
|
||||
SET(MYGUI_INCLUDE_DIRS ${MYGUI_INCLUDE_DIRS})
|
||||
SET(MYGUI_LIB_DIR ${MYGUI_LIBDIR})
|
||||
SET(MYGUI_LIBRARIES ${MYGUI_LIBRARIES} CACHE STRING "")
|
||||
SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform")
|
||||
ELSE (MYGUI_INCLUDE_DIRS)
|
||||
FIND_PATH(MYGUI_INCLUDE_DIRS MyGUI.h PATHS /usr/local/include /usr/include PATH_SUFFIXES MyGUI MYGUI)
|
||||
FIND_LIBRARY(MYGUI_LIBRARIES mygui PATHS /usr/lib /usr/local/lib)
|
||||
SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform")
|
||||
SET(MYGUI_LIB_DIR ${MYGUI_LIBRARIES})
|
||||
STRING(REGEX REPLACE "(.*)/.*" "\\1" MYGUI_LIB_DIR "${MYGUI_LIB_DIR}")
|
||||
STRING(REGEX REPLACE ".*/" "" MYGUI_LIBRARIES "${MYGUI_LIBRARIES}")
|
||||
ENDIF (MYGUI_INCLUDE_DIRS)
|
||||
ENDIF(MYGUI_STATIC)
|
||||
IF(MYGUI_STATIC)
|
||||
# don't use pkgconfig on OS X, find freetype & append it's libs to resulting MYGUI_LIBRARIES
|
||||
IF (NOT APPLE)
|
||||
PKG_SEARCH_MODULE(MYGUI MYGUIStatic MyGUIStatic)
|
||||
IF (MYGUI_INCLUDE_DIRS)
|
||||
SET(MYGUI_INCLUDE_DIRS ${MYGUI_INCLUDE_DIRS})
|
||||
SET(MYGUI_LIB_DIR ${MYGUI_LIBDIR})
|
||||
SET(MYGUI_LIBRARIES ${MYGUI_LIBRARIES} CACHE STRING "")
|
||||
SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform")
|
||||
ELSE (MYGUI_INCLUDE_DIRS)
|
||||
FIND_PATH(MYGUI_INCLUDE_DIRS MyGUI.h PATHS /usr/local/include /usr/include PATH_SUFFIXES MyGUI MYGUI)
|
||||
FIND_LIBRARY(MYGUI_LIBRARIES myguistatic PATHS /usr/lib /usr/local/lib)
|
||||
SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform")
|
||||
SET(MYGUI_LIB_DIR ${MYGUI_LIBRARIES})
|
||||
STRING(REGEX REPLACE "(.*)/.*" "\\1" MYGUI_LIB_DIR "${MYGUI_LIB_DIR}")
|
||||
STRING(REGEX REPLACE ".*/" "" MYGUI_LIBRARIES "${MYGUI_LIBRARIES}")
|
||||
ENDIF (MYGUI_INCLUDE_DIRS)
|
||||
ELSE (NOT APPLE)
|
||||
SET(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${MYGUI_DEPENDENCIES_DIR} ${OGRE_DEPENDENCIES_DIR})
|
||||
FIND_PACKAGE(freetype)
|
||||
FIND_PATH(MYGUI_INCLUDE_DIRS MyGUI.h PATHS /usr/local/include /usr/include PATH_SUFFIXES MyGUI MYGUI)
|
||||
FIND_LIBRARY(MYGUI_LIBRARIES MyGUIEngineStatic PATHS /usr/lib /usr/local/lib)
|
||||
SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform")
|
||||
SET(MYGUI_LIB_DIR ${MYGUI_LIBRARIES})
|
||||
STRING(REGEX REPLACE "(.*)/.*" "\\1" MYGUI_LIB_DIR "${MYGUI_LIB_DIR}")
|
||||
STRING(REGEX REPLACE ".*/" "" MYGUI_LIBRARIES "${MYGUI_LIBRARIES}")
|
||||
ENDIF (NOT APPLE)
|
||||
ELSE(MYGUI_STATIC)
|
||||
PKG_SEARCH_MODULE(MYGUI MYGUI MyGUI)
|
||||
IF (MYGUI_INCLUDE_DIRS)
|
||||
SET(MYGUI_INCLUDE_DIRS ${MYGUI_INCLUDE_DIRS})
|
||||
SET(MYGUI_LIB_DIR ${MYGUI_LIBDIR})
|
||||
SET(MYGUI_LIBRARIES ${MYGUI_LIBRARIES} CACHE STRING "")
|
||||
SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform")
|
||||
ELSE (MYGUI_INCLUDE_DIRS)
|
||||
FIND_PATH(MYGUI_INCLUDE_DIRS MyGUI.h PATHS /usr/local/include /usr/include PATH_SUFFIXES MyGUI MYGUI)
|
||||
FIND_LIBRARY(MYGUI_LIBRARIES mygui PATHS /usr/lib /usr/local/lib)
|
||||
SET(MYGUI_PLATFORM_LIBRARIES "MyGUI.OgrePlatform")
|
||||
SET(MYGUI_LIB_DIR ${MYGUI_LIBRARIES})
|
||||
STRING(REGEX REPLACE "(.*)/.*" "\\1" MYGUI_LIB_DIR "${MYGUI_LIB_DIR}")
|
||||
STRING(REGEX REPLACE ".*/" "" MYGUI_LIBRARIES "${MYGUI_LIBRARIES}")
|
||||
ENDIF (MYGUI_INCLUDE_DIRS)
|
||||
ENDIF(MYGUI_STATIC)
|
||||
ENDIF (WIN32)
|
||||
|
||||
#Do some preparation
|
||||
|
@ -120,17 +132,23 @@ SEPARATE_ARGUMENTS(MYGUI_INCLUDE_DIRS)
|
|||
SEPARATE_ARGUMENTS(MYGUI_LIBRARIES)
|
||||
SEPARATE_ARGUMENTS(MYGUI_PLATFORM_LIBRARIES)
|
||||
|
||||
SET(MYGUI_LIBRARIES ${MYGUI_LIBRARIES} ${FREETYPE_LIBRARIES})
|
||||
|
||||
SET(MYGUI_INCLUDE_DIRS ${MYGUI_INCLUDE_DIRS} CACHE PATH "")
|
||||
SET(MYGUI_LIBRARIES ${MYGUI_LIBRARIES} CACHE STRING "")
|
||||
SET(MYGUI_PLATFORM_LIBRARIES ${MYGUI_PLATFORM_LIBRARIES} CACHE STRING "")
|
||||
SET(MYGUI_LIB_DIR ${MYGUI_LIB_DIR} CACHE PATH "")
|
||||
|
||||
IF (MYGUI_INCLUDE_DIRS AND MYGUI_LIBRARIES)
|
||||
IF (NOT APPLE OR NOT MYGUI_STATIC) # we need explicit freetype libs only on OS X for static build, for other cases just make it TRUE
|
||||
SET(FREETYPE_LIBRARIES TRUE)
|
||||
ENDIF (NOT APPLE OR NOT MYGUI_STATIC)
|
||||
|
||||
IF (MYGUI_INCLUDE_DIRS AND MYGUI_LIBRARIES AND FREETYPE_LIBRARIES)
|
||||
SET(MYGUI_FOUND TRUE)
|
||||
ENDIF (MYGUI_INCLUDE_DIRS AND MYGUI_LIBRARIES)
|
||||
ENDIF (MYGUI_INCLUDE_DIRS AND MYGUI_LIBRARIES AND FREETYPE_LIBRARIES)
|
||||
|
||||
IF (MYGUI_FOUND)
|
||||
MARK_AS_ADVANCED(MYGUI_LIB_DIR)
|
||||
MARK_AS_ADVANCED(MYGUI_LIB_DIR)
|
||||
IF (NOT MYGUI_FIND_QUIETLY)
|
||||
MESSAGE(STATUS " libraries : ${MYGUI_LIBRARIES} from ${MYGUI_LIB_DIR}")
|
||||
MESSAGE(STATUS " includes : ${MYGUI_INCLUDE_DIRS}")
|
||||
|
|
|
@ -6,6 +6,10 @@ add_component_dir (settings
|
|||
settings
|
||||
)
|
||||
|
||||
add_component_dir (nifoverrides
|
||||
nifoverrides
|
||||
)
|
||||
|
||||
add_component_dir (bsa
|
||||
bsa_archive bsa_file
|
||||
)
|
||||
|
|
|
@ -79,7 +79,7 @@ class DirArchive: public Ogre::FileSystemArchive
|
|||
{
|
||||
passed = filename.substr(0, filename.length() - 2);
|
||||
}
|
||||
if(filename.at(filename.length() - 2) == '>')
|
||||
if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':')
|
||||
passed = filename.substr(0, filename.length() - 6);
|
||||
copy = passed;
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ public:
|
|||
{
|
||||
passed = filename.substr(0, filename.length() - 2);
|
||||
}
|
||||
if(filename.at(filename.length() - 2) == '>')
|
||||
if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':')
|
||||
passed = filename.substr(0, filename.length() - 6);
|
||||
// Open the file
|
||||
StreamPtr strm = narc->getFile(passed.c_str());
|
||||
|
@ -254,7 +254,7 @@ bool exists(const String& filename) {
|
|||
{
|
||||
passed = filename.substr(0, filename.length() - 2);
|
||||
}
|
||||
if(filename.at(filename.length() - 2) == '>')
|
||||
if(filename.at(filename.length() - 2) == '>' || filename.at(filename.length() - 2) == ':')
|
||||
passed = filename.substr(0, filename.length() - 6);
|
||||
|
||||
return arc.exists(passed.c_str());
|
||||
|
|
|
@ -11,6 +11,7 @@ void PartReferenceList::load(ESMReader &esm)
|
|||
esm.getHT(pr.part); // The INDX byte
|
||||
pr.male = esm.getHNOString("BNAM");
|
||||
pr.female = esm.getHNOString("CNAM");
|
||||
parts.push_back(pr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ void Clothing::load(ESMReader &esm)
|
|||
icon = esm.getHNOString("ITEX");
|
||||
|
||||
parts.load(esm);
|
||||
|
||||
|
||||
enchant = esm.getHNOString("ENAM");
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "ogre_nif_loader.hpp"
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <components/nifoverrides/nifoverrides.hpp>
|
||||
|
||||
typedef unsigned char ubyte;
|
||||
|
||||
|
@ -282,15 +283,61 @@ void NIFLoader::createMaterial(const String &name,
|
|||
// other values. 237 basically means normal transparencly.
|
||||
if (alphaFlags == 237)
|
||||
{
|
||||
// Enable transparency
|
||||
pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||
NifOverrides::TransparencyResult result = NifOverrides::Overrides::getTransparencyOverride(texName);
|
||||
if (result.first)
|
||||
{
|
||||
pass->setAlphaRejectFunction(CMPF_GREATER_EQUAL);
|
||||
pass->setAlphaRejectValue(result.second);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Enable transparency
|
||||
pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||
|
||||
//pass->setDepthCheckEnabled(false);
|
||||
pass->setDepthWriteEnabled(false);
|
||||
//pass->setDepthCheckEnabled(false);
|
||||
pass->setDepthWriteEnabled(false);
|
||||
//std::cout << "alpha 237; material: " << name << " texName: " << texName << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
warn("Unhandled alpha setting for texture " + texName);
|
||||
}
|
||||
else
|
||||
{
|
||||
material->getTechnique(0)->setShadowCasterMaterial("depth_shadow_caster_noalpha");
|
||||
}
|
||||
}
|
||||
|
||||
if (Settings::Manager::getBool("enabled", "Shadows"))
|
||||
{
|
||||
bool split = Settings::Manager::getBool("split", "Shadows");
|
||||
const int numsplits = 3;
|
||||
for (int i = 0; i < (split ? numsplits : 1); ++i)
|
||||
{
|
||||
TextureUnitState* tu = material->getTechnique(0)->getPass(0)->createTextureUnitState();
|
||||
tu->setName("shadowMap" + StringConverter::toString(i));
|
||||
tu->setContentType(TextureUnitState::CONTENT_SHADOW);
|
||||
tu->setTextureAddressingMode(TextureUnitState::TAM_BORDER);
|
||||
tu->setTextureBorderColour(ColourValue::White);
|
||||
}
|
||||
}
|
||||
|
||||
if (Settings::Manager::getBool("shaders", "Objects"))
|
||||
{
|
||||
material->getTechnique(0)->getPass(0)->setVertexProgram("main_vp");
|
||||
material->getTechnique(0)->getPass(0)->setFragmentProgram("main_fp");
|
||||
}
|
||||
|
||||
// Create a fallback technique without shadows and without mrt
|
||||
Technique* tech2 = material->createTechnique();
|
||||
tech2->setSchemeName("Fallback");
|
||||
Pass* pass2 = tech2->createPass();
|
||||
pass2->createTextureUnitState(texName);
|
||||
pass2->setVertexColourTracking(TVC_DIFFUSE);
|
||||
if (Settings::Manager::getBool("shaders", "Objects"))
|
||||
{
|
||||
pass2->setVertexProgram("main_fallback_vp");
|
||||
pass2->setFragmentProgram("main_fallback_fp");
|
||||
}
|
||||
|
||||
// Add material bells and whistles
|
||||
|
@ -299,151 +346,6 @@ void NIFLoader::createMaterial(const String &name,
|
|||
material->setSpecular(specular.array[0], specular.array[1], specular.array[2], alpha);
|
||||
material->setSelfIllumination(emissive.array[0], emissive.array[1], emissive.array[2]);
|
||||
material->setShininess(glossiness);
|
||||
|
||||
if (Settings::Manager::getBool("shaders", "Objects"))
|
||||
{
|
||||
bool mrt = Settings::Manager::getBool("shader", "Water");
|
||||
|
||||
// Create shader for the material
|
||||
// vertex
|
||||
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
||||
|
||||
HighLevelGpuProgramPtr vertex;
|
||||
if (mgr.getByName("main_vp").isNull())
|
||||
{
|
||||
vertex = mgr.createProgram("main_vp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
"cg", GPT_VERTEX_PROGRAM);
|
||||
vertex->setParameter("profiles", "vs_4_0 vs_2_x vp40 arbvp1");
|
||||
vertex->setParameter("entry_point", "main_vp");
|
||||
StringUtil::StrStreamType outStream;
|
||||
outStream <<
|
||||
"void main_vp( \n"
|
||||
" float4 position : POSITION, \n"
|
||||
" float4 normal : NORMAL, \n"
|
||||
" float4 colour : COLOR, \n"
|
||||
" in float2 uv : TEXCOORD0, \n"
|
||||
" out float2 oUV : TEXCOORD0, \n"
|
||||
" out float4 oPosition : POSITION, \n"
|
||||
" out float4 oPositionObjSpace : TEXCOORD1, \n"
|
||||
" out float4 oNormal : TEXCOORD2, \n"
|
||||
" out float oDepth : TEXCOORD3, \n"
|
||||
" out float4 oVertexColour : TEXCOORD4, \n"
|
||||
" uniform float4x4 worldViewProj \n"
|
||||
") \n"
|
||||
"{ \n"
|
||||
" oVertexColour = colour; \n"
|
||||
" oUV = uv; \n"
|
||||
" oNormal = normal; \n"
|
||||
" oPosition = mul( worldViewProj, position ); \n"
|
||||
" oDepth = oPosition.z; \n"
|
||||
" oPositionObjSpace = position; \n"
|
||||
"}";
|
||||
vertex->setSource(outStream.str());
|
||||
vertex->load();
|
||||
vertex->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
||||
}
|
||||
else
|
||||
vertex = mgr.getByName("main_vp");
|
||||
material->getTechnique(0)->getPass(0)->setVertexProgram(vertex->getName());
|
||||
|
||||
// the number of lights to support.
|
||||
// when rendering an object, OGRE automatically picks the lights that are
|
||||
// closest to the object being rendered. unfortunately this mechanism does
|
||||
// not work perfectly for objects batched together (they will all use the same
|
||||
// lights). to work around this, we are simply pushing the maximum number
|
||||
// of lights here in order to minimize disappearing lights.
|
||||
int num_lights = Settings::Manager::getInt("num lights", "Objects");
|
||||
|
||||
// fragment
|
||||
HighLevelGpuProgramPtr fragment;
|
||||
if (mgr.getByName("main_fp").isNull())
|
||||
{
|
||||
fragment = mgr.createProgram("main_fp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
"cg", GPT_FRAGMENT_PROGRAM);
|
||||
fragment->setParameter("profiles", "ps_4_0 ps_2_x fp40 arbfp1");
|
||||
fragment->setParameter("entry_point", "main_fp");
|
||||
StringUtil::StrStreamType outStream;
|
||||
outStream <<
|
||||
"void main_fp( \n"
|
||||
" in float2 uv : TEXCOORD0, \n"
|
||||
" out float4 oColor : COLOR, \n"
|
||||
" uniform sampler2D texture : TEXUNIT0, \n"
|
||||
" float4 positionObjSpace : TEXCOORD1, \n"
|
||||
" float4 normal : TEXCOORD2, \n"
|
||||
" float iDepth : TEXCOORD3, \n"
|
||||
" float4 vertexColour : TEXCOORD4, \n"
|
||||
" uniform float4 fogColour, \n"
|
||||
" uniform float4 fogParams, \n";
|
||||
|
||||
if (mrt) outStream <<
|
||||
" out float4 oColor1 : COLOR1, \n"
|
||||
" uniform float far, \n";
|
||||
|
||||
for (int i=0; i<num_lights; ++i)
|
||||
{
|
||||
outStream <<
|
||||
" uniform float4 lightDiffuse"<<i<<", \n"
|
||||
" uniform float4 lightPositionObjSpace"<<i<<", \n"
|
||||
" uniform float4 lightAttenuation"<<i<<", \n";
|
||||
}
|
||||
outStream <<
|
||||
" uniform float4 lightAmbient, \n"
|
||||
" uniform float4 ambient, \n"
|
||||
" uniform float4 diffuse, \n"
|
||||
" uniform float4 emissive \n"
|
||||
") \n"
|
||||
"{ \n"
|
||||
" float4 tex = tex2D(texture, uv); \n"
|
||||
" float d; \n"
|
||||
" float attn; \n"
|
||||
" float3 lightColour = float3(0, 0, 0); \n";
|
||||
|
||||
for (int i=0; i<num_lights; ++i)
|
||||
{
|
||||
outStream <<
|
||||
" float3 lightDir"<<i<<" = lightPositionObjSpace"<<i<<".xyz - (positionObjSpace.xyz * lightPositionObjSpace"<<i<<".w); \n"
|
||||
|
||||
// pre-multiply light color with attenuation factor
|
||||
" d = length( lightDir"<<i<<" ); \n"
|
||||
" attn = ( 1.0 / (( lightAttenuation"<<i<<".y ) + ( lightAttenuation"<<i<<".z * d ) + ( lightAttenuation"<<i<<".w * d * d ))); \n"
|
||||
" lightDiffuse"<<i<<" *= attn; \n"
|
||||
|
||||
" lightColour.xyz += lit(dot(normalize(lightDir"<<i<<"), normalize(normal)), 0, 0).y * lightDiffuse"<<i<<".xyz;\n";
|
||||
}
|
||||
|
||||
outStream <<
|
||||
" float3 lightingFinal = lightColour.xyz * diffuse.xyz * vertexColour.xyz + ambient.xyz * lightAmbient.xyz + emissive.xyz; \n"
|
||||
" float fogValue = saturate((iDepth - fogParams.y) * fogParams.w); \n"
|
||||
" oColor.xyz = lerp(lightingFinal * tex.xyz, fogColour, fogValue); \n"
|
||||
" oColor.a = tex.a * diffuse.a * vertexColour.a; \n";
|
||||
|
||||
if (mrt) outStream <<
|
||||
" oColor1 = float4(iDepth / far, 0, 0, (oColor.a == 1)); \n"; // only write to MRT if alpha is 1
|
||||
|
||||
outStream <<
|
||||
"}";
|
||||
fragment->setSource(outStream.str());
|
||||
fragment->load();
|
||||
|
||||
for (int i=0; i<num_lights; ++i)
|
||||
{
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightPositionObjSpace"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, i);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightDiffuse"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, i);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightAttenuation"+StringConverter::toString(i), GpuProgramParameters::ACT_LIGHT_ATTENUATION, i);
|
||||
}
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_SURFACE_AMBIENT_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("lightAmbient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR);
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
|
||||
if (mrt)
|
||||
fragment->getDefaultParameters()->setNamedAutoConstant("far", GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
|
||||
}
|
||||
else
|
||||
fragment = mgr.getByName("main_fp");
|
||||
material->getTechnique(0)->getPass(0)->setFragmentProgram(fragment->getName());
|
||||
}
|
||||
}
|
||||
|
||||
// Takes a name and adds a unique part to it. This is just used to
|
||||
|
@ -1309,6 +1211,7 @@ void NIFLoader::loadResource(Resource *resource)
|
|||
char suffix = name.at(name.length() - 2);
|
||||
bool addAnim = true;
|
||||
bool hasAnim = false;
|
||||
bool linkSkeleton = true;
|
||||
//bool baddin = false;
|
||||
bNiTri = true;
|
||||
if(name == "meshes\\base_anim.nif" || name == "meshes\\base_animkna.nif")
|
||||
|
@ -1339,6 +1242,17 @@ void NIFLoader::loadResource(Resource *resource)
|
|||
addAnim = false;
|
||||
|
||||
}
|
||||
else if(suffix == ':')
|
||||
{
|
||||
//baddin = true;
|
||||
linkSkeleton = false;
|
||||
bNiTri = true;
|
||||
std::string sub = name.substr(name.length() - 6, 4);
|
||||
|
||||
if(sub.compare("0000") != 0)
|
||||
addAnim = false;
|
||||
|
||||
}
|
||||
|
||||
switch(name.at(name.length() - 1))
|
||||
{
|
||||
|
@ -1477,7 +1391,7 @@ void NIFLoader::loadResource(Resource *resource)
|
|||
}
|
||||
//Don't link on npc parts to eliminate redundant skeletons
|
||||
//Will have to be changed later slightly for robes/skirts
|
||||
if(triname == "")
|
||||
if(linkSkeleton)
|
||||
mesh->_notifySkeleton(mSkel);
|
||||
}
|
||||
}
|
||||
|
|
37
components/nifoverrides/nifoverrides.cpp
Normal file
37
components/nifoverrides/nifoverrides.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include "nifoverrides.hpp"
|
||||
|
||||
#include <OgreStringConverter.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
using namespace NifOverrides;
|
||||
|
||||
Ogre::ConfigFile Overrides::mTransparencyOverrides = Ogre::ConfigFile();
|
||||
|
||||
void Overrides::loadTransparencyOverrides (const std::string& file)
|
||||
{
|
||||
mTransparencyOverrides.load(file);
|
||||
}
|
||||
|
||||
TransparencyResult Overrides::getTransparencyOverride(const std::string& texture)
|
||||
{
|
||||
TransparencyResult result;
|
||||
result.first = false;
|
||||
|
||||
std::string tex = texture;
|
||||
boost::to_lower(tex);
|
||||
|
||||
Ogre::ConfigFile::SectionIterator seci = mTransparencyOverrides.getSectionIterator();
|
||||
while (seci.hasMoreElements())
|
||||
{
|
||||
Ogre::String sectionName = seci.peekNextKey();
|
||||
if (sectionName == tex)
|
||||
{
|
||||
result.first = true;
|
||||
result.second = Ogre::StringConverter::parseInt(mTransparencyOverrides.getSetting("alphaRejectValue", sectionName));
|
||||
break;
|
||||
}
|
||||
seci.getNext();
|
||||
}
|
||||
return result;
|
||||
}
|
23
components/nifoverrides/nifoverrides.hpp
Normal file
23
components/nifoverrides/nifoverrides.hpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef COMPONENTS_NIFOVERRIDES_H
|
||||
#define COMPONENTS_NIFOVERRIDES_H
|
||||
|
||||
#include <OgreConfigFile.h>
|
||||
|
||||
namespace NifOverrides
|
||||
{
|
||||
|
||||
typedef std::pair<bool, int> TransparencyResult;
|
||||
|
||||
/// \brief provide overrides for some model / texture properties that bethesda has chosen poorly
|
||||
class Overrides
|
||||
{
|
||||
public:
|
||||
static Ogre::ConfigFile mTransparencyOverrides;
|
||||
void loadTransparencyOverrides (const std::string& file);
|
||||
|
||||
static TransparencyResult getTransparencyOverride(const std::string& texture);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -11,3 +11,6 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/water/water.cg "${OpenMW_BINARY_DIR}/
|
|||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer/gbuffer.cg "${OpenMW_BINARY_DIR}/resources/gbuffer/gbuffer.cg" COPYONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer/gbuffer.material "${OpenMW_BINARY_DIR}/resources/gbuffer/gbuffer.material" COPYONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gbuffer/gbuffer.compositor "${OpenMW_BINARY_DIR}/resources/gbuffer/gbuffer.compositor" COPYONLY)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/shadows/depthshadowcaster.material "${OpenMW_BINARY_DIR}/resources/shadows/depthshadowcaster.material" COPYONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/shadows/depthshadowcaster.cg "${OpenMW_BINARY_DIR}/resources/shadows/depthshadowcaster.cg" COPYONLY)
|
||||
|
|
|
@ -8,7 +8,6 @@ configure_file("${SDIR}/bigbars.png" "${DDIR}/bigbars.png" COPYONLY)
|
|||
configure_file("${SDIR}/black.png" "${DDIR}/black.png" COPYONLY)
|
||||
configure_file("${SDIR}/core.skin" "${DDIR}/core.skin" COPYONLY)
|
||||
configure_file("${SDIR}/core.xml" "${DDIR}/core.xml" COPYONLY)
|
||||
configure_file("${SDIR}/mwpointer.png" "${DDIR}/mwpointer.png" COPYONLY)
|
||||
configure_file("${SDIR}/mwgui.png" "${DDIR}/mwgui.png" COPYONLY)
|
||||
configure_file("${SDIR}/openmw_images.xml" "${DDIR}/openmw_images.xml" COPYONLY)
|
||||
configure_file("${SDIR}/openmw_settings.xml" "${DDIR}/openmw_settings.xml" COPYONLY)
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 4.7 KiB |
|
@ -2,37 +2,37 @@
|
|||
|
||||
<MyGUI type="Resource">
|
||||
<Resource type="ResourceImageSet" name="ArrowPointerImage">
|
||||
<Group name="Pointer" texture="mwpointer.png" size="32 32">
|
||||
<Group name="Pointer" texture="textures\tx_cursor.dds" size="32 32">
|
||||
<Index name="Pointer" >
|
||||
<Frame point="0 0"/>
|
||||
</Index>
|
||||
</Group>
|
||||
</Resource>
|
||||
<Resource type="ResourceImageSet" name="HResizePointerImage">
|
||||
<Group name="Pointer" texture="mwpointer.png" size="32 32">
|
||||
<Group name="Pointer" texture="textures\tx_cursormove.dds" size="32 32">
|
||||
<Index name="Pointer" >
|
||||
<Frame point="32 0"/>
|
||||
<Frame point="0 0"/>
|
||||
</Index>
|
||||
</Group>
|
||||
</Resource>
|
||||
<Resource type="ResourceImageSet" name="VResizePointerImage">
|
||||
<Group name="Pointer" texture="mwpointer.png" size="32 32">
|
||||
<Group name="Pointer" texture="mwpointer_vresize.png" size="32 32">
|
||||
<Index name="Pointer" >
|
||||
<Frame point="0 32"/>
|
||||
<Frame point="0 0"/>
|
||||
</Index>
|
||||
</Group>
|
||||
</Resource>
|
||||
<Resource type="ResourceImageSet" name="DResizePointerImage">
|
||||
<Group name="Pointer" texture="mwpointer.png" size="32 32">
|
||||
<Group name="Pointer" texture="mwpointer_dresize1.png" size="32 32">
|
||||
<Index name="Pointer" >
|
||||
<Frame point="32 32"/>
|
||||
<Frame point="o o"/>
|
||||
</Index>
|
||||
</Group>
|
||||
</Resource>
|
||||
<Resource type="ResourceImageSet" name="DResize2PointerImage">
|
||||
<Group name="Pointer" texture="mwpointer.png" size="32 32">
|
||||
<Group name="Pointer" texture="mwpointer_dresize2.png" size="32 32">
|
||||
<Index name="Pointer" >
|
||||
<Frame point="64 32"/>
|
||||
<Frame point="0 0"/>
|
||||
</Index>
|
||||
</Group>
|
||||
</Resource>
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MyGUI type="Resource" version="1.1">
|
||||
<Resource type="ResourceSkin" name="Skin name 0" size="32 32" texture="">
|
||||
<BasisSkin type="SubSkin" offset="0 0 32 32" align="Stretch">
|
||||
<State name="normal" offset="0 0 32 32"/>
|
||||
</BasisSkin>
|
||||
</Resource>
|
||||
</MyGUI>
|
|
@ -1,5 +1,5 @@
|
|||
[Desktop Entry]
|
||||
Version=0.11
|
||||
Version=${OPENMW_VERSION}
|
||||
Type=Application
|
||||
Name=OpenMW Launcher
|
||||
GenericName=Role Playing Game
|
||||
|
|
|
@ -18,6 +18,32 @@ anisotropy = 4
|
|||
# Number of texture mipmaps to generate
|
||||
num mipmaps = 5
|
||||
|
||||
[Shadows]
|
||||
# Shadows are only supported when object shaders are on!
|
||||
enabled = false
|
||||
|
||||
# Split the shadow maps, allows for a larger shadow distance
|
||||
# Warning: enabling this will cause some terrain textures to disappear due to
|
||||
# hitting the texture unit limit of the terrain material
|
||||
split = false
|
||||
|
||||
# Increasing shadow distance will lower the shadow quality.
|
||||
# Uses "shadow distance" or "split shadow distance" depending on "split" setting.
|
||||
shadow distance = 1300
|
||||
# This one shouldn't be too low, otherwise you'll see artifacts. Use at least 2x max viewing distance.
|
||||
split shadow distance = 14000
|
||||
|
||||
# Size of the shadow textures, higher means higher quality
|
||||
texture size = 1024
|
||||
|
||||
# Turn on/off various shadow casters
|
||||
actor shadows = true
|
||||
misc shadows = true
|
||||
statics shadows = true
|
||||
|
||||
# Fraction of the total shadow distance after which the shadow starts to fade out
|
||||
fade start = 0.8
|
||||
|
||||
[HUD]
|
||||
# FPS counter
|
||||
# 0: not visible
|
||||
|
@ -64,15 +90,10 @@ num lights = 8
|
|||
shader = true
|
||||
|
||||
rtt size = 512
|
||||
|
||||
reflect terrain = true
|
||||
|
||||
reflect statics = false
|
||||
|
||||
reflect small statics = false
|
||||
|
||||
reflect actors = true
|
||||
|
||||
reflect actors = false
|
||||
reflect misc = false
|
||||
|
||||
# Enable underwater effect. It is not resource intensive, so only disable it if you have problems.
|
||||
|
|
51
files/shadows/depthshadowcaster.cg
Normal file
51
files/shadows/depthshadowcaster.cg
Normal file
|
@ -0,0 +1,51 @@
|
|||
void main_vp(
|
||||
float4 position : POSITION,
|
||||
float2 uv : TEXCOORD0,
|
||||
|
||||
out float4 oPosition : POSITION,
|
||||
out float2 oDepth : TEXCOORD0,
|
||||
out float2 oUv : TEXCOORD1,
|
||||
|
||||
uniform float4x4 wvpMat)
|
||||
{
|
||||
// this is the view space position
|
||||
oPosition = mul(wvpMat, position);
|
||||
|
||||
// depth info for the fragment.
|
||||
oDepth.x = oPosition.z;
|
||||
oDepth.y = oPosition.w;
|
||||
|
||||
// clamp z to zero. seem to do the trick. :-/
|
||||
oPosition.z = max(oPosition.z, 0);
|
||||
|
||||
oUv = uv;
|
||||
}
|
||||
|
||||
void main_fp(
|
||||
float2 depth : TEXCOORD0,
|
||||
float2 uv : TEXCOORD1,
|
||||
uniform sampler2D texture1 : register(s0),
|
||||
|
||||
out float4 oColour : COLOR)
|
||||
{
|
||||
float finalDepth = depth.x / depth.y;
|
||||
|
||||
// use alpha channel of the first texture
|
||||
float alpha = tex2D(texture1, uv).a;
|
||||
|
||||
// discard if alpha is less than 0.5
|
||||
clip((alpha >= 0.5) ? 1 : -1);
|
||||
|
||||
oColour = float4(finalDepth, finalDepth, finalDepth, 1);
|
||||
}
|
||||
|
||||
void main_fp_noalpha(
|
||||
float2 depth : TEXCOORD0,
|
||||
float2 uv : TEXCOORD1,
|
||||
|
||||
out float4 oColour : COLOR)
|
||||
{
|
||||
float finalDepth = depth.x / depth.y;
|
||||
|
||||
oColour = float4(finalDepth, finalDepth, finalDepth, 1);
|
||||
}
|
67
files/shadows/depthshadowcaster.material
Normal file
67
files/shadows/depthshadowcaster.material
Normal file
|
@ -0,0 +1,67 @@
|
|||
vertex_program depth_shadow_caster_vs cg
|
||||
{
|
||||
source depthshadowcaster.cg
|
||||
profiles vs_1_1 arbvp1
|
||||
entry_point main_vp
|
||||
|
||||
default_params
|
||||
{
|
||||
param_named_auto wvpMat worldviewproj_matrix
|
||||
}
|
||||
}
|
||||
|
||||
fragment_program depth_shadow_caster_ps cg
|
||||
{
|
||||
source depthshadowcaster.cg
|
||||
profiles ps_2_0 arbfp1
|
||||
entry_point main_fp
|
||||
|
||||
default_params
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
fragment_program depth_shadow_caster_ps_noalpha cg
|
||||
{
|
||||
source depthshadowcaster.cg
|
||||
profiles ps_2_0 arbfp1
|
||||
entry_point main_fp_noalpha
|
||||
|
||||
default_params
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
material depth_shadow_caster
|
||||
{
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_program_ref depth_shadow_caster_vs
|
||||
{
|
||||
}
|
||||
|
||||
fragment_program_ref depth_shadow_caster_ps
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
material depth_shadow_caster_noalpha
|
||||
{
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_program_ref depth_shadow_caster_vs
|
||||
{
|
||||
}
|
||||
|
||||
fragment_program_ref depth_shadow_caster_ps_noalpha
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
574
files/transparency-overrides.cfg
Normal file
574
files/transparency-overrides.cfg
Normal file
|
@ -0,0 +1,574 @@
|
|||
# Bethesda has used wrong transparency settings for many textures
|
||||
# (who would have guessed)
|
||||
# This is very unfortunate because objects with real transparency:
|
||||
# - cannot cast shadows
|
||||
# - cannot receive advanced framebuffer effects like depth of field or ambient occlusion
|
||||
# - cannot cover lens flare effects (the lens flare will just shine through)
|
||||
|
||||
# This file lists textures that should be using alpha rejection instead of transparency
|
||||
# basically these are textures that are not translucent (i.e. at one spot on the texture, either transparent or opaque)
|
||||
|
||||
# Note: all the texture names here have to be lowercase
|
||||
|
||||
# fauna
|
||||
[textures\tx_wickwheat_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_wickwheat_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_red_lichen_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_stone_flower_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ivy_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ivy_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_saltrice_04.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_black_lichen_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_leaves_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_leaves_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_leaves_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_leaves_04.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_leaves_06.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_leaves_07.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ai_heather_01.dds]
|
||||
alphaRejectValue = 96
|
||||
|
||||
[textures\tx_goldkanet_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_goldkanet_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_plant_tails00.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_vine_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_comberry_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_willow_flower_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_cork_bulb_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_green_lichen_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_roobrush_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bittergreen_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_chokeweed_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_branches_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_branches_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_guarskin_hut_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_hackle-lo_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bc_fern_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bc_fern_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bc_leaves_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_marshmerrow_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bc_moss_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bc_moss_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bc_lilypad_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bc_lilypad_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bc_lilypad_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_fire_fern_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
# banners and flags
|
||||
[textures\tx_flag_imp_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_arena_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_comfort_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_child_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_count_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_faith_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_walk_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_imp_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_redoran_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_avs_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_serving_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_speak_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_stdeyln_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_stolms_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_thin_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_vivec_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_vivec_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_banner_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_banner_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_banner_04.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_banner_05.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_banner_06.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_banner_07.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_a_banner.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_e_banner.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_u_banner.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_z_banner.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_6th.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_6th_tall.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_gnisis_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_gnisis_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_bhm_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_04.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_05.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_06.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_07.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_08.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_08.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_09.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_10.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_11.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_12.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_tapestry_13.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_lutestrings_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_fabric_imp_altar_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_akatosh_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_apprentice_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_arkay_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_dibella_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_golem_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_julianos_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_kynareth_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_lady_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_lord_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_lover_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_mara_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_ritual_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_shadow_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_steed_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_stendarr_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_thief_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_tower_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_warrior_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_wizard_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_c_t_zenithar_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_dagoth_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bannerd_tavern_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bannerd_goods_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bannerd_danger_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bannerd_welcome_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bannerd_clothing_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bannerd_alchemy_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_hlaalu_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_redoran_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_temple_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_temple_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_book_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_ald_velothi.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_gnaar_mok.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_hla_oad.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_khull.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_pawn_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_sadrith_mora.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_tel_aruhn.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_tel_branora.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_tel_fyr.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_tel_mora.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_telvani_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_tel_vos.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_de_banner_vos.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bannerd_w_a_shop_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_banner_temple_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_mural1_00.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_mural1_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_mural4_00.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_mural4_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_mural5_00.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_telvanni_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_v_b_hlaalu_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_fabric_tapestry.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_fabric_tapestry_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_fabric_tapestry_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_fabric_tapestry_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_fabric_tapestry_04.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
# characters
|
||||
[textures\tx_netchgod00.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_argonian_f_hair02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_argonian_f_hair03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_argonian_m_hair01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_argonian_m_hair04.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_argonian_m_hair05.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_khajiit_f_hair01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_khajiit_f_hair02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_khajiit_m_hair01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_corprus_stalker12.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_a_clavicus02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_dark elf_m_hair11.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_b_n_dark elf_f_hair10.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
# misc items
|
||||
[textures\tx_sail.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_longboatsail01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_longboatsail01a.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_longboatsail01b.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_longboatsail02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_quill.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_note_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_note_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_parchment_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_parchment_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_scroll_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_scroll_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_scroll_03.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_alpha_small_edge.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_alpha_shadow_circular.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
# building materials
|
||||
[textures\tx_shack_thatch_strip.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_rug00.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_rug_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_rug_edge_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_awning_thatch_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_awning_woven_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_bridgeropes.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_rope_woven_01.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_rope_woven_02.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_ashl_tent_06.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_guar_tarp.dds]
|
||||
alphaRejectValue = 128
|
||||
|
||||
[textures\tx_velothi_glyph00.dds]
|
||||
alphaRejectValue = 128
|
|
@ -92,7 +92,7 @@ material Water
|
|||
}
|
||||
technique
|
||||
{
|
||||
scheme Map
|
||||
scheme Fallback
|
||||
pass
|
||||
{
|
||||
cull_hardware none
|
||||
|
|
62
libs/openengine/bullet/trace.h
Normal file
62
libs/openengine/bullet/trace.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
#ifndef OENGINE_BULLET_TRACE_H
|
||||
#define OENGINE_BULLET_TRACE_H
|
||||
|
||||
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
#include <btBulletCollisionCommon.h>
|
||||
#include <components/nifbullet/bullet_nif_loader.hpp>
|
||||
//#include <apps\openmw\mwworld\world.hpp>
|
||||
#include <openengine/bullet/pmove.h>
|
||||
#include <openengine/bullet/physic.hpp>
|
||||
|
||||
|
||||
|
||||
enum traceWorldType
|
||||
{
|
||||
collisionWorldTrace = 1,
|
||||
pickWorldTrace = 2,
|
||||
bothWorldTrace = collisionWorldTrace | pickWorldTrace
|
||||
};
|
||||
|
||||
enum collaborativePhysicsType : unsigned
|
||||
{
|
||||
No_Physics = 0, // Both are empty (example: statics you can walk through, like tall grass)
|
||||
Only_Collision = 1, // This object only has collision physics but no pickup physics (example: statics)
|
||||
Only_Pickup = 2, // This object only has pickup physics but no collision physics (example: items dropped on the ground)
|
||||
Both_Physics = 3 // This object has both kinds of physics (example: activators)
|
||||
};
|
||||
|
||||
struct NewPhysTraceResults
|
||||
{
|
||||
Ogre::Vector3 endPos;
|
||||
Ogre::Vector3 hitNormal;
|
||||
float fraction;
|
||||
bool startSolid;
|
||||
//const Object* hitObj;
|
||||
};
|
||||
struct traceResults
|
||||
{
|
||||
Ogre::Vector3 endpos;
|
||||
Ogre::Vector3 planenormal;
|
||||
|
||||
float fraction;
|
||||
|
||||
int surfaceFlags;
|
||||
int contents;
|
||||
int entityNum;
|
||||
|
||||
bool allsolid;
|
||||
bool startsolid;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <const traceWorldType traceType>
|
||||
const bool NewPhysicsTrace(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass);
|
||||
template const bool NewPhysicsTrace<collisionWorldTrace>(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass);
|
||||
template const bool NewPhysicsTrace<pickWorldTrace>(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass);
|
||||
|
||||
void newtrace(traceResults* const results, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const float rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass);
|
||||
|
||||
|
||||
#endif
|
|
@ -18,7 +18,6 @@ void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool
|
|||
// manager before the main gui system itself, otherwise the main
|
||||
// object will get the chance to spit out a few messages before we
|
||||
// can able to disable it.
|
||||
/// \todo - can't avoid this with MyGUI 3.2?
|
||||
|
||||
std::string theLogFile = std::string(MYGUI_PLATFORM_LOG_FILENAME);
|
||||
if(!logDir.empty())
|
||||
|
@ -26,9 +25,9 @@ void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool
|
|||
|
||||
// Set up OGRE platform. We might make this more generic later.
|
||||
mPlatform = new OgrePlatform();
|
||||
LogManager::getInstance().setSTDOutputEnabled(logging);
|
||||
mPlatform->initialise(wnd, mgr, "General", theLogFile);
|
||||
|
||||
LogManager::getInstance().setSTDOutputEnabled(logging);
|
||||
|
||||
// Create GUI
|
||||
mGui = new Gui();
|
||||
|
|
74
libs/openengine/ogre/imagerotate.cpp
Normal file
74
libs/openengine/ogre/imagerotate.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
#include "imagerotate.hpp"
|
||||
|
||||
#include <OgreRoot.h>
|
||||
#include <OgreSceneManager.h>
|
||||
#include <OgreImage.h>
|
||||
#include <OgreTexture.h>
|
||||
#include <OgreRenderTarget.h>
|
||||
#include <OgreCamera.h>
|
||||
#include <OgreTextureUnitState.h>
|
||||
#include <OgreHardwarePixelBuffer.h>
|
||||
|
||||
using namespace Ogre;
|
||||
using namespace OEngine::Render;
|
||||
|
||||
void ImageRotate::rotate(const std::string& sourceImage, const std::string& destImage, const float angle)
|
||||
{
|
||||
Root* root = Ogre::Root::getSingletonPtr();
|
||||
|
||||
SceneManager* sceneMgr = root->createSceneManager(ST_GENERIC);
|
||||
Camera* camera = sceneMgr->createCamera("ImageRotateCamera");
|
||||
|
||||
MaterialPtr material = MaterialManager::getSingleton().create("ImageRotateMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||
material->getTechnique(0)->getPass(0)->setLightingEnabled(false);
|
||||
material->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false);
|
||||
TextureUnitState* tus = material->getTechnique(0)->getPass(0)->createTextureUnitState(sourceImage);
|
||||
Degree deg(angle);
|
||||
tus->setTextureRotate(Radian(deg.valueRadians()));
|
||||
tus->setTextureAddressingMode(TextureUnitState::TAM_BORDER);
|
||||
tus->setTextureBorderColour(ColourValue(0, 0, 0, 0));
|
||||
|
||||
Rectangle2D* rect = new Rectangle2D(true);
|
||||
rect->setCorners(-1.0, 1.0, 1.0, -1.0);
|
||||
rect->setMaterial("ImageRotateMaterial");
|
||||
// Render the background before everything else
|
||||
rect->setRenderQueueGroup(RENDER_QUEUE_BACKGROUND);
|
||||
|
||||
// Use infinite AAB to always stay visible
|
||||
AxisAlignedBox aabInf;
|
||||
aabInf.setInfinite();
|
||||
rect->setBoundingBox(aabInf);
|
||||
|
||||
// Attach background to the scene
|
||||
SceneNode* node = sceneMgr->getRootSceneNode()->createChildSceneNode();
|
||||
node->attachObject(rect);
|
||||
|
||||
// retrieve image width and height
|
||||
TexturePtr sourceTexture = TextureManager::getSingleton().getByName(sourceImage);
|
||||
unsigned int width = sourceTexture->getWidth();
|
||||
unsigned int height = sourceTexture->getHeight();
|
||||
|
||||
TexturePtr destTexture = TextureManager::getSingleton().createManual(
|
||||
destImage,
|
||||
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
TEX_TYPE_2D,
|
||||
width, height,
|
||||
0,
|
||||
PF_A8R8G8B8,
|
||||
TU_RENDERTARGET);
|
||||
|
||||
RenderTarget* rtt = destTexture->getBuffer()->getRenderTarget();
|
||||
rtt->setAutoUpdated(false);
|
||||
Viewport* vp = rtt->addViewport(camera);
|
||||
vp->setOverlaysEnabled(false);
|
||||
vp->setShadowsEnabled(false);
|
||||
vp->setBackgroundColour(ColourValue(0,0,0,0));
|
||||
vp->setClearEveryFrame(true, FBT_DEPTH);
|
||||
|
||||
rtt->update();
|
||||
|
||||
// remove all the junk we've created
|
||||
MaterialManager::getSingleton().remove("ImageRotateMaterial");
|
||||
root->destroySceneManager(sceneMgr);
|
||||
delete rect;
|
||||
}
|
27
libs/openengine/ogre/imagerotate.hpp
Normal file
27
libs/openengine/ogre/imagerotate.hpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#ifndef OENGINE_OGRE_IMAGEROTATE_HPP
|
||||
#define OENGINE_OGRE_IMAGEROTATE_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace OEngine
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
|
||||
/// Rotate an image by certain degrees and save as file, uses the GPU
|
||||
/// Make sure Ogre Root is initialised before calling
|
||||
class ImageRotate
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param source image (file name - has to exist in an resource group)
|
||||
* @param name of the destination texture to save to (in memory)
|
||||
* @param angle in degrees to turn
|
||||
*/
|
||||
static void rotate(const std::string& sourceImage, const std::string& destImage, const float angle);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
36
readme.txt
36
readme.txt
|
@ -3,7 +3,7 @@ OpenMW: A reimplementation of The Elder Scrolls III: Morrowind
|
|||
OpenMW is an attempt at recreating the engine for the popular role-playing game
|
||||
Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work.
|
||||
|
||||
Version: 0.13.0
|
||||
Version: 0.14.0
|
||||
License: GPL (see GPL3.txt for more information)
|
||||
Website: http://www.openmw.org
|
||||
|
||||
|
@ -64,8 +64,6 @@ Allowed options:
|
|||
--start arg (=Beshara) set initial cell
|
||||
--master arg master file(s)
|
||||
--plugin arg plugin file(s)
|
||||
--fps [=arg(=1)] (=0) fps counter detail (0 = off, 1 = fps counter
|
||||
, 2 = full detail)
|
||||
--anim-verbose [=arg(=1)] (=0) output animation indices files
|
||||
--debug [=arg(=1)] (=0) debug mode
|
||||
--nosound [=arg(=1)] (=0) disable all sounds
|
||||
|
@ -90,11 +88,13 @@ Allowed options:
|
|||
win1252 - Western European (Latin) alphabet,
|
||||
used by default
|
||||
--report-focus [=arg(=1)] (=0) write name of focussed object to cout
|
||||
--fallback arg fallback values
|
||||
|
||||
|
||||
CREDITS
|
||||
|
||||
Current Developers:
|
||||
Aleksandar Jovanov
|
||||
Alexander “Ace” Olofsson
|
||||
athile
|
||||
BrotherBrick
|
||||
|
@ -133,6 +133,36 @@ Thanks to Kevin Ryan for kindly providing us with the icon used for the Data Fil
|
|||
|
||||
CHANGELOG
|
||||
|
||||
0.14.0
|
||||
|
||||
Bug #1: Meshes rendered with wrong orientation
|
||||
Bug #6/Task #220: Picking up small objects doesn't always work
|
||||
Bug #127: tcg doesn't work
|
||||
Bug #178: Compablity problems with Ogre 1.8.0 RC 1
|
||||
Bug #211: Wireframe mode (toggleWireframe command) should not apply to Console & other UI
|
||||
Bug #227: Terrain crashes when moving away from predefined cells
|
||||
Bug #229: On OS X Launcher cannot launch game if path to binary contains spaces
|
||||
Bug #235: TGA texture loading problem
|
||||
Bug #246: wireframe mode does not work in water
|
||||
Feature #8/#232: Water Rendering
|
||||
Feature #13: Terrain Rendering
|
||||
Feature #37: Render Path Grid
|
||||
Feature #66: Factions
|
||||
Feature #77: Local Map
|
||||
Feature #78: Compass/Mini-Map
|
||||
Feature #97: Render Clothing/Armour
|
||||
Feature #121: Window Pinning
|
||||
Feature #205: Auto equip
|
||||
Feature #217: Contiainer should track changes to its content
|
||||
Feature #221: NPC Dialogue Window Enhancements
|
||||
Feature #233: Game settings manager
|
||||
Feature #240: Spell List and selected spell (no GUI yet)
|
||||
Feature #243: Draw State
|
||||
Task #113: Morrowind.ini Importer
|
||||
Task #215: Refactor the sound code
|
||||
Task #216: Update MyGUI
|
||||
|
||||
|
||||
0.13.0
|
||||
|
||||
Bug #145: Fixed sound problems after cell change
|
||||
|
|
Loading…
Reference in a new issue