Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/Common/GameEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ class GameEngine : public SubsystemInterface

Bool m_quitting; ///< true when we need to quit the game
Bool m_isActive; ///< app has OS focus.

public:
Real getLogicTimeAccumulator() const { return m_logicTimeAccumulator; }
};

inline void GameEngine::setQuitting( Bool quitting ) { m_quitting = quitting; }
Expand Down
9 changes: 9 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/GameClient/Drawable.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class DrawModule;
class ClientUpdateModule;
class View;
class Locomotor;
class ProjectileUpdateInterface;
class Anim2D;
class Shadow;
class ModuleInfo;
Expand Down Expand Up @@ -652,6 +653,7 @@ class Drawable : public Thing,
private:

const Locomotor* getLocomotor() const;
void applySubFrameExtrapolation(const Coord3D* velocity);

// note, these are lazily allocated!
TintEnvelope* m_selectionFlashEnvelope; ///< used for selection flash, works WITH m_colorTintEnvelope
Expand Down Expand Up @@ -711,6 +713,7 @@ class Drawable : public Thing,

Matrix3D m_instance; ///< The instance matrix that holds the initial/default position & orientation
Real m_instanceScale; ///< the uniform scale factor applied to the instance matrix before it is sent to W3D.
Matrix3D m_visualExtrapolationMtx; ///< Decoupled visual glide matrix

DrawableInfo m_drawableInfo; ///< structure pointed to by W3D render objects so they know which drawable they belong to.

Expand All @@ -730,11 +733,17 @@ class Drawable : public Thing,
Bool m_hiddenByStealth; ///< drawable is hidden due to stealth
Bool m_instanceIsIdentity; ///< If true, instance matrix can be skipped
Bool m_drawableFullyObscuredByShroud; ///<drawable is hidden by shroud/fog
Bool m_useExtrapolation; ///< True if currently gliding
const Coord3D* m_logicVelocityPtr; ///< Cached pointer to logic velocity for smoothing
Bool m_ambientSoundEnabled;
Bool m_ambientSoundEnabledFromScript;

Bool m_receivesDynamicLights;

public:
void setLogicVelocity(const Coord3D* velocity);
static void clearLogicVelocity(Object* obj);

#ifdef DIRTY_CONDITION_FLAGS
Bool m_isModelDirty; ///< if true, must call replaceModelConditionState() before drawing or accessing drawmodule info
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class DumbProjectileBehavior : public UpdateModule, public ProjectileUpdateInter

// UpdateModuleInterface
virtual UpdateSleepTime update() override;
virtual void onDelete() override;
virtual ProjectileUpdateInterface* getProjectileUpdateInterface() override { return this; }

// ProjectileUpdateInterface
Expand All @@ -94,6 +95,7 @@ class DumbProjectileBehavior : public UpdateModule, public ProjectileUpdateInter
virtual ObjectID projectileGetLauncherID() const override { return m_launcherID; }
virtual void setFramesTillCountermeasureDiversionOccurs( UnsignedInt frames ) override {}
virtual void projectileNowJammed() override {}
virtual const Coord3D* getProjectileLogicVelocity() const override { return &m_logicStepVelocity; }

protected:

Expand All @@ -109,6 +111,7 @@ class DumbProjectileBehavior : public UpdateModule, public ProjectileUpdateInter
VecCoord3D m_flightPath; ///< The frame by frame flight path in a Bezier curve
Coord3D m_flightPathStart; ///< where flight path started (in case we must regen it)
Coord3D m_flightPathEnd; ///< where flight path ends (in case we must regen it)
Coord3D m_logicStepVelocity; ///< Logic frame velocity vector
Real m_flightPathSpeed; ///< flight path speed (in case we must regen it)
Int m_flightPathSegments; ///< number of segments in the flightpath (in case we must regen it)
Int m_currentFlightPathStep; ///< Our current index in the flight path vector. Quicker than popping off.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class NeutronMissileUpdate : public UpdateModule,
virtual const Coord3D *getVelocity() const { return &m_vel; } ///< get current velocity
virtual void setFramesTillCountermeasureDiversionOccurs( UnsignedInt frames ) override {}
virtual void projectileNowJammed() override {}
virtual const Coord3D* getProjectileLogicVelocity() const override { return &m_logicStepVelocity; }

virtual UpdateSleepTime update() override;
virtual void onDelete() override;
Expand All @@ -119,6 +120,7 @@ class NeutronMissileUpdate : public UpdateModule,

Coord3D m_accel;
Coord3D m_vel;
Coord3D m_logicStepVelocity; ///< Logic frame velocity vector

UnsignedInt m_stateTimestamp; ///< time of state change
Bool m_isLaunched;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ class ProjectileUpdateInterface
virtual Bool projectileHandleCollision(Object *other) = 0;
virtual void setFramesTillCountermeasureDiversionOccurs( UnsignedInt frames ) = 0; ///< Number of frames till missile diverts to countermeasures.
virtual void projectileNowJammed() = 0;
virtual const Coord3D* getProjectileLogicVelocity() const { return nullptr; }
};

//-------------------------------------------------------------------------------------------------
Expand Down
40 changes: 40 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/GameClient/Drawable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "Common/DrawModule.h"
#include "Common/FramePacer.h"
#include "Common/GameAudio.h"
#include "Common/GameEngine.h"
#include "Common/GameLOD.h"
#include "Common/GameState.h"
#include "Common/GameUtility.h"
Expand All @@ -61,6 +62,7 @@
#include "GameLogic/Module/StealthUpdate.h"
#include "GameLogic/Module/StickyBombUpdate.h"
#include "GameLogic/Module/BattlePlanUpdate.h"
#include "GameLogic/Module/UpdateModule.h"
#include "GameLogic/ScriptEngine.h"
#include "GameLogic/Weapon.h"

Expand Down Expand Up @@ -412,6 +414,9 @@ Drawable::Drawable( const ThingTemplate *thingTemplate, DrawableStatusBits statu
//Real scaleFuzziness = thingTemplate->getInstanceScaleFuzziness();
//Real fuzzyScale = ( 1.0f + GameClientRandomValueReal( -scaleFuzziness, scaleFuzziness ));
m_instanceScale = thingTemplate->getAssetScale();// * fuzzyScale;
m_useExtrapolation = FALSE;
m_visualExtrapolationMtx.Make_Identity();
m_logicVelocityPtr = nullptr;

// initially not bound to an object
m_object = nullptr;
Expand Down Expand Up @@ -1149,6 +1154,11 @@ void Drawable::updateDrawable()
UnsignedInt now = TheGameLogic->getFrame();
Object *obj = getObject();

if (m_logicVelocityPtr != nullptr)
{
applySubFrameExtrapolation(m_logicVelocityPtr);
}

{
for (ClientUpdateModule** cu = getClientUpdateModules(); cu && *cu; ++cu)
{
Expand Down Expand Up @@ -4248,6 +4258,11 @@ void Drawable::setInstanceMatrix( const Matrix3D *instance )
//-------------------------------------------------------------------------------------------------
const Matrix3D *Drawable::getTransformMatrix() const
{
if (m_useExtrapolation)
{
return &m_visualExtrapolationMtx;
}

const Object *obj = getObject();

if (obj)
Expand Down Expand Up @@ -5642,4 +5657,29 @@ void TintEnvelope::loadPostProcess()
{

}
void Drawable::setLogicVelocity(const Coord3D* velocity)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is going into the right direction and this ideally becomes applicable to ALL drawable, not just projectiles. I am not a fan of this hand holding of requiring external users to set velocities. It makes caller code more complicated.

I suggest to try implement this more generic so that any movements are interpolated between real logic frames. To do that, try to have a recycled history of 3 to 5 transforms and then extrapolate them. This could work alright even with accelleration and braking. Maybe make the history length configurable per drawable, because for objects that have no accelleration, 2 points would be enough for velocity.

{
m_logicVelocityPtr = velocity;
}

void Drawable::clearLogicVelocity(Object* obj)
{
if (obj && obj->getDrawable())
obj->getDrawable()->setLogicVelocity(nullptr);
}

void Drawable::applySubFrameExtrapolation(const Coord3D* v)
{
Real alpha = TheGameEngine->getLogicTimeAccumulator() * TheFramePacer->getActualLogicTimeScaleFps();

if (v && alpha > 0.0f && m_object)
{
m_visualExtrapolationMtx = *m_object->getTransformMatrix();
m_visualExtrapolationMtx.Adjust_Translation(Vector3(v->x, v->y, v->z) * (alpha > 1.0f ? 1.0f : alpha));
m_useExtrapolation = TRUE;
}
else
{
m_useExtrapolation = FALSE;
}
}
Comment thread
githubawn marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ DumbProjectileBehavior::DumbProjectileBehavior( Thing *thing, const ModuleData*
m_extraBonusFlags = 0;

m_hasDetonated = FALSE;
m_logicStepVelocity.zero();
}

//-------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -395,6 +396,8 @@ void DumbProjectileBehavior::projectileFireAtObjectOrPosition( const Object *vic
return;
}
m_currentFlightPathStep = 0;// We are at the first point, because the launching put us there
if (projectile->getDrawable())
projectile->getDrawable()->setLogicVelocity(&m_logicStepVelocity);
}

//-------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -572,13 +575,20 @@ void DumbProjectileBehavior::detonate()

}

void DumbProjectileBehavior::onDelete()
{
Drawable::clearLogicVelocity(getObject());
UpdateModule::onDelete();
}

//-------------------------------------------------------------------------------------------------
/**
* Simulate one frame of a missile's behavior
*/
UpdateSleepTime DumbProjectileBehavior::update()
{
const DumbProjectileBehaviorModuleData* d = getDumbProjectileBehaviorModuleData();
m_logicStepVelocity.zero();

if (m_lifespanFrame != 0 && TheGameLogic->getFrame() >= m_lifespanFrame)
{
Expand Down Expand Up @@ -714,6 +724,16 @@ UpdateSleepTime DumbProjectileBehavior::update()

++m_currentFlightPathStep;

if (m_currentFlightPathStep < (Int)m_flightPath.size())
{
m_logicStepVelocity = m_flightPath[m_currentFlightPathStep];
m_logicStepVelocity.sub( &flightStep ); // flightStep is currentPos
}
else
{
m_logicStepVelocity.zero();
}

return UPDATE_SLEEP_NONE;//This no longer flys with physics, so it needs to not sleep
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ NeutronMissileUpdate::NeutronMissileUpdate( Thing *thing, const ModuleData* modu
m_frameAtLaunch = 0;

m_exhaustSysTmpl = nullptr;
m_logicStepVelocity.zero();

}

Expand All @@ -137,6 +138,8 @@ NeutronMissileUpdate::~NeutronMissileUpdate()
//-------------------------------------------------------------------------------------------------
void NeutronMissileUpdate::onDelete()
{
Drawable::clearLogicVelocity(getObject());
UpdateModule::onDelete();
}

//-------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -243,6 +246,8 @@ void NeutronMissileUpdate::doLaunch()
getObject()->getExperienceTracker()->setExperienceSink( m_launcherID );

m_isLaunched = true;
if (getObject()->getDrawable())
getObject()->getDrawable()->setLogicVelocity(&m_logicStepVelocity);

if (getNeutronMissileUpdateModuleData()->m_targetFromDirectlyAbove)
m_reachedIntermediatePos = false;
Expand All @@ -262,6 +267,8 @@ void NeutronMissileUpdate::doLaunch()

getObject()->setPosition( &pos );

m_logicStepVelocity = m_vel;

FXList::doFXObj(getNeutronMissileUpdateModuleData()->m_ignitionFX, getObject());

if (m_exhaustSysTmpl != nullptr)
Expand Down Expand Up @@ -423,6 +430,7 @@ void NeutronMissileUpdate::doAttack()
getObject()->setTransformMatrix( &mx );
getObject()->setPosition( &pos );

m_logicStepVelocity = m_vel;
}

//-------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -526,6 +534,12 @@ UpdateSleepTime NeutronMissileUpdate::update()
normal.z = -1.0f;
getObject()->onCollide(nullptr, getObject()->getPosition(), &normal);
}

if (m_state == DEAD)
{
m_logicStepVelocity.zero();
}

return UPDATE_SLEEP_NONE;
}

Expand Down
Loading