Ghost kart replay fixes:

1. Allow saving steering, speed, suspension length

2. No more crashes when trying to replay
This commit is contained in:
Benau 2016-02-04 08:17:02 +08:00
parent 87862c27ae
commit 4cbb31b8e5
9 changed files with 136 additions and 32 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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,8 +794,10 @@ 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);
@ -805,11 +815,21 @@ void KartModel::update(float dt, float distance, float steer, float speed)
#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);

View File

@ -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);

View File

@ -47,6 +47,17 @@ protected:
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

View File

@ -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
{

View File

@ -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);
}
@ -141,9 +146,24 @@ void ReplayRecorder::update(float dt)
continue;
}
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
@ -185,7 +205,8 @@ void ReplayRecorder::Save()
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 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());

View File

@ -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;