mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-26 18:35:20 +00:00
intersection by refnum tag + enable paging for acti,door,cont
Signed-off-by: Bret Curtis <psi29a@gmail.com>
This commit is contained in:
parent
65cd2c77aa
commit
9f0398c021
@ -14,6 +14,8 @@
|
|||||||
#include <components/resource/scenemanager.hpp>
|
#include <components/resource/scenemanager.hpp>
|
||||||
#include <components/sceneutil/optimizer.hpp>
|
#include <components/sceneutil/optimizer.hpp>
|
||||||
#include <components/sceneutil/clone.hpp>
|
#include <components/sceneutil/clone.hpp>
|
||||||
|
#include <components/sceneutil/util.hpp>
|
||||||
|
#include <components/vfs/manager.hpp>
|
||||||
|
|
||||||
#include <osgParticle/ParticleProcessor>
|
#include <osgParticle/ParticleProcessor>
|
||||||
#include <osgParticle/ParticleSystemUpdater>
|
#include <osgParticle/ParticleSystemUpdater>
|
||||||
@ -33,18 +35,16 @@
|
|||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
|
||||||
bool typeFilter(int type, bool far, bool activeGrid)
|
bool typeFilter(int type, bool far)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ESM::REC_STAT:
|
case ESM::REC_STAT:
|
||||||
return true;
|
case ESM::REC_ACTI:
|
||||||
|
|
||||||
case ESM::REC_ACTI: // TODO enable when intersectionvisitor supported
|
|
||||||
case ESM::REC_DOOR:
|
case ESM::REC_DOOR:
|
||||||
return !activeGrid;
|
return true;
|
||||||
case ESM::REC_CONT:
|
case ESM::REC_CONT:
|
||||||
return far ? false : !activeGrid;
|
return !far;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@ -321,6 +321,21 @@ namespace MWRender
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AddRefnumMarkerVisitor : public osg::NodeVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AddRefnumMarkerVisitor(const ESM::RefNum &refnum) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), mRefnum(refnum) {}
|
||||||
|
ESM::RefNum mRefnum;
|
||||||
|
virtual void apply(osg::Geometry &node)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<RefnumMarker> marker (new RefnumMarker);
|
||||||
|
marker->mRefnum = mRefnum;
|
||||||
|
if (osg::Array* array = node.getVertexArray())
|
||||||
|
marker->mNumVertices = array->getNumElements();
|
||||||
|
node.getOrCreateUserDataContainer()->addUserObject(marker);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ObjectPaging::ObjectPaging(Resource::SceneManager* sceneManager)
|
ObjectPaging::ObjectPaging(Resource::SceneManager* sceneManager)
|
||||||
: GenericResourceManager<ChunkId>(nullptr)
|
: GenericResourceManager<ChunkId>(nullptr)
|
||||||
, mSceneManager(sceneManager)
|
, mSceneManager(sceneManager)
|
||||||
@ -365,7 +380,7 @@ namespace MWRender
|
|||||||
{
|
{
|
||||||
if (std::find(cell->mMovedRefs.begin(), cell->mMovedRefs.end(), ref.mRefNum) != cell->mMovedRefs.end()) continue;
|
if (std::find(cell->mMovedRefs.begin(), cell->mMovedRefs.end(), ref.mRefNum) != cell->mMovedRefs.end()) continue;
|
||||||
int type = store.findStatic(Misc::StringUtils::lowerCase(ref.mRefID));
|
int type = store.findStatic(Misc::StringUtils::lowerCase(ref.mRefID));
|
||||||
if (!typeFilter(type,size>=2,activeGrid)) continue;
|
if (!typeFilter(type,size>=2)) continue;
|
||||||
if (deleted) { refs.erase(ref.mRefNum); continue; }
|
if (deleted) { refs.erase(ref.mRefNum); continue; }
|
||||||
refs[ref.mRefNum] = ref;
|
refs[ref.mRefNum] = ref;
|
||||||
}
|
}
|
||||||
@ -381,7 +396,7 @@ namespace MWRender
|
|||||||
bool deleted = it->second;
|
bool deleted = it->second;
|
||||||
if (deleted) { refs.erase(ref.mRefNum); continue; }
|
if (deleted) { refs.erase(ref.mRefNum); continue; }
|
||||||
int type = store.findStatic(Misc::StringUtils::lowerCase(ref.mRefID));
|
int type = store.findStatic(Misc::StringUtils::lowerCase(ref.mRefID));
|
||||||
if (!typeFilter(type,size>=2,activeGrid)) continue;
|
if (!typeFilter(type,size>=2)) continue;
|
||||||
refs[ref.mRefNum] = ref;
|
refs[ref.mRefNum] = ref;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -446,15 +461,32 @@ namespace MWRender
|
|||||||
std::string model = getModel(type, id, store);
|
std::string model = getModel(type, id, store);
|
||||||
if (model.empty()) continue;
|
if (model.empty()) continue;
|
||||||
model = "meshes/" + model;
|
model = "meshes/" + model;
|
||||||
/*
|
|
||||||
bool useAnim = type != ESM::REC_STAT;
|
bool useAnim = type != ESM::REC_STAT;
|
||||||
if (useAnim)
|
if (useAnim)
|
||||||
|
{
|
||||||
model = Misc::ResourceHelpers::correctActorModelPath(model, mSceneManager->getVFS());
|
model = Misc::ResourceHelpers::correctActorModelPath(model, mSceneManager->getVFS());
|
||||||
*/
|
if (activeGrid)
|
||||||
|
{
|
||||||
|
std::string kfname = Misc::StringUtils::lowerCase(model);
|
||||||
|
if(kfname.size() > 4 && kfname.compare(kfname.size()-4, 4, ".nif") == 0)
|
||||||
|
{
|
||||||
|
kfname.replace(kfname.size()-4, 4, ".kf");
|
||||||
|
if (mSceneManager->getVFS()->exists(kfname))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
osg::ref_ptr<const osg::Node> cnode = mSceneManager->getTemplate(model, false);
|
osg::ref_ptr<const osg::Node> cnode = mSceneManager->getTemplate(model, false);
|
||||||
|
|
||||||
if (activeGrid)
|
if (activeGrid)
|
||||||
refnumSet->mRefnums.insert(pair.first);
|
{
|
||||||
|
if (cnode->getNumChildrenRequiringUpdateTraversal() > 0 || SceneUtil::hasUserDescription(cnode, Constants::NightDayLabel) || SceneUtil::hasUserDescription(cnode, Constants::HerbalismLabel))
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
refnumSet->mRefnums.insert(pair.first);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mDisabledMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mDisabledMutex);
|
||||||
@ -472,9 +504,6 @@ namespace MWRender
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activeGrid && cnode->getNumChildrenRequiringUpdateTraversal() > 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto emplaced = nodes.emplace(cnode, InstanceList());
|
auto emplaced = nodes.emplace(cnode, InstanceList());
|
||||||
if (emplaced.second)
|
if (emplaced.second)
|
||||||
{
|
{
|
||||||
@ -537,6 +566,20 @@ namespace MWRender
|
|||||||
osg::ref_ptr<osg::Node> node = osg::clone(cnode, co);
|
osg::ref_ptr<osg::Node> node = osg::clone(cnode, co);
|
||||||
node->setUserDataContainer(nullptr);
|
node->setUserDataContainer(nullptr);
|
||||||
|
|
||||||
|
if (activeGrid)
|
||||||
|
{
|
||||||
|
if (merge)
|
||||||
|
{
|
||||||
|
AddRefnumMarkerVisitor visitor(ref.mRefNum);
|
||||||
|
node->accept(visitor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
osg::ref_ptr<RefnumMarker> marker = new RefnumMarker; marker->mRefnum = ref.mRefNum;
|
||||||
|
node->getOrCreateUserDataContainer()->addUserObject(marker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
trans->addChild(node);
|
trans->addChild(node);
|
||||||
|
|
||||||
if (merge)
|
if (merge)
|
||||||
@ -636,7 +679,7 @@ namespace MWRender
|
|||||||
|
|
||||||
bool ObjectPaging::enableObject(int type, const ESM::RefNum & refnum, const osg::Vec3f& pos, bool enabled)
|
bool ObjectPaging::enableObject(int type, const ESM::RefNum & refnum, const osg::Vec3f& pos, bool enabled)
|
||||||
{
|
{
|
||||||
if (!typeFilter(type, false, false))
|
if (!typeFilter(type, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -655,7 +698,7 @@ namespace MWRender
|
|||||||
|
|
||||||
bool ObjectPaging::blacklistObject(int type, const ESM::RefNum & refnum, const osg::Vec3f& pos)
|
bool ObjectPaging::blacklistObject(int type, const ESM::RefNum & refnum, const osg::Vec3f& pos)
|
||||||
{
|
{
|
||||||
if (!typeFilter(type, false, true))
|
if (!typeFilter(type, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -63,6 +63,16 @@ namespace MWRender
|
|||||||
SizeCache mSizeCache;
|
SizeCache mSizeCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RefnumMarker : public osg::Object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RefnumMarker() : mNumVertices(0) {}
|
||||||
|
RefnumMarker(const RefnumMarker ©, osg::CopyOp co) : mRefnum(copy.mRefnum), mNumVertices(copy.mNumVertices) {}
|
||||||
|
META_Object(MWRender, RefnumMarker)
|
||||||
|
|
||||||
|
ESM::RefNum mRefnum;
|
||||||
|
unsigned int mNumVertices;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1016,6 +1016,7 @@ namespace MWRender
|
|||||||
{
|
{
|
||||||
RenderingManager::RayResult result;
|
RenderingManager::RayResult result;
|
||||||
result.mHit = false;
|
result.mHit = false;
|
||||||
|
result.mHitRefnum.mContentFile = -1;
|
||||||
result.mRatio = 0;
|
result.mRatio = 0;
|
||||||
if (intersector->containsIntersections())
|
if (intersector->containsIntersections())
|
||||||
{
|
{
|
||||||
@ -1027,6 +1028,7 @@ namespace MWRender
|
|||||||
result.mRatio = intersection.ratio;
|
result.mRatio = intersection.ratio;
|
||||||
|
|
||||||
PtrHolder* ptrHolder = nullptr;
|
PtrHolder* ptrHolder = nullptr;
|
||||||
|
std::vector<RefnumMarker*> refnumMarkers;
|
||||||
for (osg::NodePath::const_iterator it = intersection.nodePath.begin(); it != intersection.nodePath.end(); ++it)
|
for (osg::NodePath::const_iterator it = intersection.nodePath.begin(); it != intersection.nodePath.end(); ++it)
|
||||||
{
|
{
|
||||||
osg::UserDataContainer* userDataContainer = (*it)->getUserDataContainer();
|
osg::UserDataContainer* userDataContainer = (*it)->getUserDataContainer();
|
||||||
@ -1036,11 +1038,25 @@ namespace MWRender
|
|||||||
{
|
{
|
||||||
if (PtrHolder* p = dynamic_cast<PtrHolder*>(userDataContainer->getUserObject(i)))
|
if (PtrHolder* p = dynamic_cast<PtrHolder*>(userDataContainer->getUserObject(i)))
|
||||||
ptrHolder = p;
|
ptrHolder = p;
|
||||||
|
if (RefnumMarker* r = dynamic_cast<RefnumMarker*>(userDataContainer->getUserObject(i)))
|
||||||
|
refnumMarkers.push_back(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ptrHolder)
|
if (ptrHolder)
|
||||||
result.mHitObject = ptrHolder->mPtr;
|
result.mHitObject = ptrHolder->mPtr;
|
||||||
|
|
||||||
|
unsigned int vertexCounter = 0;
|
||||||
|
for (unsigned int i=0; i<refnumMarkers.size(); ++i)
|
||||||
|
{
|
||||||
|
unsigned int intersectionIndex = intersection.indexList.empty() ? 0 : intersection.indexList[0];
|
||||||
|
if (!refnumMarkers[i]->mNumVertices || (intersectionIndex >= vertexCounter && intersectionIndex < vertexCounter + refnumMarkers[i]->mNumVertices))
|
||||||
|
{
|
||||||
|
result.mHitRefnum = refnumMarkers[i]->mRefnum;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vertexCounter += refnumMarkers[i]->mNumVertices;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -157,6 +157,7 @@ namespace MWRender
|
|||||||
osg::Vec3f mHitNormalWorld;
|
osg::Vec3f mHitNormalWorld;
|
||||||
osg::Vec3f mHitPointWorld;
|
osg::Vec3f mHitPointWorld;
|
||||||
MWWorld::Ptr mHitObject;
|
MWWorld::Ptr mHitObject;
|
||||||
|
ESM::RefNum mHitRefnum;
|
||||||
float mRatio;
|
float mRatio;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -165,28 +165,6 @@ namespace
|
|||||||
ref.load (state);
|
ref.load (state);
|
||||||
collection.mList.push_back (ref);
|
collection.mList.push_back (ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SearchByRefNumVisitor
|
|
||||||
{
|
|
||||||
MWWorld::LiveCellRefBase* mFound;
|
|
||||||
ESM::RefNum mRefNumToFind;
|
|
||||||
|
|
||||||
SearchByRefNumVisitor(const ESM::RefNum& toFind)
|
|
||||||
: mFound(nullptr)
|
|
||||||
, mRefNumToFind(toFind)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(const MWWorld::Ptr& ptr)
|
|
||||||
{
|
|
||||||
if (ptr.getCellRef().getRefNum() == mRefNumToFind)
|
|
||||||
{
|
|
||||||
mFound = ptr.getBase();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
@ -263,9 +241,7 @@ namespace MWWorld
|
|||||||
throw std::runtime_error("moveTo: can't move object from a non-loaded cell (how did you get this object anyway?)");
|
throw std::runtime_error("moveTo: can't move object from a non-loaded cell (how did you get this object anyway?)");
|
||||||
|
|
||||||
// Ensure that the object actually exists in the cell
|
// Ensure that the object actually exists in the cell
|
||||||
SearchByRefNumVisitor searchVisitor(object.getCellRef().getRefNum());
|
if (searchViaRefNum(object.getCellRef().getRefNum()).isEmpty())
|
||||||
forEach(searchVisitor);
|
|
||||||
if (!searchVisitor.mFound)
|
|
||||||
throw std::runtime_error("moveTo: object is not in this cell");
|
throw std::runtime_error("moveTo: object is not in this cell");
|
||||||
|
|
||||||
|
|
||||||
@ -942,26 +918,22 @@ namespace MWWorld
|
|||||||
movedTo.load(reader);
|
movedTo.load(reader);
|
||||||
|
|
||||||
// Search for the reference. It might no longer exist if its content file was removed.
|
// Search for the reference. It might no longer exist if its content file was removed.
|
||||||
SearchByRefNumVisitor visitor(refnum);
|
Ptr movedRef = searchViaRefNum(refnum);
|
||||||
forEachInternal(visitor);
|
if (movedRef.isEmpty())
|
||||||
|
|
||||||
if (!visitor.mFound)
|
|
||||||
{
|
{
|
||||||
Log(Debug::Warning) << "Warning: Dropping moved ref tag for " << refnum.mIndex << " (moved object no longer exists)";
|
Log(Debug::Warning) << "Warning: Dropping moved ref tag for " << refnum.mIndex << " (moved object no longer exists)";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::LiveCellRefBase* movedRef = visitor.mFound;
|
|
||||||
|
|
||||||
CellStore* otherCell = callback->getCellStore(movedTo);
|
CellStore* otherCell = callback->getCellStore(movedTo);
|
||||||
|
|
||||||
if (otherCell == nullptr)
|
if (otherCell == nullptr)
|
||||||
{
|
{
|
||||||
Log(Debug::Warning) << "Warning: Dropping moved ref tag for " << movedRef->mRef.getRefId()
|
Log(Debug::Warning) << "Warning: Dropping moved ref tag for " << movedRef.getCellRef().getRefId()
|
||||||
<< " (target cell " << movedTo.mWorldspace << " no longer exists). Reference moved back to its original location.";
|
<< " (target cell " << movedTo.mWorldspace << " no longer exists). Reference moved back to its original location.";
|
||||||
// Note by dropping tag the object will automatically re-appear in its original cell, though potentially at inapproriate coordinates.
|
// Note by dropping tag the object will automatically re-appear in its original cell, though potentially at inapproriate coordinates.
|
||||||
// Restore original coordinates:
|
// Restore original coordinates:
|
||||||
movedRef->mData.setPosition(movedRef->mRef.getPosition());
|
movedRef.getRefData().setPosition(movedRef.getCellRef().getPosition());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -972,7 +944,7 @@ namespace MWWorld
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
moveTo(MWWorld::Ptr(movedRef, this), otherCell);
|
moveTo(movedRef, otherCell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1965,6 +1965,14 @@ namespace MWWorld
|
|||||||
rayToObject = mRendering->castCameraToViewportRay(0.5f, 0.5f, maxDistance, ignorePlayer);
|
rayToObject = mRendering->castCameraToViewportRay(0.5f, 0.5f, maxDistance, ignorePlayer);
|
||||||
|
|
||||||
facedObject = rayToObject.mHitObject;
|
facedObject = rayToObject.mHitObject;
|
||||||
|
if (facedObject.isEmpty() && rayToObject.mHitRefnum.hasContentFile())
|
||||||
|
{
|
||||||
|
for (CellStore* cellstore : mWorldScene->getActiveCells())
|
||||||
|
{
|
||||||
|
facedObject = cellstore->searchViaRefNum(rayToObject.mHitRefnum);
|
||||||
|
if (!facedObject.isEmpty()) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (rayToObject.mHit)
|
if (rayToObject.mHit)
|
||||||
mDistanceToFacedObject = (rayToObject.mRatio * maxDistance) - camDist;
|
mDistanceToFacedObject = (rayToObject.mRatio * maxDistance) - camDist;
|
||||||
else
|
else
|
||||||
|
@ -1824,6 +1824,10 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
|
|||||||
lhs.dirtyBound();
|
lhs.dirtyBound();
|
||||||
lhs.dirtyDisplayList();
|
lhs.dirtyDisplayList();
|
||||||
|
|
||||||
|
if (osg::UserDataContainer* rhsUserData = rhs.getUserDataContainer())
|
||||||
|
for (unsigned int i=0; i<rhsUserData->getNumUserObjects(); ++i)
|
||||||
|
lhs.getOrCreateUserDataContainer()->addUserObject(rhsUserData->getUserObject(i));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user