746 lines
18 KiB
C++
746 lines
18 KiB
C++
// Copyright (C) 2007 Id Software, Inc.
|
|
//
|
|
|
|
#include "../precompiled.h"
|
|
#pragma hdrstop
|
|
|
|
#if defined( _DEBUG ) && !defined( ID_REDIRECT_NEWDELETE )
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#include "Physics_Simple.h"
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
sdPhysics_Simple
|
|
|
|
===============================================================================
|
|
*/
|
|
CLASS_DECLARATION( idPhysics_Actor, sdPhysics_Simple )
|
|
END_CLASS
|
|
|
|
/*
|
|
=====================
|
|
sdSimplePhysicsNetworkData::MakeDefault
|
|
=====================
|
|
*/
|
|
void sdSimplePhysicsNetworkData::MakeDefault( void ) {
|
|
origin = vec3_origin;
|
|
velocity = vec3_zero;
|
|
orientation.x = 0.f;
|
|
orientation.y = 0.f;
|
|
orientation.z = 0.f;
|
|
angularVelocity = vec3_zero;
|
|
atRest = -2; // this will force an update straight away
|
|
locked = false;
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
sdSimplePhysicsNetworkData::Write
|
|
=====================
|
|
*/
|
|
void sdSimplePhysicsNetworkData::Write( idFile* file ) const {
|
|
file->WriteVec3( origin );
|
|
file->WriteVec3( velocity );
|
|
file->WriteCQuat( orientation );
|
|
file->WriteVec3( angularVelocity );
|
|
file->WriteInt( atRest );
|
|
file->WriteBool( locked );
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
sdSimplePhysicsNetworkData::Read
|
|
=====================
|
|
*/
|
|
void sdSimplePhysicsNetworkData::Read( idFile* file ) {
|
|
file->ReadVec3( origin );
|
|
file->ReadVec3( velocity );
|
|
file->ReadCQuat( orientation );
|
|
file->ReadVec3( angularVelocity );
|
|
file->ReadInt( atRest );
|
|
file->ReadBool( locked );
|
|
|
|
origin.FixDenormals();
|
|
velocity.FixDenormals();
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
sdSimplePhysicsBroadcastData::MakeDefault
|
|
=====================
|
|
*/
|
|
void sdSimplePhysicsBroadcastData::MakeDefault( void ) {
|
|
pushVelocity = vec3_zero;
|
|
atRest = -2; // this will force an update straight away
|
|
groundLevel = 0.f;
|
|
locked = false;
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
sdSimplePhysicsBroadcastData::Write
|
|
=====================
|
|
*/
|
|
void sdSimplePhysicsBroadcastData::Write( idFile* file ) const {
|
|
file->WriteVec3( pushVelocity );
|
|
file->WriteInt( atRest );
|
|
file->WriteFloat( groundLevel );
|
|
file->WriteBool( locked );
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
sdSimplePhysicsBroadcastData::Read
|
|
=====================
|
|
*/
|
|
void sdSimplePhysicsBroadcastData::Read( idFile* file ) {
|
|
file->ReadVec3( pushVelocity );
|
|
file->ReadInt( atRest );
|
|
file->ReadFloat( groundLevel );
|
|
file->ReadBool( locked );
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::~sdPhysics_Simple
|
|
================
|
|
*/
|
|
sdPhysics_Simple::~sdPhysics_Simple() {
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::sdPhysics_Simple
|
|
================
|
|
*/
|
|
sdPhysics_Simple::sdPhysics_Simple() {
|
|
memset( ¤t, 0, sizeof( current ) );
|
|
saved = current;
|
|
|
|
atRest = -1;
|
|
rotates = false;
|
|
locked = false;
|
|
|
|
groundLevel = gameLocal.clip.GetWorldBounds().GetMins().z;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::SetClipModel
|
|
================
|
|
*/
|
|
#define MAX_INERTIA_SCALE 10.0f
|
|
|
|
void sdPhysics_Simple::SetClipModel( idClipModel *model, const float density, int id, bool freeOld ) {
|
|
int minIndex;
|
|
idMat3 inertiaScale;
|
|
|
|
assert( self );
|
|
assert( model ); // we need a clip model
|
|
assert( density > 0.0f ); // density should be valid
|
|
|
|
if ( clipModel != NULL && clipModel != model && freeOld ) {
|
|
gameLocal.clip.DeleteClipModel( clipModel );
|
|
}
|
|
clipModel = model;
|
|
clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
|
|
|
|
if ( model->IsTraceModel() ) {
|
|
rotates = true;
|
|
|
|
// get mass properties from the trace model
|
|
clipModel->GetMassProperties( density, mass, centerOfMass, inertiaTensor );
|
|
|
|
// check whether or not the clip model has valid mass properties
|
|
if ( mass < idMath::FLT_EPSILON || FLOAT_IS_NAN( mass ) ) {
|
|
gameLocal.Warning( "sdPhysics_Simple::SetClipModel: invalid mass for entity '%s' type '%s'",
|
|
self->name.c_str(), self->GetType()->classname );
|
|
mass = 1.0f;
|
|
centerOfMass.Zero();
|
|
inertiaTensor.Identity();
|
|
}
|
|
|
|
// check whether or not the inertia tensor is balanced
|
|
minIndex = Min3Index( inertiaTensor[0][0], inertiaTensor[1][1], inertiaTensor[2][2] );
|
|
inertiaScale.Identity();
|
|
inertiaScale[0][0] = inertiaTensor[0][0] / inertiaTensor[minIndex][minIndex];
|
|
inertiaScale[1][1] = inertiaTensor[1][1] / inertiaTensor[minIndex][minIndex];
|
|
inertiaScale[2][2] = inertiaTensor[2][2] / inertiaTensor[minIndex][minIndex];
|
|
|
|
if ( inertiaScale[0][0] > MAX_INERTIA_SCALE || inertiaScale[1][1] > MAX_INERTIA_SCALE || inertiaScale[2][2] > MAX_INERTIA_SCALE ) {
|
|
gameLocal.Warning( "sdPhysics_Simple::SetClipModel: unbalanced inertia tensor for entity '%s' type '%s'",
|
|
self->name.c_str(), self->GetType()->classname );
|
|
|
|
// correct the inertia tensor by replacing it with that of a box of the same bounds as this
|
|
idTraceModel trm( clipModel->GetBounds() );
|
|
trm.GetMassProperties( density, mass, centerOfMass, inertiaTensor );
|
|
}
|
|
|
|
inverseInertiaTensor = inertiaTensor.Inverse() * ( 1.0f / 6.0f );
|
|
}
|
|
|
|
invMass = 1.0f / mass;
|
|
current.velocity.Zero();
|
|
current.angularVelocity.Zero();
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::IsAtRest
|
|
================
|
|
*/
|
|
bool sdPhysics_Simple::IsAtRest( void ) const {
|
|
return ( atRest >= 0 && gameLocal.time > atRest ) || locked;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::Evaluate
|
|
================
|
|
*/
|
|
bool sdPhysics_Simple::Evaluate( int timeStepMSec, int endTimeMSec ) {
|
|
if ( IsAtRest() ) {
|
|
current.velocity.Zero();
|
|
current.angularVelocity.Zero();
|
|
|
|
// evaluate shouldn't become active if this is at rest
|
|
self->BecomeInactive( TH_PHYSICS );
|
|
return false;
|
|
}
|
|
|
|
idVec3 oldOrigin = current.origin;
|
|
|
|
// move the critter
|
|
float timeStep = MS2SEC( timeStepMSec );
|
|
current.origin += current.velocity * timeStep;
|
|
|
|
bool rotated = false;
|
|
if ( rotates ) {
|
|
// rotation
|
|
idVec3 rotAxis = current.angularVelocity;
|
|
float angle = rotAxis.Normalize();
|
|
if ( angle > 0.00001f ) {
|
|
idRotation rotation( vec3_origin, rotAxis, -angle * timeStep );
|
|
current.axis = current.axis * rotation.ToMat3();
|
|
current.axis.OrthoNormalizeSelf();
|
|
rotated = true;
|
|
}
|
|
}
|
|
|
|
// add gravity
|
|
current.velocity += gravityVector * timeStep;
|
|
|
|
if ( -( gravityNormal * current.origin ) < groundLevel ) {
|
|
current.origin -= gravityNormal * ( ( gravityNormal * current.origin ) + groundLevel );
|
|
PutToRest();
|
|
DisableImpact();
|
|
}
|
|
|
|
if ( current.origin == oldOrigin && !rotated ) {
|
|
return false;
|
|
}
|
|
|
|
if ( clipModel ) {
|
|
clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::SetOrigin
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::SetOrigin( const idVec3 &newOrigin, int id ) {
|
|
idVec3 masterOrigin;
|
|
idMat3 masterAxis;
|
|
|
|
current.origin = newOrigin;
|
|
|
|
if ( clipModel ) {
|
|
clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::GetOrigin
|
|
================
|
|
*/
|
|
const idVec3& sdPhysics_Simple::GetOrigin( int id ) const {
|
|
return current.origin;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::SetAxis
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::SetAxis( const idMat3 &newAxis, int id ) {
|
|
current.axis = newAxis;
|
|
|
|
if ( clipModel ) {
|
|
clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::GetAxis
|
|
================
|
|
*/
|
|
const idMat3& sdPhysics_Simple::GetAxis( int id ) const {
|
|
return current.axis;
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::SetLinearVelocity
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::SetLinearVelocity( const idVec3 &newLinearVelocity, int id ) {
|
|
current.velocity = newLinearVelocity;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::GetLinearVelocity
|
|
================
|
|
*/
|
|
const idVec3& sdPhysics_Simple::GetLinearVelocity( int id ) const {
|
|
return current.velocity;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::SetAngularVelocity
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::SetAngularVelocity( const idVec3 &newAngularVelocity, int id ) {
|
|
current.angularVelocity = newAngularVelocity;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::GetAngularVelocity
|
|
================
|
|
*/
|
|
const idVec3& sdPhysics_Simple::GetAngularVelocity( int id ) const {
|
|
return current.angularVelocity;
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::SetPushed
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::SetPushed( int deltaTime ) {
|
|
// velocity with which the monster is pushed
|
|
current.pushVelocity += ( current.origin - saved.origin ) / ( deltaTime * idMath::M_MS2SEC );
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::GetPushedLinearVelocity
|
|
================
|
|
*/
|
|
const idVec3 &sdPhysics_Simple::GetPushedLinearVelocity( const int id ) const {
|
|
return current.pushVelocity;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::SaveState
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::SaveState( void ) {
|
|
saved = current;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::RestoreState
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::RestoreState( void ) {
|
|
current = saved;
|
|
|
|
clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
|
|
|
|
EvaluateContacts( CLIP_DEBUG_PARMS_ONLY );
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::SetMaster
|
|
|
|
the binding is never orientated
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::SetMaster( idEntity *master, const bool orientated ) {
|
|
return;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::UpdateTime
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::UpdateTime( int endTimeMSec ) {
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::GetTime
|
|
================
|
|
*/
|
|
int sdPhysics_Simple::GetTime( void ) const {
|
|
return gameLocal.time;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::GetImpactInfo
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const {
|
|
info->invMass = invMass;
|
|
info->invInertiaTensor.Zero();
|
|
info->position.Zero();
|
|
info->velocity = current.velocity;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::ApplyImpulse
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse ) {
|
|
if ( locked ) {
|
|
return;
|
|
}
|
|
|
|
current.velocity += impulse * invMass;
|
|
|
|
if ( rotates ) {
|
|
idVec3 angularImpulse = ( point - ( current.origin + centerOfMass * current.axis ) ).Cross( impulse );
|
|
idMat3 inverseWorldInertiaTensor = current.axis.Transpose() * inverseInertiaTensor * current.axis;
|
|
current.angularVelocity += angularImpulse * inverseInertiaTensor;
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::Translate
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::Translate( const idVec3 &translation, int id ) {
|
|
current.origin += translation;
|
|
clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::Rest
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::Rest( int time ) {
|
|
current.velocity.Zero();
|
|
current.angularVelocity.Zero();
|
|
|
|
atRest = time;
|
|
self->BecomeInactive( TH_PHYSICS );
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::PutToRest
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::PutToRest( void ) {
|
|
Rest( gameLocal.time );
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::SetComeToRest
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::SetComeToRest( bool value ) {
|
|
if ( value ) {
|
|
PutToRest();
|
|
} else {
|
|
Activate();
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::Activate
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::Activate( void ) {
|
|
if ( !locked ) {
|
|
atRest = -1;
|
|
self->BecomeActive( TH_PHYSICS );
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::SetGroundPosition
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::SetGroundPosition( const idVec3& position ) {
|
|
groundLevel = position * -gravityNormal;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::IsPushable
|
|
================
|
|
*/
|
|
bool sdPhysics_Simple::IsPushable( void ) const {
|
|
return !locked;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::EnableImpact
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::EnableImpact( void ) {
|
|
locked = false;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::DisableImpact
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::DisableImpact( void ) {
|
|
locked = true;
|
|
}
|
|
|
|
|
|
|
|
const float SIMPLE_ORIGIN_MAX = 32767.0f;
|
|
const int SIMPLE_ORIGIN_TOTAL_BITS = 24;
|
|
const int SIMPLE_ORIGIN_EXPONENT_BITS = idMath::BitsForInteger( idMath::BitsForFloat( SIMPLE_ORIGIN_MAX ) ) + 1;
|
|
const int SIMPLE_ORIGIN_MANTISSA_BITS = SIMPLE_ORIGIN_TOTAL_BITS - 1 - SIMPLE_ORIGIN_EXPONENT_BITS;
|
|
|
|
const float SIMPLE_VELOCITY_MAX = 4000;
|
|
const int SIMPLE_VELOCITY_TOTAL_BITS = 16;
|
|
const int SIMPLE_VELOCITY_EXPONENT_BITS = idMath::BitsForInteger( idMath::BitsForFloat( SIMPLE_VELOCITY_MAX ) ) + 1;
|
|
const int SIMPLE_VELOCITY_MANTISSA_BITS = SIMPLE_VELOCITY_TOTAL_BITS - 1 - SIMPLE_VELOCITY_EXPONENT_BITS;
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::CheckNetworkStateChanges
|
|
================
|
|
*/
|
|
bool sdPhysics_Simple::CheckNetworkStateChanges( networkStateMode_t mode, const sdEntityStateNetworkData& baseState ) const {
|
|
if ( mode == NSM_VISIBLE ) {
|
|
NET_GET_BASE( sdSimplePhysicsNetworkData );
|
|
|
|
if ( !baseData.origin.Compare( current.origin, 0.01f ) ) {
|
|
return true;
|
|
}
|
|
|
|
if ( !baseData.velocity.Compare( current.velocity, 0.01f ) ) {
|
|
return true;
|
|
}
|
|
|
|
if ( baseData.orientation != current.axis.ToCQuat() ) {
|
|
return true;
|
|
}
|
|
|
|
if ( !baseData.angularVelocity.Compare( current.angularVelocity, 0.01f ) ) {
|
|
}
|
|
|
|
if ( baseData.atRest != atRest ) {
|
|
return true;
|
|
}
|
|
if ( baseData.locked != locked ) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
if ( mode == NSM_BROADCAST ) {
|
|
NET_GET_BASE( sdSimplePhysicsBroadcastData );
|
|
|
|
if ( baseData.pushVelocity != current.pushVelocity ) {
|
|
return true;
|
|
}
|
|
|
|
if ( baseData.atRest != atRest ) {
|
|
return true;
|
|
}
|
|
|
|
if ( baseData.groundLevel != groundLevel ) {
|
|
return true;
|
|
}
|
|
|
|
if ( baseData.locked != locked ) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::WriteNetworkState
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::WriteNetworkState( networkStateMode_t mode, const sdEntityStateNetworkData& baseState, sdEntityStateNetworkData& newState, idBitMsg& msg ) const {
|
|
if ( mode == NSM_VISIBLE ) {
|
|
NET_GET_STATES( sdSimplePhysicsNetworkData );
|
|
|
|
newData.origin = current.origin;
|
|
newData.velocity = current.velocity;
|
|
newData.orientation = current.axis.ToCQuat();
|
|
newData.angularVelocity = current.angularVelocity;
|
|
newData.atRest = atRest;
|
|
newData.locked = locked;
|
|
|
|
msg.WriteDeltaVector( baseData.origin, newData.origin, SIMPLE_ORIGIN_EXPONENT_BITS, SIMPLE_ORIGIN_MANTISSA_BITS );
|
|
msg.WriteDeltaVector( baseData.velocity, newData.velocity, SIMPLE_VELOCITY_EXPONENT_BITS, SIMPLE_VELOCITY_MANTISSA_BITS );
|
|
msg.WriteDeltaCQuat( baseData.orientation, newData.orientation );
|
|
msg.WriteDeltaVector( baseData.angularVelocity, newData.angularVelocity, SIMPLE_VELOCITY_EXPONENT_BITS, SIMPLE_VELOCITY_MANTISSA_BITS );
|
|
msg.WriteDeltaLong( baseData.atRest, newData.atRest );
|
|
msg.WriteBool( newData.locked );
|
|
|
|
return;
|
|
}
|
|
|
|
if ( mode == NSM_BROADCAST ) {
|
|
NET_GET_STATES( sdSimplePhysicsBroadcastData );
|
|
|
|
newData.pushVelocity = current.pushVelocity;
|
|
newData.atRest = atRest;
|
|
newData.groundLevel = groundLevel;
|
|
newData.locked = locked;
|
|
|
|
msg.WriteDeltaVector( baseData.pushVelocity, newData.pushVelocity, SIMPLE_VELOCITY_EXPONENT_BITS, SIMPLE_VELOCITY_MANTISSA_BITS );
|
|
msg.WriteDeltaLong( baseData.atRest, newData.atRest );
|
|
msg.WriteDeltaFloat( baseData.groundLevel, newData.groundLevel );
|
|
msg.WriteBool( newData.locked );
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::ApplyNetworkState
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::ApplyNetworkState( networkStateMode_t mode, const sdEntityStateNetworkData& newState ) {
|
|
traceCollection.ForceNextUpdate();
|
|
if ( mode == NSM_VISIBLE ) {
|
|
NET_GET_NEW( sdSimplePhysicsNetworkData );
|
|
|
|
current.origin = newData.origin;
|
|
current.velocity = newData.velocity;
|
|
current.axis = newData.orientation.ToMat3();
|
|
current.angularVelocity = newData.angularVelocity;
|
|
|
|
locked = newData.locked;
|
|
if ( newData.atRest != atRest ) {
|
|
if ( newData.atRest == -1 ) {
|
|
Activate();
|
|
} else {
|
|
Rest( newData.atRest );
|
|
}
|
|
}
|
|
|
|
clipModel->Link( gameLocal.clip, self, 0, current.origin, current.axis );
|
|
|
|
self->UpdateVisuals();
|
|
return;
|
|
}
|
|
|
|
if ( mode == NSM_BROADCAST ) {
|
|
NET_GET_NEW( sdSimplePhysicsBroadcastData );
|
|
|
|
current.pushVelocity = newData.pushVelocity;
|
|
groundLevel = newData.groundLevel;
|
|
locked = newData.locked;
|
|
|
|
if ( newData.atRest != atRest ) {
|
|
if ( newData.atRest == -1 ) {
|
|
Activate();
|
|
} else {
|
|
Rest( newData.atRest );
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::ReadNetworkState
|
|
================
|
|
*/
|
|
void sdPhysics_Simple::ReadNetworkState( networkStateMode_t mode, const sdEntityStateNetworkData& baseState, sdEntityStateNetworkData& newState, const idBitMsg& msg ) const {
|
|
if ( mode == NSM_VISIBLE ) {
|
|
NET_GET_STATES( sdSimplePhysicsNetworkData );
|
|
|
|
newData.origin = msg.ReadDeltaVector( baseData.origin, SIMPLE_ORIGIN_EXPONENT_BITS, SIMPLE_ORIGIN_MANTISSA_BITS );
|
|
newData.velocity = msg.ReadDeltaVector( baseData.velocity, SIMPLE_VELOCITY_EXPONENT_BITS, SIMPLE_VELOCITY_MANTISSA_BITS );
|
|
newData.orientation = msg.ReadDeltaCQuat( baseData.orientation );
|
|
newData.angularVelocity = msg.ReadDeltaVector( baseData.angularVelocity, SIMPLE_VELOCITY_EXPONENT_BITS, SIMPLE_VELOCITY_MANTISSA_BITS );
|
|
newData.atRest = msg.ReadDeltaLong( baseData.atRest );
|
|
newData.locked = msg.ReadBool();
|
|
|
|
newData.origin.FixDenormals();
|
|
newData.velocity.FixDenormals();
|
|
|
|
self->OnNewOriginRead( newData.origin );
|
|
self->OnNewAxesRead( newData.orientation.ToMat3() );
|
|
return;
|
|
}
|
|
|
|
if ( mode == NSM_BROADCAST ) {
|
|
NET_GET_STATES( sdSimplePhysicsBroadcastData );
|
|
|
|
newData.pushVelocity = msg.ReadDeltaVector( baseData.pushVelocity, SIMPLE_VELOCITY_EXPONENT_BITS, SIMPLE_VELOCITY_MANTISSA_BITS );
|
|
newData.atRest = msg.ReadDeltaLong( baseData.atRest );
|
|
newData.groundLevel = msg.ReadDeltaFloat( baseData.groundLevel );
|
|
newData.locked = msg.ReadBool();
|
|
|
|
newData.pushVelocity.FixDenormals();
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
sdPhysics_Simple::CreateNetworkStructure
|
|
================
|
|
*/
|
|
sdEntityStateNetworkData* sdPhysics_Simple::CreateNetworkStructure( networkStateMode_t mode ) const {
|
|
if ( mode == NSM_VISIBLE ) {
|
|
return new sdSimplePhysicsNetworkData();
|
|
}
|
|
if ( mode == NSM_BROADCAST ) {
|
|
return new sdSimplePhysicsBroadcastData();
|
|
}
|
|
return NULL;
|
|
}
|