Merge pull request #137 from OpenMW/master

Add OpenMW commits up to 1 Feb
coverity_scan^2
David Cernat 8 years ago committed by GitHub
commit 9f8f62b765

@ -10,6 +10,7 @@
#include <osgViewer/CompositeViewer> #include <osgViewer/CompositeViewer>
#include <osgViewer/ViewerEventHandlers> #include <osgViewer/ViewerEventHandlers>
#include <osg/LightModel> #include <osg/LightModel>
#include <osg/Material>
#include <osg/Version> #include <osg/Version>
#include <components/resource/scenemanager.hpp> #include <components/resource/scenemanager.hpp>
@ -74,6 +75,12 @@ RenderWidget::RenderWidget(QWidget *parent, Qt::WindowFlags f)
mView->getCamera()->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON); mView->getCamera()->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
mView->getCamera()->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::ON); mView->getCamera()->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
osg::ref_ptr<osg::Material> defaultMat (new osg::Material);
defaultMat->setColorMode(osg::Material::OFF);
defaultMat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1));
defaultMat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1));
defaultMat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 0.f));
mView->getCamera()->getOrCreateStateSet()->getOrCreateStateSet()->setAttribute(defaultMat);
mView->setSceneData(mRootNode); mView->setSceneData(mRootNode);

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

@ -570,6 +570,10 @@ namespace MWBase
/// Return physical or rendering half extents of the given actor. /// Return physical or rendering half extents of the given actor.
virtual osg::Vec3f getHalfExtents(const MWWorld::ConstPtr& actor, bool rendering=false) const = 0; 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;
}; };
} }

@ -6,6 +6,7 @@
#include <osg/Light> #include <osg/Light>
#include <osg/LightModel> #include <osg/LightModel>
#include <osg/Fog> #include <osg/Fog>
#include <osg/Material>
#include <osg/PolygonMode> #include <osg/PolygonMode>
#include <osg/Group> #include <osg/Group>
#include <osg/UserDataContainer> #include <osg/UserDataContainer>
@ -28,6 +29,7 @@
#include <components/sceneutil/positionattitudetransform.hpp> #include <components/sceneutil/positionattitudetransform.hpp>
#include <components/sceneutil/workqueue.hpp> #include <components/sceneutil/workqueue.hpp>
#include <components/sceneutil/unrefqueue.hpp> #include <components/sceneutil/unrefqueue.hpp>
#include <components/sceneutil/writescene.hpp>
#include <components/terrain/terraingrid.hpp> #include <components/terrain/terraingrid.hpp>
@ -220,6 +222,12 @@ namespace MWRender
sceneRoot->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::ON); sceneRoot->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
sceneRoot->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON); sceneRoot->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON);
sceneRoot->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON); sceneRoot->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
osg::ref_ptr<osg::Material> defaultMat (new osg::Material);
defaultMat->setColorMode(osg::Material::OFF);
defaultMat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1));
defaultMat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1));
defaultMat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 0.f));
sceneRoot->getOrCreateStateSet()->setAttribute(defaultMat);
sceneRoot->setNodeMask(Mask_Scene); sceneRoot->setNodeMask(Mask_Scene);
sceneRoot->setName("Scene Root"); sceneRoot->setName("Scene Root");
@ -236,7 +244,10 @@ namespace MWRender
if (!Settings::Manager::getBool("small feature culling", "Camera")) if (!Settings::Manager::getBool("small feature culling", "Camera"))
cullingMode &= ~(osg::CullStack::SMALL_FEATURE_CULLING); cullingMode &= ~(osg::CullStack::SMALL_FEATURE_CULLING);
else else
{
mViewer->getCamera()->setSmallFeatureCullingPixelSize(Settings::Manager::getFloat("small feature culling pixel size", "Camera"));
cullingMode |= osg::CullStack::SMALL_FEATURE_CULLING; cullingMode |= osg::CullStack::SMALL_FEATURE_CULLING;
}
mViewer->getCamera()->setCullingMode( cullingMode ); mViewer->getCamera()->setCullingMode( cullingMode );
@ -1002,8 +1013,17 @@ namespace MWRender
if (mFieldOfViewOverridden == true) if (mFieldOfViewOverridden == true)
{ {
mFieldOfViewOverridden = false; mFieldOfViewOverridden = false;
updateProjectionMatrix(); 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. /// reset a previous overrideFieldOfView() call, i.e. revert to field of view specified in the settings file.
void resetFieldOfView(); void resetFieldOfView();
void exportSceneGraph(const MWWorld::Ptr& ptr, const std::string& filename, const std::string& format);
private: private:
void updateProjectionMatrix(); void updateProjectionMatrix();
void updateTextureFiltering(); void updateTextureFiltering();

@ -222,6 +222,7 @@ public:
setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
setReferenceFrame(osg::Camera::RELATIVE_RF); setReferenceFrame(osg::Camera::RELATIVE_RF);
setSmallFeatureCullingPixelSize(Settings::Manager::getInt("small feature culling pixel size", "Water"));
setCullMask(Mask_Effect|Mask_Scene|Mask_Terrain|Mask_Actor|Mask_ParticleSystem|Mask_Sky|Mask_Sun|Mask_Player|Mask_Lighting); setCullMask(Mask_Effect|Mask_Scene|Mask_Terrain|Mask_Actor|Mask_ParticleSystem|Mask_Sky|Mask_Sun|Mask_Player|Mask_Lighting);
setNodeMask(Mask_RenderToTexture); setNodeMask(Mask_RenderToTexture);
@ -303,6 +304,7 @@ public:
setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
setReferenceFrame(osg::Camera::RELATIVE_RF); setReferenceFrame(osg::Camera::RELATIVE_RF);
setSmallFeatureCullingPixelSize(Settings::Manager::getInt("small feature culling pixel size", "Water"));
bool reflectActors = Settings::Manager::getBool("reflect actors", "Water"); bool reflectActors = Settings::Manager::getBool("reflect actors", "Water");

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

@ -1310,6 +1310,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) void installOpcodes (Interpreter::Interpreter& interpreter)
{ {
interpreter.installSegment5 (Compiler::Misc::opcodeXBox, new OpXBox); interpreter.installSegment5 (Compiler::Misc::opcodeXBox, new OpXBox);
@ -1406,6 +1431,8 @@ namespace MWScript
interpreter.installSegment5 (Compiler::Misc::opcodeRemoveFromLevCreature, new OpRemoveFromLevCreature); interpreter.installSegment5 (Compiler::Misc::opcodeRemoveFromLevCreature, new OpRemoveFromLevCreature);
interpreter.installSegment5 (Compiler::Misc::opcodeAddToLevItem, new OpAddToLevItem); interpreter.installSegment5 (Compiler::Misc::opcodeAddToLevItem, new OpAddToLevItem);
interpreter.installSegment5 (Compiler::Misc::opcodeRemoveFromLevItem, new OpRemoveFromLevItem); interpreter.installSegment5 (Compiler::Misc::opcodeRemoveFromLevItem, new OpRemoveFromLevItem);
interpreter.installSegment3 (Compiler::Misc::opcodeShowSceneGraph, new OpShowSceneGraph<ImplicitRef>);
interpreter.installSegment3 (Compiler::Misc::opcodeShowSceneGraphExplicit, new OpShowSceneGraph<ExplicitRef>);
} }
} }
} }

@ -152,10 +152,10 @@ namespace MWWorld
const std::vector<std::string>& contentFiles, const std::vector<std::string>& contentFiles,
ToUTF8::Utf8Encoder* encoder, const std::map<std::string,std::string>& fallbackMap, ToUTF8::Utf8Encoder* encoder, const std::map<std::string,std::string>& fallbackMap,
int activationDistanceOverride, const std::string& startCell, const std::string& startupScript, 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), : mResourceSystem(resourceSystem), mFallback(fallbackMap), mPlayer (0), mLocalScripts (mStore),
mSky (true), mCells (mStore, mEsm), mSky (true), mCells (mStore, mEsm),
mGodMode(false), mScriptsEnabled(true), mContentFiles (contentFiles), mGodMode(false), mScriptsEnabled(true), mContentFiles (contentFiles), mUserDataPath(userDataPath),
mActivationDistanceOverride (activationDistanceOverride), mStartupScript(startupScript), mActivationDistanceOverride (activationDistanceOverride), mStartupScript(startupScript),
mStartCell (startCell), mDistanceToFacedObject(-1), mTeleportEnabled(true), mStartCell (startCell), mDistanceToFacedObject(-1), mTeleportEnabled(true),
mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0) mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0)
@ -3229,6 +3229,13 @@ namespace MWWorld
return mPhysics->getHalfExtents(actor); 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) void World::spawnRandomCreature(const std::string &creatureList)
{ {
const ESM::CreatureLevList* list = getStore().get<ESM::CreatureLevList>().find(creatureList); const ESM::CreatureLevList* list = getStore().get<ESM::CreatureLevList>().find(creatureList);

@ -101,6 +101,8 @@ namespace MWWorld
bool mScriptsEnabled; bool mScriptsEnabled;
std::vector<std::string> mContentFiles; std::vector<std::string> mContentFiles;
std::string mUserDataPath;
// not implemented // not implemented
World (const World&); World (const World&);
World& operator= (const World&); World& operator= (const World&);
@ -182,7 +184,7 @@ namespace MWWorld
const Files::Collections& fileCollections, const Files::Collections& fileCollections,
const std::vector<std::string>& contentFiles, const std::vector<std::string>& contentFiles,
ToUTF8::Utf8Encoder* encoder, const std::map<std::string,std::string>& fallbackMap, 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(); virtual ~World();
@ -671,6 +673,10 @@ namespace MWWorld
/// Return physical or rendering half extents of the given actor. /// Return physical or rendering half extents of the given actor.
virtual osg::Vec3f getHalfExtents(const MWWorld::ConstPtr& actor, bool rendering=false) const; 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);
}; };
} }

@ -53,7 +53,7 @@ add_component_dir (shader
add_component_dir (sceneutil add_component_dir (sceneutil
clone attach visitor util statesetupdater controller skeleton riggeometry lightcontroller 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 add_component_dir (nif

@ -312,6 +312,8 @@ namespace Compiler
extensions.registerInstruction ("betacomment", "/S", opcodeBetaComment, opcodeBetaCommentExplicit); extensions.registerInstruction ("betacomment", "/S", opcodeBetaComment, opcodeBetaCommentExplicit);
extensions.registerInstruction ("bc", "/S", opcodeBetaComment, opcodeBetaCommentExplicit); extensions.registerInstruction ("bc", "/S", opcodeBetaComment, opcodeBetaCommentExplicit);
extensions.registerInstruction ("ori", "/S", opcodeBetaComment, opcodeBetaCommentExplicit); // 'ori' stands for 'ObjectReferenceInfo' 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 ("addtolevcreature", "ccl", opcodeAddToLevCreature);
extensions.registerInstruction ("removefromlevcreature", "ccl", opcodeRemoveFromLevCreature); extensions.registerInstruction ("removefromlevcreature", "ccl", opcodeRemoveFromLevCreature);
extensions.registerInstruction ("addtolevitem", "ccl", opcodeAddToLevItem); extensions.registerInstruction ("addtolevitem", "ccl", opcodeAddToLevItem);

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

@ -1551,7 +1551,7 @@ namespace NifOsg
case Nif::RC_NiStencilProperty: case Nif::RC_NiStencilProperty:
{ {
const Nif::NiStencilProperty* stencilprop = static_cast<const Nif::NiStencilProperty*>(property); const Nif::NiStencilProperty* stencilprop = static_cast<const Nif::NiStencilProperty*>(property);
osg::FrontFace* frontFace = new osg::FrontFace; osg::ref_ptr<osg::FrontFace> frontFace = new osg::FrontFace;
switch (stencilprop->data.drawMode) switch (stencilprop->data.drawMode)
{ {
case 2: case 2:
@ -1563,6 +1563,7 @@ namespace NifOsg
frontFace->setMode(osg::FrontFace::COUNTER_CLOCKWISE); frontFace->setMode(osg::FrontFace::COUNTER_CLOCKWISE);
break; break;
} }
frontFace = shareAttribute(frontFace);
osg::StateSet* stateset = node->getOrCreateStateSet(); osg::StateSet* stateset = node->getOrCreateStateSet();
stateset->setAttribute(frontFace, osg::StateAttribute::ON); stateset->setAttribute(frontFace, osg::StateAttribute::ON);
@ -1571,11 +1572,12 @@ namespace NifOsg
if (stencilprop->data.enabled != 0) if (stencilprop->data.enabled != 0)
{ {
osg::Stencil* stencil = new osg::Stencil; osg::ref_ptr<osg::Stencil> stencil = new osg::Stencil;
stencil->setFunction(getStencilFunction(stencilprop->data.compareFunc), stencilprop->data.stencilRef, stencilprop->data.stencilMask); stencil->setFunction(getStencilFunction(stencilprop->data.compareFunc), stencilprop->data.stencilRef, stencilprop->data.stencilMask);
stencil->setStencilFailOperation(getStencilOperation(stencilprop->data.failAction)); stencil->setStencilFailOperation(getStencilOperation(stencilprop->data.failAction));
stencil->setStencilPassAndDepthFailOperation(getStencilOperation(stencilprop->data.zFailAction)); stencil->setStencilPassAndDepthFailOperation(getStencilOperation(stencilprop->data.zFailAction));
stencil->setStencilPassAndDepthPassOperation(getStencilOperation(stencilprop->data.zPassAction)); stencil->setStencilPassAndDepthPassOperation(getStencilOperation(stencilprop->data.zPassAction));
stencil = shareAttribute(stencil);
stateset->setAttributeAndModes(stencil, osg::StateAttribute::ON); stateset->setAttributeAndModes(stencil, osg::StateAttribute::ON);
} }
@ -1584,9 +1586,10 @@ namespace NifOsg
case Nif::RC_NiWireframeProperty: case Nif::RC_NiWireframeProperty:
{ {
const Nif::NiWireframeProperty* wireprop = static_cast<const Nif::NiWireframeProperty*>(property); const Nif::NiWireframeProperty* wireprop = static_cast<const Nif::NiWireframeProperty*>(property);
osg::PolygonMode* mode = new osg::PolygonMode; osg::ref_ptr<osg::PolygonMode> mode = new osg::PolygonMode;
mode->setMode(osg::PolygonMode::FRONT_AND_BACK, wireprop->flags == 0 ? osg::PolygonMode::FILL mode->setMode(osg::PolygonMode::FRONT_AND_BACK, wireprop->flags == 0 ? osg::PolygonMode::FILL
: osg::PolygonMode::LINE); : osg::PolygonMode::LINE);
mode = shareAttribute(mode);
node->getOrCreateStateSet()->setAttributeAndModes(mode, osg::StateAttribute::ON); node->getOrCreateStateSet()->setAttributeAndModes(mode, osg::StateAttribute::ON);
break; break;
} }
@ -1594,8 +1597,12 @@ namespace NifOsg
{ {
const Nif::NiZBufferProperty* zprop = static_cast<const Nif::NiZBufferProperty*>(property); const Nif::NiZBufferProperty* zprop = static_cast<const Nif::NiZBufferProperty*>(property);
// VER_MW doesn't support a DepthFunction according to NifSkope // VER_MW doesn't support a DepthFunction according to NifSkope
osg::Depth* depth = new osg::Depth; static osg::ref_ptr<osg::Depth> depth;
depth->setWriteMask((zprop->flags>>1)&1); if (!depth)
{
depth = new osg::Depth;
depth->setWriteMask((zprop->flags>>1)&1);
}
node->getOrCreateStateSet()->setAttributeAndModes(depth, osg::StateAttribute::ON); node->getOrCreateStateSet()->setAttributeAndModes(depth, osg::StateAttribute::ON);
break; break;
} }
@ -1632,21 +1639,25 @@ namespace NifOsg
} }
} }
struct CompareMaterial struct CompareStateAttribute
{ {
bool operator() (const osg::ref_ptr<osg::Material>& left, const osg::ref_ptr<osg::Material>& right) const bool operator() (const osg::ref_ptr<osg::StateAttribute>& left, const osg::ref_ptr<osg::StateAttribute>& right) const
{ {
return left->compare(*right) < 0; return left->compare(*right) < 0;
} }
}; };
osg::Material* shareMaterial(osg::Material* mat) // global sharing of State Attributes will reduce the number of GL calls as the osg::State will check by pointer to see if state is the same
template <class Attribute>
Attribute* shareAttribute(const osg::ref_ptr<Attribute>& attr)
{ {
typedef std::set<osg::ref_ptr<osg::Material>, CompareMaterial> MatCache; typedef std::set<osg::ref_ptr<Attribute>, CompareStateAttribute> Cache;
static MatCache mats; static Cache sCache;
MatCache::iterator found = mats.find(mat); static OpenThreads::Mutex sMutex;
if (found == mats.end()) OpenThreads::ScopedLock<OpenThreads::Mutex> lock(sMutex);
found = mats.insert(mat).first; typename Cache::iterator found = sCache.find(attr);
if (found == sCache.end())
found = sCache.insert(attr).first;
return *found; return *found;
} }
@ -1713,9 +1724,10 @@ namespace NifOsg
const Nif::NiAlphaProperty* alphaprop = static_cast<const Nif::NiAlphaProperty*>(property); const Nif::NiAlphaProperty* alphaprop = static_cast<const Nif::NiAlphaProperty*>(property);
if (alphaprop->flags&1) if (alphaprop->flags&1)
{ {
stateset->setAttributeAndModes(new osg::BlendFunc(getBlendMode((alphaprop->flags>>1)&0xf), osg::ref_ptr<osg::BlendFunc> blendFunc (new osg::BlendFunc(getBlendMode((alphaprop->flags>>1)&0xf),
getBlendMode((alphaprop->flags>>5)&0xf)), getBlendMode((alphaprop->flags>>5)&0xf)));
osg::StateAttribute::ON); blendFunc = shareAttribute(blendFunc);
stateset->setAttributeAndModes(blendFunc, osg::StateAttribute::ON);
bool noSort = (alphaprop->flags>>13)&1; bool noSort = (alphaprop->flags>>13)&1;
if (!noSort) if (!noSort)
@ -1732,8 +1744,9 @@ namespace NifOsg
if((alphaprop->flags>>9)&1) if((alphaprop->flags>>9)&1)
{ {
stateset->setAttributeAndModes(new osg::AlphaFunc(getTestMode((alphaprop->flags>>10)&0x7), osg::ref_ptr<osg::AlphaFunc> alphaFunc (new osg::AlphaFunc(getTestMode((alphaprop->flags>>10)&0x7), alphaprop->data.threshold/255.f));
alphaprop->data.threshold/255.f), osg::StateAttribute::ON); alphaFunc = shareAttribute(alphaFunc);
stateset->setAttributeAndModes(alphaFunc, osg::StateAttribute::ON);
} }
else else
{ {
@ -1756,9 +1769,16 @@ namespace NifOsg
mat->setColorMode(osg::Material::AMBIENT); mat->setColorMode(osg::Material::AMBIENT);
} }
// TODO: this could be replaced by a more generic mechanism of sharing any type of State Attribute if (mat->getColorMode() == osg::Material::OFF
// apply only for Materials for now && mat->getDiffuse(osg::Material::FRONT_AND_BACK) == osg::Vec4f(1,1,1,1)
mat = shareMaterial(mat); && mat->getAmbient(osg::Material::FRONT_AND_BACK) == osg::Vec4f(1,1,1,1)
&& mat->getSpecular(osg::Material::FRONT_AND_BACK) == osg::Vec4f(0.f, 0.f, 0.f, 0.f))
{
// default state, skip
return;
}
mat = shareAttribute(mat);
stateset->setAttributeAndModes(mat, osg::StateAttribute::ON); stateset->setAttributeAndModes(mat, osg::StateAttribute::ON);
} }

@ -413,13 +413,27 @@ namespace Resource
return node; return node;
} }
class TemplateRef : public osg::Object
{
public:
TemplateRef(const Object* object)
: mObject(object) {}
TemplateRef() {}
TemplateRef(const TemplateRef& copy, const osg::CopyOp&) : mObject(copy.mObject) {}
META_Object(Resource, TemplateRef)
private:
osg::ref_ptr<const Object> mObject;
};
osg::ref_ptr<osg::Node> SceneManager::createInstance(const std::string& name) osg::ref_ptr<osg::Node> SceneManager::createInstance(const std::string& name)
{ {
osg::ref_ptr<const osg::Node> scene = getTemplate(name); osg::ref_ptr<const osg::Node> scene = getTemplate(name);
osg::ref_ptr<osg::Node> cloned = osg::clone(scene.get(), SceneUtil::CopyOp()); osg::ref_ptr<osg::Node> cloned = osg::clone(scene.get(), SceneUtil::CopyOp());
// add a ref to the original template, to hint to the cache that it's still being used and should be kept in cache // add a ref to the original template, to hint to the cache that it's still being used and should be kept in cache
cloned->getOrCreateUserDataContainer()->addUserObject(const_cast<osg::Node*>(scene.get())); cloned->getOrCreateUserDataContainer()->addUserObject(new TemplateRef(scene));
return cloned; return cloned;
} }

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

@ -32,7 +32,7 @@ namespace SceneUtil
public: public:
META_Node(SceneUtil, SceneUtil::LightSource) META_Node(SceneUtil, LightSource)
LightSource(); LightSource();
@ -79,7 +79,7 @@ namespace SceneUtil
{ {
public: public:
META_Node(SceneUtil, SceneUtil::LightManager) META_Node(SceneUtil, LightManager)
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

@ -19,10 +19,21 @@ small feature culling
:Range: True/False :Range: True/False
:Default: True :Default: True
This boolean setting determines whether objects that render to a few pixels or smaller will be culled (not drawn). It generally improves performance to enable this feature, and by definition the culled objects will be very small on screen. It appears that the default definition of "small" in OpenSceneGraph is 2x2 pixels. This boolean setting determines whether objects that render to a few pixels or smaller will be culled (not drawn). It generally improves performance to enable this feature, and by definition the culled objects will be very small on screen. The size in pixels for an object to be considered 'small' is controlled by a separate setting.
The default value is true. This setting can only be configured by editing the settings configuration file. The default value is true. This setting can only be configured by editing the settings configuration file.
small feature culling pixel size
---------------------
:Type: floating point
:Range: > 0
:Default: 2.0
Controls the cutoff in pixels for the 'small feature culling' setting which will have no effect if 'small feature culling' is disabled.
This setting can only be configured by editing the settings configuration file.
viewing distance viewing distance
---------------- ----------------
@ -72,4 +83,4 @@ first person field of view
The floating point setting controls the field of view for first person meshes such as the player's hands and held objects. It is not recommended to change this value from its default value because the Bethesda provided Morrowind assets do not adapt well to large values, while small values can result in the hands not being visible. The floating point setting controls the field of view for first person meshes such as the player's hands and held objects. It is not recommended to change this value from its default value because the Bethesda provided Morrowind assets do not adapt well to large values, while small values can result in the hands not being visible.
The default value is 55.0. This setting can only be configured by editing the settings configuration file. The default value is 55.0. This setting can only be configured by editing the settings configuration file.

@ -40,4 +40,19 @@ This boolean setting enables the refraction rendering feature of the water shade
This setting has no effect if the shader setting is false. This setting has no effect if the shader setting is false.
The default setting is false. This setting can be toggled with the Refraction button in the Water tab of the Video panel of the Options menu. The default setting is false. This setting can be toggled with the Refraction button in the Water tab of the Video panel of the Options menu.
small feature culling pixel size
--------------------------------
:Type: floating point
:Range: > 0
:Default: 20.0
Controls the cutoff in pixels for small feature culling - see the 'Camera' section for more details, however this setting in the 'Water' section applies specifically to objects rendered in water reflection and refraction textures.
The setting 'rtt size' interacts with this setting because it controls how large a pixel on the water texture (technically called a texel) is in pixels on the screen.
This setting will have no effect if the shader setting is false, or the 'small feature culling' (in the 'Camera' section) is disabled.
This setting can only be configured by editing the settings configuration file.

@ -16,9 +16,11 @@
# Near clipping plane (>0.0, e.g. 0.01 to 18.0). # Near clipping plane (>0.0, e.g. 0.01 to 18.0).
near clip = 1 near clip = 1
# Cull objects smaller than one pixel. # Cull objects that occupy less than 'small feature culling pixel size' on the screen.
small feature culling = true small feature culling = true
small feature culling pixel size = 2.0
# Maximum visible distance (e.g. 2000.0 to 6666.0). Caution: this setting # Maximum visible distance (e.g. 2000.0 to 6666.0). Caution: this setting
# can dramatically affect performance, see documentation for details. # can dramatically affect performance, see documentation for details.
viewing distance = 6666.0 viewing distance = 6666.0
@ -338,6 +340,9 @@ refraction = false
# Draw NPCs and creatures on water reflections. # Draw NPCs and creatures on water reflections.
reflect actors = false reflect actors = false
# Overrides the value in '[Camera] small feature culling pixel size' specifically for water reflection/refraction textures.
small feature culling pixel size = 20.0
[Windows] [Windows]
# Location and sizes of windows as a fraction of the OpenMW window or # Location and sizes of windows as a fraction of the OpenMW window or

Loading…
Cancel
Save