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.
deque
scrawl 11 years ago
parent b20f8cc04f
commit 395f98e476

@ -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) {
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(ptr.getRefData().getLocalRotation().rot[0]);
wrap(ptr.getRefData().getLocalRotation().rot[1]);
wrap(ptr.getRefData().getLocalRotation().rot[2]);
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();
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;
wrap(rot.rot[0]);
wrap(rot.rot[1]);
wrap(rot.rot[2]);
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().setLocalRotation(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.pos[2] < terrainHeight)
pos.pos[2] = terrainHeight;
if (pos.z < terrainHeight)
pos.z = terrainHeight;
pos.pos[2] += 20; // place slightly above. will snap down to ground with code below
ptr.getRefData().getPosition().pos[2] = pos.z + 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…
Cancel
Save