mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-25 21:31:14 +00:00
372 lines
8.8 KiB
C#
Executable file
372 lines
8.8 KiB
C#
Executable file
|
|
#region ================== Copyright (c) 2007 Pascal vd Heiden
|
|
|
|
/*
|
|
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
|
|
* This program is released under GNU General Public License
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
*/
|
|
|
|
#endregion
|
|
|
|
#region ================== Namespaces
|
|
|
|
using System;
|
|
using CodeImp.DoomBuilder.Rendering;
|
|
|
|
#endregion
|
|
|
|
namespace CodeImp.DoomBuilder.Geometry
|
|
{
|
|
public struct Vector3D
|
|
{
|
|
#region ================== Constants
|
|
|
|
private const double TINY_VALUE = 0.0000000001f;
|
|
|
|
#endregion
|
|
|
|
#region ================== Variables
|
|
|
|
// Coordinates
|
|
public double x;
|
|
public double y;
|
|
public double z;
|
|
|
|
#endregion
|
|
|
|
#region ================== Constructors
|
|
|
|
// Constructor
|
|
public Vector3D(double x, double y, double z)
|
|
{
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
}
|
|
|
|
// Constructor
|
|
public Vector3D(Vector2D v)
|
|
{
|
|
this.x = v.x;
|
|
this.y = v.y;
|
|
this.z = 0f;
|
|
}
|
|
|
|
// Constructor (mxd)
|
|
public Vector3D(Vector2D v, double z)
|
|
{
|
|
this.x = v.x;
|
|
this.y = v.y;
|
|
this.z = z;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Statics
|
|
|
|
// Conversion to Vector2D
|
|
public static implicit operator Vector2D(Vector3D a)
|
|
{
|
|
return new Vector2D(a);
|
|
}
|
|
|
|
// This adds two vectors
|
|
public static Vector3D operator +(Vector3D a, Vector3D b)
|
|
{
|
|
return new Vector3D(a.x + b.x, a.y + b.y, a.z + b.z);
|
|
}
|
|
|
|
// This adds to all dimensions
|
|
public static Vector3D operator +(Vector3D a, double b)
|
|
{
|
|
return new Vector3D(a.x + b, a.y + b, a.z + b);
|
|
}
|
|
|
|
// This adds to all dimensions
|
|
public static Vector3D operator +(double b, Vector3D a)
|
|
{
|
|
return new Vector3D(a.x + b, a.y + b, a.z + b);
|
|
}
|
|
|
|
// This subtracts two vectors
|
|
public static Vector3D operator -(Vector3D a, Vector3D b)
|
|
{
|
|
return new Vector3D(a.x - b.x, a.y - b.y, a.z - b.z);
|
|
}
|
|
|
|
// This subtracts from all dimensions
|
|
public static Vector3D operator -(Vector3D a, double b)
|
|
{
|
|
return new Vector3D(a.x - b, a.y - b, a.z - b);
|
|
}
|
|
|
|
// This subtracts from all dimensions
|
|
public static Vector3D operator -(double a, Vector3D b)
|
|
{
|
|
return new Vector3D(a - b.x, a - b.y, a - b.z);
|
|
}
|
|
|
|
// This reverses a vector
|
|
public static Vector3D operator -(Vector3D a)
|
|
{
|
|
return new Vector3D(-a.x, -a.y, -a.z);
|
|
}
|
|
|
|
// This scales a vector
|
|
public static Vector3D operator *(double s, Vector3D a)
|
|
{
|
|
return new Vector3D(a.x * s, a.y * s, a.z * s);
|
|
}
|
|
|
|
// This scales a vector
|
|
public static Vector3D operator *(Vector3D a, double s)
|
|
{
|
|
return new Vector3D(a.x * s, a.y * s, a.z * s);
|
|
}
|
|
|
|
// This scales a vector
|
|
public static Vector3D operator *(Vector3D a, Vector3D b)
|
|
{
|
|
return new Vector3D(a.x * b.x, a.y * b.y, a.z * b.z);
|
|
}
|
|
|
|
// This scales a vector
|
|
public static Vector3D operator /(double s, Vector3D a)
|
|
{
|
|
return new Vector3D(a.x / s, a.y / s, a.z / s);
|
|
}
|
|
|
|
// This scales a vector
|
|
public static Vector3D operator /(Vector3D a, double s)
|
|
{
|
|
return new Vector3D(a.x / s, a.y / s, a.z / s);
|
|
}
|
|
|
|
// This scales a vector
|
|
public static Vector3D operator /(Vector3D a, Vector3D b)
|
|
{
|
|
return new Vector3D(a.x / b.x, a.y / b.y, a.z / b.z);
|
|
}
|
|
|
|
// This compares a vector
|
|
public static bool operator ==(Vector3D a, Vector3D b)
|
|
{
|
|
return (a.x == b.x) && (a.y == b.y) && (a.z == b.z);
|
|
}
|
|
|
|
// This compares a vector
|
|
public static bool operator !=(Vector3D a, Vector3D b)
|
|
{
|
|
return (a.x != b.x) || (a.y != b.y) || (a.z != b.z);
|
|
}
|
|
|
|
// This calculates the cross product
|
|
public static Vector3D CrossProduct(Vector3D a, Vector3D b)
|
|
{
|
|
Vector3D result = new Vector3D();
|
|
|
|
// Calculate and return the dot product
|
|
result.x = a.y * b.z - a.z * b.y;
|
|
result.y = a.z * b.x - a.x * b.z;
|
|
result.z = a.x * b.y - a.y * b.x;
|
|
return result;
|
|
}
|
|
|
|
// This calculates the dot product
|
|
public static double DotProduct(Vector3D a, Vector3D b)
|
|
{
|
|
// Calculate and return the dot product
|
|
return a.x * b.x + a.y * b.y + a.z * b.z;
|
|
}
|
|
|
|
// This reflects the vector v over mirror m
|
|
// Note that mirror m must be normalized!
|
|
public static Vector3D Reflect(Vector3D v, Vector3D m)
|
|
{
|
|
// Get the dot product of v and m
|
|
double dp = Vector3D.DotProduct(v, m);
|
|
|
|
// Make the reflected vector
|
|
Vector3D mv = new Vector3D();
|
|
mv.x = -v.x + 2f * m.x * dp;
|
|
mv.y = -v.y + 2f * m.y * dp;
|
|
mv.z = -v.z + 2f * m.z * dp;
|
|
|
|
// Return the reflected vector
|
|
return mv;
|
|
}
|
|
|
|
// This returns the reversed vector
|
|
public static Vector3D Reversed(Vector3D v)
|
|
{
|
|
// Return reversed vector
|
|
return new Vector3D(-v.x, -v.y, -v.z);
|
|
}
|
|
|
|
// This returns a vector from an angle
|
|
public static Vector3D FromAngleXY(double angle)
|
|
{
|
|
// Return vector from angle
|
|
return new Vector3D(Math.Sin(angle), -Math.Cos(angle), 0f);
|
|
}
|
|
|
|
// This returns a vector from an angle with a given legnth
|
|
public static Vector3D FromAngleXY(double angle, double length)
|
|
{
|
|
// Return vector from angle
|
|
return FromAngleXY(angle) * length;
|
|
}
|
|
|
|
// This returns a vector from an angle with a given legnth
|
|
public static Vector3D FromAngleXYZ(double anglexy, double anglez)
|
|
{
|
|
// Calculate x y and z
|
|
double ax = Math.Sin(anglexy) * Math.Cos(anglez);
|
|
double ay = -Math.Cos(anglexy) * Math.Cos(anglez);
|
|
double az = Math.Sin(anglez);
|
|
|
|
// Return vector
|
|
return new Vector3D(ax, ay, az);
|
|
}
|
|
|
|
//mxd
|
|
public static Vector3D Transform(Vector3D v, Matrix m)
|
|
{
|
|
return new Vector3D
|
|
{
|
|
x = m.M11 * v.x + m.M21 * v.y + m.M31 * v.z + m.M41,
|
|
y = m.M12 * v.x + m.M22 * v.y + m.M32 * v.z + m.M42,
|
|
z = m.M13 * v.x + m.M23 * v.y + m.M33 * v.z + m.M43,
|
|
};
|
|
}
|
|
|
|
//mxd
|
|
public static Vector3D Transform(double x, double y, double z, Matrix m)
|
|
{
|
|
return new Vector3D
|
|
{
|
|
x = m.M11 * x + m.M21 * y + m.M31 * z + m.M41,
|
|
y = m.M12 * x + m.M22 * y + m.M32 * z + m.M42,
|
|
z = m.M13 * x + m.M23 * y + m.M33 * z + m.M43,
|
|
};
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Methods
|
|
|
|
// This calculates the angle
|
|
public double GetAngleXY()
|
|
{
|
|
// Calculate and return the angle
|
|
return -Math.Atan2(-y, x) + Angle2D.PIHALF;//mxd // (float)Math.PI * 0.5f;
|
|
}
|
|
|
|
// This calculates the angle
|
|
public double GetAngleZ()
|
|
{
|
|
Vector2D xy = new Vector2D(x, y);
|
|
|
|
// Calculate and return the angle
|
|
return Math.Atan2(xy.GetLength(), z) + Angle2D.PIHALF;//mxd // (float)Math.PI * 0.5f;
|
|
}
|
|
|
|
// This calculates the length
|
|
public double GetLength()
|
|
{
|
|
// Calculate and return the length
|
|
return Math.Sqrt(x * x + y * y + z * z);
|
|
}
|
|
|
|
// This calculates the squared length
|
|
public double GetLengthSq()
|
|
{
|
|
// Calculate and return the length
|
|
return x * x + y * y + z * z;
|
|
}
|
|
|
|
// This calculates the length
|
|
public double GetManhattanLength()
|
|
{
|
|
// Calculate and return the length
|
|
return Math.Abs(x) + Math.Abs(y) + Math.Abs(z);
|
|
}
|
|
|
|
// This normalizes the vector
|
|
public Vector3D GetNormal()
|
|
{
|
|
double lensq = this.GetLengthSq();
|
|
if(lensq > TINY_VALUE)
|
|
{
|
|
// Divide each element by the length
|
|
double mul = 1f / Math.Sqrt(lensq);
|
|
return new Vector3D(x * mul, y * mul, z * mul);
|
|
}
|
|
else
|
|
{
|
|
// Cannot normalize
|
|
return new Vector3D(0f, 0f, 0f);
|
|
}
|
|
}
|
|
|
|
// This scales the vector
|
|
public Vector3D GetScaled(double s)
|
|
{
|
|
// Scale the vector
|
|
return new Vector3D(x * s, y * s, z * s);
|
|
}
|
|
|
|
// This changes the vector length
|
|
public Vector3D GetFixedLength(double l)
|
|
{
|
|
// Normalize, then scale
|
|
return this.GetNormal().GetScaled(l);
|
|
}
|
|
|
|
// This checks if the vector is normalized
|
|
public bool IsNormalized()
|
|
{
|
|
return (Math.Abs(GetLengthSq() - 1.0f) < 0.0001f);
|
|
}
|
|
|
|
// Output
|
|
public override string ToString()
|
|
{
|
|
return x + ", " + y + ", " + z;
|
|
}
|
|
|
|
// Checks if the Vector has valid values for x, y and z
|
|
public bool IsFinite()
|
|
{
|
|
return !double.IsNaN(x) && !double.IsNaN(y) && !double.IsNaN(z) && !double.IsInfinity(x) && !double.IsInfinity(y) && !double.IsInfinity(z);
|
|
}
|
|
|
|
//mxd. Addeed to make compiler a bit more happy...
|
|
public override int GetHashCode()
|
|
{
|
|
return base.GetHashCode();
|
|
}
|
|
|
|
//mxd. Addeed to make compiler a bit more happy...
|
|
public override bool Equals(object obj)
|
|
{
|
|
if(!(obj is Vector3D)) return false;
|
|
|
|
Vector3D other = (Vector3D)obj;
|
|
|
|
if(x != other.x) return false;
|
|
if(y != other.y) return false;
|
|
if(z != other.z) return false;
|
|
return true;
|
|
}
|
|
|
|
|
|
#endregion
|
|
}
|
|
}
|