First version of skid marks (though the skid marks are not yet

transparent, nor do they fade).


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@3616 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2009-06-18 05:36:52 +00:00
parent 8130ab34af
commit 7bb91862ff
2 changed files with 145 additions and 117 deletions

View File

@ -19,27 +19,25 @@
#include "graphics/skid_marks.hpp"
#include "graphics/scene.hpp"
#include "graphics/irr_driver.hpp"
#include "karts/kart.hpp"
#include "physics/btKart.hpp"
#include "utils/coord.hpp"
float SkidMarks::m_avoid_z_fighting = 0.0f;
const float SkidMarks::m_start_alpha = 0.5f;
const int SkidMarks::m_start_alpha = 128;
/** Initialises empty skid marks. */
SkidMarks::SkidMarks(const Kart& kart, float width) : m_kart(kart)
{
#ifndef HAVE_IRRLICHT
m_width = width;
m_skid_state = new ssgSimpleState();
m_skid_state->ref();
m_skid_state->enable(GL_BLEND);
m_skid_state->setMaterial(GL_SPECULAR, 0.0f, 0.0f, 0.0f, 1.0f);
m_skid_state->setShininess(0.0f);
m_skid_marking = false;
m_current = -1;
#endif
m_width = width;
m_material = new video::SMaterial();
m_material->MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
m_material->AmbientColor = video::SColor(255, 0, 0, 0);
m_material->DiffuseColor = video::SColor(255, 0, 0, 0);
m_material->Shininess = 0;
m_skid_marking = false;
m_current = -1;
} // SkidMark
//-----------------------------------------------------------------------------
@ -47,7 +45,7 @@ SkidMarks::SkidMarks(const Kart& kart, float width) : m_kart(kart)
SkidMarks::~SkidMarks()
{
reset(); // remove all skid marks
//ssgDeRefDelete(m_skid_state);
delete m_material;
} // ~SkidMarks
//-----------------------------------------------------------------------------
@ -55,10 +53,12 @@ SkidMarks::~SkidMarks()
*/
void SkidMarks::reset()
{
for(unsigned int i=0; i<m_left.size(); i++)
for(unsigned int i=0; i<m_nodes.size(); i++)
{
//stk_scene->remove(m_left[i]);
//stk_scene->remove(m_right[i]);
irr_driver->removeNode(m_nodes[i]);
irr_driver->removeMesh(m_meshes[i]);
delete m_left[i];
delete m_right[i];
}
m_left.clear();
m_right.clear();
@ -73,9 +73,8 @@ void SkidMarks::reset()
*/
void SkidMarks::update(float dt)
{
#ifndef HAVE_IRRLICHT
float f = dt/stk_config->m_skid_fadeout_time;
for(int i=0; i<m_current; i++)
float f = dt/stk_config->m_skid_fadeout_time*m_start_alpha;
for(unsigned int i=0; i<m_left.size(); i++)
{
m_left[i]->fade(f);
m_right[i]->fade(f);
@ -104,8 +103,10 @@ void SkidMarks::update(float dt)
delta.length2()<0.0001)
{
m_skid_marking = false;
m_left[m_current]->makeDList();
m_right[m_current]->makeDList();
// The vertices and indices will not change anymore (till these
// skid mark quads are deleted)
m_left[m_current]->setHardwareMappingHint(scene::EHM_STATIC);
m_right[m_current]->setHardwareMappingHint(scene::EHM_STATIC);
return;
}
@ -119,12 +120,19 @@ void SkidMarks::update(float dt)
raycast_left.m_contactPointWS + delta);
m_right[m_current]->add(raycast_right.m_contactPointWS-delta,
raycast_right.m_contactPointWS);
// Adjust the boundary box of the mesh to include the
// adjusted aabb of its buffers.
core::aabbox3df aabb=m_meshes[m_current]->getBoundingBox();
aabb.addInternalBox(m_left[m_current]->getAABB());
aabb.addInternalBox(m_right[m_current]->getAABB());
m_meshes[m_current]->setBoundingBox(aabb);
return;
}
// Currently no skid marking
// -------------------------
if((!m_kart.getControls().m_drift) || (fabsf(m_kart.getControls().m_steer) < 0.001f)) return; // no skidmarking
if((!m_kart.getControls().m_drift) ||
(fabsf(m_kart.getControls().m_steer) < 0.001f)) return; // no skidmarking
// not turning enough, don't draw skidmarks if kart is going straight ahead
// this is even stricter for Ai karts, since they tend to use LOTS of skidding
@ -154,116 +162,123 @@ void SkidMarks::update(float dt)
SkidMarkQuads *smq_left = new SkidMarkQuads(raycast_left.m_contactPointWS,
raycast_left.m_contactPointWS + delta,
m_skid_state, m_avoid_z_fighting);
stk_scene->add(smq_left);
m_material, m_avoid_z_fighting);
scene::SMesh *new_mesh = new scene::SMesh();
new_mesh->addMeshBuffer(smq_left);
m_avoid_z_fighting += 0.001f;
if(m_avoid_z_fighting>0.01f) m_avoid_z_fighting = 0.0f;
SkidMarkQuads *smq_right = new SkidMarkQuads(raycast_right.m_contactPointWS
- delta,
raycast_right.m_contactPointWS,
m_skid_state,
m_material,
m_avoid_z_fighting);
stk_scene->add(smq_right);
new_mesh->addMeshBuffer(smq_right);
scene::ISceneNode *new_node = irr_driver->addMesh(new_mesh);
m_current++;
if(m_current>=stk_config->m_max_skidmarks)
m_current = 0;
if(m_current>=(int)m_left.size())
{
m_left. push_back(smq_left );
m_right.push_back(smq_right);
m_left. push_back (smq_left );
m_right.push_back (smq_right);
m_meshes.push_back(new_mesh);
m_nodes.push_back (new_node);
}
else
{
stk_scene->remove(m_left [m_current]);
stk_scene->remove(m_right[m_current]);
m_left [m_current] = smq_left;
m_right[m_current] = smq_right;
irr_driver->removeNode(m_nodes[m_current]);
// Not necessary to delete m_nodes: removeNode
// deletes the node since its refcount reaches zero.
delete m_meshes[m_current];
delete m_left [m_current];
delete m_right [m_current];
m_left [m_current] = smq_left;
m_right [m_current] = smq_right;
m_meshes[m_current] = new_mesh;
m_nodes [m_current] = new_node;
}
m_skid_marking = true;
#endif
// More triangles are added each frame, so for now leave it
// to stream.
m_left[m_current]->setHardwareMappingHint(scene::EHM_STREAM);
m_right[m_current]->setHardwareMappingHint(scene::EHM_STREAM);
} // update
//=============================================================================
#ifndef HAVE_IRRLICHT
SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left, const Vec3 &right,
ssgSimpleState *state, float z_offset)
: ssgVtxTable(GL_QUAD_STRIP,
new ssgVertexArray,
new ssgNormalArray,
new ssgTexCoordArray,
new ssgColourArray )
video::SMaterial *material,
float z_offset)
: scene::SMeshBuffer()
{
m_z_offset = z_offset;
m_fade_out = 0.0f;
// If only one colours and/or normal is specified, it is used for
// all fertices in the table.
sgVec4 colour;
sgSetVec4(colour, 0.00f, 0.00f, 0.00f, SkidMarks::m_start_alpha);
colours->add(colour);
sgVec3 normal;
sgSetVec3(normal, 0, 0, 1);
normals->add(normal);
setState(state);
m_aabb_min = Vec3(10000);
m_aabb_max = Vec3(-10000);
m_material = material;
Material = *material;
m_aabb = core::aabbox3df(left.toIrrVector());
add(left, right);
} // SkidMarkQuads
#endif
//-----------------------------------------------------------------------------
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.
int n = Vertices.size();
video::S3DVertex v;
v.Color = m_material->DiffuseColor;
v.Color.setAlpha(m_start_alpha);
v.Pos = left.toIrrVector();
v.Pos.Y += m_z_offset;
v.Normal = core::vector3df(0, 1, 0);
Vertices.push_back(v);
v.Pos = right.toIrrVector();
v.Pos.Y += m_z_offset;
Vertices.push_back(v);
// Out of the box Irrlicht only supports triangle meshes and not
// triangle strips. Since this is a strip it would be more efficient
// to use a special triangle strip scene node.
if(n>=2)
{
Indices.push_back(n-2);
Indices.push_back(n );
Indices.push_back(n-1);
Indices.push_back(n-1);
Indices.push_back(n );
Indices.push_back(n+1);
}
// Adjust the axis-aligned boundary boxes.
m_aabb.addInternalPoint(left.toIrrVector() );
m_aabb.addInternalPoint(right.toIrrVector());
setBoundingBox(m_aabb);
setDirty();
} // add
// ----------------------------------------------------------------------------
/** Fades the current skid marks.
* \param f fade factor.
*/
void SkidMarks::SkidMarkQuads::fade(float f)
{
#ifndef HAVE_IRRLICHT
m_fade_out += f;
// Only actually change the alpha value every 0.1. Otherwise we can't use
// display lists, which makes skid marks too slow
if(m_fade_out>0.1f)
m_fade_out += f*255;
if(m_fade_out>0.1f*255)
{
//float *c=colours->get(0);
c[3] -= m_fade_out;
if(c[3]<0.0f) c[3]=0.0f;
//makeDList();
video::SColor &c=Material.DiffuseColor;
int a=c.getAlpha();
a -= a<m_fade_out ? a : m_fade_out;
c.setAlpha(a);
for(unsigned int i=0; i<Vertices.size(); i++)
{
Vertices[i].Color.setAlpha(a);
}
m_fade_out = 0.0f;
}
#endif
} // fade
//-----------------------------------------------------------------------------
void SkidMarks::SkidMarkQuads::recalcBSphere()
{
#ifndef HAVE_IRRLICHT
Vec3 diff = m_aabb_max - m_aabb_min;
bsphere.setRadius(diff.length()*0.5f);
Vec3 center = (m_aabb_min + m_aabb_max)*0.5f;
bsphere.setCenter(center.toFloat());
#endif
} // recalcBSphere
//-----------------------------------------------------------------------------
void SkidMarks::SkidMarkQuads::add(const Vec3 &left, const Vec3 &right)
{
#ifndef HAVE_IRRLICHT
// 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+m_z_offset;
sgVec3 r;
sgCopyVec3(r, right.toFloat());
r[2]+=0.01f;
vertices->add(l);
vertices->add(r);
// Adjust the axis-aligned boundary boxes.
m_aabb_min.min(left);m_aabb_min.min(right);
m_aabb_max.max(left);m_aabb_max.max(right);
dirtyBSphere();
#endif
} // add

View File

@ -22,6 +22,9 @@
#include <vector>
#include "irrlicht.h"
using namespace irr;
#include "utils/vec3.hpp"
class Coord;
@ -31,19 +34,21 @@ class 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;
/** Index of current (last added) skid mark quad. */
int m_current;
/** 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;
/** Index of current (last added) skid mark quad. */
int m_current;
/** Initial alpha value. */
static const int m_start_alpha;
/** Initial alpha value. */
static const float m_start_alpha;
/** Material to use for the skid marks. */
video::SMaterial *m_material;
class SkidMarkQuads //: public ssgVtxTable
class SkidMarkQuads : public scene::SMeshBuffer
{
/** Used to move skid marks at the same location slightly on
* top of each other to avoid a 'wobbling' effect when sometines
@ -54,23 +59,31 @@ private:
float m_fade_out;
/** For culling, we need the overall radius of the skid marks. We
* approximate this by maintaining an axis-aligned boundary box. */
Vec3 m_aabb_min, m_aabb_max;
core::aabbox3df m_aabb;
/** Material to use for the skid marks. */
video::SMaterial *m_material;
public:
#ifndef HAVE_IRRLICHT
SkidMarkQuads (const Vec3 &left, const Vec3 &right,
ssgSimpleState *state, float z_offset);
#endif
void recalcBSphere();
video::SMaterial *material, float z_offset);
void add (const Vec3 &left,
const Vec3 &right);
void fade (float f);
/** Returns the aabb of this skid mark quads. */
const core::aabbox3df &getAABB() { return m_aabb; }
}; // SkidMarkQuads
/** Two skidmark objects for the left and right wheel. */
std::vector <SkidMarkQuads *> m_left, m_right;
/** The state for colour etc. */
//ssgSimpleState *m_skid_state;
static float m_avoid_z_fighting;
std::vector<SkidMarkQuads *> m_left, m_right;
/** The meshes - each mesh containing two mesh buffers (left/right). */
std::vector<scene::IMesh *> m_meshes;
/** The nodes where each left/right pair is attached to. */
std::vector<scene::ISceneNode *> m_nodes;
/** Shared static so that consecutive skidmarks are at a slightly
* different height. */
static float m_avoid_z_fighting;
public:
SkidMarks(const Kart& kart, float width=0.2f);
~SkidMarks();