1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-25 15:35:23 +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:
bzzt lost a hitlab login 2020-05-11 13:37:00 +00:00 committed by Bret Curtis
parent 65cd2c77aa
commit 9f0398c021
7 changed files with 104 additions and 50 deletions

View File

@ -14,6 +14,8 @@
#include <components/resource/scenemanager.hpp>
#include <components/sceneutil/optimizer.hpp>
#include <components/sceneutil/clone.hpp>
#include <components/sceneutil/util.hpp>
#include <components/vfs/manager.hpp>
#include <osgParticle/ParticleProcessor>
#include <osgParticle/ParticleSystemUpdater>
@ -33,18 +35,16 @@
namespace MWRender
{
bool typeFilter(int type, bool far, bool activeGrid)
bool typeFilter(int type, bool far)
{
switch (type)
{
case ESM::REC_STAT:
return true;
case ESM::REC_ACTI: // TODO enable when intersectionvisitor supported
case ESM::REC_ACTI:
case ESM::REC_DOOR:
return !activeGrid;
return true;
case ESM::REC_CONT:
return far ? false : !activeGrid;
return !far;
default:
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)
: GenericResourceManager<ChunkId>(nullptr)
, mSceneManager(sceneManager)
@ -365,7 +380,7 @@ namespace MWRender
{
if (std::find(cell->mMovedRefs.begin(), cell->mMovedRefs.end(), ref.mRefNum) != cell->mMovedRefs.end()) continue;
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; }
refs[ref.mRefNum] = ref;
}
@ -381,7 +396,7 @@ namespace MWRender
bool deleted = it->second;
if (deleted) { refs.erase(ref.mRefNum); continue; }
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;
}
}
@ -446,15 +461,32 @@ namespace MWRender
std::string model = getModel(type, id, store);
if (model.empty()) continue;
model = "meshes/" + model;
/*
bool useAnim = type != ESM::REC_STAT;
if (useAnim)
{
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);
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);
@ -472,9 +504,6 @@ namespace MWRender
continue;
}
if (activeGrid && cnode->getNumChildrenRequiringUpdateTraversal() > 0)
continue;
auto emplaced = nodes.emplace(cnode, InstanceList());
if (emplaced.second)
{
@ -537,6 +566,20 @@ namespace MWRender
osg::ref_ptr<osg::Node> node = osg::clone(cnode, co);
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);
if (merge)
@ -636,7 +679,7 @@ namespace MWRender
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;
{
@ -655,7 +698,7 @@ namespace MWRender
bool ObjectPaging::blacklistObject(int type, const ESM::RefNum & refnum, const osg::Vec3f& pos)
{
if (!typeFilter(type, false, true))
if (!typeFilter(type, false))
return false;
{

View File

@ -63,6 +63,16 @@ namespace MWRender
SizeCache mSizeCache;
};
class RefnumMarker : public osg::Object
{
public:
RefnumMarker() : mNumVertices(0) {}
RefnumMarker(const RefnumMarker &copy, osg::CopyOp co) : mRefnum(copy.mRefnum), mNumVertices(copy.mNumVertices) {}
META_Object(MWRender, RefnumMarker)
ESM::RefNum mRefnum;
unsigned int mNumVertices;
};
}
#endif

View File

@ -1016,6 +1016,7 @@ namespace MWRender
{
RenderingManager::RayResult result;
result.mHit = false;
result.mHitRefnum.mContentFile = -1;
result.mRatio = 0;
if (intersector->containsIntersections())
{
@ -1027,6 +1028,7 @@ namespace MWRender
result.mRatio = intersection.ratio;
PtrHolder* ptrHolder = nullptr;
std::vector<RefnumMarker*> refnumMarkers;
for (osg::NodePath::const_iterator it = intersection.nodePath.begin(); it != intersection.nodePath.end(); ++it)
{
osg::UserDataContainer* userDataContainer = (*it)->getUserDataContainer();
@ -1036,11 +1038,25 @@ namespace MWRender
{
if (PtrHolder* p = dynamic_cast<PtrHolder*>(userDataContainer->getUserObject(i)))
ptrHolder = p;
if (RefnumMarker* r = dynamic_cast<RefnumMarker*>(userDataContainer->getUserObject(i)))
refnumMarkers.push_back(r);
}
}
if (ptrHolder)
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;

View File

@ -157,6 +157,7 @@ namespace MWRender
osg::Vec3f mHitNormalWorld;
osg::Vec3f mHitPointWorld;
MWWorld::Ptr mHitObject;
ESM::RefNum mHitRefnum;
float mRatio;
};

View File

@ -165,28 +165,6 @@ namespace
ref.load (state);
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
@ -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?)");
// Ensure that the object actually exists in the cell
SearchByRefNumVisitor searchVisitor(object.getCellRef().getRefNum());
forEach(searchVisitor);
if (!searchVisitor.mFound)
if (searchViaRefNum(object.getCellRef().getRefNum()).isEmpty())
throw std::runtime_error("moveTo: object is not in this cell");
@ -942,26 +918,22 @@ namespace MWWorld
movedTo.load(reader);
// Search for the reference. It might no longer exist if its content file was removed.
SearchByRefNumVisitor visitor(refnum);
forEachInternal(visitor);
if (!visitor.mFound)
Ptr movedRef = searchViaRefNum(refnum);
if (movedRef.isEmpty())
{
Log(Debug::Warning) << "Warning: Dropping moved ref tag for " << refnum.mIndex << " (moved object no longer exists)";
continue;
}
MWWorld::LiveCellRefBase* movedRef = visitor.mFound;
CellStore* otherCell = callback->getCellStore(movedTo);
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.";
// Note by dropping tag the object will automatically re-appear in its original cell, though potentially at inapproriate coordinates.
// Restore original coordinates:
movedRef->mData.setPosition(movedRef->mRef.getPosition());
movedRef.getRefData().setPosition(movedRef.getCellRef().getPosition());
continue;
}
@ -972,7 +944,7 @@ namespace MWWorld
continue;
}
moveTo(MWWorld::Ptr(movedRef, this), otherCell);
moveTo(movedRef, otherCell);
}
}

View File

@ -1965,6 +1965,14 @@ namespace MWWorld
rayToObject = mRendering->castCameraToViewportRay(0.5f, 0.5f, maxDistance, ignorePlayer);
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)
mDistanceToFacedObject = (rayToObject.mRatio * maxDistance) - camDist;
else

View File

@ -1824,6 +1824,10 @@ bool Optimizer::MergeGeometryVisitor::mergeGeometry(osg::Geometry& lhs,osg::Geom
lhs.dirtyBound();
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;
}