// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
+
#include "ModelRegistry.hxx"
#include <algorithm>
#include <simgear/props/props_io.hxx>
#include <simgear/props/condition.hxx>
+#include "BoundingVolumeBuildVisitor.hxx"
+
using namespace std;
using namespace osg;
using namespace osgUtil;
FilePathList _pathList;
};
+// Create new userdata structs in a copied model.
+// The BVH trees are shared with the original model, but the velocity fields
+// should usually be distinct fields for distinct models.
+class UserDataCopyVisitor : public osg::NodeVisitor {
+public:
+ UserDataCopyVisitor() :
+ osg::NodeVisitor(osg::NodeVisitor::NODE_VISITOR,
+ osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
+ {
+ }
+ virtual void apply(osg::Node& node)
+ {
+ osg::ref_ptr<SGSceneUserData> userData;
+ userData = SGSceneUserData::getSceneUserData(&node);
+ if (userData.valid()) {
+ SGSceneUserData* newUserData = new SGSceneUserData(*userData);
+ newUserData->setVelocity(0);
+ node.setUserData(newUserData);
+ }
+ node.traverse(*this);
+ }
+};
class SGTexCompressionVisitor : public SGTextureStateAttributeVisitor {
public:
if (!texture)
return;
- // Hmm, true??
- texture->setDataVariance(osg::Object::STATIC);
+ // Do not touch dynamically generated textures.
+ if (texture->getReadPBuffer())
+ return;
+ if (texture->getDataVariance() == osg::Object::DYNAMIC)
+ return;
+ // If no image attached, we assume this one is dynamically generated
Image* image = texture->getImage(0);
if (!image)
return;
if (!texture)
return;
+ // Cannot be static if this is a render to texture thing
+ if (texture->getReadPBuffer())
+ return;
+ if (texture->getDataVariance() == osg::Object::DYNAMIC)
+ return;
+ // If no image attached, we assume this one is dynamically generated
+ Image* image = texture->getImage(0);
+ if (!image)
+ return;
+
texture->setDataVariance(Object::STATIC);
}
{
if (!stateSet)
return;
- SGTextureStateAttributeVisitor::apply(stateSet);
stateSet->setDataVariance(Object::STATIC);
- }
-};
-
-class SGAcMaterialCrippleVisitor : public SGStateAttributeVisitor {
-public:
- virtual void apply(StateSet::RefAttributePair& refAttr)
- {
- Material* material;
- material = dynamic_cast<Material*>(refAttr.first.get());
- if (!material)
- return;
- material->setColorMode(Material::AMBIENT_AND_DIFFUSE);
+ SGTextureStateAttributeVisitor::apply(stateSet);
}
};
}
osg::Node* DefaultCopyPolicy::copy(osg::Node* model, const string& fileName,
- const osgDB::ReaderWriter::Options* opt)
+ const osgDB::ReaderWriter::Options* opt)
{
// Add an extra reference to the model stored in the database.
- // That it to avoid expiring the object from the cache even if it is still
+ // That is to avoid expiring the object from the cache even if it is still
// in use. Note that the object cache will think that a model is unused
// if the reference count is 1. If we clone all structural nodes here
// we need that extra reference to the original object
TextureUpdateVisitor liveryUpdate(opt->getDatabasePathList());
res->accept(liveryUpdate);
+ // Copy the userdata fields, still sharing the boundingvolumes,
+ // but introducing new data for velocities.
+ UserDataCopyVisitor userDataCopyVisitor;
+ res->accept(userDataCopyVisitor);
+
return res;
}
return absFileName;
}
+
+void
+BuildLeafBVHPolicy::buildBVH(const std::string& fileName, osg::Node* node)
+{
+ SG_LOG(SG_IO, SG_INFO, "Building leaf attached boundingvolume tree for \""
+ << fileName << "\".");
+ BoundingVolumeBuildVisitor bvBuilder(true);
+ node->accept(bvBuilder);
+}
+
+void
+BuildGroupBVHPolicy::buildBVH(const std::string& fileName, osg::Node* node)
+{
+ SG_LOG(SG_IO, SG_INFO, "Building group attached boundingvolume tree for \""
+ << fileName << "\".");
+ BoundingVolumeBuildVisitor bvBuilder(false);
+ node->accept(bvBuilder);
+}
+
+void
+NoBuildBVHPolicy::buildBVH(const std::string& fileName, osg::Node*)
+{
+ SG_LOG(SG_IO, SG_INFO, "Omitting boundingvolume tree for \""
+ << fileName << "\".");
+}
+
ModelRegistry::ModelRegistry() :
_defaultCallback(new DefaultCallback(""))
{
const ReaderWriter::Options* opt)
{
ScopedLock<ReentrantMutex> lock(readerMutex);
+
// XXX Workaround for OSG plugin bug.
Registry* registry = Registry::instance();
ReaderWriter::ReadResult res;
- Node* cached = 0;
CallbackMap::iterator iter
= nodeCallbackMap.find(getFileExtension(fileName));
+ ReaderWriter::ReadResult result;
if (iter != nodeCallbackMap.end() && iter->second.valid())
- return iter->second->readNode(fileName, opt);
- return _defaultCallback->readNode(fileName, opt);
+ result = iter->second->readNode(fileName, opt);
+ else
+ result = _defaultCallback->readNode(fileName, opt);
+
+ return result;
}
class SGReadCallbackInstaller {
transform->setDataVariance(Object::STATIC);
transform->setMatrix(m);
transform->addChild(node);
- // Ok, this step is questionable.
- // It is there to have the same visual appearance of ac objects for the
- // first cut. Osg's ac3d loader will correctly set materials from the
- // ac file. But the old plib loader used GL_AMBIENT_AND_DIFFUSE for the
- // materials that in effect igored the ambient part specified in the
- // file. We emulate that for the first cut here by changing all
- // ac models here. But in the long term we should use the
- // unchanged model and fix the input files instead ...
- SGAcMaterialCrippleVisitor matCriple;
- root->accept(matCriple);
+
return root;
}
};
typedef ModelRegistryCallback<ACProcessPolicy, DefaultCachePolicy,
ACOptimizePolicy, DefaultCopyPolicy,
- OSGSubstitutePolicy> ACCallback;
+ OSGSubstitutePolicy, BuildLeafBVHPolicy>
+ACCallback;
namespace
{