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:
15
configure.ac
15
configure.ac
@@ -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 ==============================================
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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 () {};
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
>
|
||||
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user