mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-30 03:15:32 +00:00
Start rendering npc's
This commit is contained in:
parent
5fa9b32e76
commit
8444ee9981
10 changed files with 471 additions and 38 deletions
|
@ -93,7 +93,7 @@ opencs_units (view/render
|
|||
|
||||
opencs_units_noqt (view/render
|
||||
lighting lightingday lightingnight lightingbright object cell terrainstorage tagbase
|
||||
cellarrow cellmarker cellborder pathgrid
|
||||
cellarrow cellmarker cellborder pathgrid actor
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (view/render
|
||||
|
|
196
apps/opencs/view/render/actor.cpp
Normal file
196
apps/opencs/view/render/actor.cpp
Normal file
|
@ -0,0 +1,196 @@
|
|||
#include "actor.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <osg/Group>
|
||||
#include <osg/Node>
|
||||
|
||||
#include <components/esm/mappings.hpp>
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
#include <components/resource/resourcemanager.hpp>
|
||||
#include <components/resource/scenemanager.hpp>
|
||||
#include <components/sceneutil/attach.hpp>
|
||||
#include <components/sceneutil/skeleton.hpp>
|
||||
#include <components/sceneutil/visitor.hpp>
|
||||
|
||||
#include "../../model/world/data.hpp"
|
||||
|
||||
namespace CSVRender
|
||||
{
|
||||
Actor::Actor(const std::string& id, int type, CSMWorld::Data& data)
|
||||
: mId(id)
|
||||
, mType(type)
|
||||
, mData(data)
|
||||
, mSkeleton(nullptr)
|
||||
, mBaseNode(new osg::Group())
|
||||
{
|
||||
}
|
||||
|
||||
osg::Group* Actor::getBaseNode()
|
||||
{
|
||||
return mBaseNode;
|
||||
}
|
||||
|
||||
void Actor::update()
|
||||
{
|
||||
const std::string MeshPrefix = "meshes\\";
|
||||
const unsigned int FemaleFlag = ESM::BodyPart::BPF_Female;
|
||||
|
||||
auto& bodyParts = mData.getBodyParts();
|
||||
auto& races = mData.getRaces();
|
||||
auto& referenceables = mData.getReferenceables();
|
||||
auto sceneMgr = mData.getResourceSystem()->getSceneManager();
|
||||
|
||||
|
||||
// Remove children
|
||||
mBaseNode->removeChildren(0, mBaseNode->getNumChildren());
|
||||
|
||||
// Npcs and creatures are handled differently
|
||||
if (mType == CSMWorld::UniversalId::Type_Npc)
|
||||
{
|
||||
auto& npc = dynamic_cast<const CSMWorld::Record<ESM::NPC>& >(referenceables.getRecord(mId)).get();
|
||||
|
||||
auto isBeast = [&](std::string race) -> bool {
|
||||
int index = races.searchId(race);
|
||||
if (index != -1 && !races.getRecord(index).isDeleted())
|
||||
return races.getRecord(index).get().mData.mFlags & ESM::Race::Beast;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
|
||||
// Load skeleton
|
||||
std::string skeletonResource;
|
||||
if (isBeast(npc.mRace)) {
|
||||
std::cout << "is beast\n";
|
||||
skeletonResource = "base_animkna.nif";
|
||||
}
|
||||
else if (npc.isMale()) {
|
||||
std::cout << "is male\n";
|
||||
skeletonResource = "base_anim.nif";
|
||||
}
|
||||
else {
|
||||
std::cout << "is female\n";
|
||||
skeletonResource = "base_anim_female.nif";
|
||||
}
|
||||
|
||||
std::string skeletonModel = MeshPrefix + skeletonResource;
|
||||
skeletonModel = Misc::ResourceHelpers::correctActorModelPath(skeletonModel, mData.getResourceSystem()->getVFS());
|
||||
{
|
||||
osg::ref_ptr<osg::Node> temp = sceneMgr->getInstance(skeletonModel);
|
||||
mSkeleton = dynamic_cast<SceneUtil::Skeleton*>(temp.get());
|
||||
if (!mSkeleton)
|
||||
{
|
||||
mSkeleton = new SceneUtil::Skeleton();
|
||||
mSkeleton->addChild(temp);
|
||||
}
|
||||
mBaseNode->addChild(mSkeleton);
|
||||
}
|
||||
|
||||
// Map bone names to bones
|
||||
SceneUtil::NodeMapVisitor::NodeMap nodeMap;
|
||||
SceneUtil::NodeMapVisitor nmVisitor(nodeMap);
|
||||
mSkeleton->accept(nmVisitor);
|
||||
|
||||
if (!npc.isMale()) {
|
||||
for (auto it : nodeMap) {
|
||||
std::cout << it.first << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Female mesh has some drawables attached, get rid of them
|
||||
SceneUtil::HideDrawablesVisitor hdVisitor;
|
||||
mSkeleton->accept(hdVisitor);
|
||||
|
||||
// Convenience method to retrieve the mesh name of a body part
|
||||
auto getBodyPartMesh = [&](std::string bpName) -> std::string {
|
||||
int index = bodyParts.searchId(bpName);
|
||||
if (index != -1 && !bodyParts.getRecord(index).isDeleted())
|
||||
return MeshPrefix + bodyParts.getRecord(index).get().mModel;
|
||||
else
|
||||
return "";
|
||||
};
|
||||
|
||||
using BPRaceKey = std::tuple<int, int, std::string>;
|
||||
using RaceToBPMap = std::map<BPRaceKey, std::string>;
|
||||
// Convenience method to generate a map from body part + race to mesh name
|
||||
auto genRaceToBodyPartMap = [&](RaceToBPMap& bpMap) {
|
||||
int size = bodyParts.getSize();
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
auto& record = bodyParts.getRecord(i);
|
||||
if (!record.isDeleted())
|
||||
{
|
||||
auto& bodyPart = record.get();
|
||||
bpMap.emplace(
|
||||
BPRaceKey(bodyPart.mData.mPart, bodyPart.mData.mFlags & FemaleFlag ? 1 : 0, bodyPart.mRace),
|
||||
MeshPrefix + bodyPart.mModel);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Generate mapping
|
||||
RaceToBPMap r2bpMap;
|
||||
genRaceToBodyPartMap(r2bpMap);
|
||||
|
||||
// Convenience method to add a body part
|
||||
auto addBodyPart = [&](ESM::PartReferenceType type, std::string mesh) {
|
||||
// Retrieve mesh name if necessary
|
||||
if (mesh.empty())
|
||||
{
|
||||
auto meshResult = r2bpMap.find(BPRaceKey(ESM::getMeshPart(type), npc.isMale() ? 0 : 1, npc.mRace));
|
||||
if (meshResult != r2bpMap.end())
|
||||
{
|
||||
mesh = meshResult->second;
|
||||
}
|
||||
}
|
||||
|
||||
// Attach to skeleton
|
||||
std::string boneName = ESM::getBoneName(type);
|
||||
auto node = nodeMap.find(boneName);
|
||||
if (!mesh.empty() && node != nodeMap.end())
|
||||
{
|
||||
auto instance = sceneMgr->getInstance(mesh);
|
||||
if (!npc.isMale() && type == ESM::PRT_LHand) {
|
||||
SceneUtil::NodeMapVisitor::NodeMap handNodeMap;
|
||||
SceneUtil::NodeMapVisitor nmVisitor(handNodeMap);
|
||||
instance->accept(nmVisitor);
|
||||
|
||||
std::cout << "Left hand\n";
|
||||
for (auto it : handNodeMap) {
|
||||
std::cout << it.first << std::endl;
|
||||
}
|
||||
}
|
||||
SceneUtil::attach(instance, mSkeleton, boneName, node->second);
|
||||
}
|
||||
};
|
||||
|
||||
// Add body parts
|
||||
for (unsigned int i = 0; i < ESM::PRT_Count; ++i)
|
||||
{
|
||||
auto part = static_cast<ESM::PartReferenceType>(i);
|
||||
switch (part)
|
||||
{
|
||||
case ESM::PRT_Head:
|
||||
addBodyPart(part, getBodyPartMesh(npc.mHead));
|
||||
break;
|
||||
case ESM::PRT_Hair:
|
||||
addBodyPart(part, getBodyPartMesh(npc.mHair));
|
||||
break;
|
||||
case ESM::PRT_Skirt:
|
||||
case ESM::PRT_Shield:
|
||||
case ESM::PRT_RPauldron:
|
||||
case ESM::PRT_LPauldron:
|
||||
case ESM::PRT_Weapon:
|
||||
// No body part mesh associated
|
||||
break;
|
||||
default:
|
||||
addBodyPart(part, "");
|
||||
}
|
||||
}
|
||||
// Post setup
|
||||
mSkeleton->markDirty();
|
||||
mSkeleton->setActive(SceneUtil::Skeleton::Active);
|
||||
}
|
||||
}
|
||||
}
|
51
apps/opencs/view/render/actor.hpp
Normal file
51
apps/opencs/view/render/actor.hpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
#ifndef OPENCS_VIEW_RENDER_ACTOR_H
|
||||
#define OPENCS_VIEW_RENDER_ACTOR_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Group;
|
||||
}
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class Data;
|
||||
}
|
||||
|
||||
namespace SceneUtil
|
||||
{
|
||||
class Skeleton;
|
||||
}
|
||||
|
||||
namespace CSVRender
|
||||
{
|
||||
/// Handles loading an npc or creature
|
||||
class Actor
|
||||
{
|
||||
public:
|
||||
/// Creates an actor.
|
||||
/// \param id The referenceable id
|
||||
/// \param type The record type
|
||||
/// \param data The data store
|
||||
Actor(const std::string& id, int type, CSMWorld::Data& data);
|
||||
|
||||
/// Retrieves the base node that meshes are attached to
|
||||
osg::Group* getBaseNode();
|
||||
|
||||
/// (Re)creates the npc or creature renderable
|
||||
void update();
|
||||
|
||||
private:
|
||||
std::string mId;
|
||||
int mType;
|
||||
CSMWorld::Data& mData;
|
||||
|
||||
SceneUtil::Skeleton* mSkeleton;
|
||||
osg::ref_ptr<osg::Group> mBaseNode;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,6 +1,8 @@
|
|||
#include "object.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include <osg/Depth>
|
||||
#include <osg/Group>
|
||||
|
@ -11,6 +13,7 @@
|
|||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/PrimitiveSet>
|
||||
#include <osg/MatrixTransform>
|
||||
|
||||
#include <osgFX/Scribe>
|
||||
|
||||
|
@ -28,7 +31,9 @@
|
|||
#include <components/sceneutil/lightutil.hpp>
|
||||
#include <components/sceneutil/lightmanager.hpp>
|
||||
#include <components/fallback/fallback.hpp>
|
||||
#include <components/sceneutil/attach.hpp>
|
||||
|
||||
#include "actor.hpp"
|
||||
#include "mask.hpp"
|
||||
|
||||
|
||||
|
@ -84,6 +89,7 @@ void CSVRender::Object::update()
|
|||
const CSMWorld::RefIdCollection& referenceables = mData.getReferenceables();
|
||||
|
||||
int index = referenceables.searchId (mReferenceableId);
|
||||
int recordType = -1;
|
||||
const ESM::Light* light = NULL;
|
||||
|
||||
if (index==-1)
|
||||
|
@ -96,7 +102,7 @@ void CSVRender::Object::update()
|
|||
referenceables.findColumnIndex (CSMWorld::Columns::ColumnId_Model)).
|
||||
toString().toUtf8().constData();
|
||||
|
||||
int recordType =
|
||||
recordType =
|
||||
referenceables.getData (index,
|
||||
referenceables.findColumnIndex(CSMWorld::Columns::ColumnId_RecordType)).toInt();
|
||||
if (recordType == CSMWorld::UniversalId::Type_Light)
|
||||
|
@ -112,7 +118,7 @@ void CSVRender::Object::update()
|
|||
model = "marker_creature.nif";
|
||||
}
|
||||
|
||||
if (model.empty())
|
||||
if (recordType != CSMWorld::UniversalId::Type_Npc && model.empty())
|
||||
error = 2;
|
||||
}
|
||||
|
||||
|
@ -126,9 +132,18 @@ void CSVRender::Object::update()
|
|||
{
|
||||
try
|
||||
{
|
||||
std::string path = "meshes\\" + model;
|
||||
|
||||
mResourceSystem->getSceneManager()->getInstance(path, mBaseNode);
|
||||
if (recordType == CSMWorld::UniversalId::Type_Npc)
|
||||
{
|
||||
std::cout << "recordType: Npc\n";
|
||||
Actor actor(mReferenceableId, recordType, mData);
|
||||
actor.update();
|
||||
mBaseNode->addChild(actor.getBaseNode());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string path = "meshes\\" + model;
|
||||
mResourceSystem->getSceneManager()->getInstance(path, mBaseNode);
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
|
|
|
@ -91,32 +91,6 @@ namespace
|
|||
std::vector<osg::ref_ptr<osg::Node> > mToRemove;
|
||||
};
|
||||
|
||||
class NodeMapVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
typedef std::map<std::string, osg::ref_ptr<osg::MatrixTransform> > NodeMap;
|
||||
|
||||
NodeMapVisitor(NodeMap& map)
|
||||
: osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
|
||||
, mMap(map)
|
||||
{}
|
||||
|
||||
void apply(osg::MatrixTransform& trans)
|
||||
{
|
||||
// Take transformation for first found node in file
|
||||
const std::string nodeName = Misc::StringUtils::lowerCase(trans.getName());
|
||||
if (mMap.find(nodeName) == mMap.end())
|
||||
{
|
||||
mMap[nodeName] = &trans;
|
||||
}
|
||||
|
||||
traverse(trans);
|
||||
}
|
||||
|
||||
private:
|
||||
NodeMap& mMap;
|
||||
};
|
||||
|
||||
NifOsg::TextKeyMap::const_iterator findGroupStart(const NifOsg::TextKeyMap &keys, const std::string &groupname)
|
||||
{
|
||||
NifOsg::TextKeyMap::const_iterator iter(keys.begin());
|
||||
|
@ -468,7 +442,7 @@ namespace MWRender
|
|||
}
|
||||
if (mDone)
|
||||
return;
|
||||
|
||||
|
||||
// Set the starting time to measure glow duration from if this is a temporary glow
|
||||
if ((mDuration >= 0) && mStartingTime == 0)
|
||||
mStartingTime = nv->getFrameStamp()->getSimulationTime();
|
||||
|
@ -1042,7 +1016,7 @@ namespace MWRender
|
|||
{
|
||||
if (!mNodeMapCreated && mObjectRoot)
|
||||
{
|
||||
NodeMapVisitor visitor(mNodeMap);
|
||||
SceneUtil::NodeMapVisitor visitor(mNodeMap);
|
||||
mObjectRoot->accept(visitor);
|
||||
mNodeMapCreated = true;
|
||||
}
|
||||
|
@ -1313,7 +1287,7 @@ namespace MWRender
|
|||
|
||||
if(state.getTime() >= state.mLoopStopTime)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(timepassed <= 0.0f)
|
||||
break;
|
||||
|
@ -1528,7 +1502,7 @@ namespace MWRender
|
|||
osg::ref_ptr<GlowUpdater> glowUpdater = new GlowUpdater(texUnit, glowColor, textures, node, glowDuration, mResourceSystem);
|
||||
mGlowUpdater = glowUpdater;
|
||||
node->addUpdateCallback(glowUpdater);
|
||||
|
||||
|
||||
// set a texture now so that the ShaderVisitor can find it
|
||||
osg::ref_ptr<osg::StateSet> writableStateSet = NULL;
|
||||
if (!node->getStateSet())
|
||||
|
|
|
@ -77,7 +77,7 @@ add_component_dir (esm
|
|||
loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter
|
||||
savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap inventorystate containerstate npcstate creaturestate dialoguestate statstate
|
||||
npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile
|
||||
aisequence magiceffects util custommarkerstate stolenitems transport animationstate controlsstate
|
||||
aisequence magiceffects util custommarkerstate stolenitems transport animationstate controlsstate mappings
|
||||
)
|
||||
|
||||
add_component_dir (esmterrain
|
||||
|
|
134
components/esm/mappings.cpp
Normal file
134
components/esm/mappings.cpp
Normal file
|
@ -0,0 +1,134 @@
|
|||
#include "mappings.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
ESM::BodyPart::MeshPart getMeshPart(ESM::PartReferenceType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ESM::PRT_Head:
|
||||
return ESM::BodyPart::MP_Head;
|
||||
case ESM::PRT_Hair:
|
||||
return ESM::BodyPart::MP_Hair;
|
||||
case ESM::PRT_Neck:
|
||||
return ESM::BodyPart::MP_Neck;
|
||||
case ESM::PRT_Cuirass:
|
||||
return ESM::BodyPart::MP_Chest;
|
||||
case ESM::PRT_Groin:
|
||||
return ESM::BodyPart::MP_Groin;
|
||||
case ESM::PRT_RHand:
|
||||
return ESM::BodyPart::MP_Hand;
|
||||
case ESM::PRT_LHand:
|
||||
return ESM::BodyPart::MP_Hand;
|
||||
case ESM::PRT_RWrist:
|
||||
return ESM::BodyPart::MP_Wrist;
|
||||
case ESM::PRT_LWrist:
|
||||
return ESM::BodyPart::MP_Wrist;
|
||||
case ESM::PRT_RForearm:
|
||||
return ESM::BodyPart::MP_Forearm;
|
||||
case ESM::PRT_LForearm:
|
||||
return ESM::BodyPart::MP_Forearm;
|
||||
case ESM::PRT_RUpperarm:
|
||||
return ESM::BodyPart::MP_Upperarm;
|
||||
case ESM::PRT_LUpperarm:
|
||||
return ESM::BodyPart::MP_Upperarm;
|
||||
case ESM::PRT_RFoot:
|
||||
return ESM::BodyPart::MP_Foot;
|
||||
case ESM::PRT_LFoot:
|
||||
return ESM::BodyPart::MP_Foot;
|
||||
case ESM::PRT_RAnkle:
|
||||
return ESM::BodyPart::MP_Ankle;
|
||||
case ESM::PRT_LAnkle:
|
||||
return ESM::BodyPart::MP_Ankle;
|
||||
case ESM::PRT_RKnee:
|
||||
return ESM::BodyPart::MP_Knee;
|
||||
case ESM::PRT_LKnee:
|
||||
return ESM::BodyPart::MP_Knee;
|
||||
case ESM::PRT_RLeg:
|
||||
return ESM::BodyPart::MP_Upperleg;
|
||||
case ESM::PRT_LLeg:
|
||||
return ESM::BodyPart::MP_Upperleg;
|
||||
case ESM::PRT_Tail:
|
||||
return ESM::BodyPart::MP_Tail;
|
||||
default:
|
||||
throw std::runtime_error("PartReferenceType " +
|
||||
std::to_string(type) + " not associated with a mesh part");
|
||||
}
|
||||
}
|
||||
|
||||
std::string getBoneName(ESM::PartReferenceType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ESM::PRT_Head:
|
||||
return "head";
|
||||
case ESM::PRT_Hair:
|
||||
return "head"; // This is purposeful.
|
||||
case ESM::PRT_Neck:
|
||||
return "neck";
|
||||
case ESM::PRT_Cuirass:
|
||||
return "chest";
|
||||
case ESM::PRT_Groin:
|
||||
return "groin";
|
||||
case ESM::PRT_Skirt:
|
||||
return "groin";
|
||||
case ESM::PRT_RHand:
|
||||
return "right hand";
|
||||
case ESM::PRT_LHand:
|
||||
return "left hand";
|
||||
case ESM::PRT_RWrist:
|
||||
return "right wrist";
|
||||
case ESM::PRT_LWrist:
|
||||
return "left wrist";
|
||||
case ESM::PRT_Shield:
|
||||
return "shield bone";
|
||||
case ESM::PRT_RForearm:
|
||||
return "right forearm";
|
||||
case ESM::PRT_LForearm:
|
||||
return "left forearm";
|
||||
case ESM::PRT_RUpperarm:
|
||||
return "right upper arm";
|
||||
case ESM::PRT_LUpperarm:
|
||||
return "left upper arm";
|
||||
case ESM::PRT_RFoot:
|
||||
return "right foot";
|
||||
case ESM::PRT_LFoot:
|
||||
return "left foot";
|
||||
case ESM::PRT_RAnkle:
|
||||
return "right ankle";
|
||||
case ESM::PRT_LAnkle:
|
||||
return "left ankle";
|
||||
case ESM::PRT_RKnee:
|
||||
return "right knee";
|
||||
case ESM::PRT_LKnee:
|
||||
return "left knee";
|
||||
case ESM::PRT_RLeg:
|
||||
return "right upper leg";
|
||||
case ESM::PRT_LLeg:
|
||||
return "left upper leg";
|
||||
case ESM::PRT_RPauldron:
|
||||
return "right clavicle";
|
||||
case ESM::PRT_LPauldron:
|
||||
return "left clavicle";
|
||||
case ESM::PRT_Weapon:
|
||||
return "weapon bone";
|
||||
case ESM::PRT_Tail:
|
||||
return "tail";
|
||||
default:
|
||||
throw std::runtime_error("unknown PartReferenceType");
|
||||
}
|
||||
}
|
||||
|
||||
std::string getMeshFilter(ESM::PartReferenceType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ESM::PRT_Hair:
|
||||
return "hair";
|
||||
default:
|
||||
return getBoneName(type);
|
||||
}
|
||||
}
|
||||
}
|
16
components/esm/mappings.hpp
Normal file
16
components/esm/mappings.hpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef OPENMW_ESM_MAPPINGS_H
|
||||
#define OPENMW_ESM_MAPPINGS_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <components/esm/loadarmo.hpp>
|
||||
#include <components/esm/loadbody.hpp>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
ESM::BodyPart::MeshPart getMeshPart(ESM::PartReferenceType type);
|
||||
std::string getBoneName(ESM::PartReferenceType type);
|
||||
std::string getMeshFilter(ESM::PartReferenceType type);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,5 +1,6 @@
|
|||
#include "visitor.hpp"
|
||||
|
||||
#include <osg/Drawable>
|
||||
#include <osg/MatrixTransform>
|
||||
|
||||
#include <osgParticle/ParticleSystem>
|
||||
|
@ -23,7 +24,7 @@ namespace SceneUtil
|
|||
{
|
||||
if (Misc::StringUtils::ciEqual(node.className(), mNameToFind))
|
||||
mFoundNodes.push_back(&node);
|
||||
|
||||
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
|
@ -54,4 +55,20 @@ namespace SceneUtil
|
|||
partsys->setFreezeOnCull(false);
|
||||
}
|
||||
|
||||
void NodeMapVisitor::apply(osg::MatrixTransform& trans)
|
||||
{
|
||||
// Take transformation for first found node in file
|
||||
const std::string nodeName = Misc::StringUtils::lowerCase(trans.getName());
|
||||
if (mMap.find(nodeName) == mMap.end())
|
||||
{
|
||||
mMap[nodeName] = &trans;
|
||||
}
|
||||
|
||||
traverse(trans);
|
||||
}
|
||||
|
||||
void HideDrawablesVisitor::apply(osg::Drawable& drawable)
|
||||
{
|
||||
drawable.setNodeMask(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef OPENMW_COMPONENTS_SCENEUTIL_VISITOR_H
|
||||
#define OPENMW_COMPONENTS_SCENEUTIL_VISITOR_H
|
||||
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/NodeVisitor>
|
||||
|
||||
// Commonly used scene graph visitors
|
||||
|
@ -58,6 +59,35 @@ namespace SceneUtil
|
|||
virtual void apply(osg::Drawable& drw);
|
||||
};
|
||||
|
||||
/// Maps names to nodes
|
||||
class NodeMapVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
typedef std::map<std::string, osg::ref_ptr<osg::MatrixTransform> > NodeMap;
|
||||
|
||||
NodeMapVisitor(NodeMap& map)
|
||||
: osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
|
||||
, mMap(map)
|
||||
{}
|
||||
|
||||
void apply(osg::MatrixTransform& trans);
|
||||
|
||||
private:
|
||||
NodeMap& mMap;
|
||||
};
|
||||
|
||||
/// Hides all attached drawables
|
||||
class HideDrawablesVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
HideDrawablesVisitor()
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
{
|
||||
}
|
||||
|
||||
void apply(osg::Drawable& drawable) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue