forked from mirror/DotRecast
163 lines
6.0 KiB
C#
163 lines
6.0 KiB
C#
using System;
|
|
using DotRecast.Recast.Demo.Draw;
|
|
using static DotRecast.Detour.DetourCommon;
|
|
|
|
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) {
|
|
float[] e0 = new float[3], e1 = new float[3];
|
|
float[] normal = new float[3];
|
|
for (int j = 0; j < 3; ++j) {
|
|
e0[j] = vertices[v1 + j] - vertices[v0 + j];
|
|
e1[j] = vertices[v2 + j] - vertices[v0 + j];
|
|
}
|
|
normal[0] = e0[1] * e1[2] - e0[2] * e1[1];
|
|
normal[1] = e0[2] * e1[0] - e0[0] * e1[2];
|
|
normal[2] = e0[0] * e1[1] - e0[1] * e1[0];
|
|
RecastVectors.normalize(normal);
|
|
float c = clamp(0.57735026f * (normal[0] + normal[1] + normal[2]), -1, 1);
|
|
int col = DebugDraw.duLerpCol(DebugDraw.duRGBA(32, 32, 0, 160), DebugDraw.duRGBA(220, 220, 0, 160),
|
|
(int) (127 * (1 + c)));
|
|
return col;
|
|
}
|
|
|
|
}
|