XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Numerics;
using System.Runtime.InteropServices;
using XFEEDToolBox.Core.Galaxy;
using XFEEDToolBox.Core.Models;

namespace XFEEDToolBox.Core.Rendering;

[StructLayout(LayoutKind.Sequential)]
public readonly record struct GalaxyOriginalPowerActivityBillboard(Vector4 Position,Vector4 UAxisExtent,Vector4 VAxisExtent,Vector4 Colour);

public static class GalaxyOriginalPowerActivityBillboardGeometry
{
    public const int VertexCount=4;
    public const float AllocationMultiplier=2.222222328186035f;
    public static bool TryCreate(GalaxyNativePowerOuter? source,Coordinates eye,out GalaxyOriginalPowerActivityBillboard billboard)
    {
        billboard=default;
        if(source is not{CentreSystemAddress:>0,CentrePosition:{} centre,Extent:>0 and <=1000000}||!centre.IsValid||!eye.IsValid)return false;
        var normal=new Vector3((float)(eye.X-centre.X),(float)(eye.Y-centre.Y),(float)(eye.Z-centre.Z));
        var distance=normal.Length();var extent=source.Extent.Value;
        if(!float.IsFinite(distance)||distance<=extent)return false;
        var allocation=extent*(distance/MathF.Sqrt(distance*distance-extent*extent))*AllocationMultiplier;
        if(!float.IsFinite(allocation)||allocation<=0)return false;
        normal/=distance;var absolute=Vector3.Abs(normal);Vector3 u;
        // Exact3B064F0 largest-axis branches, including tie direction.
        if(absolute.Y>absolute.X&&absolute.Z<=absolute.Y)u=new(normal.Y,-normal.X,0);
        else if(absolute.X>=absolute.Z&&absolute.Y<=absolute.X)u=new(-normal.Z,0,normal.X);
        else u=new(0,normal.Z,-normal.Y);
        u=Vector3.Normalize(u);var v=Vector3.Cross(u,normal);
        billboard=new(new((float)centre.X,(float)centre.Y,(float)centre.Z,1),new(u,allocation),new(v,allocation),
            new(BitConverter.Int32BitsToSingle(0x3CDD2F1B),BitConverter.Int32BitsToSingle(0x3F716873),1,0));
        return IsValid(billboard);
    }
    public static bool IsValid(GalaxyOriginalPowerActivityBillboard value)=>Finite(value.Position)&&Finite(value.UAxisExtent)&&
        Finite(value.VAxisExtent)&&Finite(value.Colour)&&value.UAxisExtent.W>0&&value.VAxisExtent.W>0;
    private static bool Finite(Vector4 value)=>float.IsFinite(value.X)&&float.IsFinite(value.Y)&&float.IsFinite(value.Z)&&float.IsFinite(value.W);
    public static Vector3 Vertex(GalaxyOriginalPowerActivityBillboard value,int vertex)
    {
        if(!IsValid(value)||vertex is <0 or >=VertexCount)throw new ArgumentOutOfRangeException(nameof(vertex));
        var u=((vertex&2)!=0?1:-1)*value.UAxisExtent.W*.5f;var v=((vertex&1)!=0?1:-1)*value.VAxisExtent.W*.5f;
        return new Vector3(value.Position.X,value.Position.Y,value.Position.Z)+new Vector3(value.UAxisExtent.X,value.UAxisExtent.Y,value.UAxisExtent.Z)*u+
            new Vector3(value.VAxisExtent.X,value.VAxisExtent.Y,value.VAxisExtent.Z)*v;
    }
}