First version of new skidmark implementation.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@2547 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2008-12-02 13:01:39 +00:00
parent b1f7662931
commit 325a9dce30
8 changed files with 265 additions and 362 deletions

View File

@ -58,7 +58,7 @@ supertuxkart_SOURCES = main.cpp \
grand_prix_manager.cpp grand_prix_manager.hpp \
graphics/nitro.cpp graphics/nitro.hpp \
graphics/particle_system.cpp graphics/particle_system.hpp \
graphics/skid_mark.cpp graphics/skid_mark.hpp \
graphics/skid_marks.cpp graphics/skid_marks.hpp \
graphics/smoke.cpp graphics/smoke.hpp \
items/attachment.cpp items/attachment.hpp \
items/attachment_manager.cpp items/attachment_manager.hpp \

View File

@ -1,236 +0,0 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
//
// 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 "scene.hpp"
#include "skid_mark.hpp"
#include "utils/coord.hpp"
float SkidMark::m_global_track_offset = 0.005f;
SkidMark::SkidMark(float angle_sign)
{
m_skid_state = new ssgSimpleState();
m_angle_sign = angle_sign;
m_skid_state->ref();
m_skid_state -> enable (GL_BLEND);
//This is just for the skidmarks, so the ones drawn when the kart is in
//reverse get drawn
m_skid_state -> disable (GL_CULL_FACE);
m_skid_marking = false;
} // SkidMark
//-----------------------------------------------------------------------------
SkidMark::~SkidMark()
{
if(!m_skid_marks.empty())
{
const unsigned int SIZE = (unsigned int)m_skid_marks.size() -1;
for(unsigned int i = 0; i < SIZE; ++i)
{
ssgDeRefDelete(m_skid_marks[i]);
} // for
} // if !empty
ssgDeRefDelete(m_skid_state);
} // ~SkidMark
//-----------------------------------------------------------------------------
void SkidMark::add(const Coord& coord, float angle, float length)
{
if(m_skid_marking)
{
const int CURRENT = (int)m_skid_marks.size() - 1;
m_skid_marks[CURRENT]->add(coord, m_angle_sign*angle, length);
}
else
{
addBreak(coord, angle, length);
}
} // add
//-----------------------------------------------------------------------------
void SkidMark::addBreak(const Coord& kart_coord, float angle, float length)
{
Coord coord(kart_coord);
float rad_angle = DEGREE_TO_RAD(m_angle_sign*angle);
Vec3 add( length * sin(coord.getHeading() + rad_angle),
-length * cos(coord.getHeading() + rad_angle),
0);
coord.setXYZ(coord.getXYZ()+add);
const unsigned int CURRENT = (unsigned int)m_skid_marks.size() - 1;
if(m_skid_marking)
m_skid_marks[CURRENT]->addEnd(coord);
else
{
m_global_track_offset += 0.005f;
if(m_global_track_offset > 0.05f) m_global_track_offset = 0.01f;
// Width of the skidmark
const float WIDTH = 0.1f;
sgVec3 pos;
sgSetVec3(pos,
coord.getX() + sin(coord.getHeading()-M_PI*0.5f) * WIDTH,
coord.getY() - cos(coord.getHeading()-M_PI*0.5f) * WIDTH,
coord.getZ() + m_global_track_offset);
ssgVertexArray* SkidMarkVertices = new ssgVertexArray;
SkidMarkVertices->add(pos);
sgSetVec3(pos,
coord.getX() + sin(coord.getHeading()+M_PI*0.5f) * WIDTH,
coord.getY() - cos(coord.getHeading()+M_PI*0.5f) * WIDTH,
coord.getZ() + m_global_track_offset);
SkidMarkVertices->add(pos);
sgVec3 norm;
sgSetVec3(norm, 0, 0, 1);
ssgNormalArray* SkidMarkNormals = new ssgNormalArray;
SkidMarkNormals->add(norm);
SkidMarkNormals->add(norm);
sgVec4 color;
sgSetVec4(color, 0, 0, 0, 1);
ssgColourArray* SkidMarkColors = new ssgColourArray;
SkidMarkColors->add(color);
SkidMarkColors->add(color);
SkidMarkPos* new_skid_mark = new SkidMarkPos( SkidMarkVertices,
SkidMarkNormals,
SkidMarkColors,
m_global_track_offset);
new_skid_mark->ref();
scene->add(new_skid_mark);
new_skid_mark-> setState (m_skid_state);
m_skid_marks.push_back(new_skid_mark);
} // if m_skid_marking
m_skid_marking = !m_skid_marking;
} // addBreak
//-----------------------------------------------------------------------------
bool SkidMark::wasSkidMarking() const
{
return m_skid_marking;
} // wasSkidMarking
//=============================================================================
SkidMark::SkidMarkPos::SkidMarkPos() : ssgVtxTable ( GL_QUAD_STRIP,
new ssgVertexArray,
new ssgNormalArray,
new ssgTexCoordArray,
new ssgColourArray )
{} // SkidMarkPos
//-----------------------------------------------------------------------------
SkidMark::SkidMarkPos::SkidMarkPos( ssgVertexArray* vertices,
ssgNormalArray* normals,
ssgColourArray* colors,
float global_track_offset) :
ssgVtxTable ( GL_QUAD_STRIP,
vertices,
normals,
new ssgTexCoordArray,
colors )
{
m_track_offset = global_track_offset;
} // SkidMarkPos
//-----------------------------------------------------------------------------
SkidMark::SkidMarkPos::~SkidMarkPos()
{} // ~SkidMarkPos
//-----------------------------------------------------------------------------
void SkidMark::SkidMarkPos::recalcBSphere()
{
bsphere . setRadius ( 1000.0f ) ;
bsphere . setCenter ( 0, 0, 0 ) ;
} // recalcBSphere
//-----------------------------------------------------------------------------
void SkidMark::SkidMarkPos::add(const Coord& kart_coord, float angle, float length)
{
Coord coord(kart_coord);
Vec3 add( length * sin(kart_coord.getHPR().getHeading() + angle),
-length * cos(kart_coord.getHPR().getHeading() + angle),
0);
coord.setXYZ(coord.getXYZ()+add);
// Width of the skidmark
const float WIDTH = 0.1f;
static float a = 0.5f;
sgVec3 pos;
sgSetVec3(pos,
coord.getX() + sgSin(coord.getHeading()+a*M_PI) * WIDTH,
coord.getY() - sgCos(coord.getHeading()+a*M_PI) * WIDTH,
coord.getZ() + m_track_offset);
vertices->add(pos);
sgSetVec3(pos,
coord.getX() + sin(coord.getHeading()-a*M_PI) * WIDTH,
coord.getY() - cos(coord.getHeading()-a*M_PI) * WIDTH,
coord.getZ() + m_track_offset);
vertices->add(pos);
a = (a > 0.0f ? -0.5f : 0.5f);
sgVec3 norm;
sgSetVec3(norm, 0, 0, 1);
normals->add(norm); normals->add(norm);
sgVec4 color;
sgSetVec4(color, 0.07f, 0.07f, 0.07f, 0.8f);
colours->add(color); colours->add(color);
this->dirtyBSphere();
} // add
//-----------------------------------------------------------------------------
void SkidMark::SkidMarkPos::addEnd(const Coord& coord)
{
// Width of the skidmark
const float width = 0.1f;
sgVec3 pos;
sgSetVec3(pos,
coord.getX() + sin(coord.getHeading()-M_PI*0.5f) * width,
coord.getY() - cos(coord.getHeading()-M_PI*0.5f) * width,
coord.getZ() + m_track_offset);
vertices->add(pos);
sgSetVec3(pos,
coord.getX() + sin(coord.getHeading()+M_PI*0.5f) * width,
coord.getY() - cos(coord.getHeading()+M_PI*0.5f) * width,
coord.getZ() + m_track_offset);
vertices->add(pos);
sgVec3 norm;
sgSetVec3(norm, 0, 0, 1);
normals->add(norm); normals->add(norm);
sgVec4 color;
sgSetVec4(color, 0.15f, 0.15f, 0.15f, 0.0f);
colours->add(color); colours->add(color);
makeDList();
} // addEnd
/* EOF */

View File

@ -1,77 +0,0 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
//
// 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_SKID_MARK_HPP
#define HEADER_SKID_MARK_HPP
#include <vector>
#include <plib/ssg.h>
class Coord;
class SkidMark
{
private:
float m_angle_sign;
public:
SkidMark(float angle_sign);
~SkidMark();
void add (const Coord& coord, // Add a position where the skidmark is
float angle,
float length);
void addBreak (const Coord& coord, //Begin or finish an skidmark
float angle,
float length);
bool wasSkidMarking() const;
private:
class SkidMarkPos : public ssgVtxTable
{
public:
SkidMarkPos ();
SkidMarkPos (ssgVertexArray* vertices,
ssgNormalArray* normals,
ssgColourArray* colors,
float global_track_offset);
~SkidMarkPos ();
void recalcBSphere();
void add (const Coord& coord, // Add a position where the skidmark is
float angle,
float length);
void addEnd (const Coord& coord);
private:
float m_track_offset; // Amount of which the skidmark is lifted
// above the track to avoid z-buffer errors
}
; // SkidMarkPos
bool m_skid_marking;
static float m_global_track_offset; // This is to make Z-fighting between
// skidmarks less likely, specially the
// skidmarks made by the AI
std::vector <SkidMarkPos *> m_skid_marks;
ssgSimpleState *m_skid_state;
};
#endif
/* EOF */

184
src/graphics/skid_marks.cpp Normal file
View File

@ -0,0 +1,184 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
//
// 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/skid_marks.hpp"
#include "scene.hpp"
#include "karts/kart.hpp"
#include "utils/coord.hpp"
/** Initialises empty skid marks. */
SkidMarks::SkidMarks(const Kart& kart, float width) : m_kart(kart)
{
m_width = width;
m_skid_state = new ssgSimpleState();
m_skid_state->ref();
m_skid_state->enable(GL_BLEND);
//This is just for the skidmarks, so the ones drawn when the kart is in
//reverse get drawn
// m_skid_state -> disable (GL_CULL_FACE);
m_skid_marking = false;
} // SkidMark
//-----------------------------------------------------------------------------
SkidMarks::~SkidMarks()
{
#ifdef NOTYET
if(!m_skid_marks.empty())
{
const unsigned int SIZE = (unsigned int)m_skid_marks.size() -1;
for(unsigned int i = 0; i < SIZE; ++i)
{
ssgDeRefDelete(m_skid_marks[i]);
} // for
} // if !empty
ssgDeRefDelete(m_skid_state);
#endif
} // ~SkidMarks
//-----------------------------------------------------------------------------
void SkidMarks::update(float dt)
{
if(m_skid_marking)
{
// Get raycast information
// -----------------------
const btWheelInfo::RaycastInfo &raycast_right =
m_kart.getVehicle()->getWheelInfo(2).m_raycastInfo;
const btWheelInfo::RaycastInfo raycast_left =
m_kart.getVehicle()->getWheelInfo(3).m_raycastInfo;
Vec3 delta = raycast_right.m_contactPointWS - raycast_left.m_contactPointWS;
int current=m_left.size()-1;
// We were skid marking, but not anymore (either because the
// wheels don't touch the ground, or the kart has stopped
// skidding). One special case: the physics force both wheels
// on one axis to touch the ground. If only one wheel touches
// the ground, the 2nd one gets the same raycast result -->
// delta is 0, and the behaviour is undefined. In this case
// just stop doing skid marks as well.
// ---------------------------------------------------------
if(!raycast_right.m_isInContact || !m_kart.getControls().jump ||
delta.length2()<0.0001)
{
m_skid_marking = false;
m_left[current]->makeDList();
m_right[current]->makeDList();
return;
}
// We are still skid marking, so add the latest quad
// -------------------------------------------------
delta.normalize();
delta *= m_width;
m_left [current]->add(raycast_left.m_contactPointWS,
raycast_left.m_contactPointWS + delta);
m_right[current]->add(raycast_right.m_contactPointWS-delta,
raycast_right.m_contactPointWS);
return;
}
// Currently no skid marking
// -------------------------
if(!m_kart.getControls().jump) return; // no skidmarking
// Start new skid marks
// --------------------
const btWheelInfo::RaycastInfo &raycast_right =
m_kart.getVehicle()->getWheelInfo(2).m_raycastInfo;
// No skidmarking if wheels don't have contact
if(!raycast_right.m_isInContact) return;
const btWheelInfo::RaycastInfo raycast_left =
m_kart.getVehicle()->getWheelInfo(3).m_raycastInfo;
Vec3 delta = raycast_right.m_contactPointWS - raycast_left.m_contactPointWS;
// Special case: only one wheel on one axis touches the ground --> physics
// set both wheels to touch the same spot --> delta = 0. In this case,
// don't start skidmarks.
if(delta.length2()<0.0001) return;
delta.normalize();
delta *= m_width;
SkidMarkQuads *smq_left = new SkidMarkQuads(raycast_left.m_contactPointWS,
raycast_left.m_contactPointWS + delta,
m_skid_state);
scene->add(smq_left);
m_left.push_back(smq_left);
SkidMarkQuads *smq_right = new SkidMarkQuads(raycast_right.m_contactPointWS
- delta,
raycast_right.m_contactPointWS,
m_skid_state);
scene->add(smq_right);
m_right.push_back(smq_right);
m_skid_marking = true;
} // update
//=============================================================================
SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left, const Vec3 &right,
ssgSimpleState *state)
: ssgVtxTable(GL_QUAD_STRIP,
new ssgVertexArray,
new ssgNormalArray,
new ssgTexCoordArray,
new ssgColourArray )
{
setState(state);
add(left, right);
} // SkidMarkQuads
//-----------------------------------------------------------------------------
SkidMarks::SkidMarkQuads::~SkidMarkQuads()
{} // ~SkidMarkPos
//-----------------------------------------------------------------------------
void SkidMarks::SkidMarkQuads::recalcBSphere()
{
bsphere.setRadius(1000.0f);
bsphere.setCenter(0, 0, 0);
} // recalcBSphere
//-----------------------------------------------------------------------------
void SkidMarks::SkidMarkQuads::add(const Vec3 &left, const Vec3 &right)
{
// The skid marks must be raised slightly higher, otherwise it blends
// too much with the track.
sgVec3 l;
sgCopyVec3(l, left.toFloat());
l[2]+=0.01f;
sgVec3 r;
sgCopyVec3(r, right.toFloat());
r[2]+=0.01f;
vertices->add(l);
vertices->add(r);
sgVec3 normal;
sgSetVec3(normal, 0, 0, 1);
normals->add(normal);normals->add(normal);
sgVec4 colour;
sgSetVec4(colour, 0.07f, 0.07f, 0.07f, 0.8f);
colours->add(colour); colours->add(colour);
dirtyBSphere();
} // add

View File

@ -0,0 +1,70 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
//
// 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_SKID_MARK_HPP
#define HEADER_SKID_MARK_HPP
#include <vector>
#define _WINSOCKAPI_
#include <plib/ssg.h>
#include "utils/vec3.hpp"
class Coord;
class Kart;
/** This class is responsible for drawing skid marks for a kart. */
class SkidMarks
{
private:
/** Reference to the kart to which these skidmarks belong. */
const Kart &m_kart;
/** True if the kart was skidding in the previous frame. */
bool m_skid_marking;
/** Reduce effect of Z-fighting. */
float m_width;
class SkidMarkQuads : public ssgVtxTable
{
public:
SkidMarkQuads (const Vec3 &left, const Vec3 &right,
ssgSimpleState *state);
~SkidMarkQuads();
void recalcBSphere();
void add (const Vec3 &left,
const Vec3 &right);
private:
float m_track_offset; // Amount of which the skidmark is lifted
// above the track to avoid z-buffer errors
}; // SkidMarkQuads
/** Two skidmark objects for the left and right wheel. */
std::vector <SkidMarkQuads *> m_left, m_right;
ssgSimpleState *m_skid_state;
public:
SkidMarks(const Kart& kart, float width=0.2f);
~SkidMarks();
void update (float dt);
}; // SkidMarks
#endif
/* EOF */

View File

@ -1187,7 +1187,7 @@
>
</File>
<File
RelativePath="..\..\graphics\skid_mark.cpp"
RelativePath="..\..\graphics\skid_marks.cpp"
>
</File>
<File
@ -1829,7 +1829,7 @@
>
</File>
<File
RelativePath="..\..\graphics\skid_mark.hpp"
RelativePath="..\..\graphics\skid_marks.hpp"
>
</File>
<File

View File

@ -43,7 +43,7 @@
#include "audio/sfx_manager.hpp"
#include "audio/sfx_base.hpp"
#include "graphics/nitro.hpp"
#include "graphics/skid_mark.hpp"
#include "graphics/skid_marks.hpp"
#include "graphics/smoke.hpp"
#include "gui/menu_manager.hpp"
#include "gui/race_gui.hpp"
@ -79,9 +79,7 @@ Kart::Kart (const std::string& kart_name, int position,
m_wheelie_angle = 0.0f;
m_smoke_system = NULL;
m_nitro = NULL;
m_skidmark_left = NULL;
m_skidmark_right = NULL;
m_skidmarks = NULL;
// Set position and heading:
m_reset_transform = init_transform;
@ -248,8 +246,7 @@ Kart::~Kart()
ssgDeRefDelete(m_shadow);
if(m_skidmark_left ) delete m_skidmark_left ;
if(m_skidmark_right) delete m_skidmark_right;
if(m_skidmarks) delete m_skidmarks ;
RaceManager::getWorld()->getPhysics()->removeKart(this);
delete m_vehicle;
@ -584,8 +581,7 @@ void Kart::update(float dt)
// Check if any item was hit.
item_manager->hitItem(this);
processSkidMarks();
m_skidmarks->update(dt);
} // update
//-----------------------------------------------------------------------------
@ -890,34 +886,6 @@ void Kart::endRescue()
RaceManager::getWorld()->getPhysics()->addKart(this, m_vehicle);
} // endRescue
//-----------------------------------------------------------------------------
void Kart::processSkidMarks()
{
const float threshold = 0.3f;
const float ANGLE = 43.0f;
const float LENGTH = 0.57f;
if(m_skidding>1 && isOnGround())
{
Coord coord(getXYZ(), getHPR());
coord.setZ(getVehicle()->getWheelInfo(2).m_raycastInfo.m_contactPointWS.getZ());
m_skidmark_right->add(coord, ANGLE, LENGTH);
coord.setZ(getVehicle()->getWheelInfo(2).m_raycastInfo.m_contactPointWS.getZ());
m_skidmark_left ->add(coord, ANGLE, LENGTH);
}
else
{
// Either both sides are skidding, or none at all
if(m_skidmark_left->wasSkidMarking())
{
Coord coord(getXYZ(), getHPR());
coord.setZ(getVehicle()->getWheelInfo(2).m_raycastInfo.m_contactPointWS.getZ());
m_skidmark_right->addBreak(coord, ANGLE, LENGTH);
coord.setZ(getVehicle()->getWheelInfo(3).m_raycastInfo.m_contactPointWS.getZ());
m_skidmark_left ->addBreak(coord, ANGLE, LENGTH);
}
}
} // processSkidMarks
//-----------------------------------------------------------------------------
#include <scene.hpp>
void Kart::loadData()
@ -937,15 +905,12 @@ void Kart::loadData()
getModelTransform() -> addKid ( lod ) ;
// Attach Particle System
m_smoke_system = new Smoke(this);
m_smoke_system->ref();
m_nitro = new Nitro(this);
m_nitro->ref();
m_skidmark_left = new SkidMark(/* angle sign */ -1);
m_skidmark_right = new SkidMark(/* angle sign */ 1);
m_skidmarks = new SkidMarks(*this);
m_shadow = createShadow(m_kart_properties->getShadowFile(), -1, 1, -1, 1);
m_shadow->ref();

View File

@ -33,7 +33,7 @@
#include "items/powerup.hpp"
#include "karts/kart_model.hpp"
class SkidMark;
class SkidMarks;
class Item;
class Smoke;
class Nitro;
@ -86,9 +86,8 @@ private:
* at all compressed. */
float m_default_suspension_length[4];
SkidMark* m_skidmark_left;
SkidMark* m_skidmark_right;
/** The skidmarks object for this kart. */
SkidMarks* m_skidmarks;
float m_finish_time;
bool m_finished_race;
@ -140,8 +139,6 @@ public:
float getFinishTime () const { return m_finish_time; }
bool hasFinishedRace () const { return m_finished_race; }
void endRescue ();
//float estimateFinishTime ();
void processSkidMarks ();
void getClosestKart (float *cdist, int *closest);
void updatePhysics (float dt);