267 lines
7.1 KiB
C#
267 lines
7.1 KiB
C#
//
|
||
// PositionVector4.cs - represents a tuple containing X, Y, Z, and W coordinates
|
||
//
|
||
// Author:
|
||
// Michael Becker <alcexhim@gmail.com>
|
||
//
|
||
// Copyright (c) 2013-2020 Mike Becker's Software
|
||
//
|
||
// This program is free software: you can redistribute it and/or modify
|
||
// it under the terms of the GNU General Public License as published by
|
||
// the Free Software Foundation, either version 3 of the License, or
|
||
// (at your option) any later version.
|
||
//
|
||
// 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.
|
||
//
|
||
// You should have received a copy of the GNU General Public License
|
||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
||
using System;
|
||
|
||
using Neo;
|
||
|
||
namespace UniversalEditor
|
||
{
|
||
/// <summary>
|
||
/// Represents a tuple containing X, Y, Z, and W coordinates.
|
||
/// </summary>
|
||
public struct PositionVector4 : ICloneable
|
||
{
|
||
public static readonly PositionVector4 Empty;
|
||
|
||
public double X { get; set; }
|
||
public double Y { get; set; }
|
||
public double Z { get; set; }
|
||
public double W { get; set; }
|
||
|
||
public PositionVector4(float x, float y, float z) : this(x, y, z, 1.0f) { }
|
||
public PositionVector4(double x, double y, double z) : this(x, y, z, 1.0) { }
|
||
public PositionVector4(float x, float y, float z, float w)
|
||
{
|
||
X = x;
|
||
Y = y;
|
||
Z = z;
|
||
W = w;
|
||
}
|
||
public PositionVector4(double x, double y, double z, double w)
|
||
{
|
||
X = x;
|
||
Y = y;
|
||
Z = z;
|
||
W = w;
|
||
}
|
||
public override string ToString()
|
||
{
|
||
return ToString(", ", "(", ")", 4);
|
||
}
|
||
public string ToString(string separator, string encloseStart, string encloseEnd)
|
||
{
|
||
return ToString(separator, encloseStart, encloseEnd, 4);
|
||
}
|
||
public string ToString(string separator, string encloseStart, string encloseEnd, int maxCount)
|
||
{
|
||
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||
if (encloseStart != null)
|
||
{
|
||
sb.Append(encloseStart);
|
||
}
|
||
if (maxCount >= 1)
|
||
{
|
||
sb.Append(String.Format("{0:0.0#####################}", X));
|
||
}
|
||
if (maxCount >= 2)
|
||
{
|
||
sb.Append(separator);
|
||
sb.Append(String.Format("{0:0.0#####################}", Y));
|
||
}
|
||
if (maxCount >= 3)
|
||
{
|
||
sb.Append(separator);
|
||
sb.Append(String.Format("{0:0.0#####################}", Z));
|
||
}
|
||
if (maxCount >= 4)
|
||
{
|
||
sb.Append(separator);
|
||
sb.Append(String.Format("{0:0.0#####################}", W));
|
||
}
|
||
if (encloseEnd != null)
|
||
{
|
||
sb.Append(encloseEnd);
|
||
}
|
||
return sb.ToString();
|
||
}
|
||
|
||
public static PositionVector4 operator +(PositionVector4 left, PositionVector4 right)
|
||
{
|
||
return new PositionVector4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W);
|
||
}
|
||
public static PositionVector4 operator -(PositionVector4 left, PositionVector4 right)
|
||
{
|
||
return new PositionVector4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W);
|
||
}
|
||
public static PositionVector4 operator *(PositionVector4 left, PositionVector4 right)
|
||
{
|
||
return new PositionVector4(left.X * right.X, left.Y * right.Y, left.Z * right.Z, left.W * right.W);
|
||
}
|
||
public static PositionVector4 operator /(PositionVector4 left, PositionVector4 right)
|
||
{
|
||
return new PositionVector4(left.X / right.X, left.Y / right.Y, left.Z / right.Z, left.W / right.W);
|
||
}
|
||
|
||
public double[] ToDoubleArray()
|
||
{
|
||
return new double[] { X, Y, Z, W };
|
||
}
|
||
public float[] ToFloatArray()
|
||
{
|
||
return new float[] { (float)X, (float)Y, (float)Z, (float)W };
|
||
}
|
||
|
||
public Matrix ToMatrix()
|
||
{
|
||
Matrix matrix = new Matrix(4, 4);
|
||
|
||
double x2 = X * X * 2.0f;
|
||
double y2 = Y * Y * 2.0f;
|
||
double z2 = Z * Z * 2.0f;
|
||
double xy = X * Y * 2.0f;
|
||
double yz = Y * Z * 2.0f;
|
||
double zx = Z * X * 2.0f;
|
||
double xw = X * W * 2.0f;
|
||
double yw = Y * W * 2.0f;
|
||
double zw = Z * W * 2.0f;
|
||
|
||
matrix[0, 0] = 1.0f - y2 - z2;
|
||
matrix[0, 1] = xy + zw;
|
||
matrix[0, 2] = zx - yw;
|
||
matrix[1, 0] = xy - zw;
|
||
matrix[1, 1] = 1.0f - z2 - x2;
|
||
matrix[1, 2] = yz + xw;
|
||
matrix[2, 0] = zx + yw;
|
||
matrix[2, 1] = yz - xw;
|
||
matrix[2, 2] = 1.0f - x2 - y2;
|
||
|
||
matrix[0, 3] = 0.0f;
|
||
matrix[1, 3] = 0.0f;
|
||
matrix[2, 3] = 0.0f;
|
||
matrix[3, 0] = 0.0f;
|
||
matrix[3, 1] = 0.0f;
|
||
matrix[3, 2] = 0.0f;
|
||
matrix[3, 3] = 1.0f;
|
||
return matrix;
|
||
}
|
||
|
||
public PositionVector4 Slerp(PositionVector4 pvec4Src2, float fLerpValue)
|
||
{
|
||
// Slerp
|
||
float dot = (float)((X * pvec4Src2.X) + (Y * pvec4Src2.Y) + (Z * pvec4Src2.Z) + (W * pvec4Src2.W));
|
||
|
||
// <20><><EFBFBD>]<5D><><EFBFBD><EFBFBD>
|
||
PositionVector4 vec4CorrectTarget;
|
||
|
||
if (dot < 0.0f)
|
||
{
|
||
double correctTargetX = -pvec4Src2.X;
|
||
double correctTargetY = -pvec4Src2.Y;
|
||
double correctTargetZ = -pvec4Src2.Z;
|
||
double correctTargetW = -pvec4Src2.W;
|
||
vec4CorrectTarget = new PositionVector4(correctTargetX, correctTargetY, correctTargetZ, correctTargetW);
|
||
|
||
dot = -dot;
|
||
}
|
||
else
|
||
{
|
||
vec4CorrectTarget = pvec4Src2;
|
||
}
|
||
|
||
// <20>덷<EFBFBD><EFBFBD>
|
||
if (dot >= 1.0f) { dot = 1.0f; }
|
||
float radian = (float)Math.Acos(dot);
|
||
|
||
if (Math.Abs(radian) < 0.0000000001f) { return vec4CorrectTarget; }
|
||
|
||
float inverseSin = (float)(1.0f / Math.Sin(radian));
|
||
float t0 = (float)(Math.Sin((1.0f - fLerpValue) * radian) * inverseSin);
|
||
float t1 = (float)(Math.Sin(fLerpValue * radian) * inverseSin);
|
||
|
||
double x = (X * t0 + vec4CorrectTarget.X * t1);
|
||
double y = (Y * t0 + vec4CorrectTarget.Y * t1);
|
||
double z = (Z * t0 + vec4CorrectTarget.Z * t1);
|
||
double w = (W * t0 + vec4CorrectTarget.W * t1);
|
||
return new PositionVector4(x, y, z, w);
|
||
}
|
||
|
||
public PositionVector4 Qlerp(PositionVector4 pvec4Src2, float fLerpValue)
|
||
{
|
||
// Qlerp
|
||
float qr = (float)(X * pvec4Src2.X + Y * pvec4Src2.Y + Z * pvec4Src2.Z + W * pvec4Src2.W);
|
||
float t0 = 1.0f - fLerpValue;
|
||
|
||
double x, y, z, w;
|
||
|
||
if (qr < 0)
|
||
{
|
||
x = X * t0 - pvec4Src2.X * fLerpValue;
|
||
y = Y * t0 - pvec4Src2.Y * fLerpValue;
|
||
z = Z * t0 - pvec4Src2.Z * fLerpValue;
|
||
w = W * t0 - pvec4Src2.W * fLerpValue;
|
||
}
|
||
else
|
||
{
|
||
x = X * t0 + pvec4Src2.X * fLerpValue;
|
||
y = Y * t0 + pvec4Src2.Y * fLerpValue;
|
||
z = Z * t0 + pvec4Src2.Z * fLerpValue;
|
||
w = W * t0 + pvec4Src2.W * fLerpValue;
|
||
}
|
||
|
||
PositionVector4 temp = new PositionVector4(x, y, z, w);
|
||
temp = temp.Normalize();
|
||
return temp;
|
||
}
|
||
|
||
public PositionVector4 Normalize()
|
||
{
|
||
double x, y, z, w;
|
||
float fSqr = (float)(1.0f / Math.Sqrt(X * X + Y * Y + Z * Z + W * W));
|
||
|
||
x = X * fSqr;
|
||
y = Y * fSqr;
|
||
z = Z * fSqr;
|
||
w = W * fSqr;
|
||
|
||
return new PositionVector4(x, y, z, w);
|
||
}
|
||
|
||
public object Clone()
|
||
{
|
||
PositionVector4 clone = new PositionVector4(X, Y, Z, W);
|
||
return clone;
|
||
}
|
||
|
||
public override bool Equals(object obj)
|
||
{
|
||
PositionVector4 pv = (PositionVector4)obj;
|
||
try
|
||
{
|
||
return (pv.X == X && pv.Y == Y && pv.Z == Z && pv.W == W);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
public static bool operator ==(PositionVector4 left, PositionVector4 right)
|
||
{
|
||
return left.Equals(right);
|
||
}
|
||
public static bool operator !=(PositionVector4 left, PositionVector4 right)
|
||
{
|
||
return !left.Equals(right);
|
||
}
|
||
}
|
||
}
|