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:
parent
65cd2c77aa
commit
9f0398c021
@ -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;
|
||||
|
||||
{
|
||||
|
@ -63,6 +63,16 @@ namespace MWRender
|
||||
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
|
||||
|
@ -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;
|
||||
|
@ -157,6 +157,7 @@ namespace MWRender
|
||||
osg::Vec3f mHitNormalWorld;
|
||||
osg::Vec3f mHitPointWorld;
|
||||
MWWorld::Ptr mHitObject;
|
||||
ESM::RefNum mHitRefnum;
|
||||
float mRatio;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user