forked from teamnwah/openmw-tes3coop
Merge pull request #177 from OpenMW/master
Add OpenMW commits up to 1 Mar 2017
This commit is contained in:
commit
db8218545f
4 changed files with 85 additions and 35 deletions
|
@ -192,24 +192,38 @@ namespace
|
||||||
};
|
};
|
||||||
|
|
||||||
// Removes all drawables from a graph.
|
// Removes all drawables from a graph.
|
||||||
class RemoveDrawableVisitor : public RemoveVisitor
|
class CleanObjectRootVisitor : public RemoveVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void apply(osg::Drawable& drw)
|
virtual void apply(osg::Drawable& drw)
|
||||||
{
|
{
|
||||||
applyImpl(drw);
|
applyDrawable(drw);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(osg::Group& node)
|
virtual void apply(osg::Group& node)
|
||||||
{
|
{
|
||||||
traverse(node);
|
applyNode(node);
|
||||||
}
|
}
|
||||||
virtual void apply(osg::MatrixTransform& 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;
|
osg::NodePath::iterator parent = getNodePath().end()-2;
|
||||||
// We know that the parent is a Group because only Groups can have children.
|
// We know that the parent is a Group because only Groups can have children.
|
||||||
|
@ -1123,6 +1137,32 @@ namespace MWRender
|
||||||
state->second.mLoopingEnabled = enabled;
|
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)
|
void Animation::setObjectRoot(const std::string &model, bool forceskeleton, bool baseonly, bool isCreature)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::StateSet> previousStateset;
|
osg::ref_ptr<osg::StateSet> previousStateset;
|
||||||
|
@ -1144,7 +1184,8 @@ namespace MWRender
|
||||||
|
|
||||||
if (!forceskeleton)
|
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();
|
mObjectRoot = created->asGroup();
|
||||||
if (!mObjectRoot)
|
if (!mObjectRoot)
|
||||||
{
|
{
|
||||||
|
@ -1156,7 +1197,7 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
else
|
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());
|
osg::ref_ptr<SceneUtil::Skeleton> skel = dynamic_cast<SceneUtil::Skeleton*>(created.get());
|
||||||
if (!skel)
|
if (!skel)
|
||||||
{
|
{
|
||||||
|
@ -1171,13 +1212,6 @@ namespace MWRender
|
||||||
if (previousStateset)
|
if (previousStateset)
|
||||||
mObjectRoot->setStateSet(previousStateset);
|
mObjectRoot->setStateSet(previousStateset);
|
||||||
|
|
||||||
if (baseonly)
|
|
||||||
{
|
|
||||||
RemoveDrawableVisitor removeDrawableVisitor;
|
|
||||||
mObjectRoot->accept(removeDrawableVisitor);
|
|
||||||
removeDrawableVisitor.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCreature)
|
if (isCreature)
|
||||||
{
|
{
|
||||||
RemoveTriBipVisitor removeTriBipVisitor;
|
RemoveTriBipVisitor removeTriBipVisitor;
|
||||||
|
|
|
@ -538,10 +538,15 @@ namespace Resource
|
||||||
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());
|
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
|
// 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
|
// 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)
|
if (cloned->getNumChildrenRequiringUpdateTraversal() > 0)
|
||||||
|
|
|
@ -93,6 +93,10 @@ namespace Resource
|
||||||
/// @note Thread safe.
|
/// @note Thread safe.
|
||||||
osg::ref_ptr<osg::Node> cacheInstance(const std::string& name);
|
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
|
/// Get an instance of the given scene template
|
||||||
/// @see getTemplate
|
/// @see getTemplate
|
||||||
/// @note Thread safe.
|
/// @note Thread safe.
|
||||||
|
@ -141,8 +145,6 @@ namespace Resource
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
osg::ref_ptr<osg::Node> createInstance(const std::string& name);
|
|
||||||
|
|
||||||
std::auto_ptr<Shader::ShaderManager> mShaderManager;
|
std::auto_ptr<Shader::ShaderManager> mShaderManager;
|
||||||
bool mForceShaders;
|
bool mForceShaders;
|
||||||
bool mClampLighting;
|
bool mClampLighting;
|
||||||
|
|
|
@ -317,34 +317,43 @@ namespace Shader
|
||||||
{
|
{
|
||||||
const ShaderRequirements& reqs = mRequirements.back();
|
const ShaderRequirements& reqs = mRequirements.back();
|
||||||
|
|
||||||
|
bool useShader = reqs.mShaderRequired || mForceShaders;
|
||||||
|
bool generateTangents = reqs.mTexStageRequiringTangents != -1;
|
||||||
|
|
||||||
|
if (mAllowedToModifyStateSets && (useShader || generateTangents))
|
||||||
|
{
|
||||||
osg::ref_ptr<osg::Geometry> sourceGeometry = &geometry;
|
osg::ref_ptr<osg::Geometry> sourceGeometry = &geometry;
|
||||||
SceneUtil::RigGeometry* rig = dynamic_cast<SceneUtil::RigGeometry*>(&geometry);
|
SceneUtil::RigGeometry* rig = dynamic_cast<SceneUtil::RigGeometry*>(&geometry);
|
||||||
if (rig)
|
if (rig)
|
||||||
sourceGeometry = rig->getSourceGeometry();
|
sourceGeometry = rig->getSourceGeometry();
|
||||||
|
|
||||||
if (mAllowedToModifyStateSets)
|
bool requiresSetGeometry = false;
|
||||||
{
|
|
||||||
// make sure that all UV sets are there
|
// 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)
|
for (std::map<int, std::string>::const_iterator it = reqs.mTextures.begin(); it != reqs.mTextures.end(); ++it)
|
||||||
{
|
{
|
||||||
if (sourceGeometry->getTexCoordArray(it->first) == NULL)
|
if (sourceGeometry->getTexCoordArray(it->first) == NULL)
|
||||||
|
{
|
||||||
sourceGeometry->setTexCoordArray(it->first, sourceGeometry->getTexCoordArray(0));
|
sourceGeometry->setTexCoordArray(it->first, sourceGeometry->getTexCoordArray(0));
|
||||||
|
requiresSetGeometry = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reqs.mTexStageRequiringTangents != -1 && mAllowedToModifyStateSets)
|
if (generateTangents)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osgUtil::TangentSpaceGenerator> generator (new osgUtil::TangentSpaceGenerator);
|
osg::ref_ptr<osgUtil::TangentSpaceGenerator> generator (new osgUtil::TangentSpaceGenerator);
|
||||||
generator->generate(sourceGeometry, reqs.mTexStageRequiringTangents);
|
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)
|
if (rig && requiresSetGeometry)
|
||||||
rig->setSourceGeometry(sourceGeometry);
|
rig->setSourceGeometry(sourceGeometry);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: find a better place for the stateset
|
// TODO: find a better place for the stateset
|
||||||
if (reqs.mShaderRequired || mForceShaders)
|
if (useShader)
|
||||||
createProgram(reqs, geometry);
|
createProgram(reqs, geometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue