Add 'showSceneGraph' command to export the scene or a particular object to .osgt for debugging purposes

pull/1198/head
scrawl 8 years ago
parent e90941a8b3
commit 34deb6e7b1

@ -505,7 +505,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
// Create the world
mEnvironment.setWorld( new MWWorld::World (mViewer, rootNode, mResourceSystem.get(),
mFileCollections, mContentFiles, mEncoder, mFallbackMap,
mActivationDistanceOverride, mCellName, mStartupScript, mResDir.string()));
mActivationDistanceOverride, mCellName, mStartupScript, mResDir.string(), mCfgMgr.getUserDataPath().string()));
mEnvironment.getWorld()->setupPlayer();
input->setPlayer(&mEnvironment.getWorld()->getPlayer());

@ -567,6 +567,10 @@ namespace MWBase
/// Return physical or rendering half extents of the given actor.
virtual osg::Vec3f getHalfExtents(const MWWorld::ConstPtr& actor, bool rendering=false) const = 0;
/// Export scene graph to a file and return the filename.
/// \param ptr object to export scene graph for (if empty, export entire scene graph)
virtual std::string exportSceneGraph(const MWWorld::Ptr& ptr) = 0;
};
}

@ -28,6 +28,7 @@
#include <components/sceneutil/positionattitudetransform.hpp>
#include <components/sceneutil/workqueue.hpp>
#include <components/sceneutil/unrefqueue.hpp>
#include <components/sceneutil/writescene.hpp>
#include <components/terrain/terraingrid.hpp>
@ -1002,8 +1003,17 @@ namespace MWRender
if (mFieldOfViewOverridden == true)
{
mFieldOfViewOverridden = false;
updateProjectionMatrix();
}
}
void RenderingManager::exportSceneGraph(const MWWorld::Ptr &ptr, const std::string &filename, const std::string &format)
{
osg::Node* node = mViewer->getSceneData();
if (!ptr.isEmpty())
node = ptr.getRefData().getBaseNode();
SceneUtil::writeScene(node, filename, format);
}
}

@ -188,6 +188,8 @@ namespace MWRender
/// reset a previous overrideFieldOfView() call, i.e. revert to field of view specified in the settings file.
void resetFieldOfView();
void exportSceneGraph(const MWWorld::Ptr& ptr, const std::string& filename, const std::string& format);
private:
void updateProjectionMatrix();
void updateTextureFiltering();

@ -60,7 +60,9 @@ op 0x2002b: PCJoinFaction, explicit reference
op 0x2002c: MenuTest
op 0x2002d: BetaComment
op 0x2002e: BetaComment, explicit reference
opcodes 0x2002d-0x3ffff unused
op 0x2002f: ShowSceneGraph
op 0x20030: ShowSceneGraph, explicit
opcodes 0x20031-0x3ffff unused
Segment 4:
(not implemented yet)

@ -1252,6 +1252,31 @@ namespace MWScript
}
};
template <class R>
class OpShowSceneGraph : public Interpreter::Opcode1
{
public:
virtual void execute(Interpreter::Runtime &runtime, unsigned int arg0)
{
MWWorld::Ptr ptr = R()(runtime, false);
int confirmed = 0;
if (arg0==1)
{
confirmed = runtime[0].mInteger;
runtime.pop();
}
if (ptr.isEmpty() && !confirmed)
runtime.getContext().report("Exporting the entire scene graph will result in a large file. Confirm this action using 'showscenegraph 1' or select an object instead.");
else
{
const std::string& filename = MWBase::Environment::get().getWorld()->exportSceneGraph(ptr);
runtime.getContext().report("Wrote '" + filename + "'");
}
}
};
void installOpcodes (Interpreter::Interpreter& interpreter)
{
interpreter.installSegment5 (Compiler::Misc::opcodeXBox, new OpXBox);
@ -1348,6 +1373,8 @@ namespace MWScript
interpreter.installSegment5 (Compiler::Misc::opcodeRemoveFromLevCreature, new OpRemoveFromLevCreature);
interpreter.installSegment5 (Compiler::Misc::opcodeAddToLevItem, new OpAddToLevItem);
interpreter.installSegment5 (Compiler::Misc::opcodeRemoveFromLevItem, new OpRemoveFromLevItem);
interpreter.installSegment3 (Compiler::Misc::opcodeShowSceneGraph, new OpShowSceneGraph<ImplicitRef>);
interpreter.installSegment3 (Compiler::Misc::opcodeShowSceneGraphExplicit, new OpShowSceneGraph<ExplicitRef>);
}
}
}

@ -145,10 +145,10 @@ namespace MWWorld
const std::vector<std::string>& contentFiles,
ToUTF8::Utf8Encoder* encoder, const std::map<std::string,std::string>& fallbackMap,
int activationDistanceOverride, const std::string& startCell, const std::string& startupScript,
const std::string& resourcePath)
const std::string& resourcePath, const std::string& userDataPath)
: mResourceSystem(resourceSystem), mFallback(fallbackMap), mPlayer (0), mLocalScripts (mStore),
mSky (true), mCells (mStore, mEsm),
mGodMode(false), mScriptsEnabled(true), mContentFiles (contentFiles),
mGodMode(false), mScriptsEnabled(true), mContentFiles (contentFiles), mUserDataPath(userDataPath),
mActivationDistanceOverride (activationDistanceOverride), mStartupScript(startupScript),
mStartCell (startCell), mDistanceToFacedObject(-1), mTeleportEnabled(true),
mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0)
@ -3146,6 +3146,13 @@ namespace MWWorld
return mPhysics->getHalfExtents(actor);
}
std::string World::exportSceneGraph(const Ptr &ptr)
{
std::string file = mUserDataPath + "/openmw.osgt";
mRendering->exportSceneGraph(ptr, file, "Ascii");
return file;
}
void World::spawnRandomCreature(const std::string &creatureList)
{
const ESM::CreatureLevList* list = getStore().get<ESM::CreatureLevList>().find(creatureList);

@ -101,6 +101,8 @@ namespace MWWorld
bool mScriptsEnabled;
std::vector<std::string> mContentFiles;
std::string mUserDataPath;
// not implemented
World (const World&);
World& operator= (const World&);
@ -182,7 +184,7 @@ namespace MWWorld
const Files::Collections& fileCollections,
const std::vector<std::string>& contentFiles,
ToUTF8::Utf8Encoder* encoder, const std::map<std::string,std::string>& fallbackMap,
int activationDistanceOverride, const std::string& startCell, const std::string& startupScript, const std::string& resourcePath);
int activationDistanceOverride, const std::string& startCell, const std::string& startupScript, const std::string& resourcePath, const std::string& userDataPath);
virtual ~World();
@ -668,6 +670,10 @@ namespace MWWorld
/// Return physical or rendering half extents of the given actor.
virtual osg::Vec3f getHalfExtents(const MWWorld::ConstPtr& actor, bool rendering=false) const;
/// Export scene graph to a file and return the filename.
/// \param ptr object to export scene graph for (if empty, export entire scene graph)
virtual std::string exportSceneGraph(const MWWorld::Ptr& ptr);
};
}

@ -50,7 +50,7 @@ add_component_dir (shader
add_component_dir (sceneutil
clone attach visitor util statesetupdater controller skeleton riggeometry lightcontroller
lightmanager lightutil positionattitudetransform workqueue unrefqueue pathgridutil waterutil
lightmanager lightutil positionattitudetransform workqueue unrefqueue pathgridutil waterutil writescene serialize
)
add_component_dir (nif

@ -312,6 +312,8 @@ namespace Compiler
extensions.registerInstruction ("betacomment", "/S", opcodeBetaComment, opcodeBetaCommentExplicit);
extensions.registerInstruction ("bc", "/S", opcodeBetaComment, opcodeBetaCommentExplicit);
extensions.registerInstruction ("ori", "/S", opcodeBetaComment, opcodeBetaCommentExplicit); // 'ori' stands for 'ObjectReferenceInfo'
extensions.registerInstruction ("showscenegraph", "/l", opcodeShowSceneGraph, opcodeShowSceneGraphExplicit);
extensions.registerInstruction ("ssg", "/l", opcodeShowSceneGraph, opcodeShowSceneGraphExplicit);
extensions.registerInstruction ("addtolevcreature", "ccl", opcodeAddToLevCreature);
extensions.registerInstruction ("removefromlevcreature", "ccl", opcodeRemoveFromLevCreature);
extensions.registerInstruction ("addtolevitem", "ccl", opcodeAddToLevItem);

@ -292,6 +292,8 @@ namespace Compiler
const int opcodeRemoveFromLevCreature = 0x20002fc;
const int opcodeAddToLevItem = 0x20002fd;
const int opcodeRemoveFromLevItem = 0x20002fe;
const int opcodeShowSceneGraph = 0x2002f;
const int opcodeShowSceneGraphExplicit = 0x20030;
}
namespace Sky

@ -132,7 +132,7 @@ namespace SceneUtil
: osg::NodeCallback(copy, copyop)
{ }
META_Object(SceneUtil, SceneUtil::LightManagerUpdateCallback)
META_Object(SceneUtil, LightManagerUpdateCallback)
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{

@ -32,7 +32,7 @@ namespace SceneUtil
public:
META_Node(SceneUtil, SceneUtil::LightSource)
META_Node(SceneUtil, LightSource)
LightSource();
@ -79,7 +79,7 @@ namespace SceneUtil
{
public:
META_Node(SceneUtil, SceneUtil::LightManager)
META_Node(SceneUtil, LightManager)
LightManager();

@ -0,0 +1,119 @@
#include "serialize.hpp"
#include <osgDB/ObjectWrapper>
#include <osgDB/Registry>
#include <components/sceneutil/positionattitudetransform.hpp>
#include <components/sceneutil/skeleton.hpp>
#include <components/sceneutil/riggeometry.hpp>
namespace SceneUtil
{
template <class Cls>
static osg::Object* createInstanceFunc() { return new Cls; }
class PositionAttitudeTransformSerializer : public osgDB::ObjectWrapper
{
public:
PositionAttitudeTransformSerializer()
: osgDB::ObjectWrapper(createInstanceFunc<SceneUtil::PositionAttitudeTransform>, "SceneUtil::PositionAttitudeTransform", "osg::Object osg::Node osg::Group osg::Transform SceneUtil::PositionAttitudeTransform")
{
addSerializer( new osgDB::PropByRefSerializer< SceneUtil::PositionAttitudeTransform, osg::Vec3f >(
"position", osg::Vec3f(), &SceneUtil::PositionAttitudeTransform::getPosition, &SceneUtil::PositionAttitudeTransform::setPosition), osgDB::BaseSerializer::RW_VEC3F );
addSerializer( new osgDB::PropByRefSerializer< SceneUtil::PositionAttitudeTransform, osg::Quat >(
"attitude", osg::Quat(), &SceneUtil::PositionAttitudeTransform::getAttitude, &SceneUtil::PositionAttitudeTransform::setAttitude), osgDB::BaseSerializer::RW_QUAT );
addSerializer( new osgDB::PropByRefSerializer< SceneUtil::PositionAttitudeTransform, osg::Vec3f >(
"scale", osg::Vec3f(), &SceneUtil::PositionAttitudeTransform::getScale, &SceneUtil::PositionAttitudeTransform::setScale), osgDB::BaseSerializer::RW_VEC3F );
}
};
class SkeletonSerializer : public osgDB::ObjectWrapper
{
public:
SkeletonSerializer()
: osgDB::ObjectWrapper(createInstanceFunc<SceneUtil::Skeleton>, "SceneUtil::Skeleton", "osg::Object osg::Node osg::Group SceneUtil::Skeleton")
{
}
};
class FrameSwitchSerializer : public osgDB::ObjectWrapper
{
public:
FrameSwitchSerializer()
: osgDB::ObjectWrapper(createInstanceFunc<osg::Group>, "NifOsg::FrameSwitch", "osg::Object osg::Node osg::Group NifOsg::FrameSwitch")
{
}
};
class RigGeometrySerializer : public osgDB::ObjectWrapper
{
public:
RigGeometrySerializer()
: osgDB::ObjectWrapper(createInstanceFunc<SceneUtil::RigGeometry>, "SceneUtil::RigGeometry", "osg::Object osg::Node osg::Drawable osg::Geometry SceneUtil::RigGeometry")
{
}
};
class LightManagerSerializer : public osgDB::ObjectWrapper
{
public:
LightManagerSerializer()
: osgDB::ObjectWrapper(createInstanceFunc<osg::Group>, "SceneUtil::LightManager", "osg::Object osg::Node osg::Group SceneUtil::LightManager")
{
}
};
osgDB::ObjectWrapper* makeDummySerializer(const std::string& classname)
{
return new osgDB::ObjectWrapper(createInstanceFunc<osg::DummyObject>, classname, "osg::Object");
}
void registerSerializers()
{
static bool done = false;
if (!done)
{
osgDB::Registry::instance()->getObjectWrapperManager()->addWrapper(new PositionAttitudeTransformSerializer);
osgDB::Registry::instance()->getObjectWrapperManager()->addWrapper(new SkeletonSerializer);
osgDB::Registry::instance()->getObjectWrapperManager()->addWrapper(new FrameSwitchSerializer);
osgDB::Registry::instance()->getObjectWrapperManager()->addWrapper(new RigGeometrySerializer);
osgDB::Registry::instance()->getObjectWrapperManager()->addWrapper(new LightManagerSerializer);
// ignore the below for now to avoid warning spam
const char* ignore[] = {
"MWRender::PtrHolder",
"MWRender::CameraRelativeTransform",
"Resource::TemplateRef",
"SceneUtil::LightListCallback",
"SceneUtil::LightManagerUpdateCallback",
"SceneUtil::UpdateRigBounds",
"SceneUtil::UpdateRigGeometry",
"SceneUtil::LightSource",
"NifOsg::NodeUserData",
"NifOsg::FlipController",
"NifOsg::KeyframeController",
"NifOsg::TextKeyMapHolder",
"NifOsg::Emitter",
"NifOsg::ParticleSystem",
"NifOsg::GrowFadeAffector",
"NifOsg::InverseWorldMatrix",
"NifOsg::StaticBoundingBoxCallback",
"NifOsg::GeomMorpherController",
"NifOsg::UpdateMorphGeometry",
"osgMyGUI::Drawable",
"osg::DrawCallback",
"osg::DummyObject"
};
for (size_t i=0; i<sizeof(ignore)/sizeof(ignore[0]); ++i)
{
osgDB::Registry::instance()->getObjectWrapperManager()->addWrapper(makeDummySerializer(ignore[i]));
}
done = true;
}
}
}

@ -0,0 +1,12 @@
#ifndef OPENMW_COMPONENTS_SCENEUTIL_SERIALIZE_H
#define OPENMW_COMPONENTS_SCENEUTIL_SERIALIZE_H
namespace SceneUtil
{
/// Register osg node serializers for certain SceneUtil classes if not already done so
void registerSerializers();
}
#endif

@ -0,0 +1,26 @@
#include "writescene.hpp"
#include <stdexcept>
#include <osgDB/Registry>
#include <boost/filesystem/fstream.hpp>
#include "serialize.hpp"
void SceneUtil::writeScene(osg::Node *node, const std::string& filename, const std::string& format)
{
registerSerializers();
osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension("osgt");
if (!rw)
throw std::runtime_error("can not find readerwriter for " + format);
boost::filesystem::ofstream stream;
stream.open(filename);
osg::ref_ptr<osgDB::Options> options = new osgDB::Options;
options->setPluginStringData("fileType", format);
rw->writeNode(*node, stream, options);
}

@ -0,0 +1,18 @@
#ifndef OPENMW_COMPONENTS_WRITESCENE_H
#define OPENMW_COMPONENTS_WRITESCENE_H
#include <string>
namespace osg
{
class Node;
}
namespace SceneUtil
{
void writeScene(osg::Node* node, const std::string& filename, const std::string& format);
}
#endif
Loading…
Cancel
Save