Refactor to use System.Numerics structs rather than my own.

Removes Vector2d, Vector3d, Vector4d, Plane and Ray.
Implement a standard API for .NET, Unity and Godot through extension methods.
In general, use floats rather than doubles for things.
This commit is contained in:
wfowler
2019-10-10 02:47:42 -06:00
parent a388f58073
commit 48366f4f52
35 changed files with 1141 additions and 2559 deletions

View File

@@ -9,8 +9,9 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>LibBSP</RootNamespace>
<AssemblyName>libBSP</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -36,6 +37,7 @@
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Numerics" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
@@ -49,9 +51,9 @@
<Compile Include="Source\Extensions\CustomAttributeExtensions.cs" />
<Compile Include="Source\Extensions\PlaneExtensions.cs" />
<Compile Include="Source\Extensions\StringExtensions.cs" />
<Compile Include="Source\Extensions\Vector2dExtensions.cs" />
<Compile Include="Source\Extensions\Vector3dExtensions.cs" />
<Compile Include="Source\Extensions\Vector4dExtensions.cs" />
<Compile Include="Source\Extensions\Vector2Extensions.cs" />
<Compile Include="Source\Extensions\Vector3Extensions.cs" />
<Compile Include="Source\Extensions\Vector4Extensions.cs" />
<Compile Include="Source\Extensions\VertexExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Source\Structs\BSP\Brush.cs" />
@@ -86,12 +88,7 @@
<Compile Include="Source\Structs\MAP\MAPBrushSide.cs" />
<Compile Include="Source\Structs\MAP\MAPDisplacement.cs" />
<Compile Include="Source\Structs\MAP\MAPPatch.cs" />
<Compile Include="Source\Structs\Common\Plane.cs" />
<Compile Include="Source\Structs\Common\Ray.cs" />
<Compile Include="Source\Structs\Common\Vertex.cs" />
<Compile Include="Source\Structs\Common\Vector2d.cs" />
<Compile Include="Source\Structs\Common\Vector4d.cs" />
<Compile Include="Source\Structs\Common\Vector3d.cs" />
<Compile Include="Source\Structs\MAP\MAPTerrainEF2.cs" />
<Compile Include="Source\Structs\MAP\MAPTerrainMoHAA.cs" />
<Compile Include="Source\Util\BSPReader.cs" />

View File

@@ -60,5 +60,65 @@ namespace LibBSP {
return bytes;
}
/// <summary>
/// Gets the alpha component of this <see cref="Color"/>.
/// </summary>
/// <param name="color">This <see cref="Color"/>.</param>
/// <returns>The alpha component of this <see cref="Color"/>.</returns>
public static byte A(this Color color) {
#if UNITY
return color.a;
#elif GODOT
return (byte)color.a8;
#else
return color.A;
#endif
}
/// <summary>
/// Gets the red component of this <see cref="Color"/>.
/// </summary>
/// <param name="color">This <see cref="Color"/>.</param>
/// <returns>The red component of this <see cref="Color"/>.</returns>
public static byte R(this Color color) {
#if UNITY
return color.r;
#elif GODOT
return (byte)color.r8;
#else
return color.R;
#endif
}
/// <summary>
/// Gets the green component of this <see cref="Color"/>.
/// </summary>
/// <param name="color">This <see cref="Color"/>.</param>
/// <returns>The green component of this <see cref="Color"/>.</returns>
public static byte G(this Color color) {
#if UNITY
return color.g;
#elif GODOT
return (byte)color.g8;
#else
return color.G;
#endif
}
/// <summary>
/// Gets the blue component of this <see cref="Color"/>.
/// </summary>
/// <param name="color">This <see cref="Color"/>.</param>
/// <returns>The blue component of this <see cref="Color"/>.</returns>
public static byte B(this Color color) {
#if UNITY
return color.b;
#elif GODOT
return (byte)color.b8;
#else
return color.B;
#endif
}
}
}

View File

@@ -3,16 +3,18 @@
#endif
using System;
using System.Collections.Generic;
namespace LibBSP {
#if UNITY
using Plane = UnityEngine.Plane;
using Vector3d = UnityEngine.Vector3;
using Vector3 = UnityEngine.Vector3;
using Ray = UnityEngine.Ray;
#elif GODOT
using Plane = Godot.Plane;
using Vector3d = Godot.Vector3;
using Vector3 = Godot.Vector3;
#else
using Plane = System.Numerics.Plane;
using Vector3 = System.Numerics.Vector3;
#endif
/// <summary>
@@ -23,309 +25,240 @@ namespace LibBSP {
/// <summary>
/// Array of base texture axes. When referenced properly, provides a good default texture axis for any given plane.
/// </summary>
public static readonly Vector3d[] baseAxes = new Vector3d[] {
new Vector3d(0, 0, 1), new Vector3d(1, 0, 0), new Vector3d(0, -1, 0),
new Vector3d(0, 0, -1), new Vector3d(1, 0, 0), new Vector3d(0, -1, 0),
new Vector3d(1, 0, 0), new Vector3d(0, 1, 0), new Vector3d(0, 0, -1),
new Vector3d(-1, 0, 0), new Vector3d(0, 1, 0), new Vector3d(0, 0, -1),
new Vector3d(0, 1, 0), new Vector3d(1, 0, 0), new Vector3d(0, 0, -1),
new Vector3d(0, -1, 0), new Vector3d(1, 0, 0), new Vector3d(0, 0, -1)
public static readonly Vector3[] baseAxes = new Vector3[] {
new Vector3(0, 0, 1), new Vector3(1, 0, 0), new Vector3(0, -1, 0),
new Vector3(0, 0, -1), new Vector3(1, 0, 0), new Vector3(0, -1, 0),
new Vector3(1, 0, 0), new Vector3(0, 1, 0), new Vector3(0, 0, -1),
new Vector3(-1, 0, 0), new Vector3(0, 1, 0), new Vector3(0, 0, -1),
new Vector3(0, 1, 0), new Vector3(1, 0, 0), new Vector3(0, 0, -1),
new Vector3(0, -1, 0), new Vector3(1, 0, 0), new Vector3(0, 0, -1)
};
/// <summary>
/// Gets the normal of this <see cref="Plane"/>.
/// </summary>
/// <param name="p">This <see cref="Plane"/>.</param>
/// <param name="plane">This <see cref="Plane"/>.</param>
/// <returns>The normal of this <see cref="Plane"/>.</returns>
public static Vector3d GetNormal(this Plane p) {
#if GODOT
return p.Normal;
public static Vector3 Normal(this Plane plane) {
#if UNITY
return plane.normal;
#else
return p.normal;
return plane.Normal;
#endif
}
/// <summary>
/// Gets the distance of this <see cref="Plane"/> from the origin.
/// </summary>
/// <param name="p">This <see cref="Plane"/>.</param>
/// <param name="plane">This <see cref="Plane"/>.</param>
/// <returns>The distance of this <see cref="Plane"/> from the origin.</returns>
public static double GetDistance(this Plane p) {
#if GODOT
return p.D;
#else
return p.distance;
#endif
}
/// <summary>
/// Intersects three <see cref="Plane"/>s at a <see cref="Vector3d"/>. Returns NaN for all components if two or more <see cref="Plane"/>s are parallel.
/// </summary>
/// <param name="p1"><see cref="Plane"/> to intersect.</param>
/// <param name="p2"><see cref="Plane"/> to intersect.</param>
/// <param name="p3"><see cref="Plane"/> to intersect.</param>
/// <returns>Point of intersection if all three <see cref="Plane"/>s meet at a point, (NaN, NaN, NaN) otherwise.</returns>
public static Vector3d Intersection(Plane p1, Plane p2, Plane p3) {
#if GODOT
return p1.Intersect3(p2, p3);
#else
Vector3d aN = p1.GetNormal();
Vector3d bN = p2.GetNormal();
Vector3d cN = p3.GetNormal();
var p1d = p1.distance;
var p2d = p2.distance;
var p3d = p3.distance;
var partSolx1 = (bN.y * cN.z) - (bN.z * cN.y);
var partSoly1 = (bN.z * cN.x) - (bN.x * cN.z);
var partSolz1 = (bN.x * cN.y) - (bN.y * cN.x);
var det = (aN.x * partSolx1) + (aN.y * partSoly1) + (aN.z * partSolz1);
if (det == 0) {
return new Vector3d(float.NaN, float.NaN, float.NaN);
}
return new Vector3d((p1d * partSolx1 + p2d * (cN.y * aN.z - cN.z * aN.y) + p3d * (aN.y * bN.z - aN.z * bN.y)) / det,
(p1d * partSoly1 + p2d * (aN.x * cN.z - aN.z * cN.x) + p3d * (bN.x * aN.z - bN.z * aN.x)) / det,
(p1d * partSolz1 + p2d * (cN.x * aN.y - cN.y * aN.x) + p3d * (aN.x * bN.y - aN.y * bN.x)) / det);
#endif
}
/// <summary>
/// Intersects this <see cref="Plane"/> with two other <see cref="Plane"/>s at a <see cref="Vector3d"/>. Returns NaN for all components if two or more <see cref="Plane"/>s are parallel.
/// </summary>
/// <param name="p1">This <see cref="Plane"/>.</param>
/// <param name="p2"><see cref="Plane"/> to intersect.</param>
/// <param name="p3"><see cref="Plane"/> to intersect.</param>
/// <returns>Point of intersection if all three <see cref="Plane"/>s meet at a point, (NaN, NaN, NaN) otherwise.</returns>
public static Vector3d Intersect(this Plane p1, Plane p2, Plane p3) {
#if GODOT
return p1.Intersect3(p2, p3);
#else
return Intersection(p1, p2, p3);
#endif
}
/// <summary>
/// Intersects a <see cref="Plane"/> "<paramref name="p"/>" with a <see cref="Ray"/> "<paramref name="r"/>" at a <see cref="Vector3d"/>. Returns NaN for all components if they do not intersect.
/// </summary>
/// <param name="p"><see cref="Plane"/> to intersect with.</param>
/// <param name="r"><see cref="Ray"/> to intersect.</param>
/// <returns>Point of intersection if "<paramref name="r"/>" intersects "<paramref name="p"/>", (NaN, NaN, NaN) otherwise.</returns>
public static Vector3d Intersection(Plane p, Ray r) {
public static float Distance(this Plane plane) {
#if UNITY
float enter;
return plane.distance;
#else
double enter;
return plane.D;
#endif
bool intersected = p.Raycast(r, out enter);
}
/// <summary>
/// Intersects three <see cref="Plane"/>s at a <see cref="Vector3"/>. Returns <see cref="float.NaN"/> for all components if two or more <see cref="Plane"/>s are parallel.
/// </summary>
/// <param name="plane1">First <see cref="Plane"/> to intersect.</param>
/// <param name="plane2">Second <see cref="Plane"/> to intersect.</param>
/// <param name="plane3">Third <see cref="Plane"/> to intersect.</param>
/// <returns>Point of intersection if all three <see cref="Plane"/>s meet at a point, (NaN, NaN, NaN) otherwise.</returns>
public static Vector3 Intersect3(Plane plane1, Plane plane2, Plane plane3) {
float denominator = plane1.Normal().Cross(plane2.Normal()).Dot(plane3.Normal());
if (denominator == 0) {
return new Vector3(float.NaN, float.NaN, float.NaN);
}
return (plane2.Normal().Cross(plane3.Normal()) * plane1.Distance() +
plane3.Normal().Cross(plane1.Normal()) * plane2.Distance() +
plane1.Normal().Cross(plane2.Normal()) * plane3.Distance()) / denominator;
}
/// <summary>
/// Intersects a <see cref="Plane"/> "<paramref name="plane"/>" with a ray at a <see cref="Vector3"/>. Returns NaN for all components if they do not intersect.
/// </summary>
/// <param name="plane">This <see cref="Plane"/>.</param>
/// <param name="origin">The origin point of the ray.</param>
/// <param name="direction">The direction of the ray.</param>
/// <returns>Point of intersection if the ray intersects "<paramref name="p"/>", (NaN, NaN, NaN) otherwise.</returns>
public static Vector3 Intersection(this Plane plane, Vector3 origin, Vector3 direction) {
float enter;
direction = direction.GetNormalized();
bool intersected = plane.Raycast(origin, direction, out enter);
if (intersected || enter != 0) {
return r.GetPoint(enter);
return origin + (enter * direction);
} else {
return new Vector3d(float.NaN, float.NaN, float.NaN);
return new Vector3(float.NaN, float.NaN, float.NaN);
}
}
#if GODOT
/// <summary>
/// Raycasts a <see cref="Ray"/> against this <see cref="Plane"/>.
/// </summary>
/// <param name="ray"><see cref="Ray"/> to raycast against.</param>
/// <param name="plane">This <see cref="Plane"/>.</param>
/// <param name="origin">The origin point of the ray.</param>
/// <param name="direction">The direction of the ray.</param>
/// <param name="enter"><c>out</c> parameter that will contain the distance along <paramref name="ray"/> where the collision happened.</param>
/// <returns>
/// <c>true</c> and <paramref name="enter"/> is positive if <see cref="Ray"/> intersects this <see cref="Plane"/> in front of the ray,
/// <c>false</c> and <paramref name="enter"/> is negative if <see cref="Ray"/> intersects this <see cref="Plane"/> behind the ray,
/// <c>false</c> and <paramref name="enter"/> is 0 if the <see cref="Ray"/> is parallel to this <see cref="Plane"/>.
/// <c>true</c> and <paramref name="enter"/> is positive or 0 if the ray intersects this <see cref="Plane"/> in front of the ray,
/// <c>false</c> and <paramref name="enter"/> is negative if the ray intersects this <see cref="Plane"/> behind the ray,
/// <c>false</c> and <paramref name="enter"/> is 0 if the ray is parallel to this <see cref="Plane"/>.
/// </returns>
public static bool Raycast(this Plane p, Ray ray, out double enter) {
double denom = ray.direction.Dot(p.Normal);
public static bool Raycast(this Plane plane, Vector3 origin, Vector3 direction, out float enter) {
#if UNITY
return plane.Raycast(new Ray(origin, direction), out enter);
#else
direction = direction.GetNormalized();
float denom = direction.Dot(plane.Normal());
if (denom > -0.005 && denom < 0.005) {
enter = 0;
return false;
}
enter = (-1 * ray.origin.Dot(p.Normal) + p.D) / denom;
enter = (-origin.Dot(plane.Normal()) - plane.Distance()) / denom;
if (float.IsNaN(enter)) {
enter = 0;
return false;
}
return enter > 0;
}
#endif
/// <summary>
/// Intersects this <see cref="Plane"/> with a <see cref="Ray"/> "<paramref name="r"/>" at a <see cref="Vector3d"/>. Returns NaN for all components if they do not intersect.
/// </summary>
/// <param name="p">This <see cref="Plane"/>.</param>
/// <param name="r"><see cref="Ray"/> to intersect.</param>
/// <returns>Point of intersection if "<paramref name="r"/>" intersects this <see cref="Plane"/>, (NaN, NaN, NaN) otherwise.</returns>
public static Vector3d Intersect(this Plane p, Ray r) {
return Intersection(p, r);
}
/// <summary>
/// Intersects a <see cref="Plane"/> "<paramref name="p"/>" with this <see cref="Ray"/> at a <see cref="Vector3d"/>. Returns NaN for all components if they do not intersect.
/// </summary>
/// <param name="r">This <see cref="Ray"/>.</param>
/// <param name="p"><see cref="Plane"/> to intersect with.</param>
/// <returns>Point of intersection if this <see cref="Ray"/> intersects "<paramref name="p"/>", (NaN, NaN, NaN) otherwise.</returns>
public static Vector3d Intersect(this Ray r, Plane p) {
return Intersection(p, r);
}
/// <summary>
/// Intersects two <see cref="Plane"/>s at a <see cref="Ray"/>. Returns NaN for all components of both <see cref="Vector3d"/>s of the <see cref="Ray"/> if the <see cref="Plane"/>s are parallel.
/// </summary>
/// <param name="p1"><see cref="Plane"/> to intersect.</param>
/// <param name="p2"><see cref="Plane"/> to intersect.</param>
/// <returns>Line of intersection where "<paramref name="p1"/>" intersects "<paramref name="p2"/>", ((NaN, NaN, NaN) + p(NaN, NaN, NaN)) otherwise.</returns>
public static Ray Intersection(Plane p1, Plane p2) {
Vector3d direction = p1.GetNormal().Cross(p2.GetNormal());
if (direction == new Vector3d(0, 0, 0)) {
return new Ray(new Vector3d(float.NaN, float.NaN, float.NaN), new Vector3d(float.NaN, float.NaN, float.NaN));
}
// If x == 0, solve for y in terms of z, or z in terms of y
Vector3d origin;
Vector3d sqrDirection = new Vector3d(direction.x * direction.x, direction.y * direction.y, direction.z * direction.z);
if (sqrDirection.x >= sqrDirection.y && sqrDirection.x >= sqrDirection.z) {
var denom = (p1.GetNormal().y * p2.GetNormal().z) - (p2.GetNormal().y * p1.GetNormal().z);
origin = new Vector3d(0,
((p1.GetNormal().z * (float)p2.GetDistance()) - (p2.GetNormal().z * (float)p1.GetDistance())) / denom,
((p2.GetNormal().y * (float)p1.GetDistance()) - (p1.GetNormal().y * (float)p2.GetDistance())) / denom);
} else if (sqrDirection.y >= sqrDirection.x && sqrDirection.y >= sqrDirection.z) {
var denom = (p1.GetNormal().x * p2.GetNormal().z) - (p2.GetNormal().x * p1.GetNormal().z);
origin = new Vector3d(((p1.GetNormal().z * (float)p2.GetDistance()) - (p2.GetNormal().z * (float)p1.GetDistance())) / denom,
0,
((p2.GetNormal().x * (float)p1.GetDistance()) - (p1.GetNormal().x * (float)p2.GetDistance())) / denom);
} else {
var denom = (p1.GetNormal().x * p2.GetNormal().y) - (p2.GetNormal().x * p1.GetNormal().y);
origin = new Vector3d(((p1.GetNormal().y * (float)p2.GetDistance()) - (p2.GetNormal().y * (float)p1.GetDistance())) / denom,
((p2.GetNormal().x * (float)p1.GetDistance()) - (p1.GetNormal().x * (float)p2.GetDistance())) / denom,
0);
}
return new Ray(origin, direction);
}
/// <summary>
/// Intersects this <see cref="Plane"/> with another <see cref="Plane"/> at a <see cref="Ray"/>. Returns NaN for all components of both <see cref="Vector3d"/>s of the <see cref="Ray"/> if the <see cref="Plane"/>s are parallel.
/// </summary>
/// <param name="p1">This <see cref="Plane"/>.</param>
/// <param name="p2"><see cref="Plane"/> to intersect.</param>
/// <returns>Line of intersection where this <see cref="Plane"/> intersects "<paramref name="p2"/>", ((NaN, NaN, NaN) + p(NaN, NaN, NaN)) otherwise.</returns>
public static Ray Intersect(this Plane p1, Plane p2) {
return Intersection(p1, p2);
}
/// <summary>
/// Generates three points which can be used to define this <see cref="Plane"/>.
/// </summary>
/// <param name="p">This <see cref="Plane"/>.</param>
/// <param name="plane">This <see cref="Plane"/>.</param>
/// <param name="scalar">Scale of distance between the generated points. The points will define the same <see cref="Plane"/> but will be farther apart the larger this value is. Must not be zero.</param>
/// <returns>Three points which define this <see cref="Plane"/>.</returns>
public static Vector3d[] GenerateThreePoints(this Plane p, float scalar = 16) {
Vector3d[] points = new Vector3d[3];
public static Vector3[] GenerateThreePoints(this Plane plane, float scalar = 16) {
Vector3[] points = new Vector3[3];
// Figure out if the plane is parallel to two of the axes.
if (p.GetNormal().y == 0 && p.GetNormal().z == 0) {
if (plane.Normal().Y() == 0 && plane.Normal().Z() == 0) {
// parallel to plane YZ
points[0] = new Vector3d((float)p.GetDistance() / p.GetNormal().x, -scalar, scalar);
points[1] = new Vector3d((float)p.GetDistance() / p.GetNormal().x, 0, 0);
points[2] = new Vector3d((float)p.GetDistance() / p.GetNormal().x, scalar, scalar);
if (p.GetNormal().x > 0) {
points[0] = new Vector3(plane.Distance() / plane.Normal().X(), -scalar, scalar);
points[1] = new Vector3(plane.Distance() / plane.Normal().X(), 0, 0);
points[2] = new Vector3(plane.Distance() / plane.Normal().X(), scalar, scalar);
if (plane.Normal().X() > 0) {
Array.Reverse(points);
}
} else if (p.GetNormal().x == 0 && p.GetNormal().z == 0) {
} else if (plane.Normal().X() == 0 && plane.Normal().Z() == 0) {
// parallel to plane XZ
points[0] = new Vector3d(scalar, (float)p.GetDistance() / p.GetNormal().y, -scalar);
points[1] = new Vector3d(0, (float)p.GetDistance() / p.GetNormal().y, 0);
points[2] = new Vector3d(scalar, (float)p.GetDistance() / p.GetNormal().y, scalar);
if (p.GetNormal().y > 0) {
points[0] = new Vector3(scalar, plane.Distance() / plane.Normal().Y(), -scalar);
points[1] = new Vector3(0, plane.Distance() / plane.Normal().Y(), 0);
points[2] = new Vector3(scalar, plane.Distance() / plane.Normal().Y(), scalar);
if (plane.Normal().Y() > 0) {
Array.Reverse(points);
}
} else if (p.GetNormal().x == 0 && p.GetNormal().y == 0) {
} else if (plane.Normal().X() == 0 && plane.Normal().Y() == 0) {
// parallel to plane XY
points[0] = new Vector3d(-scalar, scalar, (float)p.GetDistance() / p.GetNormal().z);
points[1] = new Vector3d(0, 0, (float)p.GetDistance() / p.GetNormal().z);
points[2] = new Vector3d(scalar, scalar, (float)p.GetDistance() / p.GetNormal().z);
if (p.GetNormal().z > 0) {
points[0] = new Vector3(-scalar, scalar, plane.Distance() / plane.Normal().Z());
points[1] = new Vector3(0, 0, plane.Distance() / plane.Normal().Z());
points[2] = new Vector3(scalar, scalar, plane.Distance() / plane.Normal().Z());
if (plane.Normal().Z() > 0) {
Array.Reverse(points);
}
} else if (p.GetNormal().x == 0) {
} else if (plane.Normal().X() == 0) {
// If you reach this point the plane is not parallel to any two-axis plane.
// parallel to X axis
points[0] = new Vector3d(-scalar, scalar * scalar, (-(scalar * scalar * p.GetNormal().y - (float)p.GetDistance())) / p.GetNormal().z);
points[1] = new Vector3d(0, 0, (float)p.GetDistance() / p.GetNormal().z);
points[2] = new Vector3d(scalar, scalar * scalar, (-(scalar * scalar * p.GetNormal().y - (float)p.GetDistance())) / p.GetNormal().z);
if (p.GetNormal().z > 0) {
points[0] = new Vector3(-scalar, scalar * scalar, (-(scalar * scalar * plane.Normal().Y() - plane.Distance())) / plane.Normal().Z());
points[1] = new Vector3(0, 0, plane.Distance() / plane.Normal().Z());
points[2] = new Vector3(scalar, scalar * scalar, (-(scalar * scalar * plane.Normal().Y() - plane.Distance())) / plane.Normal().Z());
if (plane.Normal().Z() > 0) {
Array.Reverse(points);
}
} else if (p.GetNormal().y == 0) {
} else if (plane.Normal().Y() == 0) {
// parallel to Y axis
points[0] = new Vector3d((-(scalar * scalar * p.GetNormal().z - (float)p.GetDistance())) / p.GetNormal().x, -scalar, scalar * scalar);
points[1] = new Vector3d((float)p.GetDistance() / p.GetNormal().x, 0, 0);
points[2] = new Vector3d((-(scalar * scalar * p.GetNormal().z - (float)p.GetDistance())) / p.GetNormal().x, scalar, scalar * scalar);
if (p.GetNormal().x > 0) {
points[0] = new Vector3((-(scalar * scalar * plane.Normal().Z() - plane.Distance())) / plane.Normal().X(), -scalar, scalar * scalar);
points[1] = new Vector3(plane.Distance() / plane.Normal().X(), 0, 0);
points[2] = new Vector3((-(scalar * scalar * plane.Normal().Z() - plane.Distance())) / plane.Normal().X(), scalar, scalar * scalar);
if (plane.Normal().X() > 0) {
Array.Reverse(points);
}
} else if (p.GetNormal().z == 0) {
} else if (plane.Normal().Z() == 0) {
// parallel to Z axis
points[0] = new Vector3d(scalar * scalar, (-(scalar * scalar * p.GetNormal().x - (float)p.GetDistance())) / p.GetNormal().y, -scalar);
points[1] = new Vector3d(0, (float)p.GetDistance() / p.GetNormal().y, 0);
points[2] = new Vector3d(scalar * scalar, (-(scalar * scalar * p.GetNormal().x - (float)p.GetDistance())) / p.GetNormal().y, scalar);
if (p.GetNormal().y > 0) {
points[0] = new Vector3(scalar * scalar, (-(scalar * scalar * plane.Normal().X() - plane.Distance())) / plane.Normal().Y(), -scalar);
points[1] = new Vector3(0, plane.Distance() / plane.Normal().Y(), 0);
points[2] = new Vector3(scalar * scalar, (-(scalar * scalar * plane.Normal().X() - plane.Distance())) / plane.Normal().Y(), scalar);
if (plane.Normal().Y() > 0) {
Array.Reverse(points);
}
} else {
// If you reach this point the plane is not parallel to any axis. Therefore, any two coordinates will give a third.
points[0] = new Vector3d(-scalar, scalar * scalar, -(-scalar * p.GetNormal().x + scalar * scalar * p.GetNormal().y - (float)p.GetDistance()) / p.GetNormal().z);
points[1] = new Vector3d(0, 0, (float)p.GetDistance() / p.GetNormal().z);
points[2] = new Vector3d(scalar, scalar * scalar, -(scalar * p.GetNormal().x + scalar * scalar * p.GetNormal().y - (float)p.GetDistance()) / p.GetNormal().z);
if (p.GetNormal().z > 0) {
points[0] = new Vector3(-scalar, scalar * scalar, -(-scalar * plane.Normal().X() + scalar * scalar * plane.Normal().Y() - plane.Distance()) / plane.Normal().Z());
points[1] = new Vector3(0, 0, plane.Distance() / plane.Normal().Z());
points[2] = new Vector3(scalar, scalar * scalar, -(scalar * plane.Normal().X() + scalar * scalar * plane.Normal().Y() - plane.Distance()) / plane.Normal().Z());
if (plane.Normal().Z() > 0) {
Array.Reverse(points);
}
}
return points;
}
#if !UNITY
/// <summary>
/// Gets the signed distance from this <see cref="Plane"/> to a given point.
/// </summary>
/// <param name="p">This <see cref="Plane"/>.</param>
/// <param name="to">Point to get the distance to.</param>
/// <param name="plane">This <see cref="Plane"/>.</param>
/// <param name="point">Point to get the distance to.</param>
/// <returns>Signed distance from this <see cref="Plane"/> to the given point.</returns>
/// <remarks>Unity uses the plane equation "Ax + By + Cz + D = 0" while Quake-based engines
/// use "Ax + By + Cz = D". The distance equation needs to be evaluated differently from
/// Unity's default implementation to properly apply to planes read from BSPs.</remarks>
#if UNITY || GODOT
public static float GetBSPDistanceToPoint(this Plane p, Vector3d to) {
return (p.GetNormal().x * to.x + p.GetNormal().y * to.y + p.GetNormal().z * to.z - (float)p.GetDistance()) / (float)p.GetNormal().GetMagnitude();
}
public static float GetDistanceToPoint(this Plane plane, Vector3 point) {
#if GODOT
return plane.Normal.Dot(point) + plane.D;
#else
public static double GetBSPDistanceToPoint(this Plane p, Vector3d to) {
return p.GetDistanceToPoint(to);
return Plane.DotCoordinate(plane, point);
#endif
}
/// <summary>
/// Is <paramref name="vector"/> on the positive side of this <see cref="Plane"/>?
/// </summary>
/// <param name="plane">This <see cref="Plane"/>.</param>
/// <param name="vector">Point to get the side for.</param>
/// <returns><c>true</c> if <paramref name="vector"/> is on the positive side of this <see cref="Plane"/>.</returns>
public static bool GetSide(this Plane plane, Vector3 vector) {
return plane.GetDistanceToPoint(vector) > 0;
}
#endif
#if !GODOT
/// <summary>
/// Determines whether <paramref name="point"/> lies on this <see cref="Plane"/>.
/// </summary>
/// <param name="plane">This <see cref="Plane"/>.</param>
/// <param name="point">The point to determine whether or not it lies on the plane.</param>
/// <returns><c>true</c> if <paramref name="point"/> lies on this <see cref="Plane"/>.</returns>
public static bool HasPoint(this Plane plane, Vector3 point, float epsilon = 0.00001f) {
float distanceTo = plane.GetDistanceToPoint(point);
return distanceTo < epsilon && distanceTo > -epsilon;
}
#endif
/// <summary>
/// Is <paramref name="v"/> on the positive side of this <see cref="Plane"/>?
/// Creates a <see cref="Plane"/> object that contains three specified points.
/// </summary>
/// <param name="p">This <see cref="Plane"/>.</param>
/// <param name="v">Point to get the side for.</param>
/// <returns><c>true</c> if <paramref name="v"/> is on the positive side of this <see cref="Plane"/>.</returns>
/// <remarks>Unity uses the plane equation "Ax + By + Cz + D = 0" while Quake-based engines
/// use "Ax + By + Cz = D". The distance equation needs to be evaluated differently from
/// Unity's default implementation to properly apply to planes read from BSPs.</remarks>
public static bool GetBSPSide(this Plane p, Vector3d v) {
return p.GetBSPDistanceToPoint(v) > 0;
}
/// <summary>
/// Determines whether the given <see cref="Vector3d"/> is contained in this <see cref="Plane"/>.
/// </summary>
/// <param name="v">Point.</param>
/// <returns><c>true</c> if the <see cref="Vector3d"/> is contained in this <see cref="Plane"/>.</returns>
/// <remarks>Unity uses the plane equation "Ax + By + Cz + D = 0" while Quake-based engines
/// use "Ax + By + Cz = D". The distance equation needs to be evaluated differently from
/// Unity's default implementation to properly apply to planes read from BSPs.</remarks>
public static bool BSPContains(this Plane p, Vector3d v) {
var distanceTo = p.GetBSPDistanceToPoint(v);
return distanceTo < 0.001 && distanceTo > -0.001;
/// <param name="point1">The first point defining the plane.</param>
/// <param name="point2">The second point defining the plane.</param>
/// <param name="point3">The third point defining the plane.</param>
/// <returns>The <see cref="Plane"/> containing the three points.</returns>
public static Plane CreateFromVertices(Vector3 point1, Vector3 point2, Vector3 point3) {
if ((point1 + point2).Cross(point1 + point3).Magnitude() == 0 ||
float.IsNaN(point1.X()) || float.IsNaN(point1.Y()) || float.IsNaN(point1.Z()) ||
float.IsNaN(point2.X()) || float.IsNaN(point2.Y()) || float.IsNaN(point2.Z()) ||
float.IsNaN(point3.X()) || float.IsNaN(point3.Y()) || float.IsNaN(point3.Z())) {
return new Plane(new Vector3(0, 0, 0), 0);
}
#if UNITY
return new Plane(point1, point2, point3);
#elif GODOT
Plane plane = new Plane(point1, point3, point2);
plane.D *= -1;
return plane;
#else
return Plane.CreateFromVertices(point1, point2, point3);
#endif
}
/// <summary>
@@ -346,7 +279,7 @@ namespace LibBSP {
int numObjects = data.Length / structLength;
Lump<Plane> lump = new Lump<Plane>(numObjects, bsp, lumpInfo);
for (int i = 0; i < numObjects; ++i) {
Vector3d normal = new Vector3d(BitConverter.ToSingle(data, structLength * i), BitConverter.ToSingle(data, (structLength * i) + 4), BitConverter.ToSingle(data, (structLength * i) + 8));
Vector3 normal = new Vector3(BitConverter.ToSingle(data, structLength * i), BitConverter.ToSingle(data, (structLength * i) + 4), BitConverter.ToSingle(data, (structLength * i) + 8));
float distance = BitConverter.ToSingle(data, (structLength * i) + 12);
lump.Add(new Plane(normal, distance));
}
@@ -385,8 +318,8 @@ namespace LibBSP {
break;
}
}
p.GetNormal().GetBytes().CopyTo(bytes, 0);
BitConverter.GetBytes((float)p.GetDistance()).CopyTo(bytes, 12);
p.Normal().GetBytes().CopyTo(bytes, 0);
BitConverter.GetBytes(p.Distance()).CopyTo(bytes, 12);
return bytes;
}
@@ -404,14 +337,10 @@ namespace LibBSP {
/// <returns>The best-match axis for this <see cref="Plane"/>.</returns>
public static int BestAxis(this Plane p) {
int bestaxis = 0;
double best = 0; // "Best" dot product so far
float best = 0; // "Best" dot product so far
for (int i = 0; i < 6; ++i) {
// For all possible axes, positive and negative
#if GODOT
double dot = p.Normal.Dot(baseAxes[i * 3]);
#else
double dot = p.normal.Dot(baseAxes[i * 3]);
#endif
float dot = p.Normal().Dot(baseAxes[i * 3]);
if (dot > best) {
best = dot;
bestaxis = i;
@@ -436,21 +365,21 @@ namespace LibBSP {
/// <param name="p">This <see cref="Plane"/>.</param>
/// <returns>The axial type of this plane.</returns>
public static int Type(this Plane p) {
double ax = Math.Abs(p.GetNormal().x);
float ax = Math.Abs(p.Normal().X());
if (ax >= 1.0) {
return 0;
}
double ay = Math.Abs(p.GetNormal().y);
float ay = Math.Abs(p.Normal().Y());
if (ay >= 1.0) {
return 1;
}
double az = Math.Abs(p.GetNormal().z);
float az = Math.Abs(p.Normal().Z());
if (az >= 1.0) {
return 2;
}
if (ax > ay && ax > az) {
return 3;
}

View File

@@ -0,0 +1,167 @@
#if UNITY_3_4 || UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_5_3_OR_NEWER
#define UNITY
#endif
using System;
namespace LibBSP {
#if UNITY
using Vector2 = UnityEngine.Vector2;
#elif GODOT
using Vector2 = Godot.Vector2;
#else
using Vector2 = System.Numerics.Vector2;
#endif
/// <summary>
/// Class containing helper methods for <see cref="Vector2"/> objects.
/// </summary>
public static class Vector2Extensions {
#if !GODOT
/// <summary>
/// Vector dot product. This operation is commutative.
/// </summary>
/// <param name="vector">This <see cref="Vector2"/>.</param>
/// <param name="other">The <see cref="Vector2"/> to dot with this <see cref="Vector2"/>.</param>
/// <returns>Dot product of this <see cref="Vector2"/> and <paramref name="other"/>.</returns>
public static float Dot(this Vector2 vector, Vector2 other) {
return Vector2.Dot(vector, other);
}
/// <summary>
/// Returns the distance from this <see cref="Vector2"/> to <paramref name="other"/>.
/// </summary>
/// <param name="vector">This <see cref="Vector2"/>.</param>
/// <param name="other">The <see cref="Vector2"/> to get the distance to.</param>
/// <returns>The distance from this <see cref="Vector2"/> to <paramref name="other"/>.</returns>
public static float DistanceTo(this Vector2 vector, Vector2 other) {
return Vector2.Distance(vector, other);
}
/// <summary>
/// Returns the distance from this <see cref="Vector2"/> to <paramref name="other"/> squared.
/// </summary>
/// <param name="vector">This <see cref="Vector2"/>.</param>
/// <param name="other">The <see cref="Vector2"/> to get the distance to squared.</param>
/// <returns>The distance from this <see cref="Vector2"/> to <paramref name="other"/> squared.</returns>
public static float DistanceSquaredTo(this Vector2 vector, Vector2 other) {
#if UNITY
return (vector - other).sqrMagnitude;
#else
return Vector2.DistanceSquared(vector, other);
#endif
}
#endif
/// <summary>
/// Returns this <see cref="Vector2"/> with the same direction but a length of one.
/// </summary>
/// <param name="vector">This <see cref="Vector2"/>.</param>
/// <returns><paramref name="vector"/> with a length of one.</returns>
public static Vector2 GetNormalized(this Vector2 vector) {
if ((vector.X() == 0 && vector.Y() == 0) || float.IsNaN(vector.X()) || float.IsNaN(vector.Y())) {
return new Vector2(0, 0);
}
#if UNITY
return vector.normalized;
#elif GODOT
return vector.Normalized();
#else
return Vector2.Normalize(vector);
#endif
}
/// <summary>
/// Gets the magnitude of this <see cref="Vector2"/>.
/// </summary>
/// <param name="vector">This <see cref="Vector2"/>.</param>
/// <returns>The magnitude of this <see cref="Vector2"/>.</returns>
public static float Magnitude(this Vector2 vector) {
#if UNITY
return vector.magnitude;
#else
return vector.Length();
#endif
}
/// <summary>
/// Gets the magnitude of this <see cref="Vector2"/> squared. This is useful for when you are comparing the lengths of two vectors
/// but don't need to know the exact length, and avoids calculating a square root.
/// </summary>
public static float MagnitudeSquared(this Vector2 vector) {
#if UNITY
return vector.sqrMagnitude;
#else
return vector.LengthSquared();
#endif
}
/// <summary>
/// Gets the square of the area of the triangle defined by three points. This is useful when simply comparing two areas when you don't need to know exactly what the area is.
/// </summary>
/// <param name="vertex1">First vertex of triangle.</param>
/// <param name="vertex2">Second vertex of triangle.</param>
/// <param name="vertex3">Third vertex of triangle.</param>
/// <returns>Square of the area of the triangle defined by these three vertices.</returns>
public static float TriangleAreaSquared(Vector2 vertex1, Vector2 vertex2, Vector2 vertex3) {
float side1 = vertex1.DistanceTo(vertex2);
float side2 = vertex1.DistanceTo(vertex3);
float side3 = vertex2.DistanceTo(vertex3);
float semiPerimeter = (side1 + side2 + side3) / 2f;
return semiPerimeter * (semiPerimeter - side1) * (semiPerimeter - side2) * (semiPerimeter - side3);
}
/// <summary>
/// Gets the area of the triangle defined by three points using Heron's formula.
/// </summary>
/// <param name="vertex1">First vertex of triangle.</param>
/// <param name="vertex2">Second vertex of triangle.</param>
/// <param name="vertex3">Third vertex of triangle.</param>
/// <returns>Area of the triangle defined by these three vertices.</returns>
public static float TriangleArea(Vector2 vertex1, Vector2 vertex2, Vector2 vertex3) {
return (float)Math.Sqrt(TriangleAreaSquared(vertex1, vertex2, vertex3));
}
/// <summary>
/// Gets a <c>byte</c> array representing the components of this <see cref="Vector2"/> as <c>float</c>s.
/// </summary>
/// <param name="vector">This <see cref="Vector2"/>.</param>
/// <returns><c>byte</c> array with the components' bytes.</returns>
public static byte[] GetBytes(this Vector2 vector) {
byte[] ret = new byte[8];
byte[] bytes = BitConverter.GetBytes(vector.X());
bytes.CopyTo(ret, 0);
bytes = BitConverter.GetBytes(vector.Y());
bytes.CopyTo(ret, 4);
return ret;
}
/// <summary>
/// Gets the X component of this <see cref="Vector2"/>.
/// </summary>
/// <param name="vector">This <see cref="Vector2"/>.</param>
/// <returns>The X component of this <see cref="Vector2"/>.</returns>
public static float X(this Vector2 vector) {
#if UNITY || GODOT
return vector.x;
#else
return vector.X;
#endif
}
/// <summary>
/// Gets the Y component of this <see cref="Vector2"/>.
/// </summary>
/// <param name="vector">This <see cref="Vector2"/>.</param>
/// <returns>The Y component of this <see cref="Vector2"/>.</returns>
public static float Y(this Vector2 vector) {
#if UNITY || GODOT
return vector.y;
#else
return vector.Y;
#endif
}
}
}

View File

@@ -1,60 +0,0 @@
#if UNITY_3_4 || UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_5_3_OR_NEWER
#define UNITY
#endif
using System;
using System.Collections.Generic;
namespace LibBSP {
#if UNITY
using Vector2d = UnityEngine.Vector2;
#elif GODOT
using Vector2d = Godot.Vector2;
#endif
/// <summary>
/// Class containing helper methods for <see cref="Vector2d"/> objects.
/// </summary>
public static class Vector2dExtensions {
#if !GODOT
/// <summary>
/// Vector dot product. This operation is commutative.
/// </summary>
/// <param name="v1">This <see cref="Vector2d"/>.</param>
/// <param name="v2">The <see cref="Vector2d"/> to dot with this <see cref="Vector2d"/>.</param>
/// <returns>Dot product of this <see cref="Vector2d"/> and <paramref name="v"/>.</returns>
public static double Dot(this Vector2d v1, Vector2d v) {
return Vector2d.Dot(v1, v);
}
#endif
/// <summary>
/// Gets the magnitude of this <see cref="Vector2d"/>.
/// </summary>
/// <param name="v">This <see cref="Vector2d"/>.</param>
/// <returns>The magnitude of this <see cref="Vector2d"/>.</returns>
public static double GetMagnitude(this Vector2d v) {
#if GODOT
return v.Length();
#else
return v.magnitude;
#endif
}
/// <summary>
/// Gets a <c>byte</c> array representing the components of this <see cref="Vector2d"/> as <c>float</c>s.
/// </summary>
/// <param name="vector">This <see cref="Vector2d"/>.</param>
/// <returns><c>byte</c> array with the components' bytes.</returns>
public static byte[] GetBytes(this Vector2d vector) {
byte[] ret = new byte[8];
byte[] bytes = BitConverter.GetBytes((float)vector.x);
bytes.CopyTo(ret, 0);
bytes = BitConverter.GetBytes((float)vector.y);
bytes.CopyTo(ret, 4);
return ret;
}
}
}

View File

@@ -0,0 +1,191 @@
#if UNITY_3_4 || UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_5_3_OR_NEWER
#define UNITY
#endif
using System;
namespace LibBSP {
#if UNITY
using Vector3 = UnityEngine.Vector3;
#elif GODOT
using Vector3 = Godot.Vector3;
#else
using Vector3 = System.Numerics.Vector3;
#endif
/// <summary>
/// Class containing helper methods for <see cref="Vector3"/> objects.
/// </summary>
public static class Vector3Extensions {
#if !GODOT
/// <summary>
/// Vector dot product. This operation is commutative.
/// </summary>
/// <param name="vector">This <see cref="Vector3"/>.</param>
/// <param name="other">The <see cref="Vector3"/> to dot with this <see cref="Vector3"/>.</param>
/// <returns>Dot product of this <see cref="Vector3"/> and <paramref name="other"/>.</returns>
public static float Dot(this Vector3 vector, Vector3 other) {
return Vector3.Dot(vector, other);
}
/// <summary>
/// Vector cross product. This operation is NOT commutative.
/// </summary>
/// <param name="left">This <see cref="Vector3"/>.</param>
/// <param name="right">The <see cref="Vector3"/> to have this <see cref="Vector3"/> cross.</param>
/// <returns>Cross product of these two vectors. Can be thought of as the normal to the plane defined by these two vectors.</returns>
public static Vector3 Cross(this Vector3 left, Vector3 right) {
return Vector3.Cross(left, right);
}
/// <summary>
/// Returns the distance from this <see cref="Vector3"/> to <paramref name="other"/>.
/// </summary>
/// <param name="vector">This <see cref="Vector3"/>.</param>
/// <param name="other">The <see cref="Vector3"/> to get the distance to.</param>
/// <returns>The distance from this <see cref="Vector3"/> to <paramref name="other"/>.</returns>
public static float DistanceTo(this Vector3 vector, Vector3 other) {
return Vector3.Distance(vector, other);
}
/// <summary>
/// Returns the distance from this <see cref="Vector3"/> to <paramref name="other"/> squared.
/// </summary>
/// <param name="vector">This <see cref="Vector3"/>.</param>
/// <param name="other">The <see cref="Vector3"/> to get the distance to squared.</param>
/// <returns>The distance from this <see cref="Vector3"/> to <paramref name="other"/> squared.</returns>
public static float DistanceSquaredTo(this Vector3 vector, Vector3 other) {
#if UNITY
return (vector - other).sqrMagnitude;
#else
return Vector3.DistanceSquared(vector, other);
#endif
}
#endif
/// <summary>
/// Returns this <see cref="Vector3"/> with the same direction but a length of one.
/// </summary>
/// <param name="vector">This <see cref="Vector3"/>.</param>
/// <returns><paramref name="vector"/> with a length of one.</returns>
public static Vector3 GetNormalized(this Vector3 vector) {
if ((float.IsNaN(vector.X()) || float.IsNaN(vector.Y()) || float.IsNaN(vector.Z())) || vector.X() == 0 && vector.Y() == 0 && vector.Z() == 0) {
return new Vector3(0, 0, 0);
}
#if UNITY
return vector.normalized;
#elif GODOT
return vector.Normalized();
#else
return Vector3.Normalize(vector);
#endif
}
/// <summary>
/// Gets the magnitude of this <see cref="Vector3"/>.
/// </summary>
/// <param name="vector">This <see cref="Vector3"/>.</param>
/// <returns>The magnitude of this <see cref="Vector3"/>.</returns>
public static float Magnitude(this Vector3 vector) {
#if UNITY
return vector.magnitude;
#else
return vector.Length();
#endif
}
/// <summary>
/// Gets the magnitude of this <see cref="Vector3"/> squared. This is useful for when you are comparing the lengths of two vectors
/// but don't need to know the exact length, and avoids calculating a square root.
/// </summary>
public static float MagnitudeSquared(this Vector3 vector) {
#if UNITY
return vector.sqrMagnitude;
#else
return vector.LengthSquared();
#endif
}
/// <summary>
/// Gets the square of the area of the triangle defined by three points. This is useful when simply comparing two areas when you don't need to know exactly what the area is.
/// </summary>
/// <param name="vertex1">First vertex of triangle.</param>
/// <param name="vertex2">Second vertex of triangle.</param>
/// <param name="vertex3">Third vertex of triangle.</param>
/// <returns>Square of the area of the triangle defined by these three vertices.</returns>
public static float TriangleAreaSquared(Vector3 vertex1, Vector3 vertex2, Vector3 vertex3) {
float side1 = vertex1.DistanceTo(vertex2);
float side2 = vertex1.DistanceTo(vertex3);
float side3 = vertex2.DistanceTo(vertex3);
float semiPerimeter = (side1 + side2 + side3) / 2f;
return semiPerimeter * (semiPerimeter - side1) * (semiPerimeter - side2) * (semiPerimeter - side3);
}
/// <summary>
/// Gets the area of the triangle defined by three points using Heron's formula.
/// </summary>
/// <param name="vertex1">First vertex of triangle.</param>
/// <param name="vertex2">Second vertex of triangle.</param>
/// <param name="vertex3">Third vertex of triangle.</param>
/// <returns>Area of the triangle defined by these three vertices.</returns>
public static float TriangleArea(Vector3 vertex1, Vector3 vertex2, Vector3 vertex3) {
return (float)Math.Sqrt(TriangleAreaSquared(vertex1, vertex2, vertex3));
}
/// <summary>
/// Gets a <c>byte</c> array representing the components of this <see cref="Vector3"/> as <c>float</c>s.
/// </summary>
/// <param name="vector">This <see cref="Vector3"/>.</param>
/// <returns><c>byte</c> array with the components' bytes.</returns>
public static byte[] GetBytes(this Vector3 vector) {
byte[] ret = new byte[12];
byte[] bytes = BitConverter.GetBytes(vector.X());
bytes.CopyTo(ret, 0);
bytes = BitConverter.GetBytes(vector.Y());
bytes.CopyTo(ret, 4);
bytes = BitConverter.GetBytes(vector.Z());
bytes.CopyTo(ret, 8);
return ret;
}
/// <summary>
/// Gets the X component of this <see cref="Vector3"/>.
/// </summary>
/// <param name="vector">This <see cref="Vector3"/>.</param>
/// <returns>The X component of this <see cref="Vector3"/>.</returns>
public static float X(this Vector3 vector) {
#if UNITY || GODOT
return vector.x;
#else
return vector.X;
#endif
}
/// <summary>
/// Gets the Y component of this <see cref="Vector3"/>.
/// </summary>
/// <param name="vector">This <see cref="Vector3"/>.</param>
/// <returns>The Y component of this <see cref="Vector3"/>.</returns>
public static float Y(this Vector3 vector) {
#if UNITY || GODOT
return vector.y;
#else
return vector.Y;
#endif
}
/// <summary>
/// Gets the Z component of this <see cref="Vector3"/>.
/// </summary>
/// <param name="vector">This <see cref="Vector3"/>.</param>
/// <returns>The Z component of this <see cref="Vector3"/>.</returns>
public static float Z(this Vector3 vector) {
#if UNITY || GODOT
return vector.z;
#else
return vector.Z;
#endif
}
}
}

View File

@@ -1,72 +0,0 @@
#if UNITY_3_4 || UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_5_3_OR_NEWER
#define UNITY
#endif
using System;
using System.Collections.Generic;
namespace LibBSP {
#if UNITY
using Vector3d = UnityEngine.Vector3;
#elif GODOT
using Vector3d = Godot.Vector3;
#endif
/// <summary>
/// Class containing helper methods for <see cref="Vector3d"/> objects.
/// </summary>
public static class Vector3dExtensions {
#if !GODOT
/// <summary>
/// Vector dot product. This operation is commutative.
/// </summary>
/// <param name="v1">This <see cref="Vector3d"/>.</param>
/// <param name="v">The <see cref="Vector3d"/> to dot with this <see cref="Vector3d"/>.</param>
/// <returns>Dot product of this <see cref="Vector3d"/> and <paramref name="v"/>.</returns>
public static double Dot(this Vector3d v1, Vector3d v) {
return Vector3d.Dot(v1, v);
}
/// <summary>
/// Vector cross product. This operation is NOT commutative.
/// </summary>
/// <param name="v1">This <see cref="Vector3d"/>.</param>
/// <param name="v">The <see cref="Vector3d"/> to have this <see cref="Vector3d"/> cross.</param>
/// <returns>Cross product of these two vectors. Can be thought of as the normal to the plane defined by these two vectors.</returns>
public static Vector3d Cross(this Vector3d v1, Vector3d v) {
return Vector3d.Cross(v1, v);
}
#endif
/// <summary>
/// Gets the magnitude of this <see cref="Vector3d"/>.
/// </summary>
/// <param name="v">This <see cref="Vector3d"/>.</param>
/// <returns>The magnitude of this <see cref="Vector3d"/>.</returns>
public static double GetMagnitude(this Vector3d v) {
#if GODOT
return v.Length();
#else
return v.magnitude;
#endif
}
/// <summary>
/// Gets a <c>byte</c> array representing the components of this <see cref="Vector3d"/> as <c>float</c>s.
/// </summary>
/// <param name="vector">This <see cref="Vector3d"/>.</param>
/// <returns><c>byte</c> array with the components' bytes.</returns>
public static byte[] GetBytes(this Vector3d vector) {
byte[] ret = new byte[12];
byte[] bytes = BitConverter.GetBytes((float)vector.x);
bytes.CopyTo(ret, 0);
bytes = BitConverter.GetBytes((float)vector.y);
bytes.CopyTo(ret, 4);
bytes = BitConverter.GetBytes((float)vector.z);
bytes.CopyTo(ret, 8);
return ret;
}
}
}

View File

@@ -0,0 +1,207 @@
#if UNITY_3_4 || UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_5_3_OR_NEWER
#define UNITY
#endif
using System;
namespace LibBSP {
#if UNITY
using Vector4 = UnityEngine.Vector4;
#elif GODOT
using Vector4 = Godot.Quat;
#else
using Vector4 = System.Numerics.Vector4;
#endif
/// <summary>
/// Class containing helper methods for <see cref="Vector4"/> objects.
/// </summary>
public static class Vector4Extensions {
#if !GODOT
/// <summary>
/// Vector dot product. This operation is commutative.
/// </summary>
/// <param name="vector">This <see cref="Vector4"/>.</param>
/// <param name="other">The <see cref="Vector4"/> to dot with this <see cref="Vector4"/>.</param>
/// <returns>Dot product of this <see cref="Vector4"/> and <paramref name="other"/>.</returns>
public static float Dot(this Vector4 vector, Vector4 other) {
return Vector4.Dot(vector, other);
}
#endif
/// <summary>
/// Returns this <see cref="Vector4"/> with the same direction but a length of one.
/// </summary>
/// <param name="vector">This <see cref="Vector4"/>.</param>
/// <returns><paramref name="vector"/> with a length of one.</returns>
public static Vector4 GetNormalized(this Vector4 vector) {
if ((vector.X() == 0 && vector.Y() == 0 && vector.Z() == 0 && vector.W() == 0) || float.IsNaN(vector.X()) || float.IsNaN(vector.Y()) || float.IsNaN(vector.Z()) || float.IsNaN(vector.W())) {
return new Vector4(0, 0, 0, 0);
}
#if UNITY
return vector.normalized;
#elif GODOT
return vector.Normalized();
#else
return Vector4.Normalize(vector);
#endif
}
/// <summary>
/// Returns the distance from this <see cref="Vector4"/> to <paramref name="other"/>.
/// </summary>
/// <param name="vector">This <see cref="Vector4"/>.</param>
/// <param name="other">The <see cref="Vector4"/> to get the distance to.</param>
/// <returns>The distance from this <see cref="Vector4"/> to <paramref name="other"/>.</returns>
public static float DistanceTo(this Vector4 vector, Vector4 other) {
#if GODOT
return Magnitude(vector - other);
#else
return Vector4.Distance(vector, other);
#endif
}
/// <summary>
/// Returns the distance from this <see cref="Vector4"/> to <paramref name="other"/> squared.
/// </summary>
/// <param name="vector">This <see cref="Vector4"/>.</param>
/// <param name="other">The <see cref="Vector4"/> to get the distance to squared.</param>
/// <returns>The distance from this <see cref="Vector4"/> to <paramref name="other"/> squared.</returns>
public static float DistanceSquaredTo(this Vector4 vector, Vector4 other) {
#if UNITY
return (vector - other).sqrMagnitude;
#elif GODOT
return MagnitudeSquared(vector - other);
#else
return Vector4.DistanceSquared(vector, other);
#endif
}
/// <summary>
/// Gets the magnitude of this <see cref="Vector4"/>.
/// </summary>
/// <param name="vector">This <see cref="Vector4"/>.</param>
/// <returns>The magnitude of this <see cref="Vector4"/>.</returns>
public static float Magnitude(this Vector4 vector) {
#if UNITY
return vector.magnitude;
#elif GODOT
return (float)Math.Sqrt(MagnitudeSquared(vector));
#else
return vector.Length();
#endif
}
/// <summary>
/// Gets the magnitude of this <see cref="Vector4"/> squared. This is useful for when you are comparing the lengths of two vectors
/// but don't need to know the exact length, and avoids calculating a square root.
/// </summary>
public static float MagnitudeSquared(this Vector4 vector) {
#if UNITY
return vector.sqrMagnitude;
#elif GODOT
return (vector.x * vector.x) + (vector.y * vector.y) + (vector.z * vector.z) + (vector.w * vector.w);
#else
return vector.LengthSquared();
#endif
}
/// <summary>
/// Gets the square of the area of the triangle defined by three points. This is useful when simply comparing two areas when you don't need to know exactly what the area is.
/// </summary>
/// <param name="vertex1">First vertex of triangle.</param>
/// <param name="vertex2">Second vertex of triangle.</param>
/// <param name="vertex3">Third vertex of triangle.</param>
/// <returns>Square of the area of the triangle defined by these three vertices.</returns>
public static float TriangleAreaSquared(Vector4 vertex1, Vector4 vertex2, Vector4 vertex3) {
float side1 = vertex1.DistanceTo(vertex2);
float side2 = vertex1.DistanceTo(vertex3);
float side3 = vertex2.DistanceTo(vertex3);
float semiPerimeter = (side1 + side2 + side3) / 2f;
return semiPerimeter * (semiPerimeter - side1) * (semiPerimeter - side2) * (semiPerimeter - side3);
}
/// <summary>
/// Gets the area of the triangle defined by three points using Heron's formula.
/// </summary>
/// <param name="vertex1">First vertex of triangle.</param>
/// <param name="vertex2">Second vertex of triangle.</param>
/// <param name="vertex3">Third vertex of triangle.</param>
/// <returns>Area of the triangle defined by these three vertices.</returns>
public static float TriangleArea(Vector4 vertex1, Vector4 vertex2, Vector4 vertex3) {
return (float)Math.Sqrt(TriangleAreaSquared(vertex1, vertex2, vertex3));
}
/// <summary>
/// Gets a <c>byte</c> array representing the components of this <see cref="Vector4"/> as <c>float</c>s.
/// </summary>
/// <param name="vector">This <see cref="Vector4"/>.</param>
/// <returns><c>byte</c> array with the components' bytes.</returns>
public static byte[] GetBytes(this Vector4 vector) {
byte[] ret = new byte[16];
byte[] bytes = BitConverter.GetBytes(vector.X());
bytes.CopyTo(ret, 0);
bytes = BitConverter.GetBytes(vector.Y());
bytes.CopyTo(ret, 4);
bytes = BitConverter.GetBytes(vector.Z());
bytes.CopyTo(ret, 8);
bytes = BitConverter.GetBytes(vector.W());
bytes.CopyTo(ret, 12);
return ret;
}
/// <summary>
/// Gets the X component of this <see cref="Vector4"/>.
/// </summary>
/// <param name="vector">This <see cref="Vector4"/>.</param>
/// <returns>The X component of this <see cref="Vector4"/>.</returns>
public static float X(this Vector4 vector) {
#if UNITY || GODOT
return vector.x;
#else
return vector.X;
#endif
}
/// <summary>
/// Gets the Y component of this <see cref="Vector4"/>.
/// </summary>
/// <param name="vector">This <see cref="Vector4"/>.</param>
/// <returns>The Y component of this <see cref="Vector4"/>.</returns>
public static float Y(this Vector4 vector) {
#if UNITY || GODOT
return vector.y;
#else
return vector.Y;
#endif
}
/// <summary>
/// Gets the Z component of this <see cref="Vector4"/>.
/// </summary>
/// <param name="vector">This <see cref="Vector4"/>.</param>
/// <returns>The Z component of this <see cref="Vector4"/>.</returns>
public static float Z(this Vector4 vector) {
#if UNITY || GODOT
return vector.z;
#else
return vector.Z;
#endif
}
/// <summary>
/// Gets the Z component of this <see cref="Vector4"/>.
/// </summary>
/// <param name="vector">This <see cref="Vector4"/>.</param>
/// <returns>The Z component of this <see cref="Vector4"/>.</returns>
public static float W(this Vector4 vector) {
#if UNITY || GODOT
return vector.w;
#else
return vector.W;
#endif
}
}
}

View File

@@ -1,64 +0,0 @@
#if UNITY_3_4 || UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_5_3_OR_NEWER
#define UNITY
#endif
using System;
using System.Collections.Generic;
namespace LibBSP {
#if UNITY
using Vector4d = UnityEngine.Vector4;
#elif GODOT
using Vector4d = Godot.Quat;
#endif
/// <summary>
/// Class containing helper methods for <see cref="Vector4d"/> objects.
/// </summary>
public static class Vector4dExtensions {
#if !GODOT
/// <summary>
/// Vector dot product. This operation is commutative.
/// </summary>
/// <param name="v1">This <see cref="Vector4d"/>.</param>
/// <param name="v2">The <see cref="Vector4d"/> to dot with this <see cref="Vector4d"/>.</param>
/// <returns>Dot product of this <see cref="Vector4d"/> and <paramref name="v"/>.</returns>
public static double Dot(this Vector4d v1, Vector4d v) {
return Vector4d.Dot(v1, v);
}
#endif
/// <summary>
/// Gets the magnitude of this <see cref="Vector4d"/>.
/// </summary>
/// <param name="v">This <see cref="Vector4d"/>.</param>
/// <returns>The magnitude of this <see cref="Vector4d"/>.</returns>
public static double GetMagnitude(this Vector4d v) {
#if GODOT
return v.Length;
#else
return v.magnitude;
#endif
}
/// <summary>
/// Gets a <c>byte</c> array representing the components of this <see cref="Vector4d"/> as <c>float</c>s.
/// </summary>
/// <param name="vector">This <see cref="Vector4d"/>.</param>
/// <returns><c>byte</c> array with the components' bytes.</returns>
public static byte[] GetBytes(this Vector4d vector) {
byte[] ret = new byte[16];
byte[] bytes = BitConverter.GetBytes((float)vector.x);
bytes.CopyTo(ret, 0);
bytes = BitConverter.GetBytes((float)vector.y);
bytes.CopyTo(ret, 4);
bytes = BitConverter.GetBytes((float)vector.z);
bytes.CopyTo(ret, 8);
bytes = BitConverter.GetBytes((float)vector.w);
bytes.CopyTo(ret, 12);
return ret;
}
}
}

View File

@@ -6,90 +6,61 @@
#endif
using System;
using System.Collections.Generic;
namespace LibBSP {
#if UNITY
using Vector2d = UnityEngine.Vector2;
using Vector3d = UnityEngine.Vector3;
using Vector4d = UnityEngine.Vector4;
using Vector2 = UnityEngine.Vector2;
using Vector3 = UnityEngine.Vector3;
using Vector4 = UnityEngine.Vector4;
#if !OLDUNITY
using Vertex = UnityEngine.UIVertex;
#endif
#elif GODOT
using Vector2d = Godot.Vector2;
using Vector3d = Godot.Vector3;
using Vector4d = Godot.Quat;
using Vector2 = Godot.Vector2;
using Vector3 = Godot.Vector3;
using Vector4 = Godot.Quat;
#else
using Vector2 = System.Numerics.Vector2;
using Vector3 = System.Numerics.Vector3;
using Vector4 = System.Numerics.Vector4;
#endif
/// <summary>
/// Static class containing helper methods for <see cref="Vertex"/> objects.
/// </summary>
public static class VertexExtensions {
#if !UNITY
/// <summary>
/// Scales the position of this <see cref="Vertex"/> by a scalar.
/// </summary>
/// <param name="v1">This <see cref="Vertex"/>.</param>
/// <param name="scalar">Scalar value.</param>
public static void Scale(this ref Vertex v1, float scalar) {
v1.position *= scalar;
}
/// <summary>
/// Adds the position of this <see cref="Vertex"/> to another <see cref="Vertex"/>.
/// </summary>
/// <param name="v1">This <see cref="Vertex"/>.</param>
/// <param name="v2">The other <see cref="Vertex"/>.</param>
public static void Add(this ref Vertex v1, Vertex v2) {
v1.position += v2.position;
}
/// <summary>
/// Adds the position of a <c>Vector3d</c> to this <see cref="Vertex"/>.
/// </summary>
/// <param name="v1">This <see cref="Vertex"/>.</param>
/// <param name="v2">The <see cref="Vector3d"/>.</param>
public static void Translate(this ref Vertex v1, Vector3d v2) {
v1.position += v2;
}
#endif
// Extension methods using "ref" are features of C# 7.2. They will not work in Unity, no matter what.
// Instead use these vanilla static methods in any code intended to be used with Unity.
/// <summary>
/// Scales the position of a <see cref="Vertex"/> by a scalar and returns the result.
/// </summary>
/// <param name="v1">The <see cref="Vertex"/> to scale.</param>
/// <param name="vertex">The <see cref="Vertex"/> to scale.</param>
/// <param name="scalar">Scalar value.</param>
/// <returns>The resulting <see cref="Vertex"/> of this scaling operation.</returns>
public static Vertex Scale(Vertex v1, float scalar) {
v1.position *= scalar;
return v1;
public static Vertex Scale(Vertex vertex, float scalar) {
vertex.position *= scalar;
return vertex;
}
/// <summary>
/// Adds the position of a <see cref="Vertex"/> to another <see cref="Vertex"/> and returns the result.
/// </summary>
/// <param name="v1">A <see cref="Vertex"/> to be added to another.</param>
/// <param name="v2">A <see cref="Vertex"/> to be added to another.</param>
/// <param name="vertex1">A <see cref="Vertex"/> to be added to another.</param>
/// <param name="vertex2">A <see cref="Vertex"/> to be added to another.</param>
/// <returns>The resulting <see cref="Vertex"/> of this addition.</returns>
public static Vertex Add(Vertex v1, Vertex v2) {
v1.position += v2.position;
return v1;
public static Vertex Add(Vertex vertex1, Vertex vertex2) {
vertex1.position += vertex2.position;
return vertex1;
}
/// <summary>
/// Adds the position of a <c>Vector3d</c> to a <see cref="Vertex"/> and returns the result.
/// Adds the position of a <c>Vector3</c> to a <see cref="Vertex"/> and returns the result.
/// </summary>
/// <param name="v1">The <see cref="Vertex"/> to translate.</param>
/// <param name="v2">The <see cref="Vector3d"/> to translate by.</param>
/// <returns>The resulting <see cref="Vertex"/> translated by <paramref name="v2"/>.</returns>
public static Vertex Translate(Vertex v1, Vector3d v2) {
v1.position += v2;
return v1;
/// <param name="vertex1">The <see cref="Vertex"/> to translate.</param>
/// <param name="vertex2">The <see cref="Vector3"/> to translate by.</param>
/// <returns>The resulting <see cref="Vertex"/> translated by <paramref name="vertex2"/>.</returns>
public static Vertex Translate(Vertex vertex1, Vector3 vertex2) {
vertex1.position += vertex2;
return vertex1;
}
/// <summary>
@@ -121,43 +92,43 @@ namespace LibBSP {
}
case MapType.CoD2:
case MapType.CoD4: {
result.normal = new Vector3d(BitConverter.ToSingle(data, 12), BitConverter.ToSingle(data, 16), BitConverter.ToSingle(data, 20));
result.normal = new Vector3(BitConverter.ToSingle(data, 12), BitConverter.ToSingle(data, 16), BitConverter.ToSingle(data, 20));
result.color = ColorExtensions.FromArgb(data[27], data[24], data[25], data[26]);
result.uv0 = new Vector2d(BitConverter.ToSingle(data, 28), BitConverter.ToSingle(data, 32));
result.uv1 = new Vector2d(BitConverter.ToSingle(data, 36), BitConverter.ToSingle(data, 40));
result.uv0 = new Vector2(BitConverter.ToSingle(data, 28), BitConverter.ToSingle(data, 32));
result.uv1 = new Vector2(BitConverter.ToSingle(data, 36), BitConverter.ToSingle(data, 40));
// Use these fields to store additional unknown information
result.tangent = new Vector4d(BitConverter.ToSingle(data, 44), BitConverter.ToSingle(data, 48), BitConverter.ToSingle(data, 52), BitConverter.ToSingle(data, 56));
result.uv3 = new Vector2d(BitConverter.ToSingle(data, 60), BitConverter.ToSingle(data, 64));
result.tangent = new Vector4(BitConverter.ToSingle(data, 44), BitConverter.ToSingle(data, 48), BitConverter.ToSingle(data, 52), BitConverter.ToSingle(data, 56));
result.uv3 = new Vector2(BitConverter.ToSingle(data, 60), BitConverter.ToSingle(data, 64));
goto case MapType.Quake;
}
case MapType.MOHAA:
case MapType.Quake3:
case MapType.FAKK: {
result.uv0 = new Vector2d(BitConverter.ToSingle(data, 12), BitConverter.ToSingle(data, 16));
result.uv1 = new Vector2d(BitConverter.ToSingle(data, 20), BitConverter.ToSingle(data, 24));
result.normal = new Vector3d(BitConverter.ToSingle(data, 28), BitConverter.ToSingle(data, 32), BitConverter.ToSingle(data, 36));
result.uv0 = new Vector2(BitConverter.ToSingle(data, 12), BitConverter.ToSingle(data, 16));
result.uv1 = new Vector2(BitConverter.ToSingle(data, 20), BitConverter.ToSingle(data, 24));
result.normal = new Vector3(BitConverter.ToSingle(data, 28), BitConverter.ToSingle(data, 32), BitConverter.ToSingle(data, 36));
result.color = ColorExtensions.FromArgb(data[43], data[40], data[41], data[42]);
goto case MapType.Quake;
}
case MapType.Raven: {
result.uv0 = new Vector2d(BitConverter.ToSingle(data, 12), BitConverter.ToSingle(data, 16));
result.uv1 = new Vector2d(BitConverter.ToSingle(data, 20), BitConverter.ToSingle(data, 24));
result.uv2 = new Vector2d(BitConverter.ToSingle(data, 28), BitConverter.ToSingle(data, 32));
result.uv3 = new Vector2d(BitConverter.ToSingle(data, 36), BitConverter.ToSingle(data, 40));
result.normal = new Vector3d(BitConverter.ToSingle(data, 52), BitConverter.ToSingle(data, 56), BitConverter.ToSingle(data, 60));
result.uv0 = new Vector2(BitConverter.ToSingle(data, 12), BitConverter.ToSingle(data, 16));
result.uv1 = new Vector2(BitConverter.ToSingle(data, 20), BitConverter.ToSingle(data, 24));
result.uv2 = new Vector2(BitConverter.ToSingle(data, 28), BitConverter.ToSingle(data, 32));
result.uv3 = new Vector2(BitConverter.ToSingle(data, 36), BitConverter.ToSingle(data, 40));
result.normal = new Vector3(BitConverter.ToSingle(data, 52), BitConverter.ToSingle(data, 56), BitConverter.ToSingle(data, 60));
result.color = ColorExtensions.FromArgb(data[67], data[64], data[65], data[66]);
// Use for two more float fields and two more colors.
// There's actually another field that seems to be color but I've only ever seen it be 0xFFFFFFFF.
result.tangent = new Vector4d(BitConverter.ToSingle(data, 44), BitConverter.ToSingle(data, 48), BitConverter.ToSingle(data, 68), BitConverter.ToSingle(data, 72));
result.tangent = new Vector4(BitConverter.ToSingle(data, 44), BitConverter.ToSingle(data, 48), BitConverter.ToSingle(data, 68), BitConverter.ToSingle(data, 72));
goto case MapType.Quake;
}
case MapType.STEF2:
case MapType.STEF2Demo: {
result.uv0 = new Vector2d(BitConverter.ToSingle(data, 12), BitConverter.ToSingle(data, 16));
result.uv1 = new Vector2d(BitConverter.ToSingle(data, 20), BitConverter.ToSingle(data, 24));
result.uv2 = new Vector2d(BitConverter.ToSingle(data, 28), 0);
result.uv0 = new Vector2(BitConverter.ToSingle(data, 12), BitConverter.ToSingle(data, 16));
result.uv1 = new Vector2(BitConverter.ToSingle(data, 20), BitConverter.ToSingle(data, 24));
result.uv2 = new Vector2(BitConverter.ToSingle(data, 28), 0);
result.color = ColorExtensions.FromArgb(data[35], data[32], data[33], data[34]);
result.normal = new Vector3d(BitConverter.ToSingle(data, 36), BitConverter.ToSingle(data, 40), BitConverter.ToSingle(data, 44));
result.normal = new Vector3(BitConverter.ToSingle(data, 36), BitConverter.ToSingle(data, 40), BitConverter.ToSingle(data, 44));
goto case MapType.Quake;
}
case MapType.Quake:
@@ -179,7 +150,7 @@ namespace LibBSP {
case MapType.Daikatana:
case MapType.Vindictus:
case MapType.DMoMaM: {
result.position = new Vector3d(BitConverter.ToSingle(data, 0), BitConverter.ToSingle(data, 4), BitConverter.ToSingle(data, 8));
result.position = new Vector3(BitConverter.ToSingle(data, 0), BitConverter.ToSingle(data, 4), BitConverter.ToSingle(data, 8));
break;
}
default: {
@@ -417,13 +388,13 @@ namespace LibBSP {
v.uv1.GetBytes().CopyTo(bytes, 20);
v.uv2.GetBytes().CopyTo(bytes, 28);
v.uv3.GetBytes().CopyTo(bytes, 36);
BitConverter.GetBytes((float)v.tangent.x).CopyTo(bytes, 44);
BitConverter.GetBytes((float)v.tangent.y).CopyTo(bytes, 48);
BitConverter.GetBytes((float)v.tangent.X()).CopyTo(bytes, 44);
BitConverter.GetBytes((float)v.tangent.Y()).CopyTo(bytes, 48);
v.normal.GetBytes().CopyTo(bytes, 52);
v.color.GetBytes().CopyTo(bytes, 64);
BitConverter.GetBytes((float)v.tangent.z).CopyTo(bytes, 68);
BitConverter.GetBytes((float)v.tangent.w).CopyTo(bytes, 72);
// There's actually another field that seems to be a color but I've only ever seen it be FFFFFFFF.
BitConverter.GetBytes((float)v.tangent.Z()).CopyTo(bytes, 68);
BitConverter.GetBytes((float)v.tangent.W()).CopyTo(bytes, 72);
// There's actually another field that I've only ever seen it be FFFFFFFF.
bytes[76] = 255;
bytes[77] = 255;
bytes[78] = 255;
@@ -434,7 +405,7 @@ namespace LibBSP {
case MapType.STEF2Demo: {
v.uv0.GetBytes().CopyTo(bytes, 12);
v.uv1.GetBytes().CopyTo(bytes, 20);
BitConverter.GetBytes(v.uv2.x).CopyTo(bytes, 28);
BitConverter.GetBytes(v.uv2.X()).CopyTo(bytes, 28);
v.color.GetBytes().CopyTo(bytes, 32);
v.normal.GetBytes().CopyTo(bytes, 36);
goto case MapType.Quake;

View File

@@ -18,6 +18,8 @@ namespace LibBSP {
#endif
#elif GODOT
using Plane = Godot.Plane;
#else
using Plane = System.Numerics.Plane;
#endif
/// <summary>

View File

@@ -8,9 +8,11 @@ using System.Reflection;
namespace LibBSP {
#if UNITY
using Vector3d = UnityEngine.Vector3;
using Vector3 = UnityEngine.Vector3;
#elif GODOT
using Vector3d = Godot.Vector3;
using Vector3 = Godot.Vector3;
#else
using Vector3 = System.Numerics.Vector3;
#endif
/// <summary>
@@ -52,7 +54,7 @@ namespace LibBSP {
}
}
public Vector3d origin {
public Vector3 origin {
get {
switch (MapType) {
case MapType.Source17:
@@ -67,10 +69,10 @@ namespace LibBSP {
case MapType.L4D2:
case MapType.Vindictus:
case MapType.DMoMaM: {
return new Vector3d(BitConverter.ToInt32(Data, 0), BitConverter.ToInt32(Data, 4), BitConverter.ToInt32(Data, 8));
return new Vector3(BitConverter.ToInt32(Data, 0), BitConverter.ToInt32(Data, 4), BitConverter.ToInt32(Data, 8));
}
default: {
return new Vector3d(float.NaN, float.NaN, float.NaN);
return new Vector3(float.NaN, float.NaN, float.NaN);
}
}
}

View File

@@ -8,9 +8,11 @@ using System.Reflection;
namespace LibBSP {
#if UNITY
using Vector3d = UnityEngine.Vector3;
using Vector3 = UnityEngine.Vector3;
#elif GODOT
using Vector3d = Godot.Vector3;
using Vector3 = Godot.Vector3;
#else
using Vector3 = System.Numerics.Vector3;
#endif
/// <summary>
@@ -52,9 +54,9 @@ namespace LibBSP {
}
}
public Vector3d startPosition {
public Vector3 startPosition {
get {
return new Vector3d(BitConverter.ToSingle(Data, 0), BitConverter.ToSingle(Data, 4), BitConverter.ToSingle(Data, 8));
return new Vector3(BitConverter.ToSingle(Data, 0), BitConverter.ToSingle(Data, 4), BitConverter.ToSingle(Data, 8));
}
set {
value.GetBytes().CopyTo(Data, 0);

View File

@@ -7,9 +7,11 @@ using System.Reflection;
namespace LibBSP {
#if UNITY
using Vector3d = UnityEngine.Vector3;
using Vector3 = UnityEngine.Vector3;
#elif GODOT
using Vector3d = Godot.Vector3;
using Vector3 = Godot.Vector3;
#else
using Vector3 = System.Numerics.Vector3;
#endif
/// <summary>
@@ -54,9 +56,9 @@ namespace LibBSP {
/// <summary>
/// The normalized vector direction this vertex points from "flat".
/// </summary>
public Vector3d normal {
public Vector3 normal {
get {
return new Vector3d(BitConverter.ToSingle(Data, 0), BitConverter.ToSingle(Data, 4), BitConverter.ToSingle(Data, 8));
return new Vector3(BitConverter.ToSingle(Data, 0), BitConverter.ToSingle(Data, 4), BitConverter.ToSingle(Data, 8));
}
set {
value.GetBytes().CopyTo(Data, 0);

View File

@@ -8,9 +8,11 @@ using System.Reflection;
namespace LibBSP {
#if UNITY
using Vector2d = UnityEngine.Vector2;
using Vector2 = UnityEngine.Vector2;
#elif GODOT
using Vector2d = Godot.Vector2;
using Vector2 = Godot.Vector2;
#else
using Vector2 = System.Numerics.Vector2;
#endif
/// <summary>
@@ -885,7 +887,7 @@ namespace LibBSP {
}
}
public Vector2d patchSize {
public Vector2 patchSize {
get {
switch (MapType) {
case MapType.Quake3:
@@ -894,10 +896,10 @@ namespace LibBSP {
case MapType.STEF2Demo:
case MapType.MOHAA:
case MapType.FAKK: {
return new Vector2d(BitConverter.ToInt32(Data, 96), BitConverter.ToInt32(Data, 100));
return new Vector2(BitConverter.ToInt32(Data, 96), BitConverter.ToInt32(Data, 100));
}
default: {
return new Vector2d(float.NaN, float.NaN);
return new Vector2(float.NaN, float.NaN);
}
}
}
@@ -909,9 +911,9 @@ namespace LibBSP {
case MapType.STEF2Demo:
case MapType.MOHAA:
case MapType.FAKK: {
byte[] bytes = BitConverter.GetBytes((int)value.x);
byte[] bytes = BitConverter.GetBytes((int)value.X());
bytes.CopyTo(Data, 96);
bytes = BitConverter.GetBytes((int)value.y);
bytes = BitConverter.GetBytes((int)value.Y());
bytes.CopyTo(Data, 100);
break;
}

View File

@@ -47,7 +47,7 @@ namespace LibBSP {
/// <param name="first">The first vertex to get.</param>
/// <param name="power">The power of the displacement.</param>
/// <returns>Array of <see cref="DisplacementVertex"/> objects containing all the vertices in this displacement</returns>
public virtual DisplacementVertex[] GetVerticesInDisplacement(int first, int power) {
public DisplacementVertex[] GetVerticesInDisplacement(int first, int power) {
int side = (power * power) + 1;
int numVerts = side * side;
DisplacementVertex[] ret = new DisplacementVertex[numVerts];

View File

@@ -8,9 +8,11 @@ using System.Reflection;
namespace LibBSP {
#if UNITY
using Vector2d = UnityEngine.Vector2;
using Vector2 = UnityEngine.Vector2;
#elif GODOT
using Vector2d = Godot.Vector2;
using Vector2 = Godot.Vector2;
#else
using Vector2 = System.Numerics.Vector2;
#endif
/// <summary>
@@ -96,18 +98,18 @@ namespace LibBSP {
}
}
public Vector2d dimensions {
public Vector2 dimensions {
get {
switch (MapType) {
case MapType.CoD: {
if (patchType == 0) {
return new Vector2d(BitConverter.ToInt16(Data, 4), BitConverter.ToInt16(Data, 6));
return new Vector2(BitConverter.ToInt16(Data, 4), BitConverter.ToInt16(Data, 6));
} else {
return new Vector2d(float.NaN, float.NaN);
return new Vector2(float.NaN, float.NaN);
}
}
default: {
return new Vector2d(float.NaN, float.NaN);
return new Vector2(float.NaN, float.NaN);
}
}
}
@@ -115,8 +117,8 @@ namespace LibBSP {
switch (MapType) {
case MapType.CoD: {
if (patchType == 0) {
BitConverter.GetBytes((short)value.x).CopyTo(Data, 4);
BitConverter.GetBytes((short)value.y).CopyTo(Data, 6);
BitConverter.GetBytes((short)value.X()).CopyTo(Data, 4);
BitConverter.GetBytes((short)value.Y()).CopyTo(Data, 6);
}
break;
}

View File

@@ -9,9 +9,11 @@ using System.Text;
namespace LibBSP {
#if UNITY
using Vector3d = UnityEngine.Vector3;
using Vector3 = UnityEngine.Vector3;
#elif GODOT
using Vector3d = Godot.Vector3;
using Vector3 = Godot.Vector3;
#else
using Vector3 = System.Numerics.Vector3;
#endif
/// <summary>
@@ -78,14 +80,14 @@ namespace LibBSP {
}
}
public Vector3d origin {
public Vector3 origin {
get {
switch (MapType) {
case MapType.MOHAA: {
return new Vector3d(BitConverter.ToSingle(Data, 128), BitConverter.ToSingle(Data, 132), BitConverter.ToSingle(Data, 136));
return new Vector3(BitConverter.ToSingle(Data, 128), BitConverter.ToSingle(Data, 132), BitConverter.ToSingle(Data, 136));
}
default: {
return new Vector3d(float.NaN, float.NaN, float.NaN);
return new Vector3(float.NaN, float.NaN, float.NaN);
}
}
}
@@ -99,14 +101,14 @@ namespace LibBSP {
}
}
public Vector3d angles {
public Vector3 angles {
get {
switch (MapType) {
case MapType.MOHAA: {
return new Vector3d(BitConverter.ToSingle(Data, 140), BitConverter.ToSingle(Data, 144), BitConverter.ToSingle(Data, 148));
return new Vector3(BitConverter.ToSingle(Data, 140), BitConverter.ToSingle(Data, 144), BitConverter.ToSingle(Data, 148));
}
default: {
return new Vector3d(float.NaN, float.NaN, float.NaN);
return new Vector3(float.NaN, float.NaN, float.NaN);
}
}
}

View File

@@ -8,11 +8,12 @@ using System.Text;
namespace LibBSP {
#if UNITY
using Color = UnityEngine.Color32;
using Vector3d = UnityEngine.Vector3;
using Vector3 = UnityEngine.Vector3;
#elif GODOT
using Color = Godot.Color;
using Vector3d = Godot.Vector3;
using Vector3 = Godot.Vector3;
#else
using Vector3 = System.Numerics.Vector3;
using Color = System.Drawing.Color;
#endif
@@ -55,7 +56,7 @@ namespace LibBSP {
}
}
public Vector3d origin {
public Vector3 origin {
get {
switch (MapType) {
case MapType.Source17:
@@ -81,15 +82,15 @@ namespace LibBSP {
case 10:
case 11:
case 12: {
return new Vector3d(BitConverter.ToSingle(Data, 0), BitConverter.ToSingle(Data, 4), BitConverter.ToSingle(Data, 8));
return new Vector3(BitConverter.ToSingle(Data, 0), BitConverter.ToSingle(Data, 4), BitConverter.ToSingle(Data, 8));
}
default: {
return new Vector3d(float.NaN, float.NaN, float.NaN);
return new Vector3(float.NaN, float.NaN, float.NaN);
}
}
}
default: {
return new Vector3d(float.NaN, float.NaN, float.NaN);
return new Vector3(float.NaN, float.NaN, float.NaN);
}
}
}
@@ -128,7 +129,7 @@ namespace LibBSP {
}
}
public Vector3d angles {
public Vector3 angles {
get {
switch (MapType) {
case MapType.Source17:
@@ -154,15 +155,15 @@ namespace LibBSP {
case 10:
case 11:
case 12: {
return new Vector3d(BitConverter.ToSingle(Data, 12), BitConverter.ToSingle(Data, 16), BitConverter.ToSingle(Data, 20));
return new Vector3(BitConverter.ToSingle(Data, 12), BitConverter.ToSingle(Data, 16), BitConverter.ToSingle(Data, 20));
}
default: {
return new Vector3d(float.NaN, float.NaN, float.NaN);
return new Vector3(float.NaN, float.NaN, float.NaN);
}
}
}
default: {
return new Vector3d(float.NaN, float.NaN, float.NaN);
return new Vector3(float.NaN, float.NaN, float.NaN);
}
}
}
@@ -822,7 +823,7 @@ namespace LibBSP {
}
}
public Vector3d lightingOrigin {
public Vector3 lightingOrigin {
get {
switch (MapType) {
case MapType.Source17:
@@ -847,22 +848,22 @@ namespace LibBSP {
case 10:
case 11:
case 12: {
return new Vector3d(BitConverter.ToSingle(Data, 44), BitConverter.ToSingle(Data, 48), BitConverter.ToSingle(Data, 52));
return new Vector3(BitConverter.ToSingle(Data, 44), BitConverter.ToSingle(Data, 48), BitConverter.ToSingle(Data, 52));
}
case 9: {
if (Data.Length == 76) {
return new Vector3d(BitConverter.ToSingle(Data, 48), BitConverter.ToSingle(Data, 52), BitConverter.ToSingle(Data, 56));
return new Vector3(BitConverter.ToSingle(Data, 48), BitConverter.ToSingle(Data, 52), BitConverter.ToSingle(Data, 56));
} else {
return new Vector3d(BitConverter.ToSingle(Data, 44), BitConverter.ToSingle(Data, 48), BitConverter.ToSingle(Data, 52));
return new Vector3(BitConverter.ToSingle(Data, 44), BitConverter.ToSingle(Data, 48), BitConverter.ToSingle(Data, 52));
}
}
default: {
return new Vector3d(float.NaN, float.NaN, float.NaN);
return new Vector3(float.NaN, float.NaN, float.NaN);
}
}
}
default: {
return new Vector3d(float.NaN, float.NaN, float.NaN);
return new Vector3(float.NaN, float.NaN, float.NaN);
}
}
}

View File

@@ -7,11 +7,14 @@ using System.Text;
namespace LibBSP {
#if UNITY
using Vector2d = UnityEngine.Vector2;
using Vector3d = UnityEngine.Vector3;
using Vector2 = UnityEngine.Vector2;
using Vector3 = UnityEngine.Vector3;
#elif GODOT
using Vector2d = Godot.Vector2;
using Vector3d = Godot.Vector3;
using Vector2 = Godot.Vector2;
using Vector3 = Godot.Vector3;
#else
using Vector2 = System.Numerics.Vector2;
using Vector3 = System.Numerics.Vector3;
#endif
/// <summary>
@@ -289,10 +292,10 @@ namespace LibBSP {
case MapType.SoF:
case MapType.Daikatana:
case MapType.SiN: {
return new TextureInfo(new Vector3d(BitConverter.ToSingle(Data, 0), BitConverter.ToSingle(Data, 4), BitConverter.ToSingle(Data, 8)),
new Vector3d(BitConverter.ToSingle(Data, 16), BitConverter.ToSingle(Data, 20), BitConverter.ToSingle(Data, 24)),
new Vector2d(BitConverter.ToSingle(Data, 12), BitConverter.ToSingle(Data, 28)),
new Vector2d(1, 1),
return new TextureInfo(new Vector3(BitConverter.ToSingle(Data, 0), BitConverter.ToSingle(Data, 4), BitConverter.ToSingle(Data, 8)),
new Vector3(BitConverter.ToSingle(Data, 16), BitConverter.ToSingle(Data, 20), BitConverter.ToSingle(Data, 24)),
new Vector2(BitConverter.ToSingle(Data, 12), BitConverter.ToSingle(Data, 28)),
new Vector2(1, 1),
-1, -1, 0);
}
default: {
@@ -310,9 +313,9 @@ namespace LibBSP {
bytes.CopyTo(Data, 0);
bytes = value.vAxis.GetBytes();
bytes.CopyTo(Data, 16);
bytes = BitConverter.GetBytes(value.translation.x);
bytes = BitConverter.GetBytes(value.translation.X());
bytes.CopyTo(Data, 12);
bytes = BitConverter.GetBytes(value.translation.y);
bytes = BitConverter.GetBytes(value.translation.Y());
bytes.CopyTo(Data, 28);
break;
}

View File

@@ -8,9 +8,11 @@ using System.Reflection;
namespace LibBSP {
#if UNITY
using Vector3d = UnityEngine.Vector3;
using Vector3 = UnityEngine.Vector3;
#elif GODOT
using Vector3d = Godot.Vector3;
using Vector3 = Godot.Vector3;
#else
using Vector3 = System.Numerics.Vector3;
#endif
/// <summary>
@@ -52,9 +54,9 @@ namespace LibBSP {
}
}
public Vector3d reflectivity {
public Vector3 reflectivity {
get {
return new Vector3d(BitConverter.ToSingle(Data, 0), BitConverter.ToSingle(Data, 4), BitConverter.ToSingle(Data, 8));
return new Vector3(BitConverter.ToSingle(Data, 0), BitConverter.ToSingle(Data, 4), BitConverter.ToSingle(Data, 8));
}
set {
value.GetBytes().CopyTo(Data, 0);

View File

@@ -10,11 +10,14 @@ using System.Globalization;
namespace LibBSP {
#if UNITY
using Vector3d = UnityEngine.Vector3;
using Vector4d = UnityEngine.Vector4;
using Vector3 = UnityEngine.Vector3;
using Vector4 = UnityEngine.Vector4;
#elif GODOT
using Vector3d = Godot.Vector3;
using Vector4d = Godot.Quat;
using Vector3 = Godot.Vector3;
using Vector4 = Godot.Quat;
#else
using Vector3 = System.Numerics.Vector3;
using Vector4 = System.Numerics.Vector4;
#endif
/// <summary>
@@ -90,29 +93,35 @@ namespace LibBSP {
return 0;
}
}
set { this["spawnflags"] = value.ToString(); }
set {
this["spawnflags"] = value.ToString();
}
}
/// <summary>
/// Wrapper for the "origin" attribute.
/// </summary>
public Vector3d origin {
public Vector3 origin {
get {
Vector4d vec = GetVector("origin");
return new Vector3d(vec.x, vec.y, vec.z);
Vector4 vec = GetVector("origin");
return new Vector3(vec.X(), vec.Y(), vec.Z());
}
set {
this["origin"] = value.X() + " " + value.Y() + " " + value.Z();
}
set { this["origin"] = value.x + " " + value.y + " " + value.z; }
}
/// <summary>
/// Wrapper for the "angles" attribute.
/// </summary>
public Vector3d angles {
public Vector3 angles {
get {
Vector4d vec = GetVector("angles");
return new Vector3d(vec.x, vec.y, vec.z);
Vector4 vec = GetVector("angles");
return new Vector3(vec.X(), vec.Y(), vec.Z());
}
set {
this["angles"] = value.X() + " " + value.Y() + " " + value.Z();
}
set { this["angles"] = value.x + " " + value.y + " " + value.z; }
}
/// <summary>
@@ -128,7 +137,9 @@ namespace LibBSP {
return "";
}
}
set { this["targetname"] = value; }
set {
this["targetname"] = value;
}
}
/// <summary>
@@ -143,7 +154,9 @@ namespace LibBSP {
return "";
}
}
set { this["classname"] = value; }
set {
this["classname"] = value;
}
}
/// <summary>
@@ -196,9 +209,16 @@ namespace LibBSP {
return "";
}
}
set { base[key] = value; }
set {
base[key] = value;
}
}
/// <summary>
/// Initializes a new instance of an <see cref="Entity"/> object with no initial properties.
/// </summary>
public Entity() : base(StringComparer.InvariantCultureIgnoreCase) { }
/// <summary>
/// Initializes a new instance of an <see cref="Entity"/>, parsing the given <c>byte</c> array into an <see cref="Entity"/> structure.
/// </summary>
@@ -219,9 +239,9 @@ namespace LibBSP {
}
/// <summary>
/// Initializes a new instance of an <see cref="Entity"/> object with no initial properties.
/// Initializes a new instance of an <see cref="Entity"/> object with a given parent.
/// </summary>
public Entity(ILump parent = null) : base(StringComparer.InvariantCultureIgnoreCase) {
public Entity(ILump parent) : base(StringComparer.InvariantCultureIgnoreCase) {
Parent = parent;
}
@@ -400,7 +420,7 @@ namespace LibBSP {
target = connection[0],
action = connection[1],
param = connection[2],
delay = double.Parse(connection[3], _format),
delay = float.Parse(connection[3], _format),
fireOnce = int.Parse(connection[4]),
unknown0 = connection.Length > 5 ? connection[5] : "",
unknown1 = connection.Length > 6 ? connection[6] : "",
@@ -525,7 +545,7 @@ namespace LibBSP {
/// </summary>
/// <param name="key">Name of the attribute to retrieve.</param>
/// <returns>Vector representation of the components of the attribute.</returns>
public Vector4d GetVector(string key) {
public Vector4 GetVector(string key) {
float[] results = new float[4];
if (ContainsKey(key) && !string.IsNullOrEmpty(this[key])) {
string[] nums = this[key].Split(' ');
@@ -537,7 +557,7 @@ namespace LibBSP {
}
}
}
return new Vector4d(results[0], results[1], results[2], results[3]);
return new Vector4(results[0], results[1], results[2], results[3]);
}
#region IComparable
@@ -549,9 +569,13 @@ namespace LibBSP {
/// <returns>Less than zero if this entity is first, 0 if they occur at the same time, greater than zero otherwise.</returns>
/// <exception cref="ArgumentException"><paramref name="obj"/> was not of type <see cref="Entity"/>.</exception>
public int CompareTo(object obj) {
if (obj == null) { return 1; }
if (obj == null) {
return 1;
}
Entity other = obj as Entity;
if (other == null) { throw new ArgumentException("Object is not an Entity"); }
if (other == null) {
throw new ArgumentException("Object is not an Entity");
}
int firstTry = className.CompareTo(other.className);
return firstTry != 0 ? firstTry : name.CompareTo(other.name);
@@ -564,7 +588,9 @@ namespace LibBSP {
/// <param name="other"><see cref="Entity"/> to compare to.</param>
/// <returns>Less than zero if this entity is first, 0 if they occur at the same time, greater than zero otherwise.</returns>
public int CompareTo(Entity other) {
if (other == null) { return 1; }
if (other == null) {
return 1;
}
int firstTry = className.CompareTo(other.className);
return firstTry != 0 ? firstTry : name.CompareTo(other.name);
}
@@ -581,7 +607,6 @@ namespace LibBSP {
base.GetObjectData(info, context);
info.AddValue("connections", connections, typeof(List<EntityConnection>));
info.AddValue("brushes", brushes, typeof(List<MAPBrush>));
}
#endregion
@@ -661,7 +686,7 @@ namespace LibBSP {
public string target;
public string action;
public string param;
public double delay;
public float delay;
public int fireOnce;
// As I recall, these exist in Dark Messiah only. I have no idea what they are for.
public string unknown0;

View File

@@ -9,6 +9,11 @@ namespace LibBSP {
/// Class representing a group of <see cref="Entity"/> objects. Contains helpful methods to handle Entities in the <c>List</c>.
/// </summary>
[Serializable] public class Entities : Lump<Entity> {
/// <summary>
/// Initializes a new empty <see cref="Entities"/> object.
/// </summary>
public Entities() : base(null, default(LumpInfo)) { }
/// <summary>
/// Initializes a new instance of an <see cref="Entities"/> object copying a passed <c>IEnumerable</c> of <see cref="Entity"/> objects.
@@ -27,7 +32,7 @@ namespace LibBSP {
public Entities(int initialCapacity, BSP bsp = null, LumpInfo lumpInfo = default(LumpInfo)) : base(initialCapacity, bsp, lumpInfo) { }
/// <summary>
/// Initializes a new empty <see cref="Entities"/> object.
/// Initializes a new <see cref="Entities"/> object.
/// </summary>
/// <param name="bsp">The <see cref="BSP"/> this lump came from.</param>
/// <param name="lumpInfo">The <see cref="LumpInfo"/> associated with this lump.</param>

View File

@@ -1,273 +0,0 @@
#if !(UNITY_3_4 || UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_5_3_OR_NEWER || GODOT)
using System;
namespace LibBSP {
/// <summary>
/// Holds the data for a plane in 3D space in Hesse Normal Form.
/// </summary>
[Serializable] public struct Plane : IEquatable<Plane> {
private Vector3d _normal;
public double distance;
public Vector3d normal {
get { return _normal; }
set {
_normal = value;
_normal.Normalize();
}
}
/// <summary>
/// The <c>a</c> component of this <see cref="Plane"/>.
/// </summary>
public double a {
get {
return normal.x;
}
}
/// <summary>
/// The <c>b</c> component of this <see cref="Plane"/>.
/// </summary>
public double b {
get {
return normal.y;
}
}
/// <summary>
/// The <c>c</c> component of this <see cref="Plane"/>.
/// </summary>
public double c {
get {
return normal.z;
}
}
/// <summary>
/// This <see cref="Plane"/>, flipped over so the negative side is now the positive side, and vice versa.
/// </summary>
public Plane flipped {
get {
return new Plane(-normal, -distance);
}
}
/// <summary>
/// Creates a new <see cref="Plane"/> object using <c>float</c>s. The first three <c>float</c>s are the normal, and the last one is the distance.
/// </summary>
/// <param name="nums">Components of this <see cref="Plane"/>.</param>
/// <exception cref="ArgumentException">4 <c>float</c>s were not passed.</exception>
/// <exception cref="ArgumentNullException">The passed array was <c>null</c>.</exception>
public Plane(params float[] nums) {
if (nums == null) {
throw new ArgumentNullException();
}
if (nums.Length != 4) {
throw new ArgumentException("You must provide four numbers to generate a plane!");
}
_normal = new Vector3d(nums[0], nums[1], nums[2]);
_normal.Normalize();
distance = Convert.ToDouble(nums[3]);
}
/// <summary>
/// Creates a new <see cref="Plane"/> object using <c>double</c>s. The first three <c>double</c>s are the normal, and the last one is the distance.
/// </summary>
/// <param name="nums">Components of this <see cref="Plane"/>.</param>
/// <exception cref="ArgumentException">4 <c>double</c>s were not passed.</exception>
/// <exception cref="ArgumentNullException">The passed array was <c>null</c>.</exception>
public Plane(params double[] nums) {
if (nums == null) {
throw new ArgumentNullException();
}
if (nums.Length != 4) {
throw new ArgumentException("You must provide four numbers to generate a plane!");
}
_normal = new Vector3d(nums[0], nums[1], nums[2]);
_normal.Normalize();
distance = nums[3];
}
/// <summary>
/// Creates a new <see cref="Plane"/> object using a normal and distance.
/// </summary>
/// <param name="normal">Normal of this <see cref="Plane"/>.</param>
/// <param name="dist">Distance from the origin to this <see cref="Plane"/>.</param>
public Plane(Vector3d normal, double dist) {
_normal = new Vector3d(normal);
_normal.Normalize();
distance = dist;
}
/// <summary>
/// Creates a new <see cref="Plane"/> object using a normal and distance.
/// </summary>
/// <param name="normal">Normal of this <see cref="Plane"/>.</param>
/// <param name="dist">Distance from the origin to this <see cref="Plane"/>.</param>
public Plane(Vector3d normal, float dist) : this(normal, Convert.ToDouble(dist)) { }
/// <summary>
/// Creates a new <see cref="Plane"/> object by copying another <see cref="Plane"/>.
/// </summary>
/// <param name="copy"><see cref="Plane"/> to copy.</param>
public Plane(Plane copy) {
_normal = new Vector3d(copy.normal);
distance = copy.distance;
}
/// <summary>
/// Creates a new <see cref="Plane"/> object using a normal and a point on the <see cref="Plane"/>.
/// </summary>
/// <param name="normal">Normal of this <see cref="Plane"/>.</param>
/// <param name="point">A point on this <see cref="Plane"/>.</param>
public Plane(Vector3d normal, Vector3d point) {
_normal = normal;
_normal.Normalize();
distance = point * normal;
}
/// <summary>
/// Creates a new <see cref="Plane"/> object using three points on the <see cref="Plane"/>.
/// </summary>
/// <param name="point0">A point on the <see cref="Plane"/>.</param>
/// <exception cref="ArgumentNullException"><param name="points"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">3 <see cref="Vector3d"/>s were not passed.</exception>
public Plane(params Vector3d[] points) {
if (points == null) {
throw new ArgumentNullException();
}
if (points.Length < 3) {
throw new ArgumentException("Plane constructor was not given enough points to define a plane.");
}
_normal = ((points[0] - points[2]) ^ (points[0] - points[1]));
_normal.Normalize();
distance = points[0] * _normal;
}
#region IEquatable
/// <summary>
/// Determines whether this <see cref="Plane"/> is equal to another <c>object</c>.
/// </summary>
/// <param name="obj"><c>object</c> to compare to.</param>
/// <returns>Whether <paramref name="obj"/> is a <see cref="Plane"/> and is equal to this <see cref="Plane"/>.</returns>
public override bool Equals(object obj) {
if (ReferenceEquals(obj, null) || !GetType().IsAssignableFrom(obj.GetType())) { return false; }
return Equals((Plane)obj);
}
/// <summary>
/// Compares whether two <see cref="Plane"/>s are equal, or approximately equal.
/// </summary>
/// <param name="other">The <see cref="Plane"/> to compare to.</param>
/// <returns><c>true</c> if this <see cref="Plane"/> is parallel to, faces the same direction, and has the same distance as, the given <see cref="Plane"/>.</returns>
public bool Equals(Plane other) {
return (normal == other.normal && distance + 0.001 >= other.distance && distance - 0.001 <= other.distance);
}
/// <summary>
/// Generates a hash code for this instance based on instance data.
/// </summary>
/// <returns>The hash code for this instance.</returns>
public override int GetHashCode() {
return _normal.GetHashCode() ^ distance.GetHashCode();
}
/// <summary>
/// Compares whether two <see cref="Plane"/>s are equal, or approximately equal.
/// </summary>
/// <param name="other">The <see cref="Plane"/> to compare to.</param>
/// <returns><c>true</c> if this <see cref="Plane"/> is parallel to, faces the same direction, and has the same distance as, the given <see cref="Plane"/>.</returns>
public static bool operator ==(Plane p1, Plane p2) {
return p1.Equals(p2);
}
/// <summary>
/// Compares whether two <see cref="Plane"/>s are not equal, or approximately equal.
/// </summary>
/// <param name="other">The <see cref="Plane"/> to compare to.</param>
/// <returns><c>false</c> if this <see cref="Plane"/> is parallel to, faces the same direction, and has the same distance as, the given <see cref="Plane"/>.</returns>
public static bool operator !=(Plane p1, Plane p2) {
return !p1.Equals(p2);
}
#endregion
/// <summary>
/// Determines whether the given <see cref="Vector3d"/> is contained in this <see cref="Plane"/>.
/// </summary>
/// <param name="v">Point.</param>
/// <returns><c>true</c> if the <see cref="Vector3d"/> is contained in this <see cref="Plane"/>.</returns>
public bool Contains(Vector3d v) {
double distanceTo = GetDistanceToPoint(v);
return distanceTo < 0.001 && distanceTo > -0.001;
}
/// <summary>
/// Gets the signed distance from this <see cref="Plane"/> to a given point.
/// </summary>
/// <param name="to">Point to get the distance to.</param>
/// <returns>Signed distance from this <see cref="Plane"/> to the given point.</returns>
public double GetDistanceToPoint(Vector3d to) {
// Ax + By + Cz - d = DISTANCE = normDOTpoint - d
double normLength = Math.Pow(normal.x, 2) + Math.Pow(normal.y, 2) + Math.Pow(normal.z, 2);
if (Math.Abs(normLength - 1.00) > 0.01) {
normLength = Math.Sqrt(normLength);
}
return (normal.x * to.x + normal.y * to.y + normal.z * to.z - distance) / normLength;
}
/// <summary>
/// Is <paramref name="v"/> on the positive side of this <see cref="Plane"/>?
/// </summary>
/// <param name="v">Point to get the side for.</param>
/// <returns><c>true</c> if <paramref name="v"/> is on the positive side of this <see cref="Plane"/>.</returns>
public bool GetSide(Vector3d v) {
return GetDistanceToPoint(v) > 0;
}
/// <summary>
/// Flips this <see cref="Plane"/> to face the opposite direction.
/// </summary>
public void Flip() {
normal = -normal;
distance = -distance;
}
/// <summary>
/// Flips this <see cref="Plane"/> to face the opposite direction.
/// </summary>
public static Plane operator -(Plane flipMe) {
return new Plane(-flipMe.normal, -flipMe.distance);
}
/// <summary>
/// Gets a nicely formatted string representation of this <see cref="Plane"/>.
/// </summary>
/// <returns>A nicely formatted <c>string</c> representation of this <see cref="Plane"/>.</returns>
public override string ToString() {
return "(" + normal.ToString() + ") " + distance;
}
/// <summary>
/// Raycasts a <see cref="Ray"/> against this <see cref="Plane"/>.
/// </summary>
/// <param name="ray"><see cref="Ray"/> to raycast against.</param>
/// <param name="enter"><c>out</c> parameter that will contain the distance along <paramref name="ray"/> where the collision happened.</param>
/// <returns>
/// <c>true</c> and <paramref name="enter"/> is positive if <see cref="Ray"/> intersects this <see cref="Plane"/> in front of the ray,
/// <c>false</c> and <paramref name="enter"/> is negative if <see cref="Ray"/> intersects this <see cref="Plane"/> behind the ray,
/// <c>false</c> and <paramref name="enter"/> is 0 if the <see cref="Ray"/> is parallel to this <see cref="Plane"/>.
/// </returns>
public bool Raycast(Ray ray, out double enter) {
double denom = (Vector3d.Dot(ray.direction, normal));
if (denom > -0.005 && denom < 0.005) {
enter = 0;
return false;
}
enter = (-1 * (Vector3d.Dot(ray.origin, normal) + distance)) / denom;
return enter > 0;
}
}
}
#endif

View File

@@ -1,112 +0,0 @@
#if !(UNITY_3_4 || UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_5_3_OR_NEWER)
using System;
namespace LibBSP {
#if GODOT
using Vector3d = Godot.Vector3;
#endif
/// <summary>
/// A struct for a <see cref="Ray"/> defined by a starting point and a direction vector.
/// </summary>
public struct Ray : IEquatable<Ray> {
public Vector3d origin;
private Vector3d _direction;
public Vector3d direction {
get {
return _direction;
}
set {
#if GODOT
_direction = value.Normalized();
#else
_direction = value.normalized;
#endif
}
}
/// <summary>
/// Creates a new <see cref="Ray"/> object using the specified origin and direction.
/// </summary>
/// <param name="origin">Origin point of this <see cref="Ray"/>.</param>
/// <param name="direction">Direction vector of this <see cref="Ray"/>.</param>
public Ray(Vector3d origin, Vector3d direction) {
this.origin = origin;
#if GODOT
_direction = direction.Normalized();
#else
_direction = direction.normalized;
#endif
}
/// <summary>
/// Gets the point at <paramref name="distance"/> units along this <see cref="Ray"/>.
/// </summary>
/// <param name="distance">Distance of the point to get.</param>
/// <returns>The point at <paramref name="distance"/> units along this <see cref="Ray"/>.</returns>
public Vector3d GetPoint(double distance) {
return origin + ((float)distance * direction);
}
/// <summary>
/// Gets a nicely formatted <c>string</c> representation of this <see cref="Ray"/>.
/// </summary>
/// <returns>A nicely formatted <c>string</c> representation of this <see cref="Ray"/>.</returns>
public override string ToString() {
return string.Format("( {0}, {1} )", origin, direction);
}
#region IEquatable
/// <summary>
/// Determines whether this <see cref="Ray"/> is equivalent to another.
/// </summary>
/// <param name="r1">A <see cref="Ray"/> to compare.</param>
/// <param name="r2">A <see cref="Ray"/> to compare.</param>
/// <returns><c>true</c> if <paramref name="r1"/> and <paramref name="r2"/> have the same <see cref="Ray.origin"/> and <see cref="Ray.direction"/>.</returns>
public static bool operator ==(Ray r1, Ray r2) {
return r1.Equals(r2);
}
/// <summary>
/// Determines whether this <see cref="Ray"/> is not equivalent to another.
/// </summary>
/// <param name="r1">A <see cref="Ray"/> to compare.</param>
/// <param name="r2">A <see cref="Ray"/> to compare.</param>
/// <returns><c>true</c> if <paramref name="r1"/> and <paramref name="r2"/> don't have the same <see cref="Ray.origin"/> and <see cref="Ray.direction"/>.</returns>
public static bool operator !=(Ray r1, Ray r2) {
return !r1.Equals(r2);
}
/// <summary>
/// Determines whether this <see cref="Ray"/> is equivalent to another.
/// </summary>
/// <param name="other">The <see cref="Ray"/> to compare to.</param>
/// <returns><c>true</c> if this <see cref="Ray"/> and <paramref name="other"/> have the same <see cref="Ray.origin"/> and <see cref="Ray.direction"/>.</returns>
public bool Equals(Ray other) {
return origin.Equals(other.origin) && direction.Equals(other.direction);
}
/// <summary>
/// Determines whether this <see cref="Ray"/> is equivalent to another <c>object</c>.
/// </summary>
/// <param name="obj">The <c>object</c> to compare to.</param>
/// <returns><c>true</c> if <paramref name="obj"/> is a <see cref="Ray"/> and this <see cref="Ray"/> and <paramref name="obj"/> have the same <see cref="Ray.origin"/> and <see cref="Ray.direction"/>.</returns>
public override bool Equals(object obj) {
if (ReferenceEquals(obj, null) || !GetType().IsAssignableFrom(obj.GetType())) { return false; }
return Equals((Ray)obj);
}
/// <summary>
/// Generates a hash code for this instance based on instance data.
/// </summary>
/// <returns>The hash code for this instance.</returns>
public override int GetHashCode() {
return origin.GetHashCode() ^ direction.GetHashCode();
}
#endregion
}
}
#endif

View File

@@ -3,18 +3,21 @@
#endif
using System;
using System.Collections.Generic;
using System.Reflection;
namespace LibBSP {
#if UNITY
using Vector2d = UnityEngine.Vector2;
using Vector3d = UnityEngine.Vector3;
using Vector2 = UnityEngine.Vector2;
using Vector3 = UnityEngine.Vector3;
using Plane = UnityEngine.Plane;
#elif GODOT
using Vector2d = Godot.Vector2;
using Vector3d = Godot.Vector3;
using Vector2 = Godot.Vector2;
using Vector3 = Godot.Vector3;
using Plane = Godot.Plane;
#else
using Vector2 = System.Numerics.Vector2;
using Vector3 = System.Numerics.Vector3;
using Plane = System.Numerics.Plane;
#endif
/// <summary>
@@ -59,34 +62,34 @@ namespace LibBSP {
}
// No BSP format uses these so they are fields.
public Vector2d scale;
public double rotation;
public Vector2 scale;
public float rotation;
public Vector3d uAxis {
public Vector3 uAxis {
get {
return new Vector3d(BitConverter.ToSingle(Data, 0), BitConverter.ToSingle(Data, 4), BitConverter.ToSingle(Data, 8));
return new Vector3(BitConverter.ToSingle(Data, 0), BitConverter.ToSingle(Data, 4), BitConverter.ToSingle(Data, 8));
}
set {
value.GetBytes().CopyTo(Data, 0);
}
}
public Vector3d vAxis {
public Vector3 vAxis {
get {
return new Vector3d(BitConverter.ToSingle(Data, 16), BitConverter.ToSingle(Data, 20), BitConverter.ToSingle(Data, 24));
return new Vector3(BitConverter.ToSingle(Data, 16), BitConverter.ToSingle(Data, 20), BitConverter.ToSingle(Data, 24));
}
set {
value.GetBytes().CopyTo(Data, 16);
}
}
public Vector2d translation {
public Vector2 translation {
get {
return new Vector2d(BitConverter.ToSingle(Data, 12), BitConverter.ToSingle(Data, 28));
return new Vector2(BitConverter.ToSingle(Data, 12), BitConverter.ToSingle(Data, 28));
}
set {
BitConverter.GetBytes((float)value.x).CopyTo(Data, 12);
BitConverter.GetBytes((float)value.y).CopyTo(Data, 28);
BitConverter.GetBytes(value.X()).CopyTo(Data, 12);
BitConverter.GetBytes(value.Y()).CopyTo(Data, 28);
}
}
@@ -219,7 +222,7 @@ namespace LibBSP {
Data = data;
Parent = parent;
scale = new Vector2d(1, 1);
scale = new Vector2(1, 1);
rotation = 0;
}
@@ -233,7 +236,7 @@ namespace LibBSP {
/// <param name="flags">The flags for this <see cref="TextureInfo"/>.</param>
/// <param name="texture">Index into the texture list for the texture this <see cref="TextureInfo"/> uses.</param>
/// <param name="rotation">Rotation of the texutre axes.</param>
public TextureInfo(Vector3d uAxis, Vector3d vAxis, Vector2d translation, Vector2d scale, int flags, int texture, double rotation) {
public TextureInfo(Vector3 uAxis, Vector3 vAxis, Vector2 translation, Vector2 scale, int flags, int texture, float rotation) {
Data = new byte[40];
Parent = null;
@@ -251,9 +254,9 @@ namespace LibBSP {
/// </summary>
/// <param name="p"><see cref="Plane"/> of the surface.</param>
/// <returns>The best matching texture axes for the given <see cref="Plane"/>.</returns>
public static Vector3d[] TextureAxisFromPlane(Plane p) {
public static Vector3[] TextureAxisFromPlane(Plane p) {
int bestaxis = p.BestAxis();
Vector3d[] newAxes = new Vector3d[2];
Vector3[] newAxes = new Vector3[2];
newAxes[0] = PlaneExtensions.baseAxes[bestaxis * 3 + 1];
newAxes[1] = PlaneExtensions.baseAxes[bestaxis * 3 + 2];
return newAxes;

View File

@@ -1,436 +0,0 @@
#if !(UNITY_3_4 || UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_5_3_OR_NEWER || GODOT)
using System;
using System.Collections;
using System.Collections.Generic;
namespace LibBSP {
/// <summary>
/// Holds two <c>double</c>s representing a 2-dimensional vector.
/// </summary>
[Serializable] public struct Vector2d : IEquatable<Vector2d>, IEnumerable, IEnumerable<double> {
/// <summary>Returns <see cref="Vector2d"/>(NaN, NaN).</summary>
public static Vector2d undefined { get { return new Vector2d(System.Double.NaN, System.Double.NaN); } }
/// <summary>Returns <see cref="Vector2d"/>(1, 0).</summary>
public static Vector2d right { get { return new Vector2d(1, 0); } }
/// <summary>Returns <see cref="Vector2d"/>(0, 1).</summary>
public static Vector2d up { get { return new Vector2d(0, 1); } }
/// <summary>Returns <see cref="Vector2d"/>(-1, 0).</summary>
public static Vector2d left { get { return new Vector2d(-1, 0); } }
/// <summary>Returns <see cref="Vector2d"/>(0, -1).</summary>
public static Vector2d down { get { return new Vector2d(0, -1); } }
/// <summary>Returns <see cref="Vector2d"/>(0, 0).</summary>
public static Vector2d zero { get { return new Vector2d(0, 0); } }
/// <summary>Returns <see cref="Vector2d"/>(1, 1).</summary>
public static Vector2d one { get { return new Vector2d(1, 1); } }
public double x;
public double y;
/// <summary>
/// Gets or sets a component using an indexer, x=0, y=1.
/// </summary>
/// <param name="index">Component to get or set.</param>
/// <returns>Component.</returns>
/// <exception cref="IndexOutOfRangeException"><paramref name="index"/> was negative or greater than 1.</exception>
public double this[int index] {
get {
switch (index) {
case 0: {
return x;
}
case 1: {
return y;
}
default: {
throw new IndexOutOfRangeException();
}
}
}
set {
switch (index) {
case 0: {
x = value;
break;
}
case 1: {
y = value;
break;
}
default: {
throw new IndexOutOfRangeException();
}
}
}
}
/// <summary>
/// Gets the magnitude of this <see cref="Vector2d"/>, or its distance from (0, 0).
/// </summary>
public double magnitude { get { return Math.Sqrt(sqrMagnitude); } }
/// <summary>
/// Gets the magnitude of this <see cref="Vector2d"/> squared. This is useful for when you are comparing the lengths of two vectors
/// but don't need to know the exact length, and avoids calculating a square root.
/// </summary>
public double sqrMagnitude { get { return System.Math.Pow(x, 2) + System.Math.Pow(y, 2); } }
/// <summary>
/// Gets the normalized version of this <see cref="Vector2d"/> (unit vector with the same direction).
/// </summary>
public Vector2d normalized {
get {
if (this == Vector2d.zero) { return Vector2d.zero; }
double magnitude = this.magnitude;
return new Vector2d(x / magnitude, y / magnitude);
}
}
/// <summary>
/// Creates a new <see cref="Vector2d"/> object using elements in the passed array as components.
/// </summary>
/// <param name="point">Components of the vector.</param>
public Vector2d(params float[] point) {
if (point == null) {
throw new ArgumentNullException();
}
x = 0;
y = 0;
if (point.Length == 2) {
x = Convert.ToDouble(point[0]);
y = Convert.ToDouble(point[1]);
} else if (point.Length == 1) {
x = Convert.ToDouble(point[0]);
}
}
/// <summary>
/// Creates a new <see cref="Vector2d"/> object using elements in the passed array as components.
/// </summary>
/// <param name="point">Components of the vector.</param>
public Vector2d(params double[] point) {
if (point == null) {
throw new ArgumentNullException();
}
x = 0;
y = 0;
if (point.Length == 2) {
x = point[0];
y = point[1];
} else if (point.Length == 1) {
x = point[0];
}
}
/// <summary>
/// Creates a new <see cref="Vector2d"/> object using elements in the passed array as components.
/// </summary>
/// <param name="point">Components of the vector.</param>
public Vector2d(params int[] point) {
if (point == null) {
throw new ArgumentNullException();
}
x = 0;
y = 0;
if (point.Length == 2) {
x = Convert.ToDouble(point[0]);
y = Convert.ToDouble(point[1]);
} else if (point.Length == 1) {
x = Convert.ToDouble(point[0]);
}
}
/// <summary>
/// Crates a new <see cref="Vector2d"/> instance using the components from the supplied <see cref="Vector2d"/>.
/// </summary>
/// <param name="vector">Vector to copy components from.</param>
public Vector2d(Vector2d vector) {
x = vector.x;
y = vector.y;
}
/// <summary>
/// Adds two vectors together componentwise. This operation is commutative.
/// </summary>
/// <param name="v1">First vector to add.</param>
/// <param name="v2">Second vector to add.</param>
/// <returns>The resulting vector.</returns>
public static Vector2d operator +(Vector2d v1, Vector2d v2) {
return Add(v1, v2);
}
/// <summary>
/// Adds two vectors together componentwise. This operation is commutative.
/// </summary>
/// <param name="v1">First vector to add.</param>
/// <param name="v2">Second vector to add.</param>
/// <returns>The resulting vector.</returns>
public static Vector2d Add(Vector2d v1, Vector2d v2) {
return new Vector2d(v1.x + v2.x, v1.y + v2.y);
}
/// <summary>
/// Subtracts one vector from another. This operation is NOT commutative.
/// </summary>
/// <param name="v1">Vector to subtract from.</param>
/// <param name="v2">Vector to subtract.</param>
/// <returns>Difference from <paramref name="v1"/> to <paramref name="v2"/>.</returns>
public static Vector2d operator -(Vector2d v1, Vector2d v2) {
return Subtract(v1, v2);
}
/// <summary>
/// Subtracts one vector from another. This operation is NOT commutative.
/// </summary>
/// <param name="v1">Vector to subtract from.</param>
/// <param name="v2">Vector to subtract.</param>
/// <returns>Difference from <paramref name="v1"/> to <paramref name="v2"/>.</returns>
public static Vector2d Subtract(Vector2d v1, Vector2d v2) {
return new Vector2d(v1.x - v2.x, v1.y - v2.y);
}
/// <summary>
/// Returns the negative of this vector. Equivalent to (0, 0) - <paramref name="v1"/>.
/// </summary>
/// <param name="v1">Vector to negate.</param>
/// <returns><paramref name="v1"/> with all components negated.</returns>
public static Vector2d operator -(Vector2d v1) {
return Negate(v1);
}
/// <summary>
/// Returns the negative of this vector. Equivalent to (0, 0) - <paramref name="v1"/>.
/// </summary>
/// <param name="v1">Vector to negate.</param>
/// <returns><paramref name="v1"/> with all components negated.</returns>
public static Vector2d Negate(Vector2d v1) {
return new Vector2d(-v1.x, -v1.y);
}
/// <summary>
/// Scalar multiplication. Multiplies all components of <paramref name="v1"/> by <paramref name="scalar"/> and returns the result.
/// </summary>
/// <param name="v1">Vector to scale.</param>
/// <param name="scalar">Scalar.</param>
/// <returns>Resulting Vector.</returns>
public static Vector2d operator *(Vector2d v1, double scalar) {
return Scale(v1, scalar);
}
/// <summary>
/// Scalar multiplication. Multiplies all components of <paramref name="v1"/> by <paramref name="scalar"/> and returns the result.
/// </summary>
/// <param name="scalar">Scalar.</param>
/// <param name="v1">Vector to scale.</param>
/// <returns>Resulting Vector.</returns>
public static Vector2d operator *(double scalar, Vector2d v1) {
return Scale(v1, scalar);
}
/// <summary>
/// Scalar multiplication. Multiplies all components of <paramref name="v1"/> by <paramref name="scalar"/> and returns the result.
/// </summary>
/// <param name="v1">Vector to scale.</param>
/// <param name="scalar">Scalar.</param>
/// <returns>Resulting Vector.</returns>
public static Vector2d Scale(Vector2d v1, double scalar) {
return new Vector2d(v1.x * scalar, v1.y * scalar);
}
/// <summary>
/// Scalar multiplication. Multiplies all components of <paramref name="v1"/> by <paramref name="scalar"/> and returns the result.
/// </summary>
/// <param name="scalar">Scalar.</param>
/// <param name="v1">Vector to scale.</param>
/// <returns>Resulting Vector.</returns>
public static Vector2d Scale(double scalar, Vector2d v1) {
return Scale(v1, scalar);
}
/// <summary>
/// Multiplies two vectors together componentwise. This operation is commutative.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns>Resulting vector when the passed vectors' components are multiplied.</returns>
public static Vector2d Scale(Vector2d v1, Vector2d v2) {
return new Vector2d(v1.x * v2.x, v1.y * v2.y);
}
/// <summary>
/// Vector dot product. This operation is commutative.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns>Dot product of these two vectors.</returns>
public static double operator *(Vector2d v1, Vector2d v2) {
return Dot(v1, v2);
}
/// <summary>
/// Vector dot product. This operation is commutative.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns>Dot product of these two vectors.</returns>
public static double Dot(Vector2d v1, Vector2d v2) {
return v1.x * v2.x + v1.y * v2.y;
}
/// <summary>
/// Scalar division. Divides all components of <paramref name="v1"/> by <paramref name="divisor"/> and returns the result.
/// </summary>
/// <param name="v1">Vector to divide.</param>
/// <param name="divisor">Divisor.</param>
/// <returns>Resulting vector when all components of <paramref name="v1"/> are divided by <paramref name="divisor"/>.</returns>
public static Vector2d operator /(Vector2d v1, double divisor) {
return Scale(v1, 1.0 / divisor);
}
#region IEquatable
/// <summary>
/// Equivalency. Returns <c>true</c> if the components of two vectors are equal or approximately equal.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns><c>true</c> if the components of two vectors are equal or approximately equal.</returns>
public static bool operator ==(Vector2d v1, Vector2d v2) {
return v1.Equals(v2);
}
/// <summary>
/// Non-Equivalency. Returns <c>true</c> if the components of two vectors are not equal or approximately equal.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns><c>true</c> if the components of two vectors are not equal or approximately equal.</returns>
public static bool operator !=(Vector2d v1, Vector2d v2) {
return !v1.Equals(v2);
}
/// <summary>
/// Equivalency. Returns <c>true</c> if the components of two vectors are equal or approximately equal.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns><c>true</c> if the components of two vectors are equal or approximately equal.</returns>
public bool Equals(Vector2d other) {
return (Math.Abs(x - other.x) < 0.001 && Math.Abs(y - other.y) < 0.001);
}
/// <summary>
/// Equivalency. Returns <c>true</c> if the other object is a vector, and the components of two vectors are equal or approximately equal.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns><c>true</c> if the other object is a vector, and the components of two vectors are equal or approximately equal.</returns>
public override bool Equals(object obj) {
if (object.ReferenceEquals(obj, null) || !GetType().IsAssignableFrom(obj.GetType())) { return false; }
return Equals((Vector2d)obj);
}
/// <summary>
/// Generates a hash code for this instance based on instance data.
/// </summary>
/// <returns>The hash code for this instance.</returns>
public override int GetHashCode() {
return x.GetHashCode() ^ y.GetHashCode();
}
#endregion
/// <summary>
/// Calculates the distance from this vector to another.
/// </summary>
/// <param name="to">Vector to calculate distance to.</param>
/// <returns>Distance from this vector to the passed vector.</returns>
public double Distance(Vector2d to) {
return (this - to).magnitude;
}
/// <summary>
/// Gets a human-readable <c>string</c> representation of this vector.
/// </summary>
/// <returns>Human-readable <c>string</c> representation of this vector.</returns>
public override string ToString() {
return string.Format("( {0} , {1} )", x.ToString(), y.ToString());
}
/// <summary>
/// Changes this vector to its normalized version (it will have a magnitude of 1).
/// </summary>
public void Normalize() {
if (this == Vector2d.zero) { return; }
double magnitude = this.magnitude;
x /= magnitude;
y /= magnitude;
}
/// <summary>
/// Gets the area of the triangle defined by three points using Heron's formula.
/// </summary>
/// <param name="p1">First vertex of triangle.</param>
/// <param name="p2">Second vertex of triangle.</param>
/// <param name="p3">Third vertex of triangle.</param>
/// <returns>Area of the triangle defined by these three vertices.</returns>
public static double TriangleArea(Vector3d p1, Vector3d p2, Vector3d p3) {
return Math.Sqrt(SqrTriangleArea(p1, p2, p3)) / 4.0;
}
/// <summary>
/// Gets the square of the area of the triangle defined by three points. This is useful when simply comparing two areas when you don't need to know exactly what the area is.
/// </summary>
/// <param name="p1">First vertex of triangle.</param>
/// <param name="p2">Second vertex of triangle.</param>
/// <param name="p3">Third vertex of triangle.</param>
/// <returns>Square of the area of the triangle defined by these three vertices.</returns>
public static double SqrTriangleArea(Vector3d p1, Vector3d p2, Vector3d p3) {
double a = p1.Distance(p2);
double b = p1.Distance(p3);
double c = p2.Distance(p3);
return 4.0 * a * a * b * b - Math.Pow((a * a) + (b * b) - (c * c), 2);
}
#region IEnumerable
/// <summary>
/// Allows enumeration through the components of a <see cref="Vector2d"/> using a foreach loop.
/// </summary>
public IEnumerator<double> GetEnumerator() {
yield return x;
yield return y;
}
/// <summary>
/// Allows enumeration through the components of a <see cref="Vector2d"/> using a foreach loop, auto-boxed version.
/// </summary>
/// <remarks>
/// This foreach loop will look like foreach(object o in Vector2d). This will auto-box the doubles in System.Double
/// objects, allocating memory on the heap which the garbage collector will have to free later. In general, iterate
/// through doubles rather than objects.
/// </remarks>
IEnumerator IEnumerable.GetEnumerator() {
yield return x;
yield return y;
}
#endregion
/// <summary>
/// Implicitly converts this <see cref="Vector2d"/> into a <see cref="Vector3d"/>. This will be called when <c>Vector3d v3 = v2</c> is used.
/// </summary>
/// <param name="v"><see cref="Vector2d"/> to convert.</param>
/// <returns>The input vector as a <see cref="Vector3d"/>, Z component set to 0.</returns>
public static implicit operator Vector3d(Vector2d v) {
return new Vector3d(v.x, v.y, 0);
}
/// <summary>
/// Implicitly converts this <see cref="Vector2d"/> into a <see cref="Vector4d"/>. This will be called when <c>Vector4d v4 = v2</c> is used.
/// </summary>
/// <param name="v"><see cref="Vector2d"/> to convert.</param>
/// <returns>The input vector as a <see cref="Vector4d"/>, Z and W components set to 0.</returns>
public static implicit operator Vector4d(Vector2d v) {
return new Vector4d(v.x, v.y, 0, 0);
}
}
}
#endif

View File

@@ -1,497 +0,0 @@
#if !(UNITY_3_4 || UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_5_3_OR_NEWER || GODOT)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
namespace LibBSP {
/// <summary>
/// Holds three <c>double</c>s representing a 3-dimensional vector.
/// </summary>
[Serializable] public struct Vector3d : IEquatable<Vector3d>, IEnumerable, IEnumerable<double> {
/// <summary>Returns <see cref="Vector3d"/>(NaN, NaN, NaN).</summary>
public static Vector3d undefined { get { return new Vector3d(System.Double.NaN, System.Double.NaN, System.Double.NaN); } }
/// <summary>Returns <see cref="Vector3d"/>(1, 0, 0).</summary>
public static Vector3d right { get { return new Vector3d(1, 0, 0); } }
/// <summary>Returns <see cref="Vector3d"/>(0, 1, 0).</summary>
public static Vector3d forward { get { return new Vector3d(0, 1, 0); } }
/// <summary>Returns <see cref="Vector3d"/>(0, 0, 1).</summary>
public static Vector3d up { get { return new Vector3d(0, 0, 1); } }
/// <summary>Returns <see cref="Vector3d"/>(-1, 0, 0).</summary>
public static Vector3d left { get { return new Vector3d(-1, 0, 0); } }
/// <summary>Returns <see cref="Vector3d"/>(0, -1, 0).</summary>
public static Vector3d back { get { return new Vector3d(0, -1, 0); } }
/// <summary>Returns <see cref="Vector3d"/>(0, 0, -1).</summary>
public static Vector3d down { get { return new Vector3d(0, 0, -1); } }
/// <summary>Returns <see cref="Vector3d"/>(0, 0, 0).</summary>
public static Vector3d zero { get { return new Vector3d(0, 0, 0); } }
/// <summary>Returns <see cref="Vector3d"/>(1, 1, 1).</summary>
public static Vector3d one { get { return new Vector3d(1, 1, 1); } }
public double x;
public double y;
public double z;
/// <summary>
/// Gets or sets a component using an indexer, x=0, y=1, z=2.
/// </summary>
/// <param name="index">Component to get or set.</param>
/// <returns>Component.</returns>
/// <exception cref="IndexOutOfRangeException"><paramref name="index"/> was negative or greater than 2.</exception>
public double this[int index] {
get {
switch (index) {
case 0: {
return x;
}
case 1: {
return y;
}
case 2: {
return z;
}
default: {
throw new IndexOutOfRangeException();
}
}
}
set {
switch (index) {
case 0: {
x = value;
break;
}
case 1: {
y = value;
break;
}
case 2: {
z = value;
break;
}
default: {
throw new IndexOutOfRangeException();
}
}
}
}
/// <summary>
/// Gets the magnitude of this <see cref="Vector3d"/>, or its distance from (0, 0, 0).
/// </summary>
public double magnitude { get { return Math.Sqrt(sqrMagnitude); } }
/// <summary>
/// Gets the magnitude of this <see cref="Vector3d"/> squared. This is useful for when you are comparing the lengths of two vectors
/// but don't need to know the exact length, and avoids calculating a square root.
/// </summary>
public double sqrMagnitude { get { return System.Math.Pow(x, 2) + System.Math.Pow(y, 2) + System.Math.Pow(z, 2); } }
/// <summary>
/// Gets the normalized version of this <see cref="Vector3d"/> (unit vector with the same direction).
/// </summary>
public Vector3d normalized {
get {
if (this == Vector3d.zero) { return Vector3d.zero; }
double magnitude = this.magnitude;
return new Vector3d(x / magnitude, y / magnitude, z / magnitude);
}
}
/// <summary>
/// Creates a new <see cref="Vector3d"/> object using elements in the passed array as components.
/// </summary>
/// <param name="point">Components of the vector.</param>
public Vector3d(params float[] point) {
if (point == null) {
throw new ArgumentNullException();
}
x = 0;
y = 0;
z = 0;
if (point.Length >= 3) {
x = Convert.ToDouble(point[0]);
y = Convert.ToDouble(point[1]);
z = Convert.ToDouble(point[2]);
} else if (point.Length == 2) {
x = Convert.ToDouble(point[0]);
y = Convert.ToDouble(point[1]);
} else if (point.Length == 1) {
x = Convert.ToDouble(point[0]);
}
}
/// <summary>
/// Creates a new <see cref="Vector3d"/> object using elements in the passed array as components.
/// </summary>
/// <param name="point">Components of the vector.</param>
public Vector3d(params double[] point) {
if (point == null) {
throw new ArgumentNullException();
}
x = 0;
y = 0;
z = 0;
if (point.Length >= 3) {
x = point[0];
y = point[1];
z = point[2];
} else if (point.Length == 2) {
x = point[0];
y = point[1];
} else if (point.Length == 1) {
x = point[0];
}
}
/// <summary>
/// Creates a new <see cref="Vector3d"/> object using elements in the passed array as components.
/// </summary>
/// <param name="point">Components of the vector.</param>
public Vector3d(params int[] point) {
if (point == null) {
throw new ArgumentNullException();
}
x = 0;
y = 0;
z = 0;
if (point.Length >= 3) {
x = Convert.ToDouble(point[0]);
y = Convert.ToDouble(point[1]);
z = Convert.ToDouble(point[2]);
} else if (point.Length == 2) {
x = Convert.ToDouble(point[0]);
y = Convert.ToDouble(point[1]);
} else if (point.Length == 1) {
x = Convert.ToDouble(point[0]);
}
}
/// <summary>
/// Crates a new <see cref="Vector3d"/> instance using the components from the supplied <see cref="Vector3d"/>.
/// </summary>
/// <param name="vector">Vector to copy components from.</param>
public Vector3d(Vector3d vector) {
x = vector.x;
y = vector.y;
z = vector.z;
}
/// <summary>
/// Adds two vectors together componentwise. This operation is commutative.
/// </summary>
/// <param name="v1">First vector to add.</param>
/// <param name="v2">Second vector to add.</param>
/// <returns>The resulting vector.</returns>
public static Vector3d operator +(Vector3d v1, Vector3d v2) {
return Add(v1, v2);
}
/// <summary>
/// Adds two vectors together componentwise. This operation is commutative.
/// </summary>
/// <param name="v1">First vector to add.</param>
/// <param name="v2">Second vector to add.</param>
/// <returns>The resulting vector.</returns>
public static Vector3d Add(Vector3d v1, Vector3d v2) {
return new Vector3d(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
}
/// <summary>
/// Subtracts one vector from another. This operation is NOT commutative.
/// </summary>
/// <param name="v1">Vector to subtract from.</param>
/// <param name="v2">Vector to subtract.</param>
/// <returns>Difference from <paramref name="v1"/> to <paramref name="v2"/>.</returns>
public static Vector3d operator -(Vector3d v1, Vector3d v2) {
return Subtract(v1, v2);
}
/// <summary>
/// Subtracts one vector from another. This operation is NOT commutative.
/// </summary>
/// <param name="v1">Vector to subtract from.</param>
/// <param name="v2">Vector to subtract.</param>
/// <returns>Difference from <paramref name="v1"/> to <paramref name="v2"/>.</returns>
public static Vector3d Subtract(Vector3d v1, Vector3d v2) {
return new Vector3d(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
}
/// <summary>
/// Returns the negative of this vector. Equivalent to (0, 0, 0) - <paramref name="v1"/>.
/// </summary>
/// <param name="v1">Vector to negate.</param>
/// <returns><paramref name="v1"/> with all components negated.</returns>
public static Vector3d operator -(Vector3d v1) {
return Negate(v1);
}
/// <summary>
/// Returns the negative of this vector. Equivalent to (0, 0, 0) - <paramref name="v1"/>.
/// </summary>
/// <param name="v1">Vector to negate.</param>
/// <returns><paramref name="v1"/> with all components negated.</returns>
public static Vector3d Negate(Vector3d v1) {
return new Vector3d(-v1.x, -v1.y, -v1.z);
}
/// <summary>
/// Scalar multiplication. Multiplies all components of <paramref name="v1"/> by <paramref name="scalar"/> and returns the result.
/// </summary>
/// <param name="v1">Vector to scale.</param>
/// <param name="scalar">Scalar.</param>
/// <returns>Resulting Vector.</returns>
public static Vector3d operator *(Vector3d v1, double scalar) {
return Scale(v1, scalar);
}
/// <summary>
/// Scalar multiplication. Multiplies all components of <paramref name="v1"/> by <paramref name="scalar"/> and returns the result.
/// </summary>
/// <param name="scalar">Scalar.</param>
/// <param name="v1">Vector to scale.</param>
/// <returns>Resulting Vector.</returns>
public static Vector3d operator *(double scalar, Vector3d v1) {
return Scale(v1, scalar);
}
/// <summary>
/// Scalar multiplication. Multiplies all components of <paramref name="v1"/> by <paramref name="scalar"/> and returns the result.
/// </summary>
/// <param name="v1">Vector to scale.</param>
/// <param name="scalar">Scalar.</param>
/// <returns>Resulting Vector.</returns>
public static Vector3d Scale(Vector3d v1, double scalar) {
return new Vector3d(v1.x * scalar, v1.y * scalar, v1.z * scalar);
}
/// <summary>
/// Scalar multiplication. Multiplies all components of <paramref name="v1"/> by <paramref name="scalar"/> and returns the result.
/// </summary>
/// <param name="scalar">Scalar.</param>
/// <param name="v1">Vector to scale.</param>
/// <returns>Resulting Vector.</returns>
public static Vector3d Scale(double scalar, Vector3d v1) {
return Scale(v1, scalar);
}
/// <summary>
/// Multiplies two vectors together componentwise. This operation is commutative.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns>Resulting vector when the passed vectors' components are multiplied.</returns>
public static Vector3d Scale(Vector3d v1, Vector3d v2) {
return new Vector3d(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z);
}
/// <summary>
/// Vector dot product. This operation is commutative.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns>Dot product of these two vectors.</returns>
public static double operator *(Vector3d v1, Vector3d v2) {
return Dot(v1, v2);
}
/// <summary>
/// Vector dot product. This operation is commutative.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns>Dot product of these two vectors.</returns>
public static double Dot(Vector3d v1, Vector3d v2) {
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}
/// <summary>
/// Vector cross product. This operation is NOT commutative.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns>Cross product of these two vectors. Can be thought of as the normal to the plane defined by these two vectors.</returns>
public static Vector3d operator ^(Vector3d v1, Vector3d v2) {
return Cross(v1, v2);
}
/// <summary>
/// Vector cross product. This operation is NOT commutative.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns>Cross product of these two vectors. Can be thought of as the normal to the plane defined by these two vectors.</returns>
public static Vector3d Cross(Vector3d v1, Vector3d v2) {
return new Vector3d(v1.y * v2.z - v2.y * v1.z, v2.x * v1.z - v1.x * v2.z, v1.x * v2.y - v2.x * v1.y);
}
/// <summary>
/// Scalar division. Divides all components of <paramref name="v1"/> by <paramref name="divisor"/> and returns the result.
/// </summary>
/// <param name="v1">Vector to divide.</param>
/// <param name="divisor">Divisor.</param>
/// <returns>Resulting vector when all components of <paramref name="v1"/> are divided by <paramref name="divisor"/>.</returns>
public static Vector3d operator /(Vector3d v1, double divisor) {
return Scale(v1, 1.0 / divisor);
}
#region IEquatable
/// <summary>
/// Equivalency. Returns <c>true</c> if the components of two vectors are equal or approximately equal.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns><c>true</c> if the components of two vectors are equal or approximately equal.</returns>
public static bool operator ==(Vector3d v1, Vector3d v2) {
return v1.Equals(v2);
}
/// <summary>
/// Non-Equivalency. Returns <c>true</c> if the components of two vectors are not equal or approximately equal.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns><c>true</c> if the components of two vectors are not equal or approximately equal.</returns>
public static bool operator !=(Vector3d v1, Vector3d v2) {
return !v1.Equals(v2);
}
/// <summary>
/// Equivalency. Returns <c>true</c> if the components of two vectors are equal or approximately equal.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns><c>true</c> if the components of two vectors are equal or approximately equal.</returns>
public bool Equals(Vector3d other) {
return (Math.Abs(x - other.x) < 0.001 && Math.Abs(y - other.y) < 0.001 && Math.Abs(z - other.z) < 0.001);
}
/// <summary>
/// Equivalency. Returns <c>true</c> if the other object is a vector, and the components of two vectors are equal or approximately equal.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns><c>true</c> if the other object is a vector, and the components of two vectors are equal or approximately equal.</returns>
public override bool Equals(object obj) {
if (object.ReferenceEquals(obj, null) || !GetType().IsAssignableFrom(obj.GetType())) { return false; }
return Equals((Vector3d)obj);
}
/// <summary>
/// Generates a hash code for this instance based on instance data.
/// </summary>
/// <returns>The hash code for this instance.</returns>
public override int GetHashCode() {
return x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode();
}
#endregion
/// <summary>
/// Calculates the distance from this vector to another.
/// </summary>
/// <param name="to">Vector to calculate distance to.</param>
/// <returns>Distance from this vector to the passed vector.</returns>
public double Distance(Vector3d to) {
return (this - to).magnitude;
}
/// <summary>
/// Gets a human-readable <c>string</c> representation of this vector.
/// </summary>
/// <returns>Human-readable <c>string</c> representation of this vector.</returns>
public override string ToString() {
return string.Format("( {0} , {1} , {2} )", x.ToString(), y.ToString(), z.ToString());
}
/// <summary>
/// Changes this vector to its normalized version (it will have a magnitude of 1).
/// </summary>
public void Normalize() {
if (this == Vector3d.zero) { return; }
double magnitude = this.magnitude;
x /= magnitude;
y /= magnitude;
z /= magnitude;
}
/// <summary>
/// Gets the area of the triangle defined by three points using Heron's formula.
/// </summary>
/// <param name="p1">First vertex of triangle.</param>
/// <param name="p2">Second vertex of triangle.</param>
/// <param name="p3">Third vertex of triangle.</param>
/// <returns>Area of the triangle defined by these three vertices.</returns>
public static double TriangleArea(Vector3d p1, Vector3d p2, Vector3d p3) {
return Math.Sqrt(SqrTriangleArea(p1, p2, p3)) / 4.0;
}
/// <summary>
/// Gets the square of the area of the triangle defined by three points. This is useful when simply comparing two areas when you don't need to know exactly what the area is.
/// </summary>
/// <param name="p1">First vertex of triangle.</param>
/// <param name="p2">Second vertex of triangle.</param>
/// <param name="p3">Third vertex of triangle.</param>
/// <returns>Square of the area of the triangle defined by these three vertices.</returns>
public static double SqrTriangleArea(Vector3d p1, Vector3d p2, Vector3d p3) {
double a = p1.Distance(p2);
double b = p1.Distance(p3);
double c = p2.Distance(p3);
return 4.0 * a * a * b * b - Math.Pow((a * a) + (b * b) - (c * c), 2);
}
#region IEnumerable
/// <summary>
/// Allows enumeration through the components of a <see cref="Vector3d"/> using a foreach loop.
/// </summary>
public IEnumerator<double> GetEnumerator() {
yield return x;
yield return y;
yield return z;
}
/// <summary>
/// Allows enumeration through the components of a <see cref="Vector3d"/> using a foreach loop, auto-boxed version.
/// </summary>
/// <remarks>
/// This foreach loop will look like foreach(object o in Vector3d). This will auto-box the doubles in System.Double
/// objects, allocating memory on the heap which the garbage collector will have to free later. In general, iterate
/// through doubles rather than objects.
/// </remarks>
IEnumerator IEnumerable.GetEnumerator() {
yield return x;
yield return y;
yield return z;
}
#endregion
/// <summary>
/// Implicitly converts this <see cref="Vector3d"/> into a <see cref="Vector2d"/>. This will be called when <c>Vector2d v2 = v3</c> is used.
/// </summary>
/// <param name="v"><see cref="Vector3d"/> to convert.</param>
/// <returns>The input vector as a <see cref="Vector2d"/>, Z component discarded.</returns>
public static implicit operator Vector2d(Vector3d v) {
return new Vector2d(v.x, v.y);
}
/// <summary>
/// Implicitly converts this <see cref="Vector3d"/> into a <see cref="Vector4d"/>. This will be called when <c>Vector4d v4 = v3</c> is used.
/// </summary>
/// <param name="v"><see cref="Vector3d"/> to convert.</param>
/// <returns>The input vector as a <see cref="Vector4d"/>, W component set to 0.</returns>
public static implicit operator Vector4d(Vector3d v) {
return new Vector4d(v.x, v.y, v.z, 0);
}
/// <summary>
/// Implicitly converts this <see cref="Vector3d"/> into a <c>Color</c> by interpreting (x, y, z) as (r, g, b) respectively, and alpha set to 100%.
/// </summary>
/// <param name="v"><see cref="Vector3d"/> to convert.</param>
/// <returns>This <see cref="Vector3d"/> in a <c>Color</c> object interpreted as RGB.</returns>
public static implicit operator Color(Vector3d v) {
return ColorExtensions.FromArgb(255, (int)Math.Max(v.x, 255), (int)Math.Max(v.y, 255), (int)Math.Max(v.z, 255));
}
}
}
#endif

View File

@@ -1,496 +0,0 @@
#if !(UNITY_3_4 || UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_5_3_OR_NEWER || GODOT)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
namespace LibBSP {
/// <summary>
/// Holds four <c>double</c>s representing a 4-dimensional vector.
/// </summary>
[Serializable] public struct Vector4d : IEquatable<Vector4d>, IEnumerable, IEnumerable<double> {
/// <summary>Returns <see cref="Vector4d"/>(NaN, NaN, NaN, NaN).</summary>
public static Vector4d undefined { get { return new Vector4d(System.Double.NaN, System.Double.NaN, System.Double.NaN, System.Double.NaN); } }
/// <summary>Returns <see cref="Vector4d"/>(0, 0, 0, 0).</summary>
public static Vector4d zero { get { return new Vector4d(0, 0, 0, 0); } }
/// <summary>Returns <see cref="Vector4d"/>(1, 1, 1, 1).</summary>
public static Vector4d one { get { return new Vector4d(1, 1, 1, 1); } }
public double x;
public double y;
public double z;
public double w;
/// <summary>
/// Gets or sets a component using an indexer, x=0, y=1, z=2, w=3.
/// </summary>
/// <param name="index">Component to get or set.</param>
/// <returns>Component.</returns>
/// <exception cref="IndexOutOfRangeException"><paramref name="index"/> was negative or greater than 3.</exception>
public double this[int index] {
get {
switch (index) {
case 0: {
return x;
}
case 1: {
return y;
}
case 2: {
return z;
}
case 3: {
return w;
}
default: {
throw new IndexOutOfRangeException();
}
}
}
set {
switch (index) {
case 0: {
x = value;
break;
}
case 1: {
y = value;
break;
}
case 2: {
z = value;
break;
}
case 3: {
w = value;
break;
}
default: {
throw new IndexOutOfRangeException();
}
}
}
}
/// <summary>
/// Gets the magnitude of this <see cref="Vector4d"/>, or its distance from (0, 0, 0, 0).
/// </summary>
public double magnitude { get { return Math.Sqrt(sqrMagnitude); } }
/// <summary>
/// Gets the magnitude of this <see cref="Vector4d"/> squared. This is useful for when you are comparing the lengths of two vectors
/// but don't need to know the exact length, and avoids calculating a square root.
/// </summary>
public double sqrMagnitude { get { return System.Math.Pow(x, 2) + System.Math.Pow(y, 2) + System.Math.Pow(z, 2) + System.Math.Pow(w, 2); } }
/// <summary>
/// Gets the normalized version of this <see cref="Vector4d"/> (unit vector with the same direction).
/// </summary>
public Vector4d normalized {
get {
if (this == Vector4d.zero) { return Vector4d.zero; }
double magnitude = this.magnitude;
return new Vector4d(x / magnitude, y / magnitude, z / magnitude, w / magnitude);
}
}
/// <summary>
/// Creates a new <see cref="Vector4d"/> object using elements in the passed array as components.
/// </summary>
/// <param name="point">Components of the vector.</param>
public Vector4d(params float[] point) {
if (point == null) {
throw new ArgumentNullException();
}
x = 0;
y = 0;
z = 0;
w = 0;
if (point.Length >= 4) {
x = Convert.ToDouble(point[0]);
y = Convert.ToDouble(point[1]);
z = Convert.ToDouble(point[2]);
w = Convert.ToDouble(point[3]);
} else if (point.Length == 3) {
x = Convert.ToDouble(point[0]);
y = Convert.ToDouble(point[1]);
z = Convert.ToDouble(point[2]);
} else if (point.Length == 2) {
x = Convert.ToDouble(point[0]);
y = Convert.ToDouble(point[1]);
} else if (point.Length == 1) {
x = Convert.ToDouble(point[0]);
}
}
/// <summary>
/// Creates a new <see cref="Vector4d"/> object using elements in the passed array as components.
/// </summary>
/// <param name="point">Components of the vector.</param>
public Vector4d(params double[] point) {
if (point == null) {
throw new ArgumentNullException();
}
x = 0;
y = 0;
z = 0;
w = 0;
if (point.Length >= 4) {
x = point[0];
y = point[1];
z = point[2];
w = point[3];
} else if (point.Length == 3) {
x = point[0];
y = point[1];
z = point[2];
} else if (point.Length == 2) {
x = point[0];
y = point[1];
} else if (point.Length == 1) {
x = point[0];
}
}
/// <summary>
/// Creates a new <see cref="Vector4d"/> object using elements in the passed array as components.
/// </summary>
/// <param name="point">Components of the vector.</param>
public Vector4d(params int[] point) {
if (point == null) {
throw new ArgumentNullException();
}
x = 0;
y = 0;
z = 0;
w = 0;
if (point.Length >= 4) {
x = Convert.ToDouble(point[0]);
y = Convert.ToDouble(point[1]);
z = Convert.ToDouble(point[2]);
w = Convert.ToDouble(point[3]);
} else if (point.Length == 3) {
x = Convert.ToDouble(point[0]);
y = Convert.ToDouble(point[1]);
z = Convert.ToDouble(point[2]);
} else if (point.Length == 2) {
x = Convert.ToDouble(point[0]);
y = Convert.ToDouble(point[1]);
} else if (point.Length == 1) {
x = Convert.ToDouble(point[0]);
}
}
/// <summary>
/// Crates a new <see cref="Vector4d"/> instance using the components from the supplied <see cref="Vector4d"/>.
/// </summary>
/// <param name="vector">Vector to copy components from.</param>
public Vector4d(Vector4d vector) {
x = vector.x;
y = vector.y;
z = vector.z;
w = vector.w;
}
/// <summary>
/// Adds two vectors together componentwise. This operation is commutative.
/// </summary>
/// <param name="v1">First vector to add.</param>
/// <param name="v2">Second vector to add.</param>
/// <returns>The resulting vector.</returns>
public static Vector4d operator +(Vector4d v1, Vector4d v2) {
return Add(v1, v2);
}
/// <summary>
/// Adds two vectors together componentwise. This operation is commutative.
/// </summary>
/// <param name="v1">First vector to add.</param>
/// <param name="v2">Second vector to add.</param>
/// <returns>The resulting vector.</returns>
public static Vector4d Add(Vector4d v1, Vector4d v2) {
return new Vector4d(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.w + v2.w);
}
/// <summary>
/// Subtracts one vector from another. This operation is NOT commutative.
/// </summary>
/// <param name="v1">Vector to subtract from.</param>
/// <param name="v2">Vector to subtract.</param>
/// <returns>Difference from <paramref name="v1"/> to <paramref name="v2"/>.</returns>
public static Vector4d operator -(Vector4d v1, Vector4d v2) {
return Subtract(v1, v2);
}
/// <summary>
/// Subtracts one vector from another. This operation is NOT commutative.
/// </summary>
/// <param name="v1">Vector to subtract from.</param>
/// <param name="v2">Vector to subtract.</param>
/// <returns>Difference from <paramref name="v1"/> to <paramref name="v2"/>.</returns>
public static Vector4d Subtract(Vector4d v1, Vector4d v2) {
return new Vector4d(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, v1.w - v2.w);
}
/// <summary>
/// Returns the negative of this vector. Equivalent to (0, 0, 0, 0) - <paramref name="v1"/>.
/// </summary>
/// <param name="v1">Vector to negate.</param>
/// <returns><paramref name="v1"/> with all components negated.</returns>
public static Vector4d operator -(Vector4d v1) {
return Negate(v1);
}
/// <summary>
/// Returns the negative of this vector. Equivalent to (0, 0, 0, 0) - <paramref name="v1"/>.
/// </summary>
/// <param name="v1">Vector to negate.</param>
/// <returns><paramref name="v1"/> with all components negated.</returns>
public static Vector4d Negate(Vector4d v1) {
return new Vector4d(-v1.x, -v1.y, -v1.z, -v1.w);
}
/// <summary>
/// Scalar multiplication. Multiplies all components of <paramref name="v1"/> by <paramref name="scalar"/> and returns the result.
/// </summary>
/// <param name="v1">Vector to scale.</param>
/// <param name="scalar">Scalar.</param>
/// <returns>Resulting Vector.</returns>
public static Vector4d operator *(Vector4d v1, double scalar) {
return Scale(v1, scalar);
}
/// <summary>
/// Scalar multiplication. Multiplies all components of <paramref name="v1"/> by <paramref name="scalar"/> and returns the result.
/// </summary>
/// <param name="scalar">Scalar.</param>
/// <param name="v1">Vector to scale.</param>
/// <returns>Resulting Vector.</returns>
public static Vector4d operator *(double scalar, Vector4d v1) {
return Scale(v1, scalar);
}
/// <summary>
/// Scalar multiplication. Multiplies all components of <paramref name="v1"/> by <paramref name="scalar"/> and returns the result.
/// </summary>
/// <param name="v1">Vector to scale.</param>
/// <param name="scalar">Scalar.</param>
/// <returns>Resulting Vector.</returns>
public static Vector4d Scale(Vector4d v1, double scalar) {
return new Vector4d(v1.x * scalar, v1.y * scalar, v1.z * scalar, v1.w * scalar);
}
/// <summary>
/// Scalar multiplication. Multiplies all components of <paramref name="v1"/> by <paramref name="scalar"/> and returns the result.
/// </summary>
/// <param name="scalar">Scalar.</param>
/// <param name="v1">Vector to scale.</param>
/// <returns>Resulting Vector.</returns>
public static Vector4d Scale(double scalar, Vector4d v1) {
return Scale(v1, scalar);
}
/// <summary>
/// Multiplies two vectors together componentwise. This operation is commutative.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns>Resulting vector when the passed vectors' components are multiplied.</returns>
public static Vector4d Scale(Vector4d v1, Vector4d v2) {
return new Vector4d(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z, v1.w * v2.w);
}
/// <summary>
/// Vector dot product. This operation is commutative.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns>Dot product of these two vectors.</returns>
public static double operator *(Vector4d v1, Vector4d v2) {
return Dot(v1, v2);
}
/// <summary>
/// Vector dot product. This operation is commutative.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns>Dot product of these two vectors.</returns>
public static double Dot(Vector4d v1, Vector4d v2) {
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w;
}
/// <summary>
/// Scalar division. Divides all components of <paramref name="v1"/> by <paramref name="divisor"/> and returns the result.
/// </summary>
/// <param name="v1">Vector to divide.</param>
/// <param name="divisor">Divisor.</param>
/// <returns>Resulting vector when all components of <paramref name="v1"/> are divided by <paramref name="divisor"/>.</returns>
public static Vector4d operator /(Vector4d v1, double divisor) {
return Scale(v1, 1.0 / divisor);
}
#region IEquatable
/// <summary>
/// Equivalency. Returns <c>true</c> if the components of two vectors are equal or approximately equal.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns><c>true</c> if the components of two vectors are equal or approximately equal.</returns>
public static bool operator ==(Vector4d v1, Vector4d v2) {
return v1.Equals(v2);
}
/// <summary>
/// Non-Equivalency. Returns <c>true</c> if the components of two vectors are not equal or approximately equal.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns><c>true</c> if the components of two vectors are not equal or approximately equal.</returns>
public static bool operator !=(Vector4d v1, Vector4d v2) {
return !v1.Equals(v2);
}
/// <summary>
/// Equivalency. Returns <c>true</c> if the components of two vectors are equal or approximately equal.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns><c>true</c> if the components of two vectors are equal or approximately equal.</returns>
public bool Equals(Vector4d other) {
return (Math.Abs(x - other.x) < 0.001 && Math.Abs(y - other.y) < 0.001 && Math.Abs(z - other.z) < 0.001 && Math.Abs(w - other.w) < 0.001);
}
/// <summary>
/// Equivalency. Returns <c>true</c> if the other object is a vector, and the components of two vectors are equal or approximately equal.
/// </summary>
/// <param name="v1">First vector.</param>
/// <param name="v2">Second vector.</param>
/// <returns><c>true</c> if the other object is a vector, and the components of two vectors are equal or approximately equal.</returns>
public override bool Equals(object obj) {
if (object.ReferenceEquals(obj, null) || !GetType().IsAssignableFrom(obj.GetType())) { return false; }
return Equals((Vector4d)obj);
}
/// <summary>
/// Generates a hash code for this instance based on instance data.
/// </summary>
/// <returns>The hash code for this instance.</returns>
public override int GetHashCode() {
return x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
}
#endregion
/// <summary>
/// Calculates the distance from this vector to another.
/// </summary>
/// <param name="to">Vector to calculate distance to.</param>
/// <returns>Distance from this vector to the passed vector.</returns>
public double Distance(Vector4d to) {
return (this - to).magnitude;
}
/// <summary>
/// Gets a human-readable <c>string</c> representation of this vector.
/// </summary>
/// <returns>Human-readable <c>string</c> representation of this vector.</returns>
public override string ToString() {
return string.Format("( {0} , {1} , {2} , {3} )", x.ToString(), y.ToString(), z.ToString(), w.ToString());
}
/// <summary>
/// Changes this vector to its normalized version (it will have a magnitude of 1).
/// </summary>
public void Normalize() {
if (this == Vector4d.zero) { return; }
double magnitude = this.magnitude;
x /= magnitude;
y /= magnitude;
z /= magnitude;
w /= magnitude;
}
/// <summary>
/// Gets the area of the triangle defined by three points using Heron's formula.
/// </summary>
/// <param name="p1">First vertex of triangle.</param>
/// <param name="p2">Second vertex of triangle.</param>
/// <param name="p3">Third vertex of triangle.</param>
/// <returns>Area of the triangle defined by these three vertices.</returns>
public static double TriangleArea(Vector4d p1, Vector4d p2, Vector4d p3) {
return Math.Sqrt(SqrTriangleArea(p1, p2, p3)) / 4.0;
}
/// <summary>
/// Gets the square of the area of the triangle defined by three points. This is useful when simply comparing two areas when you don't need to know exactly what the area is.
/// </summary>
/// <param name="p1">First vertex of triangle.</param>
/// <param name="p2">Second vertex of triangl.</param>
/// <param name="p3">Third vertex of triangle.</param>
/// <returns>Square of the area of the triangle defined by these three vertices.</returns>
public static double SqrTriangleArea(Vector4d p1, Vector4d p2, Vector4d p3) {
double a = p1.Distance(p2);
double b = p1.Distance(p3);
double c = p2.Distance(p3);
return 4.0 * a * a * b * b - Math.Pow((a * a) + (b * b) - (c * c), 2);
}
#region IEnumerable
/// <summary>
/// Allows enumeration through the components of a <see cref="Vector4d"/> using a foreach loop.
/// </summary>
public IEnumerator<double> GetEnumerator() {
yield return x;
yield return y;
yield return z;
yield return w;
}
/// <summary>
/// Allows enumeration through the components of a <see cref="Vector4d"/> using a foreach loop, auto-boxed version.
/// </summary>
/// <remarks>
/// This foreach loop will look like foreach(object o in Vector4d). This will auto-box the doubles in System.Double
/// objects, allocating memory on the heap which the garbage collector will have to free later. In general, iterate
/// through doubles rather than objects.
/// </remarks>
IEnumerator IEnumerable.GetEnumerator() {
yield return x;
yield return y;
yield return z;
yield return w;
}
#endregion
/// <summary>
/// Implicitly converts this <see cref="Vector4d"/> into a <see cref="Vector2d"/>. This will be called when Vector2d v2 = v4 is used.
/// </summary>
/// <param name="v"><see cref="Vector4d"/> to convert.</param>
/// <returns>The input vector as a <see cref="Vector2d"/>, Z and W components discarded.</returns>
public static implicit operator Vector2d(Vector4d v) {
return new Vector2d(v.x, v.y);
}
/// <summary>
/// Implicitly converts this <see cref="Vector4d"/> into a <see cref="Vector3d"/>. This will be called when Vector3d v3 = v4 is used.
/// </summary>
/// <param name="v"><see cref="Vector4d"/> to convert.</param>
/// <returns>The input vector as a <see cref="Vector3d"/>, W component discarded.</returns>
public static implicit operator Vector3d(Vector4d v) {
return new Vector3d(v.x, v.y, v.z);
}
/// <summary>
/// Implicitly converts this <see cref="Vector4d"/> into a <c>Color</c> by interpreting (x, y, z) as (r, g, b) respectively, and w as alpha.
/// Assumes colors range from 0 to 255.
/// </summary>
/// <param name="v"><see cref="Vector4d"/> to convert.</param>
/// <returns>This <see cref="Vector4d"/> in a <c>Color</c> object interpreted as RGBA.</returns>
public static implicit operator Color(Vector4d v) {
return ColorExtensions.FromArgb((int)Math.Max(v.w, 255), (int)Math.Max(v.x, 255), (int)Math.Max(v.y, 255), (int)Math.Max(v.z, 255));
}
}
}
#endif

View File

@@ -14,30 +14,33 @@ using System;
namespace LibBSP {
#if UNITY
using Color = UnityEngine.Color32;
using Vector2d = UnityEngine.Vector2;
using Vector3d = UnityEngine.Vector3;
using Vector4d = UnityEngine.Vector4;
using Vector2 = UnityEngine.Vector2;
using Vector3 = UnityEngine.Vector3;
using Vector4 = UnityEngine.Vector4;
#elif GODOT
using Color = Godot.Color;
using Vector2d = Godot.Vector2;
using Vector3d = Godot.Vector3;
using Vector4d = Godot.Quat;
using Vector2 = Godot.Vector2;
using Vector3 = Godot.Vector3;
using Vector4 = Godot.Quat;
#else
using Color = System.Drawing.Color;
using Vector2 = System.Numerics.Vector2;
using Vector3 = System.Numerics.Vector3;
using Vector4 = System.Numerics.Vector4;
#endif
/// <summary>
/// Vertex struct, including fields for normal, tangent and four sets of UVs.
/// </summary>
[Serializable] public struct Vertex {
public Vector3d position;
public Vector3d normal;
public Vector3 position;
public Vector3 normal;
public Color color;
public Vector2d uv0;
public Vector2d uv1;
public Vector2d uv2;
public Vector2d uv3;
public Vector4d tangent;
public Vector2 uv0;
public Vector2 uv1;
public Vector2 uv2;
public Vector2 uv3;
public Vector4 tangent;
/// <summary>
/// Simple Vertex with sensible settings.
@@ -46,13 +49,13 @@ namespace LibBSP {
get {
return new Vertex {
color = ColorExtensions.FromArgb(255, 255, 255, 255),
normal = new Vector3d(0, 0, -1),
position = new Vector3d(0, 0, 0),
tangent = new Vector4d(1, 0, 0, -1),
uv0 = new Vector2d(0, 0),
uv1 = new Vector2d(0, 0),
uv2 = new Vector2d(0, 0),
uv3 = new Vector2d(0, 0),
normal = new Vector3(0, 0, -1),
position = new Vector3(0, 0, 0),
tangent = new Vector4(1, 0, 0, -1),
uv0 = new Vector2(0, 0),
uv1 = new Vector2(0, 0),
uv2 = new Vector2(0, 0),
uv3 = new Vector2(0, 0),
};
}
}

View File

@@ -8,13 +8,17 @@ using System.Globalization;
namespace LibBSP {
#if UNITY
using Vector2d = UnityEngine.Vector2;
using Vector3d = UnityEngine.Vector3;
using Vector2 = UnityEngine.Vector2;
using Vector3 = UnityEngine.Vector3;
using Plane = UnityEngine.Plane;
#elif GODOT
using Vector2d = Godot.Vector2;
using Vector3d = Godot.Vector3;
using Vector2 = Godot.Vector2;
using Vector3 = Godot.Vector3;
using Plane = Godot.Plane;
#else
using Vector2 = System.Numerics.Vector2;
using Vector3 = System.Numerics.Vector3;
using Plane = System.Numerics.Plane;
#endif
/// <summary>
@@ -24,13 +28,13 @@ namespace LibBSP {
private static IFormatProvider _format = CultureInfo.CreateSpecificCulture("en-US");
public Vector3d[] vertices;
public Vector3[] vertices;
public Plane plane;
public string texture;
public TextureInfo textureInfo;
public string material;
public double lgtScale;
public double lgtRot;
public float lgtScale;
public float lgtRot;
public MAPDisplacement displacement;
/// <summary>
@@ -51,36 +55,36 @@ namespace LibBSP {
// If this succeeds, assume brushDef3
if (float.TryParse(tokens[4], out dist)) {
plane = new Plane(new Vector3d(float.Parse(tokens[1], _format), float.Parse(tokens[2], _format), float.Parse(tokens[3], _format)), dist);
textureInfo = new TextureInfo(new Vector3d(float.Parse(tokens[8], _format), float.Parse(tokens[9], _format), float.Parse(tokens[10], _format)),
new Vector3d(float.Parse(tokens[13], _format), float.Parse(tokens[14], _format), float.Parse(tokens[15], _format)),
new Vector2d(0, 0),
new Vector2d(1, 1),
plane = new Plane(new Vector3(float.Parse(tokens[1], _format), float.Parse(tokens[2], _format), float.Parse(tokens[3], _format)), dist);
textureInfo = new TextureInfo(new Vector3(float.Parse(tokens[8], _format), float.Parse(tokens[9], _format), float.Parse(tokens[10], _format)),
new Vector3(float.Parse(tokens[13], _format), float.Parse(tokens[14], _format), float.Parse(tokens[15], _format)),
new Vector2(0, 0),
new Vector2(1, 1),
0, 0, 0);
texture = tokens[18];
} else {
Vector3d v1 = new Vector3d(float.Parse(tokens[1], _format), float.Parse(tokens[2], _format), float.Parse(tokens[3], _format));
Vector3d v2 = new Vector3d(float.Parse(tokens[6], _format), float.Parse(tokens[7], _format), float.Parse(tokens[8], _format));
Vector3d v3 = new Vector3d(float.Parse(tokens[11], _format), float.Parse(tokens[12], _format), float.Parse(tokens[13], _format));
vertices = new Vector3d[] { v1, v2, v3 };
plane = new Plane(v1, v2, v3);
Vector3 v1 = new Vector3(float.Parse(tokens[1], _format), float.Parse(tokens[2], _format), float.Parse(tokens[3], _format));
Vector3 v2 = new Vector3(float.Parse(tokens[6], _format), float.Parse(tokens[7], _format), float.Parse(tokens[8], _format));
Vector3 v3 = new Vector3(float.Parse(tokens[11], _format), float.Parse(tokens[12], _format), float.Parse(tokens[13], _format));
vertices = new Vector3[] { v1, v2, v3 };
plane = PlaneExtensions.CreateFromVertices(v1, v2, v3);
texture = tokens[15];
// GearCraft
if (tokens[16] == "[") {
textureInfo = new TextureInfo(new Vector3d(float.Parse(tokens[17], _format), float.Parse(tokens[18], _format), float.Parse(tokens[19], _format)),
new Vector3d(float.Parse(tokens[23], _format), float.Parse(tokens[24], _format), float.Parse(tokens[25], _format)),
new Vector2d(float.Parse(tokens[20], _format), float.Parse(tokens[26], _format)),
new Vector2d(float.Parse(tokens[29], _format), float.Parse(tokens[30], _format)),
int.Parse(tokens[31]), 0, double.Parse(tokens[28], _format));
textureInfo = new TextureInfo(new Vector3(float.Parse(tokens[17], _format), float.Parse(tokens[18], _format), float.Parse(tokens[19], _format)),
new Vector3(float.Parse(tokens[23], _format), float.Parse(tokens[24], _format), float.Parse(tokens[25], _format)),
new Vector2(float.Parse(tokens[20], _format), float.Parse(tokens[26], _format)),
new Vector2(float.Parse(tokens[29], _format), float.Parse(tokens[30], _format)),
int.Parse(tokens[31]), 0, float.Parse(tokens[28], _format));
material = tokens[32];
} else {
//<x_shift> <y_shift> <rotation> <x_scale> <y_scale> <content_flags> <surface_flags> <value>
Vector3d[] axes = TextureInfo.TextureAxisFromPlane(plane);
Vector3[] axes = TextureInfo.TextureAxisFromPlane(plane);
textureInfo = new TextureInfo(axes[0],
axes[1],
new Vector2d(float.Parse(tokens[16], _format), float.Parse(tokens[17], _format)),
new Vector2d(float.Parse(tokens[19], _format), float.Parse(tokens[20], _format)),
int.Parse(tokens[22]), 0, double.Parse(tokens[18], _format));
new Vector2(float.Parse(tokens[16], _format), float.Parse(tokens[17], _format)),
new Vector2(float.Parse(tokens[19], _format), float.Parse(tokens[20], _format)),
int.Parse(tokens[22]), 0, float.Parse(tokens[18], _format));
}
}
} else {
@@ -114,32 +118,32 @@ namespace LibBSP {
case "plane": {
string[] points = tokens[1].SplitUnlessBetweenDelimiters(' ', '(', ')', StringSplitOptions.RemoveEmptyEntries);
string[] components = points[0].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
Vector3d v1 = new Vector3d(float.Parse(components[0], _format), float.Parse(components[1], _format), float.Parse(components[2], _format));
Vector3 v1 = new Vector3(float.Parse(components[0], _format), float.Parse(components[1], _format), float.Parse(components[2], _format));
components = points[1].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
Vector3d v2 = new Vector3d(float.Parse(components[0], _format), float.Parse(components[1], _format), float.Parse(components[2], _format));
Vector3 v2 = new Vector3(float.Parse(components[0], _format), float.Parse(components[1], _format), float.Parse(components[2], _format));
components = points[2].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
Vector3d v3 = new Vector3d(float.Parse(components[0], _format), float.Parse(components[1], _format), float.Parse(components[2], _format));
plane = new Plane(v1, v2, v3);
Vector3 v3 = new Vector3(float.Parse(components[0], _format), float.Parse(components[1], _format), float.Parse(components[2], _format));
plane = PlaneExtensions.CreateFromVertices(v1, v2, v3);
break;
}
case "uaxis": {
string[] split = tokens[1].SplitUnlessBetweenDelimiters(' ', '[', ']', StringSplitOptions.RemoveEmptyEntries);
textureInfo.scale = new Vector2d(float.Parse(split[1], _format), textureInfo.scale.y);
textureInfo.scale = new Vector2(float.Parse(split[1], _format), textureInfo.scale.Y());
split = split[0].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
textureInfo.uAxis = new Vector3d(float.Parse(split[0], _format), float.Parse(split[1], _format), float.Parse(split[2], _format));
textureInfo.translation = new Vector2d(float.Parse(split[3], _format), textureInfo.translation.y);
textureInfo.uAxis = new Vector3(float.Parse(split[0], _format), float.Parse(split[1], _format), float.Parse(split[2], _format));
textureInfo.translation = new Vector2(float.Parse(split[3], _format), textureInfo.translation.Y());
break;
}
case "vaxis": {
string[] split = tokens[1].SplitUnlessBetweenDelimiters(' ', '[', ']', StringSplitOptions.RemoveEmptyEntries);
textureInfo.scale = new Vector2d(textureInfo.scale.x, float.Parse(split[1], _format));
textureInfo.scale = new Vector2(textureInfo.scale.X(), float.Parse(split[1], _format));
split = split[0].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
textureInfo.vAxis = new Vector3d(float.Parse(split[0], _format), float.Parse(split[1], _format), float.Parse(split[2], _format));
textureInfo.translation = new Vector2d(textureInfo.translation.x, float.Parse(split[3], _format));
textureInfo.vAxis = new Vector3(float.Parse(split[0], _format), float.Parse(split[1], _format), float.Parse(split[2], _format));
textureInfo.translation = new Vector2(textureInfo.translation.X(), float.Parse(split[3], _format));
break;
}
case "rotation": {
textureInfo.rotation = double.Parse(tokens[1], _format);
textureInfo.rotation = float.Parse(tokens[1], _format);
break;
}
}

View File

@@ -8,9 +8,11 @@ using System.Globalization;
namespace LibBSP {
#if UNITY
using Vector3d = UnityEngine.Vector3;
using Vector3 = UnityEngine.Vector3;
#elif GODOT
using Vector3d = Godot.Vector3;
using Vector3 = Godot.Vector3;
#else
using Vector3 = System.Numerics.Vector3;
#endif
/// <summary>
@@ -21,8 +23,8 @@ namespace LibBSP {
private static IFormatProvider _format = CultureInfo.CreateSpecificCulture("en-US");
public int power;
public Vector3d start;
public Vector3d[,] normals;
public Vector3 start;
public Vector3[,] normals;
public float[,] distances;
public float[,] alphas;
@@ -72,14 +74,14 @@ namespace LibBSP {
case "power": {
power = int.Parse(tokens[1]);
int side = (int)Math.Pow(2, power) + 1;
normals = new Vector3d[side, side];
normals = new Vector3[side, side];
distances = new float[side, side];
alphas = new float[side, side];
break;
}
case "startposition": {
string[] point = tokens[1].Substring(1, tokens[1].Length - 2).Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
start = new Vector3d(float.Parse(point[0], _format), float.Parse(point[1], _format), float.Parse(point[2], _format));
start = new Vector3(float.Parse(point[0], _format), float.Parse(point[1], _format), float.Parse(point[2], _format));
break;
}
}
@@ -107,13 +109,13 @@ namespace LibBSP {
throw new ArgumentException("Bad data given to MAPDisplacement, no power specified!");
}
if (start.x == float.NaN) {
if (start.X() == float.NaN) {
throw new ArgumentException("Bad data given to MAPDisplacement, no starting point specified!");
}
foreach (int i in normalsTokens.Keys) {
for (int j = 0; j < normalsTokens[i].Length / 3; j++) {
normals[i, j] = new Vector3d(float.Parse(normalsTokens[i][j * 3], _format), float.Parse(normalsTokens[i][(j * 3) + 1], _format), float.Parse(normalsTokens[i][(j * 3) + 2], _format));
normals[i, j] = new Vector3(float.Parse(normalsTokens[i][j * 3], _format), float.Parse(normalsTokens[i][(j * 3) + 1], _format), float.Parse(normalsTokens[i][(j * 3) + 2], _format));
distances[i, j] = float.Parse(distancesTokens[i][j], _format);
alphas[i, j] = float.Parse(alphasTokens[i][j], _format);
}

View File

@@ -11,17 +11,19 @@ using System.Globalization;
namespace LibBSP {
#if UNITY
using Vector2d = UnityEngine.Vector2;
using Vector3d = UnityEngine.Vector3;
using Vector2 = UnityEngine.Vector2;
using Vector3 = UnityEngine.Vector3;
using Color = UnityEngine.Color32;
#if !OLDUNITY
using Vertex = UnityEngine.UIVertex;
#endif
#elif GODOT
using Vector2d = Godot.Vector2;
using Vector3d = Godot.Vector3;
using Vector2 = Godot.Vector2;
using Vector3 = Godot.Vector3;
using Color = Godot.Color;
#else
using Vector2 = System.Numerics.Vector2;
using Vector3 = System.Numerics.Vector3;
using Color = System.Drawing.Color;
#endif
@@ -33,7 +35,7 @@ namespace LibBSP {
private static IFormatProvider _format = CultureInfo.CreateSpecificCulture("en-US");
public Vertex[] points;
public Vector2d dims;
public Vector2 dims;
public string texture;
/// <summary>
@@ -54,12 +56,12 @@ namespace LibBSP {
case "patchDef3":
case "patchDef2": {
string[] line = lines[3].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
dims = new Vector2d(float.Parse(line[1], _format), float.Parse(line[2], _format));
for (int i = 0; i < dims.x; ++i) {
dims = new Vector2(float.Parse(line[1], _format), float.Parse(line[2], _format));
for (int i = 0; i < dims.X(); ++i) {
line = lines[i + 5].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
for (int j = 0; j < dims.y; ++j) {
Vector3d point = new Vector3d(float.Parse(line[2 + (j * 7)], _format), float.Parse(line[3 + (j * 7)], _format), float.Parse(line[4 + (j * 7)], _format));
Vector2d uv = new Vector2d(float.Parse(line[5 + (j * 7)], _format), float.Parse(line[6 + (j * 7)], _format));
for (int j = 0; j < dims.Y(); ++j) {
Vector3 point = new Vector3(float.Parse(line[2 + (j * 7)], _format), float.Parse(line[3 + (j * 7)], _format), float.Parse(line[4 + (j * 7)], _format));
Vector2 uv = new Vector2(float.Parse(line[5 + (j * 7)], _format), float.Parse(line[6 + (j * 7)], _format));
Vertex vertex = new Vertex() {
position = point,
uv0 = uv,
@@ -72,12 +74,12 @@ namespace LibBSP {
}
case "patchTerrainDef3": {
string[] line = lines[3].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
dims = new Vector2d(float.Parse(line[1], _format), float.Parse(line[2], _format));
for (int i = 0; i < dims.x; ++i) {
dims = new Vector2(float.Parse(line[1], _format), float.Parse(line[2], _format));
for (int i = 0; i < dims.X(); ++i) {
line = lines[i + 5].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
for (int j = 0; j < dims.y; ++j) {
Vector3d point = new Vector3d(float.Parse(line[2 + (j * 12)], _format), float.Parse(line[3 + (j * 12)], _format), float.Parse(line[4 + (j * 12)], _format));
Vector2d uv = new Vector2d(float.Parse(line[5 + (j * 12)], _format), float.Parse(line[6 + (j * 12)], _format));
for (int j = 0; j < dims.Y(); ++j) {
Vector3 point = new Vector3(float.Parse(line[2 + (j * 12)], _format), float.Parse(line[3 + (j * 12)], _format), float.Parse(line[4 + (j * 12)], _format));
Vector2 uv = new Vector2(float.Parse(line[5 + (j * 12)], _format), float.Parse(line[6 + (j * 12)], _format));
Color color = ColorExtensions.FromArgb(byte.Parse(line[7 + (j * 12)]), byte.Parse(line[8 + (j * 12)]), byte.Parse(line[9 + (j * 12)]), byte.Parse(line[10 + (j * 12)]));
Vertex vertex = new Vertex() {
position = point,

View File

@@ -7,11 +7,14 @@ using System.Globalization;
namespace LibBSP {
#if UNITY
using Vector4d = UnityEngine.Vector4;
using Vector3d = UnityEngine.Vector3;
using Vector4 = UnityEngine.Vector4;
using Vector3 = UnityEngine.Vector3;
#elif GODOT
using Vector4d = Godot.Quat;
using Vector3d = Godot.Vector3;
using Vector4 = Godot.Quat;
using Vector3 = Godot.Vector3;
#else
using Vector3 = System.Numerics.Vector3;
using Vector4 = System.Numerics.Vector4;
#endif
/// <summary>
@@ -23,16 +26,16 @@ namespace LibBSP {
public int side;
public string texture;
public double textureShiftS;
public double textureShiftT;
public float textureShiftS;
public float textureShiftT;
public float texRot;
public double texScaleX;
public double texScaleY;
public float texScaleX;
public float texScaleY;
public int flags;
public double sideLength;
public Vector3d start;
public Vector4d IF;
public Vector4d LF;
public float sideLength;
public Vector3 start;
public Vector4 IF;
public Vector4 LF;
public float[,] heightMap;
public float[,] alphaMap;
@@ -59,22 +62,22 @@ namespace LibBSP {
textureShiftS = float.Parse(line[2], _format);
textureShiftT = float.Parse(line[3], _format);
texRot = float.Parse(line[4], _format);
texScaleX = double.Parse(line[5], _format);
texScaleY = double.Parse(line[6], _format);
texScaleX = float.Parse(line[5], _format);
texScaleY = float.Parse(line[6], _format);
flags = int.Parse(line[8]);
break;
}
case "TD(": {
sideLength = int.Parse(line[1], _format);
start = new Vector3d(float.Parse(line[2], _format), float.Parse(line[3], _format), float.Parse(line[4], _format));
start = new Vector3(float.Parse(line[2], _format), float.Parse(line[3], _format), float.Parse(line[4], _format));
break;
}
case "IF(": {
IF = new Vector4d(float.Parse(line[1], _format), float.Parse(line[2], _format), float.Parse(line[3], _format), float.Parse(line[4], _format));
IF = new Vector4(float.Parse(line[1], _format), float.Parse(line[2], _format), float.Parse(line[3], _format), float.Parse(line[4], _format));
break;
}
case "LF(": {
LF = new Vector4d(float.Parse(line[1], _format), float.Parse(line[2], _format), float.Parse(line[3], _format), float.Parse(line[4], _format));
LF = new Vector4(float.Parse(line[1], _format), float.Parse(line[2], _format), float.Parse(line[3], _format), float.Parse(line[4], _format));
break;
}
case "V(": {

View File

@@ -7,11 +7,14 @@ using System.Collections.Generic;
namespace LibBSP {
#if UNITY
using Vector2d = UnityEngine.Vector2;
using Vector3d = UnityEngine.Vector3;
using Vector2 = UnityEngine.Vector2;
using Vector3 = UnityEngine.Vector3;
#elif GODOT
using Vector2d = Godot.Vector2;
using Vector3d = Godot.Vector3;
using Vector2 = Godot.Vector2;
using Vector3 = Godot.Vector3;
#else
using Vector2 = System.Numerics.Vector2;
using Vector3 = System.Numerics.Vector3;
#endif
/// <summary>
@@ -19,9 +22,9 @@ namespace LibBSP {
/// </summary>
[Serializable] public class MAPTerrainMoHAA {
public Vector2d size;
public Vector2 size;
public int flags;
public Vector3d origin;
public Vector3 origin;
public List<Partition> partitions;
public List<Vertex> vertices;
@@ -49,9 +52,9 @@ namespace LibBSP {
public int unknown2;
public string shader;
public int[] textureShift;
public double rotation;
public float rotation;
public int unknown3;
public double[] textureScale;
public float[] textureScale;
public int unknown4;
public int flags;
public int unknown5;
@@ -64,7 +67,7 @@ namespace LibBSP {
textureShift = new int[2];
rotation = 0;
unknown3 = 0;
textureScale = new double[] { 1, 1 };
textureScale = new float[] { 1, 1 };
unknown4 = 0;
flags = 0;
unknown5 = 0;