diff --git a/src/graphics/lod_node.hpp b/src/graphics/lod_node.hpp index 267952d6f..b190676c5 100644 --- a/src/graphics/lod_node.hpp +++ b/src/graphics/lod_node.hpp @@ -24,7 +24,7 @@ #include namespace irr { - namespace scene { class ISceneManager; } + namespace scene { class ISceneManager; class ISceneNode; } } using namespace irr; @@ -49,7 +49,7 @@ private: core::aabbox3d Box; std::vector m_detail; - std::vector m_nodes; + std::vector m_nodes; std::set m_nodes_set; diff --git a/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj b/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj index 689392cd5..79fb44189 100644 --- a/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj +++ b/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj @@ -340,6 +340,7 @@ 9598A5B613CFBA83000B83EA /* hardware_skinning.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9598A5B413CFBA83000B83EA /* hardware_skinning.cpp */; }; 959DE0C613C297B90068ED78 /* swatter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 959DE0C413C297B90068ED78 /* swatter.cpp */; }; 95A0BA2413E63F6700620EA6 /* kart_with_stats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95A0BA2213E63F6700620EA6 /* kart_with_stats.cpp */; }; + 95AA4C67148AF2CC0053771D /* lod_node_loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95AA4C65148AF2CC0053771D /* lod_node_loader.cpp */; }; 95AAD98012BAD36300B7B8A3 /* tutorial_screen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95AAD97E12BAD36300B7B8A3 /* tutorial_screen.cpp */; }; 95B5CD14102DE08F00EF2001 /* device_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95B5CD13102DE08F00EF2001 /* device_config.cpp */; }; 95BF1E68127513A100F78AE7 /* max_speed.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95BF1E66127513A100F78AE7 /* max_speed.cpp */; }; @@ -1149,6 +1150,8 @@ 95A540411481BEB60086FE38 /* dummy_network_http.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = dummy_network_http.hpp; path = ../../addons/dummy_network_http.hpp; sourceTree = SOURCE_ROOT; }; 95A540581481C4760086FE38 /* dummy_sfx.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = dummy_sfx.hpp; path = ../../audio/dummy_sfx.hpp; sourceTree = SOURCE_ROOT; }; 95A5405B1481C4DB0086FE38 /* music_dummy.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = music_dummy.hpp; path = ../../audio/music_dummy.hpp; sourceTree = SOURCE_ROOT; }; + 95AA4C65148AF2CC0053771D /* lod_node_loader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lod_node_loader.cpp; path = ../../tracks/lod_node_loader.cpp; sourceTree = SOURCE_ROOT; }; + 95AA4C66148AF2CC0053771D /* lod_node_loader.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = lod_node_loader.hpp; path = ../../tracks/lod_node_loader.hpp; sourceTree = SOURCE_ROOT; }; 95AAD97E12BAD36300B7B8A3 /* tutorial_screen.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tutorial_screen.cpp; path = ../../states_screens/tutorial_screen.cpp; sourceTree = SOURCE_ROOT; }; 95AAD97F12BAD36300B7B8A3 /* tutorial_screen.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = tutorial_screen.hpp; path = ../../states_screens/tutorial_screen.hpp; sourceTree = SOURCE_ROOT; }; 95B5CD12102DE08F00EF2001 /* device_config.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = device_config.hpp; path = ../../config/device_config.hpp; sourceTree = SOURCE_ROOT; }; @@ -2632,6 +2635,8 @@ 955DE8881004273B006A4F3C /* check_structure.hpp */, 953789720FC7829100DD1F8E /* graph_node.cpp */, 953789710FC7829100DD1F8E /* graph_node.hpp */, + 95AA4C65148AF2CC0053771D /* lod_node_loader.cpp */, + 95AA4C66148AF2CC0053771D /* lod_node_loader.hpp */, 951C357E0FC05BF400A48379 /* quad_set.cpp */, 951C357D0FC05BF400A48379 /* quad_set.hpp */, 953789810FC7831400DD1F8E /* quad.cpp */, @@ -3177,6 +3182,7 @@ 95703D1B1468C63F006334D7 /* btGeometryUtil.cpp in Sources */, 95703D1C1468C63F006334D7 /* btQuickprof.cpp in Sources */, 95703D1D1468C63F006334D7 /* btSerializer.cpp in Sources */, + 95AA4C67148AF2CC0053771D /* lod_node_loader.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/main.cpp b/src/main.cpp index 8391af0cb..4777dace6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1148,7 +1148,10 @@ int main(int argc, char *argv[] ) // Get into menu mode initially. input_manager->setMode(InputManager::MENU); - + + GUIEngine::addLoadingIcon( irr_driver->getTexture( + file_manager->getGUIDir() + "/options_input.png") ); + main_loop = new MainLoop(); material_manager -> loadMaterial (); GUIEngine::addLoadingIcon( irr_driver->getTexture( diff --git a/src/tracks/lod_node_loader.cpp b/src/tracks/lod_node_loader.cpp new file mode 100644 index 000000000..66492b2e0 --- /dev/null +++ b/src/tracks/lod_node_loader.cpp @@ -0,0 +1,187 @@ +// $Id$ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2007 Joerg Henrichs +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "tracks/lod_node_loader.hpp" +using namespace irr; + +#include "graphics/irr_driver.hpp" +#include "graphics/lod_node.hpp" +#include "io/xml_node.hpp" + +#include +#include + +LodNodeLoader::LodNodeLoader() +{ +} + +// ---------------------------------------------------------------------------- + +bool PairCompare(const std::pair& i, const std::pair& 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) +{ + 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); + + if (!lodgroup.empty()) + { + if (lod_instance) + { + lod_instances[lodgroup].push_back(xml); + } + else + { + std::string model_name; + xml->get("model", &model_name); + + lod_groups[lodgroup][(int)lod_distance] = model_name; + } + return true; + } + else + { + return false; + } +} + +// ---------------------------------------------------------------------------- + +/** + * 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(std::string directory, + std::vector& cache, + std::vector& out) +{ + scene::ISceneManager* sm = irr_driver->getSceneManager(); + scene::ISceneNode* sroot = 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 + + // 1. Sort LOD groups (highest detail first, lowest detail last) + std::map > > sorted_lod_groups; + + std::map >::iterator it; + for (it = lod_groups.begin(); it != lod_groups.end(); it++) + { + std::map::iterator it2; + for (it2 = it->second.begin(); it2 != it->second.end(); it2++) + { + //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(it2->first, it2->second) ); + } + std::sort( sorted_lod_groups[it->first].begin(), sorted_lod_groups[it->first].end(), PairCompare ); + + //printf("Group '%s' :\n", it->first.c_str()); + //for (unsigned int x=0; xfirst].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< const XMLNode* > >::iterator it3; + for (it3 = lod_instances.begin(); it3 != lod_instances.end(); it3++) + { + std::vector< std::pair >& group = sorted_lod_groups[it3->first]; + + std::vector< const XMLNode* >& v = it3->second; + for (unsigned int n=0; ngetName()!="static-object") + { + fprintf(stderr, "Incorrect tag '%s' used in LOD instance - ignored\n", + node->getName().c_str()); + continue; + } + + 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); + + std::string full_path; + + if (group.size() > 0) + { + LODNode* lod_node = new LODNode(sroot, sm); + for (unsigned int m=0; mgetAnimatedMesh(full_path); + if(!a_mesh) + { + fprintf(stderr, "Warning: object model '%s' not found, ignored.\n", + full_path.c_str()); + continue; + } + a_mesh->grab(); + cache.push_back(a_mesh); + irr_driver->grabAllTextures(a_mesh); + scene::IAnimatedMeshSceneNode* scene_node = + irr_driver->addAnimatedMesh(a_mesh); + scene_node->setPosition(xyz); + scene_node->setRotation(hpr); + scene_node->setScale(scale); + + lod_node->add( group[m].first, scene_node, true ); + } + +#ifdef DEBUG + 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 +} diff --git a/src/tracks/lod_node_loader.hpp b/src/tracks/lod_node_loader.hpp new file mode 100644 index 000000000..08193d27c --- /dev/null +++ b/src/tracks/lod_node_loader.hpp @@ -0,0 +1,57 @@ +// $Id$ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2007 Joerg Henrichs +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTe ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HEADER_LOD_NODE_LOADER_HPP +#define HEADER_LOD_NODE_LOADER_HPP + + +class XMLNode; +class LODNode; + +#include +#include + +namespace irr +{ + namespace scene + { + class IMesh; + } +} + +/** Utility class to load level-of-detail nodes + * \ingroup tracks + */ +class LodNodeLoader +{ +private: + std::map< std::string, std::map< int, std::string > > lod_groups; + std::map< std::string, std::vector< const XMLNode* > > lod_instances; + +public: + LodNodeLoader(); + + bool check(const XMLNode* xml); + void done(std::string directory, + std::vector& cache, + std::vector& out); + +}; // LodNodeLoader + +#endif // HEADER_LOD_NODE_LOADER_HPP diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index db3b79d1c..4bb336d36 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -50,6 +50,7 @@ using namespace irr; #include "race/race_manager.hpp" #include "tracks/bezier_curve.hpp" #include "tracks/check_manager.hpp" +#include "tracks/lod_node_loader.hpp" #include "tracks/quad_graph.hpp" #include "tracks/quad_set.hpp" #include "tracks/track_object_manager.hpp" @@ -595,12 +596,6 @@ void Track::convertTrackToBullet(scene::ISceneNode *node) // ---------------------------------------------------------------------------- - -bool PairCompare(const std::pair& i, const std::pair& j) -{ - return (i.first < j.first); -} - /** Loads the main track model (i.e. all other objects contained in the * scene might use raycast on this track model to determine the actual * height of the terrain. @@ -676,9 +671,8 @@ 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); - std::map< std::string, std::map< int, std::string > > lod_groups; - std::map< std::string, std::vector< const XMLNode* > > lod_instances; - + LodNodeLoader lodLoader; + for(unsigned int i=0; igetNumNodes(); i++) { const XMLNode *n=track_node->getNode(i); @@ -707,14 +701,7 @@ bool Track::loadMainTrack(const XMLNode &root) core::vector3df scale(1.0f, 1.0f, 1.0f); n->get("scale", &scale); - float lod_distance = -1.0f; - n->get("lod_distance", &lod_distance); - - bool lod_instance = false; - n->get("lod_instance", &lod_instance); - - std::string lodgroup; - n->get("lod_group", &lodgroup); + lodLoader.check(n); if (tangent) { @@ -750,18 +737,9 @@ bool Track::loadMainTrack(const XMLNode &root) handleAnimatedTextures(scene_node, *n); m_all_nodes.push_back( scene_node ); } - else if (!lodgroup.empty()) + else if (lodLoader.check(n)) { - if (lod_instance) - { - lod_instances[lodgroup].push_back(n); - //printf("LOD instance : '%s' @ (%.2f, %.2f, %.2f)\n", lodgroup.c_str(), xyz.X, xyz.Y, xyz.Z); - } - else - { - lod_groups[lodgroup][(int)lod_distance] = model_name; - //printf("LOD Model Definition : group='%s', detail='%i', model='%s'\n", lodgroup.c_str(), detail, model_name.c_str()); - } + // nothing to do } else { @@ -799,109 +777,16 @@ bool Track::loadMainTrack(const XMLNode &root) } } // for i - - scene::ISceneManager* sm = irr_driver->getSceneManager(); - scene::ISceneNode* sroot = sm->getRootSceneNode(); - // ================ Level Of Detail ================ - // 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 - - // 1. Sort LOD groups (highest detail first, lowest detail last) - std::map > > sorted_lod_groups; - - std::map >::iterator it; - for (it = lod_groups.begin(); it != lod_groups.end(); it++) + std::vector lod_nodes; + lodLoader.done(m_root, m_all_cached_meshes, lod_nodes); + for (unsigned int n=0; n::iterator it2; - for (it2 = it->second.begin(); it2 != it->second.end(); it2++) - { - //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(it2->first, it2->second) ); - } - std::sort( sorted_lod_groups[it->first].begin(), sorted_lod_groups[it->first].end(), PairCompare ); - - //printf("Group '%s' :\n", it->first.c_str()); - //for (unsigned int x=0; xfirst].size(); x++) - //{ - // printf(" - (%i) %s\n", sorted_lod_groups[it->first][x].first, sorted_lod_groups[it->first][x].second.c_str()); - //} + // FIXME: support for animated textures on LOD objects + // handleAnimatedTextures( lod_nodes[n], *node ); + m_all_nodes.push_back( lod_nodes[n] ); } - // 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; - for (it3 = lod_instances.begin(); it3 != lod_instances.end(); it3++) - { - std::vector< std::pair >& group = sorted_lod_groups[it3->first]; - - std::vector< const XMLNode* >& v = it3->second; - for (unsigned int n=0; ngetName()!="static-object") - { - fprintf(stderr, "Incorrect tag '%s' used in LOD instance - ignored\n", - node->getName().c_str()); - continue; - } - - 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) - { - LODNode* lod_node = new LODNode(sroot, sm); - for (unsigned int m=0; mgetAnimatedMesh(full_path); - if(!a_mesh) - { - fprintf(stderr, "Warning: object model '%s' not found, ignored.\n", - full_path.c_str()); - continue; - } - a_mesh->grab(); // see above for usage in m_all_cached_meshes - m_all_cached_meshes.push_back(a_mesh); - irr_driver->grabAllTextures(a_mesh); - scene::IAnimatedMeshSceneNode* scene_node = - irr_driver->addAnimatedMesh(a_mesh); - scene_node->setPosition(xyz); - scene_node->setRotation(hpr); - scene_node->setScale(scale); - - lod_node->add( group[m].first, scene_node, true ); - } - -#ifdef DEBUG - std::string debug_name = groupname+" (LOD track-object)"; - lod_node->setName(debug_name.c_str()); -#endif - - handleAnimatedTextures(lod_node, *node); - m_all_nodes.push_back( lod_node ); - } - else - { - fprintf(stderr, "[Track] WARNING, LOD group '%s' is empty\n", groupname.c_str()); - } - } - } - // ================================================= - // This will (at this stage) only convert the main track model. for(unsigned int i=0; iadd(*node); } else if(name=="water")