diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5ad4d1815..1f5bc7900 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -470,6 +470,7 @@ set( SRCS ${SRCS} src/main.cpp
src/physics/physical_object.hpp
src/physics/physics.cpp
src/physics/physics.hpp
+ src/physics/stk_dynamics_world.hpp
src/physics/triangle_mesh.cpp
src/physics/triangle_mesh.hpp
src/physics/user_pointer.hpp
diff --git a/data/stk_config.xml b/data/stk_config.xml
index 98307d1cd..00b6067e3 100644
--- a/data/stk_config.xml
+++ b/data/stk_config.xml
@@ -49,15 +49,15 @@
-
+
+ time for skidmarks to fade out. -->
+ disabled when the kart is more than this value from the track. -->
@@ -231,9 +231,12 @@
-
+ rest: Length of suspension when at rest.
+ travel-cm: maximum movement of suspension - in cm!!
+ exp-string-response: dampen the suspension spring reaction
+ exponentially -->
+
+ impact of roll.
+ downward-impulse-factor: A speed proportional impulse applied each
+ frame that pushes the vehicle onto the ground.
+ track-connection-accel: An artificial force that pulls a wheel to
+ the ground if its off ground. Reduces the affect if a kart loses
+ contact with the ground (i.e. it then can't steer or accelerate
+ anymore). -->
+ chassis-angular-damping="0"
+ downward-impulse-factor="0"
+ track-connection-accel="0"/>
-
-
-
-
-
-
+ after being hit by an explosion.
+ radius: Kart closer to this value will be affected by
+ an explosion as well. -->
diff --git a/src/Makefile.am b/src/Makefile.am
index d83241a85..350548b74 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -293,6 +293,7 @@ supertuxkart_SOURCES = \
physics/physical_object.hpp \
physics/physics.cpp \
physics/physics.hpp \
+ phsyics/stk_dynamics_world.hpp \
physics/triangle_mesh.cpp \
physics/triangle_mesh.hpp \
physics/user_pointer.hpp \
diff --git a/src/config/stk_config.cpp b/src/config/stk_config.cpp
index 10b285ebc..9ca188c09 100644
--- a/src/config/stk_config.cpp
+++ b/src/config/stk_config.cpp
@@ -38,6 +38,7 @@ STKConfig::~STKConfig()
if(m_title_music)
delete m_title_music;
} // ~STKConfig
+
//-----------------------------------------------------------------------------
/** Loads the stk configuration file. After loading it checks if all necessary
* values are actually defined, otherwise an error message is printed and STK
diff --git a/src/config/user_config.hpp b/src/config/user_config.hpp
index 38525dc29..a631022ed 100644
--- a/src/config/user_config.hpp
+++ b/src/config/user_config.hpp
@@ -389,6 +389,9 @@ namespace UserConfigParams
/** Special debug camera being high over the kart. */
PARAM_PREFIX bool m_camera_debug PARAM_DEFAULT( false );
+ /** True if physics debugging should be enabled. */
+ PARAM_PREFIX bool m_physics_debug PARAM_DEFAULT( false );
+
/** True if slipstream debugging is activated. */
PARAM_PREFIX bool m_slipstream_debug PARAM_DEFAULT( false );
diff --git a/src/ide/vc9/supertuxkart.vcproj b/src/ide/vc9/supertuxkart.vcproj
index 58c57d325..778d7bdb5 100644
--- a/src/ide/vc9/supertuxkart.vcproj
+++ b/src/ide/vc9/supertuxkart.vcproj
@@ -414,6 +414,26 @@
>
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
@@ -1712,6 +1712,10 @@
RelativePath="..\..\physics\physics.hpp"
>
+
+
diff --git a/src/input/input_manager.cpp b/src/input/input_manager.cpp
index 9097aae76..60d170352 100644
--- a/src/input/input_manager.cpp
+++ b/src/input/input_manager.cpp
@@ -235,7 +235,7 @@ void InputManager::handleStaticAction(int key, int value)
break;
case KEY_F10:
- if(world) history->Save();
+ if(world && value) history->Save();
break;
case KEY_F11:
diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp
index 237f63e5d..0c9ed7bd1 100644
--- a/src/karts/kart.cpp
+++ b/src/karts/kart.cpp
@@ -276,10 +276,8 @@ void Kart::createPhysics()
// -------------------------
m_vehicle_raycaster =
new btKartRaycaster(World::getWorld()->getPhysics()->getPhysicsWorld());
- m_tuning = new btKart::btVehicleTuning();
- m_tuning->m_maxSuspensionTravelCm = m_kart_properties->getSuspensionTravelCM();
- m_vehicle = new btKart(*m_tuning, m_body, m_vehicle_raycaster,
- m_kart_properties->getTrackConnectionAccel());
+ m_vehicle = new btKart(m_body, m_vehicle_raycaster, this);
+ //FIXMEJH m_kart_properties->getTrackConnectionAccel());
// never deactivate the vehicle
m_body->setActivationState(DISABLE_DEACTIVATION);
@@ -293,13 +291,16 @@ void Kart::createPhysics()
btVector3 wheel_direction(0.0f, -1.0f, 0.0f);
btVector3 wheel_axle(-1.0f, 0.0f, 0.0f);
+ btKart::btVehicleTuning tuning;
+ tuning.m_maxSuspensionTravelCm = m_kart_properties->getSuspensionTravelCM();
+
for(unsigned int i=0; i<4; i++)
{
bool is_front_wheel = i<2;
btWheelInfo& wheel = m_vehicle->addWheel(
m_kart_model->getWheelPhysicsPosition(i),
wheel_direction, wheel_axle, suspension_rest,
- wheel_radius, *m_tuning, is_front_wheel);
+ wheel_radius, tuning, is_front_wheel);
wheel.m_suspensionStiffness = m_kart_properties->getSuspensionStiffness();
wheel.m_wheelsDampingRelaxation = m_kart_properties->getWheelDampingRelaxation();
wheel.m_wheelsDampingCompression = m_kart_properties->getWheelDampingCompression();
@@ -416,7 +417,6 @@ Kart::~Kart()
World::getWorld()->getPhysics()->removeKart(this);
delete m_vehicle;
- delete m_tuning;
delete m_vehicle_raycaster;
delete m_uprightConstraint;
@@ -537,6 +537,7 @@ void Kart::reset()
m_bounce_back_time = 0.0f;
m_skidding = 1.0f;
m_time_last_crash = 0.0f;
+ m_speed = 0.0f;
m_view_blocked_by_plunger = 0.0f;
if(m_terrain_sound)
@@ -575,9 +576,12 @@ void Kart::reset()
if (m_skidmarks)
{
m_skidmarks->reset();
- m_skidmarks->adjustFog( track_manager->getTrack( race_manager->getTrackName() )->isFogEnabled() );
+ const Track *track =
+ track_manager->getTrack( race_manager->getTrackName() );
+ m_skidmarks->adjustFog(track->isFogEnabled() );
}
+ m_vehicle->reset();
for(int j=0; jgetNumWheels(); j++)
{
m_vehicle->updateWheelTransform(j, true);
@@ -751,12 +755,12 @@ float Kart::getActualWheelForce()
*/
bool Kart::isOnGround() const
{
- return (m_vehicle->getNumWheelsOnGround() == m_vehicle->getNumWheels()
+ return ((int)m_vehicle->getNumWheelsOnGround() == m_vehicle->getNumWheels()
&& !playingEmergencyAnimation());
} // isOnGround
//-----------------------------------------------------------------------------
-/** The kart is near the ground, but not necesarily on it (small jumps). This
+/** The kart is near the ground, but not necessarily on it (small jumps). This
* is used to determine when to switch off the upright constraint, so that
* explosions can be more violent, while still
*/
@@ -1678,18 +1682,6 @@ void Kart::updatePhysics(float dt)
}
} // !m_brake
} // not accelerating
-#ifdef ENABLE_JUMP
- if(m_controls.jump && isOnGround())
- {
- //Vector3 impulse(0.0f, 0.0f, 10.0f);
- // getVehicle()->getRigidBody()->applyCentralImpulse(impulse);
- btVector3 velocity = m_body->getLinearVelocity();
- velocity.setZ( m_kart_properties->getJumpVelocity() );
-
- getBody()->setLinearVelocity( velocity );
-
- }
-#endif
if (isOnGround())
{
if((fabs(m_controls.m_steer) > 0.001f) && m_controls.m_drift)
@@ -1725,7 +1717,7 @@ void Kart::updatePhysics(float dt)
// you have full traction; above 0.5 rad angles you have absolutely none;
// inbetween there is a linear change in friction
float friction = 1.0f;
- bool enable_skidding = false;
+ bool enable_sliding = false;
// This way the current skidding
// handling can be disabled for certain material (e.g. the
@@ -1745,7 +1737,7 @@ void Kart::updatePhysics(float dt)
if (distanceFromUp < 0.85f)
{
friction = 0.0f;
- enable_skidding = true;
+ enable_sliding = true;
}
else if (distanceFromUp > 0.9f)
{
@@ -1754,7 +1746,7 @@ void Kart::updatePhysics(float dt)
else
{
friction = (distanceFromUp - 0.85f) / 0.5f;
- enable_skidding = true;
+ enable_sliding = true;
}
}
@@ -1764,7 +1756,7 @@ void Kart::updatePhysics(float dt)
wheel.m_frictionSlip = friction*m_kart_properties->getFrictionSlip();
}
- m_vehicle->enableSliding(enable_skidding);
+ m_vehicle->setSliding(enable_sliding);
float steering = getMaxSteerAngle() * m_controls.m_steer*m_skidding;
diff --git a/src/karts/kart.hpp b/src/karts/kart.hpp
index 273d92b2c..31cb0e39b 100644
--- a/src/karts/kart.hpp
+++ b/src/karts/kart.hpp
@@ -27,7 +27,7 @@
* of karts.
*/
-#include "btBulletDynamicsCommon.h"
+#include "LinearMath/btTransform.h"
#include "items/attachment.hpp"
#include "items/powerup.hpp"
@@ -36,24 +36,23 @@
#include "karts/emergency_animation.hpp"
#include "karts/max_speed.hpp"
#include "karts/moveable.hpp"
-#include "karts/kart_model.hpp"
#include "karts/kart_properties.hpp"
#include "tracks/terrain_info.hpp"
#include "utils/no_copy.hpp"
class btKart;
class btUprightConstraint;
-class btVehicleTuning;
+
class Camera;
class Item;
-class Quad;
-class Shadow;
-class SFXBase;
-class SkidMarks;
-class SlipStream;
+class KartModel;
class ParticleEmitter;
class ParticleKind;
class Rain;
+class SFXBase;
+class Shadow;
+class SkidMarks;
+class SlipStream;
/** The main kart class. All type of karts are of this object, but with
* different controllers. The controllers are what turn a kart into a
@@ -133,8 +132,6 @@ private:
// Bullet physics parameters
// -------------------------
- btRaycastVehicle::btVehicleTuning
- *m_tuning;
btCompoundShape m_kart_chassis;
btVehicleRaycaster *m_vehicle_raycaster;
btKart *m_vehicle;
@@ -416,7 +413,7 @@ public:
const std::string& getIdent() const {return m_kart_properties->getIdent();}
// ------------------------------------------------------------------------
/** Returns the start transform, i.e. position and rotation. */
- const btTransform getResetTransform() const {return m_reset_transform;}
+ const btTransform& getResetTransform() const {return m_reset_transform;}
// ------------------------------------------------------------------------
/** Returns the controller of this kart. */
Controller* getController() { return m_controller; }
diff --git a/src/karts/kart_model.cpp b/src/karts/kart_model.cpp
index 21d0b67e6..430138df7 100644
--- a/src/karts/kart_model.cpp
+++ b/src/karts/kart_model.cpp
@@ -29,6 +29,7 @@
#include "graphics/mesh_tools.hpp"
#include "io/xml_node.hpp"
#include "karts/kart.hpp"
+#include "physics/btKart.hpp"
#include "utils/constants.hpp"
#define SKELETON_DEBUG 0
@@ -510,7 +511,9 @@ void KartModel::update(float rotation, float steer, const float suspension[4])
m_max_suspension[i]);
float ratio = clamped_suspension[i] / suspension_length;
const int sign = ratio < 0 ? -1 : 1;
- ratio = sign * fabsf(ratio*(2-ratio)); // expanded form of 1 - (1 - x)^2, i.e. making suspension display quadratic and not linear
+ // expanded form of 1 - (1 - x)^2, i.e. making suspension display
+ // quadratic and not linear
+ ratio = sign * fabsf(ratio*(2-ratio));
clamped_suspension[i] = ratio*suspension_length;
} // for i<4
@@ -521,6 +524,16 @@ void KartModel::update(float rotation, float steer, const float suspension[4])
for(unsigned int i=0; i<4; i++)
{
if(!m_wheel_node[i]) continue;
+#ifdef DEBUG
+ if(UserConfigParams::m_physics_debug)
+ {
+ // Make wheels that are not touching the ground invisible
+ bool wheel_has_contact =
+ m_kart->getVehicle()->getWheelInfo(i).m_raycastInfo
+ .m_isInContact;
+ m_wheel_node[i]->setVisible(wheel_has_contact);
+ }
+#endif
core::vector3df pos = m_wheel_graphics_position[i].toIrrVector();
pos.Y += clamped_suspension[i];
m_wheel_node[i]->setPosition(pos);
diff --git a/src/karts/kart_properties.cpp b/src/karts/kart_properties.cpp
index 43458e240..6f719e70a 100644
--- a/src/karts/kart_properties.cpp
+++ b/src/karts/kart_properties.cpp
@@ -72,7 +72,7 @@ KartProperties::KartProperties(const std::string &filename)
m_wheel_damping_compression = m_friction_slip = m_roll_influence =
m_wheel_radius = m_chassis_linear_damping =
m_chassis_angular_damping = m_suspension_rest =
- m_max_speed_reverse_ratio = m_jump_velocity =
+ m_max_speed_reverse_ratio =
m_rescue_vert_offset = m_upright_tolerance = m_collision_side_impulse =
m_upright_max_force = m_suspension_travel_cm =
m_track_connection_accel =
@@ -93,9 +93,10 @@ KartProperties::KartProperties(const std::string &filename)
m_rescue_time = m_rescue_height = m_explosion_time =
m_explosion_radius = m_ai_steering_variation =
m_swatter_distance2 = m_swatter_duration = m_squash_slowdown =
- m_squash_duration = UNDEFINED;
+ m_squash_duration = m_downward_impulse_factor = UNDEFINED;
m_gravity_center_shift = Vec3(UNDEFINED);
+ m_exp_spring_response = false;
m_has_skidmarks = true;
m_version = 0;
m_color = video::SColor(255, 0, 0, 0);
@@ -384,9 +385,10 @@ void KartProperties::getAllData(const XMLNode * root)
if(const XMLNode *suspension_node = root->getNode("suspension"))
{
- suspension_node->get("stiffness", &m_suspension_stiffness);
- suspension_node->get("rest", &m_suspension_rest );
- suspension_node->get("travel-cm", &m_suspension_travel_cm);
+ suspension_node->get("stiffness", &m_suspension_stiffness);
+ suspension_node->get("rest", &m_suspension_rest );
+ suspension_node->get("travel-cm", &m_suspension_travel_cm);
+ suspension_node->get("exp-spring-response", &m_exp_spring_response );
}
if(const XMLNode *wheels_node = root->getNode("wheels"))
@@ -401,9 +403,16 @@ void KartProperties::getAllData(const XMLNode * root)
if(const XMLNode *stability_node = root->getNode("stability"))
{
- stability_node->get("roll-influence", &m_roll_influence);
- stability_node->get("chassis-linear-damping", &m_chassis_linear_damping);
- stability_node->get("chassis-angular-damping", &m_chassis_angular_damping);
+ stability_node->get("roll-influence",
+ &m_roll_influence );
+ stability_node->get("chassis-linear-damping",
+ &m_chassis_linear_damping );
+ stability_node->get("chassis-angular-damping",
+ &m_chassis_angular_damping);
+ stability_node->get("downward-impulse-factor",
+ &m_downward_impulse_factor);
+ stability_node->get("track-connection-accel",
+ &m_track_connection_accel );
}
if(const XMLNode *upright_node = root->getNode("upright"))
@@ -412,12 +421,6 @@ void KartProperties::getAllData(const XMLNode * root)
upright_node->get("max-force", &m_upright_max_force);
}
- if(const XMLNode *track_connection_node = root->getNode("track-connection-accel"))
- track_connection_node->get("value", &m_track_connection_accel);
-
- if(const XMLNode *jump_node = root->getNode("jump"))
- jump_node->get("velocity", &m_jump_velocity);
-
if(const XMLNode *collision_node = root->getNode("collision"))
collision_node->get("side-impulse", &m_collision_side_impulse);
@@ -567,8 +570,10 @@ void KartProperties::checkAllSet(const std::string &filename)
CHECK_NEG(m_wheel_radius, "wheels radius" );
CHECK_NEG(m_friction_slip, "friction slip" );
CHECK_NEG(m_roll_influence, "stability roll-influence" );
- CHECK_NEG(m_chassis_linear_damping, "stability chassis-linear-damping");
- CHECK_NEG(m_chassis_angular_damping, "stability chassis-angular-damping");
+ CHECK_NEG(m_chassis_linear_damping, "stability chassis-linear-damping" );
+ CHECK_NEG(m_chassis_angular_damping, "stability chassis-angular-damping");
+ CHECK_NEG(m_downward_impulse_factor, "stability downward-impulse-factor");
+ CHECK_NEG(m_track_connection_accel, "stability track-connection-accel" );
CHECK_NEG(m_engine_power[0], "engine power[0]" );
CHECK_NEG(m_engine_power[1], "engine power[1]" );
CHECK_NEG(m_engine_power[2], "engine power[2]" );
@@ -581,10 +586,8 @@ void KartProperties::checkAllSet(const std::string &filename)
CHECK_NEG(m_suspension_rest, "suspension rest" );
CHECK_NEG(m_suspension_travel_cm, "suspension travel-cm" );
CHECK_NEG(m_collision_side_impulse, "collision side-impulse" );
- CHECK_NEG(m_jump_velocity, "jump velocity" );
CHECK_NEG(m_upright_tolerance, "upright tolerance" );
CHECK_NEG(m_upright_max_force, "upright max-force" );
- CHECK_NEG(m_track_connection_accel, "track-connection-accel" );
CHECK_NEG(m_plunger_in_face_duration[0],"plunger in-face-time[0]" );
CHECK_NEG(m_plunger_in_face_duration[1],"plunger in-face-time[1]" );
CHECK_NEG(m_plunger_in_face_duration[2],"plunger in-face-time[2]" );
diff --git a/src/karts/kart_properties.hpp b/src/karts/kart_properties.hpp
index 383656d9f..79e66d22b 100644
--- a/src/karts/kart_properties.hpp
+++ b/src/karts/kart_properties.hpp
@@ -85,7 +85,7 @@ private:
// Display and gui
// ---------------
- std::string m_name; /**< The human readable Name of the kart
+ std::string m_name; /**< The human readable Name of the kart
* driver. */
std::string m_ident; /**< The computer readable-name of the
* kart driver. */
@@ -217,21 +217,41 @@ private:
float m_friction_slip;
float m_roll_influence;
float m_wheel_radius;
+
+ /** An impulse pushing the kart down which is proportional to speed. So
+ * the actual impulse is speed * m_downward_impulse_factor. Set it to
+ * 0 to disable completely. Based on
+ * http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=6059\
+ * &p=21240&hilit=vehicle#p21240 */
+ float m_downward_impulse_factor;
+
+ /** Artifical acceleration that pulls a kart down onto the track if one
+ * axis loses contact with the track. */
+ float m_track_connection_accel;
+
+ /** Linear damping of the chassis to prevent it from toppling over. */
float m_chassis_linear_damping;
+
+ /** Angular damping to prevent it from turning too easily. */
float m_chassis_angular_damping;
+
float m_max_speed[3];
float m_max_speed_reverse_ratio;
- Vec3 m_gravity_center_shift; /**< Shift of center of gravity. */
- float m_track_connection_accel; /**< Artifical acceleration that pulls a
- * kart down onto the track if one axis
- * loses contact with the track. */
+
+ /** Shift of center of gravity. */
+ Vec3 m_gravity_center_shift;
+
+ /** The suspension reaction is dampened to reach an exponential behaviour.
+ * See http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=7369\
+ * &p=25236&hilit=vehicle#p25236 for details. */
+ bool m_exp_spring_response;
+
float m_suspension_rest;
float m_suspension_travel_cm;
/** An additional artifical side-impulse that pushes the slower kart
* out of the way of the faster kart in case of a collision. */
float m_collision_side_impulse;
- /** Vertical velocity set when jumping. */
- float m_jump_velocity;
+
float m_upright_tolerance;
float m_upright_max_force;
@@ -418,6 +438,12 @@ public:
float getChassisAngularDamping () const
{return m_chassis_angular_damping; }
+ /** Artifical downward impulse every frame. */
+ float getDownwardImpulseFactor() const { return m_downward_impulse_factor;}
+
+ /** Returns artificial acceleration to keep wheels on track. */
+ float getTrackConnectionAccel () const {return m_track_connection_accel;}
+
/** Returns the maximum speed dependent on the difficult level. */
float getMaxSpeed () const {return
m_max_speed[race_manager->getDifficulty()];}
@@ -456,8 +482,8 @@ public:
/** Returns the amount the suspension can extend. */
float getSuspensionTravelCM () const {return m_suspension_travel_cm; }
- /** Returns jump velocity (unused atm). */
- float getJumpVelocity () const {return m_jump_velocity; }
+ /** Returns if the spring should be exponentially dampened. */
+ bool getExpSpringResponse() const {return m_exp_spring_response; }
/** Returns the (artificial) collision side impulse this kart will apply
* to a slower kart in case of a collision. */
@@ -491,9 +517,6 @@ public:
/** Returns the maximum value of the upright counteracting force. */
float getUprightMaxForce () const {return m_upright_max_force; }
- /** Returns artificial acceleration to keep wheels on track. */
- float getTrackConnectionAccel () const {return m_track_connection_accel;}
-
/** Returns the maximum length of a rubber band before it breaks. */
float getRubberBandMaxLength () const {return m_rubber_band_max_length;}
diff --git a/src/main.cpp b/src/main.cpp
index b16f5fd0b..8391af0cb 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -457,6 +457,15 @@ int handleCmdLinePreliminary(int argc, char **argv)
{
UserConfigParams::m_verbosity |= UserConfigParams::LOG_MISC;
}
+ else if( !strcmp(argv[i], "--log=terminal"))
+ {
+ UserConfigParams::m_log_errors=false;
+ }
+ else if( !strcmp(argv[i], "--log=file"))
+ {
+ UserConfigParams::m_log_errors=true;
+ }
+
else if ( !strcmp(argv[i], "--debug=all") )
{
UserConfigParams::m_verbosity |= UserConfigParams::LOG_ALL;
@@ -607,6 +616,11 @@ int handleCmdLine(int argc, char **argv)
{
UserConfigParams::m_camera_debug=1;
}
+ else if(UserConfigParams::m_artist_debug_mode &&
+ !strcmp(argv[i], "--physics-debug"))
+ {
+ UserConfigParams::m_physics_debug=1;
+ }
else if(!strcmp(argv[i], "--kartsize-debug"))
{
for(unsigned int i=0;
@@ -859,14 +873,7 @@ int handleCmdLine(int argc, char **argv)
race_manager->setNumLaps(atoi(argv[i+1]));
i++;
}
- else if( !strcmp(argv[i], "--log=terminal"))
- {
- UserConfigParams::m_log_errors=false;
- }
- else if( !strcmp(argv[i], "--log=file"))
- {
- UserConfigParams::m_log_errors=true;
- } else if( sscanf(argv[i], "--profile-laps=%d", &n)==1)
+ else if( sscanf(argv[i], "--profile-laps=%d", &n)==1)
{
printf("Profiling %d laps\n",n);
UserConfigParams::m_no_start_screen = true;
@@ -923,6 +930,8 @@ int handleCmdLine(int argc, char **argv)
else if( !strcmp(argv[i], "--debug=flyable") ) {}
else if( !strcmp(argv[i], "--debug=misc" ) ) {}
else if( !strcmp(argv[i], "--debug=all" ) ) {}
+ else if( !strcmp(argv[i], "--log=terminal" ) ) {}
+ else if( !strcmp(argv[i], "--log=file" ) ) {}
else if( !strcmp(argv[i], "--screensize") ||
!strcmp(argv[i], "-s") ) {i++;}
else if( !strcmp(argv[i], "--fullscreen") || !strcmp(argv[i], "-f")) {}
diff --git a/src/modes/world.cpp b/src/modes/world.cpp
index 6a7f29af1..0e6f88f4f 100644
--- a/src/modes/world.cpp
+++ b/src/modes/world.cpp
@@ -368,6 +368,10 @@ void World::terminateRace()
*/
void World::resetAllKarts()
{
+ // Reset the physics 'remaining' time to 0 so that the number
+ // of timesteps is reproducible if doing a physics-based history run
+ getPhysics()->getPhysicsWorld()->resetLocalTime();
+
// If track checking is requested, check all rescue positions if
// they are heigh enough.
if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES &&
@@ -902,6 +906,9 @@ void World::restartRace()
projectile_manager->cleanup();
race_manager->reset();
+ // Make sure to overwrite the data from the previous race.
+ if(!history->replayHistory()) history->initRecording();
+
} // restartRace
//-----------------------------------------------------------------------------
diff --git a/src/physics/btKart.cpp b/src/physics/btKart.cpp
index 493a8fa3c..03974c356 100644
--- a/src/physics/btKart.cpp
+++ b/src/physics/btKart.cpp
@@ -4,137 +4,864 @@
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
- * Erwin Coumans makes no representations about the suitability
- * of this software for any purpose.
+ * Erwin Coumans makes no representations about the suitability
+ * of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
-/* Based on btRayCastVehicle, but modified for STK.
- * projectVehicleToSurface function and shorter raycast functions added.
- */
-
-#include "physics/btKart.hpp"
-
-#include "LinearMath/btMinMax.h"
#include "LinearMath/btVector3.h"
-#include "LinearMath/btQuaternion.h"
+#include "btKart.hpp"
+
#include "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h"
#include "BulletDynamics/ConstraintSolver/btJacobianEntry.h"
+#include "LinearMath/btQuaternion.h"
#include "BulletDynamics/Dynamics/btDynamicsWorld.h"
#include "BulletDynamics/Vehicle/btVehicleRaycaster.h"
#include "BulletDynamics/Vehicle/btWheelInfo.h"
+#include "LinearMath/btMinMax.h"
+#include "LinearMath/btIDebugDraw.h"
#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
-struct btWheelContactPoint;
-btScalar calcRollingFriction(btWheelContactPoint& contactPoint);
+#include "karts/kart.hpp"
+
+#define ROLLING_INFLUENCE_FIX
-btKart::btKart(const btVehicleTuning& tuning,btRigidBody* chassis,
- btVehicleRaycaster* raycaster, float track_connect_accel )
-: btRaycastVehicle(tuning, chassis, raycaster)
+btRigidBody& btActionInterface::getFixedBody()
{
- m_track_connect_accel = track_connect_accel;
-
- m_num_wheels_on_ground = 0;
-
- m_zipper_active = false;
- m_zipper_velocity = btScalar(0);
- m_allow_sliding = false;
+ static btRigidBody s_fixed(0, 0,0);
+ s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),
+ btScalar(0.),btScalar(0.)));
+ return s_fixed;
}
+// ============================================================================
+btKart::btKart(btRigidBody* chassis, btVehicleRaycaster* raycaster,
+ Kart *kart)
+ : m_vehicleRaycaster(raycaster)
+{
+ m_chassisBody = chassis;
+ m_indexRightAxis = 0;
+ m_indexUpAxis = 2;
+ m_indexForwardAxis = 1;
+ m_kart = kart;
+ reset();
+} // btKart
+
// ----------------------------------------------------------------------------
btKart::~btKart()
{
-}
+} // ~btKart
+
+// ----------------------------------------------------------------------------
+
+//
+// basically most of the code is general for 2 or 4 wheel vehicles, but some
+// of it needs to be reviewed
+//
+btWheelInfo& btKart::addWheel(const btVector3& connectionPointCS,
+ const btVector3& wheelDirectionCS0,
+ const btVector3& wheelAxleCS,
+ btScalar suspensionRestLength,
+ btScalar wheelRadius,
+ const btVehicleTuning& tuning,
+ bool isFrontWheel)
+{
+
+ btWheelInfoConstructionInfo ci;
+
+ ci.m_chassisConnectionCS = connectionPointCS;
+ ci.m_wheelDirectionCS = wheelDirectionCS0;
+ ci.m_wheelAxleCS = wheelAxleCS;
+ ci.m_suspensionRestLength = suspensionRestLength;
+ ci.m_wheelRadius = wheelRadius;
+ ci.m_bIsFrontWheel = isFrontWheel;
+ ci.m_suspensionStiffness = tuning.m_suspensionStiffness;
+ ci.m_wheelsDampingCompression = tuning.m_suspensionCompression;
+ ci.m_wheelsDampingRelaxation = tuning.m_suspensionDamping;
+ ci.m_frictionSlip = tuning.m_frictionSlip;
+ ci.m_maxSuspensionTravelCm = tuning.m_maxSuspensionTravelCm;
+ ci.m_maxSuspensionForce = tuning.m_maxSuspensionForce;
+
+ m_wheelInfo.push_back( btWheelInfo(ci));
+
+ btWheelInfo& wheel = m_wheelInfo[getNumWheels()-1];
+
+ updateWheelTransformsWS( wheel , false );
+ updateWheelTransform(getNumWheels()-1,false);
+ return wheel;
+} // addWheel
+
+// ----------------------------------------------------------------------------
+/** Resets the kart before a (re)start, to make sure all physics variable
+ * are properly defined. This is especially important for physics replay.
+ */
+void btKart::reset()
+{
+ for(int i=0; igetMotionState()))
+ {
+ getRigidBody()->getMotionState()->getWorldTransform(chassisTrans);
+ }
+
+ wheel.m_raycastInfo.m_hardPointWS =
+ chassisTrans( wheel.m_chassisConnectionPointCS );
+ wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.getBasis() *
+ wheel.m_wheelDirectionCS ;
+ wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.getBasis() *
+ wheel.m_wheelAxleCS;
+} // updateWheelTransformsWS
// ----------------------------------------------------------------------------
btScalar btKart::rayCast(btWheelInfo& wheel)
{
- updateWheelTransformsWS( wheel,false);
+ updateWheelTransformsWS( wheel,false);
+
+ btScalar depth = -1;
+
+ btScalar raylen = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius
+ + wheel.m_maxSuspensionTravelCm*0.01f;
- btScalar depth = -1;
+ btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen);
+ const btVector3& source = wheel.m_raycastInfo.m_hardPointWS;
+ wheel.m_raycastInfo.m_contactPointWS = source + rayvector;
+ const btVector3& target = wheel.m_raycastInfo.m_contactPointWS;
- btScalar raylen = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius+
- wheel.m_maxSuspensionTravelCm*0.01f;
+ btScalar param = btScalar(0.);
+
+ btVehicleRaycaster::btVehicleRaycasterResult rayResults;
- btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen);
- const btVector3& source = wheel.m_raycastInfo.m_hardPointWS;
- wheel.m_raycastInfo.m_contactPointWS = source + rayvector;
- const btVector3& target = wheel.m_raycastInfo.m_contactPointWS;
+ btAssert(m_vehicleRaycaster);
- btScalar param = btScalar(0.);
+ void* object = m_vehicleRaycaster->castRay(source,target,rayResults);
- btVehicleRaycaster::btVehicleRaycasterResult rayResults;
+ wheel.m_raycastInfo.m_groundObject = 0;
- assert(m_vehicleRaycaster);
+ if (object)
+ {
+ param = rayResults.m_distFraction;
+ depth = raylen * rayResults.m_distFraction;
+ wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld;
+ wheel.m_raycastInfo.m_isInContact = true;
+ ///@todo for driving on dynamic/movable objects!;
+ wheel.m_raycastInfo.m_groundObject = &getFixedBody();
- void* object = m_vehicleRaycaster->castRay(source,target,rayResults);
+ btScalar hitDistance = param*raylen;
+ wheel.m_raycastInfo.m_suspensionLength =
+ hitDistance - wheel.m_wheelsRadius;
+ //clamp on max suspension travel
- wheel.m_raycastInfo.m_groundObject = 0;
+ btScalar minSuspensionLength = wheel.getSuspensionRestLength()
+ - wheel.m_maxSuspensionTravelCm*btScalar(0.01);
+ btScalar maxSuspensionLength = wheel.getSuspensionRestLength()
+ + wheel.m_maxSuspensionTravelCm*btScalar(0.01);
+ if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength)
+ {
+ wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength;
+ }
+ if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength)
+ {
+ wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength;
+ }
- if (object)
+ wheel.m_raycastInfo.m_contactPointWS = rayResults.m_hitPointInWorld;
+
+ btScalar denominator = wheel.m_raycastInfo.m_contactNormalWS.dot(
+ wheel.m_raycastInfo.m_wheelDirectionWS );
+
+ btVector3 chassis_velocity_at_contactPoint;
+ btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS
+ - getRigidBody()->getCenterOfMassPosition();
+
+ chassis_velocity_at_contactPoint =
+ getRigidBody()->getVelocityInLocalPoint(relpos);
+
+ btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot(
+ chassis_velocity_at_contactPoint );
+
+ if ( denominator >= btScalar(-0.1))
+ {
+ wheel.m_suspensionRelativeVelocity = btScalar(0.0);
+ wheel.m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1);
+ }
+ else
+ {
+ btScalar inv = btScalar(-1.) / denominator;
+ wheel.m_suspensionRelativeVelocity = projVel * inv;
+ wheel.m_clippedInvContactDotSuspension = inv;
+ }
+
+ } else
+ {
+ //put wheel info as in rest position
+ wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
+ wheel.m_suspensionRelativeVelocity = btScalar(0.0);
+ wheel.m_raycastInfo.m_contactNormalWS =
+ - wheel.m_raycastInfo.m_wheelDirectionWS;
+ wheel.m_clippedInvContactDotSuspension = btScalar(1.0);
+ }
+
+ return depth;
+} // rayCast
+
+// ----------------------------------------------------------------------------
+const btTransform& btKart::getChassisWorldTransform() const
+{
+ return getRigidBody()->getCenterOfMassTransform();
+} // getChassisWorldTransform
+
+// ----------------------------------------------------------------------------
+void btKart::updateVehicle( btScalar step )
+{
+ for (int i=0;i maxSuspensionLength)
- {
- wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength;
- }
-
- wheel.m_raycastInfo.m_contactPointWS = rayResults.m_hitPointInWorld;
-
- btScalar denominator= wheel.m_raycastInfo.m_contactNormalWS.dot( wheel.m_raycastInfo.m_wheelDirectionWS );
-
- btVector3 chassis_velocity_at_contactPoint;
- btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS-getRigidBody()->getCenterOfMassPosition();
-
- chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos);
-
- btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint );
-
- if ( denominator >= btScalar(-0.1))
- {
- wheel.m_suspensionRelativeVelocity = btScalar(0.0);
- wheel.m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1);
- }
- else
- {
- btScalar inv = btScalar(-1.) / denominator;
- wheel.m_suspensionRelativeVelocity = projVel * inv;
- wheel.m_clippedInvContactDotSuspension = inv;
- }
-
- } else
- {
- //put wheel info as in rest position
- wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
- wheel.m_suspensionRelativeVelocity = btScalar(0.0);
- wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS;
- wheel.m_clippedInvContactDotSuspension = btScalar(1.0);
-
+ updateWheelTransform(i,false);
}
- return depth;
+ m_currentVehicleSpeedKmHour =
+ btScalar(3.6) * getRigidBody()->getLinearVelocity().length();
+
+ const btTransform& chassisTrans = getChassisWorldTransform();
+
+ btVector3 forwardW(chassisTrans.getBasis()[0][m_indexForwardAxis],
+ chassisTrans.getBasis()[1][m_indexForwardAxis],
+ chassisTrans.getBasis()[2][m_indexForwardAxis]);
+
+ if (forwardW.dot(getRigidBody()->getLinearVelocity()) < btScalar(0.))
+ {
+ m_currentVehicleSpeedKmHour *= btScalar(-1.);
+ }
+
+ // Simulate suspension
+ // -------------------
+
+ int i=0;
+ m_num_wheels_on_ground = 0;
+ for (i=0;i wheel.m_maxSuspensionForce)
+ {
+ suspensionForce = wheel.m_maxSuspensionForce;
+ }
+ btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS
+ * suspensionForce * step;
+ btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS
+ - getRigidBody()->getCenterOfMassPosition();
+
+ getRigidBody()->applyImpulse(impulse, relpos);
+
+ }
+
+ updateFriction( step);
+
+
+ for (i=0;igetCenterOfMassPosition();
+ btVector3 vel = getRigidBody()->getVelocityInLocalPoint(relpos);
+
+ if (wheel.m_raycastInfo.m_isInContact)
+ {
+ const btTransform& chassisWorldTransform =
+ getChassisWorldTransform();
+
+ btVector3 fwd (
+ chassisWorldTransform.getBasis()[0][m_indexForwardAxis],
+ chassisWorldTransform.getBasis()[1][m_indexForwardAxis],
+ chassisWorldTransform.getBasis()[2][m_indexForwardAxis]);
+
+ btScalar proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS);
+ fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj;
+
+ btScalar proj2 = fwd.dot(vel);
+
+ wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius);
+ wheel.m_rotation += wheel.m_deltaRotation;
+
+ } else
+ {
+ wheel.m_rotation += wheel.m_deltaRotation;
+ }
+ //damping of rotation when not in contact
+ wheel.m_deltaRotation *= btScalar(0.99);
+
+ }
+ float f = -m_kart->getSpeed()
+ * m_kart->getKartProperties()->getDownwardImpulseFactor();
+ btVector3 downwards_impulse = m_chassisBody->getWorldTransform().getBasis()
+ * btVector3(0, f, 0);
+
+ m_chassisBody->applyCentralImpulse(downwards_impulse);
+} // updateVehicle
+
+// ----------------------------------------------------------------------------
+void btKart::setSteeringValue(btScalar steering, int wheel)
+{
+ btAssert(wheel>=0 && wheel < getNumWheels());
+
+ btWheelInfo& wheelInfo = getWheelInfo(wheel);
+ wheelInfo.m_steering = steering;
+} // setSteeringValue
+
+// ----------------------------------------------------------------------------
+btScalar btKart::getSteeringValue(int wheel) const
+{
+ return getWheelInfo(wheel).m_steering;
}
+// ----------------------------------------------------------------------------
+void btKart::applyEngineForce(btScalar force, int wheel)
+{
+ btAssert(wheel>=0 && wheel < getNumWheels());
+ btWheelInfo& wheelInfo = getWheelInfo(wheel);
+ wheelInfo.m_engineForce = force;
+}
+
+
+// ----------------------------------------------------------------------------
+const btWheelInfo& btKart::getWheelInfo(int index) const
+{
+ btAssert((index >= 0) && (index < getNumWheels()));
+
+ return m_wheelInfo[index];
+}
+
+// ----------------------------------------------------------------------------
+btWheelInfo& btKart::getWheelInfo(int index)
+{
+ btAssert((index >= 0) && (index < getNumWheels()));
+
+ return m_wheelInfo[index];
+}
+
+// ----------------------------------------------------------------------------
+void btKart::setBrake(btScalar brake,int wheelIndex)
+{
+ btAssert((wheelIndex >= 0) && (wheelIndex < getNumWheels()));
+ getWheelInfo(wheelIndex).m_brake = brake;
+}
+
+
+// ----------------------------------------------------------------------------
+void btKart::updateSuspension(btScalar deltaTime)
+{
+ (void)deltaTime;
+
+ btScalar chassisMass = btScalar(1.) / m_chassisBody->getInvMass();
+
+ for (int w_it=0; w_itgetKartProperties()->getTrackConnectionAccel()
+ * chassisMass;
+ continue;
+ }
+
+ btScalar force;
+
+ // Spring
+ btScalar susp_length = wheel_info.getSuspensionRestLength();
+ btScalar current_length = wheel_info.m_raycastInfo.m_suspensionLength;
+ btScalar length_diff = (susp_length - current_length);
+ if(m_kart->getKartProperties()->getExpSpringResponse())
+ length_diff *= length_diff/susp_length;
+
+ force = wheel_info.m_suspensionStiffness * length_diff
+ * wheel_info.m_clippedInvContactDotSuspension;
+
+ // Damper
+ btScalar projected_rel_vel = wheel_info.m_suspensionRelativeVelocity;
+ btScalar susp_damping = projected_rel_vel < btScalar(0.0)
+ ? wheel_info.m_wheelsDampingCompression
+ : wheel_info.m_wheelsDampingRelaxation;
+ force -= susp_damping * projected_rel_vel;
+
+ // RESULT
+ wheel_info.m_wheelsSuspensionForce = force * chassisMass;
+ if (wheel_info.m_wheelsSuspensionForce < btScalar(0.))
+ {
+ wheel_info.m_wheelsSuspensionForce = btScalar(0.);
+ }
+ } // for (int w_it=0; w_itcomputeImpulseDenominator(frictionPosWorld,
+ frictionDirectionWorld);
+ btScalar denom1 = body1->computeImpulseDenominator(frictionPosWorld,
+ frictionDirectionWorld);
+ btScalar relaxation = 1.f;
+ m_jacDiagABInv = relaxation/(denom0+denom1);
+ }
+
+
+
+}; // struct btWheelContactPoint
+
+// ----------------------------------------------------------------------------
+btScalar calcRollingFriction(btWheelContactPoint& contactPoint)
+{
+
+ btScalar j1=0.f;
+
+ const btVector3& contactPosWorld = contactPoint.m_frictionPositionWorld;
+
+ btVector3 rel_pos1 = contactPosWorld
+ - contactPoint.m_body0->getCenterOfMassPosition();
+ btVector3 rel_pos2 = contactPosWorld
+ - contactPoint.m_body1->getCenterOfMassPosition();
+
+ btScalar maxImpulse = contactPoint.m_maxImpulse;
+
+ btVector3 vel1 = contactPoint.m_body0->getVelocityInLocalPoint(rel_pos1);
+ btVector3 vel2 = contactPoint.m_body1->getVelocityInLocalPoint(rel_pos2);
+ btVector3 vel = vel1 - vel2;
+
+ btScalar vrel = contactPoint.m_frictionDirectionWorld.dot(vel);
+
+ // calculate j that moves us to zero relative velocity
+ j1 = -vrel * contactPoint.m_jacDiagABInv;
+ btSetMin(j1, maxImpulse);
+ btSetMax(j1, -maxImpulse);
+
+ return j1;
+} // calcRollingFriction
+
+// ----------------------------------------------------------------------------
+
+void btKart::updateFriction(btScalar timeStep)
+{
+
+ //calculate the impulse, so that the wheels don't move sidewards
+ int numWheel = getNumWheels();
+ if (!numWheel)
+ return;
+
+ m_forwardWS.resize(numWheel);
+ m_axle.resize(numWheel);
+ m_forwardImpulse.resize(numWheel);
+ m_sideImpulse.resize(numWheel);
+
+ int numWheelsOnGround = 0;
+
+
+ //collapse all those loops into one!
+ for (int i=0;i 0)
+ {
+ if (wheel==2 || wheel==3)
+ {
+ // The zipper velocity is the speed that should be
+ // reached. So compute the impulse to accelerate the
+ // kart up to that speed:
+ m_forwardImpulse[wheel] =
+ 0.5f*(m_zipper_velocity -
+ getRigidBody()->getLinearVelocity().length())
+ / m_chassisBody->getInvMass();
+ }
+
+ }
+
+ btScalar rollingFriction = 0.f;
+
+ if (wheelInfo.m_engineForce != 0.f)
+ {
+ rollingFriction = wheelInfo.m_engineForce* timeStep;
+ }
+ else
+ {
+ btScalar defaultRollingFrictionImpulse = 0.f;
+ btScalar maxImpulse = wheelInfo.m_brake
+ ? wheelInfo.m_brake
+ : defaultRollingFrictionImpulse;
+ btWheelContactPoint contactPt(m_chassisBody, groundObject,
+ wheelInfo.m_raycastInfo.m_contactPointWS,
+ m_forwardWS[wheel],maxImpulse);
+ rollingFriction = calcRollingFriction(contactPt);
+ // This is a work around for the problem that a kart shakes
+ // if it is braking: we get a minor impulse forward, which
+ // bullet then tries to offset by applying a backward
+ // impulse - which is a bit too big, causing a impulse
+ // backwards, ... till the kart is shaking backwards and
+ // forwards
+ if(wheelInfo.m_brake && fabsf(rollingFriction)<10)
+ rollingFriction=0;
+ }
+
+ //switch between active rolling (throttle), braking and non-active
+ // rolling friction (no throttle/break)
+
+ m_wheelInfo[wheel].m_skidInfo= btScalar(1.);
+
+ btScalar maximp = wheelInfo.m_wheelsSuspensionForce
+ * timeStep * wheelInfo.m_frictionSlip;
+ btScalar maximpSide = maximp;
+ btScalar maximpSquared = maximp * maximpSide;
+ m_forwardImpulse[wheel] = rollingFriction;
+
+ btScalar x = (m_forwardImpulse[wheel] ) * fwdFactor;
+ btScalar y = (m_sideImpulse[wheel] ) * sideFactor;
+
+ btScalar impulseSquared = (x*x + y*y);
+
+ if (impulseSquared > maximpSquared)
+ {
+ sliding = true;
+ btScalar factor = maximp / btSqrt(impulseSquared);
+ m_wheelInfo[wheel].m_skidInfo *= factor;
+ } // if impulseSquared > maximpSquared
+
+ } // for (int wheel=0; wheelgetCenterOfMassPosition();
+
+ if (m_forwardImpulse[wheel] != btScalar(0.))
+ {
+ m_chassisBody->applyImpulse(
+ m_forwardWS[wheel]*(m_forwardImpulse[wheel]),
+#define COMPATIBLE_0_7_3
+#ifdef COMPATIBLE_0_7_3
+ // This was apparently done to help hexley
+ btVector3(0,0,0));
+#else
+ rel_pos);
+#endif
+ }
+ if (m_sideImpulse[wheel] != btScalar(0.))
+ {
+ btRigidBody* groundObject =
+ (btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject;
+ btVector3 rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS
+ - groundObject->getCenterOfMassPosition();
+ //adjust relative position above ground so that force only
+ // acts sideways
+ btVector3 delta_vec = (wheelInfo.m_raycastInfo.m_hardPointWS
+ - wheelInfo.m_raycastInfo.m_contactPointWS);
+ if (delta_vec.length() != btScalar (0))
+ {
+ delta_vec = delta_vec.normalize();
+ rel_pos -= delta_vec * rel_pos.dot(delta_vec);
+ }
+
+ btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
+
+#if defined ROLLING_INFLUENCE_FIX && !defined COMPATIBLE_0_7_3
+ // fix. It only worked if car's up was along Y - VT.
+ btVector3 vChassisWorldUp =
+ getRigidBody()->getCenterOfMassTransform()
+ .getBasis().getColumn(m_indexUpAxis);
+ rel_pos -= vChassisWorldUp * (vChassisWorldUp.dot(rel_pos) *
+ (1.f-wheelInfo.m_rollInfluence) );
+#else
+ rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence;
+#endif
+ m_chassisBody->applyImpulse(sideImp,rel_pos);
+
+ //apply friction impulse on the ground
+ groundObject->applyImpulse(-sideImp,rel_pos2);
+ } // if (m_sideImpulse[wheel] != btScalar(0.))
+ } // for wheeldrawLine(wheelPosWS,wheelPosWS+axle,wheelColor);
+ debugDrawer->drawLine(wheelPosWS,
+ getWheelInfo(v).m_raycastInfo.m_contactPointWS,
+ wheelColor);
+
+ } // for i < getNumWheels
+} // debugDraw
+
+
+// ----------------------------------------------------------------------------
+/** Enables or disables sliding.
+ * \param active Enable (true) or disable sliding.
+ */
+void btKart::setSliding(bool active)
+{
+ m_allow_sliding = active;
+} // setSliding
+
+// ----------------------------------------------------------------------------
+/** Activates an additional speedup for the kart so that it reaches the
+ * specified speed.
+ * \param speed The speed to reach.
+ */
+void btKart::activateZipper(float speed)
+{
+ m_zipper_active = true;
+ m_zipper_velocity = speed;
+} // activateZipper
+
+// ----------------------------------------------------------------------------
+void btKart::deactivateZipper()
+{
+ m_zipper_active = false;
+} // deactivateZipper
// ----------------------------------------------------------------------------
//Shorter version of above raycast function. This is used when projecting
@@ -153,7 +880,7 @@ btScalar btKart::rayCast(btWheelInfo& wheel, const btVector3& ray)
assert(m_vehicleRaycaster);
- void* object = m_vehicleRaycaster->castRay(source,target,rayResults);
+ void* object = m_vehicleRaycaster->castRay(source,target,rayResults);
wheel.m_raycastInfo.m_groundObject = 0;
@@ -167,13 +894,14 @@ btScalar btKart::rayCast(btWheelInfo& wheel, const btVector3& ray)
}
return depth;
-}
+} // rayCast(btWheelInfo& wheel, const btVector3& ray
// ----------------------------------------------------------------------------
//Project vehicle onto surface in a particular direction.
//Used in reseting kart positions.
//Please align wheel direction with ray direction first.
-bool btKart::projectVehicleToSurface(const btVector3& ray, bool translate_vehicle)
+bool btKart::projectVehicleToSurface(const btVector3& ray,
+ bool translate_vehicle)
{
if (ray.length() <= btScalar(0))
return false;
@@ -254,35 +982,44 @@ bool btKart::projectVehicleToSurface(const btVector3& ray, bool translate_vehicl
btTransform offset_trans;
offset_trans.setIdentity();
- btVector3 offset= min_wheel.m_raycastInfo.m_hardPointWS + min_wheel.m_wheelsRadius * ray_dir;
+ btVector3 offset = min_wheel.m_raycastInfo.m_hardPointWS
+ + min_wheel.m_wheelsRadius * ray_dir;
offset -= getRigidBody()->getCenterOfMassPosition();
offset_trans.setOrigin(rot_trans*offset);
- //the effect of the following rotations is to make the 3 wheels with initial
- //minimum distance to surface (in the ray direction) in contact with the
- //plane between the points of intersection (between the ray and surface).
+ // The effect of the following rotations is to make the 3 wheels with
+ // initial minimum distance to surface (in the ray direction) in contact
+ // with the plane between the points of intersection (between the ray and
+ // surface).
- //Note - For possible complex surfaces with lots of bumps directly under vehicle,
- // the raycast needs to be done from a slightly higher above the surface.
- // For such surfaces, the end result should be that at least 1 wheel touches
- // the surface, and no wheel goes below the surface.
+ //Note - For possible complex surfaces with lots of bumps directly under
+ // vehicle, the raycast needs to be done from a slightly higher
+ // above the surface. For such surfaces, the end result should be
+ // that at least 1 wheel touches the surface, and no wheel goes
+ // below the surface.
//We need to rotate vehicle, using above contact point as a pivot to put
//2nd closest wheel nearer to the surface of the track
- btScalar d_hpws = (min_wheel.m_raycastInfo.m_hardPointWS - min_wheel2.m_raycastInfo.m_hardPointWS).length();
- btScalar d_depth = (min_wheel2.m_raycastInfo.m_contactPointWS - min_wheel2.m_raycastInfo.m_hardPointWS - ray_dir * min_wheel.m_wheelsRadius).length();
+ btScalar d_hpws = ( min_wheel.m_raycastInfo.m_hardPointWS
+ - min_wheel2.m_raycastInfo.m_hardPointWS).length();
+ btScalar d_depth = ( min_wheel2.m_raycastInfo.m_contactPointWS
+ - min_wheel2.m_raycastInfo.m_hardPointWS
+ - ray_dir * min_wheel.m_wheelsRadius).length();
d_depth -= min_depth;
//calculate rotation angle from pivot point and plane perpendicular to ray
float rot_angle = atanf(d_depth / d_hpws);
- rot_angle -= atanf((min_wheel2.m_wheelsRadius - min_wheel.m_wheelsRadius) / d_hpws);
+ rot_angle -= atanf((min_wheel2.m_wheelsRadius - min_wheel.m_wheelsRadius)
+ / d_hpws);
getRigidBody()->setAngularVelocity(btVector3(0,0,0));
getRigidBody()->setLinearVelocity(btVector3(0,0,0));
- btVector3 rot_axis = (min_wheel2.m_raycastInfo.m_hardPointWS - min_wheel.m_raycastInfo.m_hardPointWS).cross(ray_dir);
+ btVector3 rot_axis =
+ ( min_wheel2.m_raycastInfo.m_hardPointWS
+ - min_wheel.m_raycastInfo.m_hardPointWS).cross(ray_dir);
btTransform operator_trans;
operator_trans.setIdentity();
@@ -293,7 +1030,8 @@ bool btKart::projectVehicleToSurface(const btVector3& ray, bool translate_vehicl
//rotate kart about pivot point, about line perpendicular to
//ray and vector between the 2 wheels
operator_trans *= offset_trans;
- operator_trans.setRotation(btQuaternion(rot_trans*rot_axis.normalize(), rot_angle));
+ operator_trans.setRotation(btQuaternion(rot_trans*rot_axis.normalize(),
+ rot_angle));
offset_trans.setOrigin(-(rot_trans*offset));
operator_trans *= offset_trans;
}
@@ -305,33 +1043,43 @@ bool btKart::projectVehicleToSurface(const btVector3& ray, bool translate_vehicl
//next, rotate about axis which is a vector between 2 wheels above, so that
//the 3rd wheel is correctly positioned.
- rot_axis = min_wheel2.m_raycastInfo.m_contactPointWS - min_wheel.m_raycastInfo.m_contactPointWS;
- btVector3 wheel_dist = min_wheel3.m_raycastInfo.m_hardPointWS - min_wheel.m_raycastInfo.m_hardPointWS;
+ rot_axis = min_wheel2.m_raycastInfo.m_contactPointWS
+ - min_wheel.m_raycastInfo.m_contactPointWS;
+ btVector3 wheel_dist = min_wheel3.m_raycastInfo.m_hardPointWS
+ - min_wheel.m_raycastInfo.m_hardPointWS;
if (rot_axis.length() != btScalar(0))
{
btVector3 proj = wheel_dist.dot(rot_axis) * rot_axis.normalize();
//calculate position on axis when a perpendicular line would go through
- //3rd wheel position when translated in ray position and rotated as above
- btVector3 pos_on_axis = min_wheel.m_raycastInfo.m_contactPointWS + proj;
+ //3rd wheel position when translated in ray position and rotated as
+ // above
+ btVector3 pos_on_axis =
+ min_wheel.m_raycastInfo.m_contactPointWS + proj;
- btVector3 to_contact_pt = min_wheel3.m_raycastInfo.m_contactPointWS - pos_on_axis;
+ btVector3 to_contact_pt = min_wheel3.m_raycastInfo.m_contactPointWS
+ - pos_on_axis;
btScalar dz = to_contact_pt.dot(ray_dir);
btScalar dw = (to_contact_pt - dz * ray_dir).length();
rot_angle = atanf (dz / dw);
- btVector3 rot_point = getRigidBody()->getCenterOfMassPosition() + min_depth * ray_dir - min_wheel.m_raycastInfo.m_contactPointWS;
+ btVector3 rot_point = getRigidBody()->getCenterOfMassPosition()
+ + min_depth * ray_dir
+ - min_wheel.m_raycastInfo.m_contactPointWS;
rot_point = rot_point.dot(rot_axis) * rot_axis.normalize() - rot_point;
- //calculate translation offset to axis from center of mass along perpendicular
+ //calculate translation offset to axis from center of mass along
+ // perpendicular
offset_trans.setIdentity();
offset= rot_point;
offset_trans.setOrigin(rot_trans*offset);
- btVector3 a = min_wheel3.m_raycastInfo.m_hardPointWS - min_wheel.m_raycastInfo.m_hardPointWS;
- btVector3 b = min_wheel2.m_raycastInfo.m_hardPointWS - min_wheel.m_raycastInfo.m_hardPointWS;
+ btVector3 a = min_wheel3.m_raycastInfo.m_hardPointWS
+ - min_wheel.m_raycastInfo.m_hardPointWS;
+ btVector3 b = min_wheel2.m_raycastInfo.m_hardPointWS
+ - min_wheel.m_raycastInfo.m_hardPointWS;
if ( (a.cross(b)).dot(ray_dir) > 0 )
{
@@ -341,7 +1089,8 @@ bool btKart::projectVehicleToSurface(const btVector3& ray, bool translate_vehicl
//rotate about new axis
operator_trans.setIdentity();
operator_trans *= offset_trans;
- operator_trans.setRotation(btQuaternion(rot_trans*rot_axis.normalize(), rot_angle));
+ operator_trans.setRotation(btQuaternion(rot_trans*rot_axis.normalize(),
+ rot_angle));
offset_trans.setOrigin(-(rot_trans*offset));
operator_trans *= offset_trans;
@@ -383,419 +1132,4 @@ bool btKart::projectVehicleToSurface(const btVector3& ray, bool translate_vehicl
getRigidBody()->translate(-min_wheel.getSuspensionRestLength() *
min_wheel.m_raycastInfo.m_wheelDirectionWS);
return true;
-}
-
-
-// ----------------------------------------------------------------------------
-void btKart::updateVehicle( btScalar step )
-{
- {
- for (int i=0;igetLinearVelocity().length();
-
- const btTransform& chassisTrans = getChassisWorldTransform();
-
- btVector3 forwardW (
- chassisTrans.getBasis()[0][m_indexForwardAxis],
- chassisTrans.getBasis()[1][m_indexForwardAxis],
- chassisTrans.getBasis()[2][m_indexForwardAxis]);
-
- if (forwardW.dot(getRigidBody()->getLinearVelocity()) < btScalar(0.))
- {
- m_currentVehicleSpeedKmHour *= btScalar(-1.);
- }
-
- //
- // simulate suspension
- //
-
- int i=0;
- m_num_wheels_on_ground = 0;
-
- for (i=0;i gMaxSuspensionForce)
- {
- suspensionForce = gMaxSuspensionForce;
- }
- btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step;
- btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition();
-
- getRigidBody()->applyImpulse(impulse, relpos);
- }
-
-
- updateFriction( step);
-
-
- for (i=0;igetCenterOfMassPosition();
- btVector3 vel = getRigidBody()->getVelocityInLocalPoint( relpos );
-
- if (wheel.m_raycastInfo.m_isInContact)
- {
- const btTransform& chassisWorldTransform = getChassisWorldTransform();
-
- btVector3 fwd (
- chassisWorldTransform.getBasis()[0][m_indexForwardAxis],
- chassisWorldTransform.getBasis()[1][m_indexForwardAxis],
- chassisWorldTransform.getBasis()[2][m_indexForwardAxis]);
-
- btScalar proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS);
- fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj;
-
- btScalar proj2 = fwd.dot(vel);
-
- wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius);
- wheel.m_rotation += wheel.m_deltaRotation;
-
- } else
- {
- wheel.m_rotation += wheel.m_deltaRotation;
- }
-
- wheel.m_deltaRotation *= btScalar(0.99);//damping of rotation when not in contact
-
- }
-
-}
-
-// ----------------------------------------------------------------------------
-void btKart::updateSuspension(btScalar deltaTime)
-{
- (void)deltaTime;
-
- btScalar chassisMass = btScalar(1.) / m_chassisBody->getInvMass();
-
- for (int w_it=0; w_itcomputeImpulseDenominator(frictionPosWorld,frictionDirectionWorld);
- btScalar denom1 = body1->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld);
- btScalar relaxation = 1.f;
- m_jacDiagABInv = relaxation/(denom0+denom1);
- }
-
-
-};
-
-// ----------------------------------------------------------------------------
-void btKart::updateFriction(btScalar timeStep)
-{
-
- //calculate the impulse, so that the wheels don't move sidewards
- int numWheel = getNumWheels();
- if (!numWheel)
- return;
-
- m_forwardWS.resize(numWheel);
- m_axle.resize(numWheel);
- m_forwardImpulse.resize(numWheel);
- m_sideImpulse.resize(numWheel);
-
-
- //collapse all those loops into one!
- for (int i=0;igetLinearVelocity().length()) / m_chassisBody->getInvMass();
- }
- }
- else
- {
-
- if (wheelInfo.m_engineForce != 0.f)
- {
- rollingFriction = wheelInfo.m_engineForce* timeStep;
- } else
- {
- //switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break)
- btScalar defaultRollingFrictionImpulse = 0.f;
- btScalar maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse;
- btWheelContactPoint contactPt(m_chassisBody,groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse);
- rollingFriction = calcRollingFriction(contactPt);
- // This is a work around for the problem that a kart shakes
- // if it is braking: we get a minor impulse forward, which
- // bullet then tries to offset by applying a backward
- // impulse - which is a bit too big, causing a impulse
- // backwards, ... till the kart is shaking backwards and
- // forwards
- if(wheelInfo.m_brake && fabsf(rollingFriction)<10)
- rollingFriction=0;
- }
-
- m_forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep;
- }
- btScalar maximp = wheelInfo.m_wheelsSuspensionForce * timeStep * wheelInfo.m_frictionSlip;
- btScalar maximpSide = maximp;
-
- btScalar maximpSquared = maximp * maximpSide;
-
- btScalar x = (m_forwardImpulse[wheel] ) * fwdFactor;
- btScalar y = (m_sideImpulse[wheel] ) * sideFactor;
-
- btScalar impulseSquared = (x*x + y*y);
-
- if (impulseSquared > maximpSquared)
- {
- sliding = true;
-
- btScalar factor = maximp / btSqrt(impulseSquared);
-
- m_wheelInfo[wheel].m_skidInfo *= factor;
- }
- } // if groundObject
-
- } // for wheelgetCenterOfMassPosition();
-
- if (m_forwardImpulse[wheel] != btScalar(0.))
- {
- m_chassisBody->applyImpulse(m_forwardWS[wheel]*(m_forwardImpulse[wheel]),
- btVector3(0,0,0));
- }
- if (m_sideImpulse[wheel] != btScalar(0.))
- {
- class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject;
-
- btVector3 rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS -
- groundObject->getCenterOfMassPosition();
-
- //adjust relative position above ground so that force only acts sideways
- btVector3 delta_vec = (wheelInfo.m_raycastInfo.m_hardPointWS - wheelInfo.m_raycastInfo.m_contactPointWS);
- if (delta_vec.length() != btScalar (0))
- {
- delta_vec = delta_vec.normalize();
- rel_pos -= delta_vec * rel_pos.dot(delta_vec);
- }
-
- btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
-
- rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence;
- m_chassisBody->applyImpulse(sideImp,rel_pos);
-
- //apply friction impulse on the ground
- groundObject->applyImpulse(-sideImp,rel_pos2);
- }
- }
- }
-
-
-}
+} // projectVehicleToSurface
diff --git a/src/physics/btKart.hpp b/src/physics/btKart.hpp
index e860ffc38..333fc6059 100644
--- a/src/physics/btKart.hpp
+++ b/src/physics/btKart.hpp
@@ -4,61 +4,237 @@
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies.
- * Erwin Coumans makes no representations about the suitability
- * of this software for any purpose.
+ * Erwin Coumans makes no representations about the suitability
+ * of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
-#ifndef HEADER_BT_KART_HPP
-#define HEADER_BT_KART_HPP
-
-#include "btBulletDynamicsCommon.h"
+#ifndef BT_KART_HPP
+#define BT_KART_HPP
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "physics/btKartRaycast.hpp"
class btDynamicsWorld;
-struct btWheelInfo;
+#include "LinearMath/btAlignedObjectArray.h"
+#include "BulletDynamics/Vehicle/btWheelInfo.h"
+#include "BulletDynamics/Dynamics/btActionInterface.h"
-/** The btKart is a raycast vehicle, that does not skid. It therefore solves
- * the problems with the plain bullet physics that karts would often rotate
- * on a spot if one of the wheels loses contact with the ground.
- * \ingroup physics
- */
-class btKart : public btRaycastVehicle
+class btVehicleTuning;
+class Kart;
+
+///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle.
+class btKart : public btActionInterface
{
- void defaultInit(const btVehicleTuning& tuning);
- btScalar m_track_connect_accel;
- int m_num_wheels_on_ground;
- bool m_zipper_active;
- btScalar m_zipper_velocity;
+private:
+ btAlignedObjectArray m_forwardWS;
+ btAlignedObjectArray m_axle;
+ btAlignedObjectArray m_forwardImpulse;
+ btAlignedObjectArray m_sideImpulse;
+
+ ///backwards compatibility
+ int m_userConstraintType;
+ int m_userConstraintId;
+
+public:
+ class btVehicleTuning
+ {
+ public:
+
+ btVehicleTuning()
+ :m_suspensionStiffness(btScalar(5.88)),
+ m_suspensionCompression(btScalar(0.83)),
+ m_suspensionDamping(btScalar(0.88)),
+ m_maxSuspensionTravelCm(btScalar(500.)),
+ m_frictionSlip(btScalar(10.5)),
+ m_maxSuspensionForce(btScalar(6000.))
+ {
+ }
+ btScalar m_suspensionStiffness;
+ btScalar m_suspensionCompression;
+ btScalar m_suspensionDamping;
+ btScalar m_maxSuspensionTravelCm;
+ btScalar m_frictionSlip;
+ btScalar m_maxSuspensionForce;
+
+ };
+protected:
+
+ btScalar m_damping;
+ btVehicleRaycaster *m_vehicleRaycaster;
+ btScalar m_currentVehicleSpeedKmHour;
+ bool m_zipper_active;
+ btScalar m_zipper_velocity;
/** Sliding (skidding) will only be permited when this is true. Also check
- * the friction parameter in the wheels since friction directly affects skidding
- */
- bool m_allow_sliding;
-
+ * the friction parameter in the wheels since friction directly affects
+ * skidding.
+ */
+ bool m_allow_sliding;
+
+ btRigidBody* m_chassisBody;
+
+ int m_num_wheels_on_ground;
+ int m_indexRightAxis;
+ int m_indexUpAxis;
+ int m_indexForwardAxis;
+
+ /** The STK kart object which uses this vehicle. This is mostly used to
+ * get access to the kart properties, which also define physics
+ * properties. */
+ Kart *m_kart;
+
+ void defaultInit();
+
public:
-
- btKart(const btVehicleTuning& tuning,btRigidBody* chassis,
- btVehicleRaycaster* raycaster, float track_connect_accel );
- virtual ~btKart() ;
- btScalar rayCast(btWheelInfo& wheel);
- btScalar rayCast(btWheelInfo& wheel, const btVector3& ray);
- bool projectVehicleToSurface(const btVector3& ray, bool translate_vehicle);
- virtual void updateVehicle(btScalar step);
- void resetSuspension();
- int getNumWheelsOnGround() const { return m_num_wheels_on_ground; }
- void setRaycastWheelInfo(int wheelIndex , bool isInContact,
- const btVector3& hitPoint,
- const btVector3& hitNormal,btScalar depth);
- void setPitchControl(btScalar pitch) { m_pitchControl = pitch; }
- void activateZipper(btScalar vel) { m_zipper_active = true; m_zipper_velocity = vel; }
- void deactivateZipper() { m_zipper_active = false; }
- void updateSuspension(btScalar deltaTime);
- virtual void updateFriction(btScalar timeStep);
-
- /** Sliding (skidding) will only be permited when this is set to true. Also check
- * the friction parameter in the wheels since friction directly affects skidding
- */
- void enableSliding(bool enabled) { m_allow_sliding = enabled; }
+
+ //constructor to create a car from an existing rigidbody
+ btKart(btRigidBody* chassis, btVehicleRaycaster* raycaster,
+ Kart *kart);
+
+ virtual ~btKart() ;
+
+ void reset();
+
+ ///btActionInterface interface
+ virtual void updateAction( btCollisionWorld* collisionWorld, btScalar step)
+ {
+ (void) collisionWorld;
+ updateVehicle(step);
+ }
+
+ ///btActionInterface interface
+ void debugDraw(btIDebugDraw* debugDrawer);
+
+ const btTransform& getChassisWorldTransform() const;
+
+ btScalar rayCast(btWheelInfo& wheel);
+
+ virtual void updateVehicle(btScalar step);
+
+
+ void resetSuspension();
+
+ btScalar getSteeringValue(int wheel) const;
+
+ void setSteeringValue(btScalar steering,int wheel);
+
+
+ void applyEngineForce(btScalar force, int wheel);
+
+ const btTransform& getWheelTransformWS( int wheelIndex ) const;
+
+ void updateWheelTransform( int wheelIndex, bool interpolatedTransform = true );
+
+// void setRaycastWheelInfo( int wheelIndex , bool isInContact, const btVector3& hitPoint, const btVector3& hitNormal,btScalar depth);
+
+ btWheelInfo& addWheel( const btVector3& connectionPointCS0, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS,btScalar suspensionRestLength,btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel);
+
+ inline int getNumWheels() const {
+ return int (m_wheelInfo.size());
+ }
+
+ btAlignedObjectArray m_wheelInfo;
+
+
+ const btWheelInfo& getWheelInfo(int index) const;
+
+ btWheelInfo& getWheelInfo(int index);
+
+ void updateWheelTransformsWS(btWheelInfo& wheel , bool interpolatedTransform = true);
+
+
+ void setBrake(btScalar brake,int wheelIndex);
+
+ void updateSuspension(btScalar deltaTime);
+
+ virtual void updateFriction(btScalar timeStep);
+
+
+
+ inline btRigidBody* getRigidBody()
+ {
+ return m_chassisBody;
+ }
+
+ const btRigidBody* getRigidBody() const
+ {
+ return m_chassisBody;
+ }
+
+ inline int getRightAxis() const
+ {
+ return m_indexRightAxis;
+ }
+ inline int getUpAxis() const
+ {
+ return m_indexUpAxis;
+ }
+
+ inline int getForwardAxis() const
+ {
+ return m_indexForwardAxis;
+ }
+
+
+ ///Worldspace forward vector
+ btVector3 getForwardVector() const
+ {
+ const btTransform& chassisTrans = getChassisWorldTransform();
+
+ btVector3 forwardW (
+ chassisTrans.getBasis()[0][m_indexForwardAxis],
+ chassisTrans.getBasis()[1][m_indexForwardAxis],
+ chassisTrans.getBasis()[2][m_indexForwardAxis]);
+
+ return forwardW;
+ }
+
+ ///Velocity of vehicle (positive if velocity vector has same direction as foward vector)
+ btScalar getCurrentSpeedKmHour() const
+ {
+ return m_currentVehicleSpeedKmHour;
+ }
+
+ virtual void setCoordinateSystem(int rightIndex,int upIndex,int forwardIndex)
+ {
+ m_indexRightAxis = rightIndex;
+ m_indexUpAxis = upIndex;
+ m_indexForwardAxis = forwardIndex;
+ }
+
+
+ ///backwards compatibility
+ int getUserConstraintType() const
+ {
+ return m_userConstraintType ;
+ }
+
+ void setUserConstraintType(int userConstraintType)
+ {
+ m_userConstraintType = userConstraintType;
+ };
+
+ void setUserConstraintId(int uid)
+ {
+ m_userConstraintId = uid;
+ }
+
+ int getUserConstraintId() const
+ {
+ return m_userConstraintId;
+ }
+private:
+ btScalar rayCast(btWheelInfo& wheel, const btVector3& ray);
+public:
+ void setSliding(bool active);
+ void activateZipper(float speed);
+ void deactivateZipper();
+ bool projectVehicleToSurface(const btVector3& ray,
+ bool translate_vehicle);
+ // ------------------------------------------------------------------------
+ /** Returns the number of wheels on the ground. */
+ unsigned int getNumWheelsOnGround() const {return m_num_wheels_on_ground;}
};
-#endif //BT_KART_H
+#endif //BT_RAYCASTVEHICLE_H
diff --git a/src/physics/btKartRaycast.hpp b/src/physics/btKartRaycast.hpp
index dc6f3fdf4..b05420066 100644
--- a/src/physics/btKartRaycast.hpp
+++ b/src/physics/btKartRaycast.hpp
@@ -8,8 +8,8 @@
* of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
-#ifndef BTKARTRAYCASTER_HPP
-#define BTKARTRAYCSATER_HPP
+#ifndef BTKARTRAYCAST_HPP
+#define BTKARTRAYCAST_HPP
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp
index 5c4d4cf2c..6681df49a 100644
--- a/src/physics/physics.cpp
+++ b/src/physics/physics.cpp
@@ -27,6 +27,7 @@
#include "physics/btUprightConstraint.hpp"
#include "physics/irr_debug_drawer.hpp"
#include "physics/physical_object.hpp"
+#include "physics/stk_dynamics_world.hpp"
#include "physics/triangle_mesh.hpp"
#include "tracks/track.hpp"
@@ -48,10 +49,10 @@ Physics::Physics() : btSequentialImpulseConstraintSolver()
void Physics::init(const Vec3 &world_min, const Vec3 &world_max)
{
m_axis_sweep = new btAxisSweep3(world_min, world_max);
- m_dynamics_world = new btDiscreteDynamicsWorld(m_dispatcher,
- m_axis_sweep,
- this,
- m_collision_conf);
+ m_dynamics_world = new STKDynamicsWorld(m_dispatcher,
+ m_axis_sweep,
+ this,
+ m_collision_conf);
m_dynamics_world->setGravity(btVector3(0.0f,
-World::getWorld()->getTrack()->getGravity(),
0.0f));
diff --git a/src/physics/physics.hpp b/src/physics/physics.hpp
index bde791fd0..9739cba20 100644
--- a/src/physics/physics.hpp
+++ b/src/physics/physics.hpp
@@ -31,10 +31,12 @@
#include "btBulletDynamicsCommon.h"
#include "physics/irr_debug_drawer.hpp"
+#include "physics/stk_dynamics_world.hpp"
#include "physics/user_pointer.hpp"
-class Vec3;
class Kart;
+class STKDynamicsWorld;
+class Vec3;
/**
* \ingroup physics
@@ -89,7 +91,10 @@ private:
}
}; // CollisionList
- btDynamicsWorld *m_dynamics_world;
+ /** Pointer to the physics dynamics world. */
+ STKDynamicsWorld *m_dynamics_world;
+
+ /** Used in physics debugging to draw the physics world. */
IrrDebugDrawer *m_debug_drawer;
btCollisionDispatcher *m_dispatcher;
btBroadphaseInterface *m_axis_sweep;
@@ -107,7 +112,7 @@ public:
void KartKartCollision(Kart *ka, Kart *kb);
void update (float dt);
void draw ();
- btDynamicsWorld*
+ STKDynamicsWorld*
getPhysicsWorld () const {return m_dynamics_world;}
/** Activates the next debug mode (or switches it off again).
*/
diff --git a/src/physics/stk_dynamics_world.hpp b/src/physics/stk_dynamics_world.hpp
new file mode 100644
index 000000000..3d5d7b677
--- /dev/null
+++ b/src/physics/stk_dynamics_world.hpp
@@ -0,0 +1,47 @@
+// $Id$
+//
+// SuperTuxKart - a fun racing game with go-kart
+// Copyright (C) 2011 Joerg Henrichs
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 3
+// of the License, or (at your option) any later version.
+//
+// This program is 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_STK_DYNAMICS_WORLD_HPP
+#define HEADER_STK_DYNAMICS_WORLD_HPP
+
+#include "btBulletDynamicsCommon.h"
+
+class STKDynamicsWorld : public btDiscreteDynamicsWorld
+{
+public:
+ /** The standard constructor which just created a btDiscreteDynamicsWorld. */
+ STKDynamicsWorld(btDispatcher* dispatcher,
+ btBroadphaseInterface* pairCache,
+ btConstraintSolver* constraintSolver,
+ btCollisionConfiguration* collisionConfiguration)
+
+ : btDiscreteDynamicsWorld(dispatcher, pairCache,
+ constraintSolver,
+ collisionConfiguration)
+ {
+ }
+
+ /** Resets m_localTime to 0. This allows more precise replay of
+ * physics, which is important for replaying histories. */
+ virtual void resetLocalTime() { m_localTime = 0; }
+
+}; // STKDynamicsWorld
+#endif
+/* EOF */
+
diff --git a/src/race/history.cpp b/src/race/history.cpp
index 1ab411177..8ceae7fd1 100644
--- a/src/race/history.cpp
+++ b/src/race/history.cpp
@@ -24,6 +24,7 @@
#include "io/file_manager.hpp"
#include "modes/world.hpp"
#include "karts/kart.hpp"
+#include "physics/physics.hpp"
#include "race/race_manager.hpp"
#include "tracks/track.hpp"
#include "utils/constants.hpp"
@@ -99,7 +100,9 @@ void History::updateSaving(float dt)
}
else
{
- m_size ++;
+ // m_size must be m_all_deltas.size() or smaller
+ if(m_size<(int)m_all_deltas.size())
+ m_size ++;
}
m_all_deltas[m_current] = dt;
@@ -122,12 +125,15 @@ void History::updateSaving(float dt)
void History::updateReplay(float dt)
{
m_current++;
+ World *world = World::getWorld();
if(m_current>=(int)m_all_deltas.size())
{
printf("Replay finished.\n");
- exit(2);
+ m_current = 0;
+ // Note that for physics replay all physics parameters
+ // need to be reset, e.g. velocity, ...
+ world->restartRace();
}
- World *world = World::getWorld();
unsigned int num_karts = world->getNumKarts();
for(unsigned k=0; k m_all_deltas;
+
+ /** Stores the kart controls being used (for physics replay). */
std::vector m_all_controls;
+
+ /** Stores the coordinates (for simple replay). */
AlignedArray m_all_xyz;
+
+ /** Stores the rotations of the karts. */
AlignedArray m_all_rotations;
/** The identities of the karts to use. */
std::vector m_kart_ident;
+
void allocateMemory(int number_of_frames);
void updateSaving(float dt);
void updateReplay(float dt);
@@ -70,7 +87,7 @@ public:
void Save ();
void Load ();
- // ------------------------------------------------------------------------
+ // -------------------I-----------------------------------------------------
/** Returns the identifier of the n-th kart. */
const std::string& getKartIdent(unsigned int n)
{
diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp
index 7d1ee8b5c..db3b79d1c 100644
--- a/src/tracks/track.cpp
+++ b/src/tracks/track.cpp
@@ -1234,7 +1234,8 @@ void Track::loadTrackModel(World* parent, unsigned int mode_id)
m_start_transforms[position].setOrigin(xyz);
m_start_transforms[position].setRotation(
- btQuaternion(btVector3(0,1,0),h ) );
+ btQuaternion(btVector3(0,1,0),
+ h*DEGREE_TO_RAD ) );
}
else if(name=="camera")
{