diff --git a/src/Makefile.am b/src/Makefile.am index be1e8f860..918382ee4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -63,6 +63,8 @@ supertuxkart_SOURCES = \ graphics/explosion.hpp \ graphics/irr_driver.cpp \ graphics/irr_driver.hpp \ + graphics/lod_node.cpp \ + graphics/lod_node.hpp \ graphics/material.cpp \ graphics/material.hpp \ graphics/material_manager.cpp \ diff --git a/src/graphics/lod_node.cpp b/src/graphics/lod_node.cpp new file mode 100644 index 000000000..b27ded809 --- /dev/null +++ b/src/graphics/lod_node.cpp @@ -0,0 +1,77 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2011 Marianne Gagnon +// based on code Copyright (C) 2002-2010 Nikolaus Gebhardt +// +// 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 "graphics/irr_driver.hpp" +#include "graphics/lod_node.hpp" + + +LODNode::LODNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id) + : IDummyTransformationSceneNode(parent, mgr, id) +{ + parent->addChild(this); +} + +LODNode::~LODNode() +{ +} + +void LODNode::render() +{ + ISceneNode::OnRegisterSceneNode(); + //ISceneNode::render(); +} + +void LODNode::OnRegisterSceneNode() +{ + // TODO: optimize this, there is no need to check every frame + scene::ICameraSceneNode* curr_cam = irr_driver->getSceneManager()->getActiveCamera(); + + // Assumes all children are at the same location + const int dist = m_nodes[0]->getPosition().getDistanceFromSQ( curr_cam->getPosition() ); + + for (unsigned int n=0; nOnRegisterSceneNode(); + return; + } + } + + if (dist >= m_detail[m_nodes.size()-1]) + { + m_nodes[m_nodes.size()-1]->OnRegisterSceneNode(); + } + else + { + // This probably means the first level of detail is not 0 + assert(false); + } + //ISceneNode::OnRegisterSceneNode(); +} + +void LODNode::add(int level, scene::ISceneNode* node, bool reparent) +{ + // FIXME : this class assumes that 'm_detail' is sorted, this may not always be the case + node->grab(); + node->remove(); + m_detail.push_back(level*level); + m_nodes.push_back(node); + node->setParent(this); + node->drop(); +} diff --git a/src/graphics/lod_node.hpp b/src/graphics/lod_node.hpp new file mode 100644 index 000000000..6e81569d4 --- /dev/null +++ b/src/graphics/lod_node.hpp @@ -0,0 +1,65 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2011 Marianne Gagnon +// based on code Copyright (C) 2002-2010 Nikolaus Gebhardt +// +// 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. + +#ifndef HEADER_LOD_NODE_HPP +#define HEADER_LOD_NODE_HPP + +#include "irrlicht.h" +using namespace irr; + + +/** + * \brief manages smoke particle effects + * \ingroup graphics + */ +class LODNode : public scene::IDummyTransformationSceneNode +{ +private: + core::matrix4 RelativeTransformationMatrix; + core::aabbox3d Box; + + std::vector m_detail; + std::vector m_nodes; + +public: + + LODNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id); + virtual ~LODNode(); + + //! returns the axis aligned bounding box of this node + virtual const core::aabbox3d& getBoundingBox() const { return Box; } + + //! Returns a reference to the current relative transformation matrix. + //! This is the matrix, this scene node uses instead of scale, translation + //! and rotation. + virtual core::matrix4& getRelativeTransformationMatrix() { return RelativeTransformationMatrix; } + + //! Returns the relative transformation of the scene node. + virtual core::matrix4 getRelativeTransformation() const { return RelativeTransformationMatrix; } + + void add(int level, scene::ISceneNode* node, bool reparent); + + virtual void OnRegisterSceneNode(); + virtual void render(); + + virtual scene::ESCENE_NODE_TYPE getType() const { return scene::ESNT_DUMMY_TRANSFORMATION; } + +}; + +#endif + diff --git a/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj b/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj index 9538748ce..6fdc48320 100644 --- a/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj +++ b/src/ide/Xcode/STK_XCode.xcodeproj/project.pbxproj @@ -47,6 +47,7 @@ 952A154D103F66D600B1895D /* shadow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 952A153D103F66D600B1895D /* shadow.cpp */; }; 952A154E103F66D600B1895D /* skid_marks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 952A153F103F66D600B1895D /* skid_marks.cpp */; }; 952A1554103F68D000B1895D /* profile_world.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 952A1552103F68D000B1895D /* profile_world.cpp */; }; + 95376CAF1320784100C842A4 /* lod_node.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95376CAD1320784100C842A4 /* lod_node.cpp */; }; 953789730FC7829100DD1F8E /* graph_node.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 953789720FC7829100DD1F8E /* graph_node.cpp */; }; 953789820FC7831400DD1F8E /* quad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 953789810FC7831400DD1F8E /* quad.cpp */; }; 9538A56012CD094200CE3220 /* addon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9538A55E12CD094200CE3220 /* addon.cpp */; }; @@ -441,6 +442,8 @@ 952A1540103F66D600B1895D /* skid_marks.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = skid_marks.hpp; path = ../../graphics/skid_marks.hpp; sourceTree = SOURCE_ROOT; }; 952A1552103F68D000B1895D /* profile_world.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = profile_world.cpp; path = ../../modes/profile_world.cpp; sourceTree = SOURCE_ROOT; }; 952A1553103F68D000B1895D /* profile_world.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = profile_world.hpp; path = ../../modes/profile_world.hpp; sourceTree = SOURCE_ROOT; }; + 95376CAD1320784100C842A4 /* lod_node.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lod_node.cpp; path = ../../graphics/lod_node.cpp; sourceTree = SOURCE_ROOT; }; + 95376CAE1320784100C842A4 /* lod_node.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = lod_node.hpp; path = ../../graphics/lod_node.hpp; sourceTree = SOURCE_ROOT; }; 953789710FC7829100DD1F8E /* graph_node.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = graph_node.hpp; path = ../../tracks/graph_node.hpp; sourceTree = SOURCE_ROOT; }; 953789720FC7829100DD1F8E /* graph_node.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = graph_node.cpp; path = ../../tracks/graph_node.cpp; sourceTree = SOURCE_ROOT; }; 953789800FC7831400DD1F8E /* quad.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = quad.hpp; path = ../../tracks/quad.hpp; sourceTree = SOURCE_ROOT; }; @@ -1355,6 +1358,8 @@ 952A1530103F66D600B1895D /* explosion.hpp */, 952A1531103F66D600B1895D /* irr_driver.cpp */, 952A1532103F66D600B1895D /* irr_driver.hpp */, + 95376CAD1320784100C842A4 /* lod_node.cpp */, + 95376CAE1320784100C842A4 /* lod_node.hpp */, 952A1533103F66D600B1895D /* material.cpp */, 952A1534103F66D600B1895D /* material.hpp */, 952A1535103F66D600B1895D /* material_manager.cpp */, @@ -2980,6 +2985,7 @@ 9559DE7F12FF777600350DE8 /* rain.cpp in Sources */, 9592DC6D13021B350039DBC8 /* minimal_race_gui.cpp in Sources */, 95E1FCDF130369EB004D83CC /* per_camera_node.cpp in Sources */, + 95376CAF1320784100C842A4 /* lod_node.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index a1cca44a3..7cf3ee57e 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -33,6 +33,7 @@ using namespace irr; #include "graphics/camera.hpp" #include "graphics/CBatchingMesh.hpp" #include "graphics/irr_driver.hpp" +#include "graphics/lod_node.hpp" #include "graphics/material_manager.hpp" #include "graphics/mesh_tools.hpp" #include "graphics/moving_texture.hpp" @@ -521,6 +522,8 @@ bool Track::loadMainTrack(const XMLNode &root) MeshTools::minMax3D(merged_mesh, &m_aabb_min, &m_aabb_max); World::getWorld()->getPhysics()->init(m_aabb_min, m_aabb_max); + std::map< std::string, std::vector< std::pair > > lod_groups; + for(unsigned int i=0; igetNumNodes(); i++) { const XMLNode *n=track_node->getNode(i); @@ -549,6 +552,12 @@ bool Track::loadMainTrack(const XMLNode &root) core::vector3df scale(1.0f, 1.0f, 1.0f); n->get("scale", &scale); + std::string lodgroup; + n->get("lodgroup", &lodgroup); + + int detail = -1; + n->get("detail", &detail); + if (tangent) { scene::IMeshManipulator* manip = irr_driver->getVideoDriver()->getMeshManipulator(); @@ -601,9 +610,31 @@ bool Track::loadMainTrack(const XMLNode &root) handleAnimatedTextures(scene_node, *n); - m_all_nodes.push_back(scene_node); + + if (lodgroup.empty()) + { + m_all_nodes.push_back( scene_node ); + } + else + { + lod_groups[lodgroup].push_back( std::pair(detail, scene_node) ); + } } // for i + scene::ISceneManager* sm = irr_driver->getSceneManager(); + scene::ISceneNode* sroot = sm->getRootSceneNode(); + std::map > >::iterator it; + for (it = lod_groups.begin(); it != lod_groups.end(); it++) + { + LODNode* node = new LODNode(sroot, sm, -1); + std::vector< std::pair >& nodes = it->second; + for (unsigned int n=0; nadd( nodes[n].first, nodes[n].second, true ); + } + m_all_nodes.push_back( node ); + } + // This will (at this stage) only convert the main track model. for(unsigned int i=0; i