change convexVolume tool impl for unity3d

This commit is contained in:
ikpil 2023-07-06 00:01:53 +09:00
parent bb047c5a1d
commit 846e1a9b65
4 changed files with 98 additions and 82 deletions

View File

@ -25,17 +25,15 @@ namespace DotRecast.Core
// Calculates convex hull on xz-plane of points on 'pts', // Calculates convex hull on xz-plane of points on 'pts',
// stores the indices of the resulting hull in 'out' and // stores the indices of the resulting hull in 'out' and
// returns number of points on hull. // returns number of points on hull.
public static List<int> Convexhull(List<float> pts) public static List<int> Convexhull(List<RcVec3f> pts)
{ {
int npts = pts.Count / 3; int npts = pts.Count;
List<int> @out = new List<int>(); List<int> @out = new List<int>();
// Find lower-leftmost point. // Find lower-leftmost point.
int hull = 0; int hull = 0;
for (int i = 1; i < npts; ++i) for (int i = 1; i < npts; ++i)
{ {
RcVec3f a = RcVec3f.Of(pts[i * 3], pts[i * 3 + 1], pts[i * 3 + 2]); if (Cmppt(pts[i], pts[hull]))
RcVec3f b = RcVec3f.Of(pts[hull * 3], pts[hull * 3 + 1], pts[hull * 3 + 2]);
if (Cmppt(a, b))
{ {
hull = i; hull = i;
} }
@ -49,9 +47,9 @@ namespace DotRecast.Core
endpt = 0; endpt = 0;
for (int j = 1; j < npts; ++j) for (int j = 1; j < npts; ++j)
{ {
RcVec3f a = RcVec3f.Of(pts[hull * 3], pts[hull * 3 + 1], pts[hull * 3 + 2]); RcVec3f a = pts[hull];
RcVec3f b = RcVec3f.Of(pts[endpt * 3], pts[endpt * 3 + 1], pts[endpt * 3 + 2]); RcVec3f b = pts[endpt];
RcVec3f c = RcVec3f.Of(pts[j * 3], pts[j * 3 + 1], pts[j * 3 + 2]); RcVec3f c = pts[j];
if (hull == endpt || Left(a, b, c)) if (hull == endpt || Left(a, b, c))
{ {
endpt = j; endpt = j;
@ -100,4 +98,4 @@ namespace DotRecast.Core
return u1 * v2 - v1 * u2 < 0; return u1 * v2 - v1 * u2 < 0;
} }
} }
} }

View File

@ -35,13 +35,13 @@ namespace DotRecast.Recast.Demo.Tools;
public class ConvexVolumeTool : IRcTool public class ConvexVolumeTool : IRcTool
{ {
private readonly ConvexVolumeToolImpl _impl; private readonly ConvexVolumeToolImpl _impl;
private int areaTypeValue = SampleAreaModifications.SAMPLE_AREAMOD_GRASS.Value; private int areaTypeValue = SampleAreaModifications.SAMPLE_AREAMOD_GRASS.Value;
private AreaModification areaType = SampleAreaModifications.SAMPLE_AREAMOD_GRASS; private AreaModification areaType = SampleAreaModifications.SAMPLE_AREAMOD_GRASS;
private float boxHeight = 6f; private float boxHeight = 6f;
private float boxDescent = 1f; private float boxDescent = 1f;
private float polyOffset = 0f; private float polyOffset = 0f;
private readonly List<float> pts = new(); private readonly List<RcVec3f> pts = new();
private readonly List<int> hull = new(); private readonly List<int> hull = new();
public ConvexVolumeTool() public ConvexVolumeTool()
@ -69,65 +69,16 @@ public class ConvexVolumeTool : IRcTool
if (shift) if (shift)
{ {
// Delete _impl.RemoveByPos(p);
int nearestIndex = -1;
IList<ConvexVolume> vols = geom.ConvexVolumes();
for (int i = 0; i < vols.Count; ++i)
{
if (PolyUtils.PointInPoly(vols[i].verts, p) && p.y >= vols[i].hmin
&& p.y <= vols[i].hmax)
{
nearestIndex = i;
}
}
// If end point close enough, delete it.
if (nearestIndex != -1)
{
geom.ConvexVolumes().RemoveAt(nearestIndex);
}
} }
else else
{ {
// Create // Create
// If clicked on that last pt, create the shape. // If clicked on that last pt, create the shape.
if (pts.Count > 0 && RcVec3f.DistSqr(p, RcVec3f.Of(pts[pts.Count - 3], pts[pts.Count - 2], pts[pts.Count - 1])) < 0.2f * 0.2f) if (pts.Count > 0 && RcVec3f.DistSqr(p, pts[pts.Count - 1]) < 0.2f * 0.2f)
{ {
if (hull.Count > 2) _impl.Add(pts, hull, areaType, boxDescent, boxHeight, polyOffset);
{
// Create shape.
float[] verts = new float[hull.Count * 3];
for (int i = 0; i < hull.Count; ++i)
{
verts[i * 3] = pts[hull[i] * 3];
verts[i * 3 + 1] = pts[hull[i] * 3 + 1];
verts[i * 3 + 2] = pts[hull[i] * 3 + 2];
}
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)
{
geom.AddConvexVolume(RcArrayUtils.CopyOf(offset, 0, noffset * 3), minh, maxh, areaType);
}
}
else
{
geom.AddConvexVolume(verts, minh, maxh, areaType);
}
}
pts.Clear(); pts.Clear();
hull.Clear(); hull.Clear();
@ -135,9 +86,8 @@ public class ConvexVolumeTool : IRcTool
else else
{ {
// Add new point // Add new point
pts.Add(p.x); pts.Add(p);
pts.Add(p.y);
pts.Add(p.z);
// Update hull. // Update hull.
if (pts.Count > 3) if (pts.Count > 3)
{ {
@ -157,24 +107,24 @@ public class ConvexVolumeTool : IRcTool
RecastDebugDraw dd = renderer.GetDebugDraw(); RecastDebugDraw dd = renderer.GetDebugDraw();
// Find height extent of the shape. // Find height extent of the shape.
float minh = float.MaxValue, maxh = 0; float minh = float.MaxValue, maxh = 0;
for (int i = 0; i < pts.Count; i += 3) for (int i = 0; i < pts.Count; ++i)
{ {
minh = Math.Min(minh, pts[i + 1]); minh = Math.Min(minh, pts[i].y);
} }
minh -= boxDescent; minh -= boxDescent;
maxh = minh + boxHeight; maxh = minh + boxHeight;
dd.Begin(POINTS, 4.0f); dd.Begin(POINTS, 4.0f);
for (int i = 0; i < pts.Count; i += 3) for (int i = 0; i < pts.Count; ++i)
{ {
int col = DuRGBA(255, 255, 255, 255); int col = DuRGBA(255, 255, 255, 255);
if (i == pts.Count - 3) if (i == pts.Count - 1)
{ {
col = DuRGBA(240, 32, 16, 255); col = DuRGBA(240, 32, 16, 255);
} }
dd.Vertex(pts[i + 0], pts[i + 1] + 0.1f, pts[i + 2], col); dd.Vertex(pts[i].x, pts[i].y + 0.1f, pts[i].z, col);
} }
dd.End(); dd.End();
@ -182,14 +132,14 @@ public class ConvexVolumeTool : IRcTool
dd.Begin(LINES, 2.0f); dd.Begin(LINES, 2.0f);
for (int i = 0, j = hull.Count - 1; i < hull.Count; j = i++) for (int i = 0, j = hull.Count - 1; i < hull.Count; j = i++)
{ {
int vi = hull[j] * 3; int vi = hull[j];
int vj = hull[i] * 3; int vj = hull[i];
dd.Vertex(pts[vj + 0], minh, pts[vj + 2], DuRGBA(255, 255, 255, 64)); dd.Vertex(pts[vj].x, minh, pts[vj].z, DuRGBA(255, 255, 255, 64));
dd.Vertex(pts[vi + 0], minh, pts[vi + 2], DuRGBA(255, 255, 255, 64)); dd.Vertex(pts[vi].x, minh, pts[vi].z, DuRGBA(255, 255, 255, 64));
dd.Vertex(pts[vj + 0], maxh, pts[vj + 2], DuRGBA(255, 255, 255, 64)); dd.Vertex(pts[vj].x, maxh, pts[vj].z, DuRGBA(255, 255, 255, 64));
dd.Vertex(pts[vi + 0], maxh, pts[vi + 2], DuRGBA(255, 255, 255, 64)); dd.Vertex(pts[vi].x, maxh, pts[vi].z, DuRGBA(255, 255, 255, 64));
dd.Vertex(pts[vj + 0], minh, pts[vj + 2], DuRGBA(255, 255, 255, 64)); dd.Vertex(pts[vj].x, minh, pts[vj].z, DuRGBA(255, 255, 255, 64));
dd.Vertex(pts[vj + 0], maxh, pts[vj + 2], DuRGBA(255, 255, 255, 64)); dd.Vertex(pts[vj].x, maxh, pts[vj].z, DuRGBA(255, 255, 255, 64));
} }
dd.End(); dd.End();

View File

@ -1,9 +1,13 @@
namespace DotRecast.Recast.DemoTool.Tools using System;
using System.Collections.Generic;
using DotRecast.Core;
namespace DotRecast.Recast.DemoTool.Tools
{ {
public class ConvexVolumeToolImpl : ISampleTool public class ConvexVolumeToolImpl : ISampleTool
{ {
private Sample _sample; private Sample _sample;
public string GetName() public string GetName()
{ {
return "Create Convex Volumes"; return "Create Convex Volumes";
@ -19,5 +23,69 @@
return _sample; return _sample;
} }
public ConvexVolume RemoveByPos(RcVec3f pos)
{
var geom = _sample.GetInputGeom();
// Delete
int nearestIndex = -1;
IList<ConvexVolume> 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(List<RcVec3f> pts, List<int> hull, AreaModification areaType, float boxDescent, float boxHeight, float polyOffset)
{
//
if (hull.Count <= 2)
return;
// 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;
var geom = _sample.GetInputGeom();
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)
{
geom.AddConvexVolume(RcArrayUtils.CopyOf(offset, 0, noffset * 3), minh, maxh, areaType);
}
}
else
{
geom.AddConvexVolume(verts, minh, maxh, areaType);
}
}
} }
} }

View File

@ -45,7 +45,7 @@ namespace DotRecast.Recast
public static int OffsetPoly(float[] verts, int nverts, float offset, float[] outVerts, int maxOutVerts) public static int OffsetPoly(float[] verts, int nverts, float offset, float[] outVerts, int maxOutVerts)
{ {
float MITER_LIMIT = 1.20f; const float MITER_LIMIT = 1.20f;
int n = 0; int n = 0;