Attempt to support 'light_origin' with editLights. #825

This commit is contained in:
Robert Beckebans 2023-12-04 20:15:34 +01:00
parent 288852224a
commit 563f1be37d
11 changed files with 162 additions and 53 deletions

View file

@ -4668,6 +4668,12 @@ idVec3 idEntity::GetOriginBrushOffset() const
return spawnArgs.GetVector( BRUSH_ORIGIN_KEY, "0 0 0" );
}
idVec3 idEntity::GetEditOrigin() const
{
return GetPhysics()->GetOrigin();
}
/***********************************************************************
Events

View file

@ -346,58 +346,83 @@ public:
// physics
// set a new physics object to be used by this entity
void SetPhysics( idPhysics* phys );
// get the physics object used by this entity
idPhysics* GetPhysics() const;
// restore physics pointer for save games
void RestorePhysics( idPhysics* phys );
// run the physics for this entity
bool RunPhysics();
// Interpolates the physics, used on MP clients.
void InterpolatePhysics( const float fraction );
// InterpolatePhysics actually calls evaluate, this version doesn't.
void InterpolatePhysicsOnly( const float fraction, bool updateTeam = false );
// set the origin of the physics object (relative to bindMaster if not NULL)
void SetOrigin( const idVec3& org );
// set the axis of the physics object (relative to bindMaster if not NULL)
void SetAxis( const idMat3& axis );
// use angles to set the axis of the physics object (relative to bindMaster if not NULL)
void SetAngles( const idAngles& ang );
// get the floor position underneath the physics object
bool GetFloorPos( float max_dist, idVec3& floorpos ) const;
// retrieves the transformation going from the physics origin/axis to the visual origin/axis
virtual bool GetPhysicsToVisualTransform( idVec3& origin, idMat3& axis );
// retrieves the transformation going from the physics origin/axis to the sound origin/axis
virtual bool GetPhysicsToSoundTransform( idVec3& origin, idMat3& axis );
// called from the physics object when colliding, should return true if the physics simulation should stop
virtual bool Collide( const trace_t& collision, const idVec3& velocity );
// retrieves impact information, 'ent' is the entity retrieving the info
virtual void GetImpactInfo( idEntity* ent, int id, const idVec3& point, impactInfo_t* info );
// apply an impulse to the physics object, 'ent' is the entity applying the impulse
virtual void ApplyImpulse( idEntity* ent, int id, const idVec3& point, const idVec3& impulse );
// add a force to the physics object, 'ent' is the entity adding the force
virtual void AddForce( idEntity* ent, int id, const idVec3& point, const idVec3& force );
// activate the physics object, 'ent' is the entity activating this entity
virtual void ActivatePhysics( idEntity* ent );
// returns true if the physics object is at rest
virtual bool IsAtRest() const;
// returns the time the physics object came to rest
virtual int GetRestStartTime() const;
// add a contact entity
virtual void AddContactEntity( idEntity* ent );
// remove a touching entity
virtual void RemoveContactEntity( idEntity* ent );
// damage
// returns true if this entity can be damaged from the given origin
virtual bool CanDamage( const idVec3& origin, idVec3& damagePoint ) const;
// applies damage to this entity
virtual void Damage( idEntity* inflictor, idEntity* attacker, const idVec3& dir, const char* damageDefName, const float damageScale, const int location );
// adds a damage effect like overlays, blood, sparks, debris etc.
virtual void AddDamageEffect( const trace_t& collision, const idVec3& velocity, const char* damageDefName );
// callback function for when another entity received damage from this entity. damage can be adjusted and returned to the caller.
virtual void DamageFeedback( idEntity* victim, idEntity* inflictor, int& damage );
// notifies this entity that it is in pain
virtual bool Pain( idEntity* inflictor, idEntity* attacker, int damage, const idVec3& dir, int location );
// notifies this entity that is has been killed
virtual void Killed( idEntity* inflictor, idEntity* attacker, int damage, const idVec3& dir, int location );
@ -557,8 +582,10 @@ private:
// physics
// initialize the default physics
void InitDefaultPhysics( const idVec3& origin, const idMat3& axis, const idDeclEntityDef* def );
// update visual position from the physics
void UpdateFromPhysics( bool moveBack );
// get physics timestep
virtual int GetPhysicsTimeStep() const;
@ -573,13 +600,14 @@ private:
// events
public:
// jmarshall
idVec3 GetOrigin();
idVec3 GetOrigin() const;
float DistanceTo( idEntity* ent );
float DistanceTo( const idVec3& pos ) const;
idStr GetNextKey( const char* prefix, const char* lastMatch );
// jmarshall end
idVec3 GetOriginBrushOffset() const;
virtual idVec3 GetEditOrigin() const; // RB: used by idEditEntities
void Event_GetName();
void Event_SetName( const char* name );

View file

@ -82,10 +82,7 @@ void idGameEdit::ParseSpawnArgsToRenderEnvprobe( const idDict* args, renderEnvir
memset( renderEnvprobe, 0, sizeof( *renderEnvprobe ) );
if( !args->GetVector( "light_origin", "", renderEnvprobe->origin ) )
{
args->GetVector( "origin", "", renderEnvprobe->origin );
}
args->GetVector( "origin", "", renderEnvprobe->origin );
// check for other attributes
args->GetVector( "_color", "1 1 1", color );
@ -554,7 +551,6 @@ EnvironmentProbe::ClientThink
*/
void EnvironmentProbe::ClientThink( const int curTime, const float fraction, const bool predict )
{
InterpolatePhysics( fraction );
if( baseColor != nextBaseColor )
@ -567,20 +563,6 @@ void EnvironmentProbe::ClientThink( const int curTime, const float fraction, con
Present();
}
/*
================
EnvironmentProbe::GetPhysicsToSoundTransform
================
*/
bool EnvironmentProbe::GetPhysicsToSoundTransform( idVec3& origin, idMat3& axis )
{
//origin = localEnvprobeOrigin + renderEnvprobe.lightCenter;
//axis = localLightAxis * GetPhysics()->GetAxis();
//return true;
return false;
}
/*
================
EnvironmentProbe::FreeEnvprobeDef

View file

@ -55,7 +55,6 @@ public:
virtual void Think();
virtual void ClientThink( const int curTime, const float fraction, const bool predict );
virtual void FreeEnvprobeDef();
virtual bool GetPhysicsToSoundTransform( idVec3& origin, idMat3& axis );
void Present();
void SaveState( idDict* args );

View file

@ -738,7 +738,7 @@ void idEditEntities::DisplayEntities()
globalLightOrigin = renderLight.origin + renderLight.axis * renderLight.lightCenter;
}
idVec3 start = ent->GetPhysics()->GetOrigin();
idVec3 start = ent->GetEditOrigin();
idVec3 end = globalLightOrigin;
gameRenderWorld->DebugArrow( colorYellow, start, end, 2 );
@ -749,12 +749,12 @@ void idEditEntities::DisplayEntities()
}
}
if( !viewBounds.ContainsPoint( ent->GetPhysics()->GetOrigin() ) )
if( !viewBounds.ContainsPoint( ent->GetEditOrigin() ) )
{
continue;
}
gameRenderWorld->DebugBounds( color, idBounds( ent->GetPhysics()->GetOrigin() ).Expand( 8 ) );
gameRenderWorld->DebugBounds( color, idBounds( ent->GetEditOrigin() ).Expand( 8 ) );
if( drawArrows )
{
idVec3 start = ent->GetPhysics()->GetOrigin();
@ -781,9 +781,9 @@ void idEditEntities::DisplayEntities()
if( textKey.Length() )
{
const char* text = ent->spawnArgs.GetString( textKey );
if( viewTextBounds.ContainsPoint( ent->GetPhysics()->GetOrigin() ) )
if( viewTextBounds.ContainsPoint( ent->GetEditOrigin() ) )
{
gameRenderWorld->DrawText( text, ent->GetPhysics()->GetOrigin() + idVec3( 0, 0, 12 ), 0.25, colorWhite, axis, 1 );
gameRenderWorld->DrawText( text, ent->GetEditOrigin() + idVec3( 0, 0, 12 ), 0.25, colorWhite, axis, 1 );
}
}
}

View file

@ -4312,7 +4312,21 @@ idEntity* idGameLocal::FindTraceEntity( idVec3 start, idVec3 end, const idTypeIn
bestScale = 1.0f;
for( ent = spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() )
{
if( ent->IsType( c ) && ent != skip )
// RB: use edit origin for lights
if( ent->IsType( idLight::Type ) && ent->IsType( c ) && ent != skip )
{
b[0] = b[1] = ent->GetEditOrigin();
b = b.Expand( 16 );
if( b.RayIntersection( start, end - start, scale ) )
{
if( scale >= 0.0f && scale < bestScale )
{
bestEnt = ent;
bestScale = scale;
}
}
}
else if( ent->IsType( c ) && ent != skip )
{
b = ent->GetPhysics()->GetAbsBounds().Expand( 16 );
if( b.RayIntersection( start, end - start, scale ) )

View file

@ -131,10 +131,19 @@ void idGameEdit::ParseSpawnArgsToRenderLight( const idDict* args, renderLight_t*
{
if( !args->GetMatrix( "rotation", "1 0 0 0 1 0 0 0 1", mat ) )
{
// RB: light_angles is specific for lights that have been modified by the editLights command
// these lights have a static model and are not proper grouped using func_group
if( args->GetAngles( "light_angles", "0 0 0", angles ) )
{
angles[ 0 ] = idMath::AngleNormalize360( angles[ 0 ] );
angles[ 1 ] = idMath::AngleNormalize360( angles[ 1 ] );
angles[ 2 ] = idMath::AngleNormalize360( angles[ 2 ] );
mat = angles.ToMat3();
}
// RB: TrenchBroom interop
// support "angles" like in Quake 3
if( args->GetAngles( "angles", "0 0 0", angles ) )
else if( args->GetAngles( "angles", "0 0 0", angles ) )
{
angles[ 0 ] = idMath::AngleNormalize360( angles[ 0 ] );
angles[ 1 ] = idMath::AngleNormalize360( angles[ 1 ] );
@ -1052,7 +1061,6 @@ idLight::ClientThink
*/
void idLight::ClientThink( const int curTime, const float fraction, const bool predict )
{
InterpolatePhysics( fraction );
if( baseColor != nextBaseColor )
@ -1077,6 +1085,12 @@ bool idLight::GetPhysicsToSoundTransform( idVec3& origin, idMat3& axis )
return true;
}
// RB
idVec3 idLight::GetEditOrigin() const
{
return ( GetPhysics()->GetOrigin() + GetPhysics()->GetAxis() * localLightOrigin );
}
/*
================
idLight::FreeLightDef

View file

@ -104,6 +104,7 @@ public:
{
return baseColor;
}
virtual idVec3 GetEditOrigin() const;
void SetShader( const char* shadername );
void SetLightParm( int parmnum, float value );
void SetLightParms( float parm0, float parm1, float parm2, float parm3 );

View file

@ -90,34 +90,45 @@ public:
public: // common physics interface
// set pointer to entity using physics
virtual void SetSelf( idEntity* e ) = 0;
// clip models
virtual void SetClipModel( idClipModel* model, float density, int id = 0, bool freeOld = true ) = 0;
virtual void SetClipBox( const idBounds& bounds, float density );
virtual idClipModel* GetClipModel( int id = 0 ) const = 0;
virtual int GetNumClipModels() const = 0;
// get/set the mass of a specific clip model or the whole physics object
virtual void SetMass( float mass, int id = -1 ) = 0;
virtual float GetMass( int id = -1 ) const = 0;
// get/set the contents of a specific clip model or the whole physics object
virtual void SetContents( int contents, int id = -1 ) = 0;
virtual int GetContents( int id = -1 ) const = 0;
// get/set the contents a specific clip model or the whole physics object collides with
virtual void SetClipMask( int mask, int id = -1 ) = 0;
virtual int GetClipMask( int id = -1 ) const = 0;
// get the bounds of a specific clip model or the whole physics object
virtual const idBounds& GetBounds( int id = -1 ) const = 0;
virtual const idBounds& GetAbsBounds( int id = -1 ) const = 0;
// evaluate the physics with the given time step, returns true if the object moved
virtual bool Evaluate( int timeStepMSec, int endTimeMSec ) = 0;
// Interpolate between the two known snapshots with the given fraction, used for MP clients.
// returns true if the object moved.
virtual bool Interpolate( const float fraction ) = 0;
// resets the prev and next states to the parameters.
virtual void ResetInterpolationState( const idVec3& origin, const idMat3& axis ) = 0;
// update the time without moving
virtual void UpdateTime( int endTimeMSec ) = 0;
// get the last physics update time
virtual int GetTime() const = 0;
// collision interaction between different physics objects
virtual void GetImpactInfo( const int id, const idVec3& point, impactInfo_t* info ) const = 0;
virtual void ApplyImpulse( const int id, const idVec3& point, const idVec3& impulse ) = 0;
@ -127,38 +138,49 @@ public: // common physics interface
virtual bool IsAtRest() const = 0;
virtual int GetRestStartTime() const = 0;
virtual bool IsPushable() const = 0;
// save and restore the physics state
virtual void SaveState() = 0;
virtual void RestoreState() = 0;
// set the position and orientation in master space or world space if no master set
virtual void SetOrigin( const idVec3& newOrigin, int id = -1 ) = 0;
virtual void SetAxis( const idMat3& newAxis, int id = -1 ) = 0;
// translate or rotate the physics object in world space
virtual void Translate( const idVec3& translation, int id = -1 ) = 0;
virtual void Rotate( const idRotation& rotation, int id = -1 ) = 0;
// get the position and orientation in world space
virtual const idVec3& GetOrigin( int id = 0 ) const = 0;
virtual const idMat3& GetAxis( int id = 0 ) const = 0;
// set linear and angular velocity
virtual void SetLinearVelocity( const idVec3& newLinearVelocity, int id = 0 ) = 0;
virtual void SetAngularVelocity( const idVec3& newAngularVelocity, int id = 0 ) = 0;
// get linear and angular velocity
virtual const idVec3& GetLinearVelocity( int id = 0 ) const = 0;
virtual const idVec3& GetAngularVelocity( int id = 0 ) const = 0;
// gravity
virtual void SetGravity( const idVec3& newGravity ) = 0;
virtual const idVec3& GetGravity() const = 0;
virtual const idVec3& GetGravityNormal() const = 0;
// get first collision when translating or rotating this physics object
virtual void ClipTranslation( trace_t& results, const idVec3& translation, const idClipModel* model ) const = 0;
virtual void ClipRotation( trace_t& results, const idRotation& rotation, const idClipModel* model ) const = 0;
virtual int ClipContents( const idClipModel* model ) const = 0;
// disable/enable the clip models contained by this physics object
virtual void DisableClip() = 0;
virtual void EnableClip() = 0;
// link/unlink the clip models contained by this physics object
virtual void UnlinkClip() = 0;
virtual void LinkClip() = 0;
// contacts
virtual bool EvaluateContacts() = 0;
virtual int GetNumContacts() const = 0;
@ -166,22 +188,28 @@ public: // common physics interface
virtual void ClearContacts() = 0;
virtual void AddContactEntity( idEntity* e ) = 0;
virtual void RemoveContactEntity( idEntity* e ) = 0;
// ground contacts
virtual bool HasGroundContacts() const = 0;
virtual bool IsGroundEntity( int entityNum ) const = 0;
virtual bool IsGroundClipModel( int entityNum, int id ) const = 0;
// set the master entity for objects bound to a master
virtual void SetMaster( idEntity* master, const bool orientated = true ) = 0;
// set pushed state
virtual void SetPushed( int deltaTime ) = 0;
virtual const idVec3& GetPushedLinearVelocity( const int id = 0 ) const = 0;
virtual const idVec3& GetPushedAngularVelocity( const int id = 0 ) const = 0;
// get blocking info, returns NULL if the object is not blocked
virtual const trace_t* GetBlockingInfo() const = 0;
virtual idEntity* GetBlockingEntity() const = 0;
// movement end times in msec for reached events at the end of predefined motion
virtual int GetLinearEndTime() const = 0;
virtual int GetAngularEndTime() const = 0;
// networking
virtual void WriteToSnapshot( idBitMsg& msg ) const = 0;
virtual void ReadFromSnapshot( const idBitMsg& msg ) = 0;

View file

@ -62,6 +62,7 @@ void LightInfo::Defaults()
hasCenter = false;
lightStyle = -1;
hasLightOrigin = false;
angles.Zero();
scale.Set( 1, 1, 1 );
}
@ -70,8 +71,11 @@ void LightInfo::Defaults()
void LightInfo::DefaultPoint()
{
idVec3 oldColor = color;
bool oldHasLightOrigin = hasLightOrigin;
Defaults();
color = oldColor;
hasLightOrigin = oldHasLightOrigin;
lightType = LIGHT_POINT;
lightRadius[0] = lightRadius[1] = lightRadius[2] = 300;
equalRadius = true;
@ -80,8 +84,11 @@ void LightInfo::DefaultPoint()
void LightInfo::DefaultProjected()
{
idVec3 oldColor = color;
bool oldHasLightOrigin = hasLightOrigin;
Defaults();
color = oldColor;
hasLightOrigin = oldHasLightOrigin;
lightType = LIGHT_SPOT;
lightTarget[2] = -256;
lightUp[1] = -128;
@ -91,8 +98,11 @@ void LightInfo::DefaultProjected()
void LightInfo::DefaultSun()
{
idVec3 oldColor = color;
bool oldHasLightOrigin = hasLightOrigin;
Defaults();
color = oldColor;
hasLightOrigin = oldHasLightOrigin;
lightType = LIGHT_SUN;
lightCenter.Set( 4, 4, 32 );
lightRadius[0] = lightRadius[1] = 2048;
@ -102,7 +112,14 @@ void LightInfo::DefaultSun()
void LightInfo::FromDict( const idDict* e )
{
e->GetVector( "origin", "", origin );
if( e->GetVector( "light_origin", "", origin ) )
{
hasLightOrigin = true;
}
else
{
e->GetVector( "origin", "", origin );
}
lightRadius.Zero();
lightTarget.Zero();
@ -121,9 +138,9 @@ void LightInfo::FromDict( const idDict* e )
if( !e->GetVector( "_color", "", color ) )
{
color[0] = color[1] = color[2] = 1.0f;
// NOTE: like the game, imgui uses color values between 0.0 and 1.0
// even though it displays them as 0 to 255
color[0] = color[1] = color[2] = 1.0f;
}
if( e->GetVector( "light_right", "", lightRight ) )
@ -145,6 +162,7 @@ void LightInfo::FromDict( const idDict* e )
else
{
explicitStartEnd = false;
// create a start a quarter of the way to the target
lightStart = lightTarget * 0.25;
lightEnd = lightTarget;
@ -168,6 +186,7 @@ void LightInfo::FromDict( const idDict* e )
lightRadius[0] = lightRadius[1] = lightRadius[2] = radius;
equalRadius = true;
}
if( e->GetVector( "light_center", "", lightCenter ) )
{
hasCenter = true;
@ -180,36 +199,39 @@ void LightInfo::FromDict( const idDict* e )
// get the rotation matrix in either full form, or single angle form
idMat3 axis;
if( !e->GetMatrix( "rotation", "1 0 0 0 1 0 0 0 1", axis ) )
if( !e->GetMatrix( "light_rotation", "1 0 0 0 1 0 0 0 1", axis ) )
{
// RB: TrenchBroom interop
// support "angles" like in Quake 3
if( e->GetAngles( "angles", "0 0 0", angles ) )
if( !e->GetMatrix( "rotation", "1 0 0 0 1 0 0 0 1", axis ) )
{
if( angles.pitch != 0.0f || angles.yaw != 0.0f || angles.roll != 0.0f )
// RB: TrenchBroom interop
// support "angles" like in Quake 3
if( e->GetAngles( "angles", "0 0 0", angles ) )
{
angles[ 0 ] = idMath::AngleNormalize360( angles[ 0 ] );
angles[ 1 ] = idMath::AngleNormalize360( angles[ 1 ] );
angles[ 2 ] = idMath::AngleNormalize360( angles[ 2 ] );
axis = angles.ToMat3();
}
else
{
axis.Identity();
}
}
else
{
float angle = e->GetFloat( "angle" );
if( angle != 0.0f )
{
axis = idAngles( 0.0f, angle, 0.0f ).ToMat3();
}
else
{
axis.Identity();
e->GetFloat( "angle", "0", angles[ 1 ] );
angles[ 0 ] = 0;
angles[ 1 ] = idMath::AngleNormalize360( angles[ 1 ] );
angles[ 2 ] = 0;
axis = angles.ToMat3();
}
}
}
// fix degenerate identity matrices
axis[0].FixDegenerateNormal();
axis[1].FixDegenerateNormal();
axis[2].FixDegenerateNormal();
angles = axis.ToAngles();
scale.Set( 1, 1, 1 );
}
@ -218,7 +240,14 @@ void LightInfo::FromDict( const idDict* e )
// and thus will contain pairs with value "" if the key should be removed from entity
void LightInfo::ToDict( idDict* e )
{
e->SetVector( "origin", origin );
if( hasLightOrigin )
{
e->SetVector( "light_origin", origin );
}
else
{
e->SetVector( "origin", origin );
}
// idGameEdit::EntityChangeSpawnArgs() will delete key/value from entity,
// if value is "" => use DELETE_VAL for readability
@ -308,7 +337,14 @@ void LightInfo::ToDict( idDict* e )
}
e->Set( "rotation", DELETE_VAL );
//if( angles.yaw != 0.0f || angles.pitch != 0.0f || angles.roll != 0.0f )
e->Set( "light_rotation", DELETE_VAL );
if( hasLightOrigin )
{
e->SetAngles( "light_angles", angles );
}
else
//if( angles.yaw != 0.0f || angles.pitch != 0.0f || angles.roll != 0.0f )
{
e->SetAngles( "angles", angles );
}

View file

@ -66,6 +66,7 @@ public:
idVec3 lightCenter;
idVec3 color;
bool hasLightOrigin;
idVec3 origin;
idAngles angles; // RBDOOM specific, saved to map as "angles"
idVec3 scale; // not saved to .map