Merge remote-tracking branch 'zini/master' into animations

actorid
Chris Robinson 12 years ago
commit 24e503330b

@ -54,7 +54,7 @@ add_openmw_dir (mwworld
containerstore actiontalk actiontake manualref player cellfunctors failedaction
cells localscripts customdata weather inventorystore ptr actionopen actionread
actionequip timestamp actionalchemy cellstore actionapply actioneat
esmstore store recordcmp fallback actionrepair actionsoulgem livecellref
esmstore store recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
)
add_openmw_dir (mwclass

@ -326,6 +326,9 @@ namespace MWBase
virtual void setupPlayer(bool newGame) = 0;
virtual void renderPlayer() = 0;
virtual void activateDoor(const MWWorld::Ptr& door) = 0;
///< activate (open or close) an non-teleport door
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering) = 0;
virtual int canRest() = 0;

@ -12,6 +12,7 @@
#include "../mwworld/nullaction.hpp"
#include "../mwworld/failedaction.hpp"
#include "../mwworld/actionteleport.hpp"
#include "../mwworld/actiondoor.hpp"
#include "../mwworld/cellstore.hpp"
#include "../mwworld/physicssystem.hpp"
#include "../mwworld/inventorystore.hpp"
@ -71,7 +72,7 @@ namespace MWClass
ptr.get<ESM::Door>();
const std::string &openSound = ref->mBase->mOpenSound;
//const std::string &closeSound = ref->mBase->closeSound;
const std::string &closeSound = ref->mBase->mCloseSound;
const std::string lockedSound = "LockedDoor";
const std::string trapActivationSound = "Disarm Trap Fail";
@ -139,12 +140,11 @@ namespace MWClass
else
{
// animated door
// TODO return action for rotating the door
// This is a little pointless, but helps with testing
boost::shared_ptr<MWWorld::Action> action(new MWWorld::NullAction);
action->setSound(openSound);
boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionDoor(ptr));
if (ptr.getRefData().getLocalRotation().rot[2] == 0)
action->setSound(openSound);
else
action->setSound(closeSound);
return action;
}

@ -28,6 +28,7 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/player.hpp"
#include "../mwworld/class.hpp"
@ -103,7 +104,7 @@ static void getStateInfo(CharacterState state, std::string *group)
CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim, CharacterState state, bool loop)
: mPtr(ptr), mAnimation(anim), mCharState(state), mSkipAnim(false), mMovingAnim(false)
: mPtr(ptr), mAnimation(anim), mCharState(state), mSkipAnim(false), mMovingAnim(false), mSecondsOfRunning(0), mSecondsOfSwimming(0)
{
if(!mAnimation)
return;
@ -152,6 +153,29 @@ void CharacterController::update(float duration, Movement &movement)
const Ogre::Vector3 &rot = cls.getRotationVector(mPtr);
speed = cls.getSpeed(mPtr);
// advance athletics
if (vec.squaredLength() > 0 && mPtr == MWBase::Environment::get().getWorld()->getPlayer().getPlayer())
{
if (inwater)
{
mSecondsOfSwimming += duration;
while (mSecondsOfSwimming > 1)
{
MWWorld::Class::get(mPtr).skillUsageSucceeded(mPtr, ESM::Skill::Athletics, 1);
mSecondsOfSwimming -= 1;
}
}
else if (isrunning)
{
mSecondsOfRunning += duration;
while (mSecondsOfRunning > 1)
{
MWWorld::Class::get(mPtr).skillUsageSucceeded(mPtr, ESM::Skill::Athletics, 0);
mSecondsOfRunning -= 1;
}
}
}
/* FIXME: The state should be set to Jump, and X/Y movement should be disallowed except
* for the initial thrust (which would be carried by "physics" until landing). */
if(onground && vec.z > 0.0f)

@ -79,6 +79,10 @@ class CharacterController
bool mLooping;
bool mSkipAnim;
// counted for skill increase
float mSecondsOfSwimming;
float mSecondsOfRunning;
bool mMovingAnim;
public:

@ -169,8 +169,7 @@ float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& cla
if (specialisationFactor<=0)
throw std::runtime_error ("invalid skill specialisation factor");
}
return 1.0 / (level +1) * (1.0 / (skillFactor)) * typeFactor * specialisationFactor;
return 1.0 / ((level+1) * (1.0/skillFactor) * typeFactor * specialisationFactor);
}
void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_, int usageType)

@ -737,4 +737,6 @@ Ogre::Vector3 Animation::runAnimation(float duration)
return movement;
}
void Animation::showWeapons(bool showWeapon){}
}

@ -161,6 +161,8 @@ public:
virtual Ogre::Vector3 runAnimation(float duration);
virtual void showWeapons(bool showWeapon);
/* Returns if there's an animation playing on the given layer. */
bool isPlaying(size_t layeridx) const
{ return mLayer[layeridx].mPlaying; }

@ -30,7 +30,7 @@ const NpcAnimation::PartInfo NpcAnimation::sPartList[NpcAnimation::sPartListSize
{ ESM::PRT_LHand, "Left Hand" },
{ ESM::PRT_RWrist, "Right Wrist" },
{ ESM::PRT_LWrist, "Left Wrist" },
{ ESM::PRT_Shield, "Shield" },
{ ESM::PRT_Shield, "Shield Bone" },
{ ESM::PRT_RForearm, "Right Forearm" },
{ ESM::PRT_LForearm, "Left Forearm" },
{ ESM::PRT_RUpperarm, "Right Upper Arm" },
@ -45,7 +45,7 @@ const NpcAnimation::PartInfo NpcAnimation::sPartList[NpcAnimation::sPartListSize
{ ESM::PRT_LLeg, "Left Upper Leg" },
{ ESM::PRT_RPauldron, "Right Clavicle" },
{ ESM::PRT_LPauldron, "Left Clavicle" },
{ ESM::PRT_Weapon, "Weapon" },
{ ESM::PRT_Weapon, "Weapon Bone" },
{ ESM::PRT_Tail, "Tail" }
};
@ -74,7 +74,10 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor
mGloveL(inv.end()),
mGloveR(inv.end()),
mSkirtIter(inv.end()),
mViewMode(viewMode)
mWeapon(inv.end()),
mShield(inv.end()),
mViewMode(viewMode),
mShowWeapons(false)
{
mNpc = mPtr.get<ESM::NPC>()->mBase;
@ -175,6 +178,7 @@ void NpcAnimation::updateParts(bool forceupdate)
{ &NpcAnimation::mGloveR, MWWorld::InventoryStore::Slot_RightGauntlet, 0 },
{ &NpcAnimation::mShirt, MWWorld::InventoryStore::Slot_Shirt, 0 },
{ &NpcAnimation::mPants, MWWorld::InventoryStore::Slot_Pants, 0 },
{ &NpcAnimation::mShield, MWWorld::InventoryStore::Slot_CarriedLeft, 0 }
};
static const size_t slotlistsize = sizeof(slotlist)/sizeof(slotlist[0]);
@ -333,6 +337,8 @@ void NpcAnimation::updateParts(bool forceupdate)
if (mPartPriorities[part] < 1 && bodypart)
addOrReplaceIndividualPart(part, -1,1, "meshes\\"+bodypart->mModel);
}
showWeapons(mShowWeapons);
}
NifOgre::ObjectList NpcAnimation::insertBoundedPart(const std::string &model, int group, const std::string &bonename)
@ -464,4 +470,23 @@ void NpcAnimation::addPartGroup(int group, int priority, const std::vector<ESM::
}
}
void NpcAnimation::showWeapons(bool showWeapon)
{
mShowWeapons = showWeapon;
if(showWeapon)
{
MWWorld::InventoryStore &inv = MWWorld::Class::get(mPtr).getInventoryStore(mPtr);
mWeapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
if(mWeapon != inv.end()) // special case for weapons
{
std::string mesh = MWWorld::Class::get(*mWeapon).getModel(*mWeapon);
addOrReplaceIndividualPart(ESM::PRT_Weapon,-1,1,mesh);
}
}
else
{
removeIndividualPart(ESM::PRT_Weapon);
}
}
}

@ -46,6 +46,7 @@ private:
std::string mHairModel;
std::string mBodyPrefix;
ViewMode mViewMode;
bool mShowWeapons;
float mTimeToChange;
MWWorld::ContainerStoreIterator mRobe;
@ -60,6 +61,8 @@ private:
MWWorld::ContainerStoreIterator mGloveL;
MWWorld::ContainerStoreIterator mGloveR;
MWWorld::ContainerStoreIterator mSkirtIter;
MWWorld::ContainerStoreIterator mWeapon;
MWWorld::ContainerStoreIterator mShield;
int mVisibilityFlags;
@ -85,6 +88,8 @@ public:
virtual Ogre::Vector3 runAnimation(float timepassed);
virtual void showWeapons(bool showWeapon);
void setViewMode(ViewMode viewMode);
void forceUpdate()

@ -329,5 +329,7 @@ op 0x2000206: Move
op 0x2000207: Move, explicit
op 0x2000208: MoveWorld
op 0x2000209: MoveWorld, explicit
op 0x200020a: Fall
op 0x200020b: Fall, explicit
opcodes 0x200020a-0x3ffffff unused
opcodes 0x200020c-0x3ffffff unused

@ -555,6 +555,16 @@ namespace MWScript
}
};
template <class R>
class OpFall : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
}
};
const int opcodeXBox = 0x200000c;
const int opcodeOnActivate = 0x200000d;
const int opcodeActivate = 0x2000075;
@ -596,6 +606,8 @@ namespace MWScript
const int opcodeSetDelete = 0x20001e5;
const int opcodeSetDeleteExplicit = 0x20001e6;
const int opcodeGetSquareRoot = 0x20001e7;
const int opcodeFall = 0x200020a;
const int opcodeFallExplicit = 0x200020b;
const int opcodePlayBink = 0x20001f7;
@ -637,6 +649,7 @@ namespace MWScript
extensions.registerFunction ("getcurrenttime", 'f', "", opcodeGetCurrentTime);
extensions.registerInstruction ("setdelete", "l", opcodeSetDelete, opcodeSetDeleteExplicit);
extensions.registerFunction ("getsquareroot", 'f', "f", opcodeGetSquareRoot);
extensions.registerInstruction ("fall", "", opcodeFall, opcodeFallExplicit);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
@ -683,6 +696,9 @@ namespace MWScript
interpreter.installSegment5 (opcodeSetDelete, new OpSetDelete<ImplicitRef>);
interpreter.installSegment5 (opcodeSetDeleteExplicit, new OpSetDelete<ExplicitRef>);
interpreter.installSegment5 (opcodeGetSquareRoot, new OpGetSquareRoot);
interpreter.installSegment5 (opcodeFall, new OpFall<ImplicitRef>);
interpreter.installSegment5 (opcodeFallExplicit, new OpFall<ExplicitRef>);
}
}
}

@ -0,0 +1,16 @@
#include "actiondoor.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
namespace MWWorld
{
ActionDoor::ActionDoor (const MWWorld::Ptr& object) : Action (false, object)
{
}
void ActionDoor::executeImp (const MWWorld::Ptr& actor)
{
MWBase::Environment::get().getWorld()->activateDoor(getTarget());
}
}

@ -0,0 +1,18 @@
#ifndef GAME_MWWORLD_ACTIONDOOR_H
#define GAME_MWWORLD_ACTIONDOOR_H
#include "action.hpp"
#include "ptr.hpp"
namespace MWWorld
{
class ActionDoor : public Action
{
virtual void executeImp (const MWWorld::Ptr& actor);
public:
ActionDoor (const Ptr& object);
};
}
#endif

@ -131,7 +131,6 @@ namespace MWWorld
return position;
}
static Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time,
bool gravity, OEngine::Physic::PhysicEngine *engine)
{
@ -390,6 +389,11 @@ namespace MWWorld
}
}
std::vector<std::string> PhysicsSystem::getCollisions(const Ptr &ptr)
{
return mEngine->getCollisions(ptr.getRefData().getBaseNode()->getName());
}
Ogre::Vector3 PhysicsSystem::move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time, bool gravity)
{
return MovementSolver::move(ptr, movement, time, gravity, mEngine);

@ -51,6 +51,7 @@ namespace MWWorld
bool toggleCollisionMode();
Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time, bool gravity);
std::vector<std::string> getCollisions(const MWWorld::Ptr &ptr); ///< get handles this object collides with
Ogre::Vector3 traceDown(const MWWorld::Ptr &ptr);
std::pair<float, std::string> getFacedHandle (MWWorld::World& world, float queryDistance);

@ -1,4 +1,5 @@
#include "store.hpp"
#include "esmstore.hpp"
namespace MWWorld {
@ -15,8 +16,39 @@ void Store<ESM::Cell>::load(ESM::ESMReader &esm, const std::string &id)
ESM::Cell *cell = new ESM::Cell;
cell->mName = id;
// The cell itself takes care of some of the hairy details
cell->load(esm, *mEsmStore);
//First part of cell loading
cell->preLoad(esm);
//Handling MovedCellRefs, there is no way to do it inside loadcell
while (esm.isNextSub("MVRF")) {
ESM::CellRef ref;
ESM::MovedCellRef cMRef;
cell->getNextMVRF(esm, cMRef);
MWWorld::Store<ESM::Cell> &cStore = const_cast<MWWorld::Store<ESM::Cell>&>(mEsmStore->get<ESM::Cell>());
ESM::Cell *cellAlt = const_cast<ESM::Cell*>(cStore.searchOrCreate(cMRef.mTarget[0], cMRef.mTarget[1]));
// Get regular moved reference data. Adapted from CellStore::loadRefs. Maybe we can optimize the following
// implementation when the oher implementation works as well.
cell->getNextRef(esm, ref);
std::string lowerCase;
std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
// Add data required to make reference appear in the correct cell.
// We should not need to test for duplicates, as this part of the code is pre-cell merge.
cell->mMovedRefs.push_back(cMRef);
// But there may be duplicates here!
ESM::CellRefTracker::iterator iter = std::find(cellAlt->mLeasedRefs.begin(), cellAlt->mLeasedRefs.end(), ref.mRefnum);
if (iter == cellAlt->mLeasedRefs.end())
cellAlt->mLeasedRefs.push_back(ref);
else
*iter = ref;
}
//Second part of cell loading
cell->postLoad(esm);
if(cell->mData.mFlags & ESM::Cell::Interior)
{
@ -62,4 +94,4 @@ void Store<ESM::Cell>::load(ESM::ESMReader &esm, const std::string &id)
delete cell;
}
}
}

@ -289,8 +289,7 @@ void WeatherManager::update(float duration)
if (exterior)
{
std::string regionstr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->mCell->mRegion;
Misc::StringUtils::toLower(regionstr);
std::string regionstr = Misc::StringUtils::lowerCase(MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->mCell->mRegion);
if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion)
{
@ -621,6 +620,9 @@ unsigned int WeatherManager::getWeatherID() const
void WeatherManager::changeWeather(const std::string& region, const unsigned int id)
{
// make sure this region exists
MWBase::Environment::get().getWorld()->getStore().get<ESM::Region>().find(region);
std::string weather;
if (id==0)
weather = "clear";
@ -645,5 +647,9 @@ void WeatherManager::changeWeather(const std::string& region, const unsigned int
else
weather = "clear";
mRegionOverrides[region] = weather;
mRegionOverrides[Misc::StringUtils::lowerCase(region)] = weather;
std::string playerRegion = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()->mCell->mRegion;
if (Misc::StringUtils::ciEqual(region, playerRegion))
setWeather(weather);
}

@ -995,10 +995,62 @@ namespace MWWorld
!isSwimming(player->first) && !isFlying(player->first));
moveObjectImp(player->first, vec.x, vec.y, vec.z);
}
// the only purpose this has currently is to update the debug drawer
processDoors(duration);
mPhysEngine->stepSimulation (duration);
}
void World::processDoors(float duration)
{
std::map<MWWorld::Ptr, int>::iterator it = mDoorStates.begin();
while (it != mDoorStates.end())
{
if (!mWorldScene->isCellActive(*it->first.getCell()))
mDoorStates.erase(it++);
else
{
float oldRot = Ogre::Radian(it->first.getRefData().getLocalRotation().rot[2]).valueDegrees();
float diff = duration * 90;
float targetRot = std::min(std::max(0.f, oldRot + diff * (it->second ? 1 : -1)), 90.f);
localRotateObject(it->first, 0, 0, targetRot);
// AABB of the door
Ogre::Vector3 min,max;
mPhysics->getObjectAABB(it->first, min, max);
Ogre::Vector3 dimensions = max-min;
std::vector<std::string> collisions = mPhysics->getCollisions(it->first);
for (std::vector<std::string>::iterator cit = collisions.begin(); cit != collisions.end(); ++cit)
{
MWWorld::Ptr ptr = getPtrViaHandle(*cit);
if (MWWorld::Class::get(ptr).isActor())
{
// we collided with an actor, we need to undo the rotation and push the door away from the actor
// figure out on which side of the door the actor we collided with is
Ogre::Vector3 relativePos = it->first.getRefData().getBaseNode()->
convertWorldToLocalPosition(ptr.getRefData().getBaseNode()->_getDerivedPosition());
float axisToCheck = (dimensions.x > dimensions.y) ? relativePos.y : -relativePos.x;
if (axisToCheck >= 0)
targetRot = std::min(std::max(0.f, oldRot + diff*0.5f), 90.f);
else
targetRot = std::min(std::max(0.f, oldRot - diff*0.5f), 90.f);
localRotateObject(it->first, 0, 0, targetRot);
break;
}
}
if ((targetRot == 90.f && it->second) || targetRot == 0.f)
mDoorStates.erase(it++);
else
++it;
}
}
}
bool World::toggleCollisionMode()
{
return mPhysics->toggleCollisionMode();;
@ -1470,7 +1522,7 @@ namespace MWWorld
Ogre::Vector3 playerPos(refdata.getPosition().pos);
const OEngine::Physic::PhysicActor *physactor = mPhysEngine->getCharacter(refdata.getHandle());
if(!physactor->getOnGround() || isUnderwater(currentCell, playerPos))
if((!physactor->getOnGround()&&physactor->getCollisionMode()) || isUnderwater(currentCell, playerPos))
return 2;
if((currentCell->mCell->mData.mFlags&ESM::Cell::NoSleep))
return 1;
@ -1497,4 +1549,20 @@ namespace MWWorld
{
mRendering->frameStarted(dt);
}
void World::activateDoor(const MWWorld::Ptr& door)
{
if (mDoorStates.find(door) != mDoorStates.end())
{
// if currently opening, then close, if closing, then open
mDoorStates[door] = !mDoorStates[door];
}
else
{
if (door.getRefData().getLocalRotation().rot[2] == 0)
mDoorStates[door] = 1; // open
else
mDoorStates[door] = 0; // close
}
}
}

@ -85,6 +85,9 @@ namespace MWWorld
float mFaced2Distance;
int mNumFacing;
std::map<MWWorld::Ptr, int> mDoorStates;
///< only holds doors that are currently moving. 0 means closing, 1 opening
unsigned long lastTick;
Ogre::Timer mTimer;
@ -269,6 +272,9 @@ namespace MWWorld
virtual void doPhysics(const PtrMovementList &actors, float duration);
///< Run physics simulation and modify \a world accordingly.
virtual void processDoors(float duration);
///< Run physics simulation and modify \a world accordingly.
virtual bool toggleCollisionMode();
///< Toggle collision mode for player. If disabled player object should ignore
/// collisions and gravity.
@ -368,6 +374,9 @@ namespace MWWorld
virtual void setupPlayer(bool newGame);
virtual void renderPlayer();
virtual void activateDoor(const MWWorld::Ptr& door);
///< activate (open or close) an non-teleport door
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering);
virtual int canRest();

@ -8,9 +8,6 @@
#include "esmreader.hpp"
#include "esmwriter.hpp"
#include <apps/openmw/mwworld/store.hpp>
#include <apps/openmw/mwworld/cellstore.hpp>
namespace ESM
{
@ -132,38 +129,13 @@ void Cell::load(ESMReader &esm, bool saveContext)
}
}
void Cell::load(ESMReader &esm, MWWorld::ESMStore &store)
void Cell::preLoad(ESMReader &esm) //Can't be "load" because it conflicts with function in esmtool
{
this->load(esm, false);
}
// preload moved references
while (esm.isNextSub("MVRF")) {
CellRef ref;
MovedCellRef cMRef;
getNextMVRF(esm, cMRef);
MWWorld::Store<ESM::Cell> &cStore = const_cast<MWWorld::Store<ESM::Cell>&>(store.get<ESM::Cell>());
ESM::Cell *cellAlt = const_cast<ESM::Cell*>(cStore.searchOrCreate(cMRef.mTarget[0], cMRef.mTarget[1]));
// Get regular moved reference data. Adapted from CellStore::loadRefs. Maybe we can optimize the following
// implementation when the oher implementation works as well.
getNextRef(esm, ref);
std::string lowerCase;
std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase),
(int(*)(int)) std::tolower);
// Add data required to make reference appear in the correct cell.
// We should not need to test for duplicates, as this part of the code is pre-cell merge.
mMovedRefs.push_back(cMRef);
// But there may be duplicates here!
ESM::CellRefTracker::iterator iter = std::find(cellAlt->mLeasedRefs.begin(), cellAlt->mLeasedRefs.end(), ref.mRefnum);
if (iter == cellAlt->mLeasedRefs.end())
cellAlt->mLeasedRefs.push_back(ref);
else
*iter = ref;
}
void Cell::postLoad(ESMReader &esm)
{
// Save position of the cell references and move on
mContextList.push_back(esm.getContext());
esm.skipRecord();

@ -96,7 +96,8 @@ struct Cell
CellRefTracker mLeasedRefs;
MovedCellRefTracker mMovedRefs;
void load(ESMReader &esm, MWWorld::ESMStore &store);
void preLoad(ESMReader &esm);
void postLoad(ESMReader &esm);
// This method is left in for compatibility with esmtool. Parsing moved references currently requires
// passing ESMStore, bit it does not know about this parameter, so we do it this way.

@ -509,6 +509,43 @@ namespace Physic
}
}
class ContactTestResultCallback : public btCollisionWorld::ContactResultCallback
{
public:
std::vector<std::string> mResult;
// added in bullet 2.81
// this is just a quick hack, as there does not seem to be a BULLET_VERSION macro?
#if defined(BT_COLLISION_OBJECT_WRAPPER_H)
virtual btScalar addSingleResult(btManifoldPoint& cp,
const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,
const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1)
{
const RigidBody* body = dynamic_cast<const RigidBody*>(colObj0Wrap->m_collisionObject);
if (body)
mResult.push_back(body->mName);
return 0.f;
}
#else
virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObject* col0, int partId0, int index0,
const btCollisionObject* col1, int partId1, int index1)
{
const RigidBody* body = dynamic_cast<const RigidBody*>(col0);
if (body)
mResult.push_back(body->mName);
return 0.f;
}
#endif
};
std::vector<std::string> PhysicEngine::getCollisions(const std::string& name)
{
RigidBody* body = getRigidBody(name);
ContactTestResultCallback callback;
dynamicsWorld->contactTest(body, callback);
return callback.mResult;
}
void PhysicEngine::stepSimulation(double deltaT)
{
// This seems to be needed for character controller objects

@ -298,6 +298,8 @@ namespace Physic
*/
std::vector< std::pair<float, std::string> > rayTest2(btVector3& from, btVector3& to);
std::vector<std::string> getCollisions(const std::string& name);
//event list of non player object
std::list<PhysicEvent> NPEventList;

Loading…
Cancel
Save