forked from mirror/DotRecast
149 lines
4.0 KiB
C#
149 lines
4.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using DotRecast.Core;
|
|
using DotRecast.Recast.Geom;
|
|
|
|
namespace DotRecast.Recast.Toolset.Tools
|
|
{
|
|
public class RcConvexVolumeTool : IRcToolable
|
|
{
|
|
private readonly List<RcVec3f> _pts;
|
|
private readonly List<int> _hull;
|
|
|
|
public RcConvexVolumeTool()
|
|
{
|
|
_pts = new List<RcVec3f>();
|
|
_hull = new List<int>();
|
|
}
|
|
|
|
public string GetName()
|
|
{
|
|
return "Convex Volumes";
|
|
}
|
|
|
|
public List<RcVec3f> GetShapePoint()
|
|
{
|
|
return _pts;
|
|
}
|
|
|
|
public List<int> GetShapeHull()
|
|
{
|
|
return _hull;
|
|
}
|
|
|
|
public void ClearShape()
|
|
{
|
|
_pts.Clear();
|
|
_hull.Clear();
|
|
}
|
|
|
|
public bool PlottingShape(RcVec3f p, out List<RcVec3f> pts, out List<int> hull)
|
|
{
|
|
pts = null;
|
|
hull = null;
|
|
|
|
// Create
|
|
// If clicked on that last pt, create the shape.
|
|
if (_pts.Count > 0 && RcVec3f.DistSqr(p, _pts[_pts.Count - 1]) < 0.2f * 0.2f)
|
|
{
|
|
pts = new List<RcVec3f>(_pts);
|
|
hull = new List<int>(_hull);
|
|
|
|
_pts.Clear();
|
|
_hull.Clear();
|
|
|
|
return true;
|
|
}
|
|
|
|
// Add new point
|
|
_pts.Add(p);
|
|
|
|
// Update hull.
|
|
if (_pts.Count > 3)
|
|
{
|
|
_hull.Clear();
|
|
_hull.AddRange(RcConvexUtils.Convexhull(_pts));
|
|
}
|
|
else
|
|
{
|
|
_hull.Clear();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
public RcConvexVolume RemoveByPos(IInputGeomProvider geom, RcVec3f pos)
|
|
{
|
|
// Delete
|
|
int nearestIndex = -1;
|
|
IList<RcConvexVolume> vols = geom.ConvexVolumes();
|
|
for (int i = 0; i < vols.Count; ++i)
|
|
{
|
|
if (PolyUtils.PointInPoly(vols[i].verts, pos) && pos.y >= vols[i].hmin
|
|
&& pos.y <= vols[i].hmax)
|
|
{
|
|
nearestIndex = i;
|
|
}
|
|
}
|
|
|
|
// If end point close enough, delete it.
|
|
if (nearestIndex == -1)
|
|
return null;
|
|
|
|
var removal = geom.ConvexVolumes()[nearestIndex];
|
|
geom.ConvexVolumes().RemoveAt(nearestIndex);
|
|
return removal;
|
|
}
|
|
|
|
public void Add(IInputGeomProvider geom, RcConvexVolume volume)
|
|
{
|
|
geom.AddConvexVolume(volume);
|
|
}
|
|
|
|
public static RcConvexVolume CreateConvexVolume(List<RcVec3f> pts, List<int> hull, RcAreaModification areaType, float boxDescent, float boxHeight, float polyOffset)
|
|
{
|
|
//
|
|
if (hull.Count <= 2)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// Create shape.
|
|
float[] verts = new float[hull.Count * 3];
|
|
for (int i = 0; i < hull.Count; ++i)
|
|
{
|
|
verts[i * 3] = pts[hull[i]].x;
|
|
verts[i * 3 + 1] = pts[hull[i]].y;
|
|
verts[i * 3 + 2] = pts[hull[i]].z;
|
|
}
|
|
|
|
float minh = float.MaxValue, maxh = 0;
|
|
for (int i = 0; i < hull.Count; ++i)
|
|
{
|
|
minh = Math.Min(minh, verts[i * 3 + 1]);
|
|
}
|
|
|
|
minh -= boxDescent;
|
|
maxh = minh + boxHeight;
|
|
|
|
if (polyOffset > 0.01f)
|
|
{
|
|
float[] offset = new float[verts.Length * 2];
|
|
int noffset = PolyUtils.OffsetPoly(verts, hull.Count, polyOffset, offset, offset.Length);
|
|
if (noffset > 0)
|
|
{
|
|
verts = RcArrayUtils.CopyOf(offset, 0, noffset * 3);
|
|
}
|
|
}
|
|
|
|
return new RcConvexVolume()
|
|
{
|
|
verts = verts,
|
|
hmin = minh,
|
|
hmax = maxh,
|
|
areaMod = areaType,
|
|
};
|
|
}
|
|
}
|
|
} |