From 72070db1a03af0fdd8981c2a3215788b9161e349 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Wed, 7 Mar 2012 02:41:41 +0000 Subject: [PATCH] Fixed memory leak: the virtual createPhysics function of GhostKart was not called, since it was called during when the contrsuctor of Kart was executed (at this time the GhostKart vtable wasn't set up, so Kart::createPhysics) was called - which resulted in a memory leak since all physics parts of the kart were actually allocated (just not used). To fix this, karts are not constructed in two phases: first a constructor, followed by a call to init (during which virtual function can be used). Fixed several bugs were physics data for a GhostKart were accessed. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@10947 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/items/attachment.cpp | 4 +- src/items/powerup.cpp | 2 +- src/karts/ghost_kart.cpp | 3 +- src/karts/ghost_kart.hpp | 7 +- src/karts/kart.cpp | 268 +++++++++++++++++----------------- src/karts/kart.hpp | 8 +- src/karts/kart_with_stats.cpp | 8 +- src/karts/kart_with_stats.hpp | 5 +- src/karts/moveable.cpp | 3 +- src/karts/moveable.hpp | 6 +- src/main.cpp | 1 + src/modes/profile_world.cpp | 6 +- src/modes/world.cpp | 5 +- src/network/network_kart.cpp | 2 +- src/physics/btKart.cpp | 6 +- src/replay/replay_play.cpp | 18 +-- src/replay/replay_play.hpp | 3 +- 17 files changed, 184 insertions(+), 171 deletions(-) diff --git a/src/items/attachment.cpp b/src/items/attachment.cpp index 40f2c299b..1e82850ca 100644 --- a/src/items/attachment.cpp +++ b/src/items/attachment.cpp @@ -186,7 +186,7 @@ void Attachment::clear() // Resets the weight of the kart if the previous attachment affected it // (e.g. anvil). This must be done *after* setting m_type to // ATTACH_NOTHING in order to reset the physics parameters. - m_kart->updatedWeight(); + m_kart->updateWeight(); } // clear // ----------------------------------------------------------------------------- @@ -285,7 +285,7 @@ void Attachment::hitBanana(Item *item, int new_attachment) // Reduce speed once (see description above), all other changes are // handled in Kart::updatePhysics m_kart->adjustSpeed(stk_config->m_anvil_speed_factor); - m_kart->updatedWeight(); + m_kart->updateWeight(); break ; } // switch } diff --git a/src/items/powerup.cpp b/src/items/powerup.cpp index 40d6bf5a5..70e41d7f5 100644 --- a/src/items/powerup.cpp +++ b/src/items/powerup.cpp @@ -315,7 +315,7 @@ void Powerup::use() { kart->getAttachment()->set(Attachment::ATTACH_ANVIL, stk_config->m_anvil_time); - kart->updatedWeight(); + kart->updateWeight(); kart->adjustSpeed(stk_config->m_anvil_speed_factor*0.5f); // should we position the sound at the kart that is hit, diff --git a/src/karts/ghost_kart.cpp b/src/karts/ghost_kart.cpp index 51f71aac7..101338f9e 100644 --- a/src/karts/ghost_kart.cpp +++ b/src/karts/ghost_kart.cpp @@ -23,8 +23,7 @@ GhostKart::GhostKart(const std::string& ident) : Kart(ident, /*world kart id*/99999, - /*position*/-1, /*is_first_kart*/false, - btTransform(), RaceManager::KT_GHOST) + /*position*/-1, btTransform()) { m_current = 0; } // GhostKart diff --git a/src/karts/ghost_kart.hpp b/src/karts/ghost_kart.hpp index fce21fe43..a8e7df60d 100644 --- a/src/karts/ghost_kart.hpp +++ b/src/karts/ghost_kart.hpp @@ -49,7 +49,12 @@ public: virtual void update (float dt); virtual void addTransform(float time, const btTransform &trans); virtual void reset(); - + // ------------------------------------------------------------------------ + /** No physics body for ghost kart, so nothing to adjust. */ + virtual void updateWeight() {}; + // ------------------------------------------------------------------------ + /** No physics for ghost kart. */ + virtual void applyEngineForce (float force) {} // ------------------------------------------------------------------------ // Not needed to create any physics for a ghost kart. virtual void createPhysics() {} diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index b9bcd97f1..d70e0b140 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -73,8 +73,7 @@ * \param init_transform The initial position and rotation for this kart. */ Kart::Kart (const std::string& ident, unsigned int world_kart_id, - int position, bool is_first_kart, - const btTransform& init_transform, RaceManager::KartType type) + int position, const btTransform& init_transform) : TerrainInfo(1), Moveable(), EmergencyAnimation(this), MaxSpeed(this), m_powerup(this) @@ -93,6 +92,7 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id, // kart_model is stored in the kart_properties all the time, // there is no risk of a mesh being deleted to early. m_kart_model = m_kart_properties->getKartModelCopy(); + m_vehicle = NULL; m_initial_position = position; m_race_position = position; m_world_kart_id = world_kart_id; @@ -147,6 +147,14 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id, m_terrain_sound = NULL; m_previous_terrain_sound = NULL; +} // Kart + +// ----------------------------------------------------------------------------- +/** This is a second initialisation phase, necessary since in the constructor + * virtual functions are not called for any superclasses. + */ +void Kart::init(RaceManager::KartType type, bool is_first_kart) +{ // In multiplayer mode, sounds are NOT positional if (race_manager->getNumLocalPlayers() > 1) { @@ -173,6 +181,7 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id, fprintf(stdout, "Error: Could not allocate a sfx object for the kart. Further errors may ensue!\n"); } + bool animations = true; const int anims = UserConfigParams::m_show_steering_animations; if (anims == ANIMS_NONE) @@ -183,7 +192,6 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id, { animations = false; } - loadData(type, is_first_kart, animations); m_kart_gfx = new KartGFX(this); @@ -191,7 +199,121 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id, m_kart_properties->getSkiddingProperties()); reset(); -} // Kart +} // init + +//----------------------------------------------------------------------------- +/** Reset before a new race. It will remove all attachments, and + * puts the kart back at its original start position. + */ +void Kart::reset() +{ + if (m_flying) + { + m_flying = false; + stopFlying(); + } + + EmergencyAnimation::reset(); + MaxSpeed::reset(); + if (m_camera) + { + m_camera->reset(); + m_camera->setInitialTransform(); + } + + // Reset animations and wheels + m_kart_model->reset(); + + // If the controller was replaced (e.g. replaced by end controller), + // restore the original controller. + if(m_saved_controller) + { + m_controller = m_saved_controller; + m_saved_controller = NULL; + } + m_kart_model->setAnimation(KartModel::AF_DEFAULT); + m_view_blocked_by_plunger = 0.0; + m_attachment->clear(); + m_kart_gfx->reset(); + m_skidding->reset(); + + + if (m_collision_particles) + m_collision_particles->setCreationRateAbsolute(0.0f); + m_powerup.reset(); + + m_race_position = m_initial_position; + m_finished_race = false; + m_finish_time = 0.0f; + m_bubblegum_time = 0.0f; + m_invulnerable_time = 0.0f; + m_squash_time = 0.0f; + m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f)); + m_collected_energy = 0; + m_has_started = false; + m_wheel_rotation = 0; + m_bounce_back_time = 0.0f; + m_time_last_crash = 0.0f; + m_speed = 0.0f; + m_view_blocked_by_plunger = 0.0f; + + if(m_terrain_sound) + { + sfx_manager->deleteSFX(m_terrain_sound); + } + if(m_previous_terrain_sound) + { + sfx_manager->deleteSFX(m_previous_terrain_sound); + } + + m_terrain_sound = NULL; + m_previous_terrain_sound = NULL; + + if(m_engine_sound) + m_engine_sound->stop(); + + m_controls.m_steer = 0.0f; + m_controls.m_accel = 0.0f; + m_controls.m_brake = false; + m_controls.m_nitro = false; + m_controls.m_skid = false; + m_controls.m_fire = false; + m_controls.m_look_back = false; + m_slipstream->reset(); + if(m_vehicle) + { + m_vehicle->reset(); + } + + setTrans(m_reset_transform); + + applyEngineForce (0.0f); + + Moveable::reset(); + if (m_skidmarks) + { + m_skidmarks->reset(); + const Track *track = + track_manager->getTrack( race_manager->getTrackName() ); + m_skidmarks->adjustFog(track->isFogEnabled() ); + } + + + TerrainInfo::update(getXYZ()); + + // Reset is also called when the kart is created, at which time + // m_controller is not yet defined, so this has to be tested here. + if(m_controller) + m_controller->reset(); + + // 3 strikes mode can hide the wheels + scene::ISceneNode** wheels = getKartModel()->getWheelNodes(); + if(wheels[0]) wheels[0]->setVisible(true); + if(wheels[1]) wheels[1]->setVisible(true); + if(wheels[2]) wheels[2]->setVisible(true); + if(wheels[3]) wheels[3]->setVisible(true); + +} // reset // ----------------------------------------------------------------------------- /** Saves the old controller in m_saved_controller and stores a new @@ -446,10 +568,14 @@ Kart::~Kart() if(m_skidmarks) delete m_skidmarks ; - World::getWorld()->getPhysics()->removeKart(this); - delete m_vehicle; - delete m_vehicle_raycaster; - delete m_uprightConstraint; + // Ghost karts don't have a body + if(m_body) + { + World::getWorld()->getPhysics()->removeKart(this); + delete m_vehicle; + delete m_vehicle_raycaster; + delete m_uprightConstraint; + } for(int i=0; igetMass() + m_attachment->weightAdjust(); btVector3 inertia; m_kart_chassis.calculateLocalInertia(mass, inertia); m_body->setMassProps(mass, inertia); -} // updatedWeight - -//----------------------------------------------------------------------------- -/** Reset before a new race. It will remove all attachments, and - * puts the kart back at its original start position. - */ -void Kart::reset() -{ - if (m_flying) - { - m_flying = false; - stopFlying(); - } - - EmergencyAnimation::reset(); - MaxSpeed::reset(); - if (m_camera) - { - m_camera->reset(); - m_camera->setInitialTransform(); - } - - // Reset animations and wheels - m_kart_model->reset(); - - // If the controller was replaced (e.g. replaced by end controller), - // restore the original controller. - if(m_saved_controller) - { - m_controller = m_saved_controller; - m_saved_controller = NULL; - } - m_kart_model->setAnimation(KartModel::AF_DEFAULT); - m_view_blocked_by_plunger = 0.0; - m_attachment->clear(); - m_kart_gfx->reset(); - m_skidding->reset(); - - - if (m_collision_particles) - m_collision_particles->setCreationRateAbsolute(0.0f); - m_powerup.reset(); - - m_race_position = m_initial_position; - m_finished_race = false; - m_finish_time = 0.0f; - m_bubblegum_time = 0.0f; - m_invulnerable_time = 0.0f; - m_squash_time = 0.0f; - m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f)); - m_collected_energy = 0; - m_has_started = false; - m_wheel_rotation = 0; - m_bounce_back_time = 0.0f; - m_time_last_crash = 0.0f; - m_speed = 0.0f; - m_view_blocked_by_plunger = 0.0f; - - if(m_terrain_sound) - { - sfx_manager->deleteSFX(m_terrain_sound); - } - if(m_previous_terrain_sound) - { - sfx_manager->deleteSFX(m_previous_terrain_sound); - } - - m_terrain_sound = NULL; - m_previous_terrain_sound = NULL; - - if(m_engine_sound) - m_engine_sound->stop(); - - m_controls.m_steer = 0.0f; - m_controls.m_accel = 0.0f; - m_controls.m_brake = false; - m_controls.m_nitro = false; - m_controls.m_skid = false; - m_controls.m_fire = false; - m_controls.m_look_back = false; - m_slipstream->reset(); - m_vehicle->deactivateZipper(); - - // Set the brakes so that karts don't slide downhill - m_vehicle->setAllBrakes(5.0f); - - setTrans(m_reset_transform); - - applyEngineForce (0.0f); - - Moveable::reset(); - if (m_skidmarks) - { - m_skidmarks->reset(); - 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); - } - - TerrainInfo::update(getXYZ()); - - // Reset is also called when the kart is created, at which time - // m_controller is not yet defined, so this has to be tested here. - if(m_controller) - m_controller->reset(); - - // 3 strikes mode can hide the wheels - scene::ISceneNode** wheels = getKartModel()->getWheelNodes(); - if(wheels[0]) wheels[0]->setVisible(true); - if(wheels[1]) wheels[1]->setVisible(true); - if(wheels[2]) wheels[2]->setVisible(true); - if(wheels[3]) wheels[3]->setVisible(true); - -} // reset +} // updateWeight //----------------------------------------------------------------------------- /** Sets that this kart has finished the race and finishing time. It also @@ -1930,7 +1937,8 @@ void Kart::loadData(RaceManager::KartType type, bool is_first_kart, // attachment is needed in createPhysics (which gets the mass, which // is dependent on the attachment). m_attachment = new Attachment(this); - createPhysics(); + if(type!=RaceManager::KT_GHOST) + createPhysics(); // Attach Particle System diff --git a/src/karts/kart.hpp b/src/karts/kart.hpp index fd5649127..825ebf46d 100644 --- a/src/karts/kart.hpp +++ b/src/karts/kart.hpp @@ -213,17 +213,18 @@ protected: public: Kart(const std::string& ident, unsigned int world_kart_id, - int position, bool is_first_kart, - const btTransform& init_transform, RaceManager::KartType type); + int position, const btTransform& init_transform); virtual ~Kart(); + virtual void init(RaceManager::KartType type, bool is_first_kart); void loadData(RaceManager::KartType type, bool is_first_kart, bool animatedModel); virtual void updateGraphics(float dt, const Vec3& off_xyz, const btQuaternion& off_rotation); virtual void createPhysics (); + virtual void updateWeight (); bool isInRest () const; void setSuspensionLength(); - void applyEngineForce (float force); + virtual void applyEngineForce (float force); float handleNitro (float dt); float getActualWheelForce(); @@ -233,7 +234,6 @@ public: void startEngineSFX (); void adjustSpeed (float f); void capSpeed (float max_speed); - void updatedWeight (); virtual void collectedItem (Item *item, int random_attachment); virtual void reset (); void handleZipper (const Material *m=NULL, bool play_sound=false); diff --git a/src/karts/kart_with_stats.cpp b/src/karts/kart_with_stats.cpp index 5f5bc24dd..96e8a3fd2 100644 --- a/src/karts/kart_with_stats.cpp +++ b/src/karts/kart_with_stats.cpp @@ -22,11 +22,9 @@ KartWithStats::KartWithStats(const std::string& ident, unsigned int world_kart_id, - int position, bool is_first_kart, - const btTransform& init_transform, - RaceManager::KartType type) - : Kart(ident, world_kart_id, position, is_first_kart, - init_transform, type) + int position, const btTransform& init_transform) + : Kart(ident, world_kart_id, position, + init_transform) { reset(); } // KartWithStats diff --git a/src/karts/kart_with_stats.hpp b/src/karts/kart_with_stats.hpp index 777de163e..8cacc00bf 100644 --- a/src/karts/kart_with_stats.hpp +++ b/src/karts/kart_with_stats.hpp @@ -67,9 +67,8 @@ private: public: KartWithStats(const std::string& ident, unsigned int world_kart_id, - int position, bool is_first_kart, - const btTransform& init_transform, - RaceManager::KartType type); + int position, + const btTransform& init_transform); virtual void update(float dt); virtual void reset(); virtual void handleExplosion(const Vec3& pos, bool direct_hit); diff --git a/src/karts/moveable.cpp b/src/karts/moveable.cpp index 20c6301ac..4ac1b83c8 100644 --- a/src/karts/moveable.cpp +++ b/src/karts/moveable.cpp @@ -179,5 +179,6 @@ void Moveable::createBody(float mass, btTransform& trans, void Moveable::setTrans(const btTransform &t) { m_transform=t; - m_motion_state->setWorldTransform(t); + if(m_motion_state) + m_motion_state->setWorldTransform(t); } // setTrans diff --git a/src/karts/moveable.hpp b/src/karts/moveable.hpp index 40ef30260..af8c211a4 100644 --- a/src/karts/moveable.hpp +++ b/src/karts/moveable.hpp @@ -89,14 +89,16 @@ public: void setXYZ(const Vec3& a) { m_transform.setOrigin(a); - m_motion_state->setWorldTransform(m_transform); + if(m_motion_state) + m_motion_state->setWorldTransform(m_transform); } // ------------------------------------------------------------------------ /** Sets the rotation of this moveable. */ void setRotation(const btQuaternion&a) { m_transform.setRotation(a); - m_motion_state->setWorldTransform(m_transform); + if(m_motion_state) + m_motion_state->setWorldTransform(m_transform); } // ------------------------------------------------------------------------ virtual void updateGraphics(float dt, const Vec3& off_xyz, diff --git a/src/main.cpp b/src/main.cpp index 190e9675e..c0778f05a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1108,6 +1108,7 @@ void cleanSuperTuxKart() //delete in reverse order of what they were created in. //see InitTuxkart() Referee::cleanup(); + if(ReplayPlay::get()) ReplayPlay::destroy(); if(race_manager) delete race_manager; if(network_http) delete network_http; if(news_manager) delete news_manager; diff --git a/src/modes/profile_world.cpp b/src/modes/profile_world.cpp index b4b1124f1..5ee431c72 100644 --- a/src/modes/profile_world.cpp +++ b/src/modes/profile_world.cpp @@ -94,10 +94,8 @@ Kart *ProfileWorld::createKart(const std::string &kart_ident, int index, Kart *new_kart = new KartWithStats(kart_ident, /*world kart id*/ index, /*position*/ index+1, - /*is_first_kart*/false, - init_pos, - RaceManager::KT_AI); - + init_pos); + new_kart->init(RaceManager::KT_AI, /*is_first_kart*/false); Controller *controller = loadAIController(new_kart); new_kart->setController(controller); diff --git a/src/modes/world.cpp b/src/modes/world.cpp index f815f6058..34f7c081f 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -197,9 +197,8 @@ Kart *World::createKart(const std::string &kart_ident, int index, { int position = index+1; btTransform init_pos = m_track->getStartTransform(index); - Kart *new_kart = new Kart(kart_ident, index, position, - (local_player_id == 0), init_pos, - race_manager->getKartType(index)); + Kart *new_kart = new Kart(kart_ident, index, position, init_pos); + new_kart->init(race_manager->getKartType(index), (local_player_id == 0)); Controller *controller = NULL; switch(kart_type) { diff --git a/src/network/network_kart.cpp b/src/network/network_kart.cpp index 1b1ae4fb8..1085a09aa 100644 --- a/src/network/network_kart.cpp +++ b/src/network/network_kart.cpp @@ -29,7 +29,7 @@ NetworkKart::NetworkKart(const std::string &kart_name, int global_player_id, RaceManager::KartType type) : Kart(kart_name, world_kart_id, position, - /*is_first_kart*/false, init_transform, type) + init_transform) { m_global_player_id = global_player_id; } // NetworkKart diff --git a/src/physics/btKart.cpp b/src/physics/btKart.cpp index 4b4041c78..6f9ad9c66 100644 --- a/src/physics/btKart.cpp +++ b/src/physics/btKart.cpp @@ -109,7 +109,7 @@ void btKart::reset() btWheelInfo &wheel = m_wheelInfo[i]; wheel.m_raycastInfo.m_suspensionLength = 0; wheel.m_rotation = 0; - updateWheelTransformsWS(wheel); + updateWheelTransform(i, true); } m_zipper_active = false; m_zipper_velocity = btScalar(0); @@ -121,6 +121,10 @@ void btKart::reset() m_time_additional_impulse = 0; m_additional_rotation = btVector3(0,0,0); m_time_additional_rotation = 0; + + // Set the brakes so that karts don't slide downhill + setAllBrakes(5.0f); + } // reset // ---------------------------------------------------------------------------- diff --git a/src/replay/replay_play.cpp b/src/replay/replay_play.cpp index 57feaf698..84a663621 100644 --- a/src/replay/replay_play.cpp +++ b/src/replay/replay_play.cpp @@ -59,9 +59,9 @@ void ReplayPlay::init() void ReplayPlay::reset() { m_next = 0; - for(unsigned int i=0; ireset(); + m_ghost_karts[i].reset(); } } // reset @@ -72,8 +72,8 @@ void ReplayPlay::reset() void ReplayPlay::update(float dt) { // First update all ghost karts - for(unsigned int i=0; iupdate(dt); + for(unsigned int i=0; i<(unsigned int)m_ghost_karts.size(); i++) + m_ghost_karts[i].update(dt); } // update @@ -82,11 +82,7 @@ void ReplayPlay::update(float dt) */ void ReplayPlay::Load() { - for(unsigned int i=0; iaddTransform(time, btTransform(q, xyz)); + m_ghost_karts[k].addTransform(time, btTransform(q, xyz)); } else { diff --git a/src/replay/replay_play.hpp b/src/replay/replay_play.hpp index c7f914dc3..f7e213e22 100644 --- a/src/replay/replay_play.hpp +++ b/src/replay/replay_play.hpp @@ -20,6 +20,7 @@ #define HEADER_REPLAY__PLAY_HPP #include "replay/replay_base.hpp" +#include "utils/ptr_vector.hpp" #include #include @@ -38,7 +39,7 @@ private: unsigned int m_next; /** All ghost karts. */ - std::vector m_ghost_karts; + PtrVector m_ghost_karts; ReplayPlay(); ~ReplayPlay();