Ghost kart replay fixes:
1. Allow saving steering, speed, suspension length 2. No more crashes when trying to replay
This commit is contained in:
parent
87862c27ae
commit
4cbb31b8e5
@ -17,6 +17,7 @@
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "karts/ghost_kart.hpp"
|
||||
#include "karts/kart_model.hpp"
|
||||
#include "modes/world.hpp"
|
||||
|
||||
#include "LinearMath/btQuaternion.h"
|
||||
@ -28,6 +29,9 @@ GhostKart::GhostKart(const std::string& ident)
|
||||
{
|
||||
m_current_transform = 0;
|
||||
m_next_event = 0;
|
||||
m_all_times.clear();
|
||||
m_all_transform.clear();
|
||||
m_all_physic_info.clear();
|
||||
} // GhostKart
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -46,7 +50,9 @@ void GhostKart::reset()
|
||||
* the previous time and transform.
|
||||
* \param
|
||||
*/
|
||||
void GhostKart::addTransform(float time, const btTransform &trans)
|
||||
void GhostKart::addTransform(float time,
|
||||
const btTransform &trans,
|
||||
const ReplayBase::PhysicInfo &pi)
|
||||
{
|
||||
// FIXME: for now avoid that transforms for the same time are set
|
||||
// twice (to avoid division by zero in update). This should be
|
||||
@ -55,6 +61,19 @@ void GhostKart::addTransform(float time, const btTransform &trans)
|
||||
return;
|
||||
m_all_times.push_back(time);
|
||||
m_all_transform.push_back(trans);
|
||||
m_all_physic_info.push_back(pi);
|
||||
|
||||
// Use first frame of replay to calculate default suspension
|
||||
if (m_all_physic_info.size() == 1)
|
||||
{
|
||||
float f = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
f += m_all_physic_info[0].m_suspension_length[i];
|
||||
m_graphical_y_offset = -f / 4 + getKartModel()->getLowestPoint();
|
||||
m_kart_model
|
||||
->setDefaultSuspension();
|
||||
}
|
||||
|
||||
} // addTransform
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -114,5 +133,14 @@ void GhostKart::updateTransform(float t, float dt)
|
||||
.getRotation(),
|
||||
f);
|
||||
setRotation(q);
|
||||
Moveable::updateGraphics(dt, Vec3(0,0,0), btQuaternion(0, 0, 0, 1));
|
||||
|
||||
Vec3 center_shift(0, 0, 0);
|
||||
center_shift.setY(m_graphical_y_offset);
|
||||
center_shift = getTrans().getBasis() * center_shift;
|
||||
|
||||
Moveable::updateGraphics(dt, center_shift, btQuaternion(0, 0, 0, 1));
|
||||
getKartModel()->update(dt, dt*(m_all_physic_info[m_current_transform].m_speed),
|
||||
m_all_physic_info[m_current_transform].m_steer,
|
||||
m_all_physic_info[m_current_transform].m_speed,
|
||||
m_current_transform);
|
||||
} // update
|
||||
|
@ -42,6 +42,8 @@ private:
|
||||
/** The transforms to assume at the corresponding time in m_all_times. */
|
||||
std::vector<btTransform> m_all_transform;
|
||||
|
||||
std::vector<ReplayBase::PhysicInfo> m_all_physic_info;
|
||||
|
||||
std::vector<ReplayBase::KartReplayEvent> m_replay_events;
|
||||
|
||||
/** Pointer to the last index in m_all_times that is smaller than
|
||||
@ -55,7 +57,9 @@ private:
|
||||
public:
|
||||
GhostKart(const std::string& ident);
|
||||
virtual void update (float dt);
|
||||
virtual void addTransform(float time, const btTransform &trans);
|
||||
virtual void addTransform(float time,
|
||||
const btTransform &trans,
|
||||
const ReplayBase::PhysicInfo &pi);
|
||||
virtual void addReplayEvent(const ReplayBase::KartReplayEvent &kre);
|
||||
virtual void reset();
|
||||
// ------------------------------------------------------------------------
|
||||
@ -68,6 +72,8 @@ public:
|
||||
// Not needed to create any physics for a ghost kart.
|
||||
virtual void createPhysics() {}
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
const float& getSuspensionLength(int index, int wheel) const
|
||||
{ return m_all_physic_info[index].m_suspension_length[wheel]; }
|
||||
// ------------------------------------------------------------------------
|
||||
}; // GhostKart
|
||||
#endif
|
||||
|
@ -64,6 +64,10 @@ class TerrainInfo;
|
||||
class Kart : public AbstractKart
|
||||
{
|
||||
friend class Skidding;
|
||||
protected:
|
||||
/** Offset of the graphical kart chassis from the physical chassis. */
|
||||
float m_graphical_y_offset;
|
||||
|
||||
private:
|
||||
/** Handles speed increase and capping due to powerup, terrain, ... */
|
||||
MaxSpeed *m_max_speed;
|
||||
@ -106,9 +110,6 @@ private:
|
||||
* new lap is triggered. */
|
||||
Vec3 m_xyz_front;
|
||||
|
||||
/** Offset of the graphical kart chassis from the physical chassis. */
|
||||
float m_graphical_y_offset;
|
||||
|
||||
/** True if the kart wins, false otherwise. */
|
||||
bool m_race_result;
|
||||
|
||||
|
@ -769,6 +769,14 @@ void KartModel::OnAnimationEnd(scene::IAnimatedMeshSceneNode *node)
|
||||
// ----------------------------------------------------------------------------
|
||||
void KartModel::setDefaultSuspension()
|
||||
{
|
||||
GhostKart* gk = dynamic_cast<GhostKart*>(m_kart);
|
||||
if (gk)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
m_default_physics_suspension[i] = gk->getSuspensionLength(0, i);
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i=0; i<m_kart->getVehicle()->getNumWheels(); i++)
|
||||
{
|
||||
const btWheelInfo &wi = m_kart->getVehicle()->getWheelInfo(i);
|
||||
@ -786,30 +794,42 @@ void KartModel::setDefaultSuspension()
|
||||
* \param suspension Suspension height for all four wheels.
|
||||
* \param speed The speed of the kart in meters/sec, used for the
|
||||
* speed-weighted objects' animations
|
||||
* \param gt_replay_index The index to get replay data, used by ghost kart
|
||||
*/
|
||||
void KartModel::update(float dt, float distance, float steer, float speed)
|
||||
void KartModel::update(float dt, float distance, float steer, float speed,
|
||||
int gt_replay_index)
|
||||
{
|
||||
core::vector3df wheel_steer(0, steer*30.0f, 0);
|
||||
|
||||
for(unsigned int i=0; i<4; i++)
|
||||
{
|
||||
if (!m_kart || !m_wheel_node[i]) continue;
|
||||
if (!m_kart || !m_wheel_node[i]) continue;
|
||||
#ifdef DEBUG
|
||||
if (UserConfigParams::m_physics_debug &&
|
||||
!dynamic_cast<GhostKart*>(m_kart) )
|
||||
{
|
||||
const btWheelInfo &wi = m_kart->getVehicle()->getWheelInfo(i);
|
||||
// Make wheels that are not touching the ground invisible
|
||||
m_wheel_node[i]->setVisible(wi.m_raycastInfo.m_isInContact);
|
||||
}
|
||||
if (UserConfigParams::m_physics_debug &&
|
||||
!dynamic_cast<GhostKart*>(m_kart) )
|
||||
{
|
||||
const btWheelInfo &wi = m_kart->getVehicle()->getWheelInfo(i);
|
||||
// Make wheels that are not touching the ground invisible
|
||||
m_wheel_node[i]->setVisible(wi.m_raycastInfo.m_isInContact);
|
||||
}
|
||||
#endif
|
||||
core::vector3df pos = m_wheel_graphics_position[i].toIrrVector();
|
||||
|
||||
const btWheelInfo &wi = m_kart->getVehicle()->getWheelInfo(i);
|
||||
float suspension_length = 0.0f;
|
||||
GhostKart* gk = dynamic_cast<GhostKart*>(m_kart);
|
||||
if (gk && gt_replay_index != -1)
|
||||
{
|
||||
suspension_length = gk->getSuspensionLength(gt_replay_index, i);
|
||||
}
|
||||
else if (!gk)
|
||||
{
|
||||
suspension_length = m_kart->getVehicle()->getWheelInfo(i).
|
||||
m_raycastInfo.m_suspensionLength;
|
||||
}
|
||||
|
||||
// Check documentation of Kart::updateGraphics for the following line
|
||||
pos.Y += m_default_physics_suspension[i]
|
||||
- wi.m_raycastInfo.m_suspensionLength
|
||||
- suspension_length
|
||||
- m_kart_lowest_point;
|
||||
m_wheel_node[i]->setPosition(pos);
|
||||
|
||||
|
@ -237,8 +237,8 @@ public:
|
||||
void loadInfo(const XMLNode &node);
|
||||
bool loadModels(const KartProperties &kart_properties);
|
||||
void setDefaultSuspension();
|
||||
void update(float dt, float distance, float steer,
|
||||
float speed);
|
||||
void update(float dt, float distance, float steer, float speed,
|
||||
int gt_replay_index = -1);
|
||||
void finishedRace();
|
||||
scene::ISceneNode*
|
||||
attachModel(bool animatedModels, bool always_animated);
|
||||
|
@ -42,11 +42,22 @@ protected:
|
||||
struct TransformEvent
|
||||
{
|
||||
/** Time at which this event happens. */
|
||||
float m_time;
|
||||
float m_time;
|
||||
/** The transform at a certain time. */
|
||||
btTransform m_transform;
|
||||
btTransform m_transform;
|
||||
}; // TransformEvent
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
struct PhysicInfo
|
||||
{
|
||||
/** The speed at a certain time. */
|
||||
float m_speed;
|
||||
/** The steering at a certain time. */
|
||||
float m_steer;
|
||||
/** The suspension length of 4 wheels at a certain time. */
|
||||
float m_suspension_length[4];
|
||||
}; // PhysicInfo
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Records all other events - atm start and end skidding. */
|
||||
struct KartReplayEvent
|
||||
|
@ -172,20 +172,28 @@ void ReplayPlay::readKartData(FILE *fd, char *next_line)
|
||||
for(unsigned int i=0; i<size; i++)
|
||||
{
|
||||
fgets(s, 1023, fd);
|
||||
float x, y, z, rx, ry, rz, rw, time;
|
||||
float x, y, z, rx, ry, rz, rw, time, speed, steer, w1, w2, w3, w4;
|
||||
|
||||
// Check for EV_TRANSFORM event:
|
||||
// -----------------------------
|
||||
if(sscanf(s, "%f %f %f %f %f %f %f %f\n",
|
||||
if(sscanf(s, "%f %f %f %f %f %f %f %f %f %f %f %f %f %f\n",
|
||||
&time,
|
||||
&x, &y, &z,
|
||||
&rx, &ry, &rz, &rw
|
||||
)==8)
|
||||
&rx, &ry, &rz, &rw,
|
||||
&speed, &steer, &w1, &w2, &w3, &w4
|
||||
)==14)
|
||||
{
|
||||
btQuaternion q(rx, ry, rz, rw);
|
||||
btVector3 xyz(x, y, z);
|
||||
PhysicInfo pi = {0};
|
||||
pi.m_speed = speed;
|
||||
pi.m_steer = steer;
|
||||
pi.m_suspension_length[0] = w1;
|
||||
pi.m_suspension_length[1] = w2;
|
||||
pi.m_suspension_length[2] = w3;
|
||||
pi.m_suspension_length[3] = w4;
|
||||
m_ghost_karts[m_ghost_karts.size()-1].addTransform(time,
|
||||
btTransform(q, xyz));
|
||||
btTransform(q, xyz), pi);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "io/file_manager.hpp"
|
||||
#include "karts/ghost_kart.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "physics/btKart.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
|
||||
@ -43,6 +44,7 @@ ReplayRecorder::ReplayRecorder()
|
||||
ReplayRecorder::~ReplayRecorder()
|
||||
{
|
||||
m_transform_events.clear();
|
||||
m_physic_info.clear();
|
||||
} // ~Replay
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -52,7 +54,9 @@ ReplayRecorder::~ReplayRecorder()
|
||||
void ReplayRecorder::init()
|
||||
{
|
||||
m_transform_events.clear();
|
||||
m_physic_info.clear();
|
||||
m_transform_events.resize(race_manager->getNumberOfKarts());
|
||||
m_physic_info.resize(race_manager->getNumberOfKarts());
|
||||
m_skid_control.resize(race_manager->getNumberOfKarts());
|
||||
m_kart_replay_event.resize(race_manager->getNumberOfKarts());
|
||||
unsigned int max_frames = (unsigned int)( stk_config->m_replay_max_time
|
||||
@ -60,6 +64,7 @@ void ReplayRecorder::init()
|
||||
for(unsigned int i=0; i<race_manager->getNumberOfKarts(); i++)
|
||||
{
|
||||
m_transform_events[i].resize(max_frames);
|
||||
m_physic_info[i].resize(max_frames);
|
||||
// Rather arbitraritly sized, it will be added with push_back
|
||||
m_kart_replay_event[i].reserve(500);
|
||||
}
|
||||
@ -140,10 +145,25 @@ void ReplayRecorder::update(float dt)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
TransformEvent *p = &(m_transform_events[i][m_count_transforms[i]-1]);
|
||||
p->m_time = World::getWorld()->getTime();
|
||||
TransformEvent *p = &(m_transform_events[i][m_count_transforms[i]-1]);
|
||||
PhysicInfo *q = &(m_physic_info[i][m_count_transforms[i]-1]);
|
||||
p->m_time = World::getWorld()->getTime();
|
||||
p->m_transform.setOrigin(kart->getXYZ());
|
||||
p->m_transform.setRotation(kart->getVisualRotation());
|
||||
|
||||
q->m_speed = kart->getSpeed();
|
||||
q->m_steer = kart->getSteerPercent();
|
||||
const int num_wheels = kart->getVehicle()->getNumWheels();
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
if (j > num_wheels || num_wheels == 0)
|
||||
q->m_suspension_length[j] = 0.0f;
|
||||
else
|
||||
{
|
||||
q->m_suspension_length[j] = kart->getVehicle()
|
||||
->getWheelInfo(j).m_raycastInfo.m_suspensionLength;
|
||||
}
|
||||
}
|
||||
} // for i
|
||||
} // update
|
||||
|
||||
@ -184,8 +204,9 @@ void ReplayRecorder::Save()
|
||||
m_count_transforms[k]);
|
||||
for(unsigned int i=0; i<num_transforms; i++)
|
||||
{
|
||||
const TransformEvent *p=&(m_transform_events[k][i]);
|
||||
fprintf(fd, "%f %f %f %f %f %f %f %f\n",
|
||||
const TransformEvent *p = &(m_transform_events[k][i]);
|
||||
const PhysicInfo *q = &(m_physic_info[k][i]);
|
||||
fprintf(fd, "%f %f %f %f %f %f %f %f %f %f %f %f %f %f\n",
|
||||
p->m_time,
|
||||
p->m_transform.getOrigin().getX(),
|
||||
p->m_transform.getOrigin().getY(),
|
||||
@ -193,7 +214,13 @@ void ReplayRecorder::Save()
|
||||
p->m_transform.getRotation().getX(),
|
||||
p->m_transform.getRotation().getY(),
|
||||
p->m_transform.getRotation().getZ(),
|
||||
p->m_transform.getRotation().getW()
|
||||
p->m_transform.getRotation().getW(),
|
||||
q->m_speed,
|
||||
q->m_steer,
|
||||
q->m_suspension_length[0],
|
||||
q->m_suspension_length[1],
|
||||
q->m_suspension_length[2],
|
||||
q->m_suspension_length[3]
|
||||
);
|
||||
} // for i
|
||||
fprintf(fd, "events: %d\n", (int)m_kart_replay_event[k].size());
|
||||
|
@ -34,6 +34,9 @@ private:
|
||||
/** A separate vector of Replay Events for all transforms. */
|
||||
std::vector< std::vector<TransformEvent> > m_transform_events;
|
||||
|
||||
/** A separate vector of Replay Events for all transforms. */
|
||||
std::vector< std::vector<PhysicInfo> > m_physic_info;
|
||||
|
||||
/** Time at which a transform was saved for the last time. */
|
||||
std::vector<float> m_last_saved_time;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user