forked from aly/qstbak
1611 lines
71 KiB
C#
1611 lines
71 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Numerics;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Text;
|
|
using Auspex.Rendering.Direct3D;
|
|
using Auspex.Rendering.ImGuiFallback;
|
|
using Dalamud.Bindings.ImGui;
|
|
using Dalamud.Interface.Textures.TextureWraps;
|
|
using Dalamud.Interface.Utility;
|
|
|
|
namespace Auspex;
|
|
|
|
public sealed class AxDrawList : IDisposable
|
|
{
|
|
private static string? _cachedWindowName;
|
|
|
|
internal readonly ImDrawListPtr _drawList;
|
|
|
|
internal readonly ImDrawListPtr _textDrawList;
|
|
|
|
internal readonly List<Vector3> _path;
|
|
|
|
internal readonly Direct3DRenderer _renderer;
|
|
|
|
internal readonly ImGuiFallbackRenderer _fallbackRenderer;
|
|
|
|
internal readonly bool isMyWindow;
|
|
|
|
private readonly bool _separateTextDrawList;
|
|
|
|
private AxTexture? _texture;
|
|
|
|
private readonly Stack<Vector4> _clipStack = new Stack<Vector4>();
|
|
|
|
internal AxDxParams DefaultDxParams { get; init; }
|
|
|
|
internal bool Finalized => _texture.HasValue;
|
|
|
|
public Vector3 CameraRight => _renderer.CameraRight;
|
|
|
|
public Vector3 CameraUp => _renderer.CameraUp;
|
|
|
|
public Matrix4x4 ViewProj => _renderer.ViewProj;
|
|
|
|
public bool FanDegraded => _renderer.FanDegraded;
|
|
|
|
public bool StrokeDegraded => _renderer.StrokeDegraded;
|
|
|
|
public bool FullScreenPassDegraded => _renderer.FSPDegraded;
|
|
|
|
public bool TexturedQuadDegraded => _renderer.TexturedQuadDegraded;
|
|
|
|
public Vector2? WorldToScreen(Vector3 worldPos)
|
|
{
|
|
Matrix4x4 viewProj = _renderer.ViewProj;
|
|
float num = worldPos.X * viewProj.M14 + worldPos.Y * viewProj.M24 + worldPos.Z * viewProj.M34 + viewProj.M44;
|
|
if (num <= 0f)
|
|
{
|
|
return null;
|
|
}
|
|
float num2 = 1f / num;
|
|
float num3 = (worldPos.X * viewProj.M11 + worldPos.Y * viewProj.M21 + worldPos.Z * viewProj.M31 + viewProj.M41) * num2;
|
|
float num4 = (worldPos.X * viewProj.M12 + worldPos.Y * viewProj.M22 + worldPos.Z * viewProj.M32 + viewProj.M42) * num2;
|
|
ImGuiViewportPtr mainViewport = ImGuiHelpers.MainViewport;
|
|
return new Vector2(0.5f * mainViewport.Size.X * (1f + num3) + mainViewport.Pos.X, 0.5f * mainViewport.Size.Y * (1f - num4) + mainViewport.Pos.Y);
|
|
}
|
|
|
|
public (Vector3 Origin, Vector3 Direction)? ScreenToWorldRay(Vector2 screenPos)
|
|
{
|
|
if (!Matrix4x4.Invert(_renderer.ViewProj, out var result))
|
|
{
|
|
return null;
|
|
}
|
|
ImGuiViewportPtr mainViewport = ImGuiHelpers.MainViewport;
|
|
float nx = 2f * (screenPos.X - mainViewport.Pos.X) / mainViewport.Size.X - 1f;
|
|
float ny = 1f - 2f * (screenPos.Y - mainViewport.Pos.Y) / mainViewport.Size.Y;
|
|
Vector3 vector = Unproject(in result, nx, ny, 0f);
|
|
Vector3 item = Vector3.Normalize(Unproject(in result, nx, ny, 1f) - vector);
|
|
return (vector, item);
|
|
}
|
|
|
|
private static Vector3 Unproject(in Matrix4x4 invViewProj, float nx, float ny, float nz)
|
|
{
|
|
float num = nx * invViewProj.M11 + ny * invViewProj.M21 + nz * invViewProj.M31 + invViewProj.M41;
|
|
float num2 = nx * invViewProj.M12 + ny * invViewProj.M22 + nz * invViewProj.M32 + invViewProj.M42;
|
|
float num3 = nx * invViewProj.M13 + ny * invViewProj.M23 + nz * invViewProj.M33 + invViewProj.M43;
|
|
float num4 = nx * invViewProj.M14 + ny * invViewProj.M24 + nz * invViewProj.M34 + invViewProj.M44;
|
|
float num5 = 1f / num4;
|
|
return new Vector3(num * num5, num2 * num5, num3 * num5);
|
|
}
|
|
|
|
internal AxDrawList(ImDrawListPtr? drawlist, Direct3DRenderer renderer)
|
|
{
|
|
if (drawlist.HasValue)
|
|
{
|
|
_drawList = (_textDrawList = drawlist.Value);
|
|
}
|
|
else
|
|
{
|
|
_drawList = ImGui.GetBackgroundDrawList();
|
|
ImGuiHelpers.ForceNextWindowMainViewport();
|
|
ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero);
|
|
ImGuiHelpers.SetNextWindowPosRelativeMainViewport(Vector2.Zero);
|
|
ImGui.SetNextWindowSize(ImGuiHelpers.MainViewport.Size);
|
|
if (_cachedWindowName == null)
|
|
{
|
|
_cachedWindowName = "AxWindow#" + AuspexService.PluginInterface.InternalName;
|
|
}
|
|
if (ImGui.Begin(_cachedWindowName, ImGuiWindowFlags.NoInputs | ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.NoFocusOnAppearing | ImGuiWindowFlags.AlwaysUseWindowPadding))
|
|
{
|
|
CImGui.igBringWindowToDisplayBack(CImGui.igGetCurrentWindow());
|
|
_textDrawList = ImGui.GetWindowDrawList();
|
|
isMyWindow = true;
|
|
}
|
|
else
|
|
{
|
|
_textDrawList = ImGui.GetBackgroundDrawList();
|
|
}
|
|
ImGui.PopStyleVar();
|
|
}
|
|
_path = renderer.SharedPath;
|
|
_path.Clear();
|
|
_renderer = renderer;
|
|
DefaultDxParams = AuspexService.Hints.DefaultDxParams;
|
|
_texture = null;
|
|
_separateTextDrawList = isMyWindow;
|
|
_renderer.BeginFrame();
|
|
_fallbackRenderer = new ImGuiFallbackRenderer(_drawList);
|
|
}
|
|
|
|
public AxTexture DrawToTexture()
|
|
{
|
|
if (!_texture.HasValue)
|
|
{
|
|
FrameRenderTarget frameRenderTarget = _renderer.EndFrame();
|
|
_texture = frameRenderTarget.Texture;
|
|
}
|
|
return _texture.Value;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (AuspexService.DrawList == this)
|
|
{
|
|
AuspexService.DrawList = null;
|
|
}
|
|
if (AuspexService.Hints.AutoDraw)
|
|
{
|
|
AxTexture axTexture = DrawToTexture();
|
|
_drawList.AddImage(axTexture.TextureId, ImGuiHelpers.MainViewport.Pos, ImGuiHelpers.MainViewport.Pos + axTexture.Size);
|
|
}
|
|
else
|
|
{
|
|
DrawToTexture();
|
|
}
|
|
if (isMyWindow)
|
|
{
|
|
ImGui.End();
|
|
}
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
public void PushClipRect(Vector2 min, Vector2 max)
|
|
{
|
|
_clipStack.Push(new Vector4(min.X, min.Y, max.X, max.Y));
|
|
_renderer.SetScissorRect(min, max);
|
|
_drawList.PushClipRect(min, max, intersectWithCurrentClipRect: false);
|
|
if (_separateTextDrawList)
|
|
{
|
|
_textDrawList.PushClipRect(min, max, intersectWithCurrentClipRect: false);
|
|
}
|
|
}
|
|
|
|
public void PopClipRect()
|
|
{
|
|
if (_clipStack.Count != 0)
|
|
{
|
|
_clipStack.Pop();
|
|
_drawList.PopClipRect();
|
|
if (_separateTextDrawList)
|
|
{
|
|
_textDrawList.PopClipRect();
|
|
}
|
|
if (_clipStack.Count > 0)
|
|
{
|
|
Vector4 vector = _clipStack.Peek();
|
|
_renderer.SetScissorRect(new Vector2(vector.X, vector.Y), new Vector2(vector.Z, vector.W));
|
|
}
|
|
else
|
|
{
|
|
_renderer.ClearScissorRect();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void AddText(Vector3 position, uint color, string text, float scale = 1f, uint? outlineColor = null, float outlineThickness = 1f, uint? shadowColor = null, Vector2? shadowOffset = null)
|
|
{
|
|
ArgumentNullException.ThrowIfNull((object)text, "text");
|
|
if (AuspexService.GameGui.WorldToScreen(position, out var screenPos))
|
|
{
|
|
ImGui.SetWindowFontScale(scale);
|
|
Vector2 vector = screenPos - ImGui.CalcTextSize(text) / 2f;
|
|
DrawTextEffects(_textDrawList, vector, text, outlineColor, outlineThickness, shadowColor, shadowOffset);
|
|
_textDrawList.AddText(vector, color, text);
|
|
ImGui.SetWindowFontScale(1f);
|
|
}
|
|
}
|
|
|
|
public void AddWorldText(Vector3 position, uint color, string text, float scale = 1f, uint? outlineColor = null, float outlineThickness = 1f, uint? shadowColor = null, Vector2? shadowOffset = null)
|
|
{
|
|
ArgumentNullException.ThrowIfNull((object)text, "text");
|
|
if (text.Length == 0)
|
|
{
|
|
return;
|
|
}
|
|
if (_renderer.TexturedQuadDegraded)
|
|
{
|
|
AddWorldTextImGui(position, color, text, scale, outlineColor, outlineThickness, shadowColor, shadowOffset);
|
|
}
|
|
else
|
|
{
|
|
if (!WorldToScreen(position).HasValue)
|
|
{
|
|
return;
|
|
}
|
|
HighResFontAtlas worldFont = _renderer.WorldFont;
|
|
ImFontPtr font = worldFont?.Font ?? ImGui.GetFont();
|
|
IntPtr textureSRV = worldFont?.TextureSRV ?? ((IntPtr)0);
|
|
float fontSize = font.FontSize;
|
|
float num = scale / fontSize;
|
|
float num2 = 0f;
|
|
foreach (Rune item in text.EnumerateRunes())
|
|
{
|
|
ushort c = ((item.Value <= 65535) ? ((ushort)item.Value) : font.FallbackChar);
|
|
num2 += font.GetCharAdvance(c) * num;
|
|
}
|
|
Vector3 cameraRight = _renderer.CameraRight;
|
|
Vector3 cameraUp = _renderer.CameraUp;
|
|
if (shadowColor.HasValue)
|
|
{
|
|
Vector2 vector = shadowOffset ?? new Vector2(1f, 1f);
|
|
Vector3 vector2 = cameraRight * (vector.X * num) - cameraUp * (vector.Y * num);
|
|
RenderWorldGlyphs(position + vector2, cameraRight, cameraUp, font, textureSRV, text, fontSize, num, num2, shadowColor.Value);
|
|
}
|
|
if (outlineColor.HasValue)
|
|
{
|
|
float num3 = outlineThickness * num;
|
|
RenderWorldGlyphs(position + cameraRight * num3, cameraRight, cameraUp, font, textureSRV, text, fontSize, num, num2, outlineColor.Value);
|
|
RenderWorldGlyphs(position - cameraRight * num3, cameraRight, cameraUp, font, textureSRV, text, fontSize, num, num2, outlineColor.Value);
|
|
RenderWorldGlyphs(position + cameraUp * num3, cameraRight, cameraUp, font, textureSRV, text, fontSize, num, num2, outlineColor.Value);
|
|
RenderWorldGlyphs(position - cameraUp * num3, cameraRight, cameraUp, font, textureSRV, text, fontSize, num, num2, outlineColor.Value);
|
|
}
|
|
RenderWorldGlyphs(position, cameraRight, cameraUp, font, textureSRV, text, fontSize, num, num2, color);
|
|
}
|
|
}
|
|
|
|
private unsafe void RenderWorldGlyphs(Vector3 origin, Vector3 right, Vector3 up, ImFontPtr font, IntPtr textureSRV, string text, float fontSize, float pixelToWorld, float totalWidthWorld, uint color)
|
|
{
|
|
float num = fontSize * 0.5f;
|
|
float num2 = (0f - totalWidthWorld) * 0.5f;
|
|
foreach (Rune item in text.EnumerateRunes())
|
|
{
|
|
ushort c = ((item.Value <= 65535) ? ((ushort)item.Value) : font.FallbackChar);
|
|
ImFontGlyph imFontGlyph = *font.FindGlyph(c);
|
|
if (imFontGlyph.Visible != 0)
|
|
{
|
|
float num3 = num2 + imFontGlyph.X0 * pixelToWorld;
|
|
float num4 = num2 + imFontGlyph.X1 * pixelToWorld;
|
|
float num5 = (0f - (imFontGlyph.Y0 - num)) * pixelToWorld;
|
|
float num6 = (0f - (imFontGlyph.Y1 - num)) * pixelToWorld;
|
|
Vector3 a = origin + right * num3 + up * num5;
|
|
Vector3 b = origin + right * num4 + up * num5;
|
|
Vector3 c2 = origin + right * num4 + up * num6;
|
|
Vector3 d = origin + right * num3 + up * num6;
|
|
IntPtr intPtr = textureSRV;
|
|
if (intPtr == (IntPtr)0)
|
|
{
|
|
ImFontAtlasPtr containerAtlas = font.ContainerAtlas;
|
|
ImTextureID texID = containerAtlas.Textures[(int)imFontGlyph.TextureIndex].TexID;
|
|
intPtr = Unsafe.As<ImTextureID, IntPtr>(ref texID);
|
|
}
|
|
_renderer.DrawTexturedQuad(intPtr, a, b, c2, d, color, new Vector2(imFontGlyph.U0, imFontGlyph.V0), new Vector2(imFontGlyph.U1, imFontGlyph.V1));
|
|
}
|
|
num2 += imFontGlyph.AdvanceX * pixelToWorld;
|
|
}
|
|
}
|
|
|
|
private void AddWorldTextImGui(Vector3 position, uint color, string text, float scale, uint? outlineColor, float outlineThickness, uint? shadowColor, Vector2? shadowOffset)
|
|
{
|
|
if (!AuspexService.GameGui.WorldToScreen(position, out var screenPos))
|
|
{
|
|
return;
|
|
}
|
|
Vector3 worldPos = position + _renderer.CameraUp * scale;
|
|
if (AuspexService.GameGui.WorldToScreen(worldPos, out var screenPos2))
|
|
{
|
|
float num = Vector2.Distance(screenPos, screenPos2) / ImGui.GetFontSize();
|
|
if (!(num < 0.01f))
|
|
{
|
|
ImGui.SetWindowFontScale(num);
|
|
Vector2 vector = screenPos - ImGui.CalcTextSize(text) / 2f;
|
|
DrawTextEffects(_textDrawList, vector, text, outlineColor, outlineThickness, shadowColor, shadowOffset);
|
|
_textDrawList.AddText(vector, color, text);
|
|
ImGui.SetWindowFontScale(1f);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void DrawTextEffects(ImDrawListPtr drawList, Vector2 textPosition, string text, uint? outlineColor, float outlineThickness, uint? shadowColor, Vector2? shadowOffset)
|
|
{
|
|
if (shadowColor.HasValue)
|
|
{
|
|
Vector2 vector = shadowOffset ?? new Vector2(1f, 1f);
|
|
drawList.AddText(textPosition + vector, shadowColor.Value, text);
|
|
}
|
|
if (outlineColor.HasValue)
|
|
{
|
|
uint value = outlineColor.Value;
|
|
drawList.AddText(textPosition + new Vector2(outlineThickness, 0f), value, text);
|
|
drawList.AddText(textPosition + new Vector2(0f - outlineThickness, 0f), value, text);
|
|
drawList.AddText(textPosition + new Vector2(0f, outlineThickness), value, text);
|
|
drawList.AddText(textPosition + new Vector2(0f, 0f - outlineThickness), value, text);
|
|
}
|
|
}
|
|
|
|
public void AddDot(Vector3 position, float radiusPixels, uint color, uint numSegments = 0u)
|
|
{
|
|
if (AuspexService.GameGui.WorldToScreen(position, out var screenPos))
|
|
{
|
|
_drawList.AddCircleFilled(screenPos, radiusPixels, color, (int)numSegments);
|
|
}
|
|
}
|
|
|
|
public void AddTexture(Vector3 position, IDalamudTextureWrap texture, float scale = 1f, uint color = uint.MaxValue)
|
|
{
|
|
ArgumentNullException.ThrowIfNull((object)texture, "texture");
|
|
if (AuspexService.GameGui.WorldToScreen(position, out var screenPos))
|
|
{
|
|
Vector2 vector = new Vector2(texture.Width, texture.Height) * scale;
|
|
Vector2 vector2 = screenPos - vector / 2f;
|
|
Vector2 pMax = vector2 + vector;
|
|
_textDrawList.AddImage(texture.Handle, vector2, pMax, Vector2.Zero, Vector2.One, color);
|
|
}
|
|
}
|
|
|
|
public void AddBillboard(Vector3 position, IDalamudTextureWrap texture, float width, float height, uint color = uint.MaxValue, float rotation = 0f, Vector2 uvMin = default(Vector2), Vector2 uvMax = default(Vector2))
|
|
{
|
|
ArgumentNullException.ThrowIfNull((object)texture, "texture");
|
|
if (uvMax == default(Vector2))
|
|
{
|
|
uvMax = Vector2.One;
|
|
}
|
|
if (_renderer.TexturedQuadDegraded)
|
|
{
|
|
AddTexture(position, texture, 1f, color);
|
|
return;
|
|
}
|
|
Vector3 vector = _renderer.CameraRight;
|
|
Vector3 vector2 = _renderer.CameraUp;
|
|
if (rotation != 0f)
|
|
{
|
|
float num = MathF.Cos(rotation);
|
|
float num2 = MathF.Sin(rotation);
|
|
Vector3 vector3 = vector * num + vector2 * num2;
|
|
Vector3 vector4 = vector2 * num - vector * num2;
|
|
vector = vector3;
|
|
vector2 = vector4;
|
|
}
|
|
float num3 = width * 0.5f;
|
|
float num4 = height * 0.5f;
|
|
Vector3 a = position - vector * num3 + vector2 * num4;
|
|
Vector3 b = position + vector * num3 + vector2 * num4;
|
|
Vector3 c = position + vector * num3 - vector2 * num4;
|
|
Vector3 d = position - vector * num3 - vector2 * num4;
|
|
ImTextureID handle = texture.Handle;
|
|
_renderer.DrawTexturedQuad(Unsafe.As<ImTextureID, IntPtr>(ref handle), a, b, c, d, color, uvMin, uvMax);
|
|
}
|
|
|
|
public void AddBillboard(Vector3 position, IDalamudTextureWrap texture, float scale = 1f, uint color = uint.MaxValue, float rotation = 0f, Vector2 uvMin = default(Vector2), Vector2 uvMax = default(Vector2))
|
|
{
|
|
ArgumentNullException.ThrowIfNull((object)texture, "texture");
|
|
float num = (float)texture.Width / (float)texture.Height;
|
|
AddBillboard(position, texture, scale * num, scale, color, rotation, uvMin, uvMax);
|
|
}
|
|
|
|
public void AddTexturedQuad(Vector3 a, Vector3 b, Vector3 c, Vector3 d, IDalamudTextureWrap texture, uint color = uint.MaxValue, Vector2 uvMin = default(Vector2), Vector2 uvMax = default(Vector2))
|
|
{
|
|
ArgumentNullException.ThrowIfNull((object)texture, "texture");
|
|
if (uvMax == default(Vector2))
|
|
{
|
|
uvMax = Vector2.One;
|
|
}
|
|
if (!_renderer.TexturedQuadDegraded)
|
|
{
|
|
ImTextureID handle = texture.Handle;
|
|
_renderer.DrawTexturedQuad(Unsafe.As<ImTextureID, IntPtr>(ref handle), a, b, c, d, color, uvMin, uvMax);
|
|
}
|
|
}
|
|
|
|
public void AddTexturedQuad(Vector3 center, Vector3 right, Vector3 up, float width, float height, IDalamudTextureWrap texture, uint color = uint.MaxValue, Vector2 uvMin = default(Vector2), Vector2 uvMax = default(Vector2))
|
|
{
|
|
float num = width * 0.5f;
|
|
float num2 = height * 0.5f;
|
|
Vector3 a = center - right * num + up * num2;
|
|
Vector3 b = center + right * num + up * num2;
|
|
Vector3 c = center + right * num - up * num2;
|
|
Vector3 d = center - right * num - up * num2;
|
|
AddTexturedQuad(a, b, c, d, texture, color, uvMin, uvMax);
|
|
}
|
|
|
|
public void PathLineTo(Vector3 point)
|
|
{
|
|
_path.Add(point);
|
|
}
|
|
|
|
public void PathArcTo(Vector3 point, float radius, float startAngle, float stopAngle, uint numSegments = 0u)
|
|
{
|
|
float num = stopAngle - startAngle;
|
|
if (num != 0f)
|
|
{
|
|
if (numSegments == 0)
|
|
{
|
|
numSegments = (uint)(MathF.Abs(num) * 16f);
|
|
}
|
|
float num2 = num / (float)numSegments;
|
|
for (int i = 0; i <= numSegments; i++)
|
|
{
|
|
float num3 = (float)Math.PI / 2f + startAngle + (float)i * num2;
|
|
Vector3 vector = new Vector3(MathF.Cos(num3), 0f, MathF.Sin(num3));
|
|
_path.Add(point + radius * vector);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void PathBezierCubicTo(Vector3 p2, Vector3 p3, Vector3 p4, uint numSegments = 0u)
|
|
{
|
|
if (_path.Count != 0)
|
|
{
|
|
List<Vector3> path = _path;
|
|
Vector3 vector = path[path.Count - 1];
|
|
if (numSegments == 0)
|
|
{
|
|
float num = Vector3.Distance(vector, p2) + Vector3.Distance(p2, p3) + Vector3.Distance(p3, p4);
|
|
numSegments = (uint)MathF.Max(4f, MathF.Ceiling(num * 8f));
|
|
}
|
|
for (int i = 1; i <= numSegments; i++)
|
|
{
|
|
float num2 = (float)i / (float)numSegments;
|
|
float num3 = 1f - num2;
|
|
_path.Add(num3 * num3 * num3 * vector + 3f * num3 * num3 * num2 * p2 + 3f * num3 * num2 * num2 * p3 + num2 * num2 * num2 * p4);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void PathBezierQuadraticTo(Vector3 p2, Vector3 p3, uint numSegments = 0u)
|
|
{
|
|
if (_path.Count != 0)
|
|
{
|
|
List<Vector3> path = _path;
|
|
Vector3 vector = path[path.Count - 1];
|
|
if (numSegments == 0)
|
|
{
|
|
float num = Vector3.Distance(vector, p2) + Vector3.Distance(p2, p3);
|
|
numSegments = (uint)MathF.Max(4f, MathF.Ceiling(num * 8f));
|
|
}
|
|
for (int i = 1; i <= numSegments; i++)
|
|
{
|
|
float num2 = (float)i / (float)numSegments;
|
|
float num3 = 1f - num2;
|
|
_path.Add(num3 * num3 * vector + 2f * num3 * num2 * p2 + num2 * num2 * p3);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void PathCatmullRomTo(ReadOnlySpan<Vector3> points, uint numSegmentsPerSpan = 0u, float tension = 0f, bool closed = false)
|
|
{
|
|
if (points.Length < 2)
|
|
{
|
|
return;
|
|
}
|
|
float num = 1f - tension;
|
|
bool flag = _path.Count > 0;
|
|
int length = points.Length;
|
|
for (int i = 0; i < (closed ? length : (length - 1)); i++)
|
|
{
|
|
Vector3 vector = points[i];
|
|
Vector3 vector2 = points[(i + 1) % length];
|
|
Vector3 vector4;
|
|
if (i == 0 && !closed)
|
|
{
|
|
Vector3 vector3;
|
|
if (!flag)
|
|
{
|
|
vector3 = vector + (vector - vector2);
|
|
}
|
|
else
|
|
{
|
|
List<Vector3> path = _path;
|
|
vector3 = path[path.Count - 1];
|
|
}
|
|
vector4 = vector3;
|
|
}
|
|
else
|
|
{
|
|
vector4 = points[(i - 1 + length) % length];
|
|
}
|
|
Vector3 vector5 = ((i != length - 2 || closed) ? points[(i + 2) % length] : (vector2 + (vector2 - vector)));
|
|
uint num2 = numSegmentsPerSpan;
|
|
if (num2 == 0)
|
|
{
|
|
num2 = (uint)MathF.Max(4f, MathF.Ceiling(Vector3.Distance(vector, vector2) * 8f));
|
|
}
|
|
for (int j = ((i != 0 || flag) ? 1 : 0); j <= num2; j++)
|
|
{
|
|
float num3 = (float)j / (float)num2;
|
|
float num4 = num3 * num3;
|
|
float num5 = num4 * num3;
|
|
float num6 = (0f - num) * num5 + 2f * num * num4 - num * num3;
|
|
float num7 = (2f - num) * num5 + (num - 3f) * num4 + 1f;
|
|
float num8 = (num - 2f) * num5 + (3f - 2f * num) * num4 + num * num3;
|
|
float num9 = num * num5 - num * num4;
|
|
_path.Add(num6 * vector4 + num7 * vector + num8 * vector2 + num9 * vector5);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void PathStroke(uint color, AxStrokeFlags flags = AxStrokeFlags.None, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxLineCap cap = AxLineCap.Butt, AxLineJoin join = AxLineJoin.None, AxDxParams? dxParams = null)
|
|
{
|
|
AxDxParams p = dxParams ?? DefaultDxParams;
|
|
if (_renderer.StrokeDegraded)
|
|
{
|
|
_fallbackRenderer.DrawStroke(_path, thickness, color, (flags & AxStrokeFlags.Closed) > AxStrokeFlags.None, dashLength, gapLength, dashOffset, colorEnd, cap, join);
|
|
}
|
|
else
|
|
{
|
|
_renderer.DrawStroke(_path, thickness, color, (flags & AxStrokeFlags.Closed) > AxStrokeFlags.None, dashLength, gapLength, dashOffset, colorEnd, cap, join, p);
|
|
}
|
|
_path.Clear();
|
|
}
|
|
|
|
public void PathStroke(uint color, float thicknessStart, float thicknessEnd, AxStrokeFlags flags = AxStrokeFlags.None, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxLineCap cap = AxLineCap.Butt, AxLineJoin join = AxLineJoin.None, AxDxParams? dxParams = null)
|
|
{
|
|
if (_path.Count < 2)
|
|
{
|
|
_path.Clear();
|
|
return;
|
|
}
|
|
Span<float> span = ((_path.Count > 1024) ? ((Span<float>)new float[_path.Count]) : stackalloc float[_path.Count]);
|
|
Span<float> span2 = span;
|
|
for (int i = 0; i < _path.Count; i++)
|
|
{
|
|
span2[i] = thicknessStart + (thicknessEnd - thicknessStart) * ((float)i / (float)(_path.Count - 1));
|
|
}
|
|
PathStroke(color, span2, flags, dashLength, gapLength, dashOffset, colorEnd, cap, join, dxParams);
|
|
}
|
|
|
|
public void PathStroke(uint color, ReadOnlySpan<float> thicknesses, AxStrokeFlags flags = AxStrokeFlags.None, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxLineCap cap = AxLineCap.Butt, AxLineJoin join = AxLineJoin.None, AxDxParams? dxParams = null)
|
|
{
|
|
if (_path.Count < 2 || thicknesses.Length < _path.Count)
|
|
{
|
|
_path.Clear();
|
|
return;
|
|
}
|
|
AxDxParams p = dxParams ?? DefaultDxParams;
|
|
bool closed = (flags & AxStrokeFlags.Closed) > AxStrokeFlags.None;
|
|
if (_renderer.StrokeDegraded)
|
|
{
|
|
float num = 0f;
|
|
for (int i = 0; i < thicknesses.Length; i++)
|
|
{
|
|
num += thicknesses[i];
|
|
}
|
|
num /= (float)thicknesses.Length;
|
|
_fallbackRenderer.DrawStroke(_path, num, color, closed, dashLength, gapLength, dashOffset, colorEnd, cap, join);
|
|
}
|
|
else
|
|
{
|
|
_renderer.DrawStroke(_path, thicknesses, color, closed, dashLength, gapLength, dashOffset, colorEnd, cap, join, p);
|
|
}
|
|
_path.Clear();
|
|
}
|
|
|
|
public void PathFill(uint color, AxDxParams? dxParams = null)
|
|
{
|
|
if (_path.Count < 3)
|
|
{
|
|
_path.Clear();
|
|
return;
|
|
}
|
|
for (int i = 1; i < _path.Count - 1; i++)
|
|
{
|
|
AddTriangleFilled(_path[0], _path[i], _path[i + 1], color, dxParams);
|
|
}
|
|
_path.Clear();
|
|
}
|
|
|
|
public void PathFill<T>(T gradient, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
if (_path.Count < 3)
|
|
{
|
|
_path.Clear();
|
|
return;
|
|
}
|
|
for (int i = 1; i < _path.Count - 1; i++)
|
|
{
|
|
AddTriangleFilled(_path[0], _path[i], _path[i + 1], gradient, dxParams);
|
|
}
|
|
_path.Clear();
|
|
}
|
|
|
|
public void AddPolyline(ReadOnlySpan<Vector3> vertices, uint color, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxLineCap cap = AxLineCap.Butt, AxLineJoin join = AxLineJoin.None, AxDxParams? dxParams = null)
|
|
{
|
|
if (vertices.Length >= 2)
|
|
{
|
|
for (int i = 0; i < vertices.Length; i++)
|
|
{
|
|
PathLineTo(vertices[i]);
|
|
}
|
|
PathStroke(color, AxStrokeFlags.None, thickness, dashLength, gapLength, dashOffset, colorEnd, cap, join);
|
|
}
|
|
}
|
|
|
|
public void AddPolygon(ReadOnlySpan<Vector3> vertices, uint color, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxDxParams? dxParams = null)
|
|
{
|
|
if (vertices.Length >= 3)
|
|
{
|
|
for (int i = 0; i < vertices.Length; i++)
|
|
{
|
|
PathLineTo(vertices[i]);
|
|
}
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
}
|
|
}
|
|
|
|
public void AddPolygonFilled(ReadOnlySpan<Vector3> vertices, uint color, AxDxParams? dxParams = null)
|
|
{
|
|
if (vertices.Length >= 3)
|
|
{
|
|
for (int i = 1; i < vertices.Length - 1; i++)
|
|
{
|
|
AddTriangleFilled(vertices[0], vertices[i], vertices[i + 1], color, dxParams);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void AddPolygonFilled<T>(ReadOnlySpan<Vector3> vertices, T gradient, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
if (vertices.Length >= 3)
|
|
{
|
|
for (int i = 1; i < vertices.Length - 1; i++)
|
|
{
|
|
AddTriangleFilled(vertices[0], vertices[i], vertices[i + 1], gradient, dxParams);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void AddTriangle(Vector3 a, Vector3 b, Vector3 c, uint color, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxDxParams? dxParams = null)
|
|
{
|
|
PathLineTo(a);
|
|
PathLineTo(b);
|
|
PathLineTo(c);
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
}
|
|
|
|
public void AddTriangleFilled(Vector3 a, Vector3 b, Vector3 c, uint color, AxDxParams? dxParams = null)
|
|
{
|
|
AddTriangleFilled(a, b, c, color, color, color, dxParams);
|
|
}
|
|
|
|
public void AddTriangleFilled(Vector3 a, Vector3 b, Vector3 c, uint colorA, uint colorB, uint colorC, AxDxParams? dxParams = null)
|
|
{
|
|
AxDxParams p = dxParams ?? DefaultDxParams;
|
|
_renderer.DrawTriangle(a, b, c, colorA, colorB, colorC, p);
|
|
}
|
|
|
|
public void AddTriangleFilled<T>(Vector3 a, Vector3 b, Vector3 c, T gradient, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
AddTriangleFilled(a, b, c, gradient.ColorAt(a), gradient.ColorAt(b), gradient.ColorAt(c), dxParams);
|
|
}
|
|
|
|
public void AddLine(Vector3 start, Vector3 stop, float halfWidth, uint color, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxDxParams? dxParams = null)
|
|
{
|
|
Vector3 vector = stop - start;
|
|
Vector3 vector2 = halfWidth * Vector3.Normalize(Vector3.Cross(vector, Vector3.UnitY));
|
|
AddQuad(start - vector2, stop - vector2, stop + vector2, start + vector2, color, thickness, dashLength, gapLength, dashOffset, colorEnd, dxParams);
|
|
}
|
|
|
|
public void AddLineFilled(Vector3 start, Vector3 stop, float halfWidth, uint color, uint? colorEnd = null, AxDxParams? dxParams = null)
|
|
{
|
|
Vector3 vector = stop - start;
|
|
Vector3 vector2 = halfWidth * Vector3.Normalize(Vector3.Cross(vector, Vector3.UnitY));
|
|
AddQuadFilled(start - vector2, stop - vector2, stop + vector2, start + vector2, color, colorEnd ?? color, colorEnd ?? color, color, dxParams);
|
|
}
|
|
|
|
public void AddLineFilled<T>(Vector3 start, Vector3 stop, float halfWidth, T gradient, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
Vector3 vector = stop - start;
|
|
Vector3 vector2 = halfWidth * Vector3.Normalize(Vector3.Cross(vector, Vector3.UnitY));
|
|
AddQuadFilled(start - vector2, stop - vector2, stop + vector2, start + vector2, gradient, dxParams);
|
|
}
|
|
|
|
public void AddArrowFilled(Vector3 start, Vector3 stop, float halfWidth, uint color, float headLength = 0f, float headHalfWidth = 0f, AxDxParams? dxParams = null)
|
|
{
|
|
Vector3 vector = stop - start;
|
|
float num = vector.Length();
|
|
if (!(num < 1E-06f))
|
|
{
|
|
if (headLength == 0f)
|
|
{
|
|
headLength = halfWidth * 3f;
|
|
}
|
|
if (headHalfWidth == 0f)
|
|
{
|
|
headHalfWidth = halfWidth * 2f;
|
|
}
|
|
Vector3 vector2 = vector / num;
|
|
Vector3 vector3 = Vector3.Normalize(Vector3.Cross(vector2, Vector3.UnitY));
|
|
if (num > headLength)
|
|
{
|
|
Vector3 vector4 = stop - vector2 * headLength;
|
|
AddQuadFilled(start - vector3 * halfWidth, vector4 - vector3 * halfWidth, vector4 + vector3 * halfWidth, start + vector3 * halfWidth, color, dxParams);
|
|
AddTriangleFilled(vector4 - vector3 * headHalfWidth, stop, vector4 + vector3 * headHalfWidth, color, dxParams);
|
|
}
|
|
else
|
|
{
|
|
AddTriangleFilled(start - vector3 * headHalfWidth, stop, start + vector3 * headHalfWidth, color, dxParams);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void AddArrowFilled<T>(Vector3 start, Vector3 stop, float halfWidth, T gradient, float headLength = 0f, float headHalfWidth = 0f, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
Vector3 vector = stop - start;
|
|
float num = vector.Length();
|
|
if (!(num < 1E-06f))
|
|
{
|
|
if (headLength == 0f)
|
|
{
|
|
headLength = halfWidth * 3f;
|
|
}
|
|
if (headHalfWidth == 0f)
|
|
{
|
|
headHalfWidth = halfWidth * 2f;
|
|
}
|
|
Vector3 vector2 = vector / num;
|
|
Vector3 vector3 = Vector3.Normalize(Vector3.Cross(vector2, Vector3.UnitY));
|
|
if (num > headLength)
|
|
{
|
|
Vector3 vector4 = stop - vector2 * headLength;
|
|
AddQuadFilled(start - vector3 * halfWidth, vector4 - vector3 * halfWidth, vector4 + vector3 * halfWidth, start + vector3 * halfWidth, gradient, dxParams);
|
|
AddTriangleFilled(vector4 - vector3 * headHalfWidth, stop, vector4 + vector3 * headHalfWidth, gradient, dxParams);
|
|
}
|
|
else
|
|
{
|
|
AddTriangleFilled(start - vector3 * headHalfWidth, stop, start + vector3 * headHalfWidth, gradient, dxParams);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void AddArrow(Vector3 start, Vector3 stop, float halfWidth, uint color, float headLength = 0f, float headHalfWidth = 0f, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxDxParams? dxParams = null)
|
|
{
|
|
Vector3 vector = stop - start;
|
|
float num = vector.Length();
|
|
if (!(num < 1E-06f))
|
|
{
|
|
if (headLength == 0f)
|
|
{
|
|
headLength = halfWidth * 3f;
|
|
}
|
|
if (headHalfWidth == 0f)
|
|
{
|
|
headHalfWidth = halfWidth * 2f;
|
|
}
|
|
Vector3 vector2 = vector / num;
|
|
Vector3 vector3 = Vector3.Normalize(Vector3.Cross(vector2, Vector3.UnitY));
|
|
if (num > headLength)
|
|
{
|
|
Vector3 vector4 = stop - vector2 * headLength;
|
|
PathLineTo(start + vector3 * halfWidth);
|
|
PathLineTo(vector4 + vector3 * halfWidth);
|
|
PathLineTo(vector4 + vector3 * headHalfWidth);
|
|
PathLineTo(stop);
|
|
PathLineTo(vector4 - vector3 * headHalfWidth);
|
|
PathLineTo(vector4 - vector3 * halfWidth);
|
|
PathLineTo(start - vector3 * halfWidth);
|
|
}
|
|
else
|
|
{
|
|
PathLineTo(start + vector3 * headHalfWidth);
|
|
PathLineTo(stop);
|
|
PathLineTo(start - vector3 * headHalfWidth);
|
|
}
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
}
|
|
}
|
|
|
|
public void AddQuad(Vector3 a, Vector3 b, Vector3 c, Vector3 d, uint color, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxDxParams? dxParams = null)
|
|
{
|
|
PathLineTo(a);
|
|
PathLineTo(b);
|
|
PathLineTo(c);
|
|
PathLineTo(d);
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
}
|
|
|
|
public void AddQuadFilled(Vector3 a, Vector3 b, Vector3 c, Vector3 d, uint color, AxDxParams? dxParams = null)
|
|
{
|
|
AddQuadFilled(a, b, c, d, color, color, color, color, dxParams);
|
|
}
|
|
|
|
public void AddQuadFilled(Vector3 a, Vector3 b, Vector3 c, Vector3 d, uint colorA, uint colorB, uint colorC, uint colorD, AxDxParams? dxParams = null)
|
|
{
|
|
AddTriangleFilled(a, b, c, colorA, colorB, colorC, dxParams);
|
|
AddTriangleFilled(a, c, d, colorA, colorC, colorD, dxParams);
|
|
}
|
|
|
|
public void AddQuadFilled<T>(Vector3 a, Vector3 b, Vector3 c, Vector3 d, T gradient, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
AddTriangleFilled(a, b, c, gradient.ColorAt(a), gradient.ColorAt(b), gradient.ColorAt(c), dxParams);
|
|
AddTriangleFilled(a, c, d, gradient.ColorAt(a), gradient.ColorAt(c), gradient.ColorAt(d), dxParams);
|
|
}
|
|
|
|
public void AddRoundedRect(Vector3 origin, float halfWidth, float halfHeight, float cornerRadius, uint color, uint numSegments = 0u, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, float rotation = 0f, AxDxParams? dxParams = null)
|
|
{
|
|
float num = MathF.Min(cornerRadius, MathF.Min(halfWidth, halfHeight));
|
|
float cos = MathF.Cos(rotation);
|
|
float sin = MathF.Sin(rotation);
|
|
if (num <= 0f)
|
|
{
|
|
AddQuad(RotateXZ(origin, 0f - halfWidth, 0f - halfHeight, cos, sin), RotateXZ(origin, halfWidth, 0f - halfHeight, cos, sin), RotateXZ(origin, halfWidth, halfHeight, cos, sin), RotateXZ(origin, 0f - halfWidth, halfHeight, cos, sin), color, thickness, dashLength, gapLength, dashOffset, colorEnd, dxParams);
|
|
return;
|
|
}
|
|
Vector3 point = RotateXZ(origin, halfWidth - num, 0f - halfHeight + num, cos, sin);
|
|
Vector3 point2 = RotateXZ(origin, halfWidth - num, halfHeight - num, cos, sin);
|
|
Vector3 point3 = RotateXZ(origin, 0f - halfWidth + num, halfHeight - num, cos, sin);
|
|
Vector3 point4 = RotateXZ(origin, 0f - halfWidth + num, 0f - halfHeight + num, cos, sin);
|
|
PathArcTo(point, num, (float)Math.PI + rotation, 4.712389f + rotation, numSegments);
|
|
PathArcTo(point2, num, 4.712389f + rotation, (float)Math.PI * 2f + rotation, numSegments);
|
|
PathArcTo(point3, num, rotation, (float)Math.PI / 2f + rotation, numSegments);
|
|
PathArcTo(point4, num, (float)Math.PI / 2f + rotation, (float)Math.PI + rotation, numSegments);
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
}
|
|
|
|
public void AddRoundedRectFilled(Vector3 origin, float halfWidth, float halfHeight, float cornerRadius, uint color, uint numSegments = 0u, float rotation = 0f, AxDxParams? dxParams = null)
|
|
{
|
|
float num = MathF.Min(cornerRadius, MathF.Min(halfWidth, halfHeight));
|
|
float cos = MathF.Cos(rotation);
|
|
float sin = MathF.Sin(rotation);
|
|
if (num <= 0f)
|
|
{
|
|
AddQuadFilled(RotateXZ(origin, 0f - halfWidth, 0f - halfHeight, cos, sin), RotateXZ(origin, halfWidth, 0f - halfHeight, cos, sin), RotateXZ(origin, halfWidth, halfHeight, cos, sin), RotateXZ(origin, 0f - halfWidth, halfHeight, cos, sin), color, dxParams);
|
|
return;
|
|
}
|
|
if (num < halfWidth)
|
|
{
|
|
AddQuadFilled(RotateXZ(origin, 0f - halfWidth + num, 0f - halfHeight, cos, sin), RotateXZ(origin, halfWidth - num, 0f - halfHeight, cos, sin), RotateXZ(origin, halfWidth - num, halfHeight, cos, sin), RotateXZ(origin, 0f - halfWidth + num, halfHeight, cos, sin), color, dxParams);
|
|
}
|
|
if (num < halfHeight)
|
|
{
|
|
AddQuadFilled(RotateXZ(origin, 0f - halfWidth, 0f - halfHeight + num, cos, sin), RotateXZ(origin, 0f - halfWidth + num, 0f - halfHeight + num, cos, sin), RotateXZ(origin, 0f - halfWidth + num, halfHeight - num, cos, sin), RotateXZ(origin, 0f - halfWidth, halfHeight - num, cos, sin), color, dxParams);
|
|
AddQuadFilled(RotateXZ(origin, halfWidth - num, 0f - halfHeight + num, cos, sin), RotateXZ(origin, halfWidth, 0f - halfHeight + num, cos, sin), RotateXZ(origin, halfWidth, halfHeight - num, cos, sin), RotateXZ(origin, halfWidth - num, halfHeight - num, cos, sin), color, dxParams);
|
|
}
|
|
Vector3 origin2 = RotateXZ(origin, halfWidth - num, 0f - halfHeight + num, cos, sin);
|
|
Vector3 origin3 = RotateXZ(origin, halfWidth - num, halfHeight - num, cos, sin);
|
|
Vector3 origin4 = RotateXZ(origin, 0f - halfWidth + num, halfHeight - num, cos, sin);
|
|
Vector3 origin5 = RotateXZ(origin, 0f - halfWidth + num, 0f - halfHeight + num, cos, sin);
|
|
AddArcFilled(origin2, num, (float)Math.PI + rotation, 4.712389f + rotation, color, null, numSegments, dxParams);
|
|
AddArcFilled(origin3, num, 4.712389f + rotation, (float)Math.PI * 2f + rotation, color, null, numSegments, dxParams);
|
|
AddArcFilled(origin4, num, rotation, (float)Math.PI / 2f + rotation, color, null, numSegments, dxParams);
|
|
AddArcFilled(origin5, num, (float)Math.PI / 2f + rotation, (float)Math.PI + rotation, color, null, numSegments, dxParams);
|
|
}
|
|
|
|
public void AddRoundedRectFilled<T>(Vector3 origin, float halfWidth, float halfHeight, float cornerRadius, T gradient, uint numSegments = 0u, float rotation = 0f, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
float num = MathF.Min(cornerRadius, MathF.Min(halfWidth, halfHeight));
|
|
float cos = MathF.Cos(rotation);
|
|
float sin = MathF.Sin(rotation);
|
|
if (num <= 0f)
|
|
{
|
|
AddQuadFilled(RotateXZ(origin, 0f - halfWidth, 0f - halfHeight, cos, sin), RotateXZ(origin, halfWidth, 0f - halfHeight, cos, sin), RotateXZ(origin, halfWidth, halfHeight, cos, sin), RotateXZ(origin, 0f - halfWidth, halfHeight, cos, sin), gradient, dxParams);
|
|
return;
|
|
}
|
|
if (num < halfWidth)
|
|
{
|
|
AddQuadFilled(RotateXZ(origin, 0f - halfWidth + num, 0f - halfHeight, cos, sin), RotateXZ(origin, halfWidth - num, 0f - halfHeight, cos, sin), RotateXZ(origin, halfWidth - num, halfHeight, cos, sin), RotateXZ(origin, 0f - halfWidth + num, halfHeight, cos, sin), gradient, dxParams);
|
|
}
|
|
if (num < halfHeight)
|
|
{
|
|
AddQuadFilled(RotateXZ(origin, 0f - halfWidth, 0f - halfHeight + num, cos, sin), RotateXZ(origin, 0f - halfWidth + num, 0f - halfHeight + num, cos, sin), RotateXZ(origin, 0f - halfWidth + num, halfHeight - num, cos, sin), RotateXZ(origin, 0f - halfWidth, halfHeight - num, cos, sin), gradient, dxParams);
|
|
AddQuadFilled(RotateXZ(origin, halfWidth - num, 0f - halfHeight + num, cos, sin), RotateXZ(origin, halfWidth, 0f - halfHeight + num, cos, sin), RotateXZ(origin, halfWidth, halfHeight - num, cos, sin), RotateXZ(origin, halfWidth - num, halfHeight - num, cos, sin), gradient, dxParams);
|
|
}
|
|
Vector3 origin2 = RotateXZ(origin, halfWidth - num, 0f - halfHeight + num, cos, sin);
|
|
Vector3 origin3 = RotateXZ(origin, halfWidth - num, halfHeight - num, cos, sin);
|
|
Vector3 origin4 = RotateXZ(origin, 0f - halfWidth + num, halfHeight - num, cos, sin);
|
|
Vector3 origin5 = RotateXZ(origin, 0f - halfWidth + num, 0f - halfHeight + num, cos, sin);
|
|
AddFanFilled(origin2, 0f, num, (float)Math.PI + rotation, 4.712389f + rotation, gradient, numSegments, dxParams);
|
|
AddFanFilled(origin3, 0f, num, 4.712389f + rotation, (float)Math.PI * 2f + rotation, gradient, numSegments, dxParams);
|
|
AddFanFilled(origin4, 0f, num, rotation, (float)Math.PI / 2f + rotation, gradient, numSegments, dxParams);
|
|
AddFanFilled(origin5, 0f, num, (float)Math.PI / 2f + rotation, (float)Math.PI + rotation, gradient, numSegments, dxParams);
|
|
}
|
|
|
|
public void AddPill(Vector3 start, Vector3 stop, float halfWidth, uint color, uint numSegments = 0u, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxDxParams? dxParams = null)
|
|
{
|
|
Vector3 vector = stop - start;
|
|
float num = vector.Length();
|
|
if (num < 1E-06f)
|
|
{
|
|
AddCircle(start, halfWidth, color, numSegments * 2, thickness, dashLength, gapLength, dashOffset, colorEnd, dxParams);
|
|
return;
|
|
}
|
|
Vector3 vector2 = vector / num;
|
|
Vector3 vector3 = Vector3.Normalize(Vector3.Cross(vector2, Vector3.UnitY));
|
|
int num2 = (int)((numSegments != 0) ? numSegments : 50);
|
|
PathLineTo(start + vector3 * halfWidth);
|
|
PathLineTo(stop + vector3 * halfWidth);
|
|
for (int i = 1; i <= num2; i++)
|
|
{
|
|
float num3 = (float)i * (float)Math.PI / (float)num2;
|
|
PathLineTo(stop + halfWidth * (MathF.Cos(num3) * vector3 + MathF.Sin(num3) * vector2));
|
|
}
|
|
PathLineTo(start - vector3 * halfWidth);
|
|
for (int j = 1; j < num2; j++)
|
|
{
|
|
float num4 = (float)Math.PI + (float)j * (float)Math.PI / (float)num2;
|
|
PathLineTo(start + halfWidth * (MathF.Cos(num4) * vector3 + MathF.Sin(num4) * vector2));
|
|
}
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
}
|
|
|
|
public void AddPillFilled(Vector3 start, Vector3 stop, float halfWidth, uint color, uint numSegments = 0u, AxDxParams? dxParams = null)
|
|
{
|
|
Vector3 vector = stop - start;
|
|
float num = vector.Length();
|
|
if (num < 1E-06f)
|
|
{
|
|
AddCircleFilled(start, halfWidth, color, null, numSegments * 2, dxParams);
|
|
return;
|
|
}
|
|
Vector3 vector2 = vector / num;
|
|
Vector3 vector3 = Vector3.Normalize(Vector3.Cross(vector2, Vector3.UnitY));
|
|
AddQuadFilled(start + vector3 * halfWidth, stop + vector3 * halfWidth, stop - vector3 * halfWidth, start - vector3 * halfWidth, color, dxParams);
|
|
int num2 = (int)((numSegments != 0) ? numSegments : 25);
|
|
Vector3 b = stop + vector3 * halfWidth;
|
|
for (int i = 1; i <= num2; i++)
|
|
{
|
|
float num3 = (float)i * (float)Math.PI / (float)num2;
|
|
Vector3 vector4 = stop + halfWidth * (MathF.Cos(num3) * vector3 + MathF.Sin(num3) * vector2);
|
|
AddTriangleFilled(stop, b, vector4, color, dxParams);
|
|
b = vector4;
|
|
}
|
|
b = start - vector3 * halfWidth;
|
|
for (int j = 1; j <= num2; j++)
|
|
{
|
|
float num4 = (float)Math.PI + (float)j * (float)Math.PI / (float)num2;
|
|
Vector3 vector5 = start + halfWidth * (MathF.Cos(num4) * vector3 + MathF.Sin(num4) * vector2);
|
|
AddTriangleFilled(start, b, vector5, color, dxParams);
|
|
b = vector5;
|
|
}
|
|
}
|
|
|
|
public void AddPillFilled<T>(Vector3 start, Vector3 stop, float halfWidth, T gradient, uint numSegments = 0u, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
Vector3 vector = stop - start;
|
|
float num = vector.Length();
|
|
if (num < 1E-06f)
|
|
{
|
|
AddCircleFilled(start, halfWidth, gradient, numSegments * 2, dxParams);
|
|
return;
|
|
}
|
|
Vector3 vector2 = vector / num;
|
|
Vector3 vector3 = Vector3.Normalize(Vector3.Cross(vector2, Vector3.UnitY));
|
|
AddQuadFilled(start + vector3 * halfWidth, stop + vector3 * halfWidth, stop - vector3 * halfWidth, start - vector3 * halfWidth, gradient, dxParams);
|
|
int num2 = (int)((numSegments != 0) ? numSegments : 25);
|
|
Vector3 b = stop + vector3 * halfWidth;
|
|
for (int i = 1; i <= num2; i++)
|
|
{
|
|
float num3 = (float)i * (float)Math.PI / (float)num2;
|
|
Vector3 vector4 = stop + halfWidth * (MathF.Cos(num3) * vector3 + MathF.Sin(num3) * vector2);
|
|
AddTriangleFilled(stop, b, vector4, gradient, dxParams);
|
|
b = vector4;
|
|
}
|
|
b = start - vector3 * halfWidth;
|
|
for (int j = 1; j <= num2; j++)
|
|
{
|
|
float num4 = (float)Math.PI + (float)j * (float)Math.PI / (float)num2;
|
|
Vector3 vector5 = start + halfWidth * (MathF.Cos(num4) * vector3 + MathF.Sin(num4) * vector2);
|
|
AddTriangleFilled(start, b, vector5, gradient, dxParams);
|
|
b = vector5;
|
|
}
|
|
}
|
|
|
|
public void AddCircle(Vector3 origin, float radius, uint color, uint numSegments = 0u, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxDxParams? dxParams = null)
|
|
{
|
|
PathArcTo(origin, radius, 0f, (float)Math.PI * 2f, numSegments);
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
}
|
|
|
|
public void AddCircleFilled(Vector3 origin, float radius, uint color, uint? colorEnd = null, uint numSegments = 0u, AxDxParams? dxParams = null)
|
|
{
|
|
AddFanFilled(origin, 0f, radius, 0f, (float)Math.PI * 2f, color, colorEnd, numSegments, dxParams);
|
|
}
|
|
|
|
public void AddCircleFilled<T>(Vector3 origin, float radius, T gradient, uint numSegments = 0u, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
AddFanFilled(origin, 0f, radius, 0f, (float)Math.PI * 2f, gradient, numSegments, dxParams);
|
|
}
|
|
|
|
public void AddArc(Vector3 origin, float radius, float minAngle, float maxAngle, uint color, uint numSegments = 0u, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxDxParams? dxParams = null)
|
|
{
|
|
PathArcTo(origin, radius, minAngle, maxAngle, numSegments);
|
|
PathStroke(color, AxStrokeFlags.None, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
}
|
|
|
|
public void AddArcFilled(Vector3 origin, float radius, float minAngle, float maxAngle, uint color, uint? colorEnd = null, uint numSegments = 0u, AxDxParams? dxParams = null)
|
|
{
|
|
AddFanFilled(origin, 0f, radius, minAngle, maxAngle, color, colorEnd, numSegments, dxParams);
|
|
}
|
|
|
|
public void AddArcFilled<T>(Vector3 origin, float radius, float minAngle, float maxAngle, T gradient, uint numSegments = 0u, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
AddFanFilled(origin, 0f, radius, minAngle, maxAngle, gradient, numSegments, dxParams);
|
|
}
|
|
|
|
public void AddCone(Vector3 origin, float radius, float rotation, float angle, uint color, uint numSegments = 0u, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxDxParams? dxParams = null)
|
|
{
|
|
float num = angle / 2f;
|
|
AddFan(origin, 0f, radius, rotation - num, rotation + num, color, numSegments, thickness, dashLength, gapLength, dashOffset, colorEnd, dxParams);
|
|
}
|
|
|
|
public void AddConeFilled(Vector3 origin, float radius, float rotation, float angle, uint color, uint? colorEnd = null, uint numSegments = 0u, AxDxParams? dxParams = null)
|
|
{
|
|
float num = angle / 2f;
|
|
AddFanFilled(origin, 0f, radius, rotation - num, rotation + num, color, colorEnd, numSegments, dxParams);
|
|
}
|
|
|
|
public void AddConeFilled<T>(Vector3 origin, float radius, float rotation, float angle, T gradient, uint numSegments = 0u, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
float num = angle / 2f;
|
|
AddFanFilled(origin, 0f, radius, rotation - num, rotation + num, gradient, numSegments, dxParams);
|
|
}
|
|
|
|
public void AddFan(Vector3 origin, float innerRadius, float outerRadius, float minAngle, float maxAngle, uint color, uint numSegments = 0u, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxDxParams? dxParams = null)
|
|
{
|
|
bool flag = (double)(maxAngle - minAngle) >= 6.283184482025146;
|
|
PathArcTo(origin, outerRadius, minAngle, maxAngle, numSegments);
|
|
if (innerRadius > 0f)
|
|
{
|
|
if (flag)
|
|
{
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
}
|
|
PathArcTo(origin, innerRadius, maxAngle, minAngle, numSegments);
|
|
}
|
|
else if (!flag)
|
|
{
|
|
PathLineTo(origin);
|
|
}
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
}
|
|
|
|
public void AddFanFilled(Vector3 origin, float innerRadius, float outerRadius, float minAngle, float maxAngle, uint color, uint? colorEnd = null, uint numSegments = 0u, AxDxParams? dxParams = null)
|
|
{
|
|
AxDxParams p = dxParams ?? DefaultDxParams;
|
|
_renderer.DrawFan(origin, innerRadius, outerRadius, minAngle, maxAngle, color, colorEnd ?? color, numSegments, p);
|
|
}
|
|
|
|
public void AddFanFilled<T>(Vector3 origin, float innerRadius, float outerRadius, float minAngle, float maxAngle, T gradient, uint numSegments = 0u, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
AxDxParams p = dxParams ?? DefaultDxParams;
|
|
_renderer.DrawTriangleFanGradient(origin, innerRadius, outerRadius, minAngle, maxAngle, gradient, numSegments, p);
|
|
}
|
|
|
|
public void AddRegularPolygon(Vector3 origin, float radius, uint numSides, uint color, float rotation = 0f, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxDxParams? dxParams = null)
|
|
{
|
|
if (numSides >= 3)
|
|
{
|
|
float num = (float)Math.PI * 2f / (float)numSides;
|
|
float num2 = (float)Math.PI / 2f + rotation;
|
|
for (uint num3 = 0u; num3 < numSides; num3++)
|
|
{
|
|
float num4 = num2 + (float)num3 * num;
|
|
PathLineTo(origin + radius * new Vector3(MathF.Cos(num4), 0f, MathF.Sin(num4)));
|
|
}
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
}
|
|
}
|
|
|
|
public void AddRegularPolygonFilled(Vector3 origin, float radius, uint numSides, uint color, float rotation = 0f, AxDxParams? dxParams = null)
|
|
{
|
|
if (numSides >= 3)
|
|
{
|
|
float num = (float)Math.PI * 2f / (float)numSides;
|
|
float num2 = (float)Math.PI / 2f + rotation;
|
|
Vector3 vector = origin + radius * new Vector3(MathF.Cos(num2), 0f, MathF.Sin(num2));
|
|
Vector3 b = vector;
|
|
for (uint num3 = 1u; num3 < numSides; num3++)
|
|
{
|
|
float num4 = num2 + (float)num3 * num;
|
|
Vector3 vector2 = origin + radius * new Vector3(MathF.Cos(num4), 0f, MathF.Sin(num4));
|
|
AddTriangleFilled(origin, b, vector2, color, dxParams);
|
|
b = vector2;
|
|
}
|
|
AddTriangleFilled(origin, b, vector, color, dxParams);
|
|
}
|
|
}
|
|
|
|
public void AddRegularPolygonFilled<T>(Vector3 origin, float radius, uint numSides, T gradient, float rotation = 0f, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
if (numSides >= 3)
|
|
{
|
|
float num = (float)Math.PI * 2f / (float)numSides;
|
|
float num2 = (float)Math.PI / 2f + rotation;
|
|
Vector3 vector = origin + radius * new Vector3(MathF.Cos(num2), 0f, MathF.Sin(num2));
|
|
Vector3 b = vector;
|
|
for (uint num3 = 1u; num3 < numSides; num3++)
|
|
{
|
|
float num4 = num2 + (float)num3 * num;
|
|
Vector3 vector2 = origin + radius * new Vector3(MathF.Cos(num4), 0f, MathF.Sin(num4));
|
|
AddTriangleFilled(origin, b, vector2, gradient, dxParams);
|
|
b = vector2;
|
|
}
|
|
AddTriangleFilled(origin, b, vector, gradient, dxParams);
|
|
}
|
|
}
|
|
|
|
public void AddStar(Vector3 origin, float outerRadius, float innerRadius, uint numPoints, uint color, float rotation = 0f, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxDxParams? dxParams = null)
|
|
{
|
|
if (numPoints >= 2)
|
|
{
|
|
float num = (float)Math.PI / (float)numPoints;
|
|
float num2 = (float)Math.PI / 2f + rotation;
|
|
for (uint num3 = 0u; num3 < numPoints * 2; num3++)
|
|
{
|
|
float num4 = num2 + (float)num3 * num;
|
|
float num5 = ((num3 % 2 == 0) ? outerRadius : innerRadius);
|
|
PathLineTo(origin + num5 * new Vector3(MathF.Cos(num4), 0f, MathF.Sin(num4)));
|
|
}
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
}
|
|
}
|
|
|
|
public void AddStarFilled(Vector3 origin, float outerRadius, float innerRadius, uint numPoints, uint color, float rotation = 0f, AxDxParams? dxParams = null)
|
|
{
|
|
if (numPoints >= 2)
|
|
{
|
|
float num = (float)Math.PI / (float)numPoints;
|
|
float num2 = (float)Math.PI / 2f + rotation;
|
|
uint num3 = numPoints * 2;
|
|
Vector3 vector = origin + outerRadius * new Vector3(MathF.Cos(num2), 0f, MathF.Sin(num2));
|
|
Vector3 b = vector;
|
|
for (uint num4 = 1u; num4 < num3; num4++)
|
|
{
|
|
float num5 = num2 + (float)num4 * num;
|
|
float num6 = ((num4 % 2 == 0) ? outerRadius : innerRadius);
|
|
Vector3 vector2 = origin + num6 * new Vector3(MathF.Cos(num5), 0f, MathF.Sin(num5));
|
|
AddTriangleFilled(origin, b, vector2, color, dxParams);
|
|
b = vector2;
|
|
}
|
|
AddTriangleFilled(origin, b, vector, color, dxParams);
|
|
}
|
|
}
|
|
|
|
public void AddStarFilled<T>(Vector3 origin, float outerRadius, float innerRadius, uint numPoints, T gradient, float rotation = 0f, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
if (numPoints >= 2)
|
|
{
|
|
float num = (float)Math.PI / (float)numPoints;
|
|
float num2 = (float)Math.PI / 2f + rotation;
|
|
uint num3 = numPoints * 2;
|
|
Vector3 vector = origin + outerRadius * new Vector3(MathF.Cos(num2), 0f, MathF.Sin(num2));
|
|
Vector3 b = vector;
|
|
for (uint num4 = 1u; num4 < num3; num4++)
|
|
{
|
|
float num5 = num2 + (float)num4 * num;
|
|
float num6 = ((num4 % 2 == 0) ? outerRadius : innerRadius);
|
|
Vector3 vector2 = origin + num6 * new Vector3(MathF.Cos(num5), 0f, MathF.Sin(num5));
|
|
AddTriangleFilled(origin, b, vector2, gradient, dxParams);
|
|
b = vector2;
|
|
}
|
|
AddTriangleFilled(origin, b, vector, gradient, dxParams);
|
|
}
|
|
}
|
|
|
|
public void AddWireframeBox(Vector3 center, Vector3 halfExtent, uint color, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxDxParams? dxParams = null)
|
|
{
|
|
float x = halfExtent.X;
|
|
float y = halfExtent.Y;
|
|
float z = halfExtent.Z;
|
|
Vector3 point = center + new Vector3(0f - x, 0f - y, 0f - z);
|
|
Vector3 point2 = center + new Vector3(x, 0f - y, 0f - z);
|
|
Vector3 point3 = center + new Vector3(x, 0f - y, z);
|
|
Vector3 point4 = center + new Vector3(0f - x, 0f - y, z);
|
|
Vector3 point5 = center + new Vector3(0f - x, y, 0f - z);
|
|
Vector3 point6 = center + new Vector3(x, y, 0f - z);
|
|
Vector3 point7 = center + new Vector3(x, y, z);
|
|
Vector3 point8 = center + new Vector3(0f - x, y, z);
|
|
PathLineTo(point);
|
|
PathLineTo(point2);
|
|
PathLineTo(point3);
|
|
PathLineTo(point4);
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
PathLineTo(point5);
|
|
PathLineTo(point6);
|
|
PathLineTo(point7);
|
|
PathLineTo(point8);
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
PathLineTo(point);
|
|
PathLineTo(point5);
|
|
PathStroke(color, AxStrokeFlags.None, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
PathLineTo(point2);
|
|
PathLineTo(point6);
|
|
PathStroke(color, AxStrokeFlags.None, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
PathLineTo(point3);
|
|
PathLineTo(point7);
|
|
PathStroke(color, AxStrokeFlags.None, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
PathLineTo(point4);
|
|
PathLineTo(point8);
|
|
PathStroke(color, AxStrokeFlags.None, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
}
|
|
|
|
public void AddWireframeSphere(Vector3 center, float radius, uint color, uint numSegments = 0u, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxDxParams? dxParams = null)
|
|
{
|
|
if (numSegments == 0)
|
|
{
|
|
numSegments = (uint)MathF.Max(12f, MathF.Ceiling(radius * 8f));
|
|
}
|
|
float num = (float)Math.PI * 2f / (float)numSegments;
|
|
for (uint num2 = 0u; num2 < numSegments; num2++)
|
|
{
|
|
float num3 = (float)num2 * num;
|
|
PathLineTo(center + new Vector3(MathF.Cos(num3) * radius, 0f, MathF.Sin(num3) * radius));
|
|
}
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
for (uint num4 = 0u; num4 < numSegments; num4++)
|
|
{
|
|
float num5 = (float)num4 * num;
|
|
PathLineTo(center + new Vector3(MathF.Cos(num5) * radius, MathF.Sin(num5) * radius, 0f));
|
|
}
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
for (uint num6 = 0u; num6 < numSegments; num6++)
|
|
{
|
|
float num7 = (float)num6 * num;
|
|
PathLineTo(center + new Vector3(0f, MathF.Cos(num7) * radius, MathF.Sin(num7) * radius));
|
|
}
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
}
|
|
|
|
public void AddWireframeCylinder(Vector3 center, float radius, float halfHeight, uint color, uint numVerticals = 4u, uint numSegments = 0u, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, AxDxParams? dxParams = null)
|
|
{
|
|
if (numSegments == 0)
|
|
{
|
|
numSegments = (uint)MathF.Max(12f, MathF.Ceiling(radius * 8f));
|
|
}
|
|
float num = (float)Math.PI * 2f / (float)numSegments;
|
|
float y = center.Y + halfHeight;
|
|
float y2 = center.Y - halfHeight;
|
|
for (uint num2 = 0u; num2 < numSegments; num2++)
|
|
{
|
|
float num3 = (float)num2 * num;
|
|
PathLineTo(new Vector3(center.X + MathF.Cos(num3) * radius, y2, center.Z + MathF.Sin(num3) * radius));
|
|
}
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
for (uint num4 = 0u; num4 < numSegments; num4++)
|
|
{
|
|
float num5 = (float)num4 * num;
|
|
PathLineTo(new Vector3(center.X + MathF.Cos(num5) * radius, y, center.Z + MathF.Sin(num5) * radius));
|
|
}
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
if (numVerticals != 0)
|
|
{
|
|
float num6 = (float)Math.PI * 2f / (float)numVerticals;
|
|
for (uint num7 = 0u; num7 < numVerticals; num7++)
|
|
{
|
|
float num8 = (float)num7 * num6;
|
|
float x = center.X + MathF.Cos(num8) * radius;
|
|
float z = center.Z + MathF.Sin(num8) * radius;
|
|
PathLineTo(new Vector3(x, y2, z));
|
|
PathLineTo(new Vector3(x, y, z));
|
|
PathStroke(color, AxStrokeFlags.None, thickness, dashLength, gapLength, dashOffset, colorEnd);
|
|
}
|
|
}
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static Vector3 RotateXZ(Vector3 origin, float dx, float dz, float cos, float sin)
|
|
{
|
|
return new Vector3(origin.X + dx * cos - dz * sin, origin.Y, origin.Z + dx * sin + dz * cos);
|
|
}
|
|
|
|
public void AddClipZone(Vector2 min, Vector2 max)
|
|
{
|
|
_renderer.AddClipZone(min, max);
|
|
}
|
|
|
|
public void AddCircleFilledOnTerrain(Vector3 origin, float radius, uint color, uint? colorEnd = null, uint numSegments = 0u, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null)
|
|
{
|
|
AxDxParams p = dxParams ?? DefaultDxParams;
|
|
_renderer.DrawTerrainFan(origin, 0f, radius, 0f, (float)Math.PI * 2f, color, colorEnd ?? color, resolution, yOffset, numSegments, p);
|
|
}
|
|
|
|
public void AddCircleFilledOnTerrain<T>(Vector3 origin, float radius, T gradient, uint numSegments = 0u, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
AxDxParams p = dxParams ?? DefaultDxParams;
|
|
_renderer.DrawTerrainFanGradient(origin, 0f, radius, 0f, (float)Math.PI * 2f, gradient, resolution, yOffset, numSegments, p);
|
|
}
|
|
|
|
public void AddFanFilledOnTerrain(Vector3 origin, float innerRadius, float outerRadius, float minAngle, float maxAngle, uint color, uint? colorEnd = null, uint numSegments = 0u, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null)
|
|
{
|
|
AxDxParams p = dxParams ?? DefaultDxParams;
|
|
_renderer.DrawTerrainFan(origin, innerRadius, outerRadius, minAngle, maxAngle, color, colorEnd ?? color, resolution, yOffset, numSegments, p);
|
|
}
|
|
|
|
public void AddFanFilledOnTerrain<T>(Vector3 origin, float innerRadius, float outerRadius, float minAngle, float maxAngle, T gradient, uint numSegments = 0u, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
AxDxParams p = dxParams ?? DefaultDxParams;
|
|
_renderer.DrawTerrainFanGradient(origin, innerRadius, outerRadius, minAngle, maxAngle, gradient, resolution, yOffset, numSegments, p);
|
|
}
|
|
|
|
public void AddQuadFilledOnTerrain(Vector3 a, Vector3 b, Vector3 c, Vector3 d, uint color, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null)
|
|
{
|
|
AxDxParams p = dxParams ?? DefaultDxParams;
|
|
_renderer.DrawTerrainQuad(a, b, c, d, color, color, color, color, resolution, yOffset, p);
|
|
}
|
|
|
|
public void AddQuadFilledOnTerrain(Vector3 a, Vector3 b, Vector3 c, Vector3 d, uint colorA, uint colorB, uint colorC, uint colorD, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null)
|
|
{
|
|
AxDxParams p = dxParams ?? DefaultDxParams;
|
|
_renderer.DrawTerrainQuad(a, b, c, d, colorA, colorB, colorC, colorD, resolution, yOffset, p);
|
|
}
|
|
|
|
public void AddQuadFilledOnTerrain<T>(Vector3 a, Vector3 b, Vector3 c, Vector3 d, T gradient, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
AxDxParams p = dxParams ?? DefaultDxParams;
|
|
_renderer.DrawTerrainQuadGradient(a, b, c, d, gradient, resolution, yOffset, p);
|
|
}
|
|
|
|
public void AddCircleOnTerrain(Vector3 origin, float radius, uint color, uint numSegments = 0u, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null)
|
|
{
|
|
PathArcToOnTerrain(origin, radius, 0f, (float)Math.PI * 2f, yOffset, numSegments, resolution);
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd, AxLineCap.Butt, AxLineJoin.None, dxParams);
|
|
}
|
|
|
|
public void AddFanOnTerrain(Vector3 origin, float innerRadius, float outerRadius, float minAngle, float maxAngle, uint color, uint numSegments = 0u, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null)
|
|
{
|
|
bool flag = (double)(maxAngle - minAngle) >= 6.283184482025146;
|
|
PathArcToOnTerrain(origin, outerRadius, minAngle, maxAngle, yOffset, numSegments, resolution);
|
|
if (innerRadius > 0f)
|
|
{
|
|
if (flag)
|
|
{
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd, AxLineCap.Butt, AxLineJoin.None, dxParams);
|
|
}
|
|
PathArcToOnTerrain(origin, innerRadius, maxAngle, minAngle, yOffset, numSegments, resolution);
|
|
}
|
|
else if (!flag)
|
|
{
|
|
float terrainYRaw = AxTerrainQuery.GetTerrainYRaw(origin.X, origin.Z);
|
|
float y = (float.IsNaN(terrainYRaw) ? origin.Y : terrainYRaw) + yOffset;
|
|
PathLineTo(new Vector3(origin.X, y, origin.Z));
|
|
}
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd, AxLineCap.Butt, AxLineJoin.None, dxParams);
|
|
}
|
|
|
|
public void AddQuadOnTerrain(Vector3 a, Vector3 b, Vector3 c, Vector3 d, uint color, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null)
|
|
{
|
|
PathLineToOnTerrain(a, b, yOffset, resolution);
|
|
PathLineToOnTerrain(b, c, yOffset, resolution);
|
|
PathLineToOnTerrain(c, d, yOffset, resolution);
|
|
PathLineToOnTerrain(d, a, yOffset, resolution);
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd, AxLineCap.Butt, AxLineJoin.None, dxParams);
|
|
}
|
|
|
|
public void AddConeFilledOnTerrain(Vector3 origin, float radius, float rotation, float angle, uint color, uint? colorEnd = null, uint numSegments = 0u, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null)
|
|
{
|
|
float num = angle / 2f;
|
|
AddFanFilledOnTerrain(origin, 0f, radius, rotation - num, rotation + num, color, colorEnd, numSegments, resolution, yOffset, dxParams);
|
|
}
|
|
|
|
public void AddConeFilledOnTerrain<T>(Vector3 origin, float radius, float rotation, float angle, T gradient, uint numSegments = 0u, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
float num = angle / 2f;
|
|
AddFanFilledOnTerrain(origin, 0f, radius, rotation - num, rotation + num, gradient, numSegments, resolution, yOffset, dxParams);
|
|
}
|
|
|
|
public void AddConeOnTerrain(Vector3 origin, float radius, float rotation, float angle, uint color, uint numSegments = 0u, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null)
|
|
{
|
|
float num = angle / 2f;
|
|
AddFanOnTerrain(origin, 0f, radius, rotation - num, rotation + num, color, numSegments, thickness, dashLength, gapLength, dashOffset, colorEnd, resolution, yOffset, dxParams);
|
|
}
|
|
|
|
public void AddArcFilledOnTerrain(Vector3 origin, float radius, float minAngle, float maxAngle, uint color, uint? colorEnd = null, uint numSegments = 0u, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null)
|
|
{
|
|
AddFanFilledOnTerrain(origin, 0f, radius, minAngle, maxAngle, color, colorEnd, numSegments, resolution, yOffset, dxParams);
|
|
}
|
|
|
|
public void AddArcFilledOnTerrain<T>(Vector3 origin, float radius, float minAngle, float maxAngle, T gradient, uint numSegments = 0u, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
AddFanFilledOnTerrain(origin, 0f, radius, minAngle, maxAngle, gradient, numSegments, resolution, yOffset, dxParams);
|
|
}
|
|
|
|
public void AddArcOnTerrain(Vector3 origin, float radius, float minAngle, float maxAngle, uint color, uint numSegments = 0u, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null)
|
|
{
|
|
PathArcToOnTerrain(origin, radius, minAngle, maxAngle, yOffset, numSegments, resolution);
|
|
PathStroke(color, AxStrokeFlags.None, thickness, dashLength, gapLength, dashOffset, colorEnd, AxLineCap.Butt, AxLineJoin.None, dxParams);
|
|
}
|
|
|
|
public void AddLineFilledOnTerrain(Vector3 start, Vector3 stop, float halfWidth, uint color, uint? colorEnd = null, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null)
|
|
{
|
|
Vector3 vector = stop - start;
|
|
Vector3 vector2 = halfWidth * Vector3.Normalize(Vector3.Cross(vector, Vector3.UnitY));
|
|
AddQuadFilledOnTerrain(start - vector2, stop - vector2, stop + vector2, start + vector2, color, colorEnd ?? color, colorEnd ?? color, color, resolution, yOffset, dxParams);
|
|
}
|
|
|
|
public void AddLineFilledOnTerrain<T>(Vector3 start, Vector3 stop, float halfWidth, T gradient, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
Vector3 vector = stop - start;
|
|
Vector3 vector2 = halfWidth * Vector3.Normalize(Vector3.Cross(vector, Vector3.UnitY));
|
|
AddQuadFilledOnTerrain(start - vector2, stop - vector2, stop + vector2, start + vector2, gradient, resolution, yOffset, dxParams);
|
|
}
|
|
|
|
public void AddLineOnTerrain(Vector3 start, Vector3 stop, float halfWidth, uint color, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null)
|
|
{
|
|
Vector3 vector = stop - start;
|
|
Vector3 vector2 = halfWidth * Vector3.Normalize(Vector3.Cross(vector, Vector3.UnitY));
|
|
AddQuadOnTerrain(start - vector2, stop - vector2, stop + vector2, start + vector2, color, thickness, dashLength, gapLength, dashOffset, colorEnd, resolution, yOffset, dxParams);
|
|
}
|
|
|
|
public void AddPillFilledOnTerrain(Vector3 start, Vector3 stop, float halfWidth, uint color, uint numSegments = 0u, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null)
|
|
{
|
|
Vector3 vector = stop - start;
|
|
float num = vector.Length();
|
|
if (num < 1E-06f)
|
|
{
|
|
AddCircleFilledOnTerrain(start, halfWidth, color, null, numSegments * 2, resolution, yOffset, dxParams);
|
|
return;
|
|
}
|
|
Vector3 vector2 = vector / num;
|
|
Vector3 vector3 = Vector3.Normalize(Vector3.Cross(vector2, Vector3.UnitY));
|
|
float num2 = MathF.Atan2(0f - vector2.X, vector2.Z);
|
|
AddQuadFilledOnTerrain(start + vector3 * halfWidth, stop + vector3 * halfWidth, stop - vector3 * halfWidth, start - vector3 * halfWidth, color, resolution, yOffset, dxParams);
|
|
AddFanFilledOnTerrain(stop, 0f, halfWidth, num2 - (float)Math.PI / 2f, num2 + (float)Math.PI / 2f, color, null, numSegments, resolution, yOffset, dxParams);
|
|
AddFanFilledOnTerrain(start, 0f, halfWidth, num2 + (float)Math.PI / 2f, num2 + 4.712389f, color, null, numSegments, resolution, yOffset, dxParams);
|
|
}
|
|
|
|
public void AddPillFilledOnTerrain<T>(Vector3 start, Vector3 stop, float halfWidth, T gradient, uint numSegments = 0u, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
Vector3 vector = stop - start;
|
|
float num = vector.Length();
|
|
if (num < 1E-06f)
|
|
{
|
|
AddCircleFilledOnTerrain(start, halfWidth, gradient, numSegments * 2, resolution, yOffset, dxParams);
|
|
return;
|
|
}
|
|
Vector3 vector2 = vector / num;
|
|
Vector3 vector3 = Vector3.Normalize(Vector3.Cross(vector2, Vector3.UnitY));
|
|
float num2 = MathF.Atan2(0f - vector2.X, vector2.Z);
|
|
AddQuadFilledOnTerrain(start + vector3 * halfWidth, stop + vector3 * halfWidth, stop - vector3 * halfWidth, start - vector3 * halfWidth, gradient, resolution, yOffset, dxParams);
|
|
AddFanFilledOnTerrain(stop, 0f, halfWidth, num2 - (float)Math.PI / 2f, num2 + (float)Math.PI / 2f, gradient, numSegments, resolution, yOffset, dxParams);
|
|
AddFanFilledOnTerrain(start, 0f, halfWidth, num2 + (float)Math.PI / 2f, num2 + 4.712389f, gradient, numSegments, resolution, yOffset, dxParams);
|
|
}
|
|
|
|
public void AddPillOnTerrain(Vector3 start, Vector3 stop, float halfWidth, uint color, uint numSegments = 0u, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null)
|
|
{
|
|
Vector3 vector = stop - start;
|
|
float num = vector.Length();
|
|
if (num < 1E-06f)
|
|
{
|
|
AddCircleOnTerrain(start, halfWidth, color, numSegments * 2, thickness, dashLength, gapLength, dashOffset, colorEnd, resolution, yOffset, dxParams);
|
|
return;
|
|
}
|
|
Vector3 vector2 = Vector3.Normalize(Vector3.Cross(vector / num, Vector3.UnitY));
|
|
float num2 = MathF.Atan2(0f - vector2.X, vector2.Z);
|
|
PathLineToOnTerrain(start + vector2 * halfWidth, stop + vector2 * halfWidth, yOffset, resolution);
|
|
PathArcToOnTerrain(stop, halfWidth, num2, num2 - (float)Math.PI, yOffset, numSegments, resolution);
|
|
PathLineToOnTerrain(stop - vector2 * halfWidth, start - vector2 * halfWidth, yOffset, resolution);
|
|
PathArcToOnTerrain(start, halfWidth, num2 - (float)Math.PI, num2 - (float)Math.PI * 2f, yOffset, numSegments, resolution);
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd, AxLineCap.Butt, AxLineJoin.None, dxParams);
|
|
}
|
|
|
|
public void AddArrowFilledOnTerrain(Vector3 start, Vector3 stop, float halfWidth, uint color, float headLength = 0f, float headHalfWidth = 0f, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null)
|
|
{
|
|
Vector3 vector = stop - start;
|
|
float num = vector.Length();
|
|
if (!(num < 1E-06f))
|
|
{
|
|
if (headLength == 0f)
|
|
{
|
|
headLength = halfWidth * 3f;
|
|
}
|
|
if (headHalfWidth == 0f)
|
|
{
|
|
headHalfWidth = halfWidth * 2f;
|
|
}
|
|
Vector3 vector2 = vector / num;
|
|
Vector3 vector3 = Vector3.Normalize(Vector3.Cross(vector2, Vector3.UnitY));
|
|
if (num > headLength)
|
|
{
|
|
Vector3 vector4 = stop - vector2 * headLength;
|
|
AddQuadFilledOnTerrain(start - vector3 * halfWidth, vector4 - vector3 * halfWidth, vector4 + vector3 * halfWidth, start + vector3 * halfWidth, color, resolution, yOffset, dxParams);
|
|
AddQuadFilledOnTerrain(vector4 - vector3 * headHalfWidth, stop, stop, vector4 + vector3 * headHalfWidth, color, resolution, yOffset, dxParams);
|
|
}
|
|
else
|
|
{
|
|
AddQuadFilledOnTerrain(start - vector3 * headHalfWidth, stop, stop, start + vector3 * headHalfWidth, color, resolution, yOffset, dxParams);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void AddArrowFilledOnTerrain<T>(Vector3 start, Vector3 stop, float halfWidth, T gradient, float headLength = 0f, float headHalfWidth = 0f, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null) where T : IPctGradient
|
|
{
|
|
Vector3 vector = stop - start;
|
|
float num = vector.Length();
|
|
if (!(num < 1E-06f))
|
|
{
|
|
if (headLength == 0f)
|
|
{
|
|
headLength = halfWidth * 3f;
|
|
}
|
|
if (headHalfWidth == 0f)
|
|
{
|
|
headHalfWidth = halfWidth * 2f;
|
|
}
|
|
Vector3 vector2 = vector / num;
|
|
Vector3 vector3 = Vector3.Normalize(Vector3.Cross(vector2, Vector3.UnitY));
|
|
if (num > headLength)
|
|
{
|
|
Vector3 vector4 = stop - vector2 * headLength;
|
|
AddQuadFilledOnTerrain(start - vector3 * halfWidth, vector4 - vector3 * halfWidth, vector4 + vector3 * halfWidth, start + vector3 * halfWidth, gradient, resolution, yOffset, dxParams);
|
|
AddQuadFilledOnTerrain(vector4 - vector3 * headHalfWidth, stop, stop, vector4 + vector3 * headHalfWidth, gradient, resolution, yOffset, dxParams);
|
|
}
|
|
else
|
|
{
|
|
AddQuadFilledOnTerrain(start - vector3 * headHalfWidth, stop, stop, start + vector3 * headHalfWidth, gradient, resolution, yOffset, dxParams);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void AddArrowOnTerrain(Vector3 start, Vector3 stop, float halfWidth, uint color, float headLength = 0f, float headHalfWidth = 0f, float thickness = 2f, float dashLength = 0f, float gapLength = 0f, float dashOffset = 0f, uint? colorEnd = null, float resolution = 0.5f, float yOffset = 0.02f, AxDxParams? dxParams = null)
|
|
{
|
|
Vector3 vector = stop - start;
|
|
float num = vector.Length();
|
|
if (!(num < 1E-06f))
|
|
{
|
|
if (headLength == 0f)
|
|
{
|
|
headLength = halfWidth * 3f;
|
|
}
|
|
if (headHalfWidth == 0f)
|
|
{
|
|
headHalfWidth = halfWidth * 2f;
|
|
}
|
|
Vector3 vector2 = vector / num;
|
|
Vector3 vector3 = Vector3.Normalize(Vector3.Cross(vector2, Vector3.UnitY));
|
|
if (num > headLength)
|
|
{
|
|
Vector3 vector4 = stop - vector2 * headLength;
|
|
PathLineToOnTerrain(start + vector3 * halfWidth, vector4 + vector3 * halfWidth, yOffset, resolution);
|
|
PathLineToOnTerrain(vector4 + vector3 * halfWidth, vector4 + vector3 * headHalfWidth, yOffset, resolution);
|
|
PathLineToOnTerrain(vector4 + vector3 * headHalfWidth, stop, yOffset, resolution);
|
|
PathLineToOnTerrain(stop, vector4 - vector3 * headHalfWidth, yOffset, resolution);
|
|
PathLineToOnTerrain(vector4 - vector3 * headHalfWidth, vector4 - vector3 * halfWidth, yOffset, resolution);
|
|
PathLineToOnTerrain(vector4 - vector3 * halfWidth, start - vector3 * halfWidth, yOffset, resolution);
|
|
}
|
|
else
|
|
{
|
|
PathLineToOnTerrain(start + vector3 * headHalfWidth, stop, yOffset, resolution);
|
|
PathLineToOnTerrain(stop, start - vector3 * headHalfWidth, yOffset, resolution);
|
|
}
|
|
PathStroke(color, AxStrokeFlags.Closed, thickness, dashLength, gapLength, dashOffset, colorEnd, AxLineCap.Butt, AxLineJoin.None, dxParams);
|
|
}
|
|
}
|
|
|
|
private void PathArcToOnTerrain(Vector3 origin, float radius, float startAngle, float stopAngle, float yOffset, uint numSegments, float resolution)
|
|
{
|
|
float num = stopAngle - startAngle;
|
|
if (num != 0f)
|
|
{
|
|
if (numSegments == 0)
|
|
{
|
|
numSegments = (uint)MathF.Max(1f, MathF.Ceiling(MathF.Abs(num) * radius / resolution));
|
|
}
|
|
float num2 = num / (float)numSegments;
|
|
for (int i = 0; i <= numSegments; i++)
|
|
{
|
|
float num3 = (float)Math.PI / 2f + startAngle + (float)i * num2;
|
|
float x = origin.X + MathF.Cos(num3) * radius;
|
|
float z = origin.Z + MathF.Sin(num3) * radius;
|
|
float terrainYRaw = AxTerrainQuery.GetTerrainYRaw(x, z);
|
|
float y = (float.IsNaN(terrainYRaw) ? origin.Y : terrainYRaw) + yOffset;
|
|
_path.Add(new Vector3(x, y, z));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void PathLineToOnTerrain(Vector3 start, Vector3 end, float yOffset, float resolution)
|
|
{
|
|
float num = Vector3.Distance(start, end);
|
|
int num2 = Math.Max(1, (int)MathF.Ceiling(num / resolution));
|
|
for (int i = 0; i < num2; i++)
|
|
{
|
|
float num3 = (float)i / (float)num2;
|
|
float x = start.X + (end.X - start.X) * num3;
|
|
float z = start.Z + (end.Z - start.Z) * num3;
|
|
float terrainYRaw = AxTerrainQuery.GetTerrainYRaw(x, z);
|
|
float num4 = start.Y + (end.Y - start.Y) * num3;
|
|
float y = (float.IsNaN(terrainYRaw) ? num4 : terrainYRaw) + yOffset;
|
|
_path.Add(new Vector3(x, y, z));
|
|
}
|
|
}
|
|
}
|