Refactor LOD to allow parenting

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@14853 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria
2013-12-31 18:09:13 +00:00
parent 9fbd2b19b1
commit 3cdf3409bf
6 changed files with 93 additions and 70 deletions

View File

@@ -43,7 +43,7 @@ bool PairCompare(const std::pair<int, LodModel>& i, const std::pair<int, LodMode
// ----------------------------------------------------------------------------
/** Check a XML node in case it contains a LOD object and if so remember it */
bool LodNodeLoader::check(const XMLNode* xml)
bool LodNodeLoader::check(const XMLNode* xml, scene::ISceneNode* parent)
{
float lod_distance = -1.0f;
xml->get("lod_distance", &lod_distance);
@@ -61,7 +61,7 @@ bool LodNodeLoader::check(const XMLNode* xml)
{
if (lod_instance)
{
lod_instances[lodgroup].push_back(xml);
lod_instances[lodgroup].push_back(LodInstance(xml, parent));
}
else
{
@@ -88,11 +88,9 @@ bool LodNodeLoader::check(const XMLNode* xml)
void LodNodeLoader::done(Track* track,
std::string directory,
std::vector<scene::IMesh*>& cache,
scene::ISceneNode* parent,
std::vector<LODNode*>& out)
{
scene::ISceneManager* sm = irr_driver->getSceneManager();
if (parent == NULL) parent = sm->getRootSceneNode();
// Creating LOD nodes is more complicated than one might have hoped, on the C++ side;
// but it was done this way to minimize the work needed on the side of the artists
@@ -120,15 +118,15 @@ void LodNodeLoader::done(Track* track,
// 2. Read the XML nodes and instanciate LOD scene nodes where relevant
std::string groupname;
std::map< std::string, std::vector< const XMLNode* > >::iterator it3;
std::map< std::string, std::vector< LodInstance > >::iterator it3;
for (it3 = lod_instances.begin(); it3 != lod_instances.end(); it3++)
{
std::vector< std::pair<int, LodModel> >& group = sorted_lod_groups[it3->first];
std::vector< const XMLNode* >& v = it3->second;
std::vector< LodInstance >& v = it3->second;
for (unsigned int n=0; n<v.size(); n++)
{
const XMLNode* node = v[n];
const XMLNode* node = v[n].m_xml_node;
groupname = "";
node->get("lod_group", &groupname);
@@ -141,10 +139,9 @@ void LodNodeLoader::done(Track* track,
core::vector3df scale(1.0f, 1.0f, 1.0f);
node->get("scale", &scale);
std::string full_path;
if (group.size() > 0)
{
scene::ISceneNode* parent = (v[n].m_parent == NULL ? sm->getRootSceneNode() : v[n].m_parent);
LODNode* lod_node = new LODNode(groupname, parent, sm);
lod_node->setPosition(xyz);
lod_node->setRotation(hpr);
@@ -158,7 +155,7 @@ void LodNodeLoader::done(Track* track,
if (!a_mesh)
{
Log::warn("LODNodeLoad", "Warning: object model '%s' not found, ignored.\n",
full_path.c_str());
group[m].second.m_model_file.c_str());
continue;
}

View File

@@ -36,6 +36,25 @@ namespace irr
}
}
struct LodInstance
{
const XMLNode* m_xml_node;
scene::ISceneNode* m_parent;
/** Constructor to allow storing this in STL containers */
LodInstance()
{
m_parent = NULL;
m_xml_node = NULL;
}
LodInstance(const XMLNode* xml_node, scene::ISceneNode* parent)
{
m_xml_node = xml_node;
m_parent = parent;
}
};
struct LodModel
{
std::string m_model_file;
@@ -68,16 +87,15 @@ class LodNodeLoader
{
private:
std::map< std::string, std::map< int, LodModel > > lod_groups;
std::map< std::string, std::vector< const XMLNode* > > lod_instances;
std::map< std::string, std::vector< LodInstance > > lod_instances;
public:
LodNodeLoader();
bool check(const XMLNode* xml);
bool check(const XMLNode* xml, scene::ISceneNode* parent);
void done(Track* track,
std::string directory,
std::vector<irr::scene::IMesh*>& cache,
scene::ISceneNode* parent,
std::vector<LODNode*>& out);
void clear();

View File

@@ -1016,7 +1016,7 @@ bool Track::loadMainTrack(const XMLNode &root)
std::string challenge;
n->get("challenge", &challenge);
bool is_lod = lodLoader.check(n);
bool is_lod = lodLoader.check(n, NULL);
if (tangent)
{
@@ -1183,7 +1183,7 @@ bool Track::loadMainTrack(const XMLNode &root)
// Create LOD nodes
std::vector<LODNode*> lod_nodes;
lodLoader.done(this, m_root, m_all_cached_meshes, NULL, lod_nodes);
lodLoader.done(this, m_root, m_all_cached_meshes, lod_nodes);
for (unsigned int n=0; n<lod_nodes.size(); n++)
{
// FIXME: support for animated textures on LOD objects
@@ -1513,7 +1513,45 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
loadMainTrack(*root);
unsigned int main_track_count = m_all_nodes.size();
loadObjects(root, path, true, NULL);
LodNodeLoader lod_loader;
std::map<std::string, XMLNode*> library_nodes;
loadObjects(root, path, lod_loader, true, NULL, library_nodes);
// -------- Create and assign LOD nodes --------
// recheck the static area, we will need LOD info
const XMLNode* track_node = root->getNode("track");
if (track_node != NULL)
{
for (unsigned int i=0; i<track_node->getNumNodes(); i++)
{
const XMLNode* n = track_node->getNode(i);
bool is_instance = false;
n->get("lod_instance", &is_instance);
if (!is_instance) lod_loader.check(n, NULL);
}
}
std::vector<LODNode*> lod_nodes;
std::vector<scene::IMesh*> devnull;
lod_loader.done(this, m_root, devnull, lod_nodes);
m_track_object_manager->assingLodNodes(lod_nodes);
// ---------------------------------------------
// Cleanup library nodes
for (std::map<std::string, XMLNode*>::iterator it = library_nodes.begin();
it != library_nodes.end(); it++)
{
delete it->second;
file_manager->popTextureSearchPath();
file_manager->popModelSearchPath();
}
// Init all track objects
m_track_object_manager->init();
// ---- Fog
// It's important to execute this BEFORE the code that creates the skycube,
@@ -1665,14 +1703,12 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
//-----------------------------------------------------------------------------
void Track::loadObjects(const XMLNode* root, const std::string& path,
bool create_lod_definitions, scene::ISceneNode* parent)
void Track::loadObjects(const XMLNode* root, const std::string& path, LodNodeLoader& lod_loader,
bool create_lod_definitions, scene::ISceneNode* parent,
std::map<std::string, XMLNode*>& library_nodes)
{
LodNodeLoader lod_loader;
unsigned int start_position_counter = 0;
std::map<std::string, XMLNode*> library_nodes;
unsigned int node_count = root->getNumNodes();
for (unsigned int i = 0; i < node_count; i++)
{
@@ -1693,11 +1729,11 @@ void Track::loadObjects(const XMLNode* root, const std::string& path,
{
// lod definition
if (create_lod_definitions)
lod_loader.check(node);
lod_loader.check(node, parent);
}
else
{
lod_loader.check(node);
lod_loader.check(node, parent);
}
m_track_object_manager->add(*node, parent);
}
@@ -1715,28 +1751,29 @@ void Track::loadObjects(const XMLNode* root, const std::string& path,
if (library_nodes.find(name) == library_nodes.end())
{
std::string lib_node_path = file_manager->getAsset("library/" + name + "/node.xml");
std::string node_path = "library/" + name + "/node.xml";
std::string lib_node_path = file_manager->getAsset(node_path);
libroot = file_manager->createXMLTree(lib_node_path);
if (libroot == NULL) continue;
if (libroot == NULL)
{
Log::error("Track", "Cannot find library '%s'", node_path.c_str());
continue;
}
file_manager->pushTextureSearchPath(lib_path + "/");
file_manager->pushModelSearchPath (lib_path);
library_nodes[name] = libroot;
}
else
{
libroot = library_nodes[name];
create_lod_definitions = false; // LOD definitions are already created, don't create them again
}
library_nodes[name] = libroot;
file_manager->pushTextureSearchPath(lib_path + "/");
file_manager->pushModelSearchPath (lib_path);
scene::ISceneNode* parent = irr_driver->getSceneManager()->addEmptySceneNode();
parent->setPosition(xyz);
parent->updateAbsolutePosition();
loadObjects(libroot, lib_path, create_lod_definitions, parent);
file_manager->popTextureSearchPath();
file_manager->popModelSearchPath();
loadObjects(libroot, lib_path, lod_loader, create_lod_definitions, parent, library_nodes);
}
else if (name == "water")
{
@@ -1854,37 +1891,6 @@ void Track::loadObjects(const XMLNode* root, const std::string& path,
}
} // for i<root->getNumNodes()
// -------- Create and assign LOD nodes --------
// recheck the static area, we will need LOD info
const XMLNode* track_node = root->getNode("track");
if (track_node != NULL)
{
for (unsigned int i=0; i<track_node->getNumNodes(); i++)
{
const XMLNode* n = track_node->getNode(i);
bool is_instance = false;
n->get("lod_instance", &is_instance);
if (!is_instance && create_lod_definitions) lod_loader.check(n);
}
}
std::vector<LODNode*> lod_nodes;
std::vector<scene::IMesh*> devnull;
lod_loader.done(this, m_root, devnull, parent, lod_nodes);
m_track_object_manager->assingLodNodes(lod_nodes, parent);
// ---------------------------------------------
// Init all track objects
m_track_object_manager->init();
for (std::map<std::string, XMLNode*>::iterator it = library_nodes.begin();
it != library_nodes.end(); it++)
{
delete it->second;
}
}
//-----------------------------------------------------------------------------

View File

@@ -35,6 +35,7 @@ namespace irr
namespace scene { class IMesh; class ILightSceneNode; }
}
using namespace irr;
class LodNodeLoader;
#include "LinearMath/btTransform.h"
@@ -399,8 +400,9 @@ private:
std::vector<MusicInformation*>& m_music );
void loadCurves(const XMLNode &node);
void handleSky(const XMLNode &root, const std::string &filename);
void loadObjects(const XMLNode* root, const std::string& path,
bool create_lod_definitions, scene::ISceneNode* parent);
void loadObjects(const XMLNode* root, const std::string& path, LodNodeLoader& lod_loader,
bool create_lod_definitions, scene::ISceneNode* parent,
std::map<std::string, XMLNode*>& library_nodes);
public:

View File

@@ -218,7 +218,7 @@ void TrackObjectManager::removeObject(TrackObject* obj)
*
* \param lod_nodes the LOD nodes created by the LodNodeLoader.
*/
void TrackObjectManager::assingLodNodes(const std::vector<LODNode*>& lod_nodes, scene::ISceneNode* parent)
void TrackObjectManager::assingLodNodes(const std::vector<LODNode*>& lod_nodes)
{
for (unsigned int n=0; n<lod_nodes.size(); n++)
{
@@ -226,7 +226,7 @@ void TrackObjectManager::assingLodNodes(const std::vector<LODNode*>& lod_nodes,
assert( queue.size() > 0 );
const XMLNode* xml = queue[ queue.size() - 1 ];
TrackObject* obj = new TrackObject(*xml, parent, lod_nodes[n]);
TrackObject* obj = new TrackObject(*xml, lod_nodes[n]->getParent(), lod_nodes[n]);
queue.erase( queue.end() - 1 );
m_all_objects.push_back(obj);

View File

@@ -68,7 +68,7 @@ public:
void removeObject(TrackObject* who);
void assingLodNodes(const std::vector<LODNode*>& lod, scene::ISceneNode* parent);
void assingLodNodes(const std::vector<LODNode*>& lod);
PtrVector<TrackObject>& getObjects() { return m_all_objects; }
const PtrVector<TrackObject>& getObjects() const { return m_all_objects; }