forked from teamnwah/openmw-tes3coop
Merge branch 'master' into graphics
This commit is contained in:
commit
ee883446b5
26 changed files with 2896 additions and 97 deletions
|
@ -122,6 +122,10 @@ set(OENGINE_BULLET
|
|||
${LIBDIR}/openengine/bullet/physic.hpp
|
||||
${LIBDIR}/openengine/bullet/BulletShapeLoader.cpp
|
||||
${LIBDIR}/openengine/bullet/BulletShapeLoader.h
|
||||
${LIBDIR}/openengine/bullet/pmove.cpp
|
||||
${LIBDIR}/openengine/bullet/pmove.h
|
||||
${LIBDIR}/openengine/bullet/trace.cpp
|
||||
${LIBDIR}/openengine/bullet/trace.h
|
||||
|
||||
)
|
||||
|
||||
|
|
|
@ -148,7 +148,6 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
|
|||
, mNewGame (false)
|
||||
, mUseSound (true)
|
||||
, mCompileAll (false)
|
||||
, mFocusTDiff (0)
|
||||
, mScriptContext (0)
|
||||
, mFSStrict (false)
|
||||
, mCfgMgr(configurationManager)
|
||||
|
@ -263,7 +262,6 @@ void OMW::Engine::setNewGame(bool newGame)
|
|||
|
||||
void OMW::Engine::go()
|
||||
{
|
||||
mFocusTDiff = 0;
|
||||
assert (!mCellName.empty());
|
||||
assert (!mMaster.empty());
|
||||
assert (!mOgre);
|
||||
|
|
|
@ -74,7 +74,6 @@ namespace OMW
|
|||
bool mNewGame;
|
||||
bool mUseSound;
|
||||
bool mCompileAll;
|
||||
float mFocusTDiff;
|
||||
std::string mFocusName;
|
||||
std::map<std::string,std::string> mFallbackMap;
|
||||
|
||||
|
|
|
@ -287,11 +287,12 @@ namespace MWClass
|
|||
{
|
||||
Ogre::Vector3 vector (0, 0, 0);
|
||||
|
||||
vector.x = - getMovementSettings (ptr).mLeftRight * 200;
|
||||
vector.y = getMovementSettings (ptr).mForwardBackward * 200;
|
||||
vector.x = - getMovementSettings (ptr).mLeftRight * 127;
|
||||
vector.y = getMovementSettings (ptr).mForwardBackward * 127;
|
||||
vector.z = getMovementSettings(ptr).mUpDown * 127;
|
||||
|
||||
if (getStance (ptr, Run, false))
|
||||
vector *= 2;
|
||||
//if (getStance (ptr, Run, false))
|
||||
// vector *= 2;
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
|
|
@ -161,6 +161,8 @@ namespace MWDialogue
|
|||
|
||||
bool DialogueManager::functionFilter(const MWWorld::Ptr& actor, const ESM::DialInfo& info,bool choice)
|
||||
{
|
||||
bool isCreature = (actor.getTypeName() != typeid(ESM::NPC).name());
|
||||
|
||||
for (std::vector<ESM::DialInfo::SelectStruct>::const_iterator iter (info.selects.begin());
|
||||
iter != info.selects.end(); ++iter)
|
||||
{
|
||||
|
@ -195,6 +197,9 @@ namespace MWDialogue
|
|||
|
||||
case 46://Same faction
|
||||
{
|
||||
if (isCreature)
|
||||
return false;
|
||||
|
||||
MWMechanics::NpcStats PCstats = MWWorld::Class::get(MWBase::Environment::get().getWorld()->getPlayer().getPlayer()).getNpcStats(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
|
||||
MWMechanics::NpcStats NPCstats = MWWorld::Class::get(actor).getNpcStats(actor);
|
||||
int sameFaction = 0;
|
||||
|
@ -283,6 +288,8 @@ namespace MWDialogue
|
|||
bool DialogueManager::isMatching (const MWWorld::Ptr& actor,
|
||||
const ESM::DialInfo::SelectStruct& select) const
|
||||
{
|
||||
bool isCreature = (actor.getTypeName() != typeid(ESM::NPC).name());
|
||||
|
||||
char type = select.selectRule[1];
|
||||
|
||||
if (type!='0')
|
||||
|
@ -380,6 +387,9 @@ namespace MWDialogue
|
|||
return true;
|
||||
|
||||
case '8':// not faction
|
||||
if (isCreature)
|
||||
return false;
|
||||
|
||||
if(select.type==ESM::VT_Int)
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* npc = actor.get<ESM::NPC>();
|
||||
|
@ -394,6 +404,9 @@ namespace MWDialogue
|
|||
return true;
|
||||
|
||||
case '9':// not class
|
||||
if (isCreature)
|
||||
return false;
|
||||
|
||||
if(select.type==ESM::VT_Int)
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* npc = actor.get<ESM::NPC>();
|
||||
|
@ -408,6 +421,9 @@ namespace MWDialogue
|
|||
return true;
|
||||
|
||||
case 'A'://not Race
|
||||
if (isCreature)
|
||||
return false;
|
||||
|
||||
if(select.type==ESM::VT_Int)
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* npc = actor.get<ESM::NPC>();
|
||||
|
@ -464,6 +480,8 @@ namespace MWDialogue
|
|||
|
||||
bool DialogueManager::isMatching (const MWWorld::Ptr& actor, const ESM::DialInfo& info) const
|
||||
{
|
||||
bool isCreature = (actor.getTypeName() != typeid(ESM::NPC).name());
|
||||
|
||||
// actor id
|
||||
if (!info.actor.empty())
|
||||
if (toLower (info.actor)!=MWWorld::Class::get (actor).getId (actor))
|
||||
|
@ -472,6 +490,9 @@ namespace MWDialogue
|
|||
//NPC race
|
||||
if (!info.race.empty())
|
||||
{
|
||||
if (isCreature)
|
||||
return false;
|
||||
|
||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
|
||||
|
||||
if (!cellRef)
|
||||
|
@ -484,6 +505,9 @@ namespace MWDialogue
|
|||
//NPC class
|
||||
if (!info.clas.empty())
|
||||
{
|
||||
if (isCreature)
|
||||
return false;
|
||||
|
||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *cellRef = actor.get<ESM::NPC>();
|
||||
|
||||
if (!cellRef)
|
||||
|
@ -496,6 +520,9 @@ namespace MWDialogue
|
|||
//NPC faction
|
||||
if (!info.npcFaction.empty())
|
||||
{
|
||||
if (isCreature)
|
||||
return false;
|
||||
|
||||
//MWWorld::Class npcClass = MWWorld::Class::get(actor);
|
||||
MWMechanics::NpcStats stats = MWWorld::Class::get(actor).getNpcStats(actor);
|
||||
std::map<std::string,int>::iterator it = stats.mFactionRank.find(info.npcFaction);
|
||||
|
@ -529,16 +556,18 @@ namespace MWDialogue
|
|||
}
|
||||
|
||||
//check gender
|
||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* npc = actor.get<ESM::NPC>();
|
||||
if(npc->base->flags&npc->base->Female)
|
||||
if (!isCreature)
|
||||
{
|
||||
if(static_cast<int> (info.data.gender)==0) return false;
|
||||
ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData>* npc = actor.get<ESM::NPC>();
|
||||
if(npc->base->flags&npc->base->Female)
|
||||
{
|
||||
if(static_cast<int> (info.data.gender)==0) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(static_cast<int> (info.data.gender)==1) return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(static_cast<int> (info.data.gender)==1) return false;
|
||||
}
|
||||
|
||||
|
||||
// check cell
|
||||
if (!info.cell.empty())
|
||||
|
@ -839,6 +868,9 @@ namespace MWDialogue
|
|||
|
||||
std::string DialogueManager::getFaction()
|
||||
{
|
||||
if (mActor.getTypeName() != typeid(ESM::NPC).name())
|
||||
return "";
|
||||
|
||||
std::string factionID("");
|
||||
MWMechanics::NpcStats stats = MWWorld::Class::get(mActor).getNpcStats(mActor);
|
||||
if(stats.mFactionRank.empty())
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "mode.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwsound/soundmanager.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -16,6 +17,7 @@ namespace
|
|||
{
|
||||
const char* mText;
|
||||
const char* mButtons[3];
|
||||
const char* mSound;
|
||||
ESM::Class::Specialization mSpecializations[3]; // The specialization for each answer
|
||||
};
|
||||
|
||||
|
@ -25,6 +27,7 @@ namespace
|
|||
{"Draw your dagger, mercifully endings its life with a single thrust.",
|
||||
"Use herbs from your pack to put it to sleep.",
|
||||
"Do not interfere in the natural evolution of events, but rather take the opportunity to learn more about a strange animal that you have never seen before."},
|
||||
"vo\\misc\\chargen qa1.wav",
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 2
|
||||
|
@ -32,6 +35,7 @@ namespace
|
|||
{"Work in the forge with him casting iron for a new plow.",
|
||||
"Gather herbs for your mother who is preparing dinner.",
|
||||
"Go catch fish at the stream using a net and line."},
|
||||
"vo\\misc\\chargen qa2.wav",
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 3
|
||||
|
@ -39,6 +43,7 @@ namespace
|
|||
{"Beat up your cousin, then tell him that if he ever calls you that nickname again, you will bloody him worse than this time.",
|
||||
"Make up a story that makes your nickname a badge of honor instead of something humiliating.",
|
||||
"Make up an even more embarrassing nickname for him and use it constantly until he learns his lesson."},
|
||||
"vo\\misc\\chargen qa3.wav",
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 4
|
||||
|
@ -46,6 +51,7 @@ namespace
|
|||
{"This is a terrible practice. A person's thoughts are his own and no one, not even a king, has the right to make such an invasion into another human's mind.",
|
||||
"Loyal followers to the king have nothing to fear from a Telepath. It is important to have a method of finding assassins and spies before it is too late.",
|
||||
"In these times, it is a necessary evil. Although you do not necessarily like the idea, a Telepath could have certain advantages during a time of war or in finding someone innocent of a crime."},
|
||||
"vo\\misc\\chargen qa4.wav",
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 5
|
||||
|
@ -53,6 +59,7 @@ namespace
|
|||
{"Return to the store and give the shopkeeper his hard-earned money, explaining to him the mistake?",
|
||||
"Decide to put the extra money to good use and purchase items that would help your family?",
|
||||
"Pocket the extra money, knowing that shopkeepers in general tend to overcharge customers anyway?"},
|
||||
"vo\\misc\\chargen qa5.wav",
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 6
|
||||
|
@ -60,6 +67,7 @@ namespace
|
|||
{"Pick up the bag and signal to the guard, knowing that the only honorable thing to do is return the money to its rightful owner.",
|
||||
"Leave the bag there, knowing that it is better not to get involved.",
|
||||
"Pick up the bag and pocket it, knowing that the extra windfall will help your family in times of trouble."},
|
||||
"vo\\misc\\chargen qa6.wav",
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 7
|
||||
|
@ -67,6 +75,7 @@ namespace
|
|||
{"Decline his offer, knowing that your father expects you to do the work, and it is better not to be in debt.",
|
||||
"Ask him to help you, knowing that two people can do the job faster than one, and agree to help him with one task of his choosing in the future.",
|
||||
"Accept his offer, reasoning that as long as the stables are cleaned, it matters not who does the cleaning."},
|
||||
"vo\\misc\\chargen qa7.wav",
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 8
|
||||
|
@ -74,6 +83,7 @@ namespace
|
|||
{"Position yourself between the pipe and your mother.",
|
||||
"Grab the hot pipe and try to push it away.",
|
||||
"Push your mother out of the way."},
|
||||
"vo\\misc\\chargen qa8.wav",
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 9
|
||||
|
@ -81,6 +91,7 @@ namespace
|
|||
{"Drop the sweetroll and step on it, then get ready for the fight.",
|
||||
"Give him the sweetroll now without argument, knowing that later this afternoon you will have all your friends with you and can come and take whatever he owes you.",
|
||||
"Act like you're going to give him the sweetroll, but at the last minute throw it in the air, hoping that they'll pay attention to it long enough for you to get a shot in on the leader."},
|
||||
"vo\\misc\\chargen qa9.wav",
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
},
|
||||
// Question 10
|
||||
|
@ -88,6 +99,7 @@ namespace
|
|||
{"Rush to the town's aid immediately, despite your lack of knowledge of the circumstances.",
|
||||
"Stand aside and allow the man and the mob to pass, realizing it is probably best not to get involved.",
|
||||
"Rush to the man's aid immediately, despite your lack of knowledge of the circumstances."},
|
||||
"vo\\misc\\chargen qa10.wav",
|
||||
{ESM::Class::Combat, ESM::Class::Magic, ESM::Class::Stealth}
|
||||
}
|
||||
} };
|
||||
|
@ -479,6 +491,8 @@ void CharacterCreation::onCreateClassDialogBack()
|
|||
|
||||
void CharacterCreation::onClassQuestionChosen(int _index)
|
||||
{
|
||||
MWBase::Environment::get().getSoundManager()->stopSay();
|
||||
|
||||
if (mGenerateClassQuestionDialog)
|
||||
mWM->removeDialog(mGenerateClassQuestionDialog);
|
||||
if (_index < 0 || _index >= 3)
|
||||
|
@ -584,6 +598,8 @@ void CharacterCreation::showClassQuestionDialog()
|
|||
mGenerateClassQuestionDialog->setButtons(buttons);
|
||||
mGenerateClassQuestionDialog->eventButtonSelected += MyGUI::newDelegate(this, &CharacterCreation::onClassQuestionChosen);
|
||||
mGenerateClassQuestionDialog->open();
|
||||
|
||||
MWBase::Environment::get().getSoundManager()->say(sGenerateClassSteps[mGenerateClassStep].mSound);
|
||||
}
|
||||
|
||||
void CharacterCreation::onGenerateClassBack()
|
||||
|
|
|
@ -60,6 +60,7 @@ namespace MWInput
|
|||
A_CycleWeaponRight,
|
||||
A_ToggleSneak, //Toggles Sneak, add Push-Sneak later
|
||||
A_ToggleWalk, //Toggle Walking/Running
|
||||
A_Crouch,
|
||||
|
||||
A_QuickSave,
|
||||
A_QuickLoad,
|
||||
|
@ -310,6 +311,9 @@ namespace MWInput
|
|||
poller.bind(A_MoveRight, KC_D);
|
||||
poller.bind(A_MoveForward, KC_W);
|
||||
poller.bind(A_MoveBackward, KC_S);
|
||||
|
||||
poller.bind(A_Jump, KC_E);
|
||||
poller.bind(A_Crouch, KC_LCONTROL);
|
||||
}
|
||||
|
||||
//NOTE: Used to check for movement keys
|
||||
|
@ -356,6 +360,13 @@ namespace MWInput
|
|||
}
|
||||
else
|
||||
player.setForwardBackward (0);
|
||||
|
||||
if (poller.isDown(A_Jump))
|
||||
player.setUpDown (1);
|
||||
else if (poller.isDown(A_Crouch))
|
||||
player.setUpDown (-1);
|
||||
else
|
||||
player.setUpDown (0);
|
||||
}
|
||||
|
||||
// Switch between gui modes. Besides controlling the Gui windows
|
||||
|
|
|
@ -8,8 +8,9 @@ namespace MWMechanics
|
|||
{
|
||||
signed char mLeftRight; // 1: wants to move left, -1: wants to move right
|
||||
signed char mForwardBackward; // 1:wants to move forward, -1: wants to move backward
|
||||
signed char mUpDown;
|
||||
|
||||
Movement() : mLeftRight (0), mForwardBackward (0) {}
|
||||
Movement() : mLeftRight (0), mForwardBackward (0), mUpDown(0) {}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -53,8 +53,10 @@ void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_)
|
|||
|
||||
Ogre::SceneNode* insert = cellnode->createChildSceneNode();
|
||||
const float *f = ptr.getRefData().getPosition().pos;
|
||||
|
||||
insert->setPosition(f[0], f[1], f[2]);
|
||||
insert->setScale(ptr.getCellRef().scale, ptr.getCellRef().scale, ptr.getCellRef().scale);
|
||||
|
||||
|
||||
// Convert MW rotation to a quaternion:
|
||||
f = ptr.getCellRef().pos.rot;
|
||||
|
|
|
@ -189,7 +189,7 @@ void MpgSnd_Decoder::readAll(std::vector<char> &output)
|
|||
{
|
||||
size_t pos = output.size();
|
||||
output.resize(pos + mSndInfo.frames*mSndInfo.channels*2);
|
||||
sf_readf_short(mSndFile, (short*)(output.data()+pos), mSndInfo.frames);
|
||||
sf_readf_short(mSndFile, (short*)(&output[0]+pos), mSndInfo.frames);
|
||||
return;
|
||||
}
|
||||
// Fallback in case we don't know the total already
|
||||
|
|
|
@ -222,8 +222,8 @@ void OpenAL_SoundStream::play()
|
|||
for(ALuint i = 0;i < sNumBuffers;i++)
|
||||
{
|
||||
size_t got;
|
||||
got = mDecoder->read(data.data(), data.size());
|
||||
alBufferData(mBuffers[i], mFormat, data.data(), got, mSampleRate);
|
||||
got = mDecoder->read(&data[0], data.size());
|
||||
alBufferData(mBuffers[i], mFormat, &data[0], got, mSampleRate);
|
||||
}
|
||||
throwALerror();
|
||||
|
||||
|
@ -299,11 +299,11 @@ bool OpenAL_SoundStream::process()
|
|||
if(finished)
|
||||
continue;
|
||||
|
||||
got = mDecoder->read(data.data(), data.size());
|
||||
got = mDecoder->read(&data[0], data.size());
|
||||
finished = (got < data.size());
|
||||
if(got > 0)
|
||||
{
|
||||
alBufferData(bufid, mFormat, data.data(), got, mSampleRate);
|
||||
alBufferData(bufid, mFormat, &data[0], got, mSampleRate);
|
||||
alSourceQueueBuffers(mSource, 1, &bufid);
|
||||
}
|
||||
} while(processed > 0);
|
||||
|
@ -595,7 +595,7 @@ ALuint OpenAL_Output::getBuffer(const std::string &fname)
|
|||
alGenBuffers(1, &buf);
|
||||
throwALerror();
|
||||
|
||||
alBufferData(buf, format, data.data(), data.size(), srate);
|
||||
alBufferData(buf, format, &data[0], data.size(), srate);
|
||||
mBufferCache[fname] = buf;
|
||||
mBufferRefs[buf] = 1;
|
||||
|
||||
|
|
|
@ -228,11 +228,47 @@ namespace MWSound
|
|||
}
|
||||
}
|
||||
|
||||
void SoundManager::say(const std::string& filename)
|
||||
{
|
||||
if(!mOutput->isInitialized())
|
||||
return;
|
||||
try
|
||||
{
|
||||
float basevol = mMasterVolume * mSFXVolume;
|
||||
std::string filePath = "Sound/"+filename;
|
||||
|
||||
SoundPtr sound = mOutput->playSound(filePath, basevol, 1.0f, Play_Normal);
|
||||
sound->mBaseVolume = basevol;
|
||||
|
||||
mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), std::string("_say_sound"));
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
std::cout <<"Sound Error: "<<e.what()<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool SoundManager::sayDone(MWWorld::Ptr ptr) const
|
||||
{
|
||||
return !isPlaying(ptr, "_say_sound");
|
||||
}
|
||||
|
||||
void SoundManager::stopSay(MWWorld::Ptr ptr)
|
||||
{
|
||||
SoundMap::iterator snditer = mActiveSounds.begin();
|
||||
while(snditer != mActiveSounds.end())
|
||||
{
|
||||
if(snditer->second.first == ptr && snditer->second.second == "_say_sound")
|
||||
{
|
||||
snditer->first->stop();
|
||||
mActiveSounds.erase(snditer++);
|
||||
}
|
||||
else
|
||||
snditer++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
SoundPtr SoundManager::playSound(const std::string& soundId, float volume, float pitch, int mode)
|
||||
{
|
||||
|
|
|
@ -97,11 +97,18 @@ namespace MWSound
|
|||
|
||||
void say(MWWorld::Ptr reference, const std::string& filename);
|
||||
///< Make an actor say some text.
|
||||
/// \param filename name of a sound file in "Sound/Vo/" in the data directory.
|
||||
/// \param filename name of a sound file in "Sound/" in the data directory.
|
||||
|
||||
bool sayDone(MWWorld::Ptr reference) const;
|
||||
void say(const std::string& filename);
|
||||
///< Say some text, without an actor ref
|
||||
/// \param filename name of a sound file in "Sound/" in the data directory.
|
||||
|
||||
bool sayDone(MWWorld::Ptr reference=MWWorld::Ptr()) const;
|
||||
///< Is actor not speaking?
|
||||
|
||||
void stopSay(MWWorld::Ptr reference=MWWorld::Ptr());
|
||||
///< Stop an actor speaking
|
||||
|
||||
SoundPtr playSound(const std::string& soundId, float volume, float pitch, int mode=Play_Normal);
|
||||
///< Play a sound, independently of 3D-position
|
||||
|
||||
|
|
|
@ -21,23 +21,24 @@ namespace MWWorld
|
|||
PhysicsSystem::PhysicsSystem(OEngine::Render::OgreRenderer &_rend) :
|
||||
mRender(_rend), mEngine(0), mFreeFly (true)
|
||||
{
|
||||
|
||||
|
||||
playerphysics = new playerMove;
|
||||
// Create physics. shapeLoader is deleted by the physic engine
|
||||
NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader();
|
||||
mEngine = new OEngine::Physic::PhysicEngine(shapeLoader);
|
||||
|
||||
playerphysics->mEngine = mEngine;
|
||||
}
|
||||
|
||||
PhysicsSystem::~PhysicsSystem()
|
||||
{
|
||||
delete mEngine;
|
||||
|
||||
|
||||
}
|
||||
OEngine::Physic::PhysicEngine* PhysicsSystem::getEngine()
|
||||
{
|
||||
return mEngine;
|
||||
}
|
||||
|
||||
|
||||
std::pair<std::string, float> PhysicsSystem::getFacedHandle (MWWorld::World& world)
|
||||
{
|
||||
std::string handle = "";
|
||||
|
@ -65,6 +66,13 @@ namespace MWWorld
|
|||
|
||||
return mEngine->rayTest2(from,to);
|
||||
}
|
||||
void PhysicsSystem::setCurrentWater(bool hasWater, int waterHeight){
|
||||
playerphysics->hasWater = hasWater;
|
||||
if(hasWater){
|
||||
playerphysics->waterHeight = waterHeight;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
btVector3 PhysicsSystem::getRayPoint(float extent)
|
||||
{
|
||||
|
@ -75,35 +83,35 @@ namespace MWWorld
|
|||
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)
|
||||
{
|
||||
btVector3 _from, _to;
|
||||
_from = btVector3(from.x, from.y, from.z);
|
||||
_to = btVector3(to.x, to.y, to.z);
|
||||
|
||||
|
||||
std::pair<std::string, float> result = mEngine->rayTest(_from, _to);
|
||||
|
||||
|
||||
return !(result.first == "");
|
||||
}
|
||||
|
||||
|
||||
std::vector< std::pair<std::string, Ogre::Vector3> > PhysicsSystem::doPhysics (float duration,
|
||||
const std::vector<std::pair<std::string, Ogre::Vector3> >& actors)
|
||||
void PhysicsSystem::doPhysics(float dt, const std::vector<std::pair<std::string, Ogre::Vector3> >& actors)
|
||||
{
|
||||
//set the DebugRenderingMode. To disable it,set it to 0
|
||||
//eng->setDebugRenderingMode(1);
|
||||
|
||||
|
||||
|
||||
//set the walkdirection to 0 (no movement) for every actor)
|
||||
for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++)
|
||||
{
|
||||
OEngine::Physic::PhysicActor* act = it->second;
|
||||
act->setWalkDirection(btVector3(0,0,0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
playerMove::playercmd& pm_ref = playerphysics->cmd;
|
||||
|
||||
pm_ref.rightmove = 0;
|
||||
pm_ref.forwardmove = 0;
|
||||
pm_ref.upmove = 0;
|
||||
|
||||
//playerphysics->ps.move_type = PM_NOCLIP;
|
||||
for (std::vector<std::pair<std::string, Ogre::Vector3> >::const_iterator iter (actors.begin());
|
||||
iter!=actors.end(); ++iter)
|
||||
|
@ -118,21 +126,24 @@ namespace MWWorld
|
|||
Ogre::Node* yawNode = sceneNode->getChildIterator().getNext();
|
||||
Ogre::Node* pitchNode = yawNode->getChildIterator().getNext();
|
||||
Ogre::Quaternion yawQuat = yawNode->getOrientation();
|
||||
Ogre::Quaternion pitchQuat = pitchNode->getOrientation();
|
||||
Ogre::Quaternion both = yawQuat * pitchQuat;
|
||||
|
||||
|
||||
//playerphysics->ps.viewangles.z = both.getPitch().valueDegrees();
|
||||
|
||||
|
||||
Ogre::Quaternion pitchQuat = pitchNode->getOrientation();
|
||||
|
||||
// unused
|
||||
//Ogre::Quaternion both = yawQuat * pitchQuat;
|
||||
|
||||
playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees();
|
||||
playerphysics->ps.viewangles.z = 0;
|
||||
playerphysics->ps.viewangles.y = yawQuat.getYaw().valueDegrees() *-1 + 90;
|
||||
|
||||
if(mFreeFly)
|
||||
{
|
||||
|
||||
Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
pm_ref.rightmove = -dir1.x;
|
||||
pm_ref.forwardmove = dir1.z;
|
||||
pm_ref.upmove = dir1.y;
|
||||
|
||||
|
||||
//std::cout << "Current angle" << yawQuat.getYaw().valueDegrees() - 90<< "\n";
|
||||
//playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees();
|
||||
//std::cout << "Pitch: " << yawQuat.getPitch() << "Yaw:" << yawQuat.getYaw() << "Roll: " << yawQuat.getRoll() << "\n";
|
||||
|
@ -140,31 +151,65 @@ namespace MWWorld
|
|||
}
|
||||
else
|
||||
{
|
||||
|
||||
Ogre::Quaternion quat = yawNode->getOrientation();
|
||||
Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y);
|
||||
|
||||
|
||||
|
||||
pm_ref.rightmove = -dir1.x;
|
||||
pm_ref.forwardmove = dir1.z;
|
||||
pm_ref.upmove = dir1.y;
|
||||
|
||||
|
||||
|
||||
dir = 0.025*(quat*dir1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//set the walk direction
|
||||
act->setWalkDirection(btVector3(dir.x,-dir.z,dir.y));
|
||||
}
|
||||
mEngine->stepSimulation(duration);
|
||||
|
||||
mEngine->stepSimulation(dt);
|
||||
}
|
||||
|
||||
std::vector< std::pair<std::string, Ogre::Vector3> > PhysicsSystem::doPhysicsFixed (
|
||||
const std::vector<std::pair<std::string, Ogre::Vector3> >& actors)
|
||||
{
|
||||
Pmove(playerphysics);
|
||||
|
||||
std::vector< std::pair<std::string, Ogre::Vector3> > response;
|
||||
for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++)
|
||||
{
|
||||
btVector3 newPos = it->second->getPosition();
|
||||
|
||||
|
||||
Ogre::Vector3 coord(newPos.x(), newPos.y(), newPos.z());
|
||||
|
||||
if(it->first == "player"){
|
||||
|
||||
coord = playerphysics->ps.origin;
|
||||
//std::cout << "ZCoord: " << coord.z << "\n";
|
||||
//std::cout << "Coord" << coord << "\n";
|
||||
//coord = Ogre::Vector3(coord.x, coord.z, coord.y); //x, z, -y
|
||||
|
||||
}
|
||||
|
||||
|
||||
response.push_back(std::pair<std::string, Ogre::Vector3>(it->first, coord));
|
||||
}
|
||||
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
void PhysicsSystem::addHeightField (float* heights,
|
||||
int x, int y, float yoffset,
|
||||
float triSize, float sqrtVerts)
|
||||
{
|
||||
mEngine->addHeightField(heights, x, y, yoffset, triSize, sqrtVerts);
|
||||
}
|
||||
|
||||
void PhysicsSystem::removeHeightField (int x, int y)
|
||||
{
|
||||
mEngine->removeHeightField(x, y);
|
||||
}
|
||||
|
||||
void PhysicsSystem::addObject (const std::string& handle, const std::string& mesh,
|
||||
const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position)
|
||||
{
|
||||
|
@ -207,7 +252,14 @@ namespace MWWorld
|
|||
{
|
||||
// TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow
|
||||
// start positions others than 0, 0, 0
|
||||
act->setPosition(btVector3(position.x,position.y,position.z));
|
||||
if (handle == "player")
|
||||
{
|
||||
playerphysics->ps.origin = position;
|
||||
}
|
||||
else
|
||||
{
|
||||
act->setPosition(btVector3(position.x,position.y,position.z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,6 +280,11 @@ namespace MWWorld
|
|||
|
||||
bool PhysicsSystem::toggleCollisionMode()
|
||||
{
|
||||
if(playerphysics->ps.move_type==PM_NOCLIP)
|
||||
playerphysics->ps.move_type=PM_NORMAL;
|
||||
|
||||
else
|
||||
playerphysics->ps.move_type=PM_NOCLIP;
|
||||
for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++)
|
||||
{
|
||||
if (it->first=="player")
|
||||
|
@ -258,7 +315,12 @@ namespace MWWorld
|
|||
}
|
||||
|
||||
void PhysicsSystem::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string model){
|
||||
|
||||
Ogre::SceneNode* node = ptr.getRefData().getBaseNode();
|
||||
|
||||
// unused
|
||||
//Ogre::Vector3 objPos = node->getPosition();
|
||||
|
||||
addObject (node->getName(), model, node->getOrientation(),
|
||||
node->getScale().x, node->getPosition());
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <openengine/ogre/renderer.hpp>
|
||||
#include <openengine/bullet/physic.hpp>
|
||||
#include "ptr.hpp"
|
||||
#include <openengine/bullet/pmove.h>
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
|
@ -15,8 +16,11 @@ namespace MWWorld
|
|||
PhysicsSystem (OEngine::Render::OgreRenderer &_rend);
|
||||
~PhysicsSystem ();
|
||||
|
||||
std::vector< std::pair<std::string, Ogre::Vector3> > doPhysics (float duration,
|
||||
const std::vector<std::pair<std::string, Ogre::Vector3> >& actors);
|
||||
void doPhysics(float duration, const std::vector<std::pair<std::string, Ogre::Vector3> >& actors);
|
||||
///< do physics with dt - Usage: first call doPhysics with frame dt, then call doPhysicsFixed as often as time steps have passed
|
||||
|
||||
std::vector< std::pair<std::string, Ogre::Vector3> > doPhysicsFixed (const std::vector<std::pair<std::string, Ogre::Vector3> >& actors);
|
||||
///< do physics with fixed timestep - Usage: first call doPhysics with frame dt, then call doPhysicsFixed as often as time steps have passed
|
||||
|
||||
void addObject (const std::string& handle, const std::string& mesh,
|
||||
const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position);
|
||||
|
@ -24,6 +28,12 @@ namespace MWWorld
|
|||
void addActor (const std::string& handle, const std::string& mesh,
|
||||
const Ogre::Vector3& position);
|
||||
|
||||
void addHeightField (float* heights,
|
||||
int x, int y, float yoffset,
|
||||
float triSize, float sqrtVerts);
|
||||
|
||||
void removeHeightField (int x, int y);
|
||||
|
||||
void removeObject (const std::string& handle);
|
||||
|
||||
void moveObject (const std::string& handle, const Ogre::Vector3& position);
|
||||
|
@ -49,11 +59,13 @@ namespace MWWorld
|
|||
|
||||
OEngine::Physic::PhysicEngine* getEngine();
|
||||
|
||||
void setCurrentWater(bool hasWater, int waterHeight);
|
||||
|
||||
private:
|
||||
OEngine::Render::OgreRenderer &mRender;
|
||||
OEngine::Physic::PhysicEngine* mEngine;
|
||||
bool mFreeFly;
|
||||
|
||||
playerMove* playerphysics;
|
||||
|
||||
PhysicsSystem (const PhysicsSystem&);
|
||||
PhysicsSystem& operator= (const PhysicsSystem&);
|
||||
|
|
|
@ -85,6 +85,14 @@ namespace MWWorld
|
|||
|
||||
MWWorld::Class::get (ptr).getMovementSettings (ptr).mForwardBackward = value;
|
||||
}
|
||||
void Player::setUpDown(int value)
|
||||
{
|
||||
MWWorld::Ptr ptr = getPlayer();
|
||||
|
||||
|
||||
|
||||
MWWorld::Class::get (ptr).getMovementSettings (ptr).mUpDown = value;
|
||||
}
|
||||
|
||||
void Player::toggleRunning()
|
||||
{
|
||||
|
@ -100,4 +108,5 @@ namespace MWWorld
|
|||
MWWorld::Ptr ptr = getPlayer();
|
||||
return MWWorld::Class::get(ptr).getNpcStats(ptr).mDrawState;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -116,6 +116,7 @@ namespace MWWorld
|
|||
void setLeftRight (int value);
|
||||
|
||||
void setForwardBackward (int value);
|
||||
void setUpDown(int value);
|
||||
|
||||
void toggleRunning();
|
||||
};
|
||||
|
|
|
@ -75,11 +75,14 @@ namespace MWWorld
|
|||
|
||||
|
||||
// silence annoying g++ warning
|
||||
for (std::vector<Ogre::SceneNode*>::const_iterator iter (functor.mHandles.begin());
|
||||
iter!=functor.mHandles.end(); ++iter){
|
||||
Ogre::SceneNode* node = *iter;
|
||||
for (std::vector<Ogre::SceneNode*>::const_iterator iter2 (functor.mHandles.begin());
|
||||
iter2!=functor.mHandles.end(); ++iter2){
|
||||
Ogre::SceneNode* node = *iter2;
|
||||
mPhysics->removeObject (node->getName());
|
||||
}
|
||||
|
||||
if (!((*iter)->cell->data.flags & ESM::Cell::Interior))
|
||||
mPhysics->removeHeightField( (*iter)->cell->data.gridX, (*iter)->cell->data.gridY );
|
||||
}
|
||||
|
||||
mRendering.removeCell(*iter);
|
||||
|
@ -103,20 +106,36 @@ namespace MWWorld
|
|||
|
||||
std::pair<CellStoreCollection::iterator, bool> result =
|
||||
mActiveCells.insert(cell);
|
||||
if(result.second){
|
||||
insertCell(*cell);
|
||||
mRendering.cellAdded(cell);
|
||||
mRendering.configureAmbient(*cell);
|
||||
mRendering.requestMap(cell);
|
||||
mRendering.configureAmbient(*cell);
|
||||
}
|
||||
|
||||
if(result.second)
|
||||
{
|
||||
insertCell(*cell);
|
||||
mRendering.cellAdded (cell);
|
||||
|
||||
float verts = ESM::Land::LAND_SIZE;
|
||||
float worldsize = ESM::Land::REAL_SIZE;
|
||||
|
||||
if (!(cell->cell->data.flags & ESM::Cell::Interior))
|
||||
{
|
||||
ESM::Land* land = mWorld->getStore().lands.search(cell->cell->data.gridX,cell->cell->data.gridY);
|
||||
mPhysics->addHeightField (land->landData->heights,
|
||||
cell->cell->data.gridX, cell->cell->data.gridY,
|
||||
0, ( worldsize/(verts-1) ), verts);
|
||||
}
|
||||
|
||||
mRendering.configureAmbient(*cell);
|
||||
mRendering.requestMap(cell);
|
||||
mRendering.configureAmbient(*cell);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Scene::playerCellChange (Ptr::CellStore *cell, const ESM::Position& position,
|
||||
bool adjustPlayerPos)
|
||||
{
|
||||
bool hasWater = cell->cell->data.flags & cell->cell->HasWater;
|
||||
mPhysics->setCurrentWater(hasWater, cell->cell->water);
|
||||
if (adjustPlayerPos)
|
||||
mWorld->getPlayer().setPos (position.pos[0], position.pos[1], position.pos[2]);
|
||||
|
||||
|
|
|
@ -215,6 +215,7 @@ namespace MWWorld
|
|||
|
||||
setFallbackValues(fallbackMap);
|
||||
|
||||
lastTick = mTimer.getMilliseconds();
|
||||
}
|
||||
|
||||
|
||||
|
@ -559,8 +560,9 @@ namespace MWWorld
|
|||
}
|
||||
}
|
||||
|
||||
void World::moveObjectImp (Ptr ptr, float x, float y, float z)
|
||||
bool World::moveObjectImp (Ptr ptr, float x, float y, float z)
|
||||
{
|
||||
bool ret = false;
|
||||
ptr.getRefData().getPosition().pos[0] = x;
|
||||
ptr.getRefData().getPosition().pos[1] = y;
|
||||
ptr.getRefData().getPosition().pos[2] = z;
|
||||
|
@ -582,6 +584,7 @@ namespace MWWorld
|
|||
if (currentCell->cell->data.gridX!=cellX || currentCell->cell->data.gridY!=cellY)
|
||||
{
|
||||
mWorldScene->changeCell (cellX, cellY, mPlayer->getPlayer().getRefData().getPosition(), false);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -591,6 +594,8 @@ namespace MWWorld
|
|||
/// \todo cell change for non-player ref
|
||||
|
||||
mRendering->moveObject (ptr, Ogre::Vector3 (x, y, z));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void World::moveObject (Ptr ptr, float x, float y, float z)
|
||||
|
@ -632,29 +637,50 @@ namespace MWWorld
|
|||
void World::doPhysics (const std::vector<std::pair<std::string, Ogre::Vector3> >& actors,
|
||||
float duration)
|
||||
{
|
||||
std::vector< std::pair<std::string, Ogre::Vector3> > vectors = mPhysics->doPhysics (duration, actors);
|
||||
mPhysics->doPhysics(duration, actors);
|
||||
|
||||
std::vector< std::pair<std::string, Ogre::Vector3> >::iterator player = vectors.end();
|
||||
const int tick = 16; // 16 ms ^= 60 Hz
|
||||
|
||||
for (std::vector< std::pair<std::string, Ogre::Vector3> >::iterator it = vectors.begin();
|
||||
it!= vectors.end(); ++it)
|
||||
// Game clock part of the loop, contains everything that has to be executed in a fixed timestep
|
||||
long long dt = mTimer.getMilliseconds() - lastTick;
|
||||
if (dt >= 100)
|
||||
{
|
||||
if (it->first=="player")
|
||||
// throw away wall clock time if necessary to keep the framerate above the minimum of 10 fps
|
||||
lastTick += (dt - 100);
|
||||
dt = 100;
|
||||
}
|
||||
while (dt >= tick)
|
||||
{
|
||||
dt -= tick;
|
||||
lastTick += tick;
|
||||
|
||||
std::vector< std::pair<std::string, Ogre::Vector3> > vectors = mPhysics->doPhysicsFixed (actors);
|
||||
|
||||
std::vector< std::pair<std::string, Ogre::Vector3> >::iterator player = vectors.end();
|
||||
|
||||
for (std::vector< std::pair<std::string, Ogre::Vector3> >::iterator it = vectors.begin();
|
||||
it!= vectors.end(); ++it)
|
||||
{
|
||||
player = it;
|
||||
if (it->first=="player")
|
||||
{
|
||||
player = it;
|
||||
}
|
||||
else
|
||||
{
|
||||
MWWorld::Ptr ptr = getPtrViaHandle (it->first);
|
||||
moveObjectImp (ptr, it->second.x, it->second.y, it->second.z);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
// Make sure player is moved last (otherwise the cell might change in the middle of an update
|
||||
// loop)
|
||||
if (player!=vectors.end())
|
||||
{
|
||||
MWWorld::Ptr ptr = getPtrViaHandle (it->first);
|
||||
moveObjectImp (ptr, it->second.x, it->second.y, it->second.z);
|
||||
if (moveObjectImp (getPtrViaHandle (player->first),
|
||||
player->second.x, player->second.y, player->second.z) == true)
|
||||
return; // abort the current loop if the cell has changed
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure player is moved last (otherwise the cell might change in the middle of an update
|
||||
// loop)
|
||||
if (player!=vectors.end())
|
||||
moveObjectImp (getPtrViaHandle (player->first),
|
||||
player->second.x, player->second.y, player->second.z);
|
||||
}
|
||||
|
||||
bool World::toggleCollisionMode()
|
||||
|
@ -789,7 +815,8 @@ namespace MWWorld
|
|||
std::vector < std::pair < float, std::string > >::iterator it = results.begin();
|
||||
while (it != results.end())
|
||||
{
|
||||
if ( getPtrViaHandle((*it).second) == mPlayer->getPlayer() )
|
||||
if ( (*it).second.find("HeightField") != std::string::npos // not interested in terrain
|
||||
|| getPtrViaHandle((*it).second) == mPlayer->getPlayer() ) // not interested in player (unless you want to talk to yourself)
|
||||
{
|
||||
it = results.erase(it);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include <openengine/bullet/physic.hpp>
|
||||
#include <openengine/ogre/fader.hpp>
|
||||
|
||||
#include <OgreTimer.h>
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class Vector3;
|
||||
|
@ -101,9 +103,13 @@ namespace MWWorld
|
|||
int mNumFacing;
|
||||
std::map<std::string,std::string> mFallback;
|
||||
|
||||
unsigned long lastTick;
|
||||
Ogre::Timer mTimer;
|
||||
|
||||
int getDaysPerMonth (int month) const;
|
||||
|
||||
void moveObjectImp (Ptr ptr, float x, float y, float z);
|
||||
bool moveObjectImp (Ptr ptr, float x, float y, float z);
|
||||
///< @return true if the active cell (cell player is in) changed
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "physic.hpp"
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
#include <btBulletCollisionCommon.h>
|
||||
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
||||
#include <components/nifbullet/bullet_nif_loader.hpp>
|
||||
//#include <apps\openmw\mwworld\world.hpp>
|
||||
#include "CMotionState.h"
|
||||
|
@ -10,6 +11,8 @@
|
|||
#include "BtOgreGP.h"
|
||||
#include "BtOgreExtras.h"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#define BIT(x) (1<<(x))
|
||||
|
||||
namespace OEngine {
|
||||
|
@ -161,10 +164,12 @@ namespace Physic
|
|||
// The actual physics solver
|
||||
solver = new btSequentialImpulseConstraintSolver;
|
||||
|
||||
//btOverlappingPairCache* pairCache = new btSortedOverlappingPairCache();
|
||||
pairCache = new btSortedOverlappingPairCache();
|
||||
|
||||
//pairCache->setInternalGhostPairCallback( new btGhostPairCallback() );
|
||||
|
||||
broadphase = new btDbvtBroadphase(pairCache);
|
||||
broadphase = new btDbvtBroadphase();
|
||||
|
||||
// The world.
|
||||
dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);
|
||||
|
@ -253,6 +258,60 @@ namespace Physic
|
|||
delete mShapeLoader;
|
||||
}
|
||||
|
||||
void PhysicEngine::addHeightField(float* heights,
|
||||
int x, int y, float yoffset,
|
||||
float triSize, float sqrtVerts)
|
||||
{
|
||||
const std::string name = "HeightField_"
|
||||
+ boost::lexical_cast<std::string>(x) + "_"
|
||||
+ boost::lexical_cast<std::string>(y);
|
||||
|
||||
// find the minimum and maximum heights (needed for bullet)
|
||||
float minh;
|
||||
float maxh;
|
||||
for (int i=0; i<sqrtVerts*sqrtVerts; ++i)
|
||||
{
|
||||
float h = heights[i];
|
||||
if (i==0)
|
||||
{
|
||||
minh = h;
|
||||
maxh = h;
|
||||
}
|
||||
|
||||
if (h>maxh) maxh = h;
|
||||
if (h<minh) minh = h;
|
||||
}
|
||||
|
||||
btHeightfieldTerrainShape* hfShape = new btHeightfieldTerrainShape(
|
||||
sqrtVerts, sqrtVerts, heights, 1,
|
||||
minh, maxh, 2,
|
||||
PHY_FLOAT,true);
|
||||
|
||||
hfShape->setUseDiamondSubdivision(true);
|
||||
|
||||
btVector3 scl(triSize, triSize, 1);
|
||||
hfShape->setLocalScaling(scl);
|
||||
|
||||
CMotionState* newMotionState = new CMotionState(this,name);
|
||||
|
||||
btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,hfShape);
|
||||
RigidBody* body = new RigidBody(CI,name);
|
||||
body->collide = true;
|
||||
body->getWorldTransform().setOrigin(btVector3( (x+0.5)*triSize*(sqrtVerts-1), (y+0.5)*triSize*(sqrtVerts-1), (maxh+minh)/2.f));
|
||||
|
||||
addRigidBody(body);
|
||||
}
|
||||
|
||||
void PhysicEngine::removeHeightField(int x, int y)
|
||||
{
|
||||
const std::string name = "HeightField_"
|
||||
+ boost::lexical_cast<std::string>(x) + "_"
|
||||
+ boost::lexical_cast<std::string>(y);
|
||||
|
||||
removeRigidBody(name);
|
||||
deleteRigidBody(name);
|
||||
}
|
||||
|
||||
RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name,float scale)
|
||||
{
|
||||
//get the shape from the .nif
|
||||
|
@ -334,7 +393,7 @@ namespace Physic
|
|||
|
||||
void PhysicEngine::stepSimulation(double deltaT)
|
||||
{
|
||||
dynamicsWorld->stepSimulation(deltaT,1,1/50.);
|
||||
dynamicsWorld->stepSimulation(deltaT,10, 1/60.0);
|
||||
if(isDebugCreated)
|
||||
{
|
||||
mDebugDrawer->step();
|
||||
|
|
|
@ -140,6 +140,18 @@ namespace Physic
|
|||
*/
|
||||
RigidBody* createRigidBody(std::string mesh,std::string name,float scale);
|
||||
|
||||
/**
|
||||
* Add a HeightField to the simulation
|
||||
*/
|
||||
void addHeightField(float* heights,
|
||||
int x, int y, float yoffset,
|
||||
float triSize, float sqrtVerts);
|
||||
|
||||
/**
|
||||
* Remove a HeightField from the simulation
|
||||
*/
|
||||
void removeHeightField(int x, int y);
|
||||
|
||||
/**
|
||||
* Add a RigidBody to the simulation
|
||||
*/
|
||||
|
|
2095
libs/openengine/bullet/pmove.cpp
Normal file
2095
libs/openengine/bullet/pmove.cpp
Normal file
File diff suppressed because it is too large
Load diff
200
libs/openengine/bullet/pmove.h
Normal file
200
libs/openengine/bullet/pmove.h
Normal file
|
@ -0,0 +1,200 @@
|
|||
#ifndef OENGINE_BULLET_PMOVE_H
|
||||
#define OENGINE_BULLET_PMOVE_H
|
||||
/*
|
||||
This source file is a *modified* version of various header files from the Quake 3 Arena source code,
|
||||
which was released under the GNU GPL (v2) in 2005.
|
||||
Quake 3 Arena is copyright (C) 1999-2005 Id Software, Inc.
|
||||
*/
|
||||
|
||||
#include <Ogre.h>
|
||||
#include <OgreMath.h>
|
||||
#include <float.h>
|
||||
#include "trace.h"
|
||||
#include "physic.hpp"
|
||||
|
||||
|
||||
//#include "GameMath.h"
|
||||
//#include "GameTime.h"
|
||||
|
||||
// Forwards-declare it!
|
||||
|
||||
/*#ifndef COMPILING_PMOVE
|
||||
#include "Scene.h"
|
||||
extern SceneInstance* global_lastscene;
|
||||
#endif*/
|
||||
|
||||
static const Ogre::Vector3 halfExtents(14.64f * 2, 14.24f * 2, 33.25f * 2);
|
||||
|
||||
#define MAX_CLIP_PLANES 5
|
||||
#define OVERCLIP 1.001f
|
||||
//#define STEPSIZE 18 // 18 is way too much
|
||||
#define STEPSIZE (18 / 2)
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846f
|
||||
#endif
|
||||
#define YAW 0
|
||||
#define PITCH /*1*/2
|
||||
#define ROLL /*2*/1
|
||||
#define SHORT2ANGLE(x) ( (x) * (360.0f / 65536.0f) )
|
||||
#define ANGLE2SHORT(x) ( (const short)( (x) / (360.0f / 65536.0f) ) )
|
||||
#define GENTITYNUM_BITS 10 // don't need to send any more
|
||||
#define MAX_GENTITIES (1 << GENTITYNUM_BITS)
|
||||
#define ENTITYNUM_NONE (MAX_GENTITIES - 1)
|
||||
#define ENTITYNUM_WORLD (MAX_GENTITIES - 2)
|
||||
#define MIN_WALK_NORMAL 0.7f // can't walk on very steep slopes
|
||||
#define JUMP_VELOCITY (270)
|
||||
#define PS_PMOVEFRAMECOUNTBITS 6
|
||||
#define MINS_Z -24
|
||||
#define DEFAULT_VIEWHEIGHT 26
|
||||
#define CROUCH_VIEWHEIGHT 12
|
||||
#define DEAD_VIEWHEIGHT (-16)
|
||||
#define CONTENTS_SOLID 1 // an eye is never valid in a solid
|
||||
#define CONTENTS_LAVA 8
|
||||
#define CONTENTS_SLIME 16
|
||||
#define CONTENTS_WATER 32
|
||||
#define CONTENTS_FOG 64
|
||||
static const float pm_accelerate = 10.0f;
|
||||
static const float pm_stopspeed = 100.0f;
|
||||
static const float pm_friction = 12.0f;
|
||||
static const float pm_flightfriction = 3.0f;
|
||||
static const float pm_waterfriction = 1.0f;
|
||||
static const float pm_airaccelerate = 1.0f;
|
||||
static const float pm_swimScale = 0.50f;
|
||||
static const float pm_duckScale = 0.25f;
|
||||
static const float pm_flyaccelerate = 8.0f;
|
||||
static const float pm_wateraccelerate = 4.0f;
|
||||
|
||||
enum pmtype_t
|
||||
{
|
||||
PM_NORMAL, // can accelerate and turn
|
||||
PM_NOCLIP, // noclip movement
|
||||
PM_SPECTATOR, // still run into walls
|
||||
PM_DEAD, // no acceleration or turning, but free falling
|
||||
PM_FREEZE, // stuck in place with no control
|
||||
PM_INTERMISSION, // no movement or status bar
|
||||
PM_SPINTERMISSION // no movement or status bar
|
||||
};
|
||||
|
||||
enum waterlevel_t
|
||||
{
|
||||
WL_DRYLAND = 0,
|
||||
WL_ANKLE,
|
||||
WL_WAIST,
|
||||
WL_UNDERWATER
|
||||
};
|
||||
|
||||
|
||||
//#include "bprintf.h"
|
||||
|
||||
struct playerMove
|
||||
{
|
||||
struct playerStruct
|
||||
{
|
||||
playerStruct() : gravity(800.0f), speed(480.0f), pmove_framecount(20), groundEntityNum(ENTITYNUM_NONE), commandTime(40), move_type(PM_NOCLIP), pm_time(0), snappingImplemented(true), bSnap(false), counter(-1)
|
||||
{
|
||||
origin = Ogre::Vector3(733.164f,900.0f, 839.432f);
|
||||
velocity = Ogre::Vector3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
viewangles = Ogre::Vector3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
delta_angles[0] = delta_angles[1] = delta_angles[2] = 0;
|
||||
|
||||
lastframe_origin.x = lastframe_origin.y = lastframe_origin.z = 0;
|
||||
lerp_multiplier.x = lerp_multiplier.y = lerp_multiplier.z = 0;
|
||||
}
|
||||
|
||||
inline void SpeedUp(void)
|
||||
{
|
||||
//printf("speed up to: %f\n", speed);
|
||||
speed *= 1.25f;
|
||||
}
|
||||
|
||||
inline void SpeedDown(void)
|
||||
{
|
||||
//printf("speed down to %f\n", speed);
|
||||
speed /= 1.25f;
|
||||
}
|
||||
|
||||
Ogre::Vector3 velocity;
|
||||
Ogre::Vector3 origin;
|
||||
bool bSnap;
|
||||
bool snappingImplemented;
|
||||
int counter;
|
||||
float gravity; // default = 800
|
||||
float speed; // default = 320
|
||||
|
||||
int commandTime; // the time at which this command was issued (in milliseconds)
|
||||
|
||||
int pm_time;
|
||||
|
||||
Ogre::Vector3 viewangles;
|
||||
|
||||
int groundEntityNum;
|
||||
|
||||
int pmove_framecount;
|
||||
|
||||
int watertype;
|
||||
waterlevel_t waterlevel;
|
||||
|
||||
signed short delta_angles[3];
|
||||
|
||||
pmtype_t move_type;
|
||||
|
||||
float last_compute_time;
|
||||
Ogre::Vector3 lastframe_origin;
|
||||
Ogre::Vector3 lerp_multiplier;
|
||||
} ps;
|
||||
|
||||
struct playercmd
|
||||
{
|
||||
enum CMDstateChange
|
||||
{
|
||||
NO_CHANGE,
|
||||
KEYDOWN,
|
||||
KEYUP
|
||||
};
|
||||
|
||||
playercmd() : forwardmove(0), rightmove(0), upmove(0), serverTime(50), ducking(false),
|
||||
activating(false), lastActivatingState(false), procActivating(NO_CHANGE),
|
||||
dropping(false), lastDroppingState(false), procDropping(NO_CHANGE)
|
||||
{
|
||||
angles[0] = angles[1] = angles[2] = 0;
|
||||
}
|
||||
|
||||
int serverTime;
|
||||
|
||||
short angles[3];
|
||||
|
||||
signed char forwardmove;
|
||||
signed char rightmove;
|
||||
signed char upmove;
|
||||
|
||||
bool ducking;
|
||||
bool activating; // if the user is holding down the activate button
|
||||
bool dropping; // if the user is dropping an item
|
||||
|
||||
bool lastActivatingState;
|
||||
bool lastDroppingState;
|
||||
|
||||
CMDstateChange procActivating;
|
||||
CMDstateChange procDropping;
|
||||
} cmd;
|
||||
|
||||
playerMove() : msec(50), pmove_fixed(false), pmove_msec(50), waterHeight(0), isInterior(true), hasWater(false)
|
||||
{
|
||||
}
|
||||
|
||||
int msec;
|
||||
int pmove_msec;
|
||||
bool pmove_fixed;
|
||||
int waterHeight;
|
||||
bool hasWater;
|
||||
bool isInterior;
|
||||
//Object* traceObj;
|
||||
OEngine::Physic::PhysicEngine* mEngine;
|
||||
};
|
||||
|
||||
void Pmove (playerMove* const pmove);
|
||||
void Ext_UpdateViewAngles(playerMove* const pm);
|
||||
void AngleVectors( const Ogre::Vector3& angles, Ogre::Vector3* const forward, Ogre::Vector3* const right, Ogre::Vector3* const up) ;
|
||||
#endif
|
190
libs/openengine/bullet/trace.cpp
Normal file
190
libs/openengine/bullet/trace.cpp
Normal file
|
@ -0,0 +1,190 @@
|
|||
|
||||
#include "trace.h"
|
||||
|
||||
|
||||
|
||||
#include <map>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void newtrace(traceResults* const results, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, const float rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass) //Traceobj was a Aedra Object
|
||||
{
|
||||
|
||||
//if (!traceobj)
|
||||
// return;
|
||||
|
||||
//if (!traceobj->incellptr)
|
||||
// return;
|
||||
|
||||
const Ogre::Vector3 rayDir = end - start;
|
||||
|
||||
// Nudge starting point backwards
|
||||
//const Position3D nudgestart = start + (rayDir * -0.1f); // by 10% (isn't that too much?)
|
||||
//const Position3D nudgestart = start;
|
||||
|
||||
NewPhysTraceResults out;
|
||||
//std::cout << "Starting trace\n";
|
||||
//Ogre::Vector3 startReplace = Ogre::Vector3(650,950, 45);
|
||||
//Ogre::Vector3 endReplace = startReplace;
|
||||
//endReplace.z -= .25;
|
||||
|
||||
const bool hasHit = NewPhysicsTrace<collisionWorldTrace>(&out, start, end, BBHalfExtents, Ogre::Vector3(0.0f, 0.0, rotation), isInterior, enginePass);
|
||||
|
||||
if (out.fraction < 0.001f)
|
||||
results->startsolid = true;
|
||||
else
|
||||
results->startsolid = false;
|
||||
|
||||
|
||||
//results->allsolid = out.startSolid;
|
||||
|
||||
// If outside and underground, we're solid
|
||||
/*if (isInterior)
|
||||
{
|
||||
const Ogre::Vector3 height = GetGroundPosition(start, CellCoords(traceCell->data->gridX, traceCell->data->gridY) );
|
||||
if (start.yPos - height.yPos < (-2.0f * BBHalfExtents.yPos) )
|
||||
{
|
||||
results->allsolid = true;
|
||||
}
|
||||
else
|
||||
results->allsolid = false;
|
||||
}*/
|
||||
|
||||
// If inside and out of the tree, we're solid
|
||||
//else
|
||||
//{
|
||||
results->allsolid = out.startSolid;
|
||||
//std::cout << "allsolid" << results->allsolid << "\n";
|
||||
//}
|
||||
|
||||
if (!hasHit)
|
||||
{
|
||||
results->endpos = end;
|
||||
results->planenormal = Ogre::Vector3(0.0f, 0.0f, 1.0f);
|
||||
results->entityNum = ENTITYNUM_NONE;
|
||||
results->fraction = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
results->fraction = out.fraction;
|
||||
results->planenormal = out.hitNormal;
|
||||
results->endpos = rayDir * results->fraction + start;
|
||||
results->entityNum = ENTITYNUM_WORLD;
|
||||
/*bprintf("Start: (%f, %f, %f) End: (%f, %f, %f) TraceDir: (%f, %f, %f) HitNormal: (%f, %f, %f) Fraction: %f Hitpos: (%f, %f, %f) CompensatedHitpos: (%f, %f, %f)\n",
|
||||
start.xPos, start.yPos, start.zPos,
|
||||
end.xPos, end.yPos, end.zPos,
|
||||
rayDir.xPos, rayDir.yPos, rayDir.zPos,
|
||||
results->planenormal.xPos, results->planenormal.yPos, results->planenormal.zPos, results->fraction,
|
||||
out.endPos.xPos, out.endPos.yPos, out.endPos.zPos,
|
||||
results->endpos.xPos, results->endpos.yPos, results->endpos.zPos);*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <const traceWorldType traceType>
|
||||
const bool NewPhysicsTrace(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end,
|
||||
const Ogre::Vector3& BBHalfExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass)
|
||||
{
|
||||
//if (!traceobj->incellptr)
|
||||
// return false;
|
||||
//if(enginePass->dynamicsWorld->getCollisionObjectArray().at(60)->getCollisionShape()->isConvex())
|
||||
// std::cout << "It's convex\n";
|
||||
|
||||
|
||||
|
||||
const btVector3 btstart(start.x, start.y, start.z);
|
||||
const btVector3 btend(end.x, end.y, end.z);
|
||||
const btQuaternion btrot(rotation.y, rotation.x, rotation.z); //y, x, z
|
||||
|
||||
const btBoxShape newshape(btVector3(BBHalfExtents.x, BBHalfExtents.y, BBHalfExtents.z));
|
||||
const btTransform from(btrot, btstart);
|
||||
const btTransform to(btrot, btend);
|
||||
|
||||
// warning: unused variable ...
|
||||
/*
|
||||
float x = from.getOrigin().getX();
|
||||
float y = from.getOrigin().getY();
|
||||
float z = from.getOrigin().getZ();
|
||||
float x2 = to.getOrigin().getX();
|
||||
float y2 = to.getOrigin().getY();
|
||||
float z2 = to.getOrigin().getZ();
|
||||
*/
|
||||
|
||||
//std::cout << "BtFrom: " << x << "," << y << "," << z << "\n";
|
||||
//std::cout << "BtTo: " << x2 << "," << y2 << "," << z2 << "\n";
|
||||
//std::cout << "BtTo: " << to.getOrigin().getX() << "," << to.getOrigin().getY() << "," << to.getOrigin().getZ() << "\n";
|
||||
|
||||
|
||||
btCollisionWorld::ClosestConvexResultCallback
|
||||
newTraceCallback(btstart, btend);
|
||||
|
||||
newTraceCallback.m_collisionFilterMask = (traceType == collisionWorldTrace) ? Only_Collision : Only_Pickup;
|
||||
|
||||
|
||||
enginePass->dynamicsWorld->convexSweepTest(&newshape, from, to, newTraceCallback);
|
||||
//newTraceCallback.
|
||||
|
||||
|
||||
//std::cout << "NUM: " << enginePass->dynamicsWorld->getNumCollisionObjects() << "\n";
|
||||
|
||||
// Copy the hit data over to our trace results struct:
|
||||
out->fraction = newTraceCallback.m_closestHitFraction;
|
||||
|
||||
Ogre::Vector3& outhitnormal = out->hitNormal;
|
||||
const btVector3& tracehitnormal = newTraceCallback.m_hitNormalWorld;
|
||||
|
||||
outhitnormal.x = tracehitnormal.x();
|
||||
outhitnormal.y = tracehitnormal.y();
|
||||
outhitnormal.z = tracehitnormal.z();
|
||||
|
||||
Ogre::Vector3& outhitpos = out->endPos;
|
||||
const btVector3& tracehitpos = newTraceCallback.m_hitPointWorld;
|
||||
|
||||
outhitpos.x = tracehitpos.x();
|
||||
outhitpos.y = tracehitpos.y();
|
||||
outhitpos.z= tracehitpos.z();
|
||||
|
||||
// StartSolid test:
|
||||
{
|
||||
out->startSolid = false;
|
||||
//btCollisionObject collision;
|
||||
//collision.setCollisionShape(const_cast<btBoxShape* const>(&newshape) );
|
||||
|
||||
//CustomContactCallback crb;
|
||||
|
||||
//world.world->contactTest(&collision, crb);
|
||||
//out->startSolid = crb.hit;
|
||||
|
||||
// If outside and underground, we're solid
|
||||
if (!isInterior) //Check if we are interior
|
||||
{
|
||||
}
|
||||
|
||||
// If inside and out of the tree, we're solid
|
||||
else
|
||||
{
|
||||
btVector3 aabbMin, aabbMax;
|
||||
enginePass->broadphase->getBroadphaseAabb(aabbMin, aabbMax);
|
||||
//std::cout << "AABBMIN" << aabbMin.getX() <<"," <<aabbMin.getY() << "," << aabbMin.getZ() << "\n";
|
||||
//std::cout << "AABBMAX" << aabbMax.getX() <<"," <<aabbMax.getY() << "," << aabbMax.getZ() << "\n";
|
||||
//std::cout << "AABBMAX" << aabbMax << "\n";
|
||||
if (!TestPointAgainstAabb2(aabbMin, aabbMax, *(const btVector3* const)&(start) ) )
|
||||
{
|
||||
//We're solid
|
||||
out->startSolid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bool hasHit = newTraceCallback.hasHit();
|
||||
|
||||
|
||||
|
||||
|
||||
return hasHit;
|
||||
}
|
|
@ -18,7 +18,7 @@ enum traceWorldType
|
|||
bothWorldTrace = collisionWorldTrace | pickWorldTrace
|
||||
};
|
||||
|
||||
enum collaborativePhysicsType : unsigned
|
||||
enum collaborativePhysicsType
|
||||
{
|
||||
No_Physics = 0, // Both are empty (example: statics you can walk through, like tall grass)
|
||||
Only_Collision = 1, // This object only has collision physics but no pickup physics (example: statics)
|
||||
|
@ -53,10 +53,10 @@ struct traceResults
|
|||
|
||||
template <const traceWorldType traceType>
|
||||
const bool NewPhysicsTrace(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass);
|
||||
template const bool NewPhysicsTrace<collisionWorldTrace>(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass);
|
||||
template const bool NewPhysicsTrace<pickWorldTrace>(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass);
|
||||
//template const bool NewPhysicsTrace<collisionWorldTrace>(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass);
|
||||
//template const bool NewPhysicsTrace<pickWorldTrace>(NewPhysTraceResults* const out, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const Ogre::Vector3& rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass);
|
||||
|
||||
void newtrace(traceResults* const results, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBExtents, const float rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass);
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue