Add the basic infrastructure to support level-of-detail. Note that at this time the implementation is not the most efficient one can think of so let's not use this widely just yet

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@7805 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria 2011-03-04 02:11:39 +00:00
parent 4fac382508
commit c08b9b3a7f
5 changed files with 182 additions and 1 deletions
src
Makefile.am
graphics
ide/Xcode/STK_XCode.xcodeproj
tracks

@ -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 \

77
src/graphics/lod_node.cpp Normal file

@ -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; n<m_detail.size(); n++)
{
if (dist < m_detail[n])
{
m_nodes[n]->OnRegisterSceneNode();
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();
}

65
src/graphics/lod_node.hpp Normal file

@ -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<f32> Box;
std::vector<int> m_detail;
std::vector<scene::ISceneNode*> 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<f32>& 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

@ -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;
};

@ -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<int, scene::ISceneNode*> > > lod_groups;
for(unsigned int i=0; i<track_node->getNumNodes(); 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<int, scene::ISceneNode*>(detail, scene_node) );
}
} // for i
scene::ISceneManager* sm = irr_driver->getSceneManager();
scene::ISceneNode* sroot = sm->getRootSceneNode();
std::map<std::string, std::vector< std::pair<int, scene::ISceneNode*> > >::iterator it;
for (it = lod_groups.begin(); it != lod_groups.end(); it++)
{
LODNode* node = new LODNode(sroot, sm, -1);
std::vector< std::pair<int, scene::ISceneNode*> >& nodes = it->second;
for (unsigned int n=0; n<nodes.size(); n++)
{
node->add( 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<m_all_nodes.size(); i++)
{