Merge pull request #177 from OpenMW/master

Add OpenMW commits up to 1 Mar 2017
0.6.1
David Cernat 8 years ago committed by GitHub
commit db8218545f

@ -192,24 +192,38 @@ namespace
};
// Removes all drawables from a graph.
class RemoveDrawableVisitor : public RemoveVisitor
class CleanObjectRootVisitor : public RemoveVisitor
{
public:
virtual void apply(osg::Drawable& drw)
{
applyImpl(drw);
applyDrawable(drw);
}
virtual void apply(osg::Group& node)
{
traverse(node);
applyNode(node);
}
virtual void apply(osg::MatrixTransform& node)
{
traverse(node);
applyNode(node);
}
virtual void apply(osg::Node& node)
{
applyNode(node);
}
void applyImpl(osg::Node& node)
void applyNode(osg::Node& node)
{
if (node.getStateSet())
node.setStateSet(NULL);
if (node.getNodeMask() == 0x1 && node.getNumParents() == 1)
mToRemove.push_back(std::make_pair(&node, node.getParent(0)));
else
traverse(node);
}
void applyDrawable(osg::Node& node)
{
osg::NodePath::iterator parent = getNodePath().end()-2;
// We know that the parent is a Group because only Groups can have children.
@ -1123,6 +1137,32 @@ namespace MWRender
state->second.mLoopingEnabled = enabled;
}
osg::ref_ptr<osg::Node> getModelInstance(Resource::SceneManager* sceneMgr, const std::string& model, bool baseonly)
{
if (baseonly)
{
typedef std::map<std::string, osg::ref_ptr<osg::Node> > Cache;
static Cache cache;
Cache::iterator found = cache.find(model);
if (found == cache.end())
{
osg::ref_ptr<osg::Node> created = sceneMgr->getInstance(model);
CleanObjectRootVisitor removeDrawableVisitor;
created->accept(removeDrawableVisitor);
removeDrawableVisitor.remove();
cache.insert(std::make_pair(model, created));
return sceneMgr->createInstance(created);
}
else
return sceneMgr->createInstance(found->second);
}
else
return sceneMgr->createInstance(model);
}
void Animation::setObjectRoot(const std::string &model, bool forceskeleton, bool baseonly, bool isCreature)
{
osg::ref_ptr<osg::StateSet> previousStateset;
@ -1144,7 +1184,8 @@ namespace MWRender
if (!forceskeleton)
{
osg::ref_ptr<osg::Node> created = mResourceSystem->getSceneManager()->getInstance(model, mInsert);
osg::ref_ptr<osg::Node> created = getModelInstance(mResourceSystem->getSceneManager(), model, baseonly);
mInsert->addChild(created);
mObjectRoot = created->asGroup();
if (!mObjectRoot)
{
@ -1156,7 +1197,7 @@ namespace MWRender
}
else
{
osg::ref_ptr<osg::Node> created = mResourceSystem->getSceneManager()->getInstance(model);
osg::ref_ptr<osg::Node> created = getModelInstance(mResourceSystem->getSceneManager(), model, baseonly);
osg::ref_ptr<SceneUtil::Skeleton> skel = dynamic_cast<SceneUtil::Skeleton*>(created.get());
if (!skel)
{
@ -1171,13 +1212,6 @@ namespace MWRender
if (previousStateset)
mObjectRoot->setStateSet(previousStateset);
if (baseonly)
{
RemoveDrawableVisitor removeDrawableVisitor;
mObjectRoot->accept(removeDrawableVisitor);
removeDrawableVisitor.remove();
}
if (isCreature)
{
RemoveTriBipVisitor removeTriBipVisitor;

@ -538,10 +538,15 @@ namespace Resource
osg::ref_ptr<osg::Node> SceneManager::createInstance(const std::string& name)
{
osg::ref_ptr<const osg::Node> scene = getTemplate(name);
osg::ref_ptr<osg::Node> cloned = osg::clone(scene.get(), SceneUtil::CopyOp());
return createInstance(scene);
}
osg::ref_ptr<osg::Node> SceneManager::createInstance(const osg::Node *base)
{
osg::ref_ptr<osg::Node> cloned = osg::clone(base, 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
cloned->getOrCreateUserDataContainer()->addUserObject(new TemplateRef(scene));
cloned->getOrCreateUserDataContainer()->addUserObject(new TemplateRef(base));
// we can skip any scene graphs without update callbacks since we know that particle emitters will have an update callback set
if (cloned->getNumChildrenRequiringUpdateTraversal() > 0)

@ -93,6 +93,10 @@ namespace Resource
/// @note Thread safe.
osg::ref_ptr<osg::Node> cacheInstance(const std::string& name);
osg::ref_ptr<osg::Node> createInstance(const std::string& name);
osg::ref_ptr<osg::Node> createInstance(const osg::Node* base);
/// Get an instance of the given scene template
/// @see getTemplate
/// @note Thread safe.
@ -141,8 +145,6 @@ namespace Resource
private:
osg::ref_ptr<osg::Node> createInstance(const std::string& name);
std::auto_ptr<Shader::ShaderManager> mShaderManager;
bool mForceShaders;
bool mClampLighting;

@ -317,34 +317,43 @@ namespace Shader
{
const ShaderRequirements& reqs = mRequirements.back();
osg::ref_ptr<osg::Geometry> sourceGeometry = &geometry;
SceneUtil::RigGeometry* rig = dynamic_cast<SceneUtil::RigGeometry*>(&geometry);
if (rig)
sourceGeometry = rig->getSourceGeometry();
bool useShader = reqs.mShaderRequired || mForceShaders;
bool generateTangents = reqs.mTexStageRequiringTangents != -1;
if (mAllowedToModifyStateSets)
if (mAllowedToModifyStateSets && (useShader || generateTangents))
{
osg::ref_ptr<osg::Geometry> sourceGeometry = &geometry;
SceneUtil::RigGeometry* rig = dynamic_cast<SceneUtil::RigGeometry*>(&geometry);
if (rig)
sourceGeometry = rig->getSourceGeometry();
bool requiresSetGeometry = false;
// make sure that all UV sets are there
for (std::map<int, std::string>::const_iterator it = reqs.mTextures.begin(); it != reqs.mTextures.end(); ++it)
{
if (sourceGeometry->getTexCoordArray(it->first) == NULL)
{
sourceGeometry->setTexCoordArray(it->first, sourceGeometry->getTexCoordArray(0));
requiresSetGeometry = true;
}
}
}
if (reqs.mTexStageRequiringTangents != -1 && mAllowedToModifyStateSets)
{
osg::ref_ptr<osgUtil::TangentSpaceGenerator> generator (new osgUtil::TangentSpaceGenerator);
generator->generate(sourceGeometry, reqs.mTexStageRequiringTangents);
if (generateTangents)
{
osg::ref_ptr<osgUtil::TangentSpaceGenerator> generator (new osgUtil::TangentSpaceGenerator);
generator->generate(sourceGeometry, reqs.mTexStageRequiringTangents);
sourceGeometry->setTexCoordArray(7, generator->getTangentArray(), osg::Array::BIND_PER_VERTEX);
}
sourceGeometry->setTexCoordArray(7, generator->getTangentArray(), osg::Array::BIND_PER_VERTEX);
requiresSetGeometry = true;
}
if (rig)
rig->setSourceGeometry(sourceGeometry);
if (rig && requiresSetGeometry)
rig->setSourceGeometry(sourceGeometry);
}
// TODO: find a better place for the stateset
if (reqs.mShaderRequired || mForceShaders)
if (useShader)
createProgram(reqs, geometry);
}

Loading…
Cancel
Save