Initial work on dynamic physics object rewind

This commit is contained in:
Benau 2018-07-12 09:05:26 +08:00
parent 7e2d25d4a9
commit 99659e8021
7 changed files with 100 additions and 50 deletions

View File

@ -27,8 +27,6 @@
#include "network/rewind_info.hpp"
#include "physics/physics.hpp"
#include "race/history.hpp"
#include "tracks/track.hpp"
#include "tracks/track_object_manager.hpp"
#include "utils/log.hpp"
#include "utils/profiler.hpp"
@ -292,8 +290,6 @@ void RewindManager::playEventsTill(int world_ticks, int *ticks)
void RewindManager::rewindTo(int rewind_ticks, int now_ticks)
{
assert(!m_is_rewinding);
// TODO Do it properly for track objects like soccer ball
Track::getCurrentTrack()->getTrackObjectManager()->removeForRewind();
bool is_history = history->replayHistory();
history->setReplayHistory(false);
@ -385,6 +381,5 @@ void RewindManager::rewindTo(int rewind_ticks, int now_ticks)
}
history->setReplayHistory(is_history);
Track::getCurrentTrack()->getTrackObjectManager()->addForRewind();
m_is_rewinding = false;
} // rewindTo

View File

@ -23,10 +23,11 @@
/** Constructor. It will add this object to the list of all rewindable
* objects in the rewind manager.
*/
Rewinder::Rewinder(bool can_be_destroyed)
Rewinder::Rewinder(bool can_be_destroyed, bool auto_add)
{
m_can_be_destroyed = can_be_destroyed;
RewindManager::get()->addRewinder(this);
m_can_be_destroyed = can_be_destroyed;
if (auto_add)
add();
} // Rewinder
// ----------------------------------------------------------------------------
@ -35,3 +36,9 @@ Rewinder::Rewinder(bool can_be_destroyed)
Rewinder::~Rewinder()
{
} // ~Rewinder
// ----------------------------------------------------------------------------
void Rewinder::add()
{
RewindManager::get()->addRewinder(this);
} // Rewinder

View File

@ -25,6 +25,8 @@ class BareNetworkString;
class Rewinder
{
protected:
void add();
private:
/** True if this object can be destroyed, i.e. if this object is a 'stand
* alone' (i.e. not used in inheritance). If the object is used in
@ -34,7 +36,7 @@ private:
bool m_can_be_destroyed;
public:
Rewinder(bool can_be_destroyed);
Rewinder(bool can_be_destroyed, bool auto_add = true);
virtual ~Rewinder();
/** Called before a rewind. Is used to save the previous position of an
@ -58,30 +60,30 @@ public:
*/
virtual void undoEvent(BareNetworkString *buffer) = 0;
/** Called when an event needs to be replayed. This is called during
/** Called when an event needs to be replayed. This is called during
* rewind, i.e. when going forward in time again.
*/
virtual void rewindToEvent(BareNetworkString *buffer) = 0;
/** Called when a state needs to be replayed. This is called during
/** Called when a state needs to be replayed. This is called during
* rewind, i.e. when going forward in time again, and only for confirmed
* states.
*/
virtual void restoreState(BareNetworkString *buffer, int count) = 0;
/** Undo the effects of the given state, but do not rewind to that
* state (which is done by rewindTo). This is called while going
* backwards for rewinding - all stored events will get an 'undo' call.
*/
virtual void undoState(BareNetworkString *buffer) = 0;
/** Undo the effects of the given state, but do not rewind to that
* state (which is done by rewindTo). This is called while going
* backwards for rewinding - all stored events will get an 'undo' call.
*/
virtual void undoState(BareNetworkString *buffer) = 0;
// -------------------------------------------------------------------------
/** Nothing to do here. */
virtual void reset() {};
// -------------------------------------------------------------------------
/** True if this rewinder can be destroyed. Karts can not be destroyed,
* cakes can. This is used by the RewindManager in reset. */
bool canBeDestroyed() const { return m_can_be_destroyed; }
// -------------------------------------------------------------------------
/** Nothing to do here. */
virtual void reset() {}
// -------------------------------------------------------------------------
/** True if this rewinder can be destroyed. Karts can not be destroyed,
* cakes can. This is used by the RewindManager in reset. */
bool canBeDestroyed() const { return m_can_be_destroyed; }
// -------------------------------------------------------------------------
virtual std::function<void()> getLocalStateRestoreFunction()
{ return nullptr; }

View File

@ -28,6 +28,7 @@
#include "io/xml_node.hpp"
#include "physics/physics.hpp"
#include "physics/triangle_mesh.hpp"
#include "network/network_string.hpp"
#include "tracks/track.hpp"
#include "tracks/track_object.hpp"
#include "utils/constants.hpp"
@ -134,6 +135,7 @@ PhysicalObject* PhysicalObject::fromXML(bool is_dynamic,
PhysicalObject::PhysicalObject(bool is_dynamic,
const PhysicalObject::Settings& settings,
TrackObject* object)
: Rewinder(false/*can_be_destroyed*/, false/*auto_add*/)
{
m_shape = NULL;
m_body = NULL;
@ -166,6 +168,7 @@ PhysicalObject::PhysicalObject(bool is_dynamic,
m_current_transform.setOrigin(Vec3());
m_current_transform.setRotation(
btQuaternion(0.0f, 0.0f, 0.0f, 1.0f));
m_previous_transform = m_current_transform;
m_body_added = false;
@ -773,5 +776,53 @@ void PhysicalObject::hit(const Material *m, const Vec3 &normal)
} // hit
// ----------------------------------------------------------------------------
/* EOF */
void PhysicalObject::addForRewind()
{
Rewinder::add();
} // addForRewind
// ----------------------------------------------------------------------------
void PhysicalObject::saveTransform()
{
} // saveTransform
// ----------------------------------------------------------------------------
void PhysicalObject::computeError()
{
} // computeError
// ----------------------------------------------------------------------------
BareNetworkString* PhysicalObject::saveState()
{
BareNetworkString *buffer = new BareNetworkString();
buffer->add(m_current_transform.getOrigin());
buffer->add(m_current_transform.getRotation());
buffer->add(m_body->getLinearVelocity());
buffer->add(m_body->getAngularVelocity());
return buffer;
} // saveState
// ----------------------------------------------------------------------------
void PhysicalObject::restoreState(BareNetworkString *buffer, int count)
{
btTransform t;
t.setOrigin(buffer->getVec3());
t.setRotation(buffer->getQuat());
m_body->setLinearVelocity(buffer->getVec3());
m_body->setAngularVelocity(buffer->getVec3());
m_body->proceedToTransform(t);
} // restoreState
// ----------------------------------------------------------------------------
std::function<void()> PhysicalObject::getLocalStateRestoreFunction()
{
btTransform t = m_current_transform;
Vec3 lv = m_body->getLinearVelocity();
Vec3 av = m_body->getAngularVelocity();
return [t, lv, av, this]()
{
m_body->setLinearVelocity(lv);
m_body->setAngularVelocity(av);
m_body->proceedToTransform(t);
};
} // getLocalStateRestoreFunction

View File

@ -23,6 +23,7 @@
#include "btBulletDynamicsCommon.h"
#include "network/rewinder.hpp"
#include "physics/user_pointer.hpp"
#include "utils/vec3.hpp"
#include "utils/leak_check.hpp"
@ -35,7 +36,7 @@ class XMLNode;
/**
* \ingroup physics
*/
class PhysicalObject
class PhysicalObject : public Rewinder
{
public:
/** The supported collision shapes. */
@ -141,6 +142,8 @@ private:
* world transform. */
btTransform m_current_transform;
btTransform m_previous_transform;
/** The mesh might not have the same center as bullet does. This
* offset is used to offset the location of the graphical mesh
* so that the graphics are aligned with the bullet collision shape. */
@ -269,6 +272,15 @@ public:
/** @} */
/** @} */
void addForRewind();
virtual void saveTransform();
virtual void computeError();
virtual BareNetworkString* saveState();
virtual void undoEvent(BareNetworkString *buffer) {}
virtual void rewindToEvent(BareNetworkString *buffer) {}
virtual void restoreState(BareNetworkString *buffer, int count);
virtual void undoState(BareNetworkString *buffer) {}
virtual std::function<void()> getLocalStateRestoreFunction();
LEAK_CHECK()
}; // PhysicalObject

View File

@ -69,8 +69,14 @@ void TrackObjectManager::init()
for_var_in(TrackObject*, curr, m_all_objects)
{
curr->onWorldReady();
// onWorldReady will hide some track objects using scripting
if (curr->isEnabled() && curr->getPhysicalObject() &&
curr->getPhysicalObject()->isDynamic())
curr->getPhysicalObject()->addForRewind();
}
} // reset
} // init
// ----------------------------------------------------------------------------
/** Initialises all track objects.
*/
@ -82,6 +88,7 @@ void TrackObjectManager::reset()
curr->resetEnabled();
}
} // reset
// ----------------------------------------------------------------------------
/** returns a reference to the track object
* with a particular ID
@ -238,25 +245,3 @@ void TrackObjectManager::removeObject(TrackObject* obj)
m_all_objects.remove(obj);
delete obj;
} // removeObject
// ----------------------------------------------------------------------------
void TrackObjectManager::removeForRewind()
{
for (TrackObject* curr : m_all_objects)
{
if (curr->isEnabled() && curr->getPhysicalObject() &&
curr->getPhysicalObject()->isDynamic())
curr->getPhysicalObject()->removeBody();
}
} // removeForRewind
// ----------------------------------------------------------------------------
void TrackObjectManager::addForRewind()
{
for (TrackObject* curr : m_all_objects)
{
if (curr->isEnabled() && curr->getPhysicalObject() &&
curr->getPhysicalObject()->isDynamic())
curr->getPhysicalObject()->addBody();
}
} // addForRewind

View File

@ -76,8 +76,6 @@ public:
PtrVector<TrackObject>& getObjects() { return m_all_objects; }
const PtrVector<TrackObject>& getObjects() const { return m_all_objects; }
void removeForRewind();
void addForRewind();
}; // class TrackObjectManager