Added support for changing the ambient color in certain areas of a track.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@4026 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2009-09-16 05:32:17 +00:00
parent 73ca693a15
commit e53d080286
15 changed files with 360 additions and 16 deletions

View File

@ -269,10 +269,14 @@ supertuxkart_SOURCES = \
states_screens/race_gui.hpp \
states_screens/state_manager.cpp \
states_screens/state_manager.hpp \
tracks/ambient_light_sphere.cpp \
tracks/ambient_light_sphere.hpp \
tracks/bezier_curve.cpp \
tracks/bezier_curve.hpp \
tracks/check_manager.cpp \
tracks/check_manager.hpp \
tracks/check_sphere.cpp \
tracks/check_sphere.hpp \
tracks/check_structure.cpp \
tracks/check_structure.hpp \
tracks/checkline.cpp \

View File

@ -608,6 +608,10 @@
<Filter
Name="tracks"
>
<File
RelativePath="..\..\tracks\ambient_light_sphere.cpp"
>
</File>
<File
RelativePath="..\..\tracks\bezier_curve.cpp"
>
@ -616,6 +620,10 @@
RelativePath="..\..\tracks\check_manager.cpp"
>
</File>
<File
RelativePath="..\..\tracks\check_sphere.cpp"
>
</File>
<File
RelativePath="..\..\tracks\check_structure.cpp"
>
@ -1326,6 +1334,10 @@
<Filter
Name="tracks"
>
<File
RelativePath="..\..\tracks\ambient_light_sphere.hpp"
>
</File>
<File
RelativePath="..\..\tracks\bezier_curve.hpp"
>
@ -1334,6 +1346,10 @@
RelativePath="..\..\tracks\check_manager.hpp"
>
</File>
<File
RelativePath="..\..\tracks\check_sphere.hpp"
>
</File>
<File
RelativePath="..\..\tracks\check_structure.hpp"
>

View File

@ -91,7 +91,7 @@ float MainLoop::getLimitedDt()
}
dt *= 0.001f;
return dt;
}
} // getLimitedDt
//-----------------------------------------------------------------------------
/** Updates all race related objects.

View File

@ -0,0 +1,85 @@
// $Id: ambient_light_sphere.cpp 1681 2008-04-09 13:52:48Z hikerstk $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 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/ambient_light_sphere.hpp"
#include <string>
#include <stdio.h>
#include "io/xml_node.hpp"
#include "modes/world.hpp"
#include "race/race_manager.hpp"
#include "tracks/track.hpp"
/** Constructor for a checksphere.
* \param check_manager Pointer to the check manager, which is needed when
* resetting e.g. new lap counters.
* \param node XML node containing the parameters for this checkline.
*/
AmbientLightSphere::AmbientLightSphere(CheckManager *check_manager,
const XMLNode &node)
: CheckSphere(check_manager, node)
{
m_ambient_color = video::SColor(255, 0, 255, 0); // green
m_inner_radius2 = 1;
node.get("inner-radius", &m_inner_radius2);
m_inner_radius2 *= m_inner_radius2; // store the squared value
node.get("color", &m_ambient_color);
} // AmbientLightSphere
// ----------------------------------------------------------------------------
void AmbientLightSphere::update(float dt)
{
CheckStructure::update(dt);
for(unsigned int i=0; i<race_manager->getNumKarts(); i++)
{
if(isInside(i))
{
float d2=getDistance2ForKart(i);
video::SColor color;
Track *track=RaceManager::getWorld()->getTrack();
if(d2<m_inner_radius2)
{ // Inside inner radius --> use new ambient color
color = m_ambient_color;
}
else // Interpolate between default and this ambient color
{
float f = (getRadius2()-d2)/(getRadius2()-m_inner_radius2);
const video::SColor &def = track->getDefaultAmbientColor();
color = m_ambient_color.getInterpolated(def, f);
}
track->setAmbientColor(color);
} // if active
} // for i<num_karts
} // update
// ----------------------------------------------------------------------------
/** Only calls the sphere check if the kart is a player kart, since other
* karts won't change the ambient light.
* \param old_pos Position in previous frame.
* \param new_pos Position in current frame.
* \param indx Index of the kart, can be used to store kart specific
* additional data.
*/
bool AmbientLightSphere::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
int indx)
{
if(!RaceManager::getWorld()->getKart(indx)->isPlayerKart()) return false;
return CheckSphere::isTriggered(old_pos, new_pos, indx);
} // isTriggered

View File

@ -0,0 +1,58 @@
// $Id: ambient_light_sphere.hpp 1681 2008-04-09 13:52:48Z hikerstk $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 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.
#ifndef HEADER_AMBIENT_LIGHT_SPHERE_HPP
#define HEADER_AMBIENT_LIGHT_SPHERE_HPP
#include "irrlicht.h"
using namespace irr;
#include "tracks/check_sphere.hpp"
class XMLNode;
class CheckManager;
/** This class implements a check sphere that is used to change the ambient
* light if a kart is inside this sphere. Besides a normal radius this
* sphere also has a 2nd 'inner' radius: player karts inside the inner
* radius will have the full new ambient light, karts outside the default
* light, and karts in between will mix the light dependent on distance.
*/
class AmbientLightSphere : public CheckSphere
{
private:
/** The inner radius defines the area during which the ambient light
* is extrapolated. The square of the value specified in the scene
* file is stored. */
float m_inner_radius2;
/** THe full ambient color to use once the kart is inside the
* inner radius. */
video::SColor m_ambient_color;
public:
AmbientLightSphere(CheckManager *check_manager,
const XMLNode &node);
virtual ~AmbientLightSphere() {};
virtual void update(float dt);
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
int indx);
}; // AmbientLightSphere
#endif

View File

@ -23,9 +23,11 @@
#include "io/xml_node.hpp"
#include "tracks/checkline.hpp"
#include "tracks/ambient_light_sphere.hpp"
#include "tracks/check_structure.hpp"
#include "tracks/track.hpp"
CheckManager::CheckManager(const XMLNode &node)
CheckManager::CheckManager(const XMLNode &node, Track *track)
{
for(unsigned int i=0; i<node.getNumNodes(); i++)
{
@ -33,8 +35,18 @@ CheckManager::CheckManager(const XMLNode &node)
const std::string &type = check_node->getName();
if(type=="checkline")
{
m_all_checks.push_back(new Checkline(this, *check_node));
}
Checkline *cl = new Checkline(this, *check_node);
m_all_checks.push_back(cl);
if(cl->getType()==CheckStructure::CT_NEW_LAP)
{
track->getQuadGraph().setStartCoordinate(cl->getCenterPoint());
}
} // checkline
else if(type=="check-sphere")
{
AmbientLightSphere *cs = new AmbientLightSphere(this, *check_node);
m_all_checks.push_back(cs);
} // checksphere
} // for i<node.getNumNodes
} // CheckManager

View File

@ -32,7 +32,7 @@ class CheckManager
private:
std::vector<CheckStructure*> m_all_checks;
public:
CheckManager(const XMLNode &node);
CheckManager(const XMLNode &node, Track *track);
void update(float dt);
void reset(const Track &track);
void activateNewLapChecks(int kart_index);

View File

@ -0,0 +1,69 @@
// $Id: check+sphere.cpp 1681 2008-04-09 13:52:48Z hikerstk $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 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/check_sphere.hpp"
#include <string>
#include <stdio.h>
#include "io/xml_node.hpp"
#include "modes/world.hpp"
#include "race/race_manager.hpp"
/** Constructor for a checksphere.
* \param check_manager Pointer to the check manager, which is needed when
* resetting e.g. new lap counters.
* \param node XML node containing the parameters for this checkline.
*/
CheckSphere::CheckSphere(CheckManager *check_manager, const XMLNode &node)
: CheckStructure(check_manager, node)
{
m_radius2 = 1;
node.get("radius", &m_radius2);
m_radius2 *= m_radius2;
node.get("xyz", &m_center_point);
m_is_inside.resize(race_manager->getNumKarts());
m_distance2.resize(race_manager->getNumKarts());
for(unsigned int i=0; i< race_manager->getNumKarts(); i++)
{
m_is_inside[i] = false;
}
} // CheckSphere
// ----------------------------------------------------------------------------
/** True if going from old_pos to new_pos enters or leaves this sphere. This
* function is called from update (of the checkline structure). It also
* updates the flag about which karts are inside
* \param old_pos Position in previous frame.
* \param new_pos Position in current frame.
* \param kart_id Index of the kart, can be used to store kart specific
* additional data.
*/
bool CheckSphere::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, int kart_id)
{
float old_dist2 = (old_pos-m_center_point).length2();
float new_dist2 = (new_pos-m_center_point).length2();
m_is_inside[kart_id] = new_dist2<m_radius2;
m_distance2[kart_id] = new_dist2;
// Trigger if the kart goes from outside (or border) to inside,
// or inside ro outside (or border).
return (old_dist2>=m_radius2 && new_dist2 < m_radius2) ||
(old_dist2< m_radius2 && new_dist2 >=m_radius2);
} // isTriggered

View File

@ -0,0 +1,70 @@
// $Id: check_sphere.hpp 1681 2008-04-09 13:52:48Z hikerstk $
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 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.
#ifndef HEADER_CHECK_SPHERE_HPP
#define HEADER_CHECK_SPHERE_HPP
#include "irrlicht.h"
using namespace irr;
#include "tracks/check_structure.hpp"
class XMLNode;
class CheckManager;
/** This class implements a check sphere that is used to change the ambient
* light if a kart is inside this sphere. Besides a normal radius this
* sphere also has a 2nd 'inner' radius: player karts inside the inner
* radius will have the full new ambient light, karts outside the default
* light, and karts in between will mix the light dependent on distance.
*/
class CheckSphere : public CheckStructure
{
private:
/** Center of the sphere. */
Vec3 m_center_point;
/** Squared radius of the sphere. */
float m_radius2;
/** A flag for each kart to indicate if it's inside of the sphere. */
std::vector<bool> m_is_inside;
/** Stores the distance of each kart from the center of this sphere.
* This saves some computations. */
std::vector<float> m_distance2;
public:
CheckSphere(CheckManager *check_manager, const XMLNode &node);
virtual ~CheckSphere() {};
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
int kart_id);
// ------------------------------------------------------------------------
/** Returns if kart indx is currently inside of the sphere. */
bool isInside(int index) const { return m_is_inside[index]; }
// -------------------------------------------------------------------------
/** Returns the squared distance of kart index from the enter of
* this sphere. */
float getDistance2ForKart(int index) const { return m_distance2[index];}
// -------------------------------------------------------------------------
/** Returns the center point of this checkline. */
Vec3 getCenterPoint() const { return m_center_point; }
// -------------------------------------------------------------------------
/** Returns the square of the radius of this sphere. */
float getRadius2() const { return m_radius2; }
}; // CheckSphere
#endif

View File

@ -34,10 +34,14 @@ CheckStructure::CheckStructure(CheckManager *check_manager,
m_check_type = CT_NEW_LAP;
else if(type=="reset-new-lap")
m_check_type = CT_RESET_NEW_LAP;
else if(type=="ambient-light")
m_check_type = CT_AMBIENT_SPHERE;
else
{
printf("Unknown check structure '%s' - ignored.\n", type.c_str());
}
m_active_at_reset=true;
node.get("active", &m_active_at_reset);
} // CheckStructure
// ----------------------------------------------------------------------------
@ -55,7 +59,7 @@ void CheckStructure::reset(const Track &track)
m_previous_position.push_back(xyz);
// Activate all checkline
m_is_active.push_back(true);
m_is_active.push_back(m_active_at_reset);
} // for i<getNumKarts
} // reset

View File

@ -53,7 +53,7 @@ public:
* structure at the rhoughly halfway mark of the track karts have to
* drive there first before a new lap will be counted.
*/
enum CheckType {CT_NEW_LAP, CT_RESET_NEW_LAP};
enum CheckType {CT_NEW_LAP, CT_RESET_NEW_LAP, CT_AMBIENT_SPHERE};
protected:
/** Stores the previous position of all karts. This is needed to detect
@ -69,6 +69,8 @@ private:
/** The type of this checkline. */
CheckType m_check_type;
/** True if this check structure should be activated at a reset. */
bool m_active_at_reset;
public:
CheckStructure(CheckManager *check_manager, const XMLNode &node);
virtual ~CheckStructure() {};
@ -84,6 +86,9 @@ public:
virtual void trigger(unsigned int kart_index);
virtual void reset(const Track &track);
virtual void activateNewLapCheck(int kart_index);
virtual Vec3 getCenterPoint() const=0;
/** Returns the type of this check structure. */
CheckType getType() const { return m_check_type; }
}; // CheckStructure
#endif

View File

@ -51,6 +51,16 @@ void Checkline::reset(const Track &track)
}
} // reset
// ----------------------------------------------------------------------------
/** Returns the center point of this checkline.
*/
Vec3 Checkline::getCenterPoint() const
{
core::vector2df c=m_line.getMiddle();
Vec3 xyz(c.X, c.Y, m_min_height);
return xyz;
} // getCenterPoint
// ----------------------------------------------------------------------------
/** True if going from old_pos to new_pos crosses this checkline. This function
* is called from update (of the checkline structure).

View File

@ -53,6 +53,7 @@ public:
virtual ~Checkline() {};
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, int indx);
virtual void reset(const Track &track);
virtual Vec3 getCenterPoint() const;
}; // ChecklineManager
#endif

View File

@ -81,9 +81,9 @@ Track::Track(std::string filename)
/** Destructor, removes quad data structures etc. */
Track::~Track()
{
if(m_quad_graph) delete m_quad_graph;
if(m_check_manager) delete m_check_manager;
if(m_mini_map) irr_driver->removeTexture(m_mini_map);
if(m_quad_graph) delete m_quad_graph;
if(m_check_manager) delete m_check_manager;
if(m_mini_map) irr_driver->removeTexture(m_mini_map);
} // ~Track
//-----------------------------------------------------------------------------
@ -93,6 +93,7 @@ Track::~Track()
*/
void Track::reset()
{
m_ambient_color = m_default_ambient_color;
if(m_animation_manager)
m_animation_manager->reset();
if(m_check_manager)
@ -201,7 +202,7 @@ void Track::loadTrackInfo(const std::string &filename)
m_sun_position = core::vector3df(0.4f, 0.4f, 0.4f);
m_sky_color = video::SColorf(0.3f, 0.7f, 0.9f, 1.0f);
m_fog_color = video::SColorf(0.3f, 0.7f, 0.9f, 1.0f).toSColor();
m_ambient_color = video::SColorf(0.5f, 0.5f, 0.5f, 1.0f);
m_default_ambient_color = video::SColor(255, 120, 120, 120);
m_specular_color = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f);
m_diffuse_color = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f);
XMLNode *root = file_manager->createXMLTree(m_filename);
@ -504,6 +505,8 @@ void Track::handleAnimatedTextures(scene::ISceneNode *node, const XMLNode &xml)
*/
void Track::update(float dt)
{
irr_driver->getSceneManager()->setAmbientLight(m_ambient_color);
for(unsigned int i=0; i<m_animated_textures.size(); i++)
{
m_animated_textures[i]->update(dt);
@ -693,7 +696,7 @@ void Track::loadTrackModel(unsigned int mode_id)
}
else if(name=="checks")
{
m_check_manager = new CheckManager(*node);
m_check_manager = new CheckManager(*node, this);
}
else if(name=="sky-dome" || name=="sky-box")
{
@ -746,7 +749,7 @@ void Track::loadTrackModel(unsigned int mode_id)
file_manager->popTextureSearchPath();
file_manager->popModelSearchPath ();
irr_driver->getSceneManager()->setAmbientLight(video::SColor(255, 120, 120, 120));
irr_driver->getSceneManager()->setAmbientLight(m_ambient_color);
m_light = irr_driver->getSceneManager()->addLightSceneNode(NULL, m_sun_position,
video::SColorf(1.0f,1.0f,1.0f));

View File

@ -131,7 +131,8 @@ private:
float m_fog_start;
float m_fog_end;
core::vector3df m_sun_position;
video::SColorf m_ambient_color;
video::SColor m_default_ambient_color;
video::SColor m_ambient_color;
video::SColorf m_specular_color;
video::SColorf m_diffuse_color;
video::SColorf m_sky_color;
@ -220,9 +221,9 @@ public:
void handleExplosion(const Vec3 &pos, const PhysicalObject *mp) const;
/** Sets pointer to the aabb of this track. */
void getAABB(const Vec3 **min, const Vec3 **max) const
{ *min = &m_aabb_min; *max = &m_aabb_max; }
{ *min = &m_aabb_min; *max = &m_aabb_max; }
/** Returns the graph of quads, mainly for the AI. */
const QuadGraph& getQuadGraph() const { return *m_quad_graph; }
QuadGraph& getQuadGraph() const { return *m_quad_graph; }
/** Returns 'a' angle for quad n. This angle is used to position a kart
* after a rescue, and to detect wrong directions. This function will
@ -248,6 +249,12 @@ public:
/** Returns the name of the i-th. mode. */
const std::string &getModeName(unsigned int i) const
{ return m_all_modes[i].m_name;}
/** Returns the default ambient color. */
const video::SColor &getDefaultAmbientColor() const
{ return m_default_ambient_color;}
/** Sets the current ambient color. */
void setAmbientColor(const video::SColor &color)
{ m_ambient_color = color; }
}; // class Track
#endif