mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-26 09:35:28 +00:00
Merge branch 'master' into gamesettings
This commit is contained in:
commit
55c984c179
@ -15,7 +15,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER})
|
|||||||
|
|
||||||
add_openmw_dir (mwrender
|
add_openmw_dir (mwrender
|
||||||
renderingmanager debugging sky player animation npcanimation creatureanimation actors objects
|
renderingmanager debugging sky player animation npcanimation creatureanimation actors objects
|
||||||
renderinginterface localmap water terrain terrainmaterial
|
renderinginterface localmap occlusionquery terrain terrainmaterial water
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwinput
|
add_openmw_dir (mwinput
|
||||||
|
@ -204,13 +204,18 @@ OMW::Engine::~Engine()
|
|||||||
void OMW::Engine::loadBSA()
|
void OMW::Engine::loadBSA()
|
||||||
{
|
{
|
||||||
const Files::MultiDirCollection& bsa = mFileCollections.getCollection (".bsa");
|
const Files::MultiDirCollection& bsa = mFileCollections.getCollection (".bsa");
|
||||||
std::string dataDirectory;
|
|
||||||
for (Files::MultiDirCollection::TIter iter(bsa.begin()); iter!=bsa.end(); ++iter)
|
for (Files::MultiDirCollection::TIter iter(bsa.begin()); iter!=bsa.end(); ++iter)
|
||||||
{
|
{
|
||||||
std::cout << "Adding " << iter->second.string() << std::endl;
|
std::cout << "Adding " << iter->second.string() << std::endl;
|
||||||
Bsa::addBSA(iter->second.string());
|
Bsa::addBSA(iter->second.string());
|
||||||
|
}
|
||||||
|
|
||||||
dataDirectory = iter->second.parent_path().string();
|
const Files::PathContainer& dataDirs = mFileCollections.getPaths();
|
||||||
|
std::string dataDirectory;
|
||||||
|
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
|
||||||
|
{
|
||||||
|
dataDirectory = iter->string();
|
||||||
std::cout << "Data dir " << dataDirectory << std::endl;
|
std::cout << "Data dir " << dataDirectory << std::endl;
|
||||||
Bsa::addDir(dataDirectory, mFSStrict);
|
Bsa::addDir(dataDirectory, mFSStrict);
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ namespace MWClass
|
|||||||
boost::shared_ptr<MWWorld::Action> Apparatus::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Apparatus::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, false, true);
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr), 1.0, 1.0, MWSound::Play_NoTrack);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
|
@ -60,7 +60,7 @@ namespace MWClass
|
|||||||
boost::shared_ptr<MWWorld::Action> Armor::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Armor::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
|
@ -58,7 +58,7 @@ namespace MWClass
|
|||||||
{
|
{
|
||||||
// TODO implement reading
|
// TODO implement reading
|
||||||
|
|
||||||
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
|
@ -57,7 +57,7 @@ namespace MWClass
|
|||||||
boost::shared_ptr<MWWorld::Action> Clothing::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Clothing::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
|
@ -85,7 +85,7 @@ namespace MWClass
|
|||||||
{
|
{
|
||||||
// TODO check for key
|
// TODO check for key
|
||||||
std::cout << "Locked container" << std::endl;
|
std::cout << "Locked container" << std::endl;
|
||||||
environment.mSoundManager->playSound3D (ptr, lockedSound, 1.0, 1.0, false);
|
environment.mSoundManager->playSound3D (ptr, lockedSound, 1.0, 1.0);
|
||||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -100,7 +100,7 @@ namespace MWClass
|
|||||||
{
|
{
|
||||||
// Trap activation goes here
|
// Trap activation goes here
|
||||||
std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl;
|
std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl;
|
||||||
environment.mSoundManager->playSound3D (ptr, trapActivationSound, 1.0, 1.0, false);
|
environment.mSoundManager->playSound3D (ptr, trapActivationSound, 1.0, 1.0);
|
||||||
ptr.getCellRef().trap = "";
|
ptr.getCellRef().trap = "";
|
||||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ namespace MWClass
|
|||||||
// TODO check for key
|
// TODO check for key
|
||||||
// TODO report failure to player (message, sound?). Look up behaviour of original MW.
|
// TODO report failure to player (message, sound?). Look up behaviour of original MW.
|
||||||
std::cout << "Locked!" << std::endl;
|
std::cout << "Locked!" << std::endl;
|
||||||
environment.mSoundManager->playSound3D (ptr, lockedSound, 1.0, 1.0, false);
|
environment.mSoundManager->playSound3D (ptr, lockedSound, 1.0, 1.0);
|
||||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ namespace MWClass
|
|||||||
{
|
{
|
||||||
// Trap activation
|
// Trap activation
|
||||||
std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl;
|
std::cout << "Activated trap: " << ptr.getCellRef().trap << std::endl;
|
||||||
environment.mSoundManager->playSound3D(ptr, trapActivationSound, 1.0, 1.0, false);
|
environment.mSoundManager->playSound3D(ptr, trapActivationSound, 1.0, 1.0);
|
||||||
ptr.getCellRef().trap = "";
|
ptr.getCellRef().trap = "";
|
||||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||||
}
|
}
|
||||||
@ -110,7 +110,7 @@ namespace MWClass
|
|||||||
// TODO return action for rotating the door
|
// TODO return action for rotating the door
|
||||||
|
|
||||||
// This is a little pointless, but helps with testing
|
// This is a little pointless, but helps with testing
|
||||||
environment.mSoundManager->playSound3D (ptr, openSound, 1.0, 1.0, false);
|
environment.mSoundManager->playSound3D (ptr, openSound, 1.0, 1.0);
|
||||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ namespace MWClass
|
|||||||
boost::shared_ptr<MWWorld::Action> Ingredient::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Ingredient::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
|
@ -59,7 +59,7 @@ namespace MWClass
|
|||||||
|
|
||||||
if (!ref->base->sound.empty())
|
if (!ref->base->sound.empty())
|
||||||
{
|
{
|
||||||
environment.mSoundManager->playSound3D (ptr, ref->base->sound, 1.0, 1.0, true);
|
environment.mSoundManager->playSound3D (ptr, ref->base->sound, 1.0, 1.0, MWSound::Play_Loop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ namespace MWClass
|
|||||||
if (!(ref->base->data.flags & ESM::Light::Carry))
|
if (!(ref->base->data.flags & ESM::Light::Carry))
|
||||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||||
|
|
||||||
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
|
@ -58,7 +58,7 @@ namespace MWClass
|
|||||||
boost::shared_ptr<MWWorld::Action> Lockpick::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Lockpick::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
|
@ -56,7 +56,7 @@ namespace MWClass
|
|||||||
boost::shared_ptr<MWWorld::Action> Miscellaneous::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Miscellaneous::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
|
@ -56,7 +56,7 @@ namespace MWClass
|
|||||||
boost::shared_ptr<MWWorld::Action> Potion::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Potion::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
|
@ -57,7 +57,7 @@ namespace MWClass
|
|||||||
boost::shared_ptr<MWWorld::Action> Probe::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Probe::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
|
@ -56,7 +56,7 @@ namespace MWClass
|
|||||||
boost::shared_ptr<MWWorld::Action> Repair::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Repair::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
|
@ -57,7 +57,7 @@ namespace MWClass
|
|||||||
boost::shared_ptr<MWWorld::Action> Weapon::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Weapon::activate (const MWWorld::Ptr& ptr,
|
||||||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
|
||||||
{
|
{
|
||||||
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, false, true);
|
environment.mSoundManager->playSound3D (ptr, getUpSoundId(ptr, environment), 1.0, 1.0, MWSound::Play_NoTrack);
|
||||||
|
|
||||||
return boost::shared_ptr<MWWorld::Action> (
|
return boost::shared_ptr<MWWorld::Action> (
|
||||||
new MWWorld::ActionTake (ptr));
|
new MWWorld::ActionTake (ptr));
|
||||||
|
@ -180,71 +180,58 @@ void WindowManager::updateVisible()
|
|||||||
// Mouse is visible whenever we're not in game mode
|
// Mouse is visible whenever we're not in game mode
|
||||||
MyGUI::PointerManager::getInstance().setVisible(isGuiMode());
|
MyGUI::PointerManager::getInstance().setVisible(isGuiMode());
|
||||||
|
|
||||||
// If in game mode, don't show anything.
|
switch(mode) {
|
||||||
if(mode == GM_Game) //Use a switch/case structure
|
case GM_Game:
|
||||||
{
|
// If in game mode, don't show anything.
|
||||||
return;
|
break;
|
||||||
}
|
case GM_MainMenu:
|
||||||
|
menu->setVisible(true);
|
||||||
|
break;
|
||||||
|
case GM_Console:
|
||||||
|
console->enable();
|
||||||
|
break;
|
||||||
|
case GM_Name:
|
||||||
|
case GM_Race:
|
||||||
|
case GM_Class:
|
||||||
|
case GM_ClassPick:
|
||||||
|
case GM_ClassCreate:
|
||||||
|
case GM_Birth:
|
||||||
|
case GM_ClassGenerate:
|
||||||
|
case GM_Review:
|
||||||
|
mCharGen->spawnDialog(mode);
|
||||||
|
break;
|
||||||
|
case GM_Inventory:
|
||||||
|
{
|
||||||
|
// First, compute the effective set of windows to show.
|
||||||
|
// This is controlled both by what windows the
|
||||||
|
// user has opened/closed (the 'shown' variable) and by what
|
||||||
|
// windows we are allowed to show (the 'allowed' var.)
|
||||||
|
int eff = shown & allowed;
|
||||||
|
|
||||||
if(mode == GM_MainMenu)
|
// Show the windows we want
|
||||||
{
|
map -> setVisible( (eff & GW_Map) != 0 );
|
||||||
// Enable the main menu
|
stats -> setVisible( (eff & GW_Stats) != 0 );
|
||||||
menu->setVisible(true);
|
break;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mode == GM_Console)
|
|
||||||
{
|
|
||||||
console->enable();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//There must be a more elegant solution
|
|
||||||
if (mode == GM_Name || mode == GM_Race || mode == GM_Class || mode == GM_ClassPick || mode == GM_ClassCreate || mode == GM_Birth || mode == GM_ClassGenerate || mode == GM_Review)
|
|
||||||
{
|
|
||||||
mCharGen->spawnDialog(mode);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mode == GM_Inventory)
|
|
||||||
{
|
|
||||||
// Ah, inventory mode. First, compute the effective set of
|
|
||||||
// windows to show. This is controlled both by what windows the
|
|
||||||
// user has opened/closed (the 'shown' variable) and by what
|
|
||||||
// windows we are allowed to show (the 'allowed' var.)
|
|
||||||
int eff = shown & allowed;
|
|
||||||
|
|
||||||
// Show the windows we want
|
|
||||||
map -> setVisible( (eff & GW_Map) != 0 );
|
|
||||||
stats -> setVisible( (eff & GW_Stats) != 0 );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode == GM_Dialogue)
|
|
||||||
{
|
|
||||||
dialogueWindow->open();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mode == GM_InterMessageBox)
|
|
||||||
{
|
|
||||||
if(!mMessageBoxManager->isInteractiveMessageBox()) {
|
|
||||||
setGuiMode(GM_Game);
|
|
||||||
}
|
}
|
||||||
return;
|
case GM_Dialogue:
|
||||||
|
dialogueWindow->open();
|
||||||
|
break;
|
||||||
|
case GM_InterMessageBox:
|
||||||
|
if(!mMessageBoxManager->isInteractiveMessageBox()) {
|
||||||
|
setGuiMode(GM_Game);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GM_Journal:
|
||||||
|
mJournal->setVisible(true);
|
||||||
|
mJournal->open();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Unsupported mode, switch back to game
|
||||||
|
// Note: The call will eventually end up this method again but
|
||||||
|
// will stop at the check if mode is GM_Game.
|
||||||
|
setGuiMode(GM_Game);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mode == GM_Journal)
|
|
||||||
{
|
|
||||||
mJournal->setVisible(true);
|
|
||||||
mJournal->open();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unsupported mode, switch back to game
|
|
||||||
// Note: The call will eventually end up this method again but
|
|
||||||
// will stop at the check if(mode == GM_Game) above.
|
|
||||||
setGuiMode(GM_Game);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
|
void WindowManager::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
|
||||||
|
@ -126,6 +126,11 @@ namespace MWRender{
|
|||||||
void Animation::handleShapes(std::vector<Nif::NiTriShapeCopy>* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel){
|
void Animation::handleShapes(std::vector<Nif::NiTriShapeCopy>* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel){
|
||||||
shapeNumber = 0;
|
shapeNumber = 0;
|
||||||
|
|
||||||
|
if (allshapes == NULL || creaturemodel == NULL || skel == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<Nif::NiTriShapeCopy>::iterator allshapesiter;
|
std::vector<Nif::NiTriShapeCopy>::iterator allshapesiter;
|
||||||
for(allshapesiter = allshapes->begin(); allshapesiter != allshapes->end(); allshapesiter++)
|
for(allshapesiter = allshapes->begin(); allshapesiter != allshapes->end(); allshapesiter++)
|
||||||
|
|
||||||
|
@ -27,11 +27,7 @@ bool Debugging::toggleRenderMode (int mode){
|
|||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case MWWorld::World::Render_CollisionDebug:
|
case MWWorld::World::Render_CollisionDebug:
|
||||||
|
return eng->toggleDebugRendering();
|
||||||
// TODO use a proper function instead of accessing the member variable
|
|
||||||
// directly.
|
|
||||||
eng->setDebugRenderingMode (!eng->isDebugCreated);
|
|
||||||
return eng->isDebugCreated;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
254
apps/openmw/mwrender/occlusionquery.cpp
Normal file
254
apps/openmw/mwrender/occlusionquery.cpp
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
#include "occlusionquery.hpp"
|
||||||
|
|
||||||
|
#include <OgreRenderSystem.h>
|
||||||
|
#include <OgreRoot.h>
|
||||||
|
#include <OgreBillboardSet.h>
|
||||||
|
#include <OgreHardwareOcclusionQuery.h>
|
||||||
|
#include <OgreEntity.h>
|
||||||
|
|
||||||
|
using namespace MWRender;
|
||||||
|
using namespace Ogre;
|
||||||
|
|
||||||
|
OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNode* sunNode) :
|
||||||
|
mSunTotalAreaQuery(0), mSunVisibleAreaQuery(0), mSingleObjectQuery(0), mActiveQuery(0),
|
||||||
|
mDoQuery(0), mSunVisibility(0), mQuerySingleObjectStarted(false), mTestResult(false),
|
||||||
|
mQuerySingleObjectRequested(false), mWasVisible(false), mObjectWasVisible(false), mDoQuery2(false)
|
||||||
|
{
|
||||||
|
mRendering = renderer;
|
||||||
|
mSunNode = sunNode;
|
||||||
|
|
||||||
|
try {
|
||||||
|
RenderSystem* renderSystem = Root::getSingleton().getRenderSystem();
|
||||||
|
|
||||||
|
mSunTotalAreaQuery = renderSystem->createHardwareOcclusionQuery();
|
||||||
|
mSunVisibleAreaQuery = renderSystem->createHardwareOcclusionQuery();
|
||||||
|
mSingleObjectQuery = renderSystem->createHardwareOcclusionQuery();
|
||||||
|
|
||||||
|
mSupported = (mSunTotalAreaQuery != 0) && (mSunVisibleAreaQuery != 0) && (mSingleObjectQuery != 0);
|
||||||
|
}
|
||||||
|
catch (Ogre::Exception e)
|
||||||
|
{
|
||||||
|
mSupported = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mSupported)
|
||||||
|
{
|
||||||
|
std::cout << "Hardware occlusion queries not supported." << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This means that everything up to RENDER_QUEUE_MAIN can occlude the objects that are tested
|
||||||
|
const int queue = RENDER_QUEUE_MAIN+1;
|
||||||
|
|
||||||
|
MaterialPtr matBase = MaterialManager::getSingleton().getByName("BaseWhiteNoLighting");
|
||||||
|
MaterialPtr matQueryArea = matBase->clone("QueryTotalPixels");
|
||||||
|
matQueryArea->setDepthWriteEnabled(false);
|
||||||
|
matQueryArea->setColourWriteEnabled(false);
|
||||||
|
matQueryArea->setDepthCheckEnabled(false); // Not occluded by objects
|
||||||
|
MaterialPtr matQueryVisible = matBase->clone("QueryVisiblePixels");
|
||||||
|
matQueryVisible->setDepthWriteEnabled(false);
|
||||||
|
matQueryVisible->setColourWriteEnabled(false); // Uncomment this to visualize the occlusion query
|
||||||
|
matQueryVisible->setDepthCheckEnabled(true); // Occluded by objects
|
||||||
|
matQueryVisible->setCullingMode(CULL_NONE);
|
||||||
|
matQueryVisible->setManualCullingMode(MANUAL_CULL_NONE);
|
||||||
|
|
||||||
|
mBBNode = mSunNode->getParentSceneNode()->createChildSceneNode();
|
||||||
|
|
||||||
|
mObjectNode = mRendering->getScene()->getRootSceneNode()->createChildSceneNode();
|
||||||
|
mBBNodeReal = mRendering->getScene()->getRootSceneNode()->createChildSceneNode();
|
||||||
|
|
||||||
|
mBBQueryTotal = mRendering->getScene()->createBillboardSet(1);
|
||||||
|
mBBQueryTotal->setDefaultDimensions(150, 150);
|
||||||
|
mBBQueryTotal->createBillboard(Vector3::ZERO);
|
||||||
|
mBBQueryTotal->setMaterialName("QueryTotalPixels");
|
||||||
|
mBBQueryTotal->setRenderQueueGroup(queue+1);
|
||||||
|
mBBNodeReal->attachObject(mBBQueryTotal);
|
||||||
|
|
||||||
|
mBBQueryVisible = mRendering->getScene()->createBillboardSet(1);
|
||||||
|
mBBQueryVisible->setDefaultDimensions(150, 150);
|
||||||
|
mBBQueryVisible->createBillboard(Vector3::ZERO);
|
||||||
|
mBBQueryVisible->setMaterialName("QueryVisiblePixels");
|
||||||
|
mBBQueryVisible->setRenderQueueGroup(queue+1);
|
||||||
|
mBBNodeReal->attachObject(mBBQueryVisible);
|
||||||
|
|
||||||
|
mBBQuerySingleObject = mRendering->getScene()->createBillboardSet(1);
|
||||||
|
/// \todo ideally this should occupy exactly 1 pixel on the screen
|
||||||
|
mBBQuerySingleObject->setDefaultDimensions(0.003, 0.003);
|
||||||
|
mBBQuerySingleObject->createBillboard(Vector3::ZERO);
|
||||||
|
mBBQuerySingleObject->setMaterialName("QueryVisiblePixels");
|
||||||
|
mBBQuerySingleObject->setRenderQueueGroup(queue);
|
||||||
|
mObjectNode->attachObject(mBBQuerySingleObject);
|
||||||
|
|
||||||
|
mRendering->getScene()->addRenderObjectListener(this);
|
||||||
|
mRendering->getScene()->addRenderQueueListener(this);
|
||||||
|
mDoQuery = true;
|
||||||
|
mDoQuery2 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
OcclusionQuery::~OcclusionQuery()
|
||||||
|
{
|
||||||
|
RenderSystem* renderSystem = Root::getSingleton().getRenderSystem();
|
||||||
|
if (mSunTotalAreaQuery) renderSystem->destroyHardwareOcclusionQuery(mSunTotalAreaQuery);
|
||||||
|
if (mSunVisibleAreaQuery) renderSystem->destroyHardwareOcclusionQuery(mSunVisibleAreaQuery);
|
||||||
|
if (mSingleObjectQuery) renderSystem->destroyHardwareOcclusionQuery(mSingleObjectQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OcclusionQuery::supported()
|
||||||
|
{
|
||||||
|
return mSupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass, const AutoParamDataSource* source,
|
||||||
|
const LightList* pLightList, bool suppressRenderStateChanges)
|
||||||
|
{
|
||||||
|
// The following code activates and deactivates the occlusion queries
|
||||||
|
// so that the queries only include the rendering of their intended targets
|
||||||
|
|
||||||
|
// Close the last occlusion query
|
||||||
|
// Each occlusion query should only last a single rendering
|
||||||
|
if (mActiveQuery != NULL)
|
||||||
|
{
|
||||||
|
mActiveQuery->endOcclusionQuery();
|
||||||
|
mActiveQuery = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open a new occlusion query
|
||||||
|
if (mDoQuery == true)
|
||||||
|
{
|
||||||
|
if (rend == mBBQueryTotal)
|
||||||
|
{
|
||||||
|
mActiveQuery = mSunTotalAreaQuery;
|
||||||
|
mWasVisible = true;
|
||||||
|
}
|
||||||
|
else if (rend == mBBQueryVisible)
|
||||||
|
{
|
||||||
|
mActiveQuery = mSunVisibleAreaQuery;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mDoQuery == true && rend == mBBQuerySingleObject)
|
||||||
|
{
|
||||||
|
mQuerySingleObjectStarted = true;
|
||||||
|
mQuerySingleObjectRequested = false;
|
||||||
|
mActiveQuery = mSingleObjectQuery;
|
||||||
|
mObjectWasVisible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mActiveQuery != NULL)
|
||||||
|
mActiveQuery->beginOcclusionQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OcclusionQuery::renderQueueEnded(uint8 queueGroupId, const String& invocation, bool& repeatThisInvocation)
|
||||||
|
{
|
||||||
|
if (mActiveQuery != NULL)
|
||||||
|
{
|
||||||
|
mActiveQuery->endOcclusionQuery();
|
||||||
|
mActiveQuery = NULL;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* for every beginOcclusionQuery(), we want a respective pullOcclusionQuery() and vice versa
|
||||||
|
* this also means that results can be wrong at other places if we pull, but beginOcclusionQuery() was never called
|
||||||
|
* this can happen for example if the object that is tested is outside of the view frustum
|
||||||
|
* to prevent this, check if the queries have been performed after everything has been rendered and if not, start them manually
|
||||||
|
*/
|
||||||
|
if (queueGroupId == RENDER_QUEUE_SKIES_LATE)
|
||||||
|
{
|
||||||
|
if (mWasVisible == false && mDoQuery)
|
||||||
|
{
|
||||||
|
mSunTotalAreaQuery->beginOcclusionQuery();
|
||||||
|
mSunTotalAreaQuery->endOcclusionQuery();
|
||||||
|
mSunVisibleAreaQuery->beginOcclusionQuery();
|
||||||
|
mSunVisibleAreaQuery->endOcclusionQuery();
|
||||||
|
}
|
||||||
|
if (mObjectWasVisible == false && mDoQuery)
|
||||||
|
{
|
||||||
|
mSingleObjectQuery->beginOcclusionQuery();
|
||||||
|
mSingleObjectQuery->endOcclusionQuery();
|
||||||
|
mQuerySingleObjectStarted = true;
|
||||||
|
mQuerySingleObjectRequested = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OcclusionQuery::update(float duration)
|
||||||
|
{
|
||||||
|
if (!mSupported) return;
|
||||||
|
|
||||||
|
mWasVisible = false;
|
||||||
|
mObjectWasVisible = false;
|
||||||
|
|
||||||
|
// Adjust the position of the sun billboards according to camera viewing distance
|
||||||
|
// we need to do this to make sure that _everything_ can occlude the sun
|
||||||
|
float dist = mRendering->getCamera()->getFarClipDistance();
|
||||||
|
if (dist==0) dist = 10000000;
|
||||||
|
dist -= 1000; // bias
|
||||||
|
dist /= 1000.f;
|
||||||
|
mBBNode->setPosition(mSunNode->getPosition() * dist);
|
||||||
|
mBBNode->setScale(dist, dist, dist);
|
||||||
|
mBBNodeReal->setPosition(mBBNode->_getDerivedPosition());
|
||||||
|
mBBNodeReal->setScale(mBBNode->getScale());
|
||||||
|
|
||||||
|
// Stop occlusion queries until we get their information
|
||||||
|
// (may not happen on the same frame they are requested in)
|
||||||
|
mDoQuery = false;
|
||||||
|
mDoQuery2 = false;
|
||||||
|
|
||||||
|
if (!mSunTotalAreaQuery->isStillOutstanding()
|
||||||
|
&& !mSunVisibleAreaQuery->isStillOutstanding()
|
||||||
|
&& !mSingleObjectQuery->isStillOutstanding())
|
||||||
|
{
|
||||||
|
unsigned int totalPixels;
|
||||||
|
unsigned int visiblePixels;
|
||||||
|
|
||||||
|
mSunTotalAreaQuery->pullOcclusionQuery(&totalPixels);
|
||||||
|
mSunVisibleAreaQuery->pullOcclusionQuery(&visiblePixels);
|
||||||
|
|
||||||
|
if (totalPixels == 0)
|
||||||
|
{
|
||||||
|
// probably outside of the view frustum
|
||||||
|
mSunVisibility = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mSunVisibility = float(visiblePixels) / float(totalPixels);
|
||||||
|
if (mSunVisibility > 1) mSunVisibility = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int result;
|
||||||
|
|
||||||
|
mSingleObjectQuery->pullOcclusionQuery(&result);
|
||||||
|
|
||||||
|
mTestResult = (result != 0);
|
||||||
|
|
||||||
|
mQuerySingleObjectStarted = false;
|
||||||
|
mQuerySingleObjectRequested = false;
|
||||||
|
|
||||||
|
mDoQuery = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OcclusionQuery::occlusionTest(const Ogre::Vector3& position, Ogre::SceneNode* object)
|
||||||
|
{
|
||||||
|
assert( !occlusionTestPending()
|
||||||
|
&& "Occlusion test still pending");
|
||||||
|
|
||||||
|
mBBQuerySingleObject->setVisible(true);
|
||||||
|
|
||||||
|
mObjectNode->setPosition(position);
|
||||||
|
// scale proportional to camera distance, in order to always give the billboard the same size in screen-space
|
||||||
|
mObjectNode->setScale( Vector3(1,1,1)*(position - mRendering->getCamera()->getRealPosition()).length() );
|
||||||
|
|
||||||
|
mQuerySingleObjectRequested = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OcclusionQuery::occlusionTestPending()
|
||||||
|
{
|
||||||
|
return (mQuerySingleObjectRequested || mQuerySingleObjectStarted);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OcclusionQuery::getTestResult()
|
||||||
|
{
|
||||||
|
assert( !occlusionTestPending()
|
||||||
|
&& "Occlusion test still pending");
|
||||||
|
|
||||||
|
return mTestResult;
|
||||||
|
}
|
95
apps/openmw/mwrender/occlusionquery.hpp
Normal file
95
apps/openmw/mwrender/occlusionquery.hpp
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#ifndef _GAME_OCCLUSION_QUERY_H
|
||||||
|
#define _GAME_OCCLUSION_QUERY_H
|
||||||
|
|
||||||
|
#include <OgreRenderObjectListener.h>
|
||||||
|
#include <OgreRenderQueueListener.h>
|
||||||
|
|
||||||
|
namespace Ogre
|
||||||
|
{
|
||||||
|
class HardwareOcclusionQuery;
|
||||||
|
class Entity;
|
||||||
|
class SceneNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <openengine/ogre/renderer.hpp>
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
///
|
||||||
|
/// \brief Implements hardware occlusion queries on the GPU
|
||||||
|
///
|
||||||
|
class OcclusionQuery : public Ogre::RenderObjectListener, public Ogre::RenderQueueListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OcclusionQuery(OEngine::Render::OgreRenderer*, Ogre::SceneNode* sunNode);
|
||||||
|
~OcclusionQuery();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if occlusion queries are supported on the user's hardware
|
||||||
|
*/
|
||||||
|
bool supported();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* per-frame update
|
||||||
|
*/
|
||||||
|
void update(float duration);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* request occlusion test for a billboard at the given position, omitting an entity
|
||||||
|
* @param position of the billboard in ogre coordinates
|
||||||
|
* @param object to exclude from the occluders
|
||||||
|
*/
|
||||||
|
void occlusionTest(const Ogre::Vector3& position, Ogre::SceneNode* object);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if a request is still outstanding
|
||||||
|
*/
|
||||||
|
bool occlusionTestPending();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the object tested in the last request was occluded
|
||||||
|
*/
|
||||||
|
bool getTestResult();
|
||||||
|
|
||||||
|
float getSunVisibility() const {return mSunVisibility;};
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ogre::HardwareOcclusionQuery* mSunTotalAreaQuery;
|
||||||
|
Ogre::HardwareOcclusionQuery* mSunVisibleAreaQuery;
|
||||||
|
Ogre::HardwareOcclusionQuery* mSingleObjectQuery;
|
||||||
|
Ogre::HardwareOcclusionQuery* mActiveQuery;
|
||||||
|
|
||||||
|
Ogre::BillboardSet* mBBQueryVisible;
|
||||||
|
Ogre::BillboardSet* mBBQueryTotal;
|
||||||
|
Ogre::BillboardSet* mBBQuerySingleObject;
|
||||||
|
|
||||||
|
Ogre::SceneNode* mSunNode;
|
||||||
|
Ogre::SceneNode* mBBNode;
|
||||||
|
Ogre::SceneNode* mBBNodeReal;
|
||||||
|
float mSunVisibility;
|
||||||
|
|
||||||
|
Ogre::SceneNode* mObjectNode;
|
||||||
|
|
||||||
|
bool mWasVisible;
|
||||||
|
bool mObjectWasVisible;
|
||||||
|
|
||||||
|
bool mTestResult;
|
||||||
|
|
||||||
|
bool mSupported;
|
||||||
|
bool mDoQuery;
|
||||||
|
bool mDoQuery2;
|
||||||
|
|
||||||
|
bool mQuerySingleObjectRequested;
|
||||||
|
bool mQuerySingleObjectStarted;
|
||||||
|
|
||||||
|
OEngine::Render::OgreRenderer* mRendering;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void notifyRenderSingleObject(Ogre::Renderable* rend, const Ogre::Pass* pass, const Ogre::AutoParamDataSource* source,
|
||||||
|
const Ogre::LightList* pLightList, bool suppressRenderStateChanges);
|
||||||
|
|
||||||
|
virtual void renderQueueEnded(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& repeatThisInvocation);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -46,9 +46,6 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
|
|||||||
mMwRoot->pitch(Degree(-90));
|
mMwRoot->pitch(Degree(-90));
|
||||||
mObjects.setMwRoot(mMwRoot);
|
mObjects.setMwRoot(mMwRoot);
|
||||||
mActors.setMwRoot(mMwRoot);
|
mActors.setMwRoot(mMwRoot);
|
||||||
|
|
||||||
//used to obtain ingame information of ogre objects (which are faced or selected)
|
|
||||||
mRaySceneQuery = mRendering.getScene()->createRayQuery(Ray());
|
|
||||||
|
|
||||||
Ogre::SceneNode *playerNode = mMwRoot->createChildSceneNode ("player");
|
Ogre::SceneNode *playerNode = mMwRoot->createChildSceneNode ("player");
|
||||||
playerNode->pitch(Degree(90));
|
playerNode->pitch(Degree(90));
|
||||||
@ -59,10 +56,10 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
|
|||||||
//mSkyManager = 0;
|
//mSkyManager = 0;
|
||||||
mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera(), &environment);
|
mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera(), &environment);
|
||||||
|
|
||||||
|
mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode());
|
||||||
|
|
||||||
mWater = 0;
|
mWater = 0;
|
||||||
|
|
||||||
|
|
||||||
mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode);
|
mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode);
|
||||||
mSun = 0;
|
mSun = 0;
|
||||||
|
|
||||||
@ -76,6 +73,7 @@ RenderingManager::~RenderingManager ()
|
|||||||
delete mSkyManager;
|
delete mSkyManager;
|
||||||
delete mTerrainManager;
|
delete mTerrainManager;
|
||||||
delete mLocalMap;
|
delete mLocalMap;
|
||||||
|
delete mOcclusionQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
MWRender::SkyManager* RenderingManager::getSkyManager()
|
MWRender::SkyManager* RenderingManager::getSkyManager()
|
||||||
@ -166,9 +164,13 @@ void RenderingManager::moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Ve
|
|||||||
void RenderingManager::update (float duration){
|
void RenderingManager::update (float duration){
|
||||||
|
|
||||||
mActors.update (duration);
|
mActors.update (duration);
|
||||||
|
|
||||||
|
mOcclusionQuery->update(duration);
|
||||||
|
|
||||||
mSkyManager->update(duration);
|
mSkyManager->update(duration);
|
||||||
|
|
||||||
|
mSkyManager->setGlare(mOcclusionQuery->getSunVisibility());
|
||||||
|
|
||||||
mRendering.update(duration);
|
mRendering.update(duration);
|
||||||
|
|
||||||
mLocalMap->updatePlayer( mRendering.getCamera()->getRealPosition(), mRendering.getCamera()->getRealDirection() );
|
mLocalMap->updatePlayer( mRendering.getCamera()->getRealPosition(), mRendering.getCamera()->getRealDirection() );
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "player.hpp"
|
#include "player.hpp"
|
||||||
#include "water.hpp"
|
#include "water.hpp"
|
||||||
#include "localmap.hpp"
|
#include "localmap.hpp"
|
||||||
|
#include "occlusionquery.hpp"
|
||||||
|
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
@ -108,6 +109,9 @@ class RenderingManager: private RenderingInterface {
|
|||||||
void sunEnable();
|
void sunEnable();
|
||||||
void sunDisable();
|
void sunDisable();
|
||||||
|
|
||||||
|
bool occlusionQuerySupported() { return mOcclusionQuery->supported(); };
|
||||||
|
OcclusionQuery* getOcclusionQuery() { return mOcclusionQuery; };
|
||||||
|
|
||||||
void setGlare(bool glare);
|
void setGlare(bool glare);
|
||||||
void skyEnable ();
|
void skyEnable ();
|
||||||
void skyDisable ();
|
void skyDisable ();
|
||||||
@ -145,10 +149,12 @@ class RenderingManager: private RenderingInterface {
|
|||||||
|
|
||||||
SkyManager* mSkyManager;
|
SkyManager* mSkyManager;
|
||||||
|
|
||||||
MWRender::Water *mWater;
|
OcclusionQuery* mOcclusionQuery;
|
||||||
|
|
||||||
TerrainManager* mTerrainManager;
|
TerrainManager* mTerrainManager;
|
||||||
|
|
||||||
|
MWRender::Water *mWater;
|
||||||
|
|
||||||
OEngine::Render::OgreRenderer &mRendering;
|
OEngine::Render::OgreRenderer &mRendering;
|
||||||
|
|
||||||
MWRender::Objects mObjects;
|
MWRender::Objects mObjects;
|
||||||
@ -164,7 +170,6 @@ class RenderingManager: private RenderingInterface {
|
|||||||
/// that the OGRE coordinate system matches that used internally in
|
/// that the OGRE coordinate system matches that used internally in
|
||||||
/// Morrowind.
|
/// Morrowind.
|
||||||
Ogre::SceneNode *mMwRoot;
|
Ogre::SceneNode *mMwRoot;
|
||||||
Ogre::RaySceneQuery *mRaySceneQuery;
|
|
||||||
|
|
||||||
OEngine::Physic::PhysicEngine* mPhysicsEngine;
|
OEngine::Physic::PhysicEngine* mPhysicsEngine;
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "../mwworld/environment.hpp"
|
#include "../mwworld/environment.hpp"
|
||||||
#include "../mwworld/world.hpp"
|
#include "../mwworld/world.hpp"
|
||||||
|
#include "occlusionquery.hpp"
|
||||||
|
|
||||||
using namespace MWRender;
|
using namespace MWRender;
|
||||||
using namespace Ogre;
|
using namespace Ogre;
|
||||||
@ -30,7 +31,7 @@ BillboardObject::BillboardObject()
|
|||||||
|
|
||||||
void BillboardObject::setVisible(const bool visible)
|
void BillboardObject::setVisible(const bool visible)
|
||||||
{
|
{
|
||||||
mNode->setVisible(visible);
|
mBBSet->setVisible(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BillboardObject::setSize(const float size)
|
void BillboardObject::setSize(const float size)
|
||||||
@ -88,7 +89,7 @@ void BillboardObject::init(const String& textureName,
|
|||||||
/// \todo These billboards are not 100% correct, might want to revisit them later
|
/// \todo These billboards are not 100% correct, might want to revisit them later
|
||||||
mBBSet = sceneMgr->createBillboardSet("SkyBillboardSet"+StringConverter::toString(bodyCount), 1);
|
mBBSet = sceneMgr->createBillboardSet("SkyBillboardSet"+StringConverter::toString(bodyCount), 1);
|
||||||
mBBSet->setDefaultDimensions(550.f*initialSize, 550.f*initialSize);
|
mBBSet->setDefaultDimensions(550.f*initialSize, 550.f*initialSize);
|
||||||
mBBSet->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY+2);
|
mBBSet->setRenderQueueGroup(RENDER_QUEUE_MAIN+2);
|
||||||
mBBSet->setBillboardType(BBT_PERPENDICULAR_COMMON);
|
mBBSet->setBillboardType(BBT_PERPENDICULAR_COMMON);
|
||||||
mBBSet->setCommonDirection( -position.normalisedCopy() );
|
mBBSet->setCommonDirection( -position.normalisedCopy() );
|
||||||
mNode = rootNode->createChildSceneNode();
|
mNode = rootNode->createChildSceneNode();
|
||||||
@ -319,8 +320,8 @@ SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera, MWWorld::Environmen
|
|||||||
, mThunderTextureUnit(NULL)
|
, mThunderTextureUnit(NULL)
|
||||||
, mRemainingTransitionTime(0.0f)
|
, mRemainingTransitionTime(0.0f)
|
||||||
, mGlareFade(0.0f)
|
, mGlareFade(0.0f)
|
||||||
|
, mGlare(0.0f)
|
||||||
, mEnabled(true)
|
, mEnabled(true)
|
||||||
, mGlareEnabled(true)
|
|
||||||
, mSunEnabled(true)
|
, mSunEnabled(true)
|
||||||
, mMasserEnabled(true)
|
, mMasserEnabled(true)
|
||||||
, mSecundaEnabled(true)
|
, mSecundaEnabled(true)
|
||||||
@ -592,10 +593,23 @@ void SkyManager::update(float duration)
|
|||||||
mMasser->setPhase( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
|
mMasser->setPhase( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
|
||||||
mSecunda->setPhase ( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
|
mSecunda->setPhase ( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
|
||||||
|
|
||||||
// increase the strength of the sun glare effect depending
|
|
||||||
// on how directly the player is looking at the sun
|
|
||||||
if (mSunEnabled)
|
if (mSunEnabled)
|
||||||
{
|
{
|
||||||
|
// take 1/5 sec for fading the glare effect from invisible to full
|
||||||
|
if (mGlareFade > mGlare)
|
||||||
|
{
|
||||||
|
mGlareFade -= duration*5;
|
||||||
|
if (mGlareFade < mGlare) mGlareFade = mGlare;
|
||||||
|
}
|
||||||
|
else if (mGlareFade < mGlare)
|
||||||
|
{
|
||||||
|
mGlareFade += duration*5;
|
||||||
|
if (mGlareFade > mGlare) mGlareFade = mGlare;
|
||||||
|
}
|
||||||
|
|
||||||
|
// increase the strength of the sun glare effect depending
|
||||||
|
// on how directly the player is looking at the sun
|
||||||
Vector3 sun = mSunGlare->getPosition();
|
Vector3 sun = mSunGlare->getPosition();
|
||||||
sun = Vector3(sun.x, sun.z, -sun.y);
|
sun = Vector3(sun.x, sun.z, -sun.y);
|
||||||
Vector3 cam = mViewport->getCamera()->getRealDirection();
|
Vector3 cam = mViewport->getCamera()->getRealDirection();
|
||||||
@ -603,21 +617,10 @@ void SkyManager::update(float duration)
|
|||||||
float val = 1- (angle.valueDegrees() / 180.f);
|
float val = 1- (angle.valueDegrees() / 180.f);
|
||||||
val = (val*val*val*val)*2;
|
val = (val*val*val*val)*2;
|
||||||
|
|
||||||
if (mGlareEnabled)
|
mSunGlare->setSize(val * mGlareFade);
|
||||||
{
|
|
||||||
mGlareFade += duration*3;
|
|
||||||
if (mGlareFade > 1) mGlareFade = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mGlareFade -= duration*3;
|
|
||||||
if (mGlareFade < 0.3) mGlareFade = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mSunGlare->setSize(val * (mGlareFade));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mSunGlare->setVisible(mGlareFade>0 && mSunEnabled);
|
mSunGlare->setVisible(mSunEnabled);
|
||||||
mSun->setVisible(mSunEnabled);
|
mSun->setVisible(mSunEnabled);
|
||||||
mMasser->setVisible(mMasserEnabled);
|
mMasser->setVisible(mMasserEnabled);
|
||||||
mSecunda->setVisible(mSecundaEnabled);
|
mSecunda->setVisible(mSecundaEnabled);
|
||||||
@ -719,15 +722,15 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
|
|||||||
else
|
else
|
||||||
strength = 1.f;
|
strength = 1.f;
|
||||||
|
|
||||||
mSunGlare->setVisibility(weather.mGlareView * strength);
|
mSunGlare->setVisibility(weather.mGlareView * mGlareFade * strength);
|
||||||
mSun->setVisibility(strength);
|
mSun->setVisibility(mGlareFade >= 0.5 ? weather.mGlareView * mGlareFade * strength : 0);
|
||||||
|
|
||||||
mAtmosphereNight->setVisible(weather.mNight && mEnabled);
|
mAtmosphereNight->setVisible(weather.mNight && mEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkyManager::setGlare(bool glare)
|
void SkyManager::setGlare(const float glare)
|
||||||
{
|
{
|
||||||
mGlareEnabled = glare;
|
mGlare = glare;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 SkyManager::getRealSunPos()
|
Vector3 SkyManager::getRealSunPos()
|
||||||
@ -812,3 +815,8 @@ void SkyManager::setDate(int day, int month)
|
|||||||
mDay = day;
|
mDay = day;
|
||||||
mMonth = month;
|
mMonth = month;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ogre::SceneNode* SkyManager::getSunNode()
|
||||||
|
{
|
||||||
|
return mSun->getNode();
|
||||||
|
}
|
||||||
|
@ -109,58 +109,60 @@ namespace MWRender
|
|||||||
public:
|
public:
|
||||||
SkyManager(Ogre::SceneNode* pMwRoot, Ogre::Camera* pCamera, MWWorld::Environment* env);
|
SkyManager(Ogre::SceneNode* pMwRoot, Ogre::Camera* pCamera, MWWorld::Environment* env);
|
||||||
~SkyManager();
|
~SkyManager();
|
||||||
|
|
||||||
void update(float duration);
|
void update(float duration);
|
||||||
|
|
||||||
void enable();
|
void enable();
|
||||||
|
|
||||||
void disable();
|
void disable();
|
||||||
|
|
||||||
void setHour (double hour);
|
void setHour (double hour);
|
||||||
///< will be called even when sky is disabled.
|
///< will be called even when sky is disabled.
|
||||||
|
|
||||||
void setDate (int day, int month);
|
void setDate (int day, int month);
|
||||||
///< will be called even when sky is disabled.
|
///< will be called even when sky is disabled.
|
||||||
|
|
||||||
int getMasserPhase() const;
|
int getMasserPhase() const;
|
||||||
///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half,
|
///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half,
|
||||||
/// 3 waxing or waning gibbous, 4 full moon
|
/// 3 waxing or waning gibbous, 4 full moon
|
||||||
|
|
||||||
int getSecundaPhase() const;
|
int getSecundaPhase() const;
|
||||||
///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half,
|
///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half,
|
||||||
/// 3 waxing or waning gibbous, 4 full moon
|
/// 3 waxing or waning gibbous, 4 full moon
|
||||||
|
|
||||||
void setMoonColour (bool red);
|
void setMoonColour (bool red);
|
||||||
///< change Secunda colour to red
|
///< change Secunda colour to red
|
||||||
|
|
||||||
void setCloudsOpacity(float opacity);
|
void setCloudsOpacity(float opacity);
|
||||||
///< change opacity of the clouds
|
///< change opacity of the clouds
|
||||||
|
|
||||||
void setWeather(const MWWorld::WeatherResult& weather);
|
void setWeather(const MWWorld::WeatherResult& weather);
|
||||||
|
|
||||||
|
Ogre::SceneNode* getSunNode();
|
||||||
|
|
||||||
void sunEnable();
|
void sunEnable();
|
||||||
|
|
||||||
void sunDisable();
|
void sunDisable();
|
||||||
|
|
||||||
void setSunDirection(const Ogre::Vector3& direction);
|
void setSunDirection(const Ogre::Vector3& direction);
|
||||||
|
|
||||||
void setMasserDirection(const Ogre::Vector3& direction);
|
void setMasserDirection(const Ogre::Vector3& direction);
|
||||||
|
|
||||||
void setSecundaDirection(const Ogre::Vector3& direction);
|
void setSecundaDirection(const Ogre::Vector3& direction);
|
||||||
|
|
||||||
void setMasserFade(const float fade);
|
void setMasserFade(const float fade);
|
||||||
|
|
||||||
void setSecundaFade(const float fade);
|
void setSecundaFade(const float fade);
|
||||||
|
|
||||||
void masserEnable();
|
void masserEnable();
|
||||||
void masserDisable();
|
void masserDisable();
|
||||||
|
|
||||||
void secundaEnable();
|
void secundaEnable();
|
||||||
void secundaDisable();
|
void secundaDisable();
|
||||||
|
|
||||||
void setThunder(const float factor);
|
void setThunder(const float factor);
|
||||||
|
|
||||||
void setGlare(bool glare);
|
void setGlare(const float glare);
|
||||||
Ogre::Vector3 getRealSunPos();
|
Ogre::Vector3 getRealSunPos();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -203,12 +205,12 @@ namespace MWRender
|
|||||||
|
|
||||||
float mRemainingTransitionTime;
|
float mRemainingTransitionTime;
|
||||||
|
|
||||||
float mGlareFade;
|
float mGlare; // target
|
||||||
|
float mGlareFade; // actual
|
||||||
|
|
||||||
void ModVertexAlpha(Ogre::Entity* ent, unsigned int meshType);
|
void ModVertexAlpha(Ogre::Entity* ent, unsigned int meshType);
|
||||||
|
|
||||||
bool mEnabled;
|
bool mEnabled;
|
||||||
bool mGlareEnabled;
|
|
||||||
bool mSunEnabled;
|
bool mSunEnabled;
|
||||||
bool mMasserEnabled;
|
bool mMasserEnabled;
|
||||||
bool mSecundaEnabled;
|
bool mSecundaEnabled;
|
||||||
|
@ -50,7 +50,7 @@ namespace Ogre
|
|||||||
terrain.
|
terrain.
|
||||||
@note Requires the Cg plugin to render correctly
|
@note Requires the Cg plugin to render correctly
|
||||||
*/
|
*/
|
||||||
class _OgreTerrainExport TerrainMaterialGeneratorB : public TerrainMaterialGenerator
|
class TerrainMaterialGeneratorB : public TerrainMaterialGenerator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TerrainMaterialGeneratorB();
|
TerrainMaterialGeneratorB();
|
||||||
@ -58,7 +58,7 @@ namespace Ogre
|
|||||||
|
|
||||||
/** Shader model 2 profile target.
|
/** Shader model 2 profile target.
|
||||||
*/
|
*/
|
||||||
class _OgreTerrainExport SM2Profile : public TerrainMaterialGenerator::Profile
|
class SM2Profile : public TerrainMaterialGenerator::Profile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SM2Profile(TerrainMaterialGenerator* parent, const String& name, const String& desc);
|
SM2Profile(TerrainMaterialGenerator* parent, const String& name, const String& desc);
|
||||||
@ -161,7 +161,7 @@ namespace Ogre
|
|||||||
void addTechnique(const MaterialPtr& mat, const Terrain* terrain, TechniqueType tt);
|
void addTechnique(const MaterialPtr& mat, const Terrain* terrain, TechniqueType tt);
|
||||||
|
|
||||||
/// Interface definition for helper class to generate shaders
|
/// Interface definition for helper class to generate shaders
|
||||||
class _OgreTerrainExport ShaderHelper : public TerrainAlloc
|
class ShaderHelper : public TerrainAlloc
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ShaderHelper() {}
|
ShaderHelper() {}
|
||||||
@ -194,7 +194,7 @@ namespace Ogre
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Utility class to help with generating shaders for Cg / HLSL.
|
/// Utility class to help with generating shaders for Cg / HLSL.
|
||||||
class _OgreTerrainExport ShaderHelperCg : public ShaderHelper
|
class ShaderHelperCg : public ShaderHelper
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
|
HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
|
||||||
@ -212,7 +212,7 @@ namespace Ogre
|
|||||||
void generateFpDynamicShadows(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream);
|
void generateFpDynamicShadows(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, StringUtil::StrStreamType& outStream);
|
||||||
};
|
};
|
||||||
|
|
||||||
class _OgreTerrainExport ShaderHelperHLSL : public ShaderHelperCg
|
class ShaderHelperHLSL : public ShaderHelperCg
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
|
HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
|
||||||
@ -220,7 +220,7 @@ namespace Ogre
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Utility class to help with generating shaders for GLSL.
|
/// Utility class to help with generating shaders for GLSL.
|
||||||
class _OgreTerrainExport ShaderHelperGLSL : public ShaderHelper
|
class ShaderHelperGLSL : public ShaderHelper
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
|
HighLevelGpuProgramPtr createVertexProgram(const SM2Profile* prof, const Terrain* terrain, TechniqueType tt);
|
||||||
|
@ -130,7 +130,7 @@ namespace MWScript
|
|||||||
std::string sound = runtime.getStringLiteral (runtime[0].mInteger);
|
std::string sound = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
|
|
||||||
context.getSoundManager().playSound3D (ptr, sound, 1.0, 1.0, mLoop);
|
context.getSoundManager().playSound3D (ptr, sound, 1.0, 1.0, mLoop ? MWSound::Play_Loop : 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ namespace MWScript
|
|||||||
Interpreter::Type_Float pitch = runtime[0].mFloat;
|
Interpreter::Type_Float pitch = runtime[0].mFloat;
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
|
|
||||||
context.getSoundManager().playSound3D (ptr, sound, volume, pitch, mLoop);
|
context.getSoundManager().playSound3D (ptr, sound, volume, pitch, mLoop ? MWSound::Play_Loop : 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -25,14 +25,20 @@ static void throwALCerror(ALCdevice *device)
|
|||||||
{
|
{
|
||||||
ALCenum err = alcGetError(device);
|
ALCenum err = alcGetError(device);
|
||||||
if(err != ALC_NO_ERROR)
|
if(err != ALC_NO_ERROR)
|
||||||
fail(alcGetString(device, err));
|
{
|
||||||
|
const ALCchar *errstring = alcGetString(device, err);
|
||||||
|
fail(errstring ? errstring : "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void throwALerror()
|
static void throwALerror()
|
||||||
{
|
{
|
||||||
ALenum err = alGetError();
|
ALenum err = alGetError();
|
||||||
if(err != AL_NO_ERROR)
|
if(err != AL_NO_ERROR)
|
||||||
fail(alGetString(err));
|
{
|
||||||
|
const ALchar *errstring = alGetString(err);
|
||||||
|
fail(errstring ? errstring : "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -89,8 +95,7 @@ public:
|
|||||||
|
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
virtual bool isPlaying();
|
virtual bool isPlaying();
|
||||||
virtual void setVolume(float volume);
|
virtual void update();
|
||||||
virtual void update(const float *pos);
|
|
||||||
|
|
||||||
void play();
|
void play();
|
||||||
bool process();
|
bool process();
|
||||||
@ -187,7 +192,6 @@ OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, Decode
|
|||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
mOutput.mFreeSources.push_back(mSource);
|
|
||||||
alDeleteBuffers(sNumBuffers, mBuffers);
|
alDeleteBuffers(sNumBuffers, mBuffers);
|
||||||
alGetError();
|
alGetError();
|
||||||
throw;
|
throw;
|
||||||
@ -255,16 +259,10 @@ bool OpenAL_SoundStream::isPlaying()
|
|||||||
return !mIsFinished;
|
return !mIsFinished;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenAL_SoundStream::setVolume(float volume)
|
void OpenAL_SoundStream::update()
|
||||||
{
|
{
|
||||||
alSourcef(mSource, AL_GAIN, volume*mBaseVolume);
|
alSourcef(mSource, AL_GAIN, mVolume*mBaseVolume);
|
||||||
throwALerror();
|
alSource3f(mSource, AL_POSITION, mPos[0], mPos[2], -mPos[1]);
|
||||||
mVolume = volume;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenAL_SoundStream::update(const float *pos)
|
|
||||||
{
|
|
||||||
alSource3f(mSource, AL_POSITION, pos[0], pos[2], -pos[1]);
|
|
||||||
alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||||
alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||||
throwALerror();
|
throwALerror();
|
||||||
@ -321,15 +319,17 @@ bool OpenAL_SoundStream::process()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// A regular OpenAL sound
|
// A regular 2D OpenAL sound
|
||||||
//
|
//
|
||||||
class OpenAL_Sound : public Sound
|
class OpenAL_Sound : public Sound
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
OpenAL_Output &mOutput;
|
OpenAL_Output &mOutput;
|
||||||
|
|
||||||
ALuint mSource;
|
ALuint mSource;
|
||||||
ALuint mBuffer;
|
ALuint mBuffer;
|
||||||
|
|
||||||
|
private:
|
||||||
OpenAL_Sound(const OpenAL_Sound &rhs);
|
OpenAL_Sound(const OpenAL_Sound &rhs);
|
||||||
OpenAL_Sound& operator=(const OpenAL_Sound &rhs);
|
OpenAL_Sound& operator=(const OpenAL_Sound &rhs);
|
||||||
|
|
||||||
@ -339,8 +339,23 @@ public:
|
|||||||
|
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
virtual bool isPlaying();
|
virtual bool isPlaying();
|
||||||
virtual void setVolume(float volume);
|
virtual void update();
|
||||||
virtual void update(const float *pos);
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// A regular 3D OpenAL sound
|
||||||
|
//
|
||||||
|
class OpenAL_Sound3D : public OpenAL_Sound
|
||||||
|
{
|
||||||
|
OpenAL_Sound3D(const OpenAL_Sound &rhs);
|
||||||
|
OpenAL_Sound3D& operator=(const OpenAL_Sound &rhs);
|
||||||
|
|
||||||
|
public:
|
||||||
|
OpenAL_Sound3D(OpenAL_Output &output, ALuint src, ALuint buf)
|
||||||
|
: OpenAL_Sound(output, src, buf)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual void update();
|
||||||
};
|
};
|
||||||
|
|
||||||
OpenAL_Sound::OpenAL_Sound(OpenAL_Output &output, ALuint src, ALuint buf)
|
OpenAL_Sound::OpenAL_Sound(OpenAL_Output &output, ALuint src, ALuint buf)
|
||||||
@ -372,16 +387,22 @@ bool OpenAL_Sound::isPlaying()
|
|||||||
return state==AL_PLAYING;
|
return state==AL_PLAYING;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenAL_Sound::setVolume(float volume)
|
void OpenAL_Sound::update()
|
||||||
{
|
{
|
||||||
alSourcef(mSource, AL_GAIN, volume*mBaseVolume);
|
alSourcef(mSource, AL_GAIN, mVolume*mBaseVolume);
|
||||||
|
alSource3f(mSource, AL_POSITION, mPos[0], mPos[2], -mPos[1]);
|
||||||
|
alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||||
|
alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||||
throwALerror();
|
throwALerror();
|
||||||
mVolume = volume;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenAL_Sound::update(const float *pos)
|
void OpenAL_Sound3D::update()
|
||||||
{
|
{
|
||||||
alSource3f(mSource, AL_POSITION, pos[0], pos[2], -pos[1]);
|
if(mPos.squaredDistance(mOutput.mPos) > mMaxDistance*mMaxDistance)
|
||||||
|
alSourcef(mSource, AL_GAIN, 0.0f);
|
||||||
|
else
|
||||||
|
alSourcef(mSource, AL_GAIN, mVolume*mBaseVolume);
|
||||||
|
alSource3f(mSource, AL_POSITION, mPos[0], mPos[2], -mPos[1]);
|
||||||
alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||||
alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||||
throwALerror();
|
throwALerror();
|
||||||
@ -410,8 +431,7 @@ std::vector<std::string> OpenAL_Output::enumerate()
|
|||||||
|
|
||||||
void OpenAL_Output::init(const std::string &devname)
|
void OpenAL_Output::init(const std::string &devname)
|
||||||
{
|
{
|
||||||
if(mDevice || mContext)
|
deinit();
|
||||||
fail("Device already open");
|
|
||||||
|
|
||||||
mDevice = alcOpenDevice(devname.c_str());
|
mDevice = alcOpenDevice(devname.c_str());
|
||||||
if(!mDevice)
|
if(!mDevice)
|
||||||
@ -428,7 +448,12 @@ void OpenAL_Output::init(const std::string &devname)
|
|||||||
|
|
||||||
mContext = alcCreateContext(mDevice, NULL);
|
mContext = alcCreateContext(mDevice, NULL);
|
||||||
if(!mContext || alcMakeContextCurrent(mContext) == ALC_FALSE)
|
if(!mContext || alcMakeContextCurrent(mContext) == ALC_FALSE)
|
||||||
|
{
|
||||||
|
if(mContext)
|
||||||
|
alcDestroyContext(mContext);
|
||||||
|
mContext = 0;
|
||||||
fail(std::string("Failed to setup context: ")+alcGetString(mDevice, alcGetError(mDevice)));
|
fail(std::string("Failed to setup context: ")+alcGetString(mDevice, alcGetError(mDevice)));
|
||||||
|
}
|
||||||
|
|
||||||
alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
|
alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
|
||||||
throwALerror();
|
throwALerror();
|
||||||
@ -442,33 +467,13 @@ void OpenAL_Output::init(const std::string &devname)
|
|||||||
{
|
{
|
||||||
ALCuint maxtotal = std::min<ALCuint>(maxmono+maxstereo, 256);
|
ALCuint maxtotal = std::min<ALCuint>(maxmono+maxstereo, 256);
|
||||||
if (maxtotal == 0) // workaround for broken implementations
|
if (maxtotal == 0) // workaround for broken implementations
|
||||||
{
|
|
||||||
maxtotal = 256;
|
maxtotal = 256;
|
||||||
bool stop = false;
|
for(size_t i = 0;i < maxtotal;i++)
|
||||||
for(size_t i = 0;i < maxtotal && !stop;i++) // generate source until error returned
|
|
||||||
{
|
|
||||||
ALuint src = 0;
|
|
||||||
alGenSources(1, &src);
|
|
||||||
ALenum err = alGetError();
|
|
||||||
if(err != AL_NO_ERROR)
|
|
||||||
{
|
|
||||||
stop = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mFreeSources.push_back(src);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // normal case
|
|
||||||
{
|
{
|
||||||
for(size_t i = 0;i < maxtotal;i++)
|
ALuint src = 0;
|
||||||
{
|
alGenSources(1, &src);
|
||||||
ALuint src = 0;
|
throwALerror();
|
||||||
alGenSources(1, &src);
|
mFreeSources.push_back(src);
|
||||||
throwALerror();
|
|
||||||
mFreeSources.push_back(src);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
@ -602,10 +607,8 @@ void OpenAL_Output::bufferFinished(ALuint buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume, float pitch, bool loop)
|
SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume, float pitch, int flags)
|
||||||
{
|
{
|
||||||
throwALerror();
|
|
||||||
|
|
||||||
boost::shared_ptr<OpenAL_Sound> sound;
|
boost::shared_ptr<OpenAL_Sound> sound;
|
||||||
ALuint src=0, buf=0;
|
ALuint src=0, buf=0;
|
||||||
|
|
||||||
@ -640,7 +643,7 @@ SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume, float
|
|||||||
alSourcef(src, AL_PITCH, pitch);
|
alSourcef(src, AL_PITCH, pitch);
|
||||||
|
|
||||||
alSourcei(src, AL_SOURCE_RELATIVE, AL_TRUE);
|
alSourcei(src, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||||
alSourcei(src, AL_LOOPING, (loop?AL_TRUE:AL_FALSE));
|
alSourcei(src, AL_LOOPING, (flags&Play_Loop) ? AL_TRUE : AL_FALSE);
|
||||||
throwALerror();
|
throwALerror();
|
||||||
|
|
||||||
alSourcei(src, AL_BUFFER, buf);
|
alSourcei(src, AL_BUFFER, buf);
|
||||||
@ -650,11 +653,9 @@ SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume, float
|
|||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const float *pos, float volume, float pitch,
|
SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre::Vector3 &pos, float volume, float pitch,
|
||||||
float min, float max, bool loop)
|
float min, float max, int flags)
|
||||||
{
|
{
|
||||||
throwALerror();
|
|
||||||
|
|
||||||
boost::shared_ptr<OpenAL_Sound> sound;
|
boost::shared_ptr<OpenAL_Sound> sound;
|
||||||
ALuint src=0, buf=0;
|
ALuint src=0, buf=0;
|
||||||
|
|
||||||
@ -666,7 +667,7 @@ SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const float *pos,
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
buf = getBuffer(fname);
|
buf = getBuffer(fname);
|
||||||
sound.reset(new OpenAL_Sound(*this, src, buf));
|
sound.reset(new OpenAL_Sound3D(*this, src, buf));
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
@ -677,7 +678,7 @@ SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const float *pos,
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
alSource3f(src, AL_POSITION, pos[0], pos[2], -pos[1]);
|
alSource3f(src, AL_POSITION, pos.x, pos.z, -pos.y);
|
||||||
alSource3f(src, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
alSource3f(src, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||||
alSource3f(src, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
alSource3f(src, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
@ -685,11 +686,12 @@ SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const float *pos,
|
|||||||
alSourcef(src, AL_MAX_DISTANCE, max);
|
alSourcef(src, AL_MAX_DISTANCE, max);
|
||||||
alSourcef(src, AL_ROLLOFF_FACTOR, 1.0f);
|
alSourcef(src, AL_ROLLOFF_FACTOR, 1.0f);
|
||||||
|
|
||||||
alSourcef(src, AL_GAIN, volume);
|
alSourcef(src, AL_GAIN, (pos.squaredDistance(mPos) > max*max) ?
|
||||||
|
0.0f : volume);
|
||||||
alSourcef(src, AL_PITCH, pitch);
|
alSourcef(src, AL_PITCH, pitch);
|
||||||
|
|
||||||
alSourcei(src, AL_SOURCE_RELATIVE, AL_FALSE);
|
alSourcei(src, AL_SOURCE_RELATIVE, AL_FALSE);
|
||||||
alSourcei(src, AL_LOOPING, (loop?AL_TRUE:AL_FALSE));
|
alSourcei(src, AL_LOOPING, (flags&Play_Loop) ? AL_TRUE : AL_FALSE);
|
||||||
throwALerror();
|
throwALerror();
|
||||||
|
|
||||||
alSourcei(src, AL_BUFFER, buf);
|
alSourcei(src, AL_BUFFER, buf);
|
||||||
@ -702,8 +704,6 @@ SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const float *pos,
|
|||||||
|
|
||||||
SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volume, float pitch)
|
SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volume, float pitch)
|
||||||
{
|
{
|
||||||
throwALerror();
|
|
||||||
|
|
||||||
boost::shared_ptr<OpenAL_SoundStream> sound;
|
boost::shared_ptr<OpenAL_SoundStream> sound;
|
||||||
ALuint src;
|
ALuint src;
|
||||||
|
|
||||||
@ -743,61 +743,21 @@ SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volume, floa
|
|||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundPtr OpenAL_Output::streamSound3D(const std::string &fname, const float *pos, float volume, float pitch,
|
|
||||||
float min, float max)
|
void OpenAL_Output::updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir)
|
||||||
{
|
{
|
||||||
throwALerror();
|
mPos = pos;
|
||||||
|
|
||||||
boost::shared_ptr<OpenAL_SoundStream> sound;
|
if(mContext)
|
||||||
ALuint src;
|
|
||||||
|
|
||||||
if(mFreeSources.empty())
|
|
||||||
fail("No free sources");
|
|
||||||
src = mFreeSources.front();
|
|
||||||
mFreeSources.pop_front();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
DecoderPtr decoder = mManager.getDecoder();
|
ALfloat orient[6] = {
|
||||||
decoder->open(fname);
|
atdir.x, atdir.z, -atdir.y,
|
||||||
sound.reset(new OpenAL_SoundStream(*this, src, decoder));
|
updir.x, updir.z, -updir.y
|
||||||
|
};
|
||||||
|
alListener3f(AL_POSITION, mPos.x, mPos.z, -mPos.y);
|
||||||
|
alListenerfv(AL_ORIENTATION, orient);
|
||||||
|
throwALerror();
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
|
||||||
{
|
|
||||||
mFreeSources.push_back(src);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
alSource3f(src, AL_POSITION, pos[0], pos[2], -pos[1]);
|
|
||||||
alSource3f(src, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
|
||||||
alSource3f(src, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
|
||||||
|
|
||||||
alSourcef(src, AL_REFERENCE_DISTANCE, min);
|
|
||||||
alSourcef(src, AL_MAX_DISTANCE, max);
|
|
||||||
alSourcef(src, AL_ROLLOFF_FACTOR, 1.0f);
|
|
||||||
|
|
||||||
alSourcef(src, AL_GAIN, volume);
|
|
||||||
alSourcef(src, AL_PITCH, pitch);
|
|
||||||
|
|
||||||
alSourcei(src, AL_SOURCE_RELATIVE, AL_FALSE);
|
|
||||||
alSourcei(src, AL_LOOPING, AL_FALSE);
|
|
||||||
throwALerror();
|
|
||||||
|
|
||||||
sound->play();
|
|
||||||
return sound;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void OpenAL_Output::updateListener(const float *pos, const float *atdir, const float *updir)
|
|
||||||
{
|
|
||||||
float orient[6] = {
|
|
||||||
atdir[0], atdir[2], -atdir[1],
|
|
||||||
updir[0], updir[2], -updir[1]
|
|
||||||
};
|
|
||||||
|
|
||||||
alListener3f(AL_POSITION, pos[0], pos[2], -pos[1]);
|
|
||||||
alListenerfv(AL_ORIENTATION, orient);
|
|
||||||
throwALerror();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,15 +40,12 @@ namespace MWSound
|
|||||||
virtual void init(const std::string &devname="");
|
virtual void init(const std::string &devname="");
|
||||||
virtual void deinit();
|
virtual void deinit();
|
||||||
|
|
||||||
virtual SoundPtr playSound(const std::string &fname, float volume, float pitch, bool loop);
|
virtual SoundPtr playSound(const std::string &fname, float volume, float pitch, int flags);
|
||||||
virtual SoundPtr playSound3D(const std::string &fname, const float *pos, float volume, float pitch,
|
virtual SoundPtr playSound3D(const std::string &fname, const Ogre::Vector3 &pos,
|
||||||
float min, float max, bool loop);
|
float volume, float pitch, float min, float max, int flags);
|
||||||
|
|
||||||
virtual SoundPtr streamSound(const std::string &fname, float volume, float pitch);
|
virtual SoundPtr streamSound(const std::string &fname, float volume, float pitch);
|
||||||
virtual SoundPtr streamSound3D(const std::string &fname, const float *pos, float volume, float pitch,
|
|
||||||
float min, float max);
|
|
||||||
|
|
||||||
virtual void updateListener(const float *pos, const float *atdir, const float *updir);
|
virtual void updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir);
|
||||||
|
|
||||||
OpenAL_Output& operator=(const OpenAL_Output &rhs);
|
OpenAL_Output& operator=(const OpenAL_Output &rhs);
|
||||||
OpenAL_Output(const OpenAL_Output &rhs);
|
OpenAL_Output(const OpenAL_Output &rhs);
|
||||||
@ -60,6 +57,7 @@ namespace MWSound
|
|||||||
std::auto_ptr<StreamThread> mStreamThread;
|
std::auto_ptr<StreamThread> mStreamThread;
|
||||||
|
|
||||||
friend class OpenAL_Sound;
|
friend class OpenAL_Sound;
|
||||||
|
friend class OpenAL_Sound3D;
|
||||||
friend class OpenAL_SoundStream;
|
friend class OpenAL_SoundStream;
|
||||||
friend class SoundManager;
|
friend class SoundManager;
|
||||||
};
|
};
|
||||||
|
@ -1,30 +1,37 @@
|
|||||||
#ifndef GAME_SOUND_SOUND_H
|
#ifndef GAME_SOUND_SOUND_H
|
||||||
#define GAME_SOUND_SOUND_H
|
#define GAME_SOUND_SOUND_H
|
||||||
|
|
||||||
|
#include <OgreVector3.h>
|
||||||
|
|
||||||
namespace MWSound
|
namespace MWSound
|
||||||
{
|
{
|
||||||
class Sound
|
class Sound
|
||||||
{
|
{
|
||||||
virtual void update(const float *pos) = 0;
|
virtual void update() = 0;
|
||||||
|
|
||||||
Sound& operator=(const Sound &rhs);
|
Sound& operator=(const Sound &rhs);
|
||||||
Sound(const Sound &rhs);
|
Sound(const Sound &rhs);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
Ogre::Vector3 mPos;
|
||||||
float mVolume; /* NOTE: Real volume = mVolume*mBaseVolume */
|
float mVolume; /* NOTE: Real volume = mVolume*mBaseVolume */
|
||||||
float mBaseVolume;
|
float mBaseVolume;
|
||||||
float mMinDistance;
|
float mMinDistance;
|
||||||
float mMaxDistance;
|
float mMaxDistance;
|
||||||
|
int mFlags;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void stop() = 0;
|
virtual void stop() = 0;
|
||||||
virtual bool isPlaying() = 0;
|
virtual bool isPlaying() = 0;
|
||||||
virtual void setVolume(float volume) = 0;
|
void setPosition(const Ogre::Vector3 &pos) { mPos = pos; }
|
||||||
|
void setVolume(float volume) { mVolume = volume; }
|
||||||
|
|
||||||
Sound() : mVolume(1.0f)
|
Sound() : mPos(0.0f, 0.0f, 0.0f)
|
||||||
|
, mVolume(1.0f)
|
||||||
, mBaseVolume(1.0f)
|
, mBaseVolume(1.0f)
|
||||||
, mMinDistance(20.0f) /* 1 * min_range_scale */
|
, mMinDistance(20.0f) /* 1 * min_range_scale */
|
||||||
, mMaxDistance(12750.0f) /* 255 * max_range_scale */
|
, mMaxDistance(12750.0f) /* 255 * max_range_scale */
|
||||||
|
, mFlags(Play_Normal)
|
||||||
{ }
|
{ }
|
||||||
virtual ~Sound() { }
|
virtual ~Sound() { }
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include <OgreVector3.h>
|
||||||
|
|
||||||
#include "soundmanager.hpp"
|
#include "soundmanager.hpp"
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
@ -22,19 +24,23 @@ namespace MWSound
|
|||||||
virtual void init(const std::string &devname="") = 0;
|
virtual void init(const std::string &devname="") = 0;
|
||||||
virtual void deinit() = 0;
|
virtual void deinit() = 0;
|
||||||
|
|
||||||
virtual SoundPtr playSound(const std::string &fname, float volume, float pitch, bool loop) = 0;
|
virtual SoundPtr playSound(const std::string &fname, float volume, float pitch, int flags) = 0;
|
||||||
virtual SoundPtr playSound3D(const std::string &fname, const float *pos, float volume, float pitch,
|
virtual SoundPtr playSound3D(const std::string &fname, const Ogre::Vector3 &pos,
|
||||||
float min, float max, bool loop) = 0;
|
float volume, float pitch, float min, float max, int flags) = 0;
|
||||||
virtual SoundPtr streamSound(const std::string &fname, float volume, float pitch) = 0;
|
virtual SoundPtr streamSound(const std::string &fname, float volume, float pitch) = 0;
|
||||||
virtual SoundPtr streamSound3D(const std::string &fname, const float *pos, float volume, float pitch,
|
|
||||||
float min, float max) = 0;
|
|
||||||
|
|
||||||
virtual void updateListener(const float *pos, const float *atdir, const float *updir) = 0;
|
virtual void updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir) = 0;
|
||||||
|
|
||||||
Sound_Output& operator=(const Sound_Output &rhs);
|
Sound_Output& operator=(const Sound_Output &rhs);
|
||||||
Sound_Output(const Sound_Output &rhs);
|
Sound_Output(const Sound_Output &rhs);
|
||||||
|
|
||||||
Sound_Output(SoundManager &mgr) : mManager(mgr) { }
|
protected:
|
||||||
|
Ogre::Vector3 mPos;
|
||||||
|
|
||||||
|
Sound_Output(SoundManager &mgr)
|
||||||
|
: mManager(mgr)
|
||||||
|
, mPos(0.0f, 0.0f, 0.0f)
|
||||||
|
{ }
|
||||||
public:
|
public:
|
||||||
virtual ~Sound_Output() { }
|
virtual ~Sound_Output() { }
|
||||||
|
|
||||||
|
@ -41,6 +41,8 @@ namespace MWSound
|
|||||||
SoundManager::SoundManager(bool useSound, MWWorld::Environment& environment)
|
SoundManager::SoundManager(bool useSound, MWWorld::Environment& environment)
|
||||||
: mResourceMgr(Ogre::ResourceGroupManager::getSingleton())
|
: mResourceMgr(Ogre::ResourceGroupManager::getSingleton())
|
||||||
, mEnvironment(environment)
|
, mEnvironment(environment)
|
||||||
|
, mOutput(new DEFAULT_OUTPUT(*this))
|
||||||
|
|
||||||
{
|
{
|
||||||
if(!useSound)
|
if(!useSound)
|
||||||
return;
|
return;
|
||||||
@ -50,8 +52,6 @@ namespace MWSound
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mOutput.reset(new DEFAULT_OUTPUT(*this));
|
|
||||||
|
|
||||||
std::vector<std::string> names = mOutput->enumerate();
|
std::vector<std::string> names = mOutput->enumerate();
|
||||||
std::cout <<"Enumerated output devices:"<< std::endl;
|
std::cout <<"Enumerated output devices:"<< std::endl;
|
||||||
for(size_t i = 0;i < names.size();i++)
|
for(size_t i = 0;i < names.size();i++)
|
||||||
@ -62,8 +62,6 @@ namespace MWSound
|
|||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
std::cout <<"Sound init failed: "<<e.what()<< std::endl;
|
std::cout <<"Sound init failed: "<<e.what()<< std::endl;
|
||||||
mOutput.reset();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +106,7 @@ namespace MWSound
|
|||||||
max = std::max(min, max);
|
max = std::max(min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::string("Sound/")+snd->sound;
|
return "Sound/"+snd->sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -182,11 +180,13 @@ namespace MWSound
|
|||||||
{
|
{
|
||||||
// The range values are not tested
|
// The range values are not tested
|
||||||
float basevol = 1.0f; /* TODO: volume settings */
|
float basevol = 1.0f; /* TODO: volume settings */
|
||||||
std::string filePath = std::string("Sound/")+filename;
|
std::string filePath = "Sound/"+filename;
|
||||||
const ESM::Position &pos = ptr.getCellRef().pos;
|
const ESM::Position &pos = ptr.getCellRef().pos;
|
||||||
|
const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]);
|
||||||
|
|
||||||
SoundPtr sound = mOutput->playSound3D(filePath, pos.pos, basevol, 1.0f,
|
SoundPtr sound = mOutput->playSound3D(filePath, objpos, basevol, 1.0f,
|
||||||
20.0f, 12750.0f, false);
|
20.0f, 12750.0f, Play_Normal);
|
||||||
|
sound->mPos = objpos;
|
||||||
sound->mBaseVolume = basevol;
|
sound->mBaseVolume = basevol;
|
||||||
|
|
||||||
mActiveSounds[sound] = std::make_pair(ptr, std::string("_say_sound"));
|
mActiveSounds[sound] = std::make_pair(ptr, std::string("_say_sound"));
|
||||||
@ -203,7 +203,7 @@ namespace MWSound
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SoundPtr SoundManager::playSound(const std::string& soundId, float volume, float pitch, bool loop)
|
SoundPtr SoundManager::playSound(const std::string& soundId, float volume, float pitch, int mode)
|
||||||
{
|
{
|
||||||
SoundPtr sound;
|
SoundPtr sound;
|
||||||
try
|
try
|
||||||
@ -212,11 +212,12 @@ namespace MWSound
|
|||||||
float min, max;
|
float min, max;
|
||||||
std::string file = lookup(soundId, basevol, min, max);
|
std::string file = lookup(soundId, basevol, min, max);
|
||||||
|
|
||||||
sound = mOutput->playSound(file, volume*basevol, pitch, loop);
|
sound = mOutput->playSound(file, volume*basevol, pitch, mode);
|
||||||
sound->mVolume = volume;
|
sound->mVolume = volume;
|
||||||
sound->mBaseVolume = basevol;
|
sound->mBaseVolume = basevol;
|
||||||
sound->mMinDistance = min;
|
sound->mMinDistance = min;
|
||||||
sound->mMaxDistance = max;
|
sound->mMaxDistance = max;
|
||||||
|
sound->mFlags = mode;
|
||||||
|
|
||||||
mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId);
|
mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId);
|
||||||
}
|
}
|
||||||
@ -228,8 +229,7 @@ namespace MWSound
|
|||||||
}
|
}
|
||||||
|
|
||||||
SoundPtr SoundManager::playSound3D(MWWorld::Ptr ptr, const std::string& soundId,
|
SoundPtr SoundManager::playSound3D(MWWorld::Ptr ptr, const std::string& soundId,
|
||||||
float volume, float pitch, bool loop,
|
float volume, float pitch, int mode)
|
||||||
bool untracked)
|
|
||||||
{
|
{
|
||||||
SoundPtr sound;
|
SoundPtr sound;
|
||||||
try
|
try
|
||||||
@ -239,15 +239,20 @@ namespace MWSound
|
|||||||
float min, max;
|
float min, max;
|
||||||
std::string file = lookup(soundId, basevol, min, max);
|
std::string file = lookup(soundId, basevol, min, max);
|
||||||
const ESM::Position &pos = ptr.getCellRef().pos;
|
const ESM::Position &pos = ptr.getCellRef().pos;
|
||||||
|
const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]);
|
||||||
|
|
||||||
sound = mOutput->playSound3D(file, pos.pos, volume*basevol, pitch, min, max, loop);
|
sound = mOutput->playSound3D(file, objpos, volume*basevol, pitch, min, max, mode);
|
||||||
|
sound->mPos = objpos;
|
||||||
sound->mVolume = volume;
|
sound->mVolume = volume;
|
||||||
sound->mBaseVolume = basevol;
|
sound->mBaseVolume = basevol;
|
||||||
sound->mMinDistance = min;
|
sound->mMinDistance = min;
|
||||||
sound->mMaxDistance = max;
|
sound->mMaxDistance = max;
|
||||||
|
sound->mFlags = mode;
|
||||||
|
|
||||||
mActiveSounds[sound] = (!untracked ? std::make_pair(ptr, soundId) :
|
if((mode&Play_NoTrack))
|
||||||
std::make_pair(MWWorld::Ptr(), soundId));
|
mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId);
|
||||||
|
else
|
||||||
|
mActiveSounds[sound] = std::make_pair(ptr, soundId);
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
@ -326,11 +331,12 @@ namespace MWSound
|
|||||||
void SoundManager::updateObject(MWWorld::Ptr ptr)
|
void SoundManager::updateObject(MWWorld::Ptr ptr)
|
||||||
{
|
{
|
||||||
const ESM::Position &pos = ptr.getCellRef().pos;
|
const ESM::Position &pos = ptr.getCellRef().pos;
|
||||||
|
const Ogre::Vector3 objpos(pos.pos[0], pos.pos[1], pos.pos[2]);
|
||||||
SoundMap::iterator snditer = mActiveSounds.begin();
|
SoundMap::iterator snditer = mActiveSounds.begin();
|
||||||
while(snditer != mActiveSounds.end())
|
while(snditer != mActiveSounds.end())
|
||||||
{
|
{
|
||||||
if(snditer->second.first == ptr)
|
if(snditer->second.first == ptr)
|
||||||
snditer->first->update(pos.pos);
|
snditer->first->setPosition(objpos);
|
||||||
snditer++;
|
snditer++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -411,9 +417,9 @@ namespace MWSound
|
|||||||
// The output handler is expecting vectors oriented like the game
|
// The output handler is expecting vectors oriented like the game
|
||||||
// (that is, -Z goes down, +Y goes forward), but that's not what we
|
// (that is, -Z goes down, +Y goes forward), but that's not what we
|
||||||
// get from Ogre's camera, so we have to convert.
|
// get from Ogre's camera, so we have to convert.
|
||||||
float pos[3] = { nPos[0], -nPos[2], nPos[1] };
|
const Ogre::Vector3 pos(nPos[0], -nPos[2], nPos[1]);
|
||||||
float at[3] = { nDir[0], -nDir[2], nDir[1] };
|
const Ogre::Vector3 at(nDir[0], -nDir[2], nDir[1]);
|
||||||
float up[3] = { nUp[0], -nUp[2], nUp[1] };
|
const Ogre::Vector3 up(nUp[0], -nUp[2], nUp[1]);
|
||||||
mOutput->updateListener(pos, at, up);
|
mOutput->updateListener(pos, at, up);
|
||||||
|
|
||||||
// Check if any sounds are finished playing, and trash them
|
// Check if any sounds are finished playing, and trash them
|
||||||
@ -423,7 +429,10 @@ namespace MWSound
|
|||||||
if(!snditer->first->isPlaying())
|
if(!snditer->first->isPlaying())
|
||||||
mActiveSounds.erase(snditer++);
|
mActiveSounds.erase(snditer++);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
snditer->first->update();
|
||||||
snditer++;
|
snditer++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,19 @@ namespace MWSound
|
|||||||
typedef boost::shared_ptr<Sound_Decoder> DecoderPtr;
|
typedef boost::shared_ptr<Sound_Decoder> DecoderPtr;
|
||||||
typedef boost::shared_ptr<Sound> SoundPtr;
|
typedef boost::shared_ptr<Sound> SoundPtr;
|
||||||
|
|
||||||
|
enum PlayMode {
|
||||||
|
Play_Normal = 0, /* tracked, non-looping, multi-instance, environment */
|
||||||
|
Play_Loop = 1<<0, /* Sound will continually loop until explicitly stopped */
|
||||||
|
Play_NoEnv = 1<<1, /* Do not apply environment effects (eg, underwater filters) */
|
||||||
|
Play_NoTrack = 1<<2, /* (3D only) Play the sound at the given object's position
|
||||||
|
* but do not keep it updated (the sound will not move with
|
||||||
|
* the object and will not stop when the object is deleted. */
|
||||||
|
};
|
||||||
|
static inline int operator|(const PlayMode &a, const PlayMode &b)
|
||||||
|
{ return (int)a | (int)b; }
|
||||||
|
static inline int operator&(const PlayMode &a, const PlayMode &b)
|
||||||
|
{ return (int)a & (int)b; }
|
||||||
|
|
||||||
class SoundManager
|
class SoundManager
|
||||||
{
|
{
|
||||||
Ogre::ResourceGroupManager& mResourceMgr;
|
Ogre::ResourceGroupManager& mResourceMgr;
|
||||||
@ -87,12 +100,11 @@ namespace MWSound
|
|||||||
bool sayDone(MWWorld::Ptr reference) const;
|
bool sayDone(MWWorld::Ptr reference) const;
|
||||||
///< Is actor not speaking?
|
///< Is actor not speaking?
|
||||||
|
|
||||||
SoundPtr playSound(const std::string& soundId, float volume, float pitch, bool loop=false);
|
SoundPtr playSound(const std::string& soundId, float volume, float pitch, int mode=Play_Normal);
|
||||||
///< Play a sound, independently of 3D-position
|
///< Play a sound, independently of 3D-position
|
||||||
|
|
||||||
SoundPtr playSound3D(MWWorld::Ptr reference, const std::string& soundId,
|
SoundPtr playSound3D(MWWorld::Ptr reference, const std::string& soundId,
|
||||||
float volume, float pitch, bool loop,
|
float volume, float pitch, int mode=Play_Normal);
|
||||||
bool untracked=false);
|
|
||||||
///< Play a sound from an object
|
///< Play a sound from an object
|
||||||
|
|
||||||
void stopSound3D(MWWorld::Ptr reference, const std::string& soundId);
|
void stopSound3D(MWWorld::Ptr reference, const std::string& soundId);
|
||||||
|
@ -50,6 +50,28 @@ namespace MWWorld
|
|||||||
|
|
||||||
return mEngine->rayTest(from,to);
|
return mEngine->rayTest(from,to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector < std::pair <float, std::string> > PhysicsSystem::getFacedObjects ()
|
||||||
|
{
|
||||||
|
//get a ray pointing to the center of the viewport
|
||||||
|
Ray centerRay = mRender.getCamera()->getCameraToViewportRay(
|
||||||
|
mRender.getViewport()->getWidth()/2,
|
||||||
|
mRender.getViewport()->getHeight()/2);
|
||||||
|
btVector3 from(centerRay.getOrigin().x,-centerRay.getOrigin().z,centerRay.getOrigin().y);
|
||||||
|
btVector3 to(centerRay.getPoint(500).x,-centerRay.getPoint(500).z,centerRay.getPoint(500).y);
|
||||||
|
|
||||||
|
return mEngine->rayTest2(from,to);
|
||||||
|
}
|
||||||
|
|
||||||
|
btVector3 PhysicsSystem::getRayPoint(float extent)
|
||||||
|
{
|
||||||
|
//get a ray pointing to the center of the viewport
|
||||||
|
Ray centerRay = mRender.getCamera()->getCameraToViewportRay(
|
||||||
|
mRender.getViewport()->getWidth()/2,
|
||||||
|
mRender.getViewport()->getHeight()/2);
|
||||||
|
btVector3 result(centerRay.getPoint(500*extent).x,-centerRay.getPoint(500*extent).z,centerRay.getPoint(500*extent).y);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool PhysicsSystem::castRay(const Vector3& from, const Vector3& to)
|
bool PhysicsSystem::castRay(const Vector3& from, const Vector3& to)
|
||||||
{
|
{
|
||||||
|
@ -35,7 +35,11 @@ namespace MWWorld
|
|||||||
bool toggleCollisionMode();
|
bool toggleCollisionMode();
|
||||||
|
|
||||||
std::pair<std::string, float> getFacedHandle (MWWorld::World& world);
|
std::pair<std::string, float> getFacedHandle (MWWorld::World& world);
|
||||||
|
|
||||||
|
btVector3 getRayPoint(float extent);
|
||||||
|
|
||||||
|
std::vector < std::pair <float, std::string> > getFacedObjects ();
|
||||||
|
|
||||||
// cast ray, return true if it hit something
|
// cast ray, return true if it hit something
|
||||||
bool castRay(const Ogre::Vector3& from, const Ogre::Vector3& to);
|
bool castRay(const Ogre::Vector3& from, const Ogre::Vector3& to);
|
||||||
|
|
||||||
|
@ -157,7 +157,8 @@ namespace MWWorld
|
|||||||
const std::string& master, const boost::filesystem::path& resDir,
|
const std::string& master, const boost::filesystem::path& resDir,
|
||||||
bool newGame, Environment& environment, const std::string& encoding)
|
bool newGame, Environment& environment, const std::string& encoding)
|
||||||
: mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0),
|
: mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0),
|
||||||
mSky (true), mEnvironment (environment), mNextDynamicRecord (0), mCells (mStore, mEsm, *this)
|
mSky (true), mEnvironment (environment), mNextDynamicRecord (0), mCells (mStore, mEsm, *this),
|
||||||
|
mNumFacing(0)
|
||||||
{
|
{
|
||||||
mPhysics = new PhysicsSystem(renderer);
|
mPhysics = new PhysicsSystem(renderer);
|
||||||
mPhysEngine = mPhysics->getEngine();
|
mPhysEngine = mPhysics->getEngine();
|
||||||
@ -498,13 +499,21 @@ namespace MWWorld
|
|||||||
|
|
||||||
std::string World::getFacedHandle()
|
std::string World::getFacedHandle()
|
||||||
{
|
{
|
||||||
std::pair<std::string, float> result = mPhysics->getFacedHandle (*this);
|
if (!mRendering->occlusionQuerySupported())
|
||||||
|
{
|
||||||
|
std::pair<std::string, float> result = mPhysics->getFacedHandle (*this);
|
||||||
|
|
||||||
if (result.first.empty() ||
|
if (result.first.empty() ||
|
||||||
result.second>getStore().gameSettings.find ("iMaxActivateDist")->i)
|
result.second>getStore().gameSettings.find ("iMaxActivateDist")->i)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
return result.first;
|
return result.first;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// updated every few frames in update()
|
||||||
|
return mFacedHandle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::deleteObject (Ptr ptr)
|
void World::deleteObject (Ptr ptr)
|
||||||
@ -706,13 +715,82 @@ namespace MWWorld
|
|||||||
|
|
||||||
mWeatherManager->update (duration);
|
mWeatherManager->update (duration);
|
||||||
|
|
||||||
// cast a ray from player to sun to detect if the sun is visible
|
if (!mRendering->occlusionQuerySupported())
|
||||||
// this is temporary until we find a better place to put this code
|
{
|
||||||
// currently its here because we need to access the physics system
|
// cast a ray from player to sun to detect if the sun is visible
|
||||||
float* p = mPlayer->getPlayer().getRefData().getPosition().pos;
|
// this is temporary until we find a better place to put this code
|
||||||
Vector3 sun = mRendering->getSkyManager()->getRealSunPos();
|
// currently its here because we need to access the physics system
|
||||||
sun = Vector3(sun.x, -sun.z, sun.y);
|
float* p = mPlayer->getPlayer().getRefData().getPosition().pos;
|
||||||
mRendering->getSkyManager()->setGlare(!mPhysics->castRay(Ogre::Vector3(p[0], p[1], p[2]), sun));
|
Vector3 sun = mRendering->getSkyManager()->getRealSunPos();
|
||||||
|
sun = Vector3(sun.x, -sun.z, sun.y);
|
||||||
|
mRendering->getSkyManager()->setGlare(!mPhysics->castRay(Ogre::Vector3(p[0], p[1], p[2]), sun));
|
||||||
|
}
|
||||||
|
|
||||||
|
// update faced handle (object the player is looking at)
|
||||||
|
// this uses a mixture of raycasts and occlusion queries.
|
||||||
|
else // if (mRendering->occlusionQuerySupported())
|
||||||
|
{
|
||||||
|
MWRender::OcclusionQuery* query = mRendering->getOcclusionQuery();
|
||||||
|
if (!query->occlusionTestPending())
|
||||||
|
{
|
||||||
|
// get result of last query
|
||||||
|
if (mNumFacing == 0) mFacedHandle = "";
|
||||||
|
else if (mNumFacing == 1)
|
||||||
|
{
|
||||||
|
bool result = query->getTestResult();
|
||||||
|
mFacedHandle = result ? mFaced1Name : "";
|
||||||
|
}
|
||||||
|
else if (mNumFacing == 2)
|
||||||
|
{
|
||||||
|
bool result = query->getTestResult();
|
||||||
|
mFacedHandle = result ? mFaced2Name : mFaced1Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send new query
|
||||||
|
// figure out which object we want to test against
|
||||||
|
std::vector < std::pair < float, std::string > > results = mPhysics->getFacedObjects();
|
||||||
|
|
||||||
|
// ignore the player
|
||||||
|
for (std::vector < std::pair < float, std::string > >::iterator it = results.begin();
|
||||||
|
it != results.end(); ++it)
|
||||||
|
{
|
||||||
|
if ( (*it).second == mPlayer->getPlayer().getRefData().getHandle() )
|
||||||
|
{
|
||||||
|
results.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results.size() == 0)
|
||||||
|
{
|
||||||
|
mNumFacing = 0;
|
||||||
|
}
|
||||||
|
else if (results.size() == 1)
|
||||||
|
{
|
||||||
|
mFaced1 = getPtrViaHandle(results.front().second);
|
||||||
|
mFaced1Name = results.front().second;
|
||||||
|
mNumFacing = 1;
|
||||||
|
|
||||||
|
btVector3 p = mPhysics->getRayPoint(results.front().first);
|
||||||
|
Ogre::Vector3 pos(p.x(), p.z(), -p.y());
|
||||||
|
Ogre::SceneNode* node = mFaced1.getRefData().getBaseNode();
|
||||||
|
query->occlusionTest(pos, node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mFaced1Name = results.front().second;
|
||||||
|
mFaced2Name = results[1].second;
|
||||||
|
mFaced1 = getPtrViaHandle(results.front().second);
|
||||||
|
mFaced2 = getPtrViaHandle(results[1].second);
|
||||||
|
mNumFacing = 2;
|
||||||
|
|
||||||
|
btVector3 p = mPhysics->getRayPoint(results[1].first);
|
||||||
|
Ogre::Vector3 pos(p.x(), p.z(), -p.y());
|
||||||
|
Ogre::SceneNode* node = mFaced2.getRefData().getBaseNode();
|
||||||
|
query->occlusionTest(pos, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool World::isCellExterior() const
|
bool World::isCellExterior() const
|
||||||
|
@ -93,6 +93,12 @@ namespace MWWorld
|
|||||||
|
|
||||||
Ptr getPtrViaHandle (const std::string& handle, Ptr::CellStore& cellStore);
|
Ptr getPtrViaHandle (const std::string& handle, Ptr::CellStore& cellStore);
|
||||||
|
|
||||||
|
std::string mFacedHandle;
|
||||||
|
Ptr mFaced1;
|
||||||
|
Ptr mFaced2;
|
||||||
|
std::string mFaced1Name;
|
||||||
|
std::string mFaced2Name;
|
||||||
|
int mNumFacing;
|
||||||
|
|
||||||
int getDaysPerMonth (int month) const;
|
int getDaysPerMonth (int month) const;
|
||||||
|
|
||||||
|
@ -45,6 +45,20 @@ struct ciLessBoost : std::binary_function<std::string, std::string, bool>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct pathComparer
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int m_start, m_size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
pathComparer(int start, int size) : m_start(start), m_size(size) { }
|
||||||
|
|
||||||
|
bool operator() (const std::string& first, const std::string& other)
|
||||||
|
{
|
||||||
|
return lexicographical_compare(first.substr(m_start,m_size), other.substr(m_start,m_size), boost::algorithm::is_iless());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static bool fsstrict = false;
|
static bool fsstrict = false;
|
||||||
|
|
||||||
/// An OGRE Archive wrapping a BSAFile archive
|
/// An OGRE Archive wrapping a BSAFile archive
|
||||||
@ -55,16 +69,62 @@ class DirArchive: public Ogre::FileSystemArchive
|
|||||||
std::map<std::string, std::vector<std::string>, ciLessBoost> m;
|
std::map<std::string, std::vector<std::string>, ciLessBoost> m;
|
||||||
unsigned int cutoff;
|
unsigned int cutoff;
|
||||||
|
|
||||||
bool comparePortion(std::string file1, std::string file2, int start, int size) const
|
bool findFile(const String& filename, std::string& copy) const
|
||||||
{
|
{
|
||||||
for(int i = start; i < start+size; i++)
|
if (filename.find(".tga") != std::string::npos)
|
||||||
|
return false;
|
||||||
|
|
||||||
{
|
{
|
||||||
char one = file1.at(i);
|
String passed = filename;
|
||||||
char two = file2.at(i);
|
if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<'
|
||||||
if(tolower(one) != tolower(two) )
|
|| filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':'
|
||||||
return false;
|
|| filename.at(filename.length() - 1) == '|')
|
||||||
|
{
|
||||||
|
passed = filename.substr(0, filename.length() - 2);
|
||||||
|
}
|
||||||
|
if(filename.at(filename.length() - 2) == '>')
|
||||||
|
passed = filename.substr(0, filename.length() - 6);
|
||||||
|
copy = passed;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
std::replace(copy.begin(), copy.end(), '\\', '/');
|
||||||
|
|
||||||
|
if(copy.at(0) == '/')
|
||||||
|
copy.erase(0, 1);
|
||||||
|
|
||||||
|
if(fsstrict == true)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
std::string folder;
|
||||||
|
int delimiter = 0;
|
||||||
|
size_t lastSlash = copy.rfind('/');
|
||||||
|
if (lastSlash != std::string::npos)
|
||||||
|
{
|
||||||
|
folder = copy.substr(0, lastSlash);
|
||||||
|
delimiter = lastSlash+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> current;
|
||||||
|
{
|
||||||
|
std::map<std::string,std::vector<std::string>,ciLessBoost>::const_iterator found = m.find(folder);
|
||||||
|
|
||||||
|
if (found == m.end())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
current = found->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
pathComparer comp(delimiter, copy.size() - delimiter-1);
|
||||||
|
std::vector<std::string>::iterator find = std::lower_bound(current.begin(), current.end(), copy, comp);
|
||||||
|
if (find != current.end() && !comp(copy, current.front()))
|
||||||
|
{
|
||||||
|
copy = *find;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -83,16 +143,14 @@ class DirArchive: public Ogre::FileSystemArchive
|
|||||||
//need to cut off first
|
//need to cut off first
|
||||||
boost::filesystem::directory_iterator dir_iter(d), dir_end;
|
boost::filesystem::directory_iterator dir_iter(d), dir_end;
|
||||||
std::vector<std::string> filesind;
|
std::vector<std::string> filesind;
|
||||||
boost::filesystem::path f;
|
|
||||||
for(;dir_iter != dir_end; dir_iter++)
|
for(;dir_iter != dir_end; dir_iter++)
|
||||||
{
|
{
|
||||||
if(boost::filesystem::is_directory(*dir_iter))
|
if(boost::filesystem::is_directory(*dir_iter))
|
||||||
populateMap(*dir_iter);
|
populateMap(*dir_iter);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
std::string s = dir_iter->path().string();
|
||||||
f = *dir_iter;
|
std::replace(s.begin(), s.end(), '\\', '/');
|
||||||
std::string s = f.string();
|
|
||||||
|
|
||||||
std::string small;
|
std::string small;
|
||||||
if(cutoff < s.size())
|
if(cutoff < s.size())
|
||||||
@ -103,14 +161,17 @@ class DirArchive: public Ogre::FileSystemArchive
|
|||||||
filesind.push_back(small);
|
filesind.push_back(small);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::sort(filesind.begin(), filesind.end(), ciLessBoost());
|
||||||
|
|
||||||
std::string small;
|
std::string small;
|
||||||
std::string original = d.string();
|
std::string original = d.string();
|
||||||
|
std::replace(original.begin(), original.end(), '\\', '/');
|
||||||
if(cutoff < original.size())
|
if(cutoff < original.size())
|
||||||
small = original.substr(cutoff, original.size() - cutoff);
|
small = original.substr(cutoff, original.size() - cutoff);
|
||||||
else
|
else
|
||||||
small = original.substr(cutoff - 1, original.size() - cutoff);
|
small = original.substr(cutoff - 1, original.size() - cutoff);
|
||||||
m[small] = filesind;
|
|
||||||
|
|
||||||
|
m[small] = filesind;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isCaseSensitive() const { return fsstrict; }
|
bool isCaseSensitive() const { return fsstrict; }
|
||||||
@ -120,97 +181,21 @@ class DirArchive: public Ogre::FileSystemArchive
|
|||||||
void unload() {}
|
void unload() {}
|
||||||
|
|
||||||
bool exists(const String& filename) {
|
bool exists(const String& filename) {
|
||||||
std::string copy = filename;
|
std::string copy;
|
||||||
|
|
||||||
|
if (findFile(filename, copy))
|
||||||
|
|
||||||
for (unsigned int i = 0; i < filename.size(); i++)
|
|
||||||
{
|
|
||||||
if(copy.at(i) == '\\' ){
|
|
||||||
copy.replace(i, 1, "/");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(copy.at(0) == '\\' || copy.at(0) == '/')
|
|
||||||
{
|
|
||||||
copy.erase(0, 1);
|
|
||||||
}
|
|
||||||
if(fsstrict == true)
|
|
||||||
{
|
|
||||||
//std::cout << "fsstrict " << copy << "\n";
|
|
||||||
return FileSystemArchive::exists(copy);
|
return FileSystemArchive::exists(copy);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int last = copy.size() - 1;
|
|
||||||
int i = last;
|
|
||||||
|
|
||||||
for (;last >= 0; i--)
|
|
||||||
{
|
|
||||||
if(copy.at(i) == '/' || copy.at(i) == '\\')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string folder = copy.substr(0, i); //folder with no slash
|
|
||||||
|
|
||||||
std::vector<std::string>& current = m[folder];
|
|
||||||
|
|
||||||
for(std::vector<std::string>::iterator iter = current.begin(); iter != current.end(); iter++)
|
|
||||||
{
|
|
||||||
if(comparePortion(*iter, copy, i + 1, copy.size() - i -1) == true){
|
|
||||||
return FileSystemArchive::exists(*iter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataStreamPtr open(const String& filename, bool readonly = true) const
|
DataStreamPtr open(const String& filename, bool readonly = true) const
|
||||||
{
|
{
|
||||||
std::map<std::string, std::vector<std::string>, ciLessBoost> mlocal = m;
|
std::string copy;
|
||||||
std::string copy = filename;
|
|
||||||
|
|
||||||
|
if (findFile(filename, copy))
|
||||||
|
|
||||||
for (unsigned int i = 0; i < filename.size(); i++)
|
|
||||||
{
|
|
||||||
if(copy.at(i) == '\\' ){
|
|
||||||
copy.replace(i, 1, "/");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(copy.at(0) == '\\' || copy.at(0) == '/')
|
|
||||||
{
|
|
||||||
copy.erase(0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(fsstrict == true)
|
|
||||||
{
|
|
||||||
return FileSystemArchive::open(copy, readonly);
|
return FileSystemArchive::open(copy, readonly);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int last = copy.size() - 1;
|
|
||||||
int i = last;
|
|
||||||
|
|
||||||
for (;last >= 0; i--)
|
|
||||||
{
|
|
||||||
if(copy.at(i) == '/' || copy.at(i) == '\\')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string folder = copy.substr(0, i); //folder with no slash
|
|
||||||
std::vector<std::string> current = mlocal[folder];
|
|
||||||
|
|
||||||
for(std::vector<std::string>::iterator iter = current.begin(); iter != current.end(); iter++)
|
|
||||||
{
|
|
||||||
if(comparePortion(*iter, copy, i + 1, copy.size() - i -1) == true){
|
|
||||||
return FileSystemArchive::open(*iter, readonly);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DataStreamPtr p;
|
DataStreamPtr p;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@ -261,7 +246,7 @@ bool exists(const String& filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if the file exists.
|
// Check if the file exists.
|
||||||
bool cexists(const String& filename) const {
|
bool cexists(const String& filename) const {
|
||||||
String passed = filename;
|
String passed = filename;
|
||||||
if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<'
|
if(filename.at(filename.length() - 1) == '*' || filename.at(filename.length() - 1) == '?' || filename.at(filename.length() - 1) == '<'
|
||||||
|| filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':'
|
|| filename.at(filename.length() - 1) == '"' || filename.at(filename.length() - 1) == '>' || filename.at(filename.length() - 1) == ':'
|
||||||
@ -272,7 +257,7 @@ bool exists(const String& filename) {
|
|||||||
if(filename.at(filename.length() - 2) == '>')
|
if(filename.at(filename.length() - 2) == '>')
|
||||||
passed = filename.substr(0, filename.length() - 6);
|
passed = filename.substr(0, filename.length() - 6);
|
||||||
|
|
||||||
return arc.exists(passed.c_str());
|
return arc.exists(passed.c_str());
|
||||||
}
|
}
|
||||||
time_t getModifiedTime(const String&) { return 0; }
|
time_t getModifiedTime(const String&) { return 0; }
|
||||||
|
|
||||||
|
@ -30,4 +30,9 @@ namespace Files
|
|||||||
|
|
||||||
return iter->second;
|
return iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Files::PathContainer& Collections::getPaths() const
|
||||||
|
{
|
||||||
|
return mDirectories;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,8 @@ namespace Files
|
|||||||
/// leading dot and must be all lower-case.
|
/// leading dot and must be all lower-case.
|
||||||
const MultiDirCollection& getCollection(const std::string& extension) const;
|
const MultiDirCollection& getCollection(const std::string& extension) const;
|
||||||
|
|
||||||
|
const Files::PathContainer& getPaths() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::map<std::string, MultiDirCollection> MultiDirCollectionContainer;
|
typedef std::map<std::string, MultiDirCollection> MultiDirCollectionContainer;
|
||||||
Files::PathContainer mDirectories;
|
Files::PathContainer mDirectories;
|
||||||
|
@ -1368,7 +1368,7 @@ void NIFLoader::loadResource(Resource *resource)
|
|||||||
|
|
||||||
if (!vfs->isFile(resourceName))
|
if (!vfs->isFile(resourceName))
|
||||||
{
|
{
|
||||||
warn("File not found.");
|
warn("File "+resourceName+" not found.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binary file not shown.
@ -151,7 +151,8 @@ namespace Physic
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
PhysicEngine::PhysicEngine(BulletShapeLoader* shapeLoader)
|
PhysicEngine::PhysicEngine(BulletShapeLoader* shapeLoader) :
|
||||||
|
mDebugActive(0)
|
||||||
{
|
{
|
||||||
// Set up the collision configuration and dispatcher
|
// Set up the collision configuration and dispatcher
|
||||||
collisionConfiguration = new btDefaultCollisionConfiguration();
|
collisionConfiguration = new btDefaultCollisionConfiguration();
|
||||||
@ -203,6 +204,13 @@ namespace Physic
|
|||||||
createDebugRendering();
|
createDebugRendering();
|
||||||
}
|
}
|
||||||
mDebugDrawer->setDebugMode(mode);
|
mDebugDrawer->setDebugMode(mode);
|
||||||
|
mDebugActive = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PhysicEngine::toggleDebugRendering()
|
||||||
|
{
|
||||||
|
setDebugRenderingMode(!mDebugActive);
|
||||||
|
return mDebugActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicEngine::~PhysicEngine()
|
PhysicEngine::~PhysicEngine()
|
||||||
@ -418,4 +426,35 @@ namespace Physic
|
|||||||
|
|
||||||
return std::pair<std::string,float>(name,d);
|
return std::pair<std::string,float>(name,d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector< std::pair<float, std::string> > PhysicEngine::rayTest2(btVector3& from, btVector3& to)
|
||||||
|
{
|
||||||
|
MyRayResultCallback resultCallback1;
|
||||||
|
resultCallback1.m_collisionFilterMask = COL_WORLD;
|
||||||
|
dynamicsWorld->rayTest(from, to, resultCallback1);
|
||||||
|
std::vector< std::pair<float, btCollisionObject*> > results = resultCallback1.results;
|
||||||
|
|
||||||
|
MyRayResultCallback resultCallback2;
|
||||||
|
resultCallback2.m_collisionFilterMask = COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL;
|
||||||
|
dynamicsWorld->rayTest(from, to, resultCallback2);
|
||||||
|
std::vector< std::pair<float, btCollisionObject*> > actorResults = resultCallback2.results;
|
||||||
|
|
||||||
|
std::vector< std::pair<float, std::string> > results2;
|
||||||
|
|
||||||
|
for (std::vector< std::pair<float, btCollisionObject*> >::iterator it=results.begin();
|
||||||
|
it != results.end(); ++it)
|
||||||
|
{
|
||||||
|
results2.push_back( std::make_pair( (*it).first, static_cast<RigidBody&>(*(*it).second).mName ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector< std::pair<float, btCollisionObject*> >::iterator it=actorResults.begin();
|
||||||
|
it != actorResults.end(); ++it)
|
||||||
|
{
|
||||||
|
results2.push_back( std::make_pair( (*it).first, static_cast<PairCachingGhostObject&>(*(*it).second).mName ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(results2.begin(), results2.end(), MyRayResultCallback::cmp);
|
||||||
|
|
||||||
|
return results2;
|
||||||
|
}
|
||||||
}};
|
}};
|
||||||
|
@ -199,11 +199,18 @@ namespace Physic
|
|||||||
*/
|
*/
|
||||||
void setDebugRenderingMode(int mode);
|
void setDebugRenderingMode(int mode);
|
||||||
|
|
||||||
|
bool toggleDebugRendering();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the closest object hit by a ray. If there are no objects, it will return ("",-1).
|
* Return the closest object hit by a ray. If there are no objects, it will return ("",-1).
|
||||||
*/
|
*/
|
||||||
std::pair<std::string,float> rayTest(btVector3& from,btVector3& to);
|
std::pair<std::string,float> rayTest(btVector3& from,btVector3& to);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all objects hit by a ray.
|
||||||
|
*/
|
||||||
|
std::vector< std::pair<float, std::string> > rayTest2(btVector3& from, btVector3& to);
|
||||||
|
|
||||||
//event list of non player object
|
//event list of non player object
|
||||||
std::list<PhysicEvent> NPEventList;
|
std::list<PhysicEvent> NPEventList;
|
||||||
|
|
||||||
@ -230,6 +237,26 @@ namespace Physic
|
|||||||
//debug rendering
|
//debug rendering
|
||||||
BtOgre::DebugDrawer* mDebugDrawer;
|
BtOgre::DebugDrawer* mDebugDrawer;
|
||||||
bool isDebugCreated;
|
bool isDebugCreated;
|
||||||
|
bool mDebugActive;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct MyRayResultCallback : public btCollisionWorld::RayResultCallback
|
||||||
|
{
|
||||||
|
virtual btScalar addSingleResult( btCollisionWorld::LocalRayResult& rayResult, bool bNormalInWorldSpace)
|
||||||
|
{
|
||||||
|
results.push_back( std::make_pair(rayResult.m_hitFraction, rayResult.m_collisionObject) );
|
||||||
|
return rayResult.m_hitFraction;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool cmp( const std::pair<float, std::string>& i, const std::pair<float, std::string>& j )
|
||||||
|
{
|
||||||
|
if( i.first > j.first ) return false;
|
||||||
|
if( j.first > i.first ) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector < std::pair<float, btCollisionObject*> > results;
|
||||||
};
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user