mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 03:53:54 +00:00
Fix triggering changed flag for all references when cell is visited
The InsertFunctor for cells was calling localRotateObject() for all references which set the mChanged flag in RefData to true. Also clean up RefData interface slightly.
This commit is contained in:
parent
b20f8cc04f
commit
395f98e476
16 changed files with 122 additions and 68 deletions
|
@ -837,8 +837,7 @@ namespace MWClass
|
|||
ptr.getRefData().setCount(1);
|
||||
|
||||
// Reset to original position
|
||||
ESM::Position& pos = ptr.getRefData().getPosition();
|
||||
pos = ptr.getCellRef().getPosition();
|
||||
ptr.getRefData().setPosition(ptr.getCellRef().getPosition());
|
||||
|
||||
ptr.getRefData().setCustomData(NULL);
|
||||
}
|
||||
|
|
|
@ -1325,8 +1325,7 @@ namespace MWClass
|
|||
ptr.getRefData().setCount(1);
|
||||
|
||||
// Reset to original position
|
||||
ESM::Position& pos = ptr.getRefData().getPosition();
|
||||
pos = ptr.getCellRef().getPosition();
|
||||
ptr.getRefData().setPosition(ptr.getCellRef().getPosition());
|
||||
|
||||
ptr.getRefData().setCustomData(NULL);
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ bool AiSequence::canAddTarget(const ESM::Position& actorPos, float distToTarget)
|
|||
else
|
||||
{
|
||||
// add new target only if current target (player) is farther
|
||||
ESM::Position &targetPos = combat->getTarget().getRefData().getPosition();
|
||||
const ESM::Position &targetPos = combat->getTarget().getRefData().getPosition();
|
||||
|
||||
float distToCurrTarget = (Ogre::Vector3(targetPos.pos) - Ogre::Vector3(actorPos.pos)).length();
|
||||
return (distToCurrTarget > distToTarget);
|
||||
|
@ -153,7 +153,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor,float duration)
|
|||
}
|
||||
else
|
||||
{
|
||||
ESM::Position &targetPos = target.getRefData().getPosition();
|
||||
const ESM::Position &targetPos = target.getRefData().getPosition();
|
||||
|
||||
float distTo = (Ogre::Vector3(targetPos.pos) - vActorPos).length();
|
||||
if (distTo < nearestDist)
|
||||
|
|
|
@ -100,6 +100,9 @@ namespace MWMechanics
|
|||
if(!cell)
|
||||
return false;
|
||||
|
||||
if(mIsGraphConstructed)
|
||||
return true;
|
||||
|
||||
mCell = cell;
|
||||
mIsExterior = cell->isExterior();
|
||||
mPathgrid = MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*cell);
|
||||
|
@ -107,8 +110,6 @@ namespace MWMechanics
|
|||
if(!mPathgrid)
|
||||
return false;
|
||||
|
||||
if(mIsGraphConstructed)
|
||||
return true;
|
||||
|
||||
mGraph.resize(mPathgrid->mPoints.size());
|
||||
for(int i = 0; i < static_cast<int> (mPathgrid->mEdges.size()); i++)
|
||||
|
|
|
@ -165,7 +165,7 @@ void RippleSimulation::addImpulses()
|
|||
// for non-player actors this is done in updateObjectCell
|
||||
it->mPtr = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
||||
}
|
||||
float* _currentPos = it->mPtr.getRefData().getPosition().pos;
|
||||
const float* _currentPos = it->mPtr.getRefData().getPosition().pos;
|
||||
Ogre::Vector3 currentPos (_currentPos[0], _currentPos[1], _currentPos[2]);
|
||||
|
||||
if ( (currentPos - it->mLastEmitPosition).length() > 2
|
||||
|
|
|
@ -578,7 +578,7 @@ namespace MWScript
|
|||
Interpreter::Type_Float rotation = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
|
||||
runtime.pop();
|
||||
|
||||
float *objRot = ptr.getRefData().getPosition().rot;
|
||||
const float *objRot = ptr.getRefData().getPosition().rot;
|
||||
|
||||
float ax = Ogre::Radian(objRot[0]).valueDegrees();
|
||||
float ay = Ogre::Radian(objRot[1]).valueDegrees();
|
||||
|
@ -613,9 +613,12 @@ namespace MWScript
|
|||
if (!ptr.isInCell())
|
||||
return;
|
||||
|
||||
ptr.getRefData().getLocalRotation().rot[0] = 0;
|
||||
ptr.getRefData().getLocalRotation().rot[1] = 0;
|
||||
ptr.getRefData().getLocalRotation().rot[2] = 0;
|
||||
MWWorld::LocalRotation rot;
|
||||
rot.rot[0] = 0;
|
||||
rot.rot[1] = 0;
|
||||
rot.rot[2] = 0;
|
||||
ptr.getRefData().setLocalRotation(rot);
|
||||
|
||||
MWBase::Environment::get().getWorld()->rotateObject(ptr, 0,0,0,true);
|
||||
MWBase::Environment::get().getWorld()->moveObject(ptr, ptr.getCellRef().getPosition().pos[0],
|
||||
ptr.getCellRef().getPosition().pos[1], ptr.getCellRef().getPosition().pos[2]);
|
||||
|
@ -678,7 +681,7 @@ namespace MWScript
|
|||
Interpreter::Type_Float movement = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
|
||||
runtime.pop();
|
||||
|
||||
float *objPos = ptr.getRefData().getPosition().pos;
|
||||
const float *objPos = ptr.getRefData().getPosition().pos;
|
||||
|
||||
if (axis == "x")
|
||||
{
|
||||
|
|
|
@ -42,7 +42,8 @@ namespace MWWorld
|
|||
float getScale() const;
|
||||
void setScale(float scale);
|
||||
|
||||
// Position and rotation of this object within the cell
|
||||
// The *original* position and rotation as it was given in the Construction Set.
|
||||
// Current position and rotation of the object is stored in RefData.
|
||||
ESM::Position getPosition() const;
|
||||
void setPosition (const ESM::Position& position);
|
||||
|
||||
|
|
|
@ -410,6 +410,9 @@ namespace MWWorld
|
|||
loadRefs (store, esm);
|
||||
|
||||
mState = State_Loaded;
|
||||
|
||||
// TODO: the pathgrid graph only needs to be loaded for active cells, so move this somewhere else.
|
||||
// In a simple test, loading the graph for all cells in MW + expansions took 200 ms
|
||||
mPathgridGraph.load(mCell);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -366,7 +366,7 @@ namespace MWWorld
|
|||
Class::copyToCell(const Ptr &ptr, CellStore &cell, const ESM::Position &pos) const
|
||||
{
|
||||
Ptr newPtr = copyToCell(ptr, cell);
|
||||
newPtr.getRefData().getPosition() = pos;
|
||||
newPtr.getRefData().setPosition(pos);
|
||||
|
||||
return newPtr;
|
||||
}
|
||||
|
|
|
@ -44,8 +44,9 @@ namespace MWWorld
|
|||
cellRef.mRefID = "player";
|
||||
mPlayer = LiveCellRef<ESM::NPC>(cellRef, player);
|
||||
|
||||
float* playerPos = mPlayer.mData.getPosition().pos;
|
||||
playerPos[0] = playerPos[1] = playerPos[2] = 0;
|
||||
ESM::Position playerPos = mPlayer.mData.getPosition();
|
||||
playerPos.pos[0] = playerPos.pos[1] = playerPos.pos[2] = 0;
|
||||
mPlayer.mData.setPosition(playerPos);
|
||||
}
|
||||
|
||||
void Player::set(const ESM::NPC *player)
|
||||
|
|
|
@ -188,15 +188,25 @@ namespace MWWorld
|
|||
mEnabled = false;
|
||||
}
|
||||
|
||||
ESM::Position& RefData::getPosition()
|
||||
void RefData::setPosition(const ESM::Position& pos)
|
||||
{
|
||||
mChanged = true;
|
||||
mPosition = pos;
|
||||
}
|
||||
|
||||
const ESM::Position& RefData::getPosition()
|
||||
{
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
LocalRotation& RefData::getLocalRotation()
|
||||
void RefData::setLocalRotation(const LocalRotation& rot)
|
||||
{
|
||||
mChanged = true;
|
||||
mLocalRotation = rot;
|
||||
}
|
||||
|
||||
const LocalRotation& RefData::getLocalRotation()
|
||||
{
|
||||
return mLocalRotation;
|
||||
}
|
||||
|
||||
|
|
|
@ -100,9 +100,11 @@ namespace MWWorld
|
|||
|
||||
void disable();
|
||||
|
||||
ESM::Position& getPosition();
|
||||
void setPosition (const ESM::Position& pos);
|
||||
const ESM::Position& getPosition();
|
||||
|
||||
LocalRotation& getLocalRotation();
|
||||
void setLocalRotation (const LocalRotation& rotation);
|
||||
const LocalRotation& getLocalRotation();
|
||||
|
||||
void setCustomData (CustomData *data);
|
||||
///< Set custom data (potentially replacing old custom data). The ownership of \æ data is
|
||||
|
|
|
@ -22,6 +22,30 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
void updateObjectLocalRotation (const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics,
|
||||
MWRender::RenderingManager& rendering)
|
||||
{
|
||||
if (ptr.getRefData().getBaseNode() != NULL)
|
||||
{
|
||||
Ogre::Quaternion worldRotQuat(Ogre::Radian(ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z);
|
||||
if (!ptr.getClass().isActor())
|
||||
worldRotQuat = Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X)*
|
||||
Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[1]), Ogre::Vector3::NEGATIVE_UNIT_Y)* worldRotQuat;
|
||||
|
||||
float x = ptr.getRefData().getLocalRotation().rot[0];
|
||||
float y = ptr.getRefData().getLocalRotation().rot[1];
|
||||
float z = ptr.getRefData().getLocalRotation().rot[2];
|
||||
|
||||
Ogre::Quaternion rot(Ogre::Radian(z), Ogre::Vector3::NEGATIVE_UNIT_Z);
|
||||
if (!ptr.getClass().isActor())
|
||||
rot = Ogre::Quaternion(Ogre::Radian(x), Ogre::Vector3::NEGATIVE_UNIT_X)*
|
||||
Ogre::Quaternion(Ogre::Radian(y), Ogre::Vector3::NEGATIVE_UNIT_Y)*rot;
|
||||
|
||||
ptr.getRefData().getBaseNode()->setOrientation(worldRotQuat*rot);
|
||||
physics.rotateObject(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
struct InsertFunctor
|
||||
{
|
||||
MWWorld::CellStore& mCell;
|
||||
|
@ -60,11 +84,7 @@ namespace
|
|||
mRendering.addObject (ptr);
|
||||
ptr.getClass().insertObject (ptr, mPhysics);
|
||||
|
||||
float ax = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[0]).valueDegrees();
|
||||
float ay = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[1]).valueDegrees();
|
||||
float az = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[2]).valueDegrees();
|
||||
MWBase::Environment::get().getWorld()->localRotateObject (ptr, ax, ay, az);
|
||||
|
||||
updateObjectLocalRotation(ptr, mPhysics, mRendering);
|
||||
MWBase::Environment::get().getWorld()->scaleObject (ptr, ptr.getCellRef().getScale());
|
||||
ptr.getClass().adjustPosition (ptr);
|
||||
}
|
||||
|
@ -85,6 +105,20 @@ namespace
|
|||
namespace MWWorld
|
||||
{
|
||||
|
||||
void Scene::updateObjectLocalRotation (const Ptr& ptr)
|
||||
{
|
||||
::updateObjectLocalRotation(ptr, *mPhysics, mRendering);
|
||||
}
|
||||
|
||||
void Scene::updateObjectRotation (const Ptr& ptr)
|
||||
{
|
||||
if(ptr.getRefData().getBaseNode() != 0)
|
||||
{
|
||||
mRendering.rotateObject(ptr);
|
||||
mPhysics->rotateObject(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void Scene::update (float duration, bool paused)
|
||||
{
|
||||
if (mNeedMapUpdate)
|
||||
|
|
|
@ -103,6 +103,10 @@ namespace MWWorld
|
|||
void removeObjectFromScene (const Ptr& ptr);
|
||||
///< Remove an object from the scene, but not from the world model.
|
||||
|
||||
void updateObjectLocalRotation (const Ptr& ptr);
|
||||
|
||||
void updateObjectRotation (const Ptr& ptr);
|
||||
|
||||
bool isCellActive(const CellStore &cell);
|
||||
|
||||
Ptr searchPtrViaHandle (const std::string& handle);
|
||||
|
|
|
@ -957,12 +957,14 @@ namespace MWWorld
|
|||
|
||||
void World::moveObject(const Ptr &ptr, CellStore* newCell, float x, float y, float z)
|
||||
{
|
||||
ESM::Position &pos = ptr.getRefData().getPosition();
|
||||
ESM::Position pos = ptr.getRefData().getPosition();
|
||||
|
||||
pos.pos[0] = x;
|
||||
pos.pos[1] = y;
|
||||
pos.pos[2] = z;
|
||||
|
||||
ptr.getRefData().setPosition(pos);
|
||||
|
||||
Ogre::Vector3 vec(x, y, z);
|
||||
|
||||
CellStore *currCell = ptr.isInCell() ? ptr.getCell() : NULL;
|
||||
|
@ -1068,7 +1070,8 @@ namespace MWWorld
|
|||
const float two_pi = Ogre::Math::TWO_PI;
|
||||
const float pi = Ogre::Math::PI;
|
||||
|
||||
float *objRot = ptr.getRefData().getPosition().rot;
|
||||
ESM::Position pos = ptr.getRefData().getPosition();
|
||||
float *objRot = pos.rot;
|
||||
if(adjust)
|
||||
{
|
||||
objRot[0] += rot.x;
|
||||
|
@ -1105,43 +1108,33 @@ namespace MWWorld
|
|||
while(objRot[2] < -pi) objRot[2] += two_pi;
|
||||
while(objRot[2] > pi) objRot[2] -= two_pi;
|
||||
|
||||
if(ptr.getRefData().getBaseNode() != 0)
|
||||
{
|
||||
mRendering->rotateObject(ptr);
|
||||
mPhysics->rotateObject(ptr);
|
||||
}
|
||||
ptr.getRefData().setPosition(pos);
|
||||
|
||||
mWorldScene->updateObjectRotation(ptr);
|
||||
}
|
||||
|
||||
void World::localRotateObject (const Ptr& ptr, float x, float y, float z)
|
||||
{
|
||||
if (ptr.getRefData().getBaseNode() != 0) {
|
||||
if (ptr.getRefData().getBaseNode() != 0)
|
||||
{
|
||||
LocalRotation rot = ptr.getRefData().getLocalRotation();
|
||||
rot.rot[0]=Ogre::Degree(x).valueRadians();
|
||||
rot.rot[1]=Ogre::Degree(y).valueRadians();
|
||||
rot.rot[2]=Ogre::Degree(z).valueRadians();
|
||||
|
||||
ptr.getRefData().getLocalRotation().rot[0]=Ogre::Degree(x).valueRadians();
|
||||
ptr.getRefData().getLocalRotation().rot[1]=Ogre::Degree(y).valueRadians();
|
||||
ptr.getRefData().getLocalRotation().rot[2]=Ogre::Degree(z).valueRadians();
|
||||
wrap(rot.rot[0]);
|
||||
wrap(rot.rot[1]);
|
||||
wrap(rot.rot[2]);
|
||||
|
||||
wrap(ptr.getRefData().getLocalRotation().rot[0]);
|
||||
wrap(ptr.getRefData().getLocalRotation().rot[1]);
|
||||
wrap(ptr.getRefData().getLocalRotation().rot[2]);
|
||||
ptr.getRefData().setLocalRotation(rot);
|
||||
|
||||
Ogre::Quaternion worldRotQuat(Ogre::Radian(ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z);
|
||||
if (!ptr.getClass().isActor())
|
||||
worldRotQuat = Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X)*
|
||||
Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[1]), Ogre::Vector3::NEGATIVE_UNIT_Y)* worldRotQuat;
|
||||
|
||||
Ogre::Quaternion rot(Ogre::Degree(z), Ogre::Vector3::NEGATIVE_UNIT_Z);
|
||||
if (!ptr.getClass().isActor())
|
||||
rot = Ogre::Quaternion(Ogre::Degree(x), Ogre::Vector3::NEGATIVE_UNIT_X)*
|
||||
Ogre::Quaternion(Ogre::Degree(y), Ogre::Vector3::NEGATIVE_UNIT_Y)*rot;
|
||||
|
||||
ptr.getRefData().getBaseNode()->setOrientation(worldRotQuat*rot);
|
||||
mPhysics->rotateObject(ptr);
|
||||
mWorldScene->updateObjectLocalRotation(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void World::adjustPosition(const Ptr &ptr)
|
||||
{
|
||||
Ogre::Vector3 pos (ptr.getRefData().getPosition().pos);
|
||||
ESM::Position pos (ptr.getRefData().getPosition());
|
||||
|
||||
if(!ptr.getRefData().getBaseNode())
|
||||
{
|
||||
|
@ -1149,21 +1142,23 @@ namespace MWWorld
|
|||
return;
|
||||
}
|
||||
|
||||
float terrainHeight = mRendering->getTerrainHeightAt(pos);
|
||||
float terrainHeight = mRendering->getTerrainHeightAt(Ogre::Vector3(pos.pos));
|
||||
|
||||
if (pos.z < terrainHeight)
|
||||
pos.z = terrainHeight;
|
||||
if (pos.pos[2] < terrainHeight)
|
||||
pos.pos[2] = terrainHeight;
|
||||
|
||||
ptr.getRefData().getPosition().pos[2] = pos.z + 20; // place slightly above. will snap down to ground with code below
|
||||
pos.pos[2] += 20; // place slightly above. will snap down to ground with code below
|
||||
|
||||
ptr.getRefData().setPosition(pos);
|
||||
|
||||
if (!isFlying(ptr))
|
||||
{
|
||||
Ogre::Vector3 traced = mPhysics->traceDown(ptr);
|
||||
if (traced.z < pos.z)
|
||||
pos.z = traced.z;
|
||||
if (traced.z < pos.pos[2])
|
||||
pos.pos[2] = traced.z;
|
||||
}
|
||||
|
||||
moveObject(ptr, ptr.getCell(), pos.x, pos.y, pos.z);
|
||||
moveObject(ptr, ptr.getCell(), pos.pos[0], pos.pos[1], pos.pos[2]);
|
||||
}
|
||||
|
||||
void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust)
|
||||
|
@ -1429,7 +1424,7 @@ namespace MWWorld
|
|||
// cast a ray from player to sun to detect if the sun is visible
|
||||
// this is temporary until we find a better place to put this code
|
||||
// currently its here because we need to access the physics system
|
||||
float* p = mPlayer->getPlayer().getRefData().getPosition().pos;
|
||||
const float* p = mPlayer->getPlayer().getRefData().getPosition().pos;
|
||||
Vector3 sun = mRendering->getSkyManager()->getRealSunPos();
|
||||
mRendering->getSkyManager()->setGlare(!mPhysics->castRay(Ogre::Vector3(p[0], p[1], p[2]), sun));
|
||||
}
|
||||
|
@ -1683,10 +1678,11 @@ namespace MWWorld
|
|||
object.getClass().copyToCell(object, *cell, pos);
|
||||
|
||||
// Reset some position values that could be uninitialized if this item came from a container
|
||||
LocalRotation& localRotation = dropped.getRefData().getLocalRotation();
|
||||
LocalRotation localRotation;
|
||||
localRotation.rot[0] = 0;
|
||||
localRotation.rot[1] = 0;
|
||||
localRotation.rot[2] = 0;
|
||||
dropped.getRefData().setLocalRotation(localRotation);
|
||||
dropped.getCellRef().setPosition(pos);
|
||||
|
||||
if (mWorldScene->isCellActive(*cell)) {
|
||||
|
@ -1785,7 +1781,7 @@ namespace MWWorld
|
|||
|
||||
bool World::isSubmerged(const MWWorld::Ptr &object) const
|
||||
{
|
||||
float *fpos = object.getRefData().getPosition().pos;
|
||||
const float *fpos = object.getRefData().getPosition().pos;
|
||||
Ogre::Vector3 pos(fpos[0], fpos[1], fpos[2]);
|
||||
|
||||
const OEngine::Physic::PhysicActor *actor = mPhysEngine->getCharacter(object.getRefData().getHandle());
|
||||
|
@ -1798,7 +1794,7 @@ namespace MWWorld
|
|||
World::isSwimming(const MWWorld::Ptr &object) const
|
||||
{
|
||||
/// \todo add check ifActor() - only actors can swim
|
||||
float *fpos = object.getRefData().getPosition().pos;
|
||||
const float *fpos = object.getRefData().getPosition().pos;
|
||||
Ogre::Vector3 pos(fpos[0], fpos[1], fpos[2]);
|
||||
|
||||
/// \fixme 3/4ths submerged?
|
||||
|
@ -2031,9 +2027,9 @@ namespace MWWorld
|
|||
if (!targetNpc.getRefData().isEnabled() || !npc.getRefData().isEnabled())
|
||||
return false; // cannot get LOS unless both NPC's are enabled
|
||||
Ogre::Vector3 halfExt1 = mPhysEngine->getCharacter(npc.getRefData().getHandle())->getHalfExtents();
|
||||
float* pos1 = npc.getRefData().getPosition().pos;
|
||||
const float* pos1 = npc.getRefData().getPosition().pos;
|
||||
Ogre::Vector3 halfExt2 = mPhysEngine->getCharacter(targetNpc.getRefData().getHandle())->getHalfExtents();
|
||||
float* pos2 = targetNpc.getRefData().getPosition().pos;
|
||||
const float* pos2 = targetNpc.getRefData().getPosition().pos;
|
||||
|
||||
btVector3 from(pos1[0],pos1[1],pos1[2]+halfExt1.z);
|
||||
btVector3 to(pos2[0],pos2[1],pos2[2]+halfExt2.z);
|
||||
|
|
|
@ -336,10 +336,11 @@ namespace MWWorld
|
|||
|
||||
virtual void scaleObject (const Ptr& ptr, float scale);
|
||||
|
||||
/// Rotates object, uses degrees
|
||||
/// World rotates object, uses degrees
|
||||
/// \param adjust indicates rotation should be set or adjusted
|
||||
virtual void rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust = false);
|
||||
|
||||
/// Local rotates object, uses degrees
|
||||
virtual void localRotateObject (const Ptr& ptr, float x, float y, float z);
|
||||
|
||||
virtual MWWorld::Ptr safePlaceObject(const MWWorld::Ptr& ptr, MWWorld::CellStore* cell, ESM::Position pos);
|
||||
|
|
Loading…
Reference in a new issue