#When appropriate (i.e. wheeled units), units will align with the slope of the terrain. *JS documentation
*added CTerrain::getSlopeAngle[Face]() which returns the angle in radians of the slope of the terrain. getSlopeAngleFace should be used for entities because it takes into account which way the entity is facing, which allows for negative angles. *the max and min graphical rotation for the slope is under traits.pitch. This is used so that you can have certain units such as infantry that don't rotate very far go down steep slopes but not rotate too much. *JS documentation in docs/JSReg.rtf -- I put in most of the relevant global functions; still needs entity functions. This was SVN commit r3794.
This commit is contained in:
parent
2702a268ef
commit
b5d9da29c1
BIN
docs/JSReg.rtf
Normal file
BIN
docs/JSReg.rtf
Normal file
Binary file not shown.
@ -19,8 +19,6 @@
|
||||
#include "CStr.h"
|
||||
#include "NUSpline.h"
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
/*
|
||||
Andrew (aka pyrolink)
|
||||
|
@ -390,8 +390,6 @@ void CGameView::CameraLock(float x, float y, float z, bool smooth)
|
||||
m_ViewCamera.m_Orientation.Translate(x, y, z);
|
||||
m_ViewCamera.m_Orientation._24=height;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,8 +53,6 @@ bool CTerrain::Initialize(u32 size,const u16* data)
|
||||
// store terrain size
|
||||
m_MapSize=(size*PATCH_SIZE)+1;
|
||||
m_MapSizePatches=size;
|
||||
// WaterManager *WaterMgr = g_Renderer.GetWaterManager();
|
||||
// WaterMgr->InitWave();
|
||||
// allocate data for new terrain
|
||||
m_Heightmap=new u16[m_MapSize*m_MapSize];
|
||||
m_Patches=new CPatch[m_MapSizePatches*m_MapSizePatches];
|
||||
@ -205,9 +203,165 @@ float CTerrain::getSlope(float x, float z) const
|
||||
float h10 = m_Heightmap[zi*m_MapSize + xi + 1];
|
||||
float h11 = m_Heightmap[zi*m_MapSize + xi + m_MapSize + 1];
|
||||
|
||||
//Difference of highest point from lowest point
|
||||
return MAX(MAX(h00, h01), MAX(h10, h11)) -
|
||||
MIN(MIN(h00, h01), MIN(h10, h11));
|
||||
}
|
||||
float CTerrain::getSlopeAngle( float x, float y ) const
|
||||
{
|
||||
float fCell = (float)CELL_SIZE;
|
||||
x /= fCell;
|
||||
y /= fCell;
|
||||
int xi = (int)floor(x);
|
||||
int yi = (int)floor(y);
|
||||
|
||||
//Keep it in bounds
|
||||
if (xi < 0)
|
||||
xi = 0;
|
||||
else if (xi >= (int)m_MapSize-1)
|
||||
xi = m_MapSize - 2;
|
||||
if (yi < 0)
|
||||
yi = 0;
|
||||
else if (yi >= (int)m_MapSize-1)
|
||||
yi = m_MapSize - 2;
|
||||
|
||||
float h00 = m_Heightmap[yi*m_MapSize + xi] * HEIGHT_SCALE;
|
||||
float h01 = m_Heightmap[yi*m_MapSize + xi + m_MapSize] * HEIGHT_SCALE;
|
||||
float h10 = m_Heightmap[yi*m_MapSize + xi + 1] * HEIGHT_SCALE;
|
||||
float h11 = m_Heightmap[yi*m_MapSize + xi + m_MapSize + 1] * HEIGHT_SCALE;
|
||||
|
||||
CVector3D flat, elevated;
|
||||
float low, high;
|
||||
|
||||
if ( h00 < h01 && h00 < h10 && h00 < h11 )
|
||||
low = h00;
|
||||
else if ( h01 < h10 && h01 < h11 )
|
||||
low = h01;
|
||||
else if ( h10 < h11 )
|
||||
low = h10;
|
||||
else
|
||||
low = h11;
|
||||
|
||||
//Find correct vector representing the flat version of the vector from low to high points
|
||||
if ( h00 > h01 && h00 > h10 && h00 > h11 )
|
||||
{
|
||||
high = h00;
|
||||
if ( low == h10 )
|
||||
flat = CVector3D( fCell, 0.0f, 0.0f );
|
||||
else if ( low == h01 )
|
||||
flat = CVector3D( 0.0f, 0.0f, fCell );
|
||||
else if ( low == h11 )
|
||||
flat = CVector3D( fCell, 0.0f, fCell );
|
||||
}
|
||||
else if ( h01 > h10 && h01 > h11 )
|
||||
{
|
||||
high = h01;
|
||||
if ( low == h00 )
|
||||
flat = CVector3D( 0.0f, 0.0f, fCell );
|
||||
else if ( low == h01 )
|
||||
flat = CVector3D( fCell, 0.0f, fCell );
|
||||
else if ( low == h11 )
|
||||
flat = CVector3D( fCell, 0.0f, 0.0f );
|
||||
}
|
||||
else if ( h10 > h11 )
|
||||
{
|
||||
high = h10;
|
||||
if ( low == h00 )
|
||||
flat = CVector3D( fCell, 0.0f, 0.0f );
|
||||
else if ( low == h01 )
|
||||
flat = CVector3D( fCell, 0.0f, fCell );
|
||||
else if ( low == h11 )
|
||||
flat = CVector3D( 0.0f, 0.0f, fCell );
|
||||
}
|
||||
else
|
||||
{
|
||||
high = h11;
|
||||
if ( low == h10 )
|
||||
flat = CVector3D( 0.0f, 0.0f, fCell );
|
||||
else if ( low == h01 )
|
||||
flat = CVector3D( fCell, 0.0f, 0.0f );
|
||||
else if ( low == h00 )
|
||||
flat = CVector3D( fCell, 0.0f, fCell );
|
||||
}
|
||||
elevated = flat;
|
||||
elevated.Y = high - low;
|
||||
elevated.Normalize();
|
||||
flat.Normalize();
|
||||
return acosf( flat.Dot( elevated ) );
|
||||
}
|
||||
float CTerrain::getSlopeAngleFace(float x, float y, float orientation) const
|
||||
{
|
||||
bool right; //true means use 0,0 and 1,1; false means use 1,0 and 0,1
|
||||
bool invert;
|
||||
float top, bottom;
|
||||
x /= (float)CELL_SIZE;
|
||||
y /= (float)CELL_SIZE;
|
||||
int xi = (int)floor(x);
|
||||
int yi = (int)floor(y);
|
||||
CVector3D flat( (float)CELL_SIZE, 0.0f, (float)CELL_SIZE );
|
||||
CVector3D elevated=flat;
|
||||
|
||||
float a0 = DEGTORAD(0.0f);
|
||||
float a90 = DEGTORAD(90.0f);
|
||||
float a180 = DEGTORAD(180.0f);
|
||||
float neg = DEGTORAD(-90.0f);
|
||||
float a45 = DEGTORAD(45.0f);
|
||||
float a135 = DEGTORAD(135.0f);
|
||||
|
||||
//Find which side it's facing; use that and the opposite
|
||||
if ( orientation > 0.0f && orientation < DEGTORAD(90.0f) )
|
||||
right = true;
|
||||
else if ( orientation > DEGTORAD(90.0f) && orientation < DEGTORAD(180.0f) )
|
||||
right = false;
|
||||
else if ( orientation < DEGTORAD(-180.0f) && orientation > DEGTORAD(-90.0f) )
|
||||
right = true;
|
||||
else
|
||||
right = false;
|
||||
|
||||
//Keep it in bounds
|
||||
if (xi < 0)
|
||||
xi = 0;
|
||||
else if (xi >= (int)m_MapSize-1)
|
||||
xi = m_MapSize - 2;
|
||||
if (yi < 0)
|
||||
yi = 0;
|
||||
else if (yi >= (int)m_MapSize-1)
|
||||
yi = m_MapSize - 2;
|
||||
|
||||
if ( right )
|
||||
{
|
||||
bottom = m_Heightmap[yi*m_MapSize + xi]*HEIGHT_SCALE;
|
||||
top = m_Heightmap[yi*m_MapSize+m_MapSize + xi + 1]*HEIGHT_SCALE;
|
||||
if ( (orientation > DEGTORAD(-45.0f) && orientation < 0.0f) ||
|
||||
(orientation < DEGTORAD(135.0f) && orientation > 0.0f) )
|
||||
elevated.Y = top-bottom;
|
||||
else
|
||||
elevated.Y = bottom-top;
|
||||
}
|
||||
else
|
||||
{
|
||||
bottom = m_Heightmap[yi*m_MapSize + xi + 1]*HEIGHT_SCALE;
|
||||
top = m_Heightmap[yi*m_MapSize+m_MapSize + xi]*HEIGHT_SCALE;
|
||||
if ( (orientation > DEGTORAD(-135.0f) && orientation < 0.0f) ||
|
||||
(orientation < DEGTORAD(45.0f) && orientation > 0.0f) )
|
||||
elevated.Y = top-bottom;
|
||||
else
|
||||
elevated.Y = bottom-top;
|
||||
}
|
||||
if ( elevated.Y > 0.0f )
|
||||
invert=false;
|
||||
else
|
||||
invert=true;
|
||||
elevated.Y = fabs(elevated.Y);
|
||||
elevated.Normalize();
|
||||
flat.Normalize();
|
||||
float ret = elevated.Dot(flat);
|
||||
|
||||
if (invert)
|
||||
return -acosf(ret);
|
||||
return acosf(ret);
|
||||
|
||||
}
|
||||
|
||||
float CTerrain::getExactGroundLevel(float x, float z) const
|
||||
{
|
||||
|
@ -45,7 +45,9 @@ public:
|
||||
inline float getExactGroundLevel(const CVector2D& v) const { return getExactGroundLevel(v.x, v.y); }
|
||||
|
||||
float getSlope(float x, float z) const ;
|
||||
|
||||
float getSlopeAngle( float x, float y) const; //In radians
|
||||
//Same as above, but picks the two vertices that the unit is facing (front+back) for slope
|
||||
float getSlopeAngleFace(float x, float y, float orientation) const;
|
||||
// resize this terrain such that each side has given number of patches
|
||||
void Resize(u32 size);
|
||||
|
||||
|
@ -49,6 +49,8 @@ CBaseEntity::CBaseEntity()
|
||||
AddProperty( L"traits.stamina.border_name", &m_staminaBorderName );
|
||||
AddProperty( L"traits.angle_penalty.sectors", &m_sectorDivs );
|
||||
AddProperty( L"traits.angle_penalty.value", &m_sectorPenalty );
|
||||
AddProperty( L"traits.pitch.max_actor", &m_maxActorPitch );
|
||||
AddProperty( L"traits.pitch.min_actor", &m_minActorPitch );
|
||||
AddProperty( L"traits.rank.width", &m_rankWidth );
|
||||
AddProperty( L"traits.rank.height", &m_rankHeight );
|
||||
AddProperty( L"traits.rank.name", &m_rankName );
|
||||
|
@ -113,6 +113,9 @@ public:
|
||||
int m_sectorDivs;
|
||||
float m_sectorPenalty;
|
||||
|
||||
float m_maxActorPitch;
|
||||
float m_minActorPitch;
|
||||
|
||||
float m_turningRadius;
|
||||
CScriptObject m_EventHandlers[EVENT_LAST];
|
||||
|
||||
|
@ -79,6 +79,8 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation, cons
|
||||
AddProperty( L"traits.stamina.border_name", &m_staminaBorderName );
|
||||
AddProperty( L"traits.angle_penalty.sectors", &m_sectorDivs);
|
||||
AddProperty( L"traits.angle_penalty.value", &m_sectorPenalty );
|
||||
AddProperty( L"traits.pitch.max_actor", &m_maxActorPitch );
|
||||
AddProperty( L"traits.pitch.min_actor", &m_minActorPitch );
|
||||
AddProperty( L"traits.rank.width", &m_rankWidth );
|
||||
AddProperty( L"traits.rank.height", &m_rankHeight );
|
||||
AddProperty( L"traits.rank.name", &m_rankName );
|
||||
@ -101,10 +103,6 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation, cons
|
||||
AddHandler( t, &m_EventHandlers[t] );
|
||||
}
|
||||
|
||||
// FIXME: janwas: this was uninitialized, which leads to disaster if
|
||||
// its value happens to be positive.
|
||||
// setting to what seems to be a reasonable default.
|
||||
m_sectorDivs = 4;
|
||||
if ( m_sectorDivs >= 0 )
|
||||
{
|
||||
m_sectorAngles.resize(m_sectorDivs);
|
||||
@ -143,6 +141,7 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation, cons
|
||||
m_graphics_orientation = m_orientation;
|
||||
m_actor_transform_valid = false;
|
||||
|
||||
m_pitchOrientation = m_pitchOrientation_previous = m_graphics_pitchOrientation = 0.0f;
|
||||
m_destroyed = false;
|
||||
|
||||
m_selected = false;
|
||||
@ -277,29 +276,22 @@ void CEntity::SetPlayer(CPlayer *pPlayer)
|
||||
void CEntity::updateActorTransforms()
|
||||
{
|
||||
CMatrix3D m;
|
||||
CMatrix3D mX;
|
||||
float Cos = cosf( m_graphics_orientation );
|
||||
float Sin = sinf( m_graphics_orientation );
|
||||
|
||||
float s = sin( m_graphics_orientation );
|
||||
float c = cos( m_graphics_orientation );
|
||||
m._11=-Cos; m._12=0.0f; m._13=-Sin; m._14=0.0f;
|
||||
m._21=0.0f; m._22=1.0f; m._23=0.0f; m._24=0.0f;
|
||||
m._31=Sin; m._32=0.0f; m._33=-Cos; m._34=0.0f;
|
||||
m._41=0.0f; m._42=0.0f; m._43=0.0f; m._44=1.0f;
|
||||
|
||||
m._11 = -c;
|
||||
m._12 = 0.0f;
|
||||
m._13 = -s;
|
||||
m._14 = m_graphics_position.X;
|
||||
m._21 = 0.0f;
|
||||
m._22 = 1.0f;
|
||||
m._23 = 0.0f;
|
||||
m._24 = m_graphics_position.Y;
|
||||
m._31 = s;
|
||||
m._32 = 0.0f;
|
||||
m._33 = -c;
|
||||
m._34 = m_graphics_position.Z;
|
||||
m._41 = 0.0f;
|
||||
m._42 = 0.0f;
|
||||
m._43 = 0.0f;
|
||||
m._44 = 1.0f;
|
||||
mX.SetXRotation( m_graphics_pitchOrientation );
|
||||
mX = m*mX;
|
||||
mX.Translate(m_graphics_position);
|
||||
//m.RotateX(m_graphics_pitchOrientation);
|
||||
|
||||
if( m_actor )
|
||||
m_actor->GetModel()->SetTransform( m );
|
||||
m_actor->GetModel()->SetTransform( mX );
|
||||
}
|
||||
|
||||
void CEntity::snapToGround()
|
||||
@ -382,6 +374,7 @@ void CEntity::update( size_t timestep )
|
||||
{
|
||||
m_position_previous = m_position;
|
||||
m_orientation_previous = m_orientation;
|
||||
m_pitchOrientation_previous = m_pitchOrientation;
|
||||
|
||||
CalculateRun( timestep );
|
||||
CalculateHealth( timestep );
|
||||
@ -809,6 +802,7 @@ void CEntity::repath()
|
||||
void CEntity::reorient()
|
||||
{
|
||||
m_orientation = m_graphics_orientation;
|
||||
m_pitchOrientation = m_graphics_pitchOrientation;
|
||||
m_ahead.x = sin( m_orientation );
|
||||
m_ahead.y = cos( m_orientation );
|
||||
if( m_bounds->m_type == CBoundingObject::BOUND_OABB )
|
||||
@ -855,6 +849,7 @@ void CEntity::interpolate( float relativeoffset )
|
||||
{
|
||||
CVector3D old_graphics_position = m_graphics_position;
|
||||
float old_graphics_orientation = m_graphics_orientation;
|
||||
float old_graphics_pitchOrientation = m_graphics_pitchOrientation;
|
||||
|
||||
m_graphics_position = Interpolate<CVector3D>( m_position_previous, m_position, relativeoffset );
|
||||
|
||||
@ -864,7 +859,13 @@ void CEntity::interpolate( float relativeoffset )
|
||||
while( m_orientation > m_orientation_previous + PI )
|
||||
m_orientation_previous += 2 * PI;
|
||||
|
||||
while( m_pitchOrientation < m_pitchOrientation_previous - PI )
|
||||
m_pitchOrientation_previous -= 2 * PI;
|
||||
while( m_pitchOrientation > m_pitchOrientation_previous + PI )
|
||||
m_pitchOrientation_previous += 2 * PI;
|
||||
|
||||
m_graphics_orientation = Interpolate<float>( m_orientation_previous, m_orientation, relativeoffset );
|
||||
m_graphics_pitchOrientation = Interpolate<float>( m_pitchOrientation_previous, m_pitchOrientation, relativeoffset );
|
||||
|
||||
// Mark the actor transform data as invalid if the entity has moved since
|
||||
// the last call to 'interpolate'.
|
||||
@ -873,9 +874,12 @@ void CEntity::interpolate( float relativeoffset )
|
||||
// handle flying units or moving terrain.
|
||||
if( m_graphics_orientation != old_graphics_orientation ||
|
||||
m_graphics_position.X != old_graphics_position.X ||
|
||||
m_graphics_position.Z != old_graphics_position.Z )
|
||||
m_graphics_position.Z != old_graphics_position.Z ||
|
||||
m_graphics_pitchOrientation != old_graphics_pitchOrientation
|
||||
)
|
||||
{
|
||||
m_actor_transform_valid = false;
|
||||
|
||||
}
|
||||
// Update the actor transform data when necessary.
|
||||
if( !m_actor_transform_valid )
|
||||
{
|
||||
|
@ -79,6 +79,9 @@ public:
|
||||
float m_runRegenRate;
|
||||
float m_runDecayRate;
|
||||
|
||||
float m_maxActorPitch;
|
||||
float m_minActorPitch;
|
||||
|
||||
float m_healthRegenRate;
|
||||
float m_healthRegenStart;
|
||||
float m_healthDecayRate;
|
||||
@ -169,6 +172,10 @@ public:
|
||||
float m_orientation_previous;
|
||||
float m_graphics_orientation;
|
||||
|
||||
float m_pitchOrientation;
|
||||
float m_pitchOrientation_previous;
|
||||
float m_graphics_pitchOrientation;
|
||||
|
||||
// If the actor's current transform data is valid (i.e. the entity hasn't
|
||||
// moved since it was last calculated, and the terrain hasn't been changed).
|
||||
bool m_actor_transform_valid;
|
||||
|
@ -89,13 +89,11 @@ uint CEntity::processGotoHelper( CEntityOrder* current, size_t timestep_millis,
|
||||
|
||||
float scale = processChooseMovement( len ) * timestep;
|
||||
|
||||
|
||||
// Note: Easy optimization: flag somewhere that this unit
|
||||
// is already pointing the way, and don't do this
|
||||
// trig every time.right
|
||||
|
||||
m_targetorientation = atan2( delta.x, delta.y );
|
||||
|
||||
float deltatheta = m_targetorientation - (float)m_orientation;
|
||||
while( deltatheta > PI ) deltatheta -= 2 * PI;
|
||||
while( deltatheta < -PI ) deltatheta += 2 * PI;
|
||||
@ -137,6 +135,12 @@ uint CEntity::processGotoHelper( CEntityOrder* current, size_t timestep_millis,
|
||||
m_orientation = m_targetorientation;
|
||||
}
|
||||
|
||||
float targetpitch = g_Game->GetWorld()->GetTerrain()->getSlopeAngleFace( m_position.X, m_position.Z, m_orientation );
|
||||
while( targetpitch > PI ) targetpitch -= 2 * PI;
|
||||
while( targetpitch < -PI ) targetpitch += 2 * PI;
|
||||
m_pitchOrientation = clamp( targetpitch, m_minActorPitch, m_maxActorPitch );
|
||||
|
||||
|
||||
if( m_bounds && m_bounds->m_type == CBoundingObject::BOUND_OABB )
|
||||
((CBoundingBox*)m_bounds)->setOrientation( m_ahead );
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user