1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "nel/misc/types_nl.h"
23 #include "nel/misc/smart_ptr.h"
24 #include "nel/misc/vector.h"
25 #include "nel/misc/vectord.h"
26 #include "nel/misc/entity_id.h"
27 #include "nel/misc/sheet_id.h"
29 #include "nel/pacs/u_move_container.h"
30 #include "nel/pacs/u_move_primitive.h"
32 #include "nel/georges/u_form.h"
33 #include "nel/georges/u_form_elm.h"
37 * The base class for moving entity
38 * \author Benjamin Legros
39 * \author Nevrax France
48 Idle
= 0, // not controlled yet
49 MovingTowardsTarget
, // first step of motion, moving towards target
50 TargetLocked
, // close to target, locked
51 TargetLost
, // target moved away, can't reach it any longer
52 TargetUnreachable
// can't reach target, too far or too many obstacles on the way
56 virtual const NLMISC::CEntityId
&getId() const = 0;
59 virtual const NLMISC::CSheetId
&getSheetId() const = 0;
62 virtual bool hasId() const = 0;
64 /// Get track Position
65 virtual void getPosition(NLMISC::CVectorD
&pos
, float &heading
) const = 0;
68 virtual bool hasPosition() const = 0;
71 virtual void setUserData(void *data
) = 0;
74 virtual void *getUserData() = 0;
77 virtual TTrackState
getTrackState() const = 0;
81 * A track that represents a moving point
82 * \author Benjamin Legros
83 * \author Nevrax France
86 class CTrack
: public CTrackBase
, public NLMISC::CRefCount
90 * The sheet type read by Georges
95 CSheet(): WalkSpeed(1.3f
), RunSpeed(6.0f
), Radius(0.5f
), Height(2.0f
), Length(1.0), Width(1.0) {}
97 /// The Walk speed of the entity
99 /// The Run speed of the entity
101 /// The Pacs radius of the entity
103 /// The Height radius of the entity
105 /// The Animation length of the entity
107 /// The Width length of the entity
110 void readGeorges (const NLMISC::CSmartPtr
<NLGEORGES::UForm
> &form
, const NLMISC::CSheetId
&sheetId
)
112 // the form was found so read the true values from George
113 form
->getRootNode ().getValueByName (WalkSpeed
, "Basics.MovementSpeeds.WalkSpeed");
114 form
->getRootNode ().getValueByName (RunSpeed
, "Basics.MovementSpeeds.RunSpeed");
115 form
->getRootNode ().getValueByName (Radius
, "Collision.CollisionRadius");
116 form
->getRootNode ().getValueByName (Height
, "Collision.Height");
117 form
->getRootNode ().getValueByName (Width
, "Collision.Width");
118 form
->getRootNode ().getValueByName (Length
, "Collision.Length");
121 void serial (NLMISC::IStream
&s
)
123 s
.serial (WalkSpeed
, RunSpeed
);
124 s
.serial (Radius
, Height
);
125 s
.serial (Length
, Width
);
128 static uint
getVersion () { return 1; }
130 /// The default sheet
131 static CSheet DefaultSheet
;
137 CTrack() : _OwnControl(NULL
), _MoveContainer(NULL
), _MovePrimitive(NULL
),
138 _Id(NLMISC::CEntityId::Unknown
), _SheetId(NLMISC::CSheetId::Unknown
), _Sheet(NULL
), _Followed(NULL
),
139 _HasPosition(false), _HasId(false), _IdRequested(false), _PositionUpdatesRequested(false), _IsStatic(false),
140 _ForceRelease(false), _ReceiveVision(false), _UserData(NULL
), _State(Idle
),
141 _SmoothedTargetDistanceDelta(3.0), _LastTargetDistance(-1.0)
150 void setId(const NLMISC::CEntityId
&id
, const NLMISC::CSheetId
&sheet
);
153 const NLMISC::CEntityId
&getId() const
159 const NLMISC::CSheetId
&getSheetId() const
165 const CSheet
*getSheet() const
178 /// Update track position
179 void setPosition(const NLMISC::CVectorD
&pos
, float heading
)
181 // don't allow more than one position to be set when control is owned
182 if (_HasPosition
&& _OwnControl
)
189 /// Get track Position
190 void getPosition(NLMISC::CVectorD
&pos
, float &heading
) const
199 nlwarning("ReynoldsLib:CTrack:getPosition(): Track %s position not yet set", _Id
.toString().c_str());
204 void setStatic(bool isstatic
= true)
206 _IsStatic
= isstatic
;
211 /// Has Control Owned ?
212 bool hasControlOwned() const
218 bool hasPosition() const
224 void invalidPosition()
226 _HasPosition
= false;
230 bool isStatic() const
238 void follow(CTrack
*followed
);
244 void update(double dt
);
247 void updateVision(const std::vector
<NLMISC::CEntityId
> &in
, const std::vector
<NLMISC::CEntityId
> &out
);
250 void updateVision(const std::vector
<NLMISC::CEntityId
> &vision
);
253 void forceRelease() { _ForceRelease
= true; }
257 /// Get current state
258 TTrackState
getTrackState() const { return _State
; }
264 void setUserData(void *data
) { _UserData
= data
; }
267 void *getUserData() { return _UserData
; }
274 /// Get contact distance
275 double rawDistance(const CTrack
*other
, NLMISC::CVectorD
&distance
) const
277 distance
= other
->_Position
- _Position
;
279 return distance
.norm();
282 /// Get contact distance
283 double contactDistance(const CTrack
*other
, NLMISC::CVectorD
&distance
, double &rawdistance
) const
285 rawdistance
= rawDistance(other
, distance
);
286 return contactDistanceWithRawDistance(other
, distance
, rawdistance
);
289 /// Get contact distance
290 double contactDistanceWithRawDistance(const CTrack
*other
, NLMISC::CVectorD
&distance
, double &rawdistance
) const
292 double theta
= atan2(distance
.y
, distance
.x
);
293 double theta1
= _Heading
- theta
;
294 double theta2
= other
->_Heading
- theta
+ 3.1415926535;
296 float l1
= _Sheet
->Length
,
298 float l2
= other
->_Sheet
->Length
,
299 w2
= other
->_Sheet
->Width
;
301 double r1
= 0.5 * sqrt( l1
*l1
+ (w1
*w1
-l1
*l1
)*NLMISC::sqr(sin(theta1
)) );
302 double r2
= 0.5 * sqrt( l2
*l2
+ (w2
*w2
-l2
*l2
)*NLMISC::sqr(sin(theta2
)) );
304 return rawdistance
- r1
- r2
;
312 void acquireControl();
315 void releaseControl();
318 void acquireVision();
321 void releaseVision();
323 /// Create Move primitive
324 void createMovePrimitive();
326 /// Delete Move primitive
327 void deleteMovePrimitive();
329 /// Check has position (ask for it if necessary)
337 if (!hasControlOwned() && !_PositionUpdatesRequested
)
338 requestPositionUpdates();
348 void requestPositionUpdates();
363 NLMISC::CEntityId _Id
;
366 NLMISC::CSheetId _SheetId
;
369 const CSheet
*_Sheet
;
378 /// @name Track Position Control
388 bool _PositionUpdatesRequested
;
391 NLMISC::CVectorD _Position
;
397 NLMISC::CSmartPtr
<CTrack
> _Followed
;
407 NLPACS::UMoveContainer
*_MoveContainer
;
410 NLPACS::UMovePrimitive
*_MovePrimitive
;
423 typedef std::map
<NLMISC::CEntityId
, NLMISC::CSmartPtr
<CTrack
> > TVision
;
438 uint32 _LastMoveCycle
;
440 /// Last target distance
441 double _LastTargetDistance
;
443 /// Smoothed target distance
444 double _SmoothedTargetDistanceDelta
;
449 /// @name Target attraction control
452 /// Required target spacing
453 static double TargetSpacing
;
455 /// Target attraction strength
456 static double TargetAttraction
;
458 /// Target attraction amplification
459 static double TargetAmp
;
464 /// @name Obstacle repulsion control
467 /// Fast obstacle exclusion distance
468 static double ObstacleExcludeDistance
;
470 /// Required obstacle spacing
471 static double ObstacleSpacing
;
473 /// Obstacle repulsion strength
474 static double ObstacleRepulsion
;
476 /// Obstacle repulsion amplification
477 static double ObstacleAmp
;
482 /// @name Track motion control
485 /// Minimum motion distance
486 static double MinimumMotion
;
488 /// Lock distance threshold
489 static double LockThreshold
;
491 /// Lose distance threshold
492 static double LoseThreshold
;
495 static uint32 StabiliseCycle
;