refactor: DynamicUpdateSampleTool

This commit is contained in:
ikpil 2023-09-10 16:03:10 +09:00
parent c03d3053c5
commit ab50f0fd53
21 changed files with 674 additions and 634 deletions

View File

@ -0,0 +1,193 @@
using DotRecast.Core;
using DotRecast.Detour.Dynamic.Colliders;
using DotRecast.Recast.Toolset.Tools.Gizmos;
using DotRecast.Recast.Demo.Draw;
using static DotRecast.Core.RcMath;
namespace DotRecast.Recast.Demo.Tools;
public class ColliderWithGizmo
{
public readonly IRcGizmoMeshFilter Gizmo;
public readonly ICollider Collider;
public ColliderWithGizmo(ICollider collider, IRcGizmoMeshFilter gizmo)
{
Collider = collider;
Gizmo = gizmo;
}
public void Render(RecastDebugDraw dd)
{
Render(dd, Gizmo);
}
public static void Render(RecastDebugDraw dd, IRcGizmoMeshFilter gizmo)
{
if (gizmo is BoxGizmo box)
{
RenderBox(dd, box);
}
else if (gizmo is CapsuleGizmo capsule)
{
RenderCapsule(dd, capsule);
}
else if (gizmo is TrimeshGizmo trimesh)
{
RenderTrimesh(dd, trimesh);
}
else if (gizmo is CylinderGizmo cylinder)
{
RenderCylinder(dd, cylinder);
}
else if (gizmo is SphereGizmo sphere)
{
RenderSphere(dd, sphere);
}
else if (gizmo is CompositeGizmo composite)
{
RenderComposite(dd, composite);
}
}
public static int GetColorByNormal(float[] vertices, int v0, int v1, int v2)
{
RcVec3f e0 = new RcVec3f();
RcVec3f e1 = new RcVec3f();
RcVec3f normal = new RcVec3f();
for (int j = 0; j < 3; ++j)
{
e0[j] = vertices[v1 + j] - vertices[v0 + j];
e1[j] = vertices[v2 + j] - vertices[v0 + j];
}
normal.x = e0.y * e1.z - e0.z * e1.y;
normal.y = e0.z * e1.x - e0.x * e1.z;
normal.z = e0.x * e1.y - e0.y * e1.x;
RcVec3f.Normalize(ref normal);
float c = Clamp(0.57735026f * (normal.x + normal.y + normal.z), -1, 1);
int col = DebugDraw.DuLerpCol(
DebugDraw.DuRGBA(32, 32, 0, 160),
DebugDraw.DuRGBA(220, 220, 0, 160),
(int)(127 * (1 + c))
);
return col;
}
public static void RenderBox(RecastDebugDraw debugDraw, BoxGizmo box)
{
var trX = RcVec3f.Of(box.halfEdges[0].x, box.halfEdges[1].x, box.halfEdges[2].x);
var trY = RcVec3f.Of(box.halfEdges[0].y, box.halfEdges[1].y, box.halfEdges[2].y);
var trZ = RcVec3f.Of(box.halfEdges[0].z, box.halfEdges[1].z, box.halfEdges[2].z);
float[] vertices = new float[8 * 3];
for (int i = 0; i < 8; i++)
{
vertices[i * 3 + 0] = RcVec3f.Dot(BoxGizmo.VERTS[i], trX) + box.center.x;
vertices[i * 3 + 1] = RcVec3f.Dot(BoxGizmo.VERTS[i], trY) + box.center.y;
vertices[i * 3 + 2] = RcVec3f.Dot(BoxGizmo.VERTS[i], trZ) + box.center.z;
}
debugDraw.Begin(DebugDrawPrimitives.TRIS);
for (int i = 0; i < 12; i++)
{
int col = DebugDraw.DuRGBA(200, 200, 50, 160);
if (i == 4 || i == 5 || i == 8 || i == 9)
{
col = DebugDraw.DuRGBA(160, 160, 40, 160);
}
else if (i > 4)
{
col = DebugDraw.DuRGBA(120, 120, 30, 160);
}
for (int j = 0; j < 3; j++)
{
int v = BoxGizmo.TRIANLGES[i * 3 + j] * 3;
debugDraw.Vertex(vertices[v], vertices[v + 1], vertices[v + 2], col);
}
}
debugDraw.End();
}
public static void RenderCapsule(RecastDebugDraw debugDraw, CapsuleGizmo capsule)
{
debugDraw.Begin(DebugDrawPrimitives.TRIS);
for (int i = 0; i < capsule.triangles.Length; i += 3)
{
for (int j = 0; j < 3; j++)
{
int v = capsule.triangles[i + j] * 3;
float c = capsule.gradient[capsule.triangles[i + j]];
int col = DebugDraw.DuLerpCol(DebugDraw.DuRGBA(32, 32, 0, 160), DebugDraw.DuRGBA(220, 220, 0, 160),
(int)(127 * (1 + c)));
debugDraw.Vertex(capsule.vertices[v], capsule.vertices[v + 1], capsule.vertices[v + 2], col);
}
}
debugDraw.End();
}
public static void RenderCylinder(RecastDebugDraw debugDraw, CylinderGizmo cylinder)
{
debugDraw.Begin(DebugDrawPrimitives.TRIS);
for (int i = 0; i < cylinder.triangles.Length; i += 3)
{
for (int j = 0; j < 3; j++)
{
int v = cylinder.triangles[i + j] * 3;
float c = cylinder.gradient[cylinder.triangles[i + j]];
int col = DebugDraw.DuLerpCol(DebugDraw.DuRGBA(32, 32, 0, 160), DebugDraw.DuRGBA(220, 220, 0, 160),
(int)(127 * (1 + c)));
debugDraw.Vertex(cylinder.vertices[v], cylinder.vertices[v + 1], cylinder.vertices[v + 2], col);
}
}
debugDraw.End();
}
public static void RenderSphere(RecastDebugDraw debugDraw, SphereGizmo sphere)
{
debugDraw.Begin(DebugDrawPrimitives.TRIS);
for (int i = 0; i < sphere.triangles.Length; i += 3)
{
for (int j = 0; j < 3; j++)
{
int v = sphere.triangles[i + j] * 3;
float c = Clamp(0.57735026f * (sphere.vertices[v] + sphere.vertices[v + 1] + sphere.vertices[v + 2]), -1, 1);
int col = DebugDraw.DuLerpCol(DebugDraw.DuRGBA(32, 32, 0, 160), DebugDraw.DuRGBA(220, 220, 0, 160), (int)(127 * (1 + c)));
debugDraw.Vertex(
sphere.radius * sphere.vertices[v] + sphere.center.x,
sphere.radius * sphere.vertices[v + 1] + sphere.center.y,
sphere.radius * sphere.vertices[v + 2] + sphere.center.z,
col
);
}
}
debugDraw.End();
}
public static void RenderTrimesh(RecastDebugDraw debugDraw, TrimeshGizmo trimesh)
{
debugDraw.Begin(DebugDrawPrimitives.TRIS);
for (int i = 0; i < trimesh.triangles.Length; i += 3)
{
int v0 = 3 * trimesh.triangles[i];
int v1 = 3 * trimesh.triangles[i + 1];
int v2 = 3 * trimesh.triangles[i + 2];
int col = GetColorByNormal(trimesh.vertices, v0, v1, v2);
debugDraw.Vertex(trimesh.vertices[v0], trimesh.vertices[v0 + 1], trimesh.vertices[v0 + 2], col);
debugDraw.Vertex(trimesh.vertices[v1], trimesh.vertices[v1 + 1], trimesh.vertices[v1 + 2], col);
debugDraw.Vertex(trimesh.vertices[v2], trimesh.vertices[v2 + 1], trimesh.vertices[v2 + 2], col);
}
debugDraw.End();
}
public static void RenderComposite(RecastDebugDraw debugDraw, CompositeGizmo composite)
{
composite.gizmoMeshes.ForEach(g => Render(debugDraw, g));
}
}

View File

@ -29,7 +29,7 @@ using DotRecast.Detour.Dynamic.Io;
using DotRecast.Recast.Toolset.Builder; using DotRecast.Recast.Toolset.Builder;
using DotRecast.Recast.Demo.Draw; using DotRecast.Recast.Demo.Draw;
using DotRecast.Recast.Toolset.Geom; using DotRecast.Recast.Toolset.Geom;
using DotRecast.Recast.Demo.Tools.Gizmos; using DotRecast.Recast.Toolset.Tools.Gizmos;
using DotRecast.Recast.Demo.UI; using DotRecast.Recast.Demo.UI;
using DotRecast.Recast.Toolset; using DotRecast.Recast.Toolset;
using DotRecast.Recast.Toolset.Tools; using DotRecast.Recast.Toolset.Tools;
@ -75,8 +75,7 @@ public class DynamicUpdateSampleTool : ISampleTool
private DynamicNavMesh dynaMesh; private DynamicNavMesh dynaMesh;
private readonly TaskFactory executor; private readonly TaskFactory executor;
private readonly Dictionary<long, ICollider> colliders = new(); private readonly Dictionary<long, ColliderWithGizmo> colliderGizmos = new();
private readonly Dictionary<long, IColliderGizmo> colliderGizmos = new();
private readonly Random random = Random.Shared; private readonly Random random = Random.Shared;
private readonly DemoInputGeomProvider bridgeGeom; private readonly DemoInputGeomProvider bridgeGeom;
private readonly DemoInputGeomProvider houseGeom; private readonly DemoInputGeomProvider houseGeom;
@ -100,7 +99,7 @@ public class DynamicUpdateSampleTool : ISampleTool
public void Layout() public void Layout()
{ {
var prevModeIdx = mode.Idx; var prevModeIdx = mode.Idx;
ImGui.Text($"Dynamic Update Tool Modes"); ImGui.Text($"Dynamic Update Tool Modes");
ImGui.Separator(); ImGui.Separator();
ImGui.RadioButton(DynamicUpdateToolMode.BUILD.Label, ref prevModeIdx, DynamicUpdateToolMode.BUILD.Idx); ImGui.RadioButton(DynamicUpdateToolMode.BUILD.Label, ref prevModeIdx, DynamicUpdateToolMode.BUILD.Idx);
@ -280,7 +279,10 @@ public class DynamicUpdateSampleTool : ISampleTool
{ {
if (showColliders) if (showColliders)
{ {
colliderGizmos.Values.ForEach(g => g.Render(renderer.GetDebugDraw())); colliderGizmos.Values.ForEach(g =>
{
g.Render(renderer.GetDebugDraw());
});
} }
} }
@ -397,8 +399,7 @@ public class DynamicUpdateSampleTool : ISampleTool
if (colliderWithGizmo != null) if (colliderWithGizmo != null)
{ {
long id = dynaMesh.AddCollider(colliderWithGizmo.Collider); long id = dynaMesh.AddCollider(colliderWithGizmo.Collider);
colliders.Add(id, colliderWithGizmo.Collider); colliderGizmos.Add(id, colliderWithGizmo);
colliderGizmos.Add(id, colliderWithGizmo.Gizmo);
} }
} }
} }
@ -525,11 +526,11 @@ public class DynamicUpdateSampleTool : ISampleTool
SphereCollider crown = new SphereCollider(crownCenter, 4f, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GRASS, SphereCollider crown = new SphereCollider(crownCenter, 4f, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GRASS,
dynaMesh.config.walkableClimb); dynaMesh.config.walkableClimb);
CompositeCollider collider = new CompositeCollider(@base, roof, trunk, crown); CompositeCollider collider = new CompositeCollider(@base, roof, trunk, crown);
IColliderGizmo baseGizmo = GizmoFactory.Box(baseCenter, Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(baseUp, forward, baseExtent)); IRcGizmoMeshFilter baseGizmo = GizmoFactory.Box(baseCenter, Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(baseUp, forward, baseExtent));
IColliderGizmo roofGizmo = GizmoFactory.Box(roofCenter, Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(roofUp, forward, roofExtent)); IRcGizmoMeshFilter roofGizmo = GizmoFactory.Box(roofCenter, Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(roofUp, forward, roofExtent));
IColliderGizmo trunkGizmo = GizmoFactory.Capsule(trunkStart, trunkEnd, 0.5f); IRcGizmoMeshFilter trunkGizmo = GizmoFactory.Capsule(trunkStart, trunkEnd, 0.5f);
IColliderGizmo crownGizmo = GizmoFactory.Sphere(crownCenter, 4f); IRcGizmoMeshFilter crownGizmo = GizmoFactory.Sphere(crownCenter, 4f);
IColliderGizmo gizmo = GizmoFactory.Composite(baseGizmo, roofGizmo, trunkGizmo, crownGizmo); IRcGizmoMeshFilter gizmo = GizmoFactory.Composite(baseGizmo, roofGizmo, trunkGizmo, crownGizmo);
return new ColliderWithGizmo(collider, gizmo); return new ColliderWithGizmo(collider, gizmo);
} }
@ -610,12 +611,11 @@ public class DynamicUpdateSampleTool : ISampleTool
{ {
if (shift) if (shift)
{ {
foreach (var e in colliders) foreach (var e in colliderGizmos)
{ {
if (Hit(start, dir, e.Value.Bounds())) if (Hit(start, dir, e.Value.Collider.Bounds()))
{ {
dynaMesh.RemoveCollider(e.Key); dynaMesh.RemoveCollider(e.Key);
colliders.Remove(e.Key);
colliderGizmos.Remove(e.Key); colliderGizmos.Remove(e.Key);
break; break;
} }
@ -691,10 +691,11 @@ public class DynamicUpdateSampleTool : ISampleTool
VoxelFile voxelFile = reader.Read(br); VoxelFile voxelFile = reader.Read(br);
dynaMesh = new DynamicNavMesh(voxelFile); dynaMesh = new DynamicNavMesh(voxelFile);
dynaMesh.config.keepIntermediateResults = true; dynaMesh.config.keepIntermediateResults = true;
UpdateUI(); UpdateUI();
BuildDynaMesh(); BuildDynaMesh();
colliders.Clear(); colliderGizmos.Clear();
} }
catch (Exception e) catch (Exception e)
{ {

View File

@ -1,86 +0,0 @@
using DotRecast.Core;
using DotRecast.Detour.Dynamic.Colliders;
using DotRecast.Recast.Demo.Draw;
namespace DotRecast.Recast.Demo.Tools.Gizmos;
public class BoxGizmo : IColliderGizmo
{
private static readonly int[] TRIANLGES =
{
0, 1, 2, 0, 2, 3, 4, 7, 6, 4, 6, 5, 0, 4, 5, 0, 5, 1, 1, 5, 6, 1, 6, 2,
2, 6, 7, 2, 7, 3, 4, 0, 3, 4, 3, 7
};
private static readonly RcVec3f[] VERTS =
{
RcVec3f.Of(-1f, -1f, -1f),
RcVec3f.Of(1f, -1f, -1f),
RcVec3f.Of(1f, -1f, 1f),
RcVec3f.Of(-1f, -1f, 1f),
RcVec3f.Of(-1f, 1f, -1f),
RcVec3f.Of(1f, 1f, -1f),
RcVec3f.Of(1f, 1f, 1f),
RcVec3f.Of(-1f, 1f, 1f),
};
private readonly float[] vertices = new float[8 * 3];
private readonly RcVec3f center;
private readonly RcVec3f[] halfEdges;
public BoxGizmo(RcVec3f center, RcVec3f extent, RcVec3f forward, RcVec3f up) :
this(center, BoxCollider.GetHalfEdges(up, forward, extent))
{
}
public BoxGizmo(RcVec3f center, RcVec3f[] halfEdges)
{
this.center = center;
this.halfEdges = halfEdges;
for (int i = 0; i < 8; ++i)
{
float s0 = (i & 1) != 0 ? 1f : -1f;
float s1 = (i & 2) != 0 ? 1f : -1f;
float s2 = (i & 4) != 0 ? 1f : -1f;
vertices[i * 3 + 0] = center.x + s0 * halfEdges[0].x + s1 * halfEdges[1].x + s2 * halfEdges[2].x;
vertices[i * 3 + 1] = center.y + s0 * halfEdges[0].y + s1 * halfEdges[1].y + s2 * halfEdges[2].y;
vertices[i * 3 + 2] = center.z + s0 * halfEdges[0].z + s1 * halfEdges[1].z + s2 * halfEdges[2].z;
}
}
public void Render(RecastDebugDraw debugDraw)
{
var trX = RcVec3f.Of(halfEdges[0].x, halfEdges[1].x, halfEdges[2].x);
var trY = RcVec3f.Of(halfEdges[0].y, halfEdges[1].y, halfEdges[2].y);
var trZ = RcVec3f.Of(halfEdges[0].z, halfEdges[1].z, halfEdges[2].z);
float[] vertices = new float[8 * 3];
for (int i = 0; i < 8; i++)
{
vertices[i * 3 + 0] = RcVec3f.Dot(VERTS[i], trX) + center.x;
vertices[i * 3 + 1] = RcVec3f.Dot(VERTS[i], trY) + center.y;
vertices[i * 3 + 2] = RcVec3f.Dot(VERTS[i], trZ) + center.z;
}
debugDraw.Begin(DebugDrawPrimitives.TRIS);
for (int i = 0; i < 12; i++)
{
int col = DebugDraw.DuRGBA(200, 200, 50, 160);
if (i == 4 || i == 5 || i == 8 || i == 9)
{
col = DebugDraw.DuRGBA(160, 160, 40, 160);
}
else if (i > 4)
{
col = DebugDraw.DuRGBA(120, 120, 30, 160);
}
for (int j = 0; j < 3; j++)
{
int v = TRIANLGES[i * 3 + j] * 3;
debugDraw.Vertex(vertices[v], vertices[v + 1], vertices[v + 2], col);
}
}
debugDraw.End();
}
}

View File

@ -1,88 +0,0 @@
using DotRecast.Core;
using DotRecast.Recast.Demo.Draw;
using static DotRecast.Core.RcMath;
using static DotRecast.Recast.Demo.Tools.Gizmos.GizmoHelper;
namespace DotRecast.Recast.Demo.Tools.Gizmos;
public class CapsuleGizmo : IColliderGizmo
{
private readonly float[] vertices;
private readonly int[] triangles;
private readonly float[] center;
private readonly float[] gradient;
public CapsuleGizmo(RcVec3f start, RcVec3f end, float radius)
{
center = new float[]
{
0.5f * (start.x + end.x), 0.5f * (start.y + end.y),
0.5f * (start.z + end.z)
};
RcVec3f axis = RcVec3f.Of(end.x - start.x, end.y - start.y, end.z - start.z);
RcVec3f[] normals = new RcVec3f[3];
normals[1] = RcVec3f.Of(end.x - start.x, end.y - start.y, end.z - start.z);
RcVec3f.Normalize(ref normals[1]);
normals[0] = GetSideVector(axis);
normals[2] = RcVec3f.Zero;
RcVec3f.Cross(ref normals[2], normals[0], normals[1]);
RcVec3f.Normalize(ref normals[2]);
triangles = GenerateSphericalTriangles();
var trX = RcVec3f.Of(normals[0].x, normals[1].x, normals[2].x);
var trY = RcVec3f.Of(normals[0].y, normals[1].y, normals[2].y);
var trZ = RcVec3f.Of(normals[0].z, normals[1].z, normals[2].z);
float[] spVertices = GenerateSphericalVertices();
float halfLength = 0.5f * axis.Length();
vertices = new float[spVertices.Length];
gradient = new float[spVertices.Length / 3];
RcVec3f v = new RcVec3f();
for (int i = 0; i < spVertices.Length; i += 3)
{
float offset = (i >= spVertices.Length / 2) ? -halfLength : halfLength;
float x = radius * spVertices[i];
float y = radius * spVertices[i + 1] + offset;
float z = radius * spVertices[i + 2];
vertices[i] = x * trX.x + y * trX.y + z * trX.z + center[0];
vertices[i + 1] = x * trY.x + y * trY.y + z * trY.z + center[1];
vertices[i + 2] = x * trZ.x + y * trZ.y + z * trZ.z + center[2];
v.x = vertices[i] - center[0];
v.y = vertices[i + 1] - center[1];
v.z = vertices[i + 2] - center[2];
RcVec3f.Normalize(ref v);
gradient[i / 3] = Clamp(0.57735026f * (v.x + v.y + v.z), -1, 1);
}
}
private RcVec3f GetSideVector(RcVec3f axis)
{
RcVec3f side = RcVec3f.Of(1, 0, 0);
if (axis.x > 0.8)
{
side = RcVec3f.Of(0, 0, 1);
}
RcVec3f forward = new RcVec3f();
RcVec3f.Cross(ref forward, side, axis);
RcVec3f.Cross(ref side, axis, forward);
RcVec3f.Normalize(ref side);
return side;
}
public void Render(RecastDebugDraw debugDraw)
{
debugDraw.Begin(DebugDrawPrimitives.TRIS);
for (int i = 0; i < triangles.Length; i += 3)
{
for (int j = 0; j < 3; j++)
{
int v = triangles[i + j] * 3;
float c = gradient[triangles[i + j]];
int col = DebugDraw.DuLerpCol(DebugDraw.DuRGBA(32, 32, 0, 160), DebugDraw.DuRGBA(220, 220, 0, 160),
(int)(127 * (1 + c)));
debugDraw.Vertex(vertices[v], vertices[v + 1], vertices[v + 2], col);
}
}
debugDraw.End();
}
}

View File

@ -1,15 +0,0 @@
using DotRecast.Detour.Dynamic.Colliders;
namespace DotRecast.Recast.Demo.Tools.Gizmos;
public class ColliderWithGizmo
{
public readonly ICollider Collider;
public readonly IColliderGizmo Gizmo;
public ColliderWithGizmo(ICollider collider, IColliderGizmo gizmo)
{
Collider = collider;
Gizmo = gizmo;
}
}

View File

@ -1,20 +0,0 @@
using System;
using DotRecast.Core;
using DotRecast.Recast.Demo.Draw;
namespace DotRecast.Recast.Demo.Tools.Gizmos;
public class CompositeGizmo : IColliderGizmo
{
private readonly IColliderGizmo[] gizmos;
public CompositeGizmo(params IColliderGizmo[] gizmos)
{
this.gizmos = gizmos;
}
public void Render(RecastDebugDraw debugDraw)
{
gizmos.ForEach(g => g.Render(debugDraw));
}
}

View File

@ -1,94 +0,0 @@
using DotRecast.Core;
using DotRecast.Recast.Demo.Draw;
using static DotRecast.Core.RcMath;
using static DotRecast.Recast.Demo.Tools.Gizmos.GizmoHelper;
namespace DotRecast.Recast.Demo.Tools.Gizmos;
public class CylinderGizmo : IColliderGizmo
{
private readonly float[] vertices;
private readonly int[] triangles;
private readonly RcVec3f center;
private readonly float[] gradient;
public CylinderGizmo(RcVec3f start, RcVec3f end, float radius)
{
center = RcVec3f.Of(
0.5f * (start.x + end.x), 0.5f * (start.y + end.y),
0.5f * (start.z + end.z)
);
RcVec3f axis = RcVec3f.Of(end.x - start.x, end.y - start.y, end.z - start.z);
RcVec3f[] normals = new RcVec3f[3];
normals[1] = RcVec3f.Of(end.x - start.x, end.y - start.y, end.z - start.z);
RcVec3f.Normalize(ref normals[1]);
normals[0] = GetSideVector(axis);
normals[2] = RcVec3f.Zero;
RcVec3f.Cross(ref normals[2], normals[0], normals[1]);
RcVec3f.Normalize(ref normals[2]);
triangles = GenerateCylindricalTriangles();
RcVec3f trX = RcVec3f.Of(normals[0].x, normals[1].x, normals[2].x);
RcVec3f trY = RcVec3f.Of(normals[0].y, normals[1].y, normals[2].y);
RcVec3f trZ = RcVec3f.Of(normals[0].z, normals[1].z, normals[2].z);
vertices = GenerateCylindricalVertices();
float halfLength = 0.5f * axis.Length();
gradient = new float[vertices.Length / 3];
RcVec3f v = new RcVec3f();
for (int i = 0; i < vertices.Length; i += 3)
{
float offset = (i >= vertices.Length / 2) ? -halfLength : halfLength;
float x = radius * vertices[i];
float y = vertices[i + 1] + offset;
float z = radius * vertices[i + 2];
vertices[i] = x * trX.x + y * trX.y + z * trX.z + center.x;
vertices[i + 1] = x * trY.x + y * trY.y + z * trY.z + center.y;
vertices[i + 2] = x * trZ.x + y * trZ.y + z * trZ.z + center.z;
if (i < vertices.Length / 4 || i >= 3 * vertices.Length / 4)
{
gradient[i / 3] = 1;
}
else
{
v.x = vertices[i] - center.x;
v.y = vertices[i + 1] - center.y;
v.z = vertices[i + 2] - center.z;
RcVec3f.Normalize(ref v);
gradient[i / 3] = Clamp(0.57735026f * (v.x + v.y + v.z), -1, 1);
}
}
}
private RcVec3f GetSideVector(RcVec3f axis)
{
RcVec3f side = RcVec3f.Of(1, 0, 0);
if (axis.x > 0.8)
{
side = RcVec3f.Of(0, 0, 1);
}
RcVec3f forward = new RcVec3f();
RcVec3f.Cross(ref forward, side, axis);
RcVec3f.Cross(ref side, axis, forward);
RcVec3f.Normalize(ref side);
return side;
}
public void Render(RecastDebugDraw debugDraw)
{
debugDraw.Begin(DebugDrawPrimitives.TRIS);
for (int i = 0; i < triangles.Length; i += 3)
{
for (int j = 0; j < 3; j++)
{
int v = triangles[i + j] * 3;
float c = gradient[triangles[i + j]];
int col = DebugDraw.DuLerpCol(DebugDraw.DuRGBA(32, 32, 0, 160), DebugDraw.DuRGBA(220, 220, 0, 160),
(int)(127 * (1 + c)));
debugDraw.Vertex(vertices[v], vertices[v + 1], vertices[v + 2], col);
}
}
debugDraw.End();
}
}

View File

@ -1,36 +0,0 @@
using DotRecast.Core;
namespace DotRecast.Recast.Demo.Tools.Gizmos;
public static class GizmoFactory
{
public static IColliderGizmo Box(RcVec3f center, RcVec3f[] halfEdges)
{
return new BoxGizmo(center, halfEdges);
}
public static IColliderGizmo Sphere(RcVec3f center, float radius)
{
return new SphereGizmo(center, radius);
}
public static IColliderGizmo Capsule(RcVec3f start, RcVec3f end, float radius)
{
return new CapsuleGizmo(start, end, radius);
}
public static IColliderGizmo Cylinder(RcVec3f start, RcVec3f end, float radius)
{
return new CylinderGizmo(start, end, radius);
}
public static IColliderGizmo Trimesh(float[] verts, int[] faces)
{
return new TrimeshGizmo(verts, faces);
}
public static IColliderGizmo Composite(params IColliderGizmo[] gizmos)
{
return new CompositeGizmo(gizmos);
}
}

View File

@ -1,197 +0,0 @@
using System;
using DotRecast.Core;
using DotRecast.Recast.Demo.Draw;
using static DotRecast.Core.RcMath;
namespace DotRecast.Recast.Demo.Tools.Gizmos;
public class GizmoHelper
{
private static readonly int SEGMENTS = 16;
private static readonly int RINGS = 8;
private static float[] sphericalVertices;
public static float[] GenerateSphericalVertices()
{
if (sphericalVertices == null)
{
sphericalVertices = GenerateSphericalVertices(SEGMENTS, RINGS);
}
return sphericalVertices;
}
private static float[] GenerateSphericalVertices(int segments, int rings)
{
float[] vertices = new float[6 + 3 * (segments + 1) * (rings + 1)];
// top
int vi = 0;
vertices[vi++] = 0;
vertices[vi++] = 1;
vertices[vi++] = 0;
for (int r = 0; r <= rings; r++)
{
double theta = Math.PI * (r + 1) / (rings + 2);
vi = GenerateRingVertices(segments, vertices, vi, theta);
}
// bottom
vertices[vi++] = 0;
vertices[vi++] = -1;
vertices[vi++] = 0;
return vertices;
}
public static float[] GenerateCylindricalVertices()
{
return GenerateCylindricalVertices(SEGMENTS);
}
private static float[] GenerateCylindricalVertices(int segments)
{
float[] vertices = new float[3 * (segments + 1) * 4];
int vi = 0;
for (int r = 0; r < 4; r++)
{
vi = GenerateRingVertices(segments, vertices, vi, Math.PI * 0.5);
}
return vertices;
}
private static int GenerateRingVertices(int segments, float[] vertices, int vi, double theta)
{
double cosTheta = Math.Cos(theta);
double sinTheta = Math.Sin(theta);
for (int p = 0; p <= segments; p++)
{
double phi = 2 * Math.PI * p / segments;
double cosPhi = Math.Cos(phi);
double sinPhi = Math.Sin(phi);
vertices[vi++] = (float)(sinTheta * cosPhi);
vertices[vi++] = (float)cosTheta;
vertices[vi++] = (float)(sinTheta * sinPhi);
}
return vi;
}
public static int[] GenerateSphericalTriangles()
{
return GenerateSphericalTriangles(SEGMENTS, RINGS);
}
private static int[] GenerateSphericalTriangles(int segments, int rings)
{
int[] triangles = new int[6 * (segments + rings * (segments + 1))];
int ti = GenerateSphereUpperCapTriangles(segments, triangles, 0);
ti = GenerateRingTriangles(segments, rings, triangles, 1, ti);
GenerateSphereLowerCapTriangles(segments, rings, triangles, ti);
return triangles;
}
public static int GenerateRingTriangles(int segments, int rings, int[] triangles, int vertexOffset, int ti)
{
for (int r = 0; r < rings; r++)
{
for (int p = 0; p < segments; p++)
{
int current = p + r * (segments + 1) + vertexOffset;
int next = p + 1 + r * (segments + 1) + vertexOffset;
int currentBottom = p + (r + 1) * (segments + 1) + vertexOffset;
int nextBottom = p + 1 + (r + 1) * (segments + 1) + vertexOffset;
triangles[ti++] = current;
triangles[ti++] = next;
triangles[ti++] = nextBottom;
triangles[ti++] = current;
triangles[ti++] = nextBottom;
triangles[ti++] = currentBottom;
}
}
return ti;
}
private static int GenerateSphereUpperCapTriangles(int segments, int[] triangles, int ti)
{
for (int p = 0; p < segments; p++)
{
triangles[ti++] = p + 2;
triangles[ti++] = p + 1;
triangles[ti++] = 0;
}
return ti;
}
private static void GenerateSphereLowerCapTriangles(int segments, int rings, int[] triangles, int ti)
{
int lastVertex = 1 + (segments + 1) * (rings + 1);
for (int p = 0; p < segments; p++)
{
triangles[ti++] = lastVertex;
triangles[ti++] = lastVertex - (p + 2);
triangles[ti++] = lastVertex - (p + 1);
}
}
public static int[] GenerateCylindricalTriangles()
{
return GenerateCylindricalTriangles(SEGMENTS);
}
private static int[] GenerateCylindricalTriangles(int segments)
{
int circleTriangles = segments - 2;
int[] triangles = new int[6 * (circleTriangles + (segments + 1))];
int vi = 0;
int ti = GenerateCircleTriangles(segments, triangles, vi, 0, false);
ti = GenerateRingTriangles(segments, 1, triangles, segments + 1, ti);
int vertexCount = (segments + 1) * 4;
ti = GenerateCircleTriangles(segments, triangles, vertexCount - segments, ti, true);
return triangles;
}
private static int GenerateCircleTriangles(int segments, int[] triangles, int vi, int ti, bool invert)
{
for (int p = 0; p < segments - 2; p++)
{
if (invert)
{
triangles[ti++] = vi;
triangles[ti++] = vi + p + 1;
triangles[ti++] = vi + p + 2;
}
else
{
triangles[ti++] = vi + p + 2;
triangles[ti++] = vi + p + 1;
triangles[ti++] = vi;
}
}
return ti;
}
public static int GetColorByNormal(float[] vertices, int v0, int v1, int v2)
{
RcVec3f e0 = new RcVec3f();
RcVec3f e1 = new RcVec3f();
RcVec3f normal = new RcVec3f();
for (int j = 0; j < 3; ++j)
{
e0[j] = vertices[v1 + j] - vertices[v0 + j];
e1[j] = vertices[v2 + j] - vertices[v0 + j];
}
normal.x = e0.y * e1.z - e0.z * e1.y;
normal.y = e0.z * e1.x - e0.x * e1.z;
normal.z = e0.x * e1.y - e0.y * e1.x;
RcVec3f.Normalize(ref normal);
float c = Clamp(0.57735026f * (normal.x + normal.y + normal.z), -1, 1);
int col = DebugDraw.DuLerpCol(DebugDraw.DuRGBA(32, 32, 0, 160), DebugDraw.DuRGBA(220, 220, 0, 160),
(int)(127 * (1 + c)));
return col;
}
}

View File

@ -1,8 +0,0 @@
using DotRecast.Recast.Demo.Draw;
namespace DotRecast.Recast.Demo.Tools.Gizmos;
public interface IColliderGizmo
{
void Render(RecastDebugDraw debugDraw);
}

View File

@ -1,42 +0,0 @@
using DotRecast.Core;
using DotRecast.Recast.Demo.Draw;
using static DotRecast.Core.RcMath;
using static DotRecast.Recast.Demo.Tools.Gizmos.GizmoHelper;
namespace DotRecast.Recast.Demo.Tools.Gizmos;
public class SphereGizmo : IColliderGizmo
{
private readonly float[] vertices;
private readonly int[] triangles;
private readonly float radius;
private readonly RcVec3f center;
public SphereGizmo(RcVec3f center, float radius)
{
this.center = center;
this.radius = radius;
vertices = GenerateSphericalVertices();
triangles = GenerateSphericalTriangles();
}
public void Render(RecastDebugDraw debugDraw)
{
debugDraw.Begin(DebugDrawPrimitives.TRIS);
for (int i = 0; i < triangles.Length; i += 3)
{
for (int j = 0; j < 3; j++)
{
int v = triangles[i + j] * 3;
float c = Clamp(0.57735026f * (vertices[v] + vertices[v + 1] + vertices[v + 2]), -1, 1);
int col = DebugDraw.DuLerpCol(DebugDraw.DuRGBA(32, 32, 0, 160), DebugDraw.DuRGBA(220, 220, 0, 160),
(int)(127 * (1 + c)));
debugDraw.Vertex(radius * vertices[v] + center.x, radius * vertices[v + 1] + center.y,
radius * vertices[v + 2] + center.z, col);
}
}
debugDraw.End();
}
}

View File

@ -1,32 +0,0 @@
using DotRecast.Recast.Demo.Draw;
namespace DotRecast.Recast.Demo.Tools.Gizmos;
public class TrimeshGizmo : IColliderGizmo
{
private readonly float[] vertices;
private readonly int[] triangles;
public TrimeshGizmo(float[] vertices, int[] triangles)
{
this.vertices = vertices;
this.triangles = triangles;
}
public void Render(RecastDebugDraw debugDraw)
{
debugDraw.Begin(DebugDrawPrimitives.TRIS);
for (int i = 0; i < triangles.Length; i += 3)
{
int v0 = 3 * triangles[i];
int v1 = 3 * triangles[i + 1];
int v2 = 3 * triangles[i + 2];
int col = GizmoHelper.GetColorByNormal(vertices, v0, v1, v2);
debugDraw.Vertex(vertices[v0], vertices[v0 + 1], vertices[v0 + 2], col);
debugDraw.Vertex(vertices[v1], vertices[v1 + 1], vertices[v1 + 2], col);
debugDraw.Vertex(vertices[v2], vertices[v2 + 1], vertices[v2 + 2], col);
}
debugDraw.End();
}
}

View File

@ -0,0 +1,50 @@
using DotRecast.Core;
using DotRecast.Detour.Dynamic.Colliders;
namespace DotRecast.Recast.Toolset.Tools.Gizmos
{
public class BoxGizmo : IRcGizmoMeshFilter
{
public static readonly int[] TRIANLGES =
{
0, 1, 2, 0, 2, 3, 4, 7, 6, 4, 6, 5, 0, 4, 5, 0, 5, 1, 1, 5, 6, 1, 6, 2,
2, 6, 7, 2, 7, 3, 4, 0, 3, 4, 3, 7
};
public static readonly RcVec3f[] VERTS =
{
RcVec3f.Of(-1f, -1f, -1f),
RcVec3f.Of(1f, -1f, -1f),
RcVec3f.Of(1f, -1f, 1f),
RcVec3f.Of(-1f, -1f, 1f),
RcVec3f.Of(-1f, 1f, -1f),
RcVec3f.Of(1f, 1f, -1f),
RcVec3f.Of(1f, 1f, 1f),
RcVec3f.Of(-1f, 1f, 1f),
};
public readonly float[] vertices = new float[8 * 3];
public readonly RcVec3f center;
public readonly RcVec3f[] halfEdges;
public BoxGizmo(RcVec3f center, RcVec3f extent, RcVec3f forward, RcVec3f up) :
this(center, BoxCollider.GetHalfEdges(up, forward, extent))
{
}
public BoxGizmo(RcVec3f center, RcVec3f[] halfEdges)
{
this.center = center;
this.halfEdges = halfEdges;
for (int i = 0; i < 8; ++i)
{
float s0 = (i & 1) != 0 ? 1f : -1f;
float s1 = (i & 2) != 0 ? 1f : -1f;
float s2 = (i & 4) != 0 ? 1f : -1f;
vertices[i * 3 + 0] = center.x + s0 * halfEdges[0].x + s1 * halfEdges[1].x + s2 * halfEdges[2].x;
vertices[i * 3 + 1] = center.y + s0 * halfEdges[0].y + s1 * halfEdges[1].y + s2 * halfEdges[2].y;
vertices[i * 3 + 2] = center.z + s0 * halfEdges[0].z + s1 * halfEdges[1].z + s2 * halfEdges[2].z;
}
}
}
}

View File

@ -0,0 +1,70 @@
using DotRecast.Core;
using static DotRecast.Core.RcMath;
using static DotRecast.Recast.Toolset.Tools.Gizmos.GizmoHelper;
namespace DotRecast.Recast.Toolset.Tools.Gizmos
{
public class CapsuleGizmo : IRcGizmoMeshFilter
{
public readonly float[] vertices;
public readonly int[] triangles;
public readonly float[] center;
public readonly float[] gradient;
public CapsuleGizmo(RcVec3f start, RcVec3f end, float radius)
{
center = new float[]
{
0.5f * (start.x + end.x), 0.5f * (start.y + end.y),
0.5f * (start.z + end.z)
};
RcVec3f axis = RcVec3f.Of(end.x - start.x, end.y - start.y, end.z - start.z);
RcVec3f[] normals = new RcVec3f[3];
normals[1] = RcVec3f.Of(end.x - start.x, end.y - start.y, end.z - start.z);
RcVec3f.Normalize(ref normals[1]);
normals[0] = GetSideVector(axis);
normals[2] = RcVec3f.Zero;
RcVec3f.Cross(ref normals[2], normals[0], normals[1]);
RcVec3f.Normalize(ref normals[2]);
triangles = GenerateSphericalTriangles();
var trX = RcVec3f.Of(normals[0].x, normals[1].x, normals[2].x);
var trY = RcVec3f.Of(normals[0].y, normals[1].y, normals[2].y);
var trZ = RcVec3f.Of(normals[0].z, normals[1].z, normals[2].z);
float[] spVertices = GenerateSphericalVertices();
float halfLength = 0.5f * axis.Length();
vertices = new float[spVertices.Length];
gradient = new float[spVertices.Length / 3];
RcVec3f v = new RcVec3f();
for (int i = 0; i < spVertices.Length; i += 3)
{
float offset = (i >= spVertices.Length / 2) ? -halfLength : halfLength;
float x = radius * spVertices[i];
float y = radius * spVertices[i + 1] + offset;
float z = radius * spVertices[i + 2];
vertices[i] = x * trX.x + y * trX.y + z * trX.z + center[0];
vertices[i + 1] = x * trY.x + y * trY.y + z * trY.z + center[1];
vertices[i + 2] = x * trZ.x + y * trZ.y + z * trZ.z + center[2];
v.x = vertices[i] - center[0];
v.y = vertices[i + 1] - center[1];
v.z = vertices[i + 2] - center[2];
RcVec3f.Normalize(ref v);
gradient[i / 3] = Clamp(0.57735026f * (v.x + v.y + v.z), -1, 1);
}
}
private RcVec3f GetSideVector(RcVec3f axis)
{
RcVec3f side = RcVec3f.Of(1, 0, 0);
if (axis.x > 0.8)
{
side = RcVec3f.Of(0, 0, 1);
}
RcVec3f forward = new RcVec3f();
RcVec3f.Cross(ref forward, side, axis);
RcVec3f.Cross(ref side, axis, forward);
RcVec3f.Normalize(ref side);
return side;
}
}
}

View File

@ -0,0 +1,12 @@
namespace DotRecast.Recast.Toolset.Tools.Gizmos
{
public class CompositeGizmo : IRcGizmoMeshFilter
{
public readonly IRcGizmoMeshFilter[] gizmoMeshes;
public CompositeGizmo(params IRcGizmoMeshFilter[] gizmoMeshes)
{
this.gizmoMeshes = gizmoMeshes;
}
}
}

View File

@ -0,0 +1,76 @@
using DotRecast.Core;
using static DotRecast.Core.RcMath;
using static DotRecast.Recast.Toolset.Tools.Gizmos.GizmoHelper;
namespace DotRecast.Recast.Toolset.Tools.Gizmos
{
public class CylinderGizmo : IRcGizmoMeshFilter
{
public readonly float[] vertices;
public readonly int[] triangles;
public readonly RcVec3f center;
public readonly float[] gradient;
public CylinderGizmo(RcVec3f start, RcVec3f end, float radius)
{
center = RcVec3f.Of(
0.5f * (start.x + end.x), 0.5f * (start.y + end.y),
0.5f * (start.z + end.z)
);
RcVec3f axis = RcVec3f.Of(end.x - start.x, end.y - start.y, end.z - start.z);
RcVec3f[] normals = new RcVec3f[3];
normals[1] = RcVec3f.Of(end.x - start.x, end.y - start.y, end.z - start.z);
RcVec3f.Normalize(ref normals[1]);
normals[0] = GetSideVector(axis);
normals[2] = RcVec3f.Zero;
RcVec3f.Cross(ref normals[2], normals[0], normals[1]);
RcVec3f.Normalize(ref normals[2]);
triangles = GenerateCylindricalTriangles();
RcVec3f trX = RcVec3f.Of(normals[0].x, normals[1].x, normals[2].x);
RcVec3f trY = RcVec3f.Of(normals[0].y, normals[1].y, normals[2].y);
RcVec3f trZ = RcVec3f.Of(normals[0].z, normals[1].z, normals[2].z);
vertices = GenerateCylindricalVertices();
float halfLength = 0.5f * axis.Length();
gradient = new float[vertices.Length / 3];
RcVec3f v = new RcVec3f();
for (int i = 0; i < vertices.Length; i += 3)
{
float offset = (i >= vertices.Length / 2) ? -halfLength : halfLength;
float x = radius * vertices[i];
float y = vertices[i + 1] + offset;
float z = radius * vertices[i + 2];
vertices[i] = x * trX.x + y * trX.y + z * trX.z + center.x;
vertices[i + 1] = x * trY.x + y * trY.y + z * trY.z + center.y;
vertices[i + 2] = x * trZ.x + y * trZ.y + z * trZ.z + center.z;
if (i < vertices.Length / 4 || i >= 3 * vertices.Length / 4)
{
gradient[i / 3] = 1;
}
else
{
v.x = vertices[i] - center.x;
v.y = vertices[i + 1] - center.y;
v.z = vertices[i + 2] - center.z;
RcVec3f.Normalize(ref v);
gradient[i / 3] = Clamp(0.57735026f * (v.x + v.y + v.z), -1, 1);
}
}
}
private RcVec3f GetSideVector(RcVec3f axis)
{
RcVec3f side = RcVec3f.Of(1, 0, 0);
if (axis.x > 0.8)
{
side = RcVec3f.Of(0, 0, 1);
}
RcVec3f forward = new RcVec3f();
RcVec3f.Cross(ref forward, side, axis);
RcVec3f.Cross(ref side, axis, forward);
RcVec3f.Normalize(ref side);
return side;
}
}
}

View File

@ -0,0 +1,37 @@
using DotRecast.Core;
namespace DotRecast.Recast.Toolset.Tools.Gizmos
{
public static class GizmoFactory
{
public static BoxGizmo Box(RcVec3f center, RcVec3f[] halfEdges)
{
return new BoxGizmo(center, halfEdges);
}
public static SphereGizmo Sphere(RcVec3f center, float radius)
{
return new SphereGizmo(center, radius);
}
public static CapsuleGizmo Capsule(RcVec3f start, RcVec3f end, float radius)
{
return new CapsuleGizmo(start, end, radius);
}
public static CylinderGizmo Cylinder(RcVec3f start, RcVec3f end, float radius)
{
return new CylinderGizmo(start, end, radius);
}
public static TrimeshGizmo Trimesh(float[] verts, int[] faces)
{
return new TrimeshGizmo(verts, faces);
}
public static CompositeGizmo Composite(params IRcGizmoMeshFilter[] gizmos)
{
return new CompositeGizmo(gizmos);
}
}
}

View File

@ -0,0 +1,174 @@
using System;
namespace DotRecast.Recast.Toolset.Tools.Gizmos
{
public static class GizmoHelper
{
private static readonly int SEGMENTS = 16;
private static readonly int RINGS = 8;
private static float[] sphericalVertices;
public static float[] GenerateSphericalVertices()
{
if (sphericalVertices == null)
{
sphericalVertices = GenerateSphericalVertices(SEGMENTS, RINGS);
}
return sphericalVertices;
}
private static float[] GenerateSphericalVertices(int segments, int rings)
{
float[] vertices = new float[6 + 3 * (segments + 1) * (rings + 1)];
// top
int vi = 0;
vertices[vi++] = 0;
vertices[vi++] = 1;
vertices[vi++] = 0;
for (int r = 0; r <= rings; r++)
{
double theta = Math.PI * (r + 1) / (rings + 2);
vi = GenerateRingVertices(segments, vertices, vi, theta);
}
// bottom
vertices[vi++] = 0;
vertices[vi++] = -1;
vertices[vi++] = 0;
return vertices;
}
public static float[] GenerateCylindricalVertices()
{
return GenerateCylindricalVertices(SEGMENTS);
}
private static float[] GenerateCylindricalVertices(int segments)
{
float[] vertices = new float[3 * (segments + 1) * 4];
int vi = 0;
for (int r = 0; r < 4; r++)
{
vi = GenerateRingVertices(segments, vertices, vi, Math.PI * 0.5);
}
return vertices;
}
private static int GenerateRingVertices(int segments, float[] vertices, int vi, double theta)
{
double cosTheta = Math.Cos(theta);
double sinTheta = Math.Sin(theta);
for (int p = 0; p <= segments; p++)
{
double phi = 2 * Math.PI * p / segments;
double cosPhi = Math.Cos(phi);
double sinPhi = Math.Sin(phi);
vertices[vi++] = (float)(sinTheta * cosPhi);
vertices[vi++] = (float)cosTheta;
vertices[vi++] = (float)(sinTheta * sinPhi);
}
return vi;
}
public static int[] GenerateSphericalTriangles()
{
return GenerateSphericalTriangles(SEGMENTS, RINGS);
}
private static int[] GenerateSphericalTriangles(int segments, int rings)
{
int[] triangles = new int[6 * (segments + rings * (segments + 1))];
int ti = GenerateSphereUpperCapTriangles(segments, triangles, 0);
ti = GenerateRingTriangles(segments, rings, triangles, 1, ti);
GenerateSphereLowerCapTriangles(segments, rings, triangles, ti);
return triangles;
}
public static int GenerateRingTriangles(int segments, int rings, int[] triangles, int vertexOffset, int ti)
{
for (int r = 0; r < rings; r++)
{
for (int p = 0; p < segments; p++)
{
int current = p + r * (segments + 1) + vertexOffset;
int next = p + 1 + r * (segments + 1) + vertexOffset;
int currentBottom = p + (r + 1) * (segments + 1) + vertexOffset;
int nextBottom = p + 1 + (r + 1) * (segments + 1) + vertexOffset;
triangles[ti++] = current;
triangles[ti++] = next;
triangles[ti++] = nextBottom;
triangles[ti++] = current;
triangles[ti++] = nextBottom;
triangles[ti++] = currentBottom;
}
}
return ti;
}
private static int GenerateSphereUpperCapTriangles(int segments, int[] triangles, int ti)
{
for (int p = 0; p < segments; p++)
{
triangles[ti++] = p + 2;
triangles[ti++] = p + 1;
triangles[ti++] = 0;
}
return ti;
}
private static void GenerateSphereLowerCapTriangles(int segments, int rings, int[] triangles, int ti)
{
int lastVertex = 1 + (segments + 1) * (rings + 1);
for (int p = 0; p < segments; p++)
{
triangles[ti++] = lastVertex;
triangles[ti++] = lastVertex - (p + 2);
triangles[ti++] = lastVertex - (p + 1);
}
}
public static int[] GenerateCylindricalTriangles()
{
return GenerateCylindricalTriangles(SEGMENTS);
}
private static int[] GenerateCylindricalTriangles(int segments)
{
int circleTriangles = segments - 2;
int[] triangles = new int[6 * (circleTriangles + (segments + 1))];
int vi = 0;
int ti = GenerateCircleTriangles(segments, triangles, vi, 0, false);
ti = GenerateRingTriangles(segments, 1, triangles, segments + 1, ti);
int vertexCount = (segments + 1) * 4;
ti = GenerateCircleTriangles(segments, triangles, vertexCount - segments, ti, true);
return triangles;
}
private static int GenerateCircleTriangles(int segments, int[] triangles, int vi, int ti, bool invert)
{
for (int p = 0; p < segments - 2; p++)
{
if (invert)
{
triangles[ti++] = vi;
triangles[ti++] = vi + p + 1;
triangles[ti++] = vi + p + 2;
}
else
{
triangles[ti++] = vi + p + 2;
triangles[ti++] = vi + p + 1;
triangles[ti++] = vi;
}
}
return ti;
}
}
}

View File

@ -0,0 +1,9 @@
//using DotRecast.Recast.Demo.Draw;
namespace DotRecast.Recast.Toolset.Tools.Gizmos
{
public interface IRcGizmoMeshFilter
{
//void Render(RecastDebugDraw debugDraw);
}
}

View File

@ -0,0 +1,22 @@
using DotRecast.Core;
using static DotRecast.Recast.Toolset.Tools.Gizmos.GizmoHelper;
namespace DotRecast.Recast.Toolset.Tools.Gizmos
{
public class SphereGizmo : IRcGizmoMeshFilter
{
public readonly float[] vertices;
public readonly int[] triangles;
public readonly float radius;
public readonly RcVec3f center;
public SphereGizmo(RcVec3f center, float radius)
{
this.center = center;
this.radius = radius;
vertices = GenerateSphericalVertices();
triangles = GenerateSphericalTriangles();
}
}
}

View File

@ -0,0 +1,14 @@
namespace DotRecast.Recast.Toolset.Tools.Gizmos
{
public class TrimeshGizmo : IRcGizmoMeshFilter
{
public readonly float[] vertices;
public readonly int[] triangles;
public TrimeshGizmo(float[] vertices, int[] triangles)
{
this.vertices = vertices;
this.triangles = triangles;
}
}
}