1) Added support for animated textures.

2) Removed static_ssg source files.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@3335 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk
2009-03-31 23:45:20 +00:00
parent 6da2c08e99
commit 4ccd7662ef
12 changed files with 102 additions and 692 deletions

View File

@@ -322,21 +322,6 @@ if test x$have_svnversion != xno; then
AC_DEFINE_UNQUOTED([SVNVERSION],"$SVNVERSION",["SVN revision number"])
fi
AC_MSG_CHECKING([for gcc -fno-regmove option ])
dnl =========================
dnl test regmove compiler bug
dnl =========================
dnl Test if -fno-regmove is supported, since -fregmove (which is part of -O2 on
dnl g++) triggers an optimisation problem with static_ssg:
ORIGCXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS -fno-regmove"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
AC_MSG_RESULT(yes); NOREGMOVE=-fno-regmove,
AC_MSG_RESULT(no); NOREGMOVE="")
CXXFLAGS="$ORIGCXXFLAGS"
AC_SUBST(NOREGMOVE)
dnl ==============================================
dnl Glut (optional), used by bullet debugging only
dnl ==============================================

View File

@@ -245,28 +245,8 @@ supertuxkart_SOURCES = \
replay/replay_recorder.hpp \
replay/replay_recorder.cpp
# This is a VERY ugly work-around for a compiler bug: if static_ssg s compiled with -O2
# (more particularly: with -fregmove, which is part of -O2), it will causes the kart
# to fall through the tracks very easily. Therefore, static_ssg needs special compiler
# flags to work correctly.
# It might (didn't check the details) be that this is the problem reported in
# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28146
# (which states that the problem does not happen with i686 and x86_64, which
# is what I have seen as well, it only happened on i586, not on x86_64).
#
# Since it is not possible to set compiler flags for a single .o file (see
# http://sources.redhat.com/ml/automake/2004-12/msg00063.html), I used the
# workaround provided there.
# Adding -fno-regmove works, even though it is put before the actual compiler flags,
# i.e.: -fno-regmove -g -O2, still works by disabling -fregmove.
# The configure script checks if the compiler accepts this flag, and if so, it
# will be used here.
noinst_LIBRARIES = libstatic_ssg.a
libstatic_ssg_a_SOURCES = static_ssg.cpp static_ssg.hpp
libstatic_ssg_a_CXXFLAGS = $(NOREGMOVE)
# Link in the specific gcc 4.1 bug work around
supertuxkart_LDADD = libstatic_ssg.a \
supertuxkart_LDADD = \
-lplibjs -lplibsl -lplibssg -lplibpu -lplibfnt -lplibsg \
-lplibul -lplibssgaux $(irrlicht_LIBS) $(bullet_LIBS) $(enet_LIBS) $(glut_LIBS) \
$(opengl_LIBS) $(sdl_LIBS) $(openal_LIBS) $(oggvorbis_LIBS) \

View File

@@ -18,122 +18,35 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "graphics/moving_texture.hpp"
#include "io/xml_node.hpp"
#include "modes/world.hpp"
#include "utils/constants.hpp"
#include "utils/string_utils.hpp"
MovingTexture::MovingTexture(char *data, ssgBranch *branch)
MovingTexture::MovingTexture(core::matrix4 *matrix, const XMLNode &node)
: m_matrix(matrix)
{
m_branch = branch;
branch->setUserData(new ssgBase());
branch->setName("MovingTexture");
m_branch->ref();
m_phase = 0.0f;
m_mode = MODE_FORWARD;
m_cycle = 30.0f;
sgSetCoord(&m_now, 0, 0, 0, 0, 0, 0 ) ;
sgSetCoord(&m_delta, 0, 0, 0, 0, 0, 0 ) ;
parseData(data);
m_dx = 0.0f;
m_dy = 0.0f;
core::vector3df v = m_matrix->getTranslation();
m_x = v.X;
m_y = v.Y;
node.get("dx", &m_dx);
node.get("dy", &m_dy);
} // MovingTexture
//-----------------------------------------------------------------------------
MovingTexture::~MovingTexture()
{
ssgDeRefDelete(m_branch);
} // ~MovingTexture
//-----------------------------------------------------------------------------
void MovingTexture::parseData(char *data)
{
char *s = data;
// convert to uppercase
while(*s!='\0')
{
if( *s>='a' && *s<='z' ) *s = *s - 'a' + 'A' ;
s++;
}
s = data;
while ( s != NULL && *s != '\0' )
{
while ( *s > ' ' ) s++ ; /* Skip previous token */
while ( *s <= ' ' && *s != '\0' ) s++ ; /* Skip spaces */
if ( *s == '\0' ) break ;
float f ;
if ( sscanf ( s, "H=%f", & f ) == 1 ) m_delta.hpr[0] = f ; else
if ( sscanf ( s, "P=%f", & f ) == 1 ) m_delta.hpr[1] = f ; else
if ( sscanf ( s, "R=%f", & f ) == 1 ) m_delta.hpr[2] = f ; else
if ( sscanf ( s, "X=%f", & f ) == 1 ) m_delta.xyz[0] = f ; else
if ( sscanf ( s, "Y=%f", & f ) == 1 ) m_delta.xyz[1] = f ; else
if ( sscanf ( s, "Z=%f", & f ) == 1 ) m_delta.xyz[2] = f ; else
if ( sscanf ( s, "C=%f", & f ) == 1 ) m_cycle = f ; else
if ( sscanf ( s, "M=%f", & f ) == 1 ) m_mode = (int) f ; else
if ( sscanf ( s, "O=%f", & f ) == 1 ) m_phase = f ; else
fprintf ( stderr, "Unrecognised @autodcs string: '%s'\n", data );
} // while s!=NULL&&s!='\0'
} // parseData
//-----------------------------------------------------------------------------
void MovingTexture::update(float dt)
{
sgCoord add;
m_x = m_x + dt*m_dx;
m_y = m_y + dt*m_dy;
if(m_x>1.0f) m_x = fmod(m_x, 1.0f);
if(m_y>1.0f) m_y = fmod(m_y, 1.0f);
float timer = RaceManager::getWorld()->getTime() + m_phase ;
if ( m_cycle != 0.0 && m_mode != MODE_FORWARD )
{
if ( m_mode == MODE_SHUTTLE )
{
const float CTIMER = fmod ( timer, m_cycle ) ;
if ( CTIMER > m_cycle / 2.0f )
timer = m_cycle - CTIMER ;
else
timer = CTIMER ;
}
else
{
if ( m_mode == MODE_SINESHUTTLE )
timer = sin ( timer * 2.0f * M_PI / m_cycle ) * m_cycle / 2.0f ;
else
timer = fmod ( timer, m_cycle ) ;
}
} // m_mode!=MODE_FORWARD
sgCopyCoord(&add, &m_delta );
sgScaleVec3(add.xyz, dt);
sgScaleVec3(add.hpr, dt);
sgAddVec3(m_now.xyz, add.xyz);
sgAddVec3(m_now.hpr, add.hpr);
/*
To avoid roundoff problems with very large values
accumulated after long runs all rotations
can be modulo-360 degrees.
*/
m_now.hpr[0] = fmod ( m_now.hpr[0], 360.0f);
m_now.hpr[1] = fmod ( m_now.hpr[1], 360.0f);
m_now.hpr[2] = fmod ( m_now.hpr[2], 360.0f);
if ( m_branch->isAKindOf(ssgTypeTexTrans()) )
{
m_now.xyz[0] = fmod( m_now.xyz[0], 1.0f);
m_now.xyz[1] = fmod( m_now.xyz[1], 1.0f);
m_now.xyz[2] = fmod( m_now.xyz[2], 1.0f);
}
((ssgBaseTransform *) m_branch) -> setTransform(&m_now);
m_matrix->setTextureTranslate(m_x, m_y);
} // update

View File

@@ -21,30 +21,26 @@
#define MOVING_TEXTURE_HPP
#include <string>
#define _WINSOCKAPI_
#include <plib/sg.h>
#include <plib/ssg.h>
#include "irrlicht.h"
using namespace irr;
#include "callback.hpp"
class XMLNode;
class MovingTexture : public Callback
{
private:
// the ac model files assume MODE_FORWARD=1, so a MODE_NONE is added
enum allCallbackModesType { MODE_NONE, MODE_FORWARD, MODE_CYCLE, MODE_SHUTTLE,
MODE_SINESHUTTLE};
sgCoord m_delta;
sgCoord m_now;
float m_phase;
float m_cycle;
int m_mode;
ssgBranch *m_branch;
void parseData(char *data);
/** Translation increment per second. */
float m_dx, m_dy;
/** Current x,y position. */
float m_x, m_y;
/** The texture matrix of this texture. */
core::matrix4 *m_matrix;
public:
MovingTexture(char *data, ssgBranch *branch_);
~MovingTexture();
MovingTexture(core::matrix4 *matrix, const XMLNode &node);
~MovingTexture();
void update (float dt);
void init () {};
}

View File

@@ -253,10 +253,6 @@
RelativePath="..\..\sdl_manager.cpp"
>
</File>
<File
RelativePath="../../../src\static_ssg.cpp"
>
</File>
<File
RelativePath="../../../src\stk_config.cpp"
>
@@ -787,10 +783,6 @@
RelativePath="../../../src\ssg_help.hpp"
>
</File>
<File
RelativePath="../../../src\static_ssg.hpp"
>
</File>
<File
RelativePath="../../../src\stk_config.hpp"
>

View File

@@ -104,7 +104,7 @@ void XMLNode::readXML(io::IXMLReader *xml)
/** Returns the i.th node.
* \param i Number of node to return.
*/
XMLNode *XMLNode::getNode(unsigned int i)
const XMLNode *XMLNode::getNode(unsigned int i) const
{
return m_nodes[i];
} // getNode
@@ -112,7 +112,7 @@ XMLNode *XMLNode::getNode(unsigned int i)
/** Returns the node with the given name.
* \param s Name of the node to return.
*/
XMLNode *XMLNode::getNode(const std::string &s)
const XMLNode *XMLNode::getNode(const std::string &s) const
{
for(unsigned int i=0; i<m_nodes.size(); i++)
{

View File

@@ -42,9 +42,9 @@ public:
XMLNode(io::IXMLReader *xml);
XMLNode(const std::string &filename);
const std::string &getName() const {return m_name; }
XMLNode *getNode(const std::string &name);
XMLNode *getNode(unsigned int i);
unsigned int getNumNodes() {return m_nodes.size(); }
const XMLNode *getNode(const std::string &name) const;
const XMLNode *getNode(unsigned int i) const;
unsigned int getNumNodes() const {return m_nodes.size(); }
int get(const std::string &attribute, std::string *value) const;
int get(const std::string &attribute, int *value) const;
int get(const std::string &attribute, float *value) const;

View File

@@ -276,6 +276,7 @@ void World::update(float dt)
// Clear race state so that new information can be stored
race_state->clear();
m_track->update(dt);
if(network_manager->getMode()!=NetworkManager::NW_CLIENT &&
!history->dontDoPhysics())
{

View File

@@ -1,419 +0,0 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 Joerg Henrichs
// Using the plib functions for InfoTriangle::collision and
// InfoTriangle::hot, (C) Steve Baker
//
// 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 distribhuted 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.
#ifdef XX
#include "static_ssg.hpp"
#include <algorithm>
#include "material_manager.hpp"
#include "material.hpp"
#include "utils/ssg_help.hpp"
#ifndef round
# define round(x) (floor(x+0.5f))
#endif
StaticSSG::StaticSSG(ssgEntity* start_, int nSize)
{
m_start = start_;
m_x_min = m_y_min = 1E10;
m_x_max = m_y_max = -1E10;
m_test_number = 0;
Setup(nSize);
} // StaticSSG
//-----------------------------------------------------------------------------
void StaticSSG::Setup(int nSize)
{
// First compute the minimum and maximum x/y values of all leaves
Vec3 min, max;
SSGHelp::MinMax(m_start, &min, &max);
m_x_min = min.getX();
m_x_max = max.getX();
m_y_min = min.getY();
m_y_max = max.getY();
const float RATIO = (m_x_max-m_x_min)/(m_y_max-m_y_min);
/* The m_n, m_m computed here is the maximum value which can be used,
so the actual range is 0-m_n and 0-m_m, or m_n+1 and m_m+1 'buckets' */
m_n = (int)round(sqrt(nSize/RATIO));
m_m = (int)round(nSize/m_n);
/* Make sure that we don't use more than requested.
This is done by reducing the larger value by 1. */
while(m_n*m_m>nSize)
{
if(m_n>m_m) m_n--; else m_m--;
}
/* If 'm_m' would be used instead of 'm_m-1', the hash value for the column
can be any number between 0 and m_m, i.e. m_m+1 different values! */
m_invdx = (float)(m_m-1)/(m_x_max-m_x_min);
m_invdy = (float)(m_n-1)/(m_y_max-m_y_min);
//JH printf("hash data: m_m=%d, m_n=%d, m_x_max=%f, m_x_min=%f, m_y_max=%f, m_y_min=%f, m_invdx=%f, m_invdy=%f\m_n",
// m_m,m_n,m_x_max,m_x_min,m_y_max,m_y_min,m_invdx,m_invdy);
m_buckets = new allBucketsType(m_n*m_m);
sgMat4 mat;
sgMakeIdentMat4(mat);
Distribute(m_start, mat);
} // Setup
//-----------------------------------------------------------------------------
void StaticSSG::Draw(ssgBranch* b)
{
for(int j=0; j<m_n; j++)
{
for(int i=0; i<m_m; i++)
{
ssgVertexArray* a = new ssgVertexArray();
sgVec3 v;
float h=0.2f;
v[0]=m_x_min+1/m_invdx*i; v[1]= m_y_min+1/m_invdy*j; v[2]=h; a->add(v);
v[0]=m_x_min+1/m_invdx*(i+1);v[1]= m_y_min+1/m_invdy*j; v[2]=h; a->add(v);
v[0]=m_x_min+1/m_invdx*(i+1);v[1]= m_y_min+1/m_invdy*(j+1);v[2]=h; a->add(v);
v[0]=m_x_min+1/m_invdx*i; v[1]= m_y_min+1/m_invdy*(j+1);v[2]=h; a->add(v);
ssgColourArray* c = new ssgColourArray();
v[0]=float(j)/float(m_n);v[1]=float(i)/float(m_m);v[2]=0;
c->add(v);c->add(v);c->add(v);c->add(v);
ssgVtxTable* l = new ssgVtxTable(GL_POLYGON, a,
(ssgNormalArray*)NULL,
(ssgTexCoordArray*)NULL,
c);
// (ssgColourArray*)NULL);
b->addKid(l);
} // for i
} // for j
} // Draw
//-----------------------------------------------------------------------------
void StaticSSG::Distribute(ssgEntity* p, sgMat4 m)
{
if(p->isAKindOf(ssgTypeLeaf()))
{
ssgLeaf* l=(ssgLeaf*)p;
if (material_manager->getMaterial(l)->isIgnore())return;
for(int i=0; i<l->getNumTriangles(); i++)
{
short v1,v2,v3;
sgVec3 vv1, vv2, vv3;
l->getTriangle(i, &v1, &v2, &v3);
sgXformPnt3 ( vv1, l->getVertex(v1), m );
sgXformPnt3 ( vv2, l->getVertex(v2), m );
sgXformPnt3 ( vv3, l->getVertex(v3), m );
StoreTriangle(l, i, vv1, vv2, vv3);
} // for i<p->getNumTriangles
}
else if (p->isAKindOf(ssgTypeTransform()))
{
ssgBaseTransform* t=(ssgBaseTransform*)p;
sgMat4 tmpT, tmpM;
t->getTransform(tmpT);
sgCopyMat4(tmpM, m);
sgPreMultMat4(tmpM,tmpT);
for(ssgEntity* e=t->getKid(0); e!=NULL; e=t->getNextKid())
{
Distribute(e, tmpM);
} // for i<getNumKids
}
else if (p->isAKindOf(ssgTypeBranch()))
{
ssgBranch* b =(ssgBranch*)p;
for(ssgEntity* e=b->getKid(0); e!=NULL; e=b->getNextKid())
{
Distribute(e, m);
} // for i<getNumKids
}
else
{
printf("StaticSSG::Distribute: unkown type\n");
p->print(stdout, 0, 0);
}
} // Distribute
//-----------------------------------------------------------------------------
void StaticSSG::StoreTriangle(ssgLeaf* l, int indx, sgVec3 vv1,
sgVec3 vv2, sgVec3 vv3 )
{
InfoTriangle* t;
t = new InfoTriangle(l, indx, vv1, vv2, vv3);
t->m_x_min = std::min(std::min(vv1[0],vv2[0]), vv3[0]);
t->m_x_max = std::max(std::max(vv1[0],vv2[0]), vv3[0]);
t->m_y_min = std::min(std::min(vv1[1],vv2[1]), vv3[1]);
t->m_y_max = std::max(std::max(vv1[1],vv2[1]), vv3[1]);
sgMakePlane(t->m_plane, vv1,vv2,vv3);
int nMin, mMin, nMax, mMax;
GetRowCol(t->m_x_min, t->m_y_min, &mMin, &nMin);
GetRowCol(t->m_x_max, t->m_y_max, &mMax, &nMax);
for(int j=nMin; j<=nMax; j++)
{
for(int i=mMin; i<=mMax; i++)
{
int nHash = GetHash(i, j);
(*m_buckets)[nHash].push_back(t);
} // for i<=mMax
} // for j<=nMax
} // StoreTriangle
//-----------------------------------------------------------------------------
float StaticSSG::hot(sgVec3 start, sgVec3 end, ssgLeaf** leaf, sgVec4** nrm)
{
float hot = NOINTERSECT;
int N_HASH_START = GetHash(start[0], start[1]);
int nTriangles = (int)(*m_buckets)[N_HASH_START].size();
*leaf = NULL;
for(int i=0; i<nTriangles; i++)
{
InfoTriangle *t = (*m_buckets)[N_HASH_START][i];
const float HOT_NEW = t->hot(start);
if(HOT_NEW>hot)
{
hot = HOT_NEW;
*leaf = t->m_leaf;
*nrm = &t->m_plane;
}
} // for i <nTriangles
if(start[0]==end[0] && start[1]==end[1]) return hot;
const int HASH_END = GetHash(end[0], end[1]);
nTriangles = (int)(*m_buckets)[HASH_END].size();
for(int i=0; i<nTriangles; i++)
{
InfoTriangle *t = (*m_buckets)[HASH_END][i];
const float HOT_NEW = t->hot(end);
if(HOT_NEW>hot)
{
hot=HOT_NEW;
*leaf = t->m_leaf;
}
} // for i <nTriangles
return hot;
} // StaticSSG::hot
//-----------------------------------------------------------------------------
int StaticSSG::collision(sgSphere *s, AllHits *allHits)
{
sgVec3 center; sgCopyVec3(center,s->getCenter());
float RADIUS = s->getRadius();
/* m_test_number is used to tag each triangle tested during this call to
collision. This way we make sure that each triangle is tested at
most once, even if it belongs to different buckets. To remove the
need to reset the m_test_nr value, we increase the testnumber at each test,
and only reset this flag if the m_test_number wraps around again to
zero ... which is unlikely to happen :) */
m_test_number++;
if(m_test_number==0)
{
/* wrap around of the test number, reset all m_test_nr values to zero,
and set m_test_number to 1 to have a clean start */
for(unsigned int i=0; i<m_all_leaves.size(); i++)
{
m_all_leaves[i]->m_test_nr=0;
}
m_test_number=1;
} // if m_test_number==0
int nMin, nMax, mMin, mMax;
GetRowCol(center[0]-RADIUS, center[1]-RADIUS, &mMin, &nMin);
GetRowCol(center[0]+RADIUS, center[1]+RADIUS, &mMax, &nMax);
int count=0;
for(int j=nMin; j<=nMax; j++)
{
for(int i=mMin; i<=mMax; i++)
{
int N_HASH = GetHash(i, j);
if(N_HASH<0 || N_HASH>=m_n*m_m)
{ // that should be a car off track
continue; // rescue should take care of this
}
int nCount = (int)(*m_buckets)[N_HASH].size();
for(int k=0; k<nCount; k++)
{
InfoTriangle *t = (*m_buckets)[N_HASH][k];
// Make sure that each triangle is tested only once
if(t->m_test_nr!=m_test_number)
{
t->m_test_nr=m_test_number;
if(t->collision(s))
{
allHits->push_back(t);
count++;
} // if hit
} // if t->m_test_nr!=m_test_number
} // for k
} // for i<=mMax
} // for j<=nMax
return count;
} // StaticSSG::collision
//=============================================================================
float InfoTriangle::hot(sgVec3 s)
{
/*
Does the X/Y coordinate lie outside the triangle's bbox, or
does the Z coordinate lie beneath the bbox ?
*/
if ( ( s[0] < m_vv1[0] && s[0] < m_vv2[0] && s[0] < m_vv3[0] ) ||
( s[1] < m_vv1[1] && s[1] < m_vv2[1] && s[1] < m_vv3[1] ) ||
( s[0] > m_vv1[0] && s[0] > m_vv2[0] && s[0] > m_vv3[0] ) ||
( s[1] > m_vv1[1] && s[1] > m_vv2[1] && s[1] > m_vv3[1] ) ||
( s[2] < m_vv1[2] && s[2] < m_vv2[2] && s[2] < m_vv3[2] ) ) return NOINTERSECT;
/* No HOT from upside-down or vertical triangles */
if ( m_leaf->getCullFace() && m_plane [ 2 ] <= 0 ) return NOINTERSECT;
/* Find the point vertically below the text point
as it crosses the plane of the polygon */
const float Z = sgHeightOfPlaneVec2 ( m_plane, s );
/* No HOT from below the triangle */
if ( Z > s[2] ) return NOINTERSECT;
/* Outside the vertical extent of the triangle? */
if ( ( Z < m_vv1[2] && Z < m_vv2[2] && Z < m_vv3[2] ) ||
( Z > m_vv1[2] && Z > m_vv2[2] && Z > m_vv3[2] ) ) return NOINTERSECT;
/*
Now it gets messy - the isect point is inside
the bbox of the triangle - but that's not enough.
Is it inside the triangle itself?
*/
const float E1 = s [0] * m_vv1[1] - s [1] * m_vv1[0] ;
const float E2 = s [0] * m_vv2[1] - s [1] * m_vv2[0] ;
const float E3 = s [0] * m_vv3[1] - s [1] * m_vv3[0] ;
const float EP1 = m_vv1[0] * m_vv2[1] - m_vv1[1] * m_vv2[0] ;
const float EP2 = m_vv2[0] * m_vv3[1] - m_vv2[1] * m_vv3[0] ;
const float EP3 = m_vv3[0] * m_vv1[1] - m_vv3[1] * m_vv1[0] ;
const float AP = (float) fabs ( EP1 + EP2 + EP3 ) ;
const float AI = (float) ( fabs ( E1 + EP1 - E2 ) +
fabs ( E2 + EP2 - E3 ) +
fabs ( E3 + EP3 - E1 ) ) ;
if ( AI > AP * 1.01 ) return NOINTERSECT;
return Z;
} // InfoTriangle::hot
//-----------------------------------------------------------------------------
int InfoTriangle::collision(sgSphere *s)
{
const sgVec3 * const CENTER = (sgVec3*)s->getCenter();
const float R = s->getRadius();
/* First test: see if the sphere is outside the 2d bounding box
of the triangle - a quite fast and easy test */
if((*CENTER)[0]+R<m_x_min || (*CENTER)[0]-R>m_x_max ||
(*CENTER)[1]+R<m_y_min || (*CENTER)[1]-R>m_y_max)
{
return 0;
}
m_dist = (float)fabs( sgDistToPlaneVec3(m_plane, s->getCenter()) );
if ( m_dist > R ) return 0;
/*
The BSphere touches the plane containing
the triangle - but does it actually touch
the triangle itself? Let's erect some
vertical walls around the triangle.
*/
/*
Construct a 'wall' as a plane through
two vertices and a third vertex made
by adding the surface normal to the
first of those two vertices.
*/
sgVec3 vvX;
sgVec4 planeX;
sgAddVec3 ( vvX, m_plane, m_vv1 );
sgMakePlane ( planeX, m_vv1, m_vv2, vvX );
const float DP1 = sgDistToPlaneVec3 ( planeX, s->getCenter() );
if ( DP1 > s->getRadius() ) return 0;
sgAddVec3 ( vvX, m_plane, m_vv2 );
sgMakePlane ( planeX, m_vv2, m_vv3, vvX );
const float DP2 = sgDistToPlaneVec3 ( planeX, s->getCenter() );
if ( DP2 > s->getRadius() ) return 0;
sgAddVec3 ( vvX, m_plane, m_vv3 );
sgMakePlane ( planeX, m_vv3, m_vv1, vvX );
const float DP3 = sgDistToPlaneVec3 ( planeX, s->getCenter() );
if ( DP3 > s->getRadius() ) return 0;
/*
OK, so we now know that the sphere
intersects the plane of the triangle
and is not more than one radius outside
the walls. However, you can still get
close enough to the wall and to the
triangle itself and *still* not
intersect the triangle itself.
However, if the center is inside the
triangle then we don't need that
costly test.
*/
if ( DP1 <= 0 && DP2 <= 0 && DP3 <= 0 ) return 1;
/*
<sigh> ...now we really need that costly set of tests...
If the sphere penetrates the plane of the triangle
and the plane of the wall, then we can use pythagoras
to determine if the sphere actually intersects that
edge between the wall and the triangle.
if ( dp_sqd + dp1_sqd > radius_sqd ) ...in! else ...out!
*/
const float R2 = s->getRadius() * s->getRadius() - m_dist * m_dist ;
if ( DP1 * DP1 <= R2 || DP2 * DP2 <= R2 || DP3 * DP3 <= R2 )
{
return 1;
}
return 0;
} // InfoTriangle::collision
#endif

View File

@@ -1,102 +0,0 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 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 distribhuted 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.
#ifdef XX
#ifndef _HEADER_STATICSSG_
#define _HEADER_STATICSSG_
#include <vector>
#include <plib/ssg.h>
#define NOINTERSECT -999999.9f
class InfoTriangle
{
public:
ssgLeaf* m_leaf;
int m_indx;
sgVec3 m_vv1,m_vv2,m_vv3;
unsigned int m_test_nr;
sgVec4 m_plane;
float m_x_min, m_x_max, m_y_min, m_y_max;
// distance to plane in case of a hit, undefined otherwise
float m_dist;
public:
InfoTriangle() {};
InfoTriangle(ssgLeaf* l,int i,sgVec3 v1,sgVec3 v2,sgVec3 v3)
{
m_leaf = l; m_indx=i;
sgCopyVec3(m_vv1,v1);
sgCopyVec3(m_vv2,v2);
sgCopyVec3(m_vv3,v3);
m_test_nr=0;
l->ref();
}
~InfoTriangle() { ssgDeRefDelete(m_leaf); }
float hot(sgVec3 p);
int collision(sgSphere *s);
}
; // InfoTriangle
// =============================================================================
typedef std::vector<InfoTriangle*> AllHits;
// =============================================================================
class StaticSSG
{
private:
/* allLeavesType is a list storing all triangles which
touch a certain hash bucket. */
typedef std::vector<InfoTriangle*> allLeavesType;
/* This is the list of buckets, each of which stores
a list of leaves at that hash value/bucket */
typedef std::vector<allLeavesType> allBucketsType;
allLeavesType m_all_leaves;
allBucketsType* m_buckets;
float m_x_min, m_x_max, m_y_min, m_y_max;
int m_n, m_m;
unsigned int m_test_number;
float m_invdx, m_invdy;
ssgEntity* m_start;
void Setup (int n);
void Distribute (ssgEntity* start, sgMat4 m);
void StoreTriangle(ssgLeaf* l, int indx, sgVec3 vv1, sgVec3 vv2, sgVec3 vv3);
int GetHash (float x, float y)
{
int m1; int n1;
GetRowCol(x,y,&m1,&n1);
return GetHash(m1, n1);
}
int GetHash (int m1, int n1 ) { return m1+n1*m_m; }
void GetRowCol(float x, float y, int *m1, int *n1)
{
*m1=(int)((x-m_x_min)*m_invdx);
*n1=(int)((y-m_y_min)*m_invdy);
}
public:
StaticSSG(ssgEntity* start, int n);
void Draw(ssgBranch* b);
float hot(sgVec3 start, sgVec3 end, ssgLeaf** l, sgVec4** nrm);
int collision(sgSphere *s, AllHits *allHits);
};
#endif
#endif

View File

@@ -34,6 +34,7 @@
#include "audio/sound_manager.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/mesh_tools.hpp"
#include "graphics/moving_texture.hpp"
#include "graphics/scene.hpp"
#include "io/file_manager.hpp"
#include "io/xml_node.hpp"
@@ -88,6 +89,10 @@ Track::~Track()
*/
void Track::cleanup()
{
for(unsigned int i=0; i<m_animated_textures.size(); i++)
{
delete m_animated_textures[i];
}
for(unsigned int i=0; i<m_all_nodes.size(); i++)
{
irr_driver->removeNode(m_all_nodes[i]);
@@ -910,7 +915,7 @@ void Track::loadTrack(const std::string &filename)
m_camera_final_hpr.degreeToRad();
m_sky_type = SKY_NONE;
XMLNode *node = root->getNode("sky-dome");
const XMLNode *node = root->getNode("sky-dome");
if(node)
{
m_sky_type = SKY_DOME;
@@ -1205,6 +1210,7 @@ bool Track::loadMainTrack(const XMLNode &node)
node.getName().c_str(), model_name.c_str());
exit(-1);
}
m_all_meshes.push_back(mesh);
Vec3 min, max;
@@ -1222,13 +1228,62 @@ bool Track::loadMainTrack(const XMLNode &node)
node.getHPR(&hpr);
scene_node->setPosition(xyz);
scene_node->setRotation(hpr);
handleAnimatedTextures(scene_node, node);
m_all_nodes.push_back(scene_node);
scene_node->setMaterialFlag(video::EMF_LIGHTING, false);
return true;
} // loadMainTrack
// ----------------------------------------------------------------------------
/** Handles animated textures.
* \param node The node containing the data for the animated notion.
*/
void Track::handleAnimatedTextures(scene::ISceneNode *node, const XMLNode &xml)
{
for(unsigned int node_number = 0; node_number<xml.getNumNodes();
node_number++)
{
const XMLNode *texture_node = xml.getNode(node_number);
if(texture_node->getName()!="animated-texture") continue;
std::string name;
texture_node->get("name", &name);
if(name=="")
{
fprintf(stderr,
"Animated texture: no texture name specified for track '%s'\n",
getIdent());
continue;
}
for(unsigned int i=0; i<node->getMaterialCount(); i++)
{
video::SMaterial &irrMaterial=node->getMaterial(i);
for(unsigned int j=0; j<video::MATERIAL_MAX_TEXTURES; j++)
{
video::ITexture* t=irrMaterial.getTexture(j);
if(!t) continue;
const std::string texture_name =
StringUtils::basename(t->getName().c_str());
if(texture_name!=name) continue;
core::matrix4 *m = &irrMaterial.getTextureMatrix(j);
m_animated_textures.push_back(new MovingTexture(m, *texture_node));
} // for j<MATERIAL_MAX_TEXTURES
} // for i<getMaterialCount
} // for node_number < xml->getNumNodes
} // handleAnimatedTextures
// ----------------------------------------------------------------------------
/** Update, called once per frame.
* \param dt Timestep.
*/
void Track::update(float dt)
{
for(unsigned int i=0; i<m_animated_textures.size(); i++)
{
m_animated_textures[i]->update(dt);
}
} // update
// ----------------------------------------------------------------------------
/** Creates a water node.
* \param node The XML node containing the specifications for the water node.
@@ -1311,7 +1366,7 @@ void Track::loadTrackModel()
<<"', aborting.";
throw std::runtime_error(msg.str());
}
XMLNode *node = root->getNode("track");
const XMLNode *node = root->getNode("track");
loadMainTrack(*node);
for(unsigned int i=0; i<root->getNumNodes(); i++)
{
@@ -1349,6 +1404,7 @@ void Track::loadTrackModel()
node->getHPR(&hpr);
scene_node->setPosition(xyz);
scene_node->setRotation(hpr);
handleAnimatedTextures(scene_node, *node);
m_all_nodes.push_back(scene_node);
scene_node->setMaterialFlag(video::EMF_LIGHTING, false);
}

View File

@@ -40,6 +40,7 @@ using namespace irr;
#include "utils/vec3.hpp"
class TriangleMesh;
class MovingTexture;
class XMLNode;
class Track
@@ -73,6 +74,9 @@ private:
/** A list of the textures for the sky to use. It contains one texture
* in case of a dome, and 6 textures for a box. */
std::vector<std::string> m_sky_textures;
/** The list of all animated textures. */
std::vector<MovingTexture*> m_animated_textures;
/** If a sky dome is used, the number of horizontal segments
* the sphere should be divided in. */
int m_sky_hori_segments;
@@ -83,6 +87,9 @@ private:
float m_sky_sphere_percent;
/** If a sky dome is used, percentage of the texture to be used. */
float m_sky_texture_percent;
void handleAnimatedTextures(scene::ISceneNode *node, const XMLNode &xml);
public:
enum RoadSide{ RS_DONT_KNOW = -1, RS_LEFT = 0, RS_RIGHT = 1 };
@@ -209,6 +216,7 @@ public:
const Material **material) const;
float getTerrainHeight(const Vec3 &pos) const;
void createPhysicsModel();
void update(float dt);
void glVtx (sgVec2 v, float x_offset, float y_offset) const
{
glVertex2f(