2023-03-14 08:02:43 +03:00
|
|
|
/*
|
|
|
|
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
|
|
|
recast4j copyright (c) 2015-2019 Piotr Piastucki piotr@jtilia.org
|
2023-03-15 17:00:29 +03:00
|
|
|
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
2023-03-14 08:02:43 +03:00
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
|
warranty. In no event will the authors be held liable for any damages
|
|
|
|
arising from the use of this software.
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
|
|
including commercial applications, and to alter it and redistribute it
|
|
|
|
freely, subject to the following restrictions:
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
|
|
claim that you wrote the original software. If you use this software
|
|
|
|
in a product, an acknowledgment in the product documentation would be
|
|
|
|
appreciated but is not required.
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
|
|
misrepresented as being the original software.
|
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
|
*/
|
|
|
|
|
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
2023-03-28 19:52:26 +03:00
|
|
|
using DotRecast.Core;
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-16 19:09:10 +03:00
|
|
|
namespace DotRecast.Detour.Crowd
|
|
|
|
{
|
2023-03-16 19:48:49 +03:00
|
|
|
/// Represents an agent managed by a #dtCrowd object.
|
|
|
|
/// @ingroup crowd
|
2023-06-08 15:38:02 +03:00
|
|
|
public class DtCrowdAgent
|
2023-03-16 19:48:49 +03:00
|
|
|
{
|
|
|
|
public readonly long idx;
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-16 19:48:49 +03:00
|
|
|
/// The type of mesh polygon the agent is traversing. (See: #CrowdAgentState)
|
|
|
|
public CrowdAgentState state;
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-16 19:48:49 +03:00
|
|
|
/// True if the agent has valid path (targetState == DT_CROWDAGENT_TARGET_VALID) and the path does not lead to the
|
|
|
|
/// requested position, else false.
|
|
|
|
public bool partial;
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-16 19:48:49 +03:00
|
|
|
/// The path corridor the agent is using.
|
2023-06-08 15:38:02 +03:00
|
|
|
public DtPathCorridor corridor;
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-16 19:48:49 +03:00
|
|
|
/// The local boundary data for the agent.
|
2023-06-08 15:38:02 +03:00
|
|
|
public DtLocalBoundary boundary;
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-16 19:48:49 +03:00
|
|
|
/// Time since the agent's path corridor was optimized.
|
|
|
|
public float topologyOptTime;
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-16 19:48:49 +03:00
|
|
|
/// The known neighbors of the agent.
|
2023-06-08 15:38:02 +03:00
|
|
|
public List<DtCrowdNeighbour> neis = new List<DtCrowdNeighbour>();
|
2023-03-16 19:48:49 +03:00
|
|
|
|
|
|
|
/// The desired speed.
|
|
|
|
public float desiredSpeed;
|
|
|
|
|
2023-06-03 15:47:26 +03:00
|
|
|
public RcVec3f npos = new RcVec3f();
|
2023-03-16 19:48:49 +03:00
|
|
|
|
|
|
|
/// < The current agent position. [(x, y, z)]
|
2023-06-03 15:47:26 +03:00
|
|
|
public RcVec3f disp = new RcVec3f();
|
2023-03-16 19:48:49 +03:00
|
|
|
|
|
|
|
/// < A temporary value used to accumulate agent displacement during iterative
|
|
|
|
/// collision resolution. [(x, y, z)]
|
2023-06-03 15:47:26 +03:00
|
|
|
public RcVec3f dvel = new RcVec3f();
|
2023-03-16 19:48:49 +03:00
|
|
|
|
|
|
|
/// < The desired velocity of the agent. Based on the current path, calculated
|
|
|
|
/// from
|
|
|
|
/// scratch each frame. [(x, y, z)]
|
2023-06-03 15:47:26 +03:00
|
|
|
public RcVec3f nvel = new RcVec3f();
|
2023-03-16 19:48:49 +03:00
|
|
|
|
|
|
|
/// < The desired velocity adjusted by obstacle avoidance, calculated from scratch each
|
|
|
|
/// frame. [(x, y, z)]
|
2023-06-03 15:47:26 +03:00
|
|
|
public RcVec3f vel = new RcVec3f();
|
2023-03-16 19:48:49 +03:00
|
|
|
|
|
|
|
/// < The actual velocity of the agent. The change from nvel -> vel is
|
|
|
|
/// constrained by max acceleration. [(x, y, z)]
|
|
|
|
/// The agent's configuration parameters.
|
2023-06-08 15:38:02 +03:00
|
|
|
public DtCrowdAgentParams option;
|
2023-03-16 19:48:49 +03:00
|
|
|
|
|
|
|
/// The local path corridor corners for the agent.
|
|
|
|
public List<StraightPathItem> corners = new List<StraightPathItem>();
|
|
|
|
|
|
|
|
public MoveRequestState targetState;
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-16 19:48:49 +03:00
|
|
|
/// < State of the movement request.
|
|
|
|
public long targetRef;
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-16 19:48:49 +03:00
|
|
|
/// < Target polyref of the movement request.
|
2023-06-03 15:47:26 +03:00
|
|
|
public RcVec3f targetPos = new RcVec3f();
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-16 19:48:49 +03:00
|
|
|
/// < Target position of the movement request (or velocity in case of
|
|
|
|
/// DT_CROWDAGENT_TARGET_VELOCITY).
|
2023-06-08 15:38:02 +03:00
|
|
|
public DtPathQueryResult targetPathQueryResult;
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-16 19:48:49 +03:00
|
|
|
/// < Path finder query
|
|
|
|
public bool targetReplan;
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-16 19:48:49 +03:00
|
|
|
/// < Flag indicating that the current path is being replanned.
|
|
|
|
public float targetReplanTime;
|
2023-03-14 08:02:43 +03:00
|
|
|
|
2023-03-16 19:48:49 +03:00
|
|
|
/// <Time since the agent's target was replanned.
|
|
|
|
public float targetReplanWaitTime;
|
|
|
|
|
2023-06-08 15:38:02 +03:00
|
|
|
public DtCrowdAgentAnimation animation;
|
2023-03-16 19:48:49 +03:00
|
|
|
|
2023-06-08 15:38:02 +03:00
|
|
|
public DtCrowdAgent(int idx)
|
2023-03-16 19:48:49 +03:00
|
|
|
{
|
|
|
|
this.idx = idx;
|
2023-06-08 15:38:02 +03:00
|
|
|
corridor = new DtPathCorridor();
|
|
|
|
boundary = new DtLocalBoundary();
|
|
|
|
animation = new DtCrowdAgentAnimation();
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
|
|
|
|
2023-05-05 02:44:48 +03:00
|
|
|
public void Integrate(float dt)
|
2023-03-16 19:48:49 +03:00
|
|
|
{
|
|
|
|
// Fake dynamic constraint.
|
|
|
|
float maxDelta = option.maxAcceleration * dt;
|
2023-06-03 15:47:26 +03:00
|
|
|
RcVec3f dv = nvel.Subtract(vel);
|
2023-05-18 02:25:57 +03:00
|
|
|
float ds = dv.Length();
|
2023-03-16 19:48:49 +03:00
|
|
|
if (ds > maxDelta)
|
2023-05-20 05:02:59 +03:00
|
|
|
dv = dv.Scale(maxDelta / ds);
|
2023-05-18 02:15:50 +03:00
|
|
|
vel = vel.Add(dv);
|
2023-03-16 19:48:49 +03:00
|
|
|
|
|
|
|
// Integrate
|
2023-05-18 02:25:57 +03:00
|
|
|
if (vel.Length() > 0.0001f)
|
2023-06-03 15:47:26 +03:00
|
|
|
npos = RcVec3f.Mad(npos, vel, dt);
|
2023-03-16 19:48:49 +03:00
|
|
|
else
|
2023-06-03 15:47:26 +03:00
|
|
|
vel = RcVec3f.Zero;
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
|
|
|
|
2023-05-05 02:44:48 +03:00
|
|
|
public bool OverOffmeshConnection(float radius)
|
2023-03-16 19:48:49 +03:00
|
|
|
{
|
|
|
|
if (0 == corners.Count)
|
|
|
|
return false;
|
|
|
|
|
2023-05-05 02:44:48 +03:00
|
|
|
bool offMeshConnection = ((corners[corners.Count - 1].GetFlags()
|
2023-06-08 15:38:02 +03:00
|
|
|
& DtNavMeshQuery.DT_STRAIGHTPATH_OFFMESH_CONNECTION) != 0)
|
2023-03-16 19:48:49 +03:00
|
|
|
? true
|
|
|
|
: false;
|
|
|
|
if (offMeshConnection)
|
|
|
|
{
|
2023-06-03 15:47:26 +03:00
|
|
|
float distSq = RcVec3f.Dist2DSqr(npos, corners[corners.Count - 1].GetPos());
|
2023-03-16 19:48:49 +03:00
|
|
|
if (distSq < radius * radius)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2023-03-14 08:02:43 +03:00
|
|
|
}
|
|
|
|
|
2023-05-05 02:44:48 +03:00
|
|
|
public float GetDistanceToGoal(float range)
|
2023-03-16 19:48:49 +03:00
|
|
|
{
|
|
|
|
if (0 == corners.Count)
|
|
|
|
return range;
|
|
|
|
|
2023-06-08 15:38:02 +03:00
|
|
|
bool endOfPath = ((corners[corners.Count - 1].GetFlags() & DtNavMeshQuery.DT_STRAIGHTPATH_END) != 0) ? true : false;
|
2023-03-16 19:48:49 +03:00
|
|
|
if (endOfPath)
|
2023-06-03 15:47:26 +03:00
|
|
|
return Math.Min(RcVec3f.Dist2D(npos, corners[corners.Count - 1].GetPos()), range);
|
2023-03-16 19:48:49 +03:00
|
|
|
|
|
|
|
return range;
|
|
|
|
}
|
|
|
|
|
2023-06-03 15:47:26 +03:00
|
|
|
public RcVec3f CalcSmoothSteerDirection()
|
2023-03-16 19:48:49 +03:00
|
|
|
{
|
2023-06-03 15:47:26 +03:00
|
|
|
RcVec3f dir = new RcVec3f();
|
2023-03-16 19:48:49 +03:00
|
|
|
if (0 < corners.Count)
|
|
|
|
{
|
|
|
|
int ip0 = 0;
|
|
|
|
int ip1 = Math.Min(1, corners.Count - 1);
|
2023-05-05 02:44:48 +03:00
|
|
|
var p0 = corners[ip0].GetPos();
|
|
|
|
var p1 = corners[ip1].GetPos();
|
2023-03-16 19:48:49 +03:00
|
|
|
|
2023-05-14 10:57:57 +03:00
|
|
|
var dir0 = p0.Subtract(npos);
|
|
|
|
var dir1 = p1.Subtract(npos);
|
2023-04-29 07:06:21 +03:00
|
|
|
dir0.y = 0;
|
|
|
|
dir1.y = 0;
|
2023-03-16 19:48:49 +03:00
|
|
|
|
2023-05-18 02:25:57 +03:00
|
|
|
float len0 = dir0.Length();
|
|
|
|
float len1 = dir1.Length();
|
2023-03-16 19:48:49 +03:00
|
|
|
if (len1 > 0.001f)
|
2023-05-20 05:02:59 +03:00
|
|
|
dir1 = dir1.Scale(1.0f / len1);
|
2023-03-16 19:48:49 +03:00
|
|
|
|
2023-04-29 07:06:21 +03:00
|
|
|
dir.x = dir0.x - dir1.x * len0 * 0.5f;
|
|
|
|
dir.y = 0;
|
|
|
|
dir.z = dir0.z - dir1.z * len0 * 0.5f;
|
2023-05-15 17:25:50 +03:00
|
|
|
dir.Normalize();
|
2023-03-16 19:48:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return dir;
|
|
|
|
}
|
|
|
|
|
2023-06-03 15:47:26 +03:00
|
|
|
public RcVec3f CalcStraightSteerDirection()
|
2023-03-16 19:48:49 +03:00
|
|
|
{
|
2023-06-03 15:47:26 +03:00
|
|
|
RcVec3f dir = new RcVec3f();
|
2023-03-16 19:48:49 +03:00
|
|
|
if (0 < corners.Count)
|
|
|
|
{
|
2023-05-14 10:57:57 +03:00
|
|
|
dir = corners[0].GetPos().Subtract(npos);
|
2023-04-29 07:06:21 +03:00
|
|
|
dir.y = 0;
|
2023-05-15 17:25:50 +03:00
|
|
|
dir.Normalize();
|
2023-03-16 19:48:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return dir;
|
|
|
|
}
|
|
|
|
|
2023-06-03 15:47:26 +03:00
|
|
|
public void SetTarget(long refs, RcVec3f pos)
|
2023-03-16 19:48:49 +03:00
|
|
|
{
|
|
|
|
targetRef = refs;
|
2023-04-12 17:53:28 +03:00
|
|
|
targetPos = pos;
|
2023-03-16 19:48:49 +03:00
|
|
|
targetPathQueryResult = null;
|
|
|
|
if (targetRef != 0)
|
|
|
|
{
|
|
|
|
targetState = MoveRequestState.DT_CROWDAGENT_TARGET_REQUESTING;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
targetState = MoveRequestState.DT_CROWDAGENT_TARGET_FAILED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-05-07 12:15:22 +03:00
|
|
|
}
|