Remove the old LOD loading code, we now support only the new much cleaner way. Will need to re-export all tracks that use LOD, meanwhile LOD objects will be missing from tracks

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@14879 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria 2014-01-01 21:18:06 +00:00
parent 9fe6b6a6e9
commit 0f97aee66a
9 changed files with 129 additions and 262 deletions

View File

@ -29,174 +29,104 @@ using namespace irr;
#include <IMeshManipulator.h>
#include <algorithm>
LodNodeLoader::LodNodeLoader()
LodNodeLoader::LodNodeLoader(Track* track)
{
m_track = track;
}
// ----------------------------------------------------------------------------
bool PairCompare(const std::pair<int, LodModel>& i, const std::pair<int, LodModel>& j)
{
return (i.first < j.first);
}
// ----------------------------------------------------------------------------
/** Check a XML node in case it contains a LOD object and if so remember it */
bool LodNodeLoader::check(const XMLNode* xml, scene::ISceneNode* parent)
void LodNodeLoader::addLODModelDefinition(const XMLNode* xml)
{
float lod_distance = -1.0f;
xml->get("lod_distance", &lod_distance);
bool lod_instance = false;
xml->get("lod_instance", &lod_instance);
std::string lodgroup;
xml->get("lod_group", &lodgroup);
bool tangent = false;
xml->get("tangents", &tangent);
if (!lodgroup.empty())
{
if (lod_instance)
{
lod_instances[lodgroup].push_back(LodInstance(xml, parent));
}
else
{
std::string model_name;
xml->get("model", &model_name);
std::string model_name;
xml->get("model", &model_name);
lod_groups[lodgroup][(int)lod_distance] = LodModel(xml, model_name, tangent);
}
return true;
}
else
{
return false;
}
m_lod_groups[lodgroup].push_back(LodModel(xml, (int)lod_distance, model_name, tangent));
}
// ----------------------------------------------------------------------------
/**
* Call when the XML file is fully parsed and we're ready to create the node
* @param cache the individual meshes will be added there
* @param[out] out the nodes are added here
*/
void LodNodeLoader::done(Track* track,
std::string directory,
std::vector<scene::IMesh*>& cache,
std::vector<LODNode*>& out)
LODNode* LodNodeLoader::instanciate(const XMLNode* node, scene::ISceneNode* parent)
//Track* track, std::vector<irr::scene::IMesh*>& cache)
{
scene::ISceneManager* sm = irr_driver->getSceneManager();
// 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
std::string groupname = "";
node->get("lod_group", &groupname);
// 1. Sort LOD groups (highest detail first, lowest detail last)
std::map<std::string, std::vector< std::pair<int, LodModel> > > sorted_lod_groups;
std::vector< LodModel >& group = m_lod_groups[groupname];
std::map<std::string, std::map<int, LodModel> >::iterator it;
for (it = lod_groups.begin(); it != lod_groups.end(); it++)
//core::vector3df xyz(0,0,0);
//node->get("xyz", &xyz);
//core::vector3df hpr(0,0,0);
//node->get("hpr", &hpr);
//core::vector3df scale(1.0f, 1.0f, 1.0f);
//node->get("scale", &scale);
if (group.size() > 0)
{
std::map<int, LodModel>::iterator it2;
for (it2 = it->second.begin(); it2 != it->second.end(); it2++)
scene::ISceneNode* actual_parent = (parent == NULL ? sm->getRootSceneNode() : parent);
LODNode* lod_node = new LODNode(groupname, actual_parent, sm);
//lod_node->setPosition(xyz);
//lod_node->setRotation(hpr);
//lod_node->setScale(scale);
lod_node->updateAbsolutePosition();
for (unsigned int m=0; m<group.size(); m++)
{
//printf("Copying before sort : (%i) %s is in group %s\n", it2->first, it2->second.c_str(), it->first.c_str());
sorted_lod_groups[it->first].push_back( std::pair<int, LodModel>(it2->first, it2->second) );
}
std::sort( sorted_lod_groups[it->first].begin(), sorted_lod_groups[it->first].end(), PairCompare );
// TODO: check whether the mesh contains animations or not?
scene::IMesh* a_mesh = irr_driver->getMesh(group[m].m_model_file);
//printf("Group '%s' :\n", it->first.c_str());
//for (unsigned int x=0; x<sorted_lod_groups[it->first].size(); x++)
//{
// printf(" - (%i) %s\n", sorted_lod_groups[it->first][x].first, sorted_lod_groups[it->first][x].second.c_str());
//}
}
// 2. Read the XML nodes and instanciate LOD scene nodes where relevant
std::string groupname;
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< LodInstance >& v = it3->second;
for (unsigned int n=0; n<v.size(); n++)
{
const XMLNode* node = v[n].m_xml_node;
groupname = "";
node->get("lod_group", &groupname);
//if (model_name != sorted_lod_groups[it3->first][0].second) continue;
core::vector3df xyz(0,0,0);
node->get("xyz", &xyz);
core::vector3df hpr(0,0,0);
node->get("hpr", &hpr);
core::vector3df scale(1.0f, 1.0f, 1.0f);
node->get("scale", &scale);
if (group.size() > 0)
if (!a_mesh)
{
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);
lod_node->setScale(scale);
lod_node->updateAbsolutePosition();
for (unsigned int m=0; m<group.size(); m++)
{
// TODO: check whether the mesh contains animations or not?
scene::IMesh* a_mesh = irr_driver->getMesh(group[m].second.m_model_file);
Log::warn("LODNodeLoad", "Warning: object model '%s' not found, ignored.\n",
group[m].m_model_file.c_str());
continue;
}
if (!a_mesh)
{
Log::warn("LODNodeLoad", "Warning: object model '%s' not found, ignored.\n",
group[m].second.m_model_file.c_str());
continue;
}
if (group[m].m_tangent && a_mesh->getMeshBuffer(0)->getVertexType() != video::EVT_TANGENTS)
{
scene::IMeshManipulator* manip = irr_driver->getVideoDriver()->getMeshManipulator();
scene::IMesh* m2 = manip->createMeshWithTangents(a_mesh);
// FIXME: do we need to clean up 'a_mesh' ?
a_mesh = m2;
irr_driver->setAllMaterialFlags(a_mesh);
}
if (group[m].second.m_tangent)
{
scene::IMeshManipulator* manip = irr_driver->getVideoDriver()->getMeshManipulator();
scene::IMesh* m2 = manip->createMeshWithTangents(a_mesh);
// FIXME: do we need to clean up 'a_mesh' ?
a_mesh = m2;
irr_driver->setAllMaterialFlags(a_mesh);
a_mesh->grab();
//cache.push_back(a_mesh);
irr_driver->grabAllTextures(a_mesh);
scene::IMeshSceneNode* scene_node = irr_driver->addMesh(a_mesh);
}
m_track->handleAnimatedTextures( scene_node, *group[m].m_xml );
a_mesh->grab();
cache.push_back(a_mesh);
irr_driver->grabAllTextures(a_mesh);
scene::IMeshSceneNode* scene_node = irr_driver->addMesh(a_mesh);
track->handleAnimatedTextures( scene_node, *group[m].second.m_xml );
lod_node->add( group[m].first, scene_node, true );
}
lod_node->add( group[m].m_distance, scene_node, true );
}
#ifdef DEBUG
std::string debug_name = groupname+" (LOD track-object)";
lod_node->setName(debug_name.c_str());
std::string debug_name = groupname+" (LOD track-object)";
lod_node->setName(debug_name.c_str());
#endif
out.push_back(lod_node);
}
else
{
fprintf(stderr, "[LodNodeLoader] WARNING, LOD group '%s' is empty\n", groupname.c_str());
}
}
} // end for
return lod_node;
}
else
{
Log::warn("LodNodeLoader", "LOD group '%s' is empty", groupname.c_str());
return NULL;
}
}
// ----------------------------------------------------------------------------
void LodNodeLoader::clear()
{
lod_groups.clear();
lod_instances.clear();
m_lod_groups.clear();
}

View File

@ -36,43 +36,28 @@ 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;
bool m_tangent;
const XMLNode* m_xml;
int m_distance;
/** Constructor to allow storing this in STL containers */
LodModel()
{
m_tangent = false;
m_distance = 0;
m_xml = NULL;
}
LodModel(const XMLNode* xml, std::string& model, bool tangent)
LodModel(const XMLNode* xml, int distance, std::string& model, bool tangent)
{
m_model_file = model;
m_tangent = tangent;
m_xml = xml;
m_distance = distance;
}
~LodModel()
@ -86,17 +71,15 @@ struct LodModel
class LodNodeLoader
{
private:
std::map< std::string, std::map< int, LodModel > > lod_groups;
std::map< std::string, std::vector< LodInstance > > lod_instances;
std::map< std::string, std::vector< LodModel > > m_lod_groups;
Track* m_track;
public:
LodNodeLoader();
LodNodeLoader(Track* track);
bool check(const XMLNode* xml, scene::ISceneNode* parent);
void done(Track* track,
std::string directory,
std::vector<irr::scene::IMesh*>& cache,
std::vector<LODNode*>& out);
void addLODModelDefinition(const XMLNode* xml);
LODNode* instanciate(const XMLNode* xml_node, scene::ISceneNode* parent);
//Track* track, std::vector<irr::scene::IMesh*>& cache);
void clear();

View File

@ -854,7 +854,7 @@ bool Track::loadMainTrack(const XMLNode &root)
m_aabb_max.setY(m_aabb_max.getY()+30.0f);
World::getWorld()->getPhysics()->init(m_aabb_min, m_aabb_max);
LodNodeLoader lodLoader;
LodNodeLoader lodLoader(this);
// Load LOD groups
const XMLNode *lod_xml_node = root.getNode("lod");
@ -865,10 +865,7 @@ bool Track::loadMainTrack(const XMLNode &root)
const XMLNode* lod_group_xml = lod_xml_node->getNode(i);
for (unsigned int j = 0; j < lod_group_xml->getNumNodes(); j++)
{
// TODO: eventually, remove support for the old way of specifying LOD
// definitions among node, and support only the new way of using
// a <lod> section. Then, the LOD loading sequence can be simplified a lot
lodLoader.check(lod_group_xml->getNode(j), NULL);
lodLoader.addLODModelDefinition(lod_group_xml->getNode(j));
}
}
}
@ -1033,7 +1030,8 @@ bool Track::loadMainTrack(const XMLNode &root)
std::string challenge;
n->get("challenge", &challenge);
bool is_lod = lodLoader.check(n, NULL);
bool lod_instance = false;
n->get("lod_instance", &lod_instance);
if (tangent)
{
@ -1078,9 +1076,17 @@ bool Track::loadMainTrack(const XMLNode &root)
handleAnimatedTextures(scene_node, *n);
m_all_nodes.push_back( scene_node );
}
else if (is_lod)
else if (lod_instance)
{
// nothing to do
LODNode* node = lodLoader.instanciate(n, NULL);
if (node != NULL)
{
node->setPosition(xyz);
node->setRotation(hpr);
node->setScale(scale);
m_all_nodes.push_back( node );
}
}
else
{
@ -1198,16 +1204,6 @@ bool Track::loadMainTrack(const XMLNode &root)
} // for i
// Create LOD nodes
std::vector<LODNode*> 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
// handleAnimatedTextures( lod_nodes[n], *node );
m_all_nodes.push_back( lod_nodes[n] );
}
// This will (at this stage) only convert the main track model.
for(unsigned int i=0; i<m_all_nodes.size(); i++)
{
@ -1530,31 +1526,24 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
loadMainTrack(*root);
unsigned int main_track_count = m_all_nodes.size();
LodNodeLoader lod_loader;
std::map<std::string, XMLNode*> library_nodes;
loadObjects(root, path, lod_loader, true, NULL, library_nodes);
LodNodeLoader lod_loader(this);
// -------- 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)
// Load LOD groups
const XMLNode *lod_xml_node = root->getNode("lod");
if (lod_xml_node != NULL)
{
for (unsigned int i=0; i<track_node->getNumNodes(); i++)
for (unsigned int i = 0; i < lod_xml_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);
const XMLNode* lod_group_xml = lod_xml_node->getNode(i);
for (unsigned int j = 0; j < lod_group_xml->getNumNodes(); j++)
{
lod_loader.addLODModelDefinition(lod_group_xml->getNode(j));
}
}
}
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);
// ---------------------------------------------
std::map<std::string, XMLNode*> library_nodes;
loadObjects(root, path, lod_loader, true, NULL, library_nodes);
// Cleanup library nodes
for (std::map<std::string, XMLNode*>::iterator it = library_nodes.begin();
@ -1736,23 +1725,7 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, LodNodeLoa
if (name == "track" || name == "default-start") continue;
if (name == "object")
{
bool is_instance = false;
node->get("lod_instance", &is_instance);
float lod_distance = -1;
node->get("lod_distance", &lod_distance);
if (lod_distance > 0.0f && !is_instance)
{
// lod definition
if (create_lod_definitions)
lod_loader.check(node, parent);
}
else
{
lod_loader.check(node, parent);
}
m_track_object_manager->add(*node, parent);
m_track_object_manager->add(*node, parent, lod_loader);
}
else if (name == "library")
{
@ -1790,10 +1763,7 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, LodNodeLoa
const XMLNode* lod_group_xml = lod_xml_node->getNode(i);
for (unsigned int j = 0; j < lod_group_xml->getNumNodes(); j++)
{
// TODO: eventually, remove support for the old way of specifying LOD
// definitions among node, and support only the new way of using
// a <lod> section. Then, the LOD loading sequence can be simplified a lot
lod_loader.check(lod_group_xml->getNode(j), NULL);
lod_loader.addLODModelDefinition(lod_group_xml->getNode(j));
}
}
}
@ -1851,7 +1821,7 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, LodNodeLoa
{
if (UserConfigParams::m_graphical_effects)
{
m_track_object_manager->add(*node, parent);
m_track_object_manager->add(*node, parent, lod_loader);
}
}
else if (name == "sky-dome" || name == "sky-box" || name == "sky-color")
@ -1864,7 +1834,7 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, LodNodeLoa
}
else if (name == "light")
{
m_track_object_manager->add(*node, parent);
m_track_object_manager->add(*node, parent, lod_loader);
}
else if (name == "weather")
{

View File

@ -38,9 +38,9 @@
* model, enable/disable status, timer information.
* \param lod_node Lod node (defaults to NULL).
*/
TrackObject::TrackObject(const XMLNode &xml_node, scene::ISceneNode* parent, LODNode* lod_node)
TrackObject::TrackObject(const XMLNode &xml_node, scene::ISceneNode* parent, LodNodeLoader& lod_loader)
{
init(xml_node, parent, lod_node);
init(xml_node, parent, lod_loader);
}
// ----------------------------------------------------------------------------
@ -79,7 +79,7 @@ TrackObject::TrackObject(const core::vector3df& xyz, const core::vector3df& hpr,
// ----------------------------------------------------------------------------
void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent, LODNode* lod_node)
void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent, LodNodeLoader& lod_loader)
{
m_init_xyz = core::vector3df(0,0,0);
m_init_hpr = core::vector3df(0,0,0);
@ -99,6 +99,9 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent, LODNo
xml_node.get("interaction", &m_interaction);
xml_node.get("lod_group", &m_lod_group);
bool lod_instance = false;
xml_node.get("lod_instance", &lod_instance);
m_soccer_ball = false;
xml_node.get("soccer_ball", &m_soccer_ball);
@ -152,12 +155,13 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent, LODNo
{
scene::ISceneNode *glownode = NULL;
if (lod_node != NULL)
if (lod_instance)
{
m_type = "lod";
m_presentation = new TrackObjectPresentationLOD(xml_node, lod_node);
TrackObjectPresentationLOD* lod_node = new TrackObjectPresentationLOD(xml_node, parent, lod_loader);
m_presentation = lod_node;
glownode = lod_node->getAllNodes()[0];
glownode = ((LODNode*)lod_node->getNode())->getAllNodes()[0];
}
else
{

View File

@ -31,7 +31,7 @@
class XMLNode;
class ThreeDAnimation;
class LodNodeLoader;
/**
* \ingroup tracks
@ -82,10 +82,10 @@ protected:
ThreeDAnimation* m_animator;
void init(const XMLNode &xml_node, scene::ISceneNode* parent, LODNode* lodNode);
void init(const XMLNode &xml_node, scene::ISceneNode* parent, LodNodeLoader& lod_loader);
public:
TrackObject(const XMLNode &xml_node, scene::ISceneNode* parent, LODNode* lodNode=NULL);
TrackObject(const XMLNode &xml_node, scene::ISceneNode* parent, LodNodeLoader& lod_loader);
TrackObject(const core::vector3df& xyz,
const core::vector3df& hpr,

View File

@ -49,31 +49,16 @@ TrackObjectManager::~TrackObjectManager()
* in a separate section that's read before everything and remove all this
* crap
*/
void TrackObjectManager::add(const XMLNode &xml_node, scene::ISceneNode* parent)
void TrackObjectManager::add(const XMLNode &xml_node, scene::ISceneNode* parent, LodNodeLoader& lod_loader)
{
try
{
std::string groupname;
xml_node.get("lod_group", &groupname);
bool is_lod = !groupname.empty();
if (is_lod)
{
bool lod_instance = false;
xml_node.get("lod_instance", &lod_instance);
if (lod_instance)
m_lod_objects[groupname].push_back(&xml_node);
}
else
{
m_all_objects.push_back(new TrackObject(xml_node, parent));
}
m_all_objects.push_back(new TrackObject(xml_node, parent, lod_loader));
}
catch (std::exception& e)
{
fprintf(stderr, "[TrackObjectManager] WARNING: Could not load track object. Reason : %s\n",
e.what());
Log::warn("TrackObjectManager", "Could not load track object. Reason : %s",
e.what());
}
} // add
@ -219,13 +204,8 @@ void TrackObjectManager::removeObject(TrackObject* obj)
} // removeObject
// ----------------------------------------------------------------------------
/**
* \brief To be called after all objects are loaded and the LodNodeLoader is done
* parsing everything.
* This method exists because LOD objects need to be created after others.
*
* \param lod_nodes the LOD nodes created by the LodNodeLoader.
*/
/*
void TrackObjectManager::assingLodNodes(const std::vector<LODNode*>& lod_nodes)
{
for (unsigned int n=0; n<lod_nodes.size(); n++)
@ -242,3 +222,4 @@ void TrackObjectManager::assingLodNodes(const std::vector<LODNode*>& lod_nodes)
m_lod_objects.clear();
}
*/

View File

@ -46,15 +46,10 @@ protected:
enum TrackObjectType {TO_PHYSICAL, TO_GRAPHICAL};
PtrVector<TrackObject> m_all_objects;
/** Temporary storage for LOD objects whose XML node was read but whose
* scene node is not yet ready
*/
std::map<std::string, std::vector<const XMLNode*> > m_lod_objects;
public:
TrackObjectManager();
~TrackObjectManager();
void add(const XMLNode &xml_node, scene::ISceneNode* parent);
void add(const XMLNode &xml_node, scene::ISceneNode* parent, LodNodeLoader& lod_loader);
void update(float dt);
void handleExplosion(const Vec3 &pos, const PhysicalObject *mp,
bool secondary_hits=true);
@ -68,8 +63,6 @@ public:
void removeObject(TrackObject* who);
void assingLodNodes(const std::vector<LODNode*>& lod);
PtrVector<TrackObject>& getObjects() { return m_all_objects; }
const PtrVector<TrackObject>& getObjects() const { return m_all_objects; }

View File

@ -32,6 +32,7 @@
#include "modes/world.hpp"
#include "states_screens/dialogs/race_paused_dialog.hpp"
#include "states_screens/dialogs/tutorial_message_dialog.hpp"
#include "tracks/lod_node_loader.hpp"
#include "tracks/track.hpp"
#include <ISceneManager.h>
@ -125,10 +126,12 @@ TrackObjectPresentationEmpty::~TrackObjectPresentationEmpty()
// ----------------------------------------------------------------------------
TrackObjectPresentationLOD::TrackObjectPresentationLOD(const XMLNode& xml_node, LODNode* lod_node) :
TrackObjectPresentationLOD::TrackObjectPresentationLOD(const XMLNode& xml_node,
scene::ISceneNode* parent, LodNodeLoader& lod_loader) :
TrackObjectPresentationSceneNode(xml_node)
{
m_node = lod_node;
m_node = lod_loader.instanciate(&xml_node, parent);
if (m_node == NULL) throw std::exception("Cannot load LOD node");
m_node->setPosition(m_init_xyz);
m_node->setRotation(m_init_hpr);
m_node->setScale(m_init_scale);
@ -136,8 +139,8 @@ TrackObjectPresentationLOD::TrackObjectPresentationLOD(const XMLNode& xml_node,
TrackObjectPresentationLOD::~TrackObjectPresentationLOD()
{
irr_driver->removeNode(m_node);
}
// ----------------------------------------------------------------------------
TrackObjectPresentationMesh::TrackObjectPresentationMesh(const XMLNode& xml_node,

View File

@ -40,6 +40,7 @@ class SFXBase;
class ParticleEmitter;
class PhysicalObject;
class ThreeDAnimation;
class LodNodeLoader;
/**
* \ingroup tracks
@ -147,7 +148,9 @@ class TrackObjectPresentationLOD : public TrackObjectPresentationSceneNode
{
public:
TrackObjectPresentationLOD(const XMLNode& xml_node, LODNode* lod_node);
TrackObjectPresentationLOD(const XMLNode& xml_node,
scene::ISceneNode* parent,
LodNodeLoader& lod_loader);
virtual ~TrackObjectPresentationLOD();
};