forked from teamnwah/openmw-tes3coop
Trace actors onto the ground after load, when moved to a different cell by the console or on player cell change.
This commit is contained in:
parent
43cdbd033d
commit
ebaf80d539
18 changed files with 138 additions and 15 deletions
|
@ -216,6 +216,9 @@ namespace MWBase
|
|||
virtual MWWorld::Ptr getFacedObject() = 0;
|
||||
///< Return pointer to the object the player is looking at, if it is within activation range
|
||||
|
||||
virtual void adjustPosition (const MWWorld::Ptr& ptr) = 0;
|
||||
///< Adjust position after load to be on ground. Must be called after model load.
|
||||
|
||||
virtual void deleteObject (const MWWorld::Ptr& ptr) = 0;
|
||||
|
||||
virtual void moveObject (const MWWorld::Ptr& ptr, float x, float y, float z) = 0;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontalk.hpp"
|
||||
|
@ -86,6 +87,11 @@ namespace MWClass
|
|||
return ref->mBase->mId;
|
||||
}
|
||||
|
||||
void Creature::adjustPosition(const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->adjustPosition(ptr);
|
||||
}
|
||||
|
||||
void Creature::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
MWRender::Actors& actors = renderingInterface.getActors();
|
||||
|
|
|
@ -22,6 +22,8 @@ namespace MWClass
|
|||
|
||||
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const;
|
||||
|
||||
virtual void adjustPosition(const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual std::string getName (const MWWorld::Ptr& ptr) const;
|
||||
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||
/// can return an empty string.
|
||||
|
|
|
@ -160,6 +160,11 @@ namespace MWClass
|
|||
return ref->mBase->mId;
|
||||
}
|
||||
|
||||
void Npc::adjustPosition(const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->adjustPosition(ptr);
|
||||
}
|
||||
|
||||
void Npc::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
|
||||
{
|
||||
renderingInterface.getActors().insertNPC(ptr, getInventoryStore(ptr));
|
||||
|
|
|
@ -44,6 +44,8 @@ namespace MWClass
|
|||
|
||||
virtual void insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const;
|
||||
|
||||
virtual void adjustPosition(const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual std::string getName (const MWWorld::Ptr& ptr) const;
|
||||
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||
/// can return an empty string.
|
||||
|
|
|
@ -529,25 +529,28 @@ void RenderingManager::applyFog (bool underwater)
|
|||
|
||||
void RenderingManager::setAmbientMode()
|
||||
{
|
||||
switch (mAmbientMode)
|
||||
{
|
||||
switch (mAmbientMode)
|
||||
{
|
||||
case 0:
|
||||
|
||||
setAmbientColour(mAmbientColor);
|
||||
break;
|
||||
setAmbientColour(mAmbientColor);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
||||
setAmbientColour(0.7f*mAmbientColor + 0.3f*ColourValue(1,1,1));
|
||||
break;
|
||||
setAmbientColour(0.7f*mAmbientColor + 0.3f*ColourValue(1,1,1));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
setAmbientColour(ColourValue(1,1,1));
|
||||
break;
|
||||
}
|
||||
setAmbientColour(ColourValue(1,1,1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float RenderingManager::getTerrainHeightAt(Ogre::Vector3 worldPos)
|
||||
{
|
||||
return mTerrainManager->getTerrainHeightAt(worldPos);
|
||||
}
|
||||
|
||||
|
||||
void RenderingManager::configureAmbient(MWWorld::Ptr::CellStore &mCell)
|
||||
{
|
||||
mAmbientColor.setAsABGR (mCell.mCell->mAmbi.mAmbient);
|
||||
|
|
|
@ -158,6 +158,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList
|
|||
|
||||
void getTriangleBatchCount(unsigned int &triangles, unsigned int &batches);
|
||||
|
||||
float getTerrainHeightAt (Ogre::Vector3 worldPos);
|
||||
|
||||
void setGlare(bool glare);
|
||||
void skyEnable ();
|
||||
void skyDisable ();
|
||||
|
|
|
@ -71,6 +71,17 @@ namespace MWRender
|
|||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
||||
float TerrainManager::getTerrainHeightAt(Vector3 worldPos)
|
||||
{
|
||||
Ogre::Terrain* terrain = NULL;
|
||||
float height = mTerrainGroup.getHeightAtWorldPosition(worldPos, &terrain);
|
||||
if (terrain == NULL)
|
||||
return std::numeric_limits<int>().min();
|
||||
return height;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
||||
TerrainManager::~TerrainManager()
|
||||
{
|
||||
OGRE_DELETE mTerrainGlobals;
|
||||
|
|
|
@ -40,6 +40,9 @@ namespace MWRender{
|
|||
|
||||
void cellAdded(MWWorld::CellStore* store);
|
||||
void cellRemoved(MWWorld::CellStore* store);
|
||||
|
||||
float getTerrainHeightAt (Ogre::Vector3 worldPos);
|
||||
|
||||
private:
|
||||
Ogre::TerrainGlobalOptions* mTerrainGlobals;
|
||||
Ogre::TerrainGroup mTerrainGroup;
|
||||
|
|
|
@ -303,6 +303,8 @@ namespace MWScript
|
|||
zRot = zRot/60.;
|
||||
}
|
||||
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,zRot);
|
||||
|
||||
MWBase::Environment::get().getWorld()->adjustPosition(ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -341,6 +343,7 @@ namespace MWScript
|
|||
zRot = zRot/60.;
|
||||
}
|
||||
MWBase::Environment::get().getWorld()->rotateObject(ptr,ax,ay,zRot);
|
||||
MWBase::Environment::get().getWorld()->adjustPosition(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -259,6 +259,10 @@ namespace MWWorld
|
|||
throw std::runtime_error ("class can't be enchanted");
|
||||
}
|
||||
|
||||
void Class::adjustPosition(const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
}
|
||||
|
||||
MWWorld::Ptr
|
||||
Class::copyToCellImpl(const Ptr &ptr, CellStore &cell) const
|
||||
{
|
||||
|
|
|
@ -81,6 +81,9 @@ namespace MWWorld
|
|||
///< \return name (the one that is to be presented to the user; not the internal one);
|
||||
/// can return an empty string.
|
||||
|
||||
virtual void adjustPosition(const MWWorld::Ptr& ptr) const;
|
||||
///< Adjust position to stand on ground. Must be called post model load
|
||||
|
||||
virtual MWMechanics::CreatureStats& getCreatureStats (const Ptr& ptr) const;
|
||||
///< Return creature stats or throw an exception, if class does not have creature stats
|
||||
/// (default implementation: throw an exceoption)
|
||||
|
|
|
@ -88,6 +88,50 @@ namespace MWWorld
|
|||
}
|
||||
|
||||
public:
|
||||
static Ogre::Vector3 traceDown(const MWWorld::Ptr &ptr, OEngine::Physic::PhysicEngine *engine)
|
||||
{
|
||||
const ESM::Position &refpos = ptr.getRefData().getPosition();
|
||||
Ogre::Vector3 position(refpos.pos);
|
||||
|
||||
bool hit=false;
|
||||
bool isInterior = !ptr.getCell()->isExterior();
|
||||
|
||||
OEngine::Physic::PhysicActor *physicActor = engine->getCharacter(ptr.getRefData().getHandle());
|
||||
if (!physicActor)
|
||||
return position;
|
||||
|
||||
bool wasCollisionMode = physicActor->getCollisionMode();
|
||||
|
||||
physicActor->enableCollisions(false);
|
||||
|
||||
Ogre::Vector3 halfExtents = physicActor->getHalfExtents();// + Vector3(1,1,1);
|
||||
|
||||
Ogre::Vector3 newPosition = position;
|
||||
|
||||
traceResults trace; //no initialization needed
|
||||
|
||||
int maxHeight = 400.f;
|
||||
int steps = 100;
|
||||
for (int i=0; i<steps; ++i)
|
||||
{
|
||||
newtrace(&trace, newPosition, newPosition-Ogre::Vector3(0,0,maxHeight / steps), halfExtents, isInterior, engine);
|
||||
if(trace.fraction < 1.0f)
|
||||
hit = true;
|
||||
newPosition = trace.endpos;
|
||||
}
|
||||
|
||||
newPosition = trace.endpos;
|
||||
|
||||
physicActor->setOnGround(hit);
|
||||
physicActor->enableCollisions(wasCollisionMode);
|
||||
|
||||
if (hit)
|
||||
return newPosition;
|
||||
else
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
static Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time,
|
||||
bool gravity, OEngine::Physic::PhysicEngine *engine)
|
||||
{
|
||||
|
@ -318,7 +362,7 @@ namespace MWWorld
|
|||
btVector3 btTo = btVector3(to.x, to.y, to.z);
|
||||
|
||||
std::pair<std::string, float> test = mEngine->rayTest(btFrom, btTo);
|
||||
if (test.first == "") {
|
||||
if (test.second == -1) {
|
||||
return std::make_pair(false, Ogre::Vector3());
|
||||
}
|
||||
return std::make_pair(true, ray.getPoint(len * test.second));
|
||||
|
@ -351,6 +395,10 @@ namespace MWWorld
|
|||
return MovementSolver::move(ptr, movement, time, gravity, mEngine);
|
||||
}
|
||||
|
||||
Ogre::Vector3 PhysicsSystem::traceDown(const MWWorld::Ptr &ptr)
|
||||
{
|
||||
return MovementSolver::traceDown(ptr, mEngine);
|
||||
}
|
||||
|
||||
void PhysicsSystem::addHeightField (float* heights,
|
||||
int x, int y, float yoffset,
|
||||
|
|
|
@ -51,6 +51,7 @@ namespace MWWorld
|
|||
bool toggleCollisionMode();
|
||||
|
||||
Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time, bool gravity);
|
||||
Ogre::Vector3 traceDown(const MWWorld::Ptr &ptr);
|
||||
|
||||
std::pair<float, std::string> getFacedHandle (MWWorld::World& world, float queryDistance);
|
||||
std::vector < std::pair <float, std::string> > getFacedHandles (float queryDistance);
|
||||
|
|
|
@ -51,6 +51,7 @@ namespace
|
|||
class_.insertObject(ptr, physics);
|
||||
MWBase::Environment::get().getWorld()->rotateObject(ptr, 0, 0, 0, true);
|
||||
MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().mScale);
|
||||
class_.adjustPosition(ptr);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
@ -99,7 +100,6 @@ namespace MWWorld
|
|||
}
|
||||
|
||||
mRendering.removeCell(*iter);
|
||||
//mPhysics->removeObject("Unnamed_43");
|
||||
|
||||
MWBase::Environment::get().getWorld()->getLocalScripts().clearCell (*iter);
|
||||
MWBase::Environment::get().getMechanicsManager()->drop (*iter);
|
||||
|
@ -165,6 +165,8 @@ namespace MWWorld
|
|||
float y = Ogre::Radian(pos.rot[1]).valueDegrees();
|
||||
float z = Ogre::Radian(pos.rot[2]).valueDegrees();
|
||||
world->rotateObject(player, x, y, z);
|
||||
|
||||
world->adjustPosition(player);
|
||||
}
|
||||
|
||||
MWBase::MechanicsManager *mechMgr =
|
||||
|
@ -355,6 +357,8 @@ namespace MWWorld
|
|||
float y = Ogre::Radian(position.rot[1]).valueDegrees();
|
||||
float z = Ogre::Radian(position.rot[2]).valueDegrees();
|
||||
world->rotateObject(world->getPlayer().getPlayer(), x, y, z);
|
||||
|
||||
world->adjustPosition(world->getPlayer().getPlayer());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -709,6 +709,7 @@ namespace MWWorld
|
|||
pos.pos[0] = x;
|
||||
pos.pos[1] = y;
|
||||
pos.pos[2] = z;
|
||||
|
||||
Ogre::Vector3 vec(x, y, z);
|
||||
|
||||
CellStore *currCell = ptr.getCell();
|
||||
|
@ -822,6 +823,24 @@ namespace MWWorld
|
|||
}
|
||||
}
|
||||
|
||||
void World::adjustPosition(const Ptr &ptr)
|
||||
{
|
||||
Ogre::Vector3 pos (ptr.getRefData().getPosition().pos[0], ptr.getRefData().getPosition().pos[1], ptr.getRefData().getPosition().pos[2]);
|
||||
|
||||
if (!isFlying(ptr))
|
||||
{
|
||||
Ogre::Vector3 traced = mPhysics->traceDown(ptr);
|
||||
if (traced.z < pos.z)
|
||||
pos.z = traced.z;
|
||||
}
|
||||
|
||||
float terrainHeight = mRendering->getTerrainHeightAt(pos);
|
||||
if (pos.z < terrainHeight)
|
||||
pos.z = terrainHeight;
|
||||
|
||||
moveObject(ptr, pos.x, pos.y, pos.z);
|
||||
}
|
||||
|
||||
void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust)
|
||||
{
|
||||
rotateObjectImp(ptr, Ogre::Vector3(Ogre::Degree(x).valueRadians(),
|
||||
|
|
|
@ -188,6 +188,9 @@ namespace MWWorld
|
|||
virtual Ptr searchPtrViaHandle (const std::string& handle);
|
||||
///< Return a pointer to a liveCellRef with the given Ogre handle or Ptr() if not found
|
||||
|
||||
virtual void adjustPosition (const Ptr& ptr);
|
||||
///< Adjust position after load to be on ground. Must be called after model load.
|
||||
|
||||
virtual void enable (const Ptr& ptr);
|
||||
|
||||
virtual void disable (const Ptr& ptr);
|
||||
|
|
|
@ -323,7 +323,8 @@ namespace Physic
|
|||
|
||||
mHeightFieldMap [name] = hf;
|
||||
|
||||
dynamicsWorld->addRigidBody(body,CollisionType_World,CollisionType_World|CollisionType_ActorInternal|CollisionType_ActorExternal);
|
||||
dynamicsWorld->addRigidBody(body,CollisionType_World|CollisionType_Raycasting,
|
||||
CollisionType_World|CollisionType_ActorInternal|CollisionType_ActorExternal|CollisionType_Raycasting);
|
||||
}
|
||||
|
||||
void PhysicEngine::removeHeightField(int x, int y)
|
||||
|
|
Loading…
Reference in a new issue