diff --git a/src/animations/three_d_animation.cpp b/src/animations/three_d_animation.cpp index adf525664..8531746a2 100644 --- a/src/animations/three_d_animation.cpp +++ b/src/animations/three_d_animation.cpp @@ -43,14 +43,17 @@ ThreeDAnimation::ThreeDAnimation(const XMLNode &node) node.get("reset", &m_crash_reset); m_triangle_mesh = NULL; - /** Save the initial position and rotation in the base animation object. */ - setInitialTransform(AnimationBase::m_node->getPosition(), - AnimationBase::m_node->getRotation() ); - + if (AnimationBase::m_node) + { + /** Save the initial position and rotation in the base animation object. */ + setInitialTransform(AnimationBase::m_node->getPosition(), + AnimationBase::m_node->getRotation() ); + m_hpr = AnimationBase::m_node->getRotation(); + } + m_body = NULL; m_motion_state = NULL; m_collision_shape = NULL; - m_hpr = AnimationBase::m_node->getRotation(); std::string shape; node.get("shape", &shape); if(shape!="") diff --git a/src/graphics/lod_node.cpp b/src/graphics/lod_node.cpp index 6104ec2ea..318e77bd2 100644 --- a/src/graphics/lod_node.cpp +++ b/src/graphics/lod_node.cpp @@ -24,11 +24,18 @@ #include #include -LODNode::LODNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id) -: ISceneNode(parent, mgr, id) //: IDummyTransformationSceneNode(parent, mgr, id) +/** + * @param group_name Only useful for getGroupName() + */ +LODNode::LODNode(std::string group_name, scene::ISceneNode* parent, + scene::ISceneManager* mgr, s32 id) + : ISceneNode(parent, mgr, id) //: IDummyTransformationSceneNode(parent, mgr, id) { assert(mgr != NULL); assert(parent != NULL); + + m_group_name = group_name; + // At this stage refcount is two: one because of the object being // created, and once because it is a child of the parent. Drop once, // so that only the reference from the parent is active, causing this diff --git a/src/graphics/lod_node.hpp b/src/graphics/lod_node.hpp index b190676c5..480b161e2 100644 --- a/src/graphics/lod_node.hpp +++ b/src/graphics/lod_node.hpp @@ -53,9 +53,11 @@ private: std::set m_nodes_set; + std::string m_group_name; + public: - LODNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id=-1); + LODNode(std::string group_name, scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id=-1); virtual ~LODNode(); //! returns the axis aligned bounding box of this node @@ -90,6 +92,7 @@ public: virtual scene::ESCENE_NODE_TYPE getType() const { return (scene::ESCENE_NODE_TYPE)scene::ESNT_LOD_NODE; } + const std::string& getGroupName() const { return m_group_name; } }; #endif diff --git a/src/items/item.cpp b/src/items/item.cpp index 93b56a3ff..e286b162d 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -50,7 +50,9 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal, m_original_mesh = mesh; m_original_lowmesh = lowres_mesh; - LODNode* lodnode = new LODNode(irr_driver->getSceneManager()->getRootSceneNode(), irr_driver->getSceneManager()); + LODNode* lodnode = new LODNode("item", + irr_driver->getSceneManager()->getRootSceneNode(), + irr_driver->getSceneManager()); scene::IMeshSceneNode* meshnode = irr_driver->addMesh(mesh); if (lowres_mesh != NULL) diff --git a/src/karts/kart_model.cpp b/src/karts/kart_model.cpp index c0c4fd8aa..cee317b9f 100644 --- a/src/karts/kart_model.cpp +++ b/src/karts/kart_model.cpp @@ -222,9 +222,9 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models) if (animated_models) { - LODNode* lod_node = new LODNode( - irr_driver->getSceneManager()->getRootSceneNode(), - irr_driver->getSceneManager() ); + LODNode* lod_node = new LODNode("kart", + irr_driver->getSceneManager()->getRootSceneNode(), + irr_driver->getSceneManager() ); node = irr_driver->addAnimatedMesh(m_mesh); diff --git a/src/tracks/lod_node_loader.cpp b/src/tracks/lod_node_loader.cpp index 66492b2e0..88f3e4c4c 100644 --- a/src/tracks/lod_node_loader.cpp +++ b/src/tracks/lod_node_loader.cpp @@ -123,13 +123,6 @@ void LodNodeLoader::done(std::string directory, { const XMLNode* node = v[n]; - if(node->getName()!="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; @@ -145,7 +138,7 @@ void LodNodeLoader::done(std::string directory, if (group.size() > 0) { - LODNode* lod_node = new LODNode(sroot, sm); + LODNode* lod_node = new LODNode(groupname, sroot, sm); for (unsigned int m=0; m& cache, std::vector& out); + + void clear(); }; // LodNodeLoader diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 4bb336d36..d0d360dbe 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -1068,6 +1068,8 @@ void Track::loadTrackModel(World* parent, unsigned int mode_id) loadMainTrack(*root); + LodNodeLoader lod_loader; + for(unsigned int i=0; igetNumNodes(); i++) { const XMLNode *node = root->getNode(i); @@ -1077,7 +1079,7 @@ void Track::loadTrackModel(World* parent, unsigned int mode_id) if(name=="track" || name=="default-start") continue; if(name=="object") { - // FIXME: this may be LOD + lod_loader.check(node); m_track_object_manager->add(*node); } else if(name=="water") @@ -1156,7 +1158,7 @@ void Track::loadTrackModel(World* parent, unsigned int mode_id) { scene::ISceneManager* sm = irr_driver->getSceneManager(); scene::ISceneNode* sroot = sm->getRootSceneNode(); - LODNode* lod = new LODNode(sroot, sm); + LODNode* lod = new LODNode("particles", sroot, sm); lod->add(clip_distance, (scene::ISceneNode*)emitter->getNode(), true); //m_all_emitters.push_back(emitter); m_all_nodes.push_back( lod ); @@ -1221,6 +1223,34 @@ void Track::loadTrackModel(World* parent, unsigned int mode_id) } } // for igetNumNodes() + + // recheck the static area, we will need LOD info + const XMLNode* track_node = root->getNode("track"); + for(unsigned int i=0; igetNumNodes(); i++) + { + const XMLNode* n = track_node->getNode(i); + lod_loader.check(n); + } + + // -------- Create and assign LOD nodes -------- + std::vector lod_nodes; + std::vector devnull; + lod_loader.done(m_root, devnull, lod_nodes); + + std::map >& track_objects = + m_track_object_manager->getLodObjects(); + + for (unsigned int n=0; n& queue = track_objects[ lod_nodes[n]->getGroupName() ]; + assert( queue.size() > 0 ); + queue[ queue.size() - 1 ]->setNode( lod_nodes[n] ); + queue.erase( queue.end() - 1 ); + } + + track_objects.clear(); + // --------------------------------------------- + delete root; // Init all track objects diff --git a/src/tracks/track_object.cpp b/src/tracks/track_object.cpp index 49a227e5c..cad6c3fe2 100644 --- a/src/tracks/track_object.cpp +++ b/src/tracks/track_object.cpp @@ -55,6 +55,8 @@ TrackObject::TrackObject(const XMLNode &xml_node) std::string sound; xml_node.get("sound", &sound ); + xml_node.get("lod_group", &m_lod_group); + // FIXME: at this time sound emitters are just disabled in multiplayer // otherwise the sounds would be constantly heard if (sound.size() > 0 && race_manager->getNumLocalPlayers() == 1) diff --git a/src/tracks/track_object.hpp b/src/tracks/track_object.hpp index 6595ebb53..1a1706b8c 100644 --- a/src/tracks/track_object.hpp +++ b/src/tracks/track_object.hpp @@ -84,6 +84,9 @@ protected: /** If a sound is attached to this objectt and/or this is a sound emitter object */ SFXBase* m_sound; + /** LOD group this object is part of, if it is LOD */ + std::string m_lod_group; + public: TrackObject(const XMLNode &xml_node); TrackObject(const core::vector3df& pos, const core::vector3df& hpr, @@ -100,6 +103,19 @@ public: void setEnable(bool mode); scene::ISceneNode* getNode() { return m_node; } + + /** 2-step construction */ + void setNode(scene::ISceneNode* node) + { + assert(m_node == NULL); + m_node = node; + m_node->setPosition(m_init_xyz); + m_node->setRotation(m_init_hpr); + m_node->setScale(m_init_scale); + } + + const std::string& getLodGroup() const { return m_lod_group; } + }; // TrackObject #endif diff --git a/src/tracks/track_object_manager.cpp b/src/tracks/track_object_manager.cpp index 45c362a9b..13162d914 100644 --- a/src/tracks/track_object_manager.cpp +++ b/src/tracks/track_object_manager.cpp @@ -45,15 +45,33 @@ TrackObjectManager::~TrackObjectManager() */ void TrackObjectManager::add(const XMLNode &xml_node) { + std::string groupname; + xml_node.get("lod_group", &groupname); + bool is_lod = !groupname.empty(); + std::string type; xml_node.get("type", &type); if(type=="movable") { - m_all_objects.push_back(new PhysicalObject(xml_node)); + if (is_lod) + { + m_lod_objects[groupname].push_back(new PhysicalObject(xml_node)); + } + else + { + m_all_objects.push_back(new PhysicalObject(xml_node)); + } } else if(type=="animation") { - m_all_objects.push_back(new ThreeDAnimation(xml_node)); + if (is_lod) + { + m_lod_objects[groupname].push_back(new ThreeDAnimation(xml_node)); + } + else + { + m_all_objects.push_back(new ThreeDAnimation(xml_node)); + } } else if(type=="billboard") { diff --git a/src/tracks/track_object_manager.hpp b/src/tracks/track_object_manager.hpp index f20585d6c..903c277b7 100644 --- a/src/tracks/track_object_manager.hpp +++ b/src/tracks/track_object_manager.hpp @@ -28,12 +28,16 @@ class Track; class Vec3; class XMLNode; +#include +#include +#include + /** * \ingroup tracks */ class TrackObjectManager { -public: +protected: /** * The different type of track objects: physical objects, graphical * objects (without a physical representation) - the latter might be @@ -42,6 +46,11 @@ public: enum TrackObjectType {TO_PHYSICAL, TO_GRAPHICAL}; PtrVector m_all_objects; + /** Temporary storage for LOD objects whose XML node was read but whose + * scene node is not yet ready + */ + std::map > m_lod_objects; + public: TrackObjectManager(); ~TrackObjectManager(); @@ -62,6 +71,9 @@ public: const core::vector3df& scale); void removeObject(PhysicalObject* who); + + /** Get the queue of LOD objects that are waiting to be assigned a scene node */ + std::map >& getLodObjects() { return m_lod_objects; } }; // class TrackObjectManager #endif