1) Improved rockets and sparks for bullet physics

Parameters for rockets etc. can for now be
   set in data/*.projectile
2) Fixed bugs causing rockets not to explode (and
   potentialy start rotating)
3) Added (somewhat temporarily) some cheats to get
   rockets, homing missiles and sparks as F1/2/3
4) Fixed several memory leaks.
5) Fixed (very rare) occurring crash when deleting
   phsyics.
6) Started to remove non-bullet physics code
7) Bullet physics is now the default, and it
   can not be disabled anymore!!
Important note: 
From this revision on, non-bullet physics is NOT
supported anymore, and will (most likely) not
compile. For now a -DBULLET is still necessary (it
is added as default), but the code will be cleaned
up in the near future.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1325 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2007-12-08 13:04:56 +00:00
parent 12cee75a0f
commit 7ed846ca3e
44 changed files with 504 additions and 670 deletions

View File

@ -1,16 +1,17 @@
Preliminary support for the bullet physics engine has been Beginning with revision r1325 bullet physics is being used
added, and bullet itself is part of the STK sources by noq. in SuperTuxKart. A copy of bullet is included in
To enable it, use the '--enable-bullet' option in configure, the sources and the STK build environment, so it's
that should be all (though up to now only linux and cygwin not necessary to install your own version.
have been tested with the new, integrated bullet version).
Even though we officiall switched to bullet physics,
not all 'old' features of STK are fully supported yet.
For now mainly the race track works as expected, all tracks For now mainly the race track works as expected, all tracks
can be played (though the performance in some tracks is somewhat can be played. Most important bugs:
bad at the moment). Most important bugs:
- not all collectable work - not all collectable work
(zippers don't work, homing missiles don't go to the target, (zippers don't do much at the moment, rockets and sparks mostly
sparks won't fly as expected either), but collision with work, but are sometimes too high)
karts work. - karts are not automatically rescued when touching
water or lava
- no proper friction handling, so no skidding - no proper friction handling, so no skidding
(though skidding potentially works - if the friction is (though skidding potentially works - if the friction is
set correctly). set correctly).
@ -19,8 +20,6 @@ bad at the moment). Most important bugs:
- rescuing an upside-down kart will return the kart to the middle - rescuing an upside-down kart will return the kart to the middle
of the track (waypoints) - the kart should be returned to where of the track (waypoints) - the kart should be returned to where
it ended, just with a proper orientation. it ended, just with a proper orientation.
- if a kart is upside down, it will actually hang under the
track.
- tuxtrack is using real rigid bodies for the roadcone and roadblock, - tuxtrack is using real rigid bodies for the roadcone and roadblock,
so they are pushed around when hit by a kart. Currently, the so they are pushed around when hit by a kart. Currently, the
start orientation is not used, so the heading of the objects start orientation is not used, so the heading of the objects

View File

@ -32,11 +32,12 @@ Comments:
Visual C++ Express Visual C++ Express
================== ==================
There are now project files included for building SuperTuxKart with
Visual C++ - have a look at the src/ide/vc8 folder.
Since version r793 SuperTuxKart compiles with Visual C++ Express, Since version r793 SuperTuxKart compiles with Visual C++ Express,
version 8.0, since rev 1267 Visual C++ project files are included. version 8.0, since rev 1267 Visual C++ project files are included.
The main project file is .../src/ide/vc8/supertuxkart.vcproj, The main project file is .../src/ide/vc8/supertuxkart.vcproj,
and it include a sub project for the bullet library. More details and it includes a sub project for the bullet library. More details
can be found in .../src/ide/vc8/README. can be found in .../src/ide/vc8/README.
You still have to install all dependencies, and: You still have to install all dependencies, and:

View File

@ -347,34 +347,20 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
CXXFLAGS="$ORIGCXXFLAGS" CXXFLAGS="$ORIGCXXFLAGS"
AC_SUBST(NOREGMOVE) AC_SUBST(NOREGMOVE)
dnl ======================================= dnl ==============
dnl Bullet physics - currently experimental dnl Bullet physics
dnl ======================================= dnl ==============
dnl Check for bullet physics. Currently, this is optional and needs AC_DEFINE([BULLET], [], [Use the bullet physics engine])
dnl a '--enable-bullet' during configure to be used. CXXFLAGS="$CXXFLAGS -Ibullet/src"
AC_MSG_CHECKING(for bullet physics) AC_CONFIG_FILES([ \
AC_ARG_ENABLE(bullet,
AC_HELP_STRING([--enable-bullet], [enable bullet physics]),
[enable_bullet="$enableval"],
[enable_bullet="no"])
if test "x${enable_bullet}" != "xno"; then
AC_DEFINE([BULLET], [], [Use the bullet physics engine])
AC_MSG_RESULT([enabled])
CXXFLAGS="$CXXFLAGS -Ibullet/src"
AC_CONFIG_FILES([ \
src/bullet/Makefile \ src/bullet/Makefile \
src/bullet/src/Makefile \ src/bullet/src/Makefile \
src/bullet/Demos/OpenGL/Makefile src/bullet/Demos/OpenGL/Makefile
]) ])
SUMMARY="$SUMMARY\nUsing bullet physics." SUMMARY="$SUMMARY\nUsing bullet physics."
BULLETTREE="src/bullet" BULLETTREE="src/bullet"
bullet_LIBS="-L bullet/Demos/OpenGL -lbulletopenglsupport -L bullet/src -lbulletdynamics -lbulletcollision -lbulletmath -lglut" bullet_LIBS="-L bullet/Demos/OpenGL -lbulletopenglsupport -L bullet/src -lbulletdynamics -lbulletcollision -lbulletmath -lglut"
else
AC_MSG_RESULT([disabled])
BULLETTREE=""
bullet_LIBS=""
fi
AC_SUBST(BULLETTREE) AC_SUBST(BULLETTREE)
dnl ================ dnl ================

View File

@ -4,7 +4,12 @@
(name "homing") (name "homing")
(model "homingmissile.ac") (model "homingmissile.ac")
(icon "homingmissile.rgb") (icon "homingmissile.rgb")
(speed 25.0) (speed 35.0)
(min-height 0.2)
(max-height 1.0)
(max-distance 20.0) ;; maximum distance at which a kart is still followed
(max-turn-angle 5.0) ;; maximum turn angle when following a kart
(force-updown 25.0) ;; force raising/lowering the homing missile if it's too low/high
) )
;; EOF ;; ;; EOF ;;

View File

@ -5,6 +5,9 @@
(model "missile.ac") (model "missile.ac")
(icon "missile.rgb") (icon "missile.rgb")
(speed 50.0) (speed 50.0)
(min-height 0.2)
(max-height 1.0)
(force-updown 15.0)
) )
;; EOF ;; ;; EOF ;;

View File

@ -5,6 +5,16 @@
(model "spark.ac") (model "spark.ac")
(icon "spark.rgb") (icon "spark.rgb")
(speed 5.0) (speed 5.0)
(min-height 0.2) ; height above terrain below which a spark is
; started to be pulled up
(max-height 3.0) ; height above terrain at which a spark is
; started to be pulled back to ground
(force-updown 20.0) ; force pushing the spark down
; when it's too high above ground
(force-to-target 20) ; force with which a spark flies towards
; the nearest kart
(max-distance 10) ; maximum distance the spark can be away
; from a kart when accelerating towards it
) )
;; EOF ;; ;; EOF ;;

View File

@ -26,7 +26,7 @@ libstatic_ssg_a_CXXFLAGS = @NOREGMOVE@
AM_CPPFLAGS=-DSUPERTUXKART_DATADIR="\"$(datadir)/games/@PACKAGE@/\"" AM_CPPFLAGS=-DSUPERTUXKART_DATADIR="\"$(datadir)/games/@PACKAGE@/\""
supertuxkart_SOURCES = main.cpp \ supertuxkart_SOURCES = main.cpp \
actionmap.cpp actionmap.hpp \ actionmap.cpp actionmap.hpp \
material.cpp material.hpp \ material.cpp material.hpp \
material_manager.cpp material_manager.hpp \ material_manager.cpp material_manager.hpp \
attachment.cpp attachment.hpp \ attachment.cpp attachment.hpp \
@ -38,8 +38,7 @@ supertuxkart_SOURCES = main.cpp \
music_mikmod.cpp music_mikmod.hpp \ music_mikmod.cpp music_mikmod.hpp \
music_ogg.cpp music_ogg.hpp \ music_ogg.cpp music_ogg.hpp \
sfx_openal.cpp sfx_openal.hpp \ sfx_openal.cpp sfx_openal.hpp \
utils.cpp utils.hpp \ input.hpp \
input.hpp \
isect.cpp isect.hpp \ isect.cpp isect.hpp \
track.cpp track.hpp \ track.cpp track.hpp \
herring.cpp herring.hpp \ herring.cpp herring.hpp \
@ -68,8 +67,8 @@ supertuxkart_SOURCES = main.cpp \
shadow.cpp shadow.hpp \ shadow.cpp shadow.hpp \
particle_system.cpp particle_system.hpp \ particle_system.cpp particle_system.hpp \
game_manager.cpp game_manager.hpp \ game_manager.cpp game_manager.hpp \
widget_manager.cpp widget_manager.hpp \ widget_manager.cpp widget_manager.hpp \
widget.cpp widget.hpp \ widget.cpp widget.hpp \
camera.cpp camera.hpp \ camera.cpp camera.hpp \
sdldrv.cpp sdldrv.hpp \ sdldrv.cpp sdldrv.hpp \
moveable.cpp moveable.hpp \ moveable.cpp moveable.hpp \
@ -77,14 +76,17 @@ supertuxkart_SOURCES = main.cpp \
kart.cpp kart.hpp \ kart.cpp kart.hpp \
auto_kart.hpp \ auto_kart.hpp \
player_kart.cpp player_kart.hpp \ player_kart.cpp player_kart.hpp \
projectile.cpp projectile.hpp \ flyable.cpp flyable.hpp \
missile.cpp missile.hpp \
homing.cpp homing.hpp \
spark.cpp spark.hpp \
history.cpp history.hpp \ history.cpp history.hpp \
scene.hpp scene.cpp \ scene.hpp scene.cpp \
race_setup.hpp no_copy.hpp \ race_setup.hpp no_copy.hpp \
constants.hpp \ constants.hpp \
translation.hpp \ translation.hpp \
traffic.cpp \ traffic.cpp \
player.hpp \ player.hpp \
lisp/lisp.cpp lisp/lisp.hpp \ lisp/lisp.cpp lisp/lisp.hpp \
lisp/lexer.cpp lisp/lexer.hpp \ lisp/lexer.cpp lisp/lexer.hpp \
lisp/parser.cpp lisp/parser.hpp \ lisp/parser.cpp lisp/parser.hpp \
@ -111,12 +113,12 @@ supertuxkart_SOURCES = main.cpp \
gui/credits_menu.cpp gui/credits_menu.hpp \ gui/credits_menu.cpp gui/credits_menu.hpp \
gui/grand_prix_select.cpp gui/grand_prix_select.hpp \ gui/grand_prix_select.cpp gui/grand_prix_select.hpp \
gui/font.hpp gui/font.cpp \ gui/font.hpp gui/font.cpp \
robots/default_robot.cpp robots/default_robot.hpp \ robots/default_robot.cpp robots/default_robot.hpp \
replay_buffer_tpl.hpp \ replay_buffer_tpl.hpp \
replay_buffers.hpp replay_buffers.cpp \ replay_buffers.hpp replay_buffers.cpp \
replay_base.hpp replay_base.cpp \ replay_base.hpp replay_base.cpp \
replay_player.hpp replay_player.cpp \ replay_player.hpp replay_player.cpp \
replay_recorder.hpp replay_recorder.cpp replay_recorder.hpp replay_recorder.cpp
# Link in the specific gcc 4.1 bug work around # Link in the specific gcc 4.1 bug work around

View File

@ -36,7 +36,7 @@ Attachment::Attachment(Kart* _kart)
m_kart = _kart; m_kart = _kart;
m_holder = new ssgSelector(); m_holder = new ssgSelector();
m_previous_owner = NULL; m_previous_owner = NULL;
m_kart->getModel()->addKid(m_holder); m_kart->getModelTransform()->addKid(m_holder);
for(int i=ATTACH_PARACHUTE; i<=ATTACH_TINYTUX; i++) for(int i=ATTACH_PARACHUTE; i<=ATTACH_TINYTUX; i++)
{ {

View File

@ -58,6 +58,7 @@ public:
} }
attachmentType getType () const { return m_type; } attachmentType getType () const { return m_type; }
float getTimeLeft () const { return m_time_left; } float getTimeLeft () const { return m_time_left; }
void setTimeLeft (float t){ m_time_left = t; }
Kart* getPreviousOwner () const { return m_previous_owner; } Kart* getPreviousOwner () const { return m_previous_owner; }
float WeightAdjust () const { float WeightAdjust () const {
return m_type==ATTACH_ANVIL return m_type==ATTACH_ANVIL

View File

@ -18,6 +18,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "callback_manager.hpp" #include "callback_manager.hpp"
#include "moving_physics.hpp"
CallbackManager *callback_manager=NULL; CallbackManager *callback_manager=NULL;

View File

@ -28,21 +28,21 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
Collectable::Collectable(Kart* kart_) Collectable::Collectable(Kart* kart_)
{ {
owner = kart_; m_owner = kart_;
type = COLLECT_NOTHING; m_type = COLLECT_NOTHING;
number = 0; m_number = 0;
} // Collectable } // Collectable
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Collectable::set(collectableType _type, int n) void Collectable::set(CollectableType type, int n)
{ {
if (type==_type) if (m_type==type)
{ {
number+=n; m_number+=n;
return; return;
} }
type=_type; m_type=type;
number=n; m_number=n;
} // set } // set
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -50,7 +50,7 @@ Material *Collectable::getIcon()
{ {
// Check if it's one of the types which have a separate // Check if it's one of the types which have a separate
// data file which includes the icon: // data file which includes the icon:
return collectable_manager->getIcon(type); return collectable_manager->getIcon(m_type);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -70,22 +70,22 @@ void Collectable::use()
} // if MAGNET_BZZT } // if MAGNET_BZZT
} // user_config->disableMagnet } // user_config->disableMagnet
#endif #endif
number--; m_number--;
switch (type) switch (m_type)
{ {
#ifdef USE_MAGNET #ifdef USE_MAGNET
case COLLECT_MAGNET: owner->attach(ATTACH_MAGNET_BZZT, stk_config->m_magnet_time); case COLLECT_MAGNET: m_owner->attach(ATTACH_MAGNET_BZZT, stk_config->m_magnet_time);
break ; break ;
#endif #endif
case COLLECT_ZIPPER: owner->handleZipper(); case COLLECT_ZIPPER: m_owner->handleZipper();
break ; break ;
case COLLECT_HOMING_MISSILE: case COLLECT_HOMING:
case COLLECT_SPARK: case COLLECT_SPARK:
case COLLECT_MISSILE: case COLLECT_MISSILE:
if(owner->isPlayerKart()) if(m_owner->isPlayerKart())
sound_manager->playSfx(SOUND_SHOT); sound_manager->playSfx(SOUND_SHOT);
projectile_manager->newProjectile(owner, type); projectile_manager->newProjectile(m_owner, m_type);
break ; break ;
case COLLECT_ANVIL: case COLLECT_ANVIL:
@ -93,7 +93,7 @@ void Collectable::use()
//by the bananas) to the kart in the 1st position. //by the bananas) to the kart in the 1st position.
for(unsigned int i = 0 ; i < world->getNumKarts(); ++i) for(unsigned int i = 0 ; i < world->getNumKarts(); ++i)
{ {
if(world->getKart(i) == owner) continue; if(world->getKart(i) == m_owner) continue;
if(world->getKart(i)->getPosition() == 1) if(world->getKart(i)->getPosition() == 1)
{ {
world->getKart(i)-> world->getKart(i)->
@ -117,8 +117,8 @@ void Collectable::use()
//are in front of this one. //are in front of this one.
for(unsigned int i = 0 ; i < world->getNumKarts(); ++i) for(unsigned int i = 0 ; i < world->getNumKarts(); ++i)
{ {
if(world->getKart(i) == owner) continue; if(world->getKart(i) == m_owner) continue;
if(owner->getPosition() > world-> if(m_owner->getPosition() > world->
getKart(i)->getPosition()) getKart(i)->getPosition())
{ {
world->getKart(i)->attach( world->getKart(i)->attach(
@ -139,7 +139,7 @@ void Collectable::use()
default : break ; default : break ;
} }
if ( number <= 0 ) if ( m_number <= 0 )
{ {
clear(); clear();
} }
@ -152,10 +152,10 @@ void Collectable::hitRedHerring(int n)
//depending on how bad the owner's position is. For the first //depending on how bad the owner's position is. For the first
//driver the posibility is none, for the last player is 15 %. //driver the posibility is none, for the last player is 15 %.
if(owner->getPosition() != 1 && type == COLLECT_NOTHING) if(m_owner->getPosition() != 1 && m_type == COLLECT_NOTHING)
{ {
const int SPECIAL_PROB = (int)(15.0 / ((float)world->getNumKarts() / const int SPECIAL_PROB = (int)(15.0 / ((float)world->getNumKarts() /
(float)owner->getPosition())); (float)m_owner->getPosition()));
const int RAND_NUM = rand()%100; const int RAND_NUM = rand()%100;
if(RAND_NUM <= SPECIAL_PROB) if(RAND_NUM <= SPECIAL_PROB)
{ {
@ -163,18 +163,18 @@ void Collectable::hitRedHerring(int n)
//the parachute. //the parachute.
for(unsigned int i=0; i < world->getNumKarts(); ++i) for(unsigned int i=0; i < world->getNumKarts(); ++i)
{ {
if(world->getKart(i) == owner) continue; if(world->getKart(i) == m_owner) continue;
if(world->getKart(i)->getPosition() == 1 && world->getKart(i)-> if(world->getKart(i)->getPosition() == 1 && world->getKart(i)->
raceIsFinished()) raceIsFinished())
{ {
type = COLLECT_PARACHUTE; m_type = COLLECT_PARACHUTE;
number = 1; m_number = 1;
return; return;
} }
} }
type = rand()%(2) == 0 ? COLLECT_ANVIL : COLLECT_PARACHUTE; m_type = rand()%(2) == 0 ? COLLECT_ANVIL : COLLECT_PARACHUTE;
number = 1; m_number = 1;
return; return;
} }
} }
@ -182,7 +182,7 @@ void Collectable::hitRedHerring(int n)
//rand() is moduled by COLLECT_MAX - 1 - 2 because because we have to //rand() is moduled by COLLECT_MAX - 1 - 2 because because we have to
//exclude the anvil and the parachute, but later we have to add 1 to prevent //exclude the anvil and the parachute, but later we have to add 1 to prevent
//having a value of 0 since that isn't a valid collectable. //having a value of 0 since that isn't a valid collectable.
collectableType newC; CollectableType newC;
if(!user_config->m_profile) if(!user_config->m_profile)
{ {
// A zipper should not be used during time trial, since it // A zipper should not be used during time trial, since it
@ -190,24 +190,24 @@ void Collectable::hitRedHerring(int n)
// in time trail, but only the top 2 in any other mode // in time trail, but only the top 2 in any other mode
int nIgnore = (world->m_race_setup.m_mode == RaceSetup::RM_TIME_TRIAL) int nIgnore = (world->m_race_setup.m_mode == RaceSetup::RM_TIME_TRIAL)
? 3 : 2; ? 3 : 2;
newC = (collectableType)(rand()%(COLLECT_MAX - 1 - nIgnore) + 1); newC = (CollectableType)(rand()%(COLLECT_MAX - 1 - nIgnore) + 1);
} }
else else
{ {
// No random effects when profiling! // No random effects when profiling!
static int simpleCounter=-1; static int simpleCounter=-1;
simpleCounter++; simpleCounter++;
newC = (collectableType)(simpleCounter%(COLLECT_MAX - 1 - 2) + 1); newC = (CollectableType)(simpleCounter%(COLLECT_MAX - 1 - 2) + 1);
} }
if(type==COLLECT_NOTHING) if(m_type==COLLECT_NOTHING)
{ {
type=newC; m_type=newC;
number = n; m_number = n;
} }
else if(newC==type) else if(newC==m_type)
{ {
number+=n; m_number+=n;
if(number > MAX_COLLECTABLES) number = MAX_COLLECTABLES; if(m_number > MAX_COLLECTABLES) m_number = MAX_COLLECTABLES;
} }
// Ignore new collectable if it is different from the current one // Ignore new collectable if it is different from the current one
} // hitRedHerring } // hitRedHerring

View File

@ -29,16 +29,16 @@ class Kart;
class Collectable class Collectable
{ {
protected: protected:
Kart* owner; Kart* m_owner;
collectableType type; CollectableType m_type;
int number; int m_number;
public: public:
Collectable (Kart* kart_); Collectable (Kart* kart_);
void set (collectableType _type, int n=1); void set (CollectableType _type, int n=1);
void clear () {type=COLLECT_NOTHING; number=0;} void clear () {m_type=COLLECT_NOTHING; m_number=0;}
int getNum () const {return number;} int getNum () const {return m_number;}
collectableType getType () {return type;} CollectableType getType () {return m_type;}
void hitRedHerring(int n); void hitRedHerring(int n);
Material* getIcon (); Material* getIcon ();
void use (); void use ();

View File

@ -24,29 +24,32 @@
#include "material_manager.hpp" #include "material_manager.hpp"
#include "material.hpp" #include "material.hpp"
#include "translation.hpp" #include "translation.hpp"
#include "spark.hpp"
#include "missile.hpp"
#include "homing.hpp"
#if defined(WIN32) && !defined(__CYGWIN__) #if defined(WIN32) && !defined(__CYGWIN__)
# define snprintf _snprintf # define snprintf _snprintf
#endif #endif
typedef struct typedef struct
{ {
collectableType collectable; CollectableType collectable;
const char*const dataFile; const char*const dataFile;
} }
initCollectableType; initCollectableType;
initCollectableType ict[]= initCollectableType ict[]=
{ {
{COLLECT_ZIPPER, "zipper.collectable" }, {COLLECT_ZIPPER, "zipper.collectable" },
#ifdef USE_MAGNETS #ifdef USE_MAGNETS
{COLLECT_MAGNET, "magnet.collectable" }, {COLLECT_MAGNET, "magnet.collectable" },
#endif #endif
{COLLECT_SPARK, "spark.projectile" }, {COLLECT_SPARK, "spark.projectile" },
{COLLECT_MISSILE, "missile.projectile" }, {COLLECT_MISSILE, "missile.projectile" },
{COLLECT_HOMING_MISSILE, "homingmissile.projectile" }, {COLLECT_HOMING, "homingmissile.projectile" },
{COLLECT_ANVIL, "anvil.collectable" }, {COLLECT_ANVIL, "anvil.collectable" },
{COLLECT_PARACHUTE, "parachute.collectable" }, {COLLECT_PARACHUTE, "parachute.collectable" },
{COLLECT_MAX, "" }, {COLLECT_MAX, "" },
}; };
CollectableManager* collectable_manager=0; CollectableManager* collectable_manager=0;
@ -109,23 +112,13 @@ void CollectableManager::Load(int collectType, const char* filename)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CollectableManager::LoadNode(const lisp::Lisp* lisp, int collectType ) void CollectableManager::LoadNode(const lisp::Lisp* lisp, int collectType )
{ {
std::string sName, sModel, sIconFile; std::string sName, sModel, sIconFile;
int dummy; lisp->get("name", sName );
lisp->get("name", sName ); // the name is actually ignored lisp->get("model", sModel );
lisp->get("model", sModel ); lisp->get("icon", sIconFile );
lisp->get("icon", sIconFile );
// If the speed value is an integer (e.g. no "."), an uninitialised
// value will be returned. In this case try reading the speed as
// an integer value.
if(!lisp->get("speed", m_all_speeds[collectType]))
{
dummy=-1;
lisp->get("speed", dummy);
m_all_speeds[collectType]=(float)dummy;
}
// load material // load material
m_all_icons [collectType] = material_manager->getMaterial(sIconFile); m_all_icons[collectType] = material_manager->getMaterial(sIconFile);
m_all_icons[collectType]->getState()->ref(); m_all_icons[collectType]->getState()->ref();
//FIXME: something probably forgets to disable GL_CULL_FACE after enabling it, //FIXME: something probably forgets to disable GL_CULL_FACE after enabling it,
@ -142,6 +135,21 @@ void CollectableManager::LoadNode(const lisp::Lisp* lisp, int collectType )
else else
{ {
m_all_models[collectType] = 0; m_all_models[collectType] = 0;
#ifdef BULLET
m_all_extends[collectType] = btVector3(0.0f,0.0f,0.0f);
#endif
} }
// Load special attributes for certain collectables
switch (collectType) {
case COLLECT_SPARK:
Spark::init (lisp, m_all_models[collectType]); break;
case COLLECT_MISSILE:
Missile::init(lisp, m_all_models[collectType]); break;
case COLLECT_HOMING:
Homing::init (lisp, m_all_models[collectType]); break;
default:;
} // switch
} // LoadNode } // LoadNode

View File

@ -22,14 +22,18 @@
#include "lisp/parser.hpp" #include "lisp/parser.hpp"
#include "lisp/lisp.hpp" #include "lisp/lisp.hpp"
#ifdef BULLET
#include "btBulletDynamicsCommon.h"
#endif
class Material; class Material;
class ssgEntity; class ssgEntity;
// The anvil and parachute must be at the end of the enum, and the // The anvil and parachute must be at the end of the enum, and the
// zipper just before them (see collectable::hitRedHerring). // zipper just before them (see collectable::hitRedHerring).
enum collectableType {COLLECT_NOTHING, enum CollectableType {COLLECT_NOTHING,
COLLECT_MISSILE, COLLECT_HOMING_MISSILE, COLLECT_MISSILE, COLLECT_HOMING,
COLLECT_SPARK, COLLECT_ZIPPER, COLLECT_SPARK, COLLECT_ZIPPER,
COLLECT_PARACHUTE, COLLECT_ANVIL, COLLECT_PARACHUTE, COLLECT_ANVIL,
#ifdef USE_MAGNETS #ifdef USE_MAGNETS
@ -41,17 +45,26 @@ class CollectableManager
{ {
protected: protected:
Material* m_all_icons [COLLECT_MAX]; Material* m_all_icons [COLLECT_MAX];
float m_all_speeds[COLLECT_MAX]; float m_all_max_distance[COLLECT_MAX]; // if a target is closer than this
float m_all_force_to_target[COLLECT_MAX]; // apply this force to move towards
// the target
float m_all_max_turn_angle[COLLECT_MAX]; // maximum turn angle for homing
ssgEntity* m_all_models[COLLECT_MAX]; ssgEntity* m_all_models[COLLECT_MAX];
btVector3 m_all_extends[COLLECT_MAX];
void LoadNode (const lisp::Lisp* lisp, int collectType); void LoadNode (const lisp::Lisp* lisp, int collectType);
public: public:
CollectableManager (); CollectableManager ();
void loadCollectables(); void loadCollectables();
void removeTextures (); void removeTextures ();
void Load (int collectType, const char* filename); void Load (int collectType, const char* filename);
Material* getIcon (int type) {return m_all_icons [type];} Material* getIcon (int type) const {return m_all_icons [type]; }
float getSpeed (int type) {return m_all_speeds[type];} ssgEntity* getModel (int type) const {return m_all_models[type]; }
ssgEntity* getModel (int type) {return m_all_models[type];} float getForceToTarget(int type) const {return m_all_force_to_target[type]; }
float getMaxDistance (int type) const {return m_all_max_distance[type];}
float getMaxTurnAngle (int type) const {return m_all_max_turn_angle[type];}
#ifdef BULLET
const btVector3& getExtend (int type) const {return m_all_extends[type]; }
#endif
}; };
extern CollectableManager* collectable_manager; extern CollectableManager* collectable_manager;

View File

@ -74,5 +74,6 @@
#define NINETY_DEGREE_RAD (M_PI/2.0f) #define NINETY_DEGREE_RAD (M_PI/2.0f)
#define DEGREE_TO_RAD(x) ((x)*M_PI/180.0f) #define DEGREE_TO_RAD(x) ((x)*M_PI/180.0f)
#define RAD_TO_DEGREE(x) ((x)*180.0f/M_PI)
#endif #endif

View File

@ -26,12 +26,9 @@
Explosion::Explosion(sgCoord* coord) : ssgTransform() Explosion::Explosion(sgCoord* coord) : ssgTransform()
{ {
this->ref();
ssgCutout *cut = new ssgCutout(); ssgCutout *cut = new ssgCutout();
addKid(cut); addKid(cut); // derefing the explosion will free the cutout
// Make sure that the transform object does not get deleted when it is
// removed from the scene graphs. This can happen when the explosion is
// moved to the deletedExplosion list in the projecile_manager.
ref();
m_seq = projectile_manager->getExplosionModel(); m_seq = projectile_manager->getExplosionModel();
cut->addKid(m_seq); cut->addKid(m_seq);
init(coord); init(coord);
@ -45,6 +42,7 @@ void Explosion::init(sgCoord* coord)
setTransform(coord); setTransform(coord);
m_step = -1; m_step = -1;
scene->add(this); scene->add(this);
printf("explosion\n");
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -53,8 +51,8 @@ void Explosion::update (float dt)
if ( ++m_step >= m_seq->getNumKids() ) if ( ++m_step >= m_seq->getNumKids() )
{ {
projectile_manager->FinishedExplosion();
scene->remove((ssgTransform*)this); scene->remove((ssgTransform*)this);
projectile_manager->FinishedExplosion();
return ; return ;
} }

View File

@ -29,10 +29,10 @@ public:
ssgSelector *m_seq ; ssgSelector *m_seq ;
public: public:
Explosion(sgCoord* coord); Explosion(sgCoord* coord);
int inUse () {return (m_step >= 0); }
void init (sgCoord *coord); void init (sgCoord *coord);
void update (float delta_t); void update (float delta_t);
int inUse () {return (m_step >= 0); }
bool hasEnded () {return m_step >= m_seq->getNumKids(); } bool hasEnded () {return m_step >= m_seq->getNumKids(); }
} ; } ;

View File

@ -286,7 +286,7 @@ void HelpMenu::switch_to_second_screen()
widget_manager->add_wgt(WTOK_ITEMIMG2, 10, 13); widget_manager->add_wgt(WTOK_ITEMIMG2, 10, 13);
widget_manager->set_wgt_texture(WTOK_ITEMIMG2, widget_manager->set_wgt_texture(WTOK_ITEMIMG2,
collectable_manager->getIcon(COLLECT_HOMING_MISSILE)->getState()->getTextureHandle()); collectable_manager->getIcon(COLLECT_HOMING)->getState()->getTextureHandle());
widget_manager->set_wgt_color(WTOK_ITEMIMG2, WGT_WHITE); widget_manager->set_wgt_color(WTOK_ITEMIMG2, WGT_WHITE);
widget_manager->show_wgt_texture( WTOK_ITEMIMG2 ); widget_manager->show_wgt_texture( WTOK_ITEMIMG2 );
widget_manager->set_wgt_round_corners(WTOK_ITEMIMG2, WGT_AREA_NONE); widget_manager->set_wgt_round_corners(WTOK_ITEMIMG2, WGT_AREA_NONE);

View File

@ -100,11 +100,25 @@ RaceGUI::handle(GameAction ga, int value)
switch (ga) switch (ga)
{ {
case GA_DEBUG_ADD_SPARK:
if (world->m_race_setup.getNumPlayers() ==1 )
{
Kart* kart = world->getPlayerKart(0);
kart->setCollectable(COLLECT_SPARK, 10000);
}
break;
case GA_DEBUG_ADD_MISSILE: case GA_DEBUG_ADD_MISSILE:
if (world->m_race_setup.getNumPlayers() ==1 ) if (world->m_race_setup.getNumPlayers() ==1 )
{ {
Kart* kart = world->getPlayerKart(0); Kart* kart = world->getPlayerKart(0);
kart->setCollectable((rand()%2)?COLLECT_MISSILE :COLLECT_HOMING_MISSILE, 10000); kart->setCollectable(COLLECT_MISSILE, 10000);
}
break;
case GA_DEBUG_ADD_HOMING:
if (world->m_race_setup.getNumPlayers() ==1 )
{
Kart* kart = world->getPlayerKart(0);
kart->setCollectable(COLLECT_HOMING, 10000);
} }
break; break;
case GA_DEBUG_TOGGLE_FPS: case GA_DEBUG_TOGGLE_FPS:
@ -708,7 +722,7 @@ void RaceGUI::drawSpeed(Kart* kart, int offset_x, int offset_y,
else else
{ {
glTexCoord2f(0, 1);glVertex2i(offset_x, offset_y+width); glTexCoord2f(0, 1);glVertex2i(offset_x, offset_y+width);
glTexCoord2f((speedRatio-0.5)*2, 1);glVertex2i((int)(offset_x+height*(speedRatio-0.5)*2), offset_y+height); glTexCoord2f((speedRatio-0.5f)*2, 1);glVertex2i((int)(offset_x+height*(speedRatio-0.5f)*2), offset_y+height);
} }
glEnd () ; glEnd () ;

View File

@ -105,7 +105,7 @@
/> />
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
WholeProgramOptimization="true" WholeProgramOptimization="false"
AdditionalIncludeDirectories="..\..\bullet\src;&quot;$(GLUT_PATH)\include&quot;" AdditionalIncludeDirectories="..\..\bullet\src;&quot;$(GLUT_PATH)\include&quot;"
PreprocessorDefinitions="WIN32;NDEBUG" PreprocessorDefinitions="WIN32;NDEBUG"
MinimalRebuild="true" MinimalRebuild="true"

View File

@ -704,6 +704,10 @@
RelativePath="../../../src\explosion.cpp" RelativePath="../../../src\explosion.cpp"
> >
</File> </File>
<File
RelativePath="..\..\flyable.cpp"
>
</File>
<File <File
RelativePath="../../../src\game_manager.cpp" RelativePath="../../../src\game_manager.cpp"
> >
@ -728,6 +732,10 @@
RelativePath="../../../src\history.cpp" RelativePath="../../../src\history.cpp"
> >
</File> </File>
<File
RelativePath="..\..\homing.cpp"
>
</File>
<File <File
RelativePath="../../../src\isect.cpp" RelativePath="../../../src\isect.cpp"
> >
@ -760,6 +768,10 @@
RelativePath="../../../src\material_manager.cpp" RelativePath="../../../src\material_manager.cpp"
> >
</File> </File>
<File
RelativePath="..\..\missile.cpp"
>
</File>
<File <File
RelativePath="../../../src\moveable.cpp" RelativePath="../../../src\moveable.cpp"
> >
@ -792,10 +804,6 @@
RelativePath="../../../src\player_kart.cpp" RelativePath="../../../src\player_kart.cpp"
> >
</File> </File>
<File
RelativePath="../../../src\projectile.cpp"
>
</File>
<File <File
RelativePath="../../../src\projectile_manager.cpp" RelativePath="../../../src\projectile_manager.cpp"
> >
@ -848,6 +856,10 @@
RelativePath="../../../src\sound_plib.cpp" RelativePath="../../../src\sound_plib.cpp"
> >
</File> </File>
<File
RelativePath="..\..\spark.cpp"
>
</File>
<File <File
RelativePath="../../../src\ssg_help.cpp" RelativePath="../../../src\ssg_help.cpp"
> >
@ -880,10 +892,6 @@
RelativePath="../../../src\user_config.cpp" RelativePath="../../../src\user_config.cpp"
> >
</File> </File>
<File
RelativePath="../../../src\utils.cpp"
>
</File>
<File <File
RelativePath="..\..\widget.cpp" RelativePath="..\..\widget.cpp"
> >
@ -1070,6 +1078,10 @@
RelativePath="../../../src\explosion.hpp" RelativePath="../../../src\explosion.hpp"
> >
</File> </File>
<File
RelativePath="..\..\flyable.hpp"
>
</File>
<File <File
RelativePath="../../../src\game_manager.hpp" RelativePath="../../../src\game_manager.hpp"
> >
@ -1094,6 +1106,14 @@
RelativePath="../../../src\history.hpp" RelativePath="../../../src\history.hpp"
> >
</File> </File>
<File
RelativePath="..\..\homing.hpp"
>
</File>
<File
RelativePath="..\..\input.hpp"
>
</File>
<File <File
RelativePath="../../../src\isect.hpp" RelativePath="../../../src\isect.hpp"
> >
@ -1122,6 +1142,10 @@
RelativePath="../../../src\material_manager.hpp" RelativePath="../../../src\material_manager.hpp"
> >
</File> </File>
<File
RelativePath="..\..\missile.hpp"
>
</File>
<File <File
RelativePath="../../../src\moveable.hpp" RelativePath="../../../src\moveable.hpp"
> >
@ -1166,10 +1190,6 @@
RelativePath="../../../src\player_kart.hpp" RelativePath="../../../src\player_kart.hpp"
> >
</File> </File>
<File
RelativePath="../../../src\projectile.hpp"
>
</File>
<File <File
RelativePath="../../../src\projectile_manager.hpp" RelativePath="../../../src\projectile_manager.hpp"
> >
@ -1234,6 +1254,10 @@
RelativePath="../../../src\sound_plib.hpp" RelativePath="../../../src\sound_plib.hpp"
> >
</File> </File>
<File
RelativePath="..\..\spark.hpp"
>
</File>
<File <File
RelativePath="../../../src\ssg_help.hpp" RelativePath="../../../src\ssg_help.hpp"
> >
@ -1266,10 +1290,6 @@
RelativePath="../../../src\user_config.hpp" RelativePath="../../../src\user_config.hpp"
> >
</File> </File>
<File
RelativePath="../../../src\utils.hpp"
>
</File>
<File <File
RelativePath="..\..\widget.hpp" RelativePath="..\..\widget.hpp"
> >

View File

@ -155,6 +155,8 @@ enum GameAction
GA_LEAVE_RACE, // Switch from race to menu. GA_LEAVE_RACE, // Switch from race to menu.
GA_DEBUG_ADD_MISSILE, GA_DEBUG_ADD_MISSILE,
GA_DEBUG_ADD_SPARK,
GA_DEBUG_ADD_HOMING,
GA_DEBUG_TOGGLE_FPS, GA_DEBUG_TOGGLE_FPS,
GA_DEBUG_BULLET, GA_DEBUG_BULLET,
GA_DEBUG_TOGGLE_WIREFRAME, GA_DEBUG_TOGGLE_WIREFRAME,

View File

@ -349,6 +349,7 @@ void Kart::reset()
m_race_lap = -1; m_race_lap = -1;
m_lap_start_time = -1.0f; m_lap_start_time = -1.0f;
m_time_at_last_lap = 99999.9f;
m_shortcut_count = 0; m_shortcut_count = 0;
m_shortcut_sector = Track::UNKNOWN_SECTOR; m_shortcut_sector = Track::UNKNOWN_SECTOR;
m_shortcut_type = SC_NONE; m_shortcut_type = SC_NONE;
@ -927,8 +928,6 @@ float Kart::handleWheelie(float dt)
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void Kart::updatePhysics (float dt) void Kart::updatePhysics (float dt)
{ {
#ifdef BULLET
float engine_power = getActualWheelForce() + handleWheelie(dt); float engine_power = getActualWheelForce() + handleWheelie(dt);
if(m_attachment.getType()==ATTACH_PARACHUTE) engine_power*=0.2f; if(m_attachment.getType()==ATTACH_PARACHUTE) engine_power*=0.2f;
@ -1011,222 +1010,6 @@ void Kart::updatePhysics (float dt)
//at low velocity, forces on kart push it back and forth so we ignore this //at low velocity, forces on kart push it back and forth so we ignore this
if(fabsf(m_speed) < 0.2f) // quick'n'dirty workaround for bug 1776883 if(fabsf(m_speed) < 0.2f) // quick'n'dirty workaround for bug 1776883
m_speed = 0; m_speed = 0;
#else // ! BULLET
m_skid_front = m_skid_rear = false;
sgVec3 AirResistance, SysResistance;
// Get some values once, to avoid calling them more than once.
const float WORLD_GRAVITY = world->getGravity();
const float WHEEL_BASE = getWheelBase();
const float MASS = getMass(); // includes m_attachment.WeightAdjust
const float AIR_FRICTION = getAirResistance(); // includes attachmetn.AirFrictAdjust
const float ROLL_RESIST = getRollResistance();
if(m_wheelie_angle>0.0f)
{
m_velocity.xyz[1]-=getWheelieSpeedBoost()*m_wheelie_angle/getWheelieMaxPitch();
if(m_velocity.xyz[1]<0) m_velocity.xyz[1]=0.0;
}
// Handle throttle and brakes
// ==========================
float throttle;
if(m_on_ground)
{
if(m_controls.brake)
{
throttle = m_velocity.xyz[1]<0.0f ? -1.0f : -getBrakeFactor();
}
else
{ // not braking
throttle = m_velocity.xyz[1]<0.0f ? getBrakeFactor()
: m_controls.accel*m_current_friction*m_current_friction;
}
// Handle wheelies
// ===============
if ( m_controls.wheelie && m_velocity.xyz[1] >=
getMaxSpeed()*getWheelieMaxSpeedRatio())
{
m_velocity.hpr[0]=0.0;
if ( m_wheelie_angle < getWheelieMaxPitch() )
m_wheelie_angle += getWheeliePitchRate() * dt;
else
m_wheelie_angle = getWheelieMaxPitch();
}
else if ( m_wheelie_angle > 0.0f )
{
m_wheelie_angle -= getWheelieRestoreRate() * dt;
if ( m_wheelie_angle <= 0.0f ) m_wheelie_angle = 0.0f ;
}
}
else
{ // not on ground
throttle = 0.0;
} // if !m_on_ground
float ForceLong = throttle * getMaxPower();
// apply air friction and system friction
AirResistance[0] = 0.0f;
AirResistance[1] = AIR_FRICTION*m_velocity.xyz[1]*fabs(m_velocity.xyz[1]);
AirResistance[2] = 0.0f;
SysResistance[0] = ROLL_RESIST*m_velocity.xyz[0];;
SysResistance[1] = ROLL_RESIST*m_velocity.xyz[1];
SysResistance[2] = 0.0f;
//
// Compute longitudinal acceleration for slipping
// ----------------------------------------------
const float FORCE_ON_REAR_TIRE = 0.5f*MASS*WORLD_GRAVITY + m_prev_accel*MASS*getHeightCOG()/WHEEL_BASE;
const float FORCE_ON_FRONT_TIRE = MASS*WORLD_GRAVITY - FORCE_ON_REAR_TIRE;
float maxGrip = std::max(FORCE_ON_REAR_TIRE,FORCE_ON_FRONT_TIRE)*getTireGrip();
// If the kart is on ground, modify the grip by the friction
// modifier for the texture/terrain.
if(m_on_ground && m_material_hot) maxGrip *= m_material_hot->getFriction();
// Gravity handling
// ================
float ForceGravity;
if(m_on_ground)
{
if(m_normal_hot)
{
// Adjust pitch and roll according to the current terrain. To compute
// the correspondant angles, we consider first a normalised line
// pointing into the direction the kart is facing (pointing from (0,0,0)
// to (x,y,0)). The angle between this line and the triangle the kart is
// on determines the pitch. Similartly the roll is computed, using a
// normalised line pointing to the right of the kart, for which we simply
// use (-y,x,0).
const float kartAngle = m_curr_pos.hpr[0]*M_PI/180.0f;
const float X = -sin(kartAngle);
const float Y = cos(kartAngle);
// Compute the angle between the normal of the plane and the line to
// (x,y,0). (x,y,0) is normalised, so are the coordinates of the plane,
// simplifying the computation of the scalar product.
float pitch = ( (*m_normal_hot)[0]*X + (*m_normal_hot)[1]*Y ); // use ( x,y,0)
float roll = (-(*m_normal_hot)[0]*Y + (*m_normal_hot)[1]*X ); // use (-y,x,0)
// The actual angle computed above is between the normal and the (x,y,0)
// line, so to compute the actual angles 90 degrees must be subtracted.
pitch = acosf(pitch)/M_PI*180.0f-90.0f;
roll = acosf(roll )/M_PI*180.0f-90.0f;
// if dt is too big, the relaxation will overshoot, and the
// karts will either be hopping, or even turn upside down etc.
if(dt<=0.05)
{
# define RELAX(oldVal, newVal) (oldVal + (newVal-oldVal)*dt*20.0f)
m_curr_pos.hpr[1] = RELAX(m_curr_pos.hpr[1],pitch);
m_curr_pos.hpr[2] = RELAX(m_curr_pos.hpr[2],roll );
}
else
{
m_curr_pos.hpr[1] = pitch;
m_curr_pos.hpr[2] = roll ;
}
if(fabsf(m_curr_pos.hpr[1])>fabsf(pitch)) m_curr_pos.hpr[1]=pitch;
if(fabsf(m_curr_pos.hpr[2])>fabsf(roll )) m_curr_pos.hpr[2]=roll;
}
if(m_controls.jump)
{ // ignore gravity down when jumping
ForceGravity = stk_config->m_jump_impulse*WORLD_GRAVITY;
}
else
{ // kart is on groud and not jumping
if(user_config->m_improved_physics)
{
// FIXME:
// While these physics computation is correct, it is very difficult
// to drive, esp. the sandtrack: the grades (with the current
// physics parameters) are too steep, so the kart needs a very high
// initial velocity to be able to reach the top. Especially the
// AI gets stuck very easily! Perhaps reduce the forces somewhat?
const float PITCH_IN_RAD = m_curr_pos.hpr[1]*M_PI/180.0f;
ForceGravity = -WORLD_GRAVITY * MASS * cos(PITCH_IN_RAD);
ForceLong -= WORLD_GRAVITY * MASS * sin(PITCH_IN_RAD);
}
else
{
ForceGravity = -WORLD_GRAVITY * MASS;
}
}
}
else
{ // kart is not on ground, gravity applies all to z axis.
ForceGravity = -WORLD_GRAVITY * MASS;
}
m_velocity.xyz[2] += ForceGravity / MASS * dt;
if(m_wheelie_angle <= 0.0f && m_on_ground)
{
// At low speed, the advanced turning mode can result in 'flickering', i.e.
// very quick left/right movements. The reason might be:
// 1) integration timestep to big
// 2) the kart turning too much, thus 'oversteering', which then gets
// corrected (which might be caused by wrongly tuned physics parameters,
// or the too big timestep mentioned above
// Since at lower speed the simple turning algorithm is good enough,
// the advanced sliding turn algorithm is only used at higher speeds.
// FIXME: for now, only use the simple steering algorithm.
// so the test for 'lower speed' is basically disabled for now,
// since the velocity will always be lower than 1.5*100000.0f
if(fabsf(m_velocity.xyz[1])<150000.0f)
{
const float MSA = getMaxSteerAngle();
m_velocity.hpr[0] = m_controls.lr * ((m_velocity.xyz[1]>=0.0f) ? MSA : -MSA);
if(m_velocity.hpr[0]> MSA) m_velocity.hpr[0] = MSA; // In case the AI sets
if(m_velocity.hpr[0]<-MSA) m_velocity.hpr[0] = -MSA; // m_controls.lr >1 or <-1
}
else
{
const float STEER_ANGLE = m_controls.lr*getMaxSteerAngle()*M_PI/180.0f;
const float TURN_DISTANCE = m_velocity.hpr[0]*M_PI/180.0f * WHEEL_BASE/2.0f;
const float SLIP_ANGLE_FRONT = atan((m_velocity.xyz[0]+TURN_DISTANCE)
/fabsf(m_velocity.xyz[1]))
- sgn(m_velocity.xyz[1])*STEER_ANGLE;
const float SLIP_ANGLE_REAR = atan((m_velocity.xyz[0]-TURN_DISTANCE)
/fabsf(m_velocity.xyz[1]));
const float FORCE_LAT_FRONT = NormalizedLateralForce(SLIP_ANGLE_FRONT, getCornerStiffF())
* FORCE_ON_FRONT_TIRE - SysResistance[0]*0.5f;
const float FORCE_LAT_REAR = NormalizedLateralForce(SLIP_ANGLE_REAR, getCornerStiffR())
* FORCE_ON_REAR_TIRE - SysResistance[0]*0.5f;
const float CORNER_FORCE = FORCE_LAT_REAR + cos(STEER_ANGLE)*FORCE_LAT_FRONT;
m_velocity.xyz[0] = CORNER_FORCE/MASS*dt;
const float TORQUE = FORCE_LAT_REAR *WHEEL_BASE/2
- cos(STEER_ANGLE)*FORCE_LAT_FRONT*WHEEL_BASE/2;
const float ANGLE_ACCELERATION = TORQUE/getInertia();
m_velocity.hpr[0] += ANGLE_ACCELERATION*dt*180.0f/M_PI;
} // fabsf(m_velocity.xyz[1])<0.5
} // m_wheelie_angle <=0.0f && m_on_ground
// Longitudinal accelleration
// ==========================
const float EFECTIVE_FORCE = (ForceLong-AirResistance[1]-SysResistance[1]);
// Slipping: more force than what can be supported by the back wheels
// --> reduce the effective force acting on the kart - currently
// by an arbitrary value.
if(fabs(EFECTIVE_FORCE)>maxGrip)
{
// EFECTIVE_FORCE *= 0.4f;
// m_skid_rear = true;
} // while EFECTIVE_FORCE>maxGrip
float ACCELERATION = EFECTIVE_FORCE / MASS;
m_velocity.xyz[1] += ACCELERATION * dt;
m_prev_accel = ACCELERATION;
if(m_wheelie_angle>0.0f)
{
m_velocity.xyz[1]+=
getWheelieSpeedBoost()*m_wheelie_angle/getWheelieMaxPitch();
if(m_velocity.xyz[1]<0) m_velocity.xyz[1]=0.0;
}
#endif
} // updatePhysics } // updatePhysics
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1478,7 +1261,7 @@ void Kart::loadData()
lod -> addKid ( obj ) ; lod -> addKid ( obj ) ;
lod -> setRanges ( r, 2 ) ; lod -> setRanges ( r, 2 ) ;
this-> getModel() -> addKid ( lod ) ; this-> getModelTransform() -> addKid ( lod ) ;
// Attach Particle System // Attach Particle System
//JH sgCoord pipe_pos = {{0, 0, .3}, {0, 0, 0}} ; //JH sgCoord pipe_pos = {{0, 0, .3}, {0, 0, 0}} ;
@ -1495,7 +1278,7 @@ void Kart::loadData()
m_shadow = createShadow(m_kart_properties->getShadowFile(), -1, 1, -1, 1); m_shadow = createShadow(m_kart_properties->getShadowFile(), -1, 1, -1, 1);
m_shadow->ref(); m_shadow->ref();
m_model->addKid ( m_shadow ); m_model_transform->addKid ( m_shadow );
} // loadData } // loadData
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1548,7 +1331,7 @@ void Kart::placeModel ()
// c.xyz[2] += 0.3f*fabs(sin(m_wheelie_angle*SG_DEGREES_TO_RADIANS)); // c.xyz[2] += 0.3f*fabs(sin(m_wheelie_angle*SG_DEGREES_TO_RADIANS));
const float CENTER_SHIFT = getGravityCenterShift(); const float CENTER_SHIFT = getGravityCenterShift();
c.xyz[2] -= (0.5f-CENTER_SHIFT)*m_kart_height; // adjust for center of gravity c.xyz[2] -= (0.5f-CENTER_SHIFT)*m_kart_height; // adjust for center of gravity
m_model->setTransform(&c); m_model_transform->setTransform(&c);
// Check if a kart needs to be rescued. // Check if a kart needs to be rescued.
if((fabs(m_curr_pos.hpr[2])>60 && if((fabs(m_curr_pos.hpr[2])>60 &&

View File

@ -163,8 +163,8 @@ public:
m_wheelie_angle=angle; m_wheelie_angle=angle;
m_zipper_time_left=time; m_zipper_time_left=time;
} }
void setCollectable (collectableType t, int n) void setCollectable (CollectableType t, int n)
{ m_collectable.set(t, n); } { m_collectable.set(t, n); }
void setPosition (int p) {m_race_position = p; } void setPosition (int p) {m_race_position = p; }
int getSector () { return m_track_sector; } int getSector () { return m_track_sector; }
float getDistanceDownTrack() { return m_curr_track_coords[1]; } float getDistanceDownTrack() { return m_curr_track_coords[1]; }

View File

@ -42,7 +42,7 @@ public:
const int getKartId (const std::string IDENT); const int getKartId (const std::string IDENT);
void loadKartData (bool dont_load_models=false); void loadKartData (bool dont_load_models=false);
const float getMaximumSteeringAngle() {return m_max_steer_angle;} const float getMaximumSteeringAngle() {return m_max_steer_angle;}
const unsigned int getNumberOfKarts () {return m_karts_properties.size();} const unsigned int getNumberOfKarts () {return (unsigned int)m_karts_properties.size();}
/** Return len random karts */ /** Return len random karts */
std::vector<std::string> getRandomKarts (int len); std::vector<std::string> getRandomKarts (int len);

View File

@ -32,10 +32,8 @@
#include "plib/ul.h" #include "plib/ul.h"
#include "loader.hpp" #include "loader.hpp"
#include "world.hpp" #include "world.hpp"
#ifdef BULLET
#include "btBulletDynamicsCommon.h" #include "btBulletDynamicsCommon.h"
#include "moving_physics.hpp" #include "moving_physics.hpp"
#endif
#include "moving_texture.hpp" #include "moving_texture.hpp"
#include "translation.hpp" #include "translation.hpp"
#include "material_manager.hpp" #include "material_manager.hpp"
@ -361,20 +359,16 @@ ssgBranch *Loader::createBranch(char *data) const
{ {
ssgTexTrans *br = new ssgTexTrans(); ssgTexTrans *br = new ssgTexTrans();
Callback *c = new MovingTexture(data, br); Callback *c = new MovingTexture(data, br);
br->setUserData(new ssgBase());
br->setName("MovingTexture");
callback_manager->addCallback(c, m_current_callback_type); callback_manager->addCallback(c, m_current_callback_type);
return br; return br;
} }
if(strncmp("physics", data, strlen("physics")) == 0) if(strncmp("physics", data, strlen("physics")) == 0)
{ {
#ifdef BULLET ssgTransform *tr = new ssgTransform();
MovingPhysics *mp = new MovingPhysics(std::string(data)); MovingPhysics *mp = new MovingPhysics(std::string(data), tr);
callback_manager->addCallback(mp, m_current_callback_type); callback_manager->addCallback(mp, m_current_callback_type);
return mp;
#else return tr;
return NULL;
#endif
} }
fprintf(stderr, "Warning: Ignoring userdata '%s'\n", data); fprintf(stderr, "Warning: Ignoring userdata '%s'\n", data);
return NULL ; return NULL ;

View File

@ -27,15 +27,13 @@
Moveable::Moveable (bool bHasHistory) Moveable::Moveable (bool bHasHistory)
{ {
#ifdef BULLET m_body = 0;
m_body = 0; m_motion_state = 0;
m_motion_state = 0; m_shadow = 0;
#endif m_first_time = true ;
m_shadow = 0; m_model_transform = new ssgTransform();
m_first_time = true ;
m_model = new ssgTransform();
m_model->ref(); m_model_transform->ref();
sgZeroVec3 ( m_reset_pos.xyz ) ; sgZeroVec3 ( m_reset_pos.hpr ) ; sgZeroVec3 ( m_reset_pos.xyz ) ; sgZeroVec3 ( m_reset_pos.hpr ) ;
@ -55,11 +53,9 @@ Moveable::Moveable (bool bHasHistory)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
Moveable::~Moveable() Moveable::~Moveable()
{ {
#ifdef BULLET
// The body is being removed from the world in kart/projectile // The body is being removed from the world in kart/projectile
if(m_body) delete m_body; if(m_body) delete m_body;
if(m_motion_state) delete m_motion_state; if(m_motion_state) delete m_motion_state;
#endif
if(m_history_velocity) if(m_history_velocity)
{ {
delete [] m_history_velocity; delete [] m_history_velocity;
@ -71,9 +67,6 @@ Moveable::~Moveable()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Moveable::reset () void Moveable::reset ()
{ {
#ifndef BULLET
m_on_ground = true;
#endif
m_collided = false; m_collided = false;
m_crashed = false; m_crashed = false;
m_material_hot = NULL; m_material_hot = NULL;
@ -87,7 +80,6 @@ void Moveable::reset ()
} // reset } // reset
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifdef BULLET
void Moveable::createBody(float mass, btTransform& trans, void Moveable::createBody(float mass, btTransform& trans,
btCollisionShape *shape, MoveableType m) { btCollisionShape *shape, MoveableType m) {
@ -102,7 +94,7 @@ void Moveable::createBody(float mass, btTransform& trans,
m_body->setUserPointer(this); m_body->setUserPointer(this);
setMoveableType(m); setMoveableType(m);
} // createBody } // createBody
#endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Moveable::update (float dt) void Moveable::update (float dt)
{ {
@ -140,7 +132,6 @@ void Moveable::update (float dt)
sgVec3 start ; sgCopyVec3 (start, m_curr_pos.xyz ); sgVec3 start ; sgCopyVec3 (start, m_curr_pos.xyz );
sgVec3 end ; sgCopyVec3 (end , result[3] ); sgVec3 end ; sgCopyVec3 (end , result[3] );
const float HOT = collectIsectData(start, end );
sgCopyVec3 (result[3], end) ; sgCopyVec3 (result[3], end) ;
@ -177,13 +168,7 @@ void Moveable::update (float dt)
sgCopyCoord(&(m_history_position[history->GetCurrentIndex()]), &m_curr_pos); sgCopyCoord(&(m_history_position[history->GetCurrentIndex()]), &m_curr_pos);
} }
} // if m_history_position } // if m_history_position
const float HAT = m_curr_pos.xyz[2]-HOT;
#ifndef BULLET
m_on_ground = ( HAT <= 0.01 );
doCollisionAnalysis(dt, HOT);
#endif
placeModel () ; placeModel () ;
m_first_time = false ; m_first_time = false ;
@ -250,10 +235,6 @@ void Moveable::ReadHistory(char* s, int kartNumber, int indx)
} // ReadHistory } // ReadHistory
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifndef BULLET
void Moveable::doCollisionAnalysis ( float,float ) { /* Empty by Default. */ }
#endif
#define ISECT_STEP_SIZE 0.4f #define ISECT_STEP_SIZE 0.4f
#define COLLISION_SPHERE_RADIUS 0.6f #define COLLISION_SPHERE_RADIUS 0.6f
@ -371,8 +352,7 @@ float Moveable::getIsectData ( sgVec3 start, sgVec3 end )
m_material_hot = material_manager->getMaterial(m_leaf); m_material_hot = material_manager->getMaterial(m_leaf);
// Only rescue the kart if it (nearly) touches the reset-material, // Only rescue the kart if it (nearly) touches the reset-material,
// not only when it is above it. The condition for touching // not only when it is above it. The condition for touching
// a material is coarser then for the m_on_ground condition // a material is somewha coars, since the kart might have been falling
// (which tests for <0.01) - since the kart might have been falling
// for quite some time, it might be really fast, so I guess a somewhat // for quite some time, it might be really fast, so I guess a somewhat
// coarser test is better for that case. // coarser test is better for that case.
if(m_material_hot->isReset() && if(m_material_hot->isReset() &&

View File

@ -41,7 +41,7 @@
class Moveable class Moveable
{ {
public: public:
enum MoveableType {MOV_KART, MOV_PROJECTILE} ; enum MoveableType {MOV_KART, MOV_PROJECTILE, MOV_TRACK} ;
protected: protected:
MoveableType m_moveable_type; /* used when upcasting bullet user pointers */ MoveableType m_moveable_type; /* used when upcasting bullet user pointers */
sgCoord m_reset_pos; /* Where to start in case of a reset */ sgCoord m_reset_pos; /* Where to start in case of a reset */
@ -50,15 +50,12 @@ protected:
sgVec3 m_abs_velocity; /* world coordinates' velocity vector */ sgVec3 m_abs_velocity; /* world coordinates' velocity vector */
sgVec4* m_normal_hot; /* plane on which HOT was computed */ sgVec4* m_normal_hot; /* plane on which HOT was computed */
Material* m_material_hot; /* Material at HOT */ Material* m_material_hot; /* Material at HOT */
ssgTransform* m_model; ssgTransform* m_model_transform; // The transform where the model is under
ssgTransform* m_shadow; ssgTransform* m_shadow;
int m_collided; int m_collided;
int m_crashed; int m_crashed;
sgVec3 m_surface_avoidance_vector ; sgVec3 m_surface_avoidance_vector ;
int m_first_time ; int m_first_time ;
#ifndef BULLET
int m_on_ground ;
#endif
float collectIsectData ( sgVec3 start, sgVec3 end ) ; float collectIsectData ( sgVec3 start, sgVec3 end ) ;
sgCoord* m_history_velocity; sgCoord* m_history_velocity;
@ -76,10 +73,7 @@ public:
Moveable (bool bHasHistory=false); Moveable (bool bHasHistory=false);
virtual ~Moveable(); virtual ~Moveable();
ssgTransform* getModel () {return m_model ; } ssgTransform* getModelTransform() {return m_model_transform; }
#ifndef BULLET
int isOnGround () {return m_on_ground; }
#endif
MoveableType getMoveableType() const {return m_moveable_type; } MoveableType getMoveableType() const {return m_moveable_type; }
void setMoveableType(MoveableType m){m_moveable_type=m; } void setMoveableType(MoveableType m){m_moveable_type=m; }
sgCoord* getVelocity () {return & m_velocity; } sgCoord* getVelocity () {return & m_velocity; }
@ -87,7 +81,7 @@ public:
const sgCoord* getCoord () const {return &m_curr_pos; } const sgCoord* getCoord () const {return &m_curr_pos; }
const sgVec4* getNormalHOT () const {return m_normal_hot; } const sgVec4* getNormalHOT () const {return m_normal_hot; }
void setCoord (sgCoord* pos) {sgCopyCoord ( &m_curr_pos,pos); } void setCoord (sgCoord* pos) {sgCopyCoord ( &m_curr_pos,pos); }
virtual void placeModel () {m_model->setTransform(&m_curr_pos); } virtual void placeModel () {m_model_transform->setTransform(&m_curr_pos); }
virtual void handleZipper () {}; virtual void handleZipper () {};
virtual void reset (); virtual void reset ();
virtual void update (float dt) ; virtual void update (float dt) ;
@ -104,14 +98,12 @@ public:
float getIsectData (sgVec3 start, sgVec3 end ); float getIsectData (sgVec3 start, sgVec3 end );
void WriteHistory (char* s, int kartNumber, int indx); void WriteHistory (char* s, int kartNumber, int indx);
void ReadHistory (char* s, int kartNumber, int indx); void ReadHistory (char* s, int kartNumber, int indx);
#ifdef BULLET
btRigidBody* getBody () const {return m_body; } btRigidBody* getBody () const {return m_body; }
void createBody(float mass, btTransform& trans, void createBody(float mass, btTransform& trans,
btCollisionShape *shape, MoveableType m); btCollisionShape *shape, MoveableType m);
void getTrans (btTransform* t) const void getTrans (btTransform* t) const
{m_motion_state->getWorldTransform(*t);} {m_motion_state->getWorldTransform(*t);}
void setTrans (btTransform& t){m_motion_state->setWorldTransform(t);} void setTrans (btTransform& t){m_motion_state->setWorldTransform(t);}
#endif
} }
; // class Moveable ; // class Moveable

View File

@ -26,17 +26,16 @@
#include "ssg_help.hpp" #include "ssg_help.hpp"
#include "scene.hpp" #include "scene.hpp"
#ifdef BULLET
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
MovingPhysics::MovingPhysics(const std::string data) MovingPhysics::MovingPhysics(const std::string data, ssgTransform* trans)
: ssgTransform(), Callback() : Callback()
{ {
m_trans = trans;
m_shape = NULL; m_shape = NULL;
m_body = NULL; m_body = NULL;
m_motion_state = NULL; m_motion_state = NULL;
m_mass = 1; m_mass = 1;
setUserData(new ssgBase()); m_trans->setUserData(new ssgBase()); // prevent tree optimisations to remove this node
ref();
std::vector<std::string> parameters = StringUtils::split(data, ' '); std::vector<std::string> parameters = StringUtils::split(data, ' ');
if(parameters.size()<2) if(parameters.size()<2)
@ -81,8 +80,8 @@ MovingPhysics::MovingPhysics(const std::string data)
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
MovingPhysics::~MovingPhysics() MovingPhysics::~MovingPhysics()
{ {
world->getPhysics()->getPhysicsWorld()->removeRigidBody(m_body); scene->remove(m_trans);
deRef(); world->getPhysics()->removeBody(m_body);
delete m_shape; delete m_shape;
delete m_motion_state; delete m_motion_state;
delete m_body; delete m_body;
@ -104,15 +103,15 @@ void MovingPhysics::init()
// 1. Remove the object from the graph and attach it to the root // 1. Remove the object from the graph and attach it to the root
// ------------------------------------------------------------- // -------------------------------------------------------------
if(getNumParents()>1) if(m_trans->getNumParents()>1)
{ {
fprintf(stderr, "WARNING: physical object with more than one parent!!\n"); fprintf(stderr, "WARNING: physical object with more than one parent!!\n");
return; return;
} }
ssgBranch *parent = getParent(0); ssgBranch *parent = m_trans->getParent(0);
parent->removeKid(this); scene->add(m_trans);
scene->add(this); parent->removeKid(m_trans);
// 2. Determine the original position of the object // 2. Determine the original position of the object
// ------------------------------------------------ // ------------------------------------------------
@ -161,18 +160,18 @@ void MovingPhysics::init()
// 3. Determine size of the object // 3. Determine size of the object
// ------------------------------- // -------------------------------
float x_min, x_max, y_min, y_max, z_min, z_max, radius; float x_min, x_max, y_min, y_max, z_min, z_max, radius;
MinMax(this, &x_min, &x_max, &y_min, &y_max, &z_min, &z_max); MinMax(m_trans, &x_min, &x_max, &y_min, &y_max, &z_min, &z_max);
m_half_height = 0.5f*(z_max-z_min); m_half_height = 0.5f*(z_max-z_min);
switch (m_body_type) switch (m_body_type)
{ {
case BODY_CONE: radius = 0.5f*std::max(x_max-x_min, y_max-y_min); case BODY_CONE: radius = 0.5f*std::max(x_max-x_min, y_max-y_min);
m_shape = new btConeShape(radius, z_max-z_min); m_shape = new btConeShape(radius, z_max-z_min);
setName("cone"); m_trans->setName("cone");
break; break;
case BODY_BOX: m_shape = new btBoxShape(btVector3(0.5f*(x_max-x_min), case BODY_BOX: m_shape = new btBoxShape(btVector3(0.5f*(x_max-x_min),
0.5f*(y_max-y_min), 0.5f*(y_max-y_min),
0.5f*(z_max-z_min) ) ); 0.5f*(z_max-z_min) ) );
setName("box"); m_trans->setName("box");
break; break;
case BODY_NONE: fprintf(stderr, "WARNING: Uninitialised moving shape\n"); case BODY_NONE: fprintf(stderr, "WARNING: Uninitialised moving shape\n");
break; break;
@ -204,10 +203,9 @@ void MovingPhysics::update(float dt)
// Transfer the new position and hpr to m_curr_pos // Transfer the new position and hpr to m_curr_pos
sgCoord m_curr_pos; sgCoord m_curr_pos;
sgSetCoord(&m_curr_pos, m); sgSetCoord(&m_curr_pos, m);
setTransform(&m_curr_pos); m_trans->setTransform(&m_curr_pos);
} // update } // update
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#endif
/* EOF */ /* EOF */

View File

@ -24,20 +24,21 @@
#include "btBulletDynamicsCommon.h" #include "btBulletDynamicsCommon.h"
#include "callback.hpp" #include "callback.hpp"
class MovingPhysics : public ssgTransform, public Callback class MovingPhysics : public Callback
{ {
public: public:
enum bodyTypes {BODY_NONE, BODY_CONE, BODY_BOX}; enum bodyTypes {BODY_NONE, BODY_CONE, BODY_BOX};
protected: protected:
bodyTypes m_body_type; bodyTypes m_body_type;
ssgTransform *m_trans;
btCollisionShape *m_shape; btCollisionShape *m_shape;
btRigidBody *m_body; btRigidBody *m_body;
btDefaultMotionState *m_motion_state; btDefaultMotionState *m_motion_state;
float m_half_height; float m_half_height;
float m_mass; float m_mass;
public: public:
MovingPhysics (const std::string data); MovingPhysics (const std::string data, ssgTransform *trans);
~MovingPhysics (); ~MovingPhysics ();
void update (float dt); void update (float dt);
void init (); void init ();

View File

@ -26,6 +26,9 @@
MovingTexture::MovingTexture(char *data, ssgBranch *branch) MovingTexture::MovingTexture(char *data, ssgBranch *branch)
{ {
m_branch = branch; m_branch = branch;
branch->setUserData(new ssgBase());
branch->setName("MovingTexture");
m_branch->ref(); m_branch->ref();
m_phase = 0.0f; m_phase = 0.0f;
m_mode = MODE_FORWARD; m_mode = MODE_FORWARD;

View File

@ -25,7 +25,7 @@
#include "physics.hpp" #include "physics.hpp"
#include "ssg_help.hpp" #include "ssg_help.hpp"
#include "world.hpp" #include "world.hpp"
#include "projectile.hpp" #include "flyable.hpp"
#include "moving_physics.hpp" #include "moving_physics.hpp"
#include "user_config.hpp" #include "user_config.hpp"
@ -34,22 +34,19 @@
/** Initialise physics. */ /** Initialise physics. */
float Physics::NOHIT=-99999.9f; float const Physics::NOHIT=-99999.9f;
Physics::Physics(float gravity) Physics::Physics(float gravity) : btSequentialImpulseConstraintSolver()
{ {
m_collision_conf = new btDefaultCollisionConfiguration(); m_collision_conf = new btDefaultCollisionConfiguration();
m_dispatcher = new btCollisionDispatcher(m_collision_conf); m_dispatcher = new btCollisionDispatcher(m_collision_conf);
btVector3 worldMin(-1000, -1000, -1000); btVector3 worldMin(-1000, -1000, -1000);
btVector3 worldMax( 1000, 1000, 1000); btVector3 worldMax( 1000, 1000, 1000);
m_axis_sweep = new btAxisSweep3(worldMin, worldMax); m_axis_sweep = new btAxisSweep3(worldMin, worldMax);
m_constraint_solver = new btSequentialImpulseConstraintSolver();
m_dynamics_world = new btDiscreteDynamicsWorld(m_dispatcher, m_dynamics_world = new btDiscreteDynamicsWorld(m_dispatcher,
m_axis_sweep, m_axis_sweep,
m_constraint_solver, this,
m_collision_conf); m_collision_conf);
m_dynamics_world->setGravity(btVector3(0.0f, 0.0f, -gravity)); m_dynamics_world->setGravity(btVector3(0.0f, 0.0f, -gravity));
if(user_config->m_bullet_debug) if(user_config->m_bullet_debug)
@ -63,12 +60,11 @@ Physics::Physics(float gravity)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
Physics::~Physics() Physics::~Physics()
{ {
delete m_dispatcher; if(user_config->m_bullet_debug) delete m_debug_drawer;
delete m_dynamics_world; delete m_dynamics_world;
delete m_axis_sweep; delete m_axis_sweep;
delete m_dispatcher;
delete m_collision_conf; delete m_collision_conf;
delete m_constraint_solver;
if(user_config->m_bullet_debug) delete m_debug_drawer;
} // ~Physics } // ~Physics
@ -178,21 +174,112 @@ void Physics::removeKart(const Kart *kart)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Physics::update(float dt) void Physics::update(float dt)
{ {
// Bullet can report the same collision more than once (up to 4
// contact points per collision. Additionally, more than one internal
// substep might be taken, resulting in potentially even more
// duplicates. To handle this, all collisions (i.e. pair of objects)
// are stored in a vector, but only one entry per collision pair
// of objects.
m_all_collisions.clear();
m_dynamics_world->stepSimulation(dt); m_dynamics_world->stepSimulation(dt);
// ??? m_dynamicsWorld->updateAabbs();
handleCollisions(); // Now handle the actual collision. Note: rockets can not be removed
// inside of this loop, since the same rocket might hit more than one
// other object. So, only a flag is set in the rockets, the actual
// clean up is then done later in the projectile manager.
std::vector<CollisionPair>::iterator p;
for(p=m_all_collisions.begin(); p!=m_all_collisions.end(); ++p)
{
if(p->type_a==Moveable::MOV_KART) { // kart-kart collision
Kart *kartA = (Kart*)(p->a);
Kart *kartB = (Kart*)(p->b);
KartKartCollision(kartA, kartB);
} // if kart-kart collision
else // now the first object must be a projectile
{
if(p->type_b==Moveable::MOV_TRACK) // must be projectile hit track
{
((Flyable*)(p->a))->hitTrack();
}
else if(p->type_b==Moveable::MOV_KART) // projectile hit kart
{
Flyable *f=(Flyable*)(p->a);
f->explode((Kart*)(p->b));
}
else // projectile hits projectile
{
((Flyable*)(p->a))->explode(NULL);
((Flyable*)(p->b))->explode(NULL);
}
}
} // for all p in m_all_collisions
} // update } // update
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Physics::handleCollisions() { /** Handles the special case of two karts colliding with each other
int numManifolds = m_dispatcher->getNumManifolds(); * If both karts have a bomb, they'll explode immediately
for(int i=0; i<numManifolds; i++) */
void Physics::KartKartCollision(Kart *kartA, Kart *kartB)
{
Attachment *attachmentA=kartA->getAttachment();
Attachment *attachmentB=kartB->getAttachment();
if(attachmentA->getType()==ATTACH_BOMB)
{
// If both karts have a bomb, explode them immediately:
if(attachmentB->getType()==ATTACH_BOMB)
{
attachmentA->setTimeLeft(0.0f);
attachmentB->setTimeLeft(0.0f);
}
else // only A has a bomb, move it to B (unless it was from B)
{
if(attachmentA->getPreviousOwner()!=kartB)
{
attachmentA->moveBombFromTo(kartA, kartB);
}
}
}
else if(attachmentB->getType()==ATTACH_BOMB &&
attachmentB->getPreviousOwner()!=kartA)
{
attachmentB->moveBombFromTo(kartB, kartA);
}
if(kartA->isPlayerKart()) sound_manager->playSfx(SOUND_CRASH);
if(kartB->isPlayerKart()) sound_manager->playSfx(SOUND_CRASH);
} // KartKartCollision
//-----------------------------------------------------------------------------
/** This function is called at each internal bullet timestep. It is used
* here to do the collision handling: using the contact manifolds after a
* physics time step might miss some collisions (when more than one internal
* time step was done, and the collision is added and removed).
**/
btScalar Physics::solveGroup(btCollisionObject** bodies, int numBodies,
btPersistentManifold** manifold,int numManifolds,
btTypedConstraint** constraints,int numConstraints,
const btContactSolverInfo& info,
btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,
btDispatcher* dispatcher) {
btScalar returnValue=
btSequentialImpulseConstraintSolver::solveGroup(bodies, numBodies, manifold,
numManifolds, constraints,
numConstraints, info,
debugDrawer, stackAlloc,
dispatcher);
int currentNumManifolds = m_dispatcher->getNumManifolds();
// We can't explode a rocket in a loop, since a rocket might collide with
// more than one object, and/or more than once with each object (if there
// is more than one collision point). So keep a list of rockets that will
// be exploded after the collisions
std::vector<Moveable*> rocketsToExplode;
for(int i=0; i<currentNumManifolds; i++)
{ {
btPersistentManifold* contactManifold = m_dynamics_world->getDispatcher()->getManifoldByIndexInternal(i); btPersistentManifold* contactManifold = m_dynamics_world->getDispatcher()->getManifoldByIndexInternal(i);
btCollisionObject* objA = static_cast<btCollisionObject*>(contactManifold->getBody0()); btCollisionObject* objA = static_cast<btCollisionObject*>(contactManifold->getBody0());
btCollisionObject* objB = static_cast<btCollisionObject*>(contactManifold->getBody1()); btCollisionObject* objB = static_cast<btCollisionObject*>(contactManifold->getBody1());
contactManifold->refreshContactPoints(objA->getWorldTransform(),objB->getWorldTransform());
int numContacts = contactManifold->getNumContacts(); int numContacts = contactManifold->getNumContacts();
if(!numContacts) continue; // no real collision if(!numContacts) continue; // no real collision
@ -200,63 +287,35 @@ void Physics::handleCollisions() {
Moveable *movA = static_cast<Moveable*>(objA->getUserPointer()); Moveable *movA = static_cast<Moveable*>(objA->getUserPointer());
Moveable *movB = static_cast<Moveable*>(objB->getUserPointer()); Moveable *movB = static_cast<Moveable*>(objB->getUserPointer());
if(!numContacts) continue; // no real collision
// 1) object A is a track // 1) object A is a track
// ======================= // =======================
if(!movA) if(!movA)
{ {
if(!movB) if(movB && movB->getMoveableType()==Moveable::MOV_PROJECTILE)
{ // 1.1) track hits track ?? { // 1.1 projectile hits track
// ------------------------
continue; // --> ignore
}
else if(movB->getMoveableType()==Moveable::MOV_PROJECTILE)
{ // 1.2 projectile hits track
// ------------------------- // -------------------------
Projectile *p=(Projectile*)movB; m_all_collisions.push_back(CollisionPair(movB, Moveable::MOV_PROJECTILE,
p->explode(NULL); // explode on track NULL, Moveable::MOV_TRACK ));
}
else
{ // 1.3 kart hits track
// -------------------
continue;
} }
} }
// 2) object a is a kart // 2) object a is a kart
// ===================== // =====================
else if(movA->getMoveableType()==Moveable::MOV_KART) else if(movA->getMoveableType()==Moveable::MOV_KART)
{ {
if(!movB) if(movB && movB->getMoveableType()==Moveable::MOV_PROJECTILE)
{ // 2.1) kart hits track { // 2.1 projectile hits kart
// --------------------
continue; // --> ignore
}
else if(movB->getMoveableType()==Moveable::MOV_PROJECTILE)
{ // 2.2 projectile hits kart
// ------------------------- // -------------------------
Projectile *p=(Projectile*)movB; m_all_collisions.push_back(CollisionPair(movB, Moveable::MOV_PROJECTILE,
p->explode((Kart*)movA); movA, Moveable::MOV_KART ));
} }
else if(movB->getMoveableType()==Moveable::MOV_KART) else if(movB && movB->getMoveableType()==Moveable::MOV_KART)
{ // 2.3 kart hits kart { // 2.2 kart hits kart
// ------------------ // ------------------
Kart *kartA = (Kart*)movA; m_all_collisions.push_back(CollisionPair(movA, Moveable::MOV_KART,
Kart *kartB = (Kart*)movB; movB, Moveable::MOV_KART ));
// First check for bomb attachments
Attachment *attachmentA=kartA->getAttachment();
if(attachmentA->getType()==ATTACH_BOMB &&
attachmentA->getPreviousOwner()!=kartB)
{
attachmentA->moveBombFromTo(kartA, kartB);
}
Attachment *attachmentB=kartB->getAttachment();
if(attachmentB->getType()==ATTACH_BOMB &&
attachmentB->getPreviousOwner()!=kartA)
{
attachmentB->moveBombFromTo(kartB, kartA);
}
if(kartA->isPlayerKart()) sound_manager->playSfx(SOUND_CRASH);
if(kartB->isPlayerKart()) sound_manager->playSfx(SOUND_CRASH);
} }
} }
// 3) object is a projectile // 3) object is a projectile
@ -266,19 +325,20 @@ void Physics::handleCollisions() {
if(!movB) if(!movB)
{ // 3.1) projectile hits track { // 3.1) projectile hits track
// -------------------------- // --------------------------
((Projectile*)movA)->explode(NULL); m_all_collisions.push_back(CollisionPair(movA, Moveable::MOV_PROJECTILE,
NULL, Moveable::MOV_TRACK ));
} }
else if(movB->getMoveableType()==Moveable::MOV_PROJECTILE) else if(movB->getMoveableType()==Moveable::MOV_PROJECTILE)
{ // 3.2 projectile hits projectile { // 3.2 projectile hits projectile
// ------------------------------ // ------------------------------
((Projectile*)movA)->explode(NULL); m_all_collisions.push_back(CollisionPair(movA, Moveable::MOV_PROJECTILE,
((Projectile*)movB)->explode(NULL); movB, Moveable::MOV_PROJECTILE));
} }
else if(movB->getMoveableType()==Moveable::MOV_KART) else if(movB->getMoveableType()==Moveable::MOV_KART)
{ // 3.3 projectile hits kart { // 3.3 projectile hits kart
// ------------------------ // ------------------------
Projectile *p=(Projectile*)movA; m_all_collisions.push_back(CollisionPair(movA, Moveable::MOV_PROJECTILE,
p->explode((Kart*)movB); movB, Moveable::MOV_KART ));
} }
} }
// 4) Nothing else should happen // 4) Nothing else should happen
@ -288,7 +348,9 @@ void Physics::handleCollisions() {
assert("Unknown user pointer"); assert("Unknown user pointer");
} }
} // for i<numManifolds } // for i<numManifolds
} // handleCollisions
return returnValue;
} // solveGroup
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
float Physics::getHAT(btVector3 pos) float Physics::getHAT(btVector3 pos)
@ -300,8 +362,9 @@ float Physics::getHAT(btVector3 pos)
m_dynamics_world->rayTest(pos, to_pos, rayCallback); m_dynamics_world->rayTest(pos, to_pos, rayCallback);
if(!rayCallback.HasHit()) return NOHIT; if(!rayCallback.HasHit()) return NOHIT;
return rayCallback.m_hitPointWorld.getZ() - pos.getZ();
} // getHOT return pos.getZ()-rayCallback.m_hitPointWorld.getZ();
} // getHAT
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
bool Physics::getTerrainNormal(btVector3 pos, btVector3* normal) bool Physics::getTerrainNormal(btVector3 pos, btVector3* normal)
{ {

View File

@ -21,24 +21,71 @@
#define HEADER_PHYSICS_H #define HEADER_PHYSICS_H
#include "kart.hpp" #include "kart.hpp"
#include "flyable.hpp"
#include <plib/sg.h> #include <plib/sg.h>
#include <set>
#ifdef BULLET
#include "btBulletDynamicsCommon.h" #include "btBulletDynamicsCommon.h"
#include "bullet/Demos/OpenGL/GLDebugDrawer.h" #include "bullet/Demos/OpenGL/GLDebugDrawer.h"
class Physics class Physics : public btSequentialImpulseConstraintSolver
{ {
protected: private:
btDynamicsWorld *m_dynamics_world; btDynamicsWorld *m_dynamics_world;
Kart *m_kart; Kart *m_kart;
GLDebugDrawer *m_debug_drawer; GLDebugDrawer *m_debug_drawer;
btCollisionDispatcher *m_dispatcher; btCollisionDispatcher *m_dispatcher;
btBroadphaseInterface *m_axis_sweep; btBroadphaseInterface *m_axis_sweep;
btDefaultCollisionConfiguration *m_collision_conf; btDefaultCollisionConfiguration *m_collision_conf;
btConstraintSolver *m_constraint_solver;
void convertTrack(ssgEntity *track, sgMat4 m, btTriangleMesh* track_mesh); // Bullet can report the same collision more than once (up to 4
// contact points per collision. Additionally, more than one internal
// substep might be taken, resulting in potentially even more
// duplicates. To handle this, all collisions (i.e. pair of objects)
// are stored in a vector, but only one entry per collision pair
// of objects.
// While this is a natural application of std::set, the set has some
// overhead (since it will likely use a tree to sort the entries).
// Considering that the number of collisions is usually rather small
// a simple list and linear search is being used here.
class CollisionPair {
public:
void *a, *b;
Moveable::MoveableType type_a, type_b;
// The entries in Collision Pairs are sorted: if a projectile
// is included, it's always 'a'. If only two karts are reported
// the first kart pointer is the smaller one
CollisionPair(void *a1, Moveable::MoveableType atype,
void *b1, Moveable::MoveableType btype) {
if(atype==Moveable::MOV_KART && btype==Moveable::MOV_KART && a1>b1) {
a=b1;b=a1; type_a=btype; type_b=atype;
} else {
a=a1; b=b1; type_a=atype; type_b=btype;
}
}; // CollisionPair
bool operator==(const CollisionPair p) {
return (p.a==a && p.b==b);
}
};
// This class is the list of collision objects, where each collision
// pair is stored as most once.
class CollisionList : public std::vector<CollisionPair> {
public:
void push_back(CollisionPair p) {
// only add a pair if it's not already in there
for(iterator i=begin(); i!=end(); i++) {
if((*i)==p) return;
}
std::vector<CollisionPair>::push_back(p);
}; // push_back
};
CollisionList m_all_collisions;
void KartKartCollision(Kart *ka, Kart *kb);
public: public:
void convertTrack (ssgEntity *track, sgMat4 m, btTriangleMesh* track_mesh);
Physics (float gravity); Physics (float gravity);
~Physics (); ~Physics ();
void addKart (const Kart *k, btRaycastVehicle *v); void addKart (const Kart *k, btRaycastVehicle *v);
@ -46,30 +93,21 @@ public:
void removeKart (const Kart *k); void removeKart (const Kart *k);
void removeBody (btRigidBody* b) {m_dynamics_world->removeRigidBody(b);} void removeBody (btRigidBody* b) {m_dynamics_world->removeRigidBody(b);}
void update (float dt); void update (float dt);
void handleCollisions();
void draw (); void draw ();
void setTrack (ssgEntity *track); void setTrack (ssgEntity *track);
btDynamicsWorld* btDynamicsWorld*
getPhysicsWorld () const {return m_dynamics_world;} getPhysicsWorld () const {return m_dynamics_world;}
void debugDraw (float m[16], btCollisionShape *s, const btVector3 color); void debugDraw (float m[16], btCollisionShape *s, const btVector3 color);
static float NOHIT; static const float NOHIT;
float getHAT (btVector3 pos); float getHAT (btVector3 pos);
bool getTerrainNormal(btVector3 pos, btVector3* normal); bool getTerrainNormal(btVector3 pos, btVector3* normal);
virtual btScalar solveGroup(btCollisionObject** bodies, int numBodies,
btPersistentManifold** manifold,int numManifolds,
btTypedConstraint** constraints,int numConstraints,
const btContactSolverInfo& info,
btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,
btDispatcher* dispatcher);
}; };
// For non-bullet version: empty object
#else
class Physics
{
public:
Physics(float gravity) {};
~Physics() {};
void update(float dt) {};
void setTrack(ssgEntity *track) {};
void draw () {};
};
#endif
#endif #endif
/* EOF */ /* EOF */

View File

@ -147,7 +147,7 @@ void PlayerKart::update(float dt)
m_collectable.use() ; m_collectable.use() ;
m_controls.fire = false; m_controls.fire = false;
} }
if ( isOnGround() && m_controls.rescue ) if ( m_controls.rescue )
{ {
sound_manager -> playSfx ( SOUND_BEEP ) ; sound_manager -> playSfx ( SOUND_BEEP ) ;
forceRescue(); forceRescue();

View File

@ -19,7 +19,9 @@
#include "loader.hpp" #include "loader.hpp"
#include "projectile_manager.hpp" #include "projectile_manager.hpp"
#include "projectile.hpp" #include "spark.hpp"
#include "missile.hpp"
#include "homing.hpp"
#include "explosion.hpp" #include "explosion.hpp"
#include "collectable_manager.hpp" #include "collectable_manager.hpp"
#include "collectable.hpp" #include "collectable.hpp"
@ -50,7 +52,7 @@ void ProjectileManager::removeTextures()
{ {
cleanup(); cleanup();
ssgDeRefDelete(m_explosion_model); ssgDeRefDelete(m_explosion_model);
// Only the explosion is here, all other models are actualy managed // Only the explosion is here, all other models are actually managed
// by collectable_manager. // by collectable_manager.
callback_manager->clear(CB_EXPLOSION); callback_manager->clear(CB_EXPLOSION);
} // removeTextures } // removeTextures
@ -61,7 +63,7 @@ void ProjectileManager::cleanup()
for(Projectiles::iterator i = m_active_projectiles.begin(); for(Projectiles::iterator i = m_active_projectiles.begin();
i != m_active_projectiles.end(); ++i) i != m_active_projectiles.end(); ++i)
{ {
ssgTransform *m = (*i)->getModel(); ssgTransform *m = (*i)->getModelTransform();
m->removeAllKids(); m->removeAllKids();
delete *i; delete *i;
} }
@ -93,12 +95,10 @@ void ProjectileManager::update(float dt)
{ {
if(! (*p)->hasHit()) { p++; continue; } if(! (*p)->hasHit()) { p++; continue; }
newExplosion((*p)->getCoord()); newExplosion((*p)->getCoord());
// Create a new explosion, move the projectile to the Flyable *f=*p;
// list of deleted projectiles (so that they can be Projectiles::iterator pNext=m_active_projectiles.erase(p); // returns the next element
// reused later), and remove it from the list of active delete f;
// projectiles. p=pNext;
m_deleted_projectiles.push_back(*p);
p=m_active_projectiles.erase(p); // returns the next element
} // while p!=m_active_projectiles.end() } // while p!=m_active_projectiles.end()
} }
@ -115,32 +115,27 @@ void ProjectileManager::update(float dt)
while(e!=m_active_explosions.end()) while(e!=m_active_explosions.end())
{ {
if(!(*e)->hasEnded()) { e++; continue;} if(!(*e)->hasEnded()) { e++; continue;}
m_deleted_explosions.push_back(*e); Explosion *exp=*e;
e=m_active_explosions.erase(e); Explosions::iterator eNext=m_active_explosions.erase(e);
ssgDeRefDelete(exp); // reduce refcount and free object
e=eNext;
} // while e!=m_active_explosions.end() } // while e!=m_active_explosions.end()
} // if m_explosion_ended } // if m_explosion_ended
m_something_was_hit=false; m_something_was_hit=false;
} // update } // update
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
/** See if there is an old, unused projectile object available. If so, Flyable *ProjectileManager::newProjectile(Kart *kart, CollectableType type)
* reuse this object, otherwise create a new one. */
Projectile *ProjectileManager::newProjectile(Kart *kart, int type)
{ {
Projectile *p; Flyable *f;
if(m_deleted_projectiles.size()>0) switch(type) {
{ case COLLECT_SPARK: f = new Spark(kart); break;
p = m_deleted_projectiles.back(); case COLLECT_HOMING: f = new Homing(kart); break;
m_deleted_projectiles.pop_back(); case COLLECT_MISSILE: f = new Missile(kart); break;
p->init(kart, type); default: return NULL;
} }
else m_active_projectiles.push_back(f);
{ return f;
p=new Projectile(kart, type);
}
m_active_projectiles.push_back(p);
return p;
} // newProjectile } // newProjectile
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -148,17 +143,7 @@ Projectile *ProjectileManager::newProjectile(Kart *kart, int type)
* reuse this object, otherwise create a new one. */ * reuse this object, otherwise create a new one. */
Explosion* ProjectileManager::newExplosion(sgCoord* coord) Explosion* ProjectileManager::newExplosion(sgCoord* coord)
{ {
Explosion *e; Explosion *e = new Explosion(coord);
if(m_deleted_explosions.size()>0)
{
e = m_deleted_explosions.back();
m_deleted_explosions.pop_back();
e->init(coord);
}
else
{
e=new Explosion(coord);
}
m_active_explosions.push_back(e); m_active_explosions.push_back(e);
return e; return e;
} // newExplosion } // newExplosion

View File

@ -22,34 +22,26 @@
#include <vector> #include <vector>
#include <plib/ssg.h> #include <plib/ssg.h>
#include "flyable.hpp"
#include "collectable_manager.hpp"
class Kart; class Kart;
class Projectile;
class Explosion; class Explosion;
class ProjectileManager class ProjectileManager
{ {
private: private:
typedef std::vector<Projectile*> Projectiles; typedef std::vector<Flyable*> Projectiles;
typedef std::vector<Explosion* > Explosions; typedef std::vector<Explosion* > Explosions;
// The list of all active projectiles, i.e. projectiles // The list of all active projectiles, i.e. projectiles
// which are currently moving on the track // which are currently moving on the track
Projectiles m_active_projectiles; Projectiles m_active_projectiles;
// The list of all deleted projectiles, i.e. projectils which
// hit something and have therefore been deleted. The objects
// in this list can be reused later, this removes the overhead
// of object creation
Projectiles m_deleted_projectiles;
// All active explosions, i.e. explosions which are currently // All active explosions, i.e. explosions which are currently
// being shown // being shown
Explosions m_active_explosions; Explosions m_active_explosions;
// The list of deleted explosion, which will be reused.
Explosions m_deleted_explosions;
ssgSelector* m_explosion_model; ssgSelector* m_explosion_model;
bool m_something_was_hit; bool m_something_was_hit;
bool m_explosion_ended; bool m_explosion_ended;
@ -67,9 +59,9 @@ public:
void loadData (); void loadData ();
void cleanup (); void cleanup ();
void update (float dt); void update (float dt);
Projectile* newProjectile (Kart *kart, int type); Flyable* newProjectile (Kart *kart, CollectableType type);
Explosion* newExplosion (sgCoord *coord); Explosion* newExplosion (sgCoord *coord);
void Deactivate (Projectile *p) {} void Deactivate (Flyable *p) {}
void removeTextures (); void removeTextures ();
}; };

View File

@ -326,7 +326,7 @@ void DefaultRobot::handle_items( const float DELTA, const int STEPS )
break; break;
case COLLECT_MISSILE: case COLLECT_MISSILE:
case COLLECT_HOMING_MISSILE: case COLLECT_HOMING:
if( m_time_since_last_shot > 5.0f && m_crashes.m_kart != -1 ) if( m_time_since_last_shot > 5.0f && m_crashes.m_kart != -1 )
{ {
if( sgDistanceVec2( m_curr_pos.xyz, if( sgDistanceVec2( m_curr_pos.xyz,

View File

@ -65,6 +65,7 @@ SoundManager::SoundManager()
} }
else else
m_initialized = true; m_initialized = true;
getcwd
#else #else
if(alutInit(0, NULL) == AL_TRUE) // init OpenAL sound system if(alutInit(0, NULL) == AL_TRUE) // init OpenAL sound system
m_initialized = true; m_initialized = true;

View File

@ -197,8 +197,12 @@ void UserConfig::setDefaults()
set(GA_LEAVE_RACE, set(GA_LEAVE_RACE,
Input(IT_KEYBOARD, SDLK_ESCAPE)); Input(IT_KEYBOARD, SDLK_ESCAPE));
set(GA_DEBUG_ADD_SPARK,
Input(IT_KEYBOARD, SDLK_F1));
set(GA_DEBUG_ADD_MISSILE, set(GA_DEBUG_ADD_MISSILE,
Input(IT_KEYBOARD, SDLK_F7)); Input(IT_KEYBOARD, SDLK_F2));
set(GA_DEBUG_ADD_HOMING,
Input(IT_KEYBOARD, SDLK_F3));
set(GA_DEBUG_TOGGLE_FPS, set(GA_DEBUG_TOGGLE_FPS,
Input(IT_KEYBOARD, SDLK_F12)); Input(IT_KEYBOARD, SDLK_F12));
set(GA_DEBUG_TOGGLE_WIREFRAME, set(GA_DEBUG_TOGGLE_WIREFRAME,
@ -206,7 +210,7 @@ void UserConfig::setDefaults()
set(GA_DEBUG_HISTORY, set(GA_DEBUG_HISTORY,
Input(IT_KEYBOARD, SDLK_F10)); Input(IT_KEYBOARD, SDLK_F10));
set(GA_DEBUG_BULLET, set(GA_DEBUG_BULLET,
Input(IT_KEYBOARD, SDLK_F2)); Input(IT_KEYBOARD, SDLK_F4));
// TODO: The following should become a static // TODO: The following should become a static
// array. This allows: // array. This allows:

View File

@ -1,37 +0,0 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004 Steve Baker <sjbaker1@airmail.net>
//
// 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 2
// 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 <plib/sg.h>
void pr_from_normal ( sgVec3 hpr, sgVec3 nrm )
{
const float SY = sin ( -hpr [ 0 ] * SG_DEGREES_TO_RADIANS ) ;
const float CY = cos ( -hpr [ 0 ] * SG_DEGREES_TO_RADIANS ) ;
hpr[2] = SG_RADIANS_TO_DEGREES * atan2 ( nrm[0] * CY - nrm[1] * SY, nrm[2] ) ;
hpr[1] = -SG_RADIANS_TO_DEGREES * atan2 ( nrm[1] * CY + nrm[0] * SY, nrm[2] ) ;
}
//-----------------------------------------------------------------------------
void hpr_from_normal ( sgVec3 hpr, sgVec3 nrm )
{
pr_from_normal ( hpr, nrm ) ;
hpr[0] = -SG_RADIANS_TO_DEGREES * atan2 ( nrm[0], nrm[1] ) ;
}

View File

@ -1,26 +0,0 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004 Steve Baker <sjbaker1@airmail.net>
//
// 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 2
// 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_UTILS_H
#define HEADER_UTILS_H
//FIXME: erase this file or put what should go here?
#endif

View File

@ -27,9 +27,9 @@
#ifdef __APPLE__ #ifdef __APPLE__
# include <OpenGL/gl.h> # include <OpenGL/gl.h>
#else #else
# ifdef WIN32 # ifdef WIN32
# define WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN
# include <windows.h> # include <windows.h>
# endif # endif
# include <GL/gl.h> # include <GL/gl.h>
#endif #endif

View File

@ -102,9 +102,6 @@ World::World(const RaceSetup& raceSetup_) : m_race_setup(raceSetup_)
assert(m_race_setup.m_karts.size() > 0); assert(m_race_setup.m_karts.size() > 0);
// Clear all callbacks, which might still be stored there from a previous race.
callback_manager->clear(CB_TRACK);
// Load the track models - this must be done before the karts so that the // Load the track models - this must be done before the karts so that the
// karts can be positioned properly on (and not in) the tracks. // karts can be positioned properly on (and not in) the tracks.
loadTrack ( ) ; loadTrack ( ) ;
@ -118,7 +115,6 @@ World::World(const RaceSetup& raceSetup_) : m_race_setup(raceSetup_)
{ {
sgCoord init_pos; sgCoord init_pos;
m_track->getStartCoords(pos, &init_pos); m_track->getStartCoords(pos, &init_pos);
Kart* newkart; Kart* newkart;
if(user_config->m_profile) if(user_config->m_profile)
{ {
@ -149,9 +145,9 @@ World::World(const RaceSetup& raceSetup_) : m_race_setup(raceSetup_)
{ {
history->LoadKartData(newkart, pos); history->LoadKartData(newkart, pos);
} }
newkart -> getModel () -> clrTraversalMaskBits(SSGTRAV_ISECT|SSGTRAV_HOT); newkart -> getModelTransform() -> clrTraversalMaskBits(SSGTRAV_ISECT|SSGTRAV_HOT);
scene->add ( newkart -> getModel() ) ; scene->add ( newkart -> getModelTransform() ) ;
m_kart.push_back(newkart); m_kart.push_back(newkart);
pos++; pos++;
} // for i } // for i
@ -201,7 +197,7 @@ World::World(const RaceSetup& raceSetup_) : m_race_setup(raceSetup_)
} }
if( m_p_replay_player ) m_p_replay_player->showReplayAt( 0.0 ); if( m_p_replay_player ) m_p_replay_player->showReplayAt( 0.0 );
#endif #endif
} } // World
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
World::~World() World::~World()
@ -210,6 +206,9 @@ World::~World()
saveReplayHumanReadable( "test" ); saveReplayHumanReadable( "test" );
#endif #endif
// Clear all callbacks
callback_manager->clear(CB_TRACK);
for ( unsigned int i = 0 ; i < m_kart.size() ; i++ ) for ( unsigned int i = 0 ; i < m_kart.size() ; i++ )
delete m_kart[i]; delete m_kart[i];
@ -253,7 +252,7 @@ void World::resetAllKarts()
{ {
#ifdef BULLET #ifdef BULLET
bool all_finished=false; bool all_finished=false;
for(int i=0; i<10; i++) m_physics->update(1./60.); for(int i=0; i<10; i++) m_physics->update(1.f/60.f);
while(!all_finished) while(!all_finished)
{ {
m_physics->update(1.f/60.f); m_physics->update(1.f/60.f);

View File

@ -102,9 +102,9 @@ public:
float getGravity() const { return m_track->getGravity(); } float getGravity() const { return m_track->getGravity(); }
Physics *getPhysics() const { return m_physics; } Physics *getPhysics() const { return m_physics; }
Track *getTrack() const { return m_track; } Track *getTrack() const { return m_track; }
#ifdef BULLET
float getHAT(btVector3 pos) const { return m_physics->getHAT(pos); } float getHAT(btVector3 pos) const { return m_physics->getHAT(pos); }
#endif bool getTerrainNormal(btVector3 pos, btVector3 *nrm)
const { return m_physics->getTerrainNormal(pos,nrm);}
Kart* getFastestKart() const { return m_fastest_kart; } Kart* getFastestKart() const { return m_fastest_kart; }
float getFastestLapTime() const { return m_fastest_lap; } float getFastestLapTime() const { return m_fastest_lap; }
void setFastestLap(Kart *k, float time) {m_fastest_kart=k;m_fastest_lap=time;} void setFastestLap(Kart *k, float time) {m_fastest_kart=k;m_fastest_lap=time;}