khanat-opennel-code/code/ryzom/tools/reynolds/track.h
2010-11-02 13:42:25 +01:00

503 lines
10 KiB
C++

// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_TRACK_H
#define NL_TRACK_H
#include "nel/misc/types_nl.h"
#include "nel/misc/smart_ptr.h"
#include "nel/misc/vector.h"
#include "nel/misc/vectord.h"
#include "nel/misc/entity_id.h"
#include "nel/misc/sheet_id.h"
#include "nel/pacs/u_move_container.h"
#include "nel/pacs/u_move_primitive.h"
#include "nel/georges/u_form.h"
#include "nel/georges/u_form_elm.h"
/**
* The base class for moving entity
* \author Benjamin Legros
* \author Nevrax France
* \date 2002
*/
class CTrackBase
{
public:
/// State type
enum TTrackState
{
Idle = 0, // not controlled yet
MovingTowardsTarget, // first step of motion, moving towards target
TargetLocked, // close to target, locked
TargetLost, // target moved away, can't reach it any longer
TargetUnreachable // can't reach target, too far or too many obstacles on the way
};
/// Get Id
virtual const NLMISC::CEntityId &getId() const = 0;
/// Get SheetId
virtual const NLMISC::CSheetId &getSheetId() const = 0;
/// Has Id ?
virtual bool hasId() const = 0;
/// Get track Position
virtual void getPosition(NLMISC::CVectorD &pos, float &heading) const = 0;
/// Has Position ?
virtual bool hasPosition() const = 0;
/// Set user data
virtual void setUserData(void *data) = 0;
/// Get user data
virtual void *getUserData() = 0;
/// Get Track state
virtual TTrackState getTrackState() const = 0;
};
/**
* A track that represents a moving point
* \author Benjamin Legros
* \author Nevrax France
* \date 2002
*/
class CTrack : public CTrackBase, public NLMISC::CRefCount
{
public:
/**
* The sheet type read by Georges
*/
class CSheet
{
public:
CSheet(): WalkSpeed(1.3f), RunSpeed(6.0f), Radius(0.5f), Height(2.0f), Length(1.0), Width(1.0) {}
/// The Walk speed of the entity
float WalkSpeed;
/// The Run speed of the entity
float RunSpeed;
/// The Pacs radius of the entity
float Radius;
/// The Height radius of the entity
float Height;
/// The Animation length of the entity
float Length;
/// The Width length of the entity
float Width;
void readGeorges (const NLMISC::CSmartPtr<NLGEORGES::UForm> &form, const NLMISC::CSheetId &sheetId)
{
// the form was found so read the true values from George
form->getRootNode ().getValueByName (WalkSpeed, "Basics.MovementSpeeds.WalkSpeed");
form->getRootNode ().getValueByName (RunSpeed, "Basics.MovementSpeeds.RunSpeed");
form->getRootNode ().getValueByName (Radius, "Collision.CollisionRadius");
form->getRootNode ().getValueByName (Height, "Collision.Height");
form->getRootNode ().getValueByName (Width, "Collision.Width");
form->getRootNode ().getValueByName (Length, "Collision.Length");
}
void serial (NLMISC::IStream &s)
{
s.serial (WalkSpeed, RunSpeed);
s.serial (Radius, Height);
s.serial (Length, Width);
}
static uint getVersion () { return 1; }
/// The default sheet
static CSheet DefaultSheet;
};
public:
/// Constructor
CTrack() : _OwnControl(NULL), _MoveContainer(NULL), _MovePrimitive(NULL),
_Id(NLMISC::CEntityId::Unknown), _SheetId(NLMISC::CSheetId::Unknown), _Sheet(NULL), _Followed(NULL),
_HasPosition(false), _HasId(false), _IdRequested(false), _PositionUpdatesRequested(false), _IsStatic(false),
_ForceRelease(false), _ReceiveVision(false), _UserData(NULL), _State(Idle),
_SmoothedTargetDistanceDelta(3.0), _LastTargetDistance(-1.0)
{
}
/// Destructor
~CTrack();
/// Init track
void setId(const NLMISC::CEntityId &id, const NLMISC::CSheetId &sheet);
/// Get Id
const NLMISC::CEntityId &getId() const
{
return _Id;
}
/// Get SheetId
const NLMISC::CSheetId &getSheetId() const
{
return _SheetId;
}
/// Get SheetId
const CSheet *getSheet() const
{
return _Sheet;
}
/// Has Id ?
bool hasId() const
{
return _HasId;
}
/// Update track position
void setPosition(const NLMISC::CVectorD &pos, float heading)
{
// don't allow more than one position to be set when control is owned
if (_HasPosition && _OwnControl)
return;
_Position = pos;
_Heading = heading;
_HasPosition = true;
}
/// Get track Position
void getPosition(NLMISC::CVectorD &pos, float &heading) const
{
if (_HasPosition)
{
pos = _Position;
heading = _Heading;
}
else
{
nlwarning("ReynoldsLib:CTrack:getPosition(): Track %s position not yet set", _Id.toString().c_str());
}
}
/// Set Static state
void setStatic(bool isstatic = true)
{
_IsStatic = isstatic;
}
/// Has Control Owned ?
bool hasControlOwned() const
{
return _OwnControl;
}
/// Has Position ?
bool hasPosition() const
{
return _HasPosition;
}
/// Invalid position
void invalidPosition()
{
_HasPosition = false;
}
/// Is static ?
bool isStatic() const
{
return _IsStatic;
}
/// Follow
void follow(CTrack *followed);
/// Leave
void leave();
/// Update
void update(double dt);
/// Update vision
void updateVision(const std::vector<NLMISC::CEntityId> &in, const std::vector<NLMISC::CEntityId> &out);
/// Update vision
void updateVision(const std::vector<NLMISC::CEntityId> &vision);
/// Force release
void forceRelease() { _ForceRelease = true; }
/// Get current state
TTrackState getTrackState() const { return _State; }
/// Set user data
void setUserData(void *data) { _UserData = data; }
/// Get user data
void *getUserData() { return _UserData; }
/// Get contact distance
double rawDistance(const CTrack *other, NLMISC::CVectorD &distance) const
{
distance = other->_Position - _Position;
distance.z = 0.0;
return distance.norm();
}
/// Get contact distance
double contactDistance(const CTrack *other, NLMISC::CVectorD &distance, double &rawdistance) const
{
rawdistance = rawDistance(other, distance);
return contactDistanceWithRawDistance(other, distance, rawdistance);
}
/// Get contact distance
double contactDistanceWithRawDistance(const CTrack *other, NLMISC::CVectorD &distance, double &rawdistance) const
{
double theta = atan2(distance.y, distance.x);
double theta1 = _Heading - theta;
double theta2 = other->_Heading - theta + 3.1415926535;
float l1 = _Sheet->Length,
w1 = _Sheet->Width;
float l2 = other->_Sheet->Length,
w2 = other->_Sheet->Width;
double r1 = 0.5 * sqrt( l1*l1 + (w1*w1-l1*l1)*NLMISC::sqr(sin(theta1)) );
double r2 = 0.5 * sqrt( l2*l2 + (w2*w2-l2*l2)*NLMISC::sqr(sin(theta2)) );
return rawdistance - r1 - r2;
}
protected:
/// Own Control
void acquireControl();
/// Release Control
void releaseControl();
/// Acquire vision
void acquireVision();
/// Release vision
void releaseVision();
/// Create Move primitive
void createMovePrimitive();
/// Delete Move primitive
void deleteMovePrimitive();
/// Check has position (ask for it if necessary)
bool isValid()
{
if (!hasId())
return false;
if (!hasPosition())
{
if (!hasControlOwned() && !_PositionUpdatesRequested)
requestPositionUpdates();
return false;
}
return true;
}
/// Request Id
void requestId();
/// Request Position
void requestPositionUpdates();
protected:
/// @name Track Id
//@{
/// Has Id
bool _HasId;
/// Id Requested
bool _IdRequested;
/// Entity Id
NLMISC::CEntityId _Id;
/// Sheet Id
NLMISC::CSheetId _SheetId;
/// Sheet
const CSheet *_Sheet;
/// Is static
bool _IsStatic;
//@}
/// @name Track Position Control
//@{
/// Own control
bool _OwnControl;
/// Has Position
bool _HasPosition;
/// Id Requested
bool _PositionUpdatesRequested;
/// Position
NLMISC::CVectorD _Position;
/// Heading
float _Heading;
/// Followed track
NLMISC::CSmartPtr<CTrack> _Followed;
//@}
/// @name Track PACS
//@{
/// Move Container
NLPACS::UMoveContainer *_MoveContainer;
/// Move Primitive
NLPACS::UMovePrimitive *_MovePrimitive;
//@}
/// @name Misc
//@{
/// Force release
bool _ForceRelease;
/// Vision container
typedef std::map<NLMISC::CEntityId, NLMISC::CSmartPtr<CTrack> > TVision;
/// Vision
TVision _Vision;
/// Receive vision
bool _ReceiveVision;
/// User data
void *_UserData;
/// Track state
TTrackState _State;
/// Last move cycle
uint32 _LastMoveCycle;
/// Last target distance
double _LastTargetDistance;
/// Smoothed target distance
double _SmoothedTargetDistanceDelta;
//@}
public:
/// @name Target attraction control
//@{
/// Required target spacing
static double TargetSpacing;
/// Target attraction strength
static double TargetAttraction;
/// Target attraction amplification
static double TargetAmp;
//@}
/// @name Obstacle repulsion control
//@{
/// Fast obstacle exclusion distance
static double ObstacleExcludeDistance;
/// Required obstacle spacing
static double ObstacleSpacing;
/// Obstacle repulsion strength
static double ObstacleRepulsion;
/// Obstacle repulsion amplification
static double ObstacleAmp;
//@}
/// @name Track motion control
//@{
/// Minimum motion distance
static double MinimumMotion;
/// Lock distance threshold
static double LockThreshold;
/// Lose distance threshold
static double LoseThreshold;
/// Stabilise cycle
static uint32 StabiliseCycle;
//@}
};
#endif // NL_TRACK_H
/* End of track.h */