Merged Cake and Abel branched into 2.0.3 (#131)
Co-authored-by: azyges <aaaaaa@aaa.aaa> Co-authored-by: cake <admin@cakeandbanana.nl> Co-authored-by: defnotken <itsdefnotken@gmail.com> Reviewed-on: #131
This commit was merged in pull request #131.
This commit is contained in:
169
LightlessSync/ThirdParty/MeshDecimator/Algorithms/DecimationAlgorithm.cs
vendored
Normal file
169
LightlessSync/ThirdParty/MeshDecimator/Algorithms/DecimationAlgorithm.cs
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
#region License
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright(c) 2017-2018 Mattias Edlund
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace MeshDecimator.Algorithms
|
||||
{
|
||||
/// <summary>
|
||||
/// A decimation algorithm.
|
||||
/// </summary>
|
||||
public abstract class DecimationAlgorithm
|
||||
{
|
||||
#region Delegates
|
||||
/// <summary>
|
||||
/// A callback for decimation status reports.
|
||||
/// </summary>
|
||||
/// <param name="iteration">The current iteration, starting at zero.</param>
|
||||
/// <param name="originalTris">The original count of triangles.</param>
|
||||
/// <param name="currentTris">The current count of triangles.</param>
|
||||
/// <param name="targetTris">The target count of triangles.</param>
|
||||
public delegate void StatusReportCallback(int iteration, int originalTris, int currentTris, int targetTris);
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
private bool preserveBorders = false;
|
||||
private int maxVertexCount = 0;
|
||||
private bool verbose = false;
|
||||
|
||||
private StatusReportCallback statusReportInvoker = null;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Gets or sets if borders should be kept.
|
||||
/// Default value: false
|
||||
/// </summary>
|
||||
[Obsolete("Use the 'DecimationAlgorithm.PreserveBorders' property instead.", false)]
|
||||
public bool KeepBorders
|
||||
{
|
||||
get { return preserveBorders; }
|
||||
set { preserveBorders = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if borders should be preserved.
|
||||
/// Default value: false
|
||||
/// </summary>
|
||||
public bool PreserveBorders
|
||||
{
|
||||
get { return preserveBorders; }
|
||||
set { preserveBorders = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if linked vertices should be kept.
|
||||
/// Default value: false
|
||||
/// </summary>
|
||||
[Obsolete("This feature has been removed, for more details why please read the readme.", true)]
|
||||
public bool KeepLinkedVertices
|
||||
{
|
||||
get { return false; }
|
||||
set { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum vertex count. Set to zero for no limitation.
|
||||
/// Default value: 0 (no limitation)
|
||||
/// </summary>
|
||||
public int MaxVertexCount
|
||||
{
|
||||
get { return maxVertexCount; }
|
||||
set { maxVertexCount = Math.MathHelper.Max(value, 0); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if verbose information should be printed in the console.
|
||||
/// Default value: false
|
||||
/// </summary>
|
||||
public bool Verbose
|
||||
{
|
||||
get { return verbose; }
|
||||
set { verbose = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the logger used for diagnostics.
|
||||
/// </summary>
|
||||
public ILogger? Logger { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
/// <summary>
|
||||
/// An event for status reports for this algorithm.
|
||||
/// </summary>
|
||||
public event StatusReportCallback StatusReport
|
||||
{
|
||||
add { statusReportInvoker += value; }
|
||||
remove { statusReportInvoker -= value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Protected Methods
|
||||
/// <summary>
|
||||
/// Reports the current status of the decimation.
|
||||
/// </summary>
|
||||
/// <param name="iteration">The current iteration, starting at zero.</param>
|
||||
/// <param name="originalTris">The original count of triangles.</param>
|
||||
/// <param name="currentTris">The current count of triangles.</param>
|
||||
/// <param name="targetTris">The target count of triangles.</param>
|
||||
protected void ReportStatus(int iteration, int originalTris, int currentTris, int targetTris)
|
||||
{
|
||||
var statusReportInvoker = this.statusReportInvoker;
|
||||
if (statusReportInvoker != null)
|
||||
{
|
||||
statusReportInvoker.Invoke(iteration, originalTris, currentTris, targetTris);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
/// <summary>
|
||||
/// Initializes the algorithm with the original mesh.
|
||||
/// </summary>
|
||||
/// <param name="mesh">The mesh.</param>
|
||||
public abstract void Initialize(Mesh mesh);
|
||||
|
||||
/// <summary>
|
||||
/// Decimates the mesh.
|
||||
/// </summary>
|
||||
/// <param name="targetTrisCount">The target triangle count.</param>
|
||||
public abstract void DecimateMesh(int targetTrisCount);
|
||||
|
||||
/// <summary>
|
||||
/// Decimates the mesh without losing any quality.
|
||||
/// </summary>
|
||||
public abstract void DecimateMeshLossless();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the resulting mesh.
|
||||
/// </summary>
|
||||
/// <returns>The resulting mesh.</returns>
|
||||
public abstract Mesh ToMesh();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
1549
LightlessSync/ThirdParty/MeshDecimator/Algorithms/FastQuadricMeshSimplification.cs
vendored
Normal file
1549
LightlessSync/ThirdParty/MeshDecimator/Algorithms/FastQuadricMeshSimplification.cs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
249
LightlessSync/ThirdParty/MeshDecimator/BoneWeight.cs
vendored
Normal file
249
LightlessSync/ThirdParty/MeshDecimator/BoneWeight.cs
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
#region License
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright(c) 2017-2018 Mattias Edlund
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using MeshDecimator.Math;
|
||||
|
||||
namespace MeshDecimator
|
||||
{
|
||||
/// <summary>
|
||||
/// A bone weight.
|
||||
/// </summary>
|
||||
public struct BoneWeight : IEquatable<BoneWeight>
|
||||
{
|
||||
#region Fields
|
||||
/// <summary>
|
||||
/// The first bone index.
|
||||
/// </summary>
|
||||
public int boneIndex0;
|
||||
/// <summary>
|
||||
/// The second bone index.
|
||||
/// </summary>
|
||||
public int boneIndex1;
|
||||
/// <summary>
|
||||
/// The third bone index.
|
||||
/// </summary>
|
||||
public int boneIndex2;
|
||||
/// <summary>
|
||||
/// The fourth bone index.
|
||||
/// </summary>
|
||||
public int boneIndex3;
|
||||
|
||||
/// <summary>
|
||||
/// The first bone weight.
|
||||
/// </summary>
|
||||
public float boneWeight0;
|
||||
/// <summary>
|
||||
/// The second bone weight.
|
||||
/// </summary>
|
||||
public float boneWeight1;
|
||||
/// <summary>
|
||||
/// The third bone weight.
|
||||
/// </summary>
|
||||
public float boneWeight2;
|
||||
/// <summary>
|
||||
/// The fourth bone weight.
|
||||
/// </summary>
|
||||
public float boneWeight3;
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
/// <summary>
|
||||
/// Creates a new bone weight.
|
||||
/// </summary>
|
||||
/// <param name="boneIndex0">The first bone index.</param>
|
||||
/// <param name="boneIndex1">The second bone index.</param>
|
||||
/// <param name="boneIndex2">The third bone index.</param>
|
||||
/// <param name="boneIndex3">The fourth bone index.</param>
|
||||
/// <param name="boneWeight0">The first bone weight.</param>
|
||||
/// <param name="boneWeight1">The second bone weight.</param>
|
||||
/// <param name="boneWeight2">The third bone weight.</param>
|
||||
/// <param name="boneWeight3">The fourth bone weight.</param>
|
||||
public BoneWeight(int boneIndex0, int boneIndex1, int boneIndex2, int boneIndex3, float boneWeight0, float boneWeight1, float boneWeight2, float boneWeight3)
|
||||
{
|
||||
this.boneIndex0 = boneIndex0;
|
||||
this.boneIndex1 = boneIndex1;
|
||||
this.boneIndex2 = boneIndex2;
|
||||
this.boneIndex3 = boneIndex3;
|
||||
|
||||
this.boneWeight0 = boneWeight0;
|
||||
this.boneWeight1 = boneWeight1;
|
||||
this.boneWeight2 = boneWeight2;
|
||||
this.boneWeight3 = boneWeight3;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
/// <summary>
|
||||
/// Returns if two bone weights equals eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side bone weight.</param>
|
||||
/// <param name="rhs">The right hand side bone weight.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public static bool operator ==(BoneWeight lhs, BoneWeight rhs)
|
||||
{
|
||||
return (lhs.boneIndex0 == rhs.boneIndex0 && lhs.boneIndex1 == rhs.boneIndex1 && lhs.boneIndex2 == rhs.boneIndex2 && lhs.boneIndex3 == rhs.boneIndex3 &&
|
||||
new Vector4(lhs.boneWeight0, lhs.boneWeight1, lhs.boneWeight2, lhs.boneWeight3) == new Vector4(rhs.boneWeight0, rhs.boneWeight1, rhs.boneWeight2, rhs.boneWeight3));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two bone weights don't equal eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side bone weight.</param>
|
||||
/// <param name="rhs">The right hand side bone weight.</param>
|
||||
/// <returns>If not equals.</returns>
|
||||
public static bool operator !=(BoneWeight lhs, BoneWeight rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private void MergeBoneWeight(int boneIndex, float weight)
|
||||
{
|
||||
if (boneIndex == boneIndex0)
|
||||
{
|
||||
boneWeight0 = (boneWeight0 + weight) * 0.5f;
|
||||
}
|
||||
else if (boneIndex == boneIndex1)
|
||||
{
|
||||
boneWeight1 = (boneWeight1 + weight) * 0.5f;
|
||||
}
|
||||
else if (boneIndex == boneIndex2)
|
||||
{
|
||||
boneWeight2 = (boneWeight2 + weight) * 0.5f;
|
||||
}
|
||||
else if (boneIndex == boneIndex3)
|
||||
{
|
||||
boneWeight3 = (boneWeight3 + weight) * 0.5f;
|
||||
}
|
||||
else if(boneWeight0 == 0f)
|
||||
{
|
||||
boneIndex0 = boneIndex;
|
||||
boneWeight0 = weight;
|
||||
}
|
||||
else if (boneWeight1 == 0f)
|
||||
{
|
||||
boneIndex1 = boneIndex;
|
||||
boneWeight1 = weight;
|
||||
}
|
||||
else if (boneWeight2 == 0f)
|
||||
{
|
||||
boneIndex2 = boneIndex;
|
||||
boneWeight2 = weight;
|
||||
}
|
||||
else if (boneWeight3 == 0f)
|
||||
{
|
||||
boneIndex3 = boneIndex;
|
||||
boneWeight3 = weight;
|
||||
}
|
||||
Normalize();
|
||||
}
|
||||
|
||||
private void Normalize()
|
||||
{
|
||||
float mag = (float)System.Math.Sqrt(boneWeight0 * boneWeight0 + boneWeight1 * boneWeight1 + boneWeight2 * boneWeight2 + boneWeight3 * boneWeight3);
|
||||
if (mag > float.Epsilon)
|
||||
{
|
||||
boneWeight0 /= mag;
|
||||
boneWeight1 /= mag;
|
||||
boneWeight2 /= mag;
|
||||
boneWeight3 /= mag;
|
||||
}
|
||||
else
|
||||
{
|
||||
boneWeight0 = boneWeight1 = boneWeight2 = boneWeight3 = 0f;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
#region Object
|
||||
/// <summary>
|
||||
/// Returns a hash code for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return boneIndex0.GetHashCode() ^ boneIndex1.GetHashCode() << 2 ^ boneIndex2.GetHashCode() >> 2 ^ boneIndex3.GetHashCode() >>
|
||||
1 ^ boneWeight0.GetHashCode() << 5 ^ boneWeight1.GetHashCode() << 4 ^ boneWeight2.GetHashCode() >> 4 ^ boneWeight3.GetHashCode() >> 3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this bone weight is equal to another object.
|
||||
/// </summary>
|
||||
/// <param name="obj">The other object to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is BoneWeight))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
BoneWeight other = (BoneWeight)obj;
|
||||
return (boneIndex0 == other.boneIndex0 && boneIndex1 == other.boneIndex1 && boneIndex2 == other.boneIndex2 && boneIndex3 == other.boneIndex3 &&
|
||||
boneWeight0 == other.boneWeight0 && boneWeight1 == other.boneWeight1 && boneWeight2 == other.boneWeight2 && boneWeight3 == other.boneWeight3);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this bone weight is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other bone weight to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public bool Equals(BoneWeight other)
|
||||
{
|
||||
return (boneIndex0 == other.boneIndex0 && boneIndex1 == other.boneIndex1 && boneIndex2 == other.boneIndex2 && boneIndex3 == other.boneIndex3 &&
|
||||
boneWeight0 == other.boneWeight0 && boneWeight1 == other.boneWeight1 && boneWeight2 == other.boneWeight2 && boneWeight3 == other.boneWeight3);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this bone weight.
|
||||
/// </summary>
|
||||
/// <returns>The string.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("({0}:{4:F1}, {1}:{5:F1}, {2}:{6:F1}, {3}:{7:F1})",
|
||||
boneIndex0, boneIndex1, boneIndex2, boneIndex3, boneWeight0, boneWeight1, boneWeight2, boneWeight3);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Static
|
||||
/// <summary>
|
||||
/// Merges two bone weights and stores the merged result in the first parameter.
|
||||
/// </summary>
|
||||
/// <param name="a">The first bone weight, also stores result.</param>
|
||||
/// <param name="b">The second bone weight.</param>
|
||||
public static void Merge(ref BoneWeight a, ref BoneWeight b)
|
||||
{
|
||||
if (b.boneWeight0 > 0f) a.MergeBoneWeight(b.boneIndex0, b.boneWeight0);
|
||||
if (b.boneWeight1 > 0f) a.MergeBoneWeight(b.boneIndex1, b.boneWeight1);
|
||||
if (b.boneWeight2 > 0f) a.MergeBoneWeight(b.boneIndex2, b.boneWeight2);
|
||||
if (b.boneWeight3 > 0f) a.MergeBoneWeight(b.boneIndex3, b.boneWeight3);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
179
LightlessSync/ThirdParty/MeshDecimator/Collections/ResizableArray.cs
vendored
Normal file
179
LightlessSync/ThirdParty/MeshDecimator/Collections/ResizableArray.cs
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
#region License
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright(c) 2017-2018 Mattias Edlund
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace MeshDecimator.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// A resizable array.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The item type.</typeparam>
|
||||
internal sealed class ResizableArray<T>
|
||||
{
|
||||
#region Fields
|
||||
private T[] items = null;
|
||||
private int length = 0;
|
||||
|
||||
private static T[] emptyArr = new T[0];
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Gets the length of this array.
|
||||
/// </summary>
|
||||
public int Length
|
||||
{
|
||||
get { return length; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the internal data buffer for this array.
|
||||
/// </summary>
|
||||
public T[] Data
|
||||
{
|
||||
get { return items; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the element value at a specific index.
|
||||
/// </summary>
|
||||
/// <param name="index">The element index.</param>
|
||||
/// <returns>The element value.</returns>
|
||||
public T this[int index]
|
||||
{
|
||||
get { return items[index]; }
|
||||
set { items[index] = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
/// <summary>
|
||||
/// Creates a new resizable array.
|
||||
/// </summary>
|
||||
/// <param name="capacity">The initial array capacity.</param>
|
||||
public ResizableArray(int capacity)
|
||||
: this(capacity, 0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new resizable array.
|
||||
/// </summary>
|
||||
/// <param name="capacity">The initial array capacity.</param>
|
||||
/// <param name="length">The initial length of the array.</param>
|
||||
public ResizableArray(int capacity, int length)
|
||||
{
|
||||
if (capacity < 0)
|
||||
throw new ArgumentOutOfRangeException("capacity");
|
||||
else if (length < 0 || length > capacity)
|
||||
throw new ArgumentOutOfRangeException("length");
|
||||
|
||||
if (capacity > 0)
|
||||
items = new T[capacity];
|
||||
else
|
||||
items = emptyArr;
|
||||
|
||||
this.length = length;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private void IncreaseCapacity(int capacity)
|
||||
{
|
||||
T[] newItems = new T[capacity];
|
||||
Array.Copy(items, 0, newItems, 0, System.Math.Min(length, capacity));
|
||||
items = newItems;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
/// <summary>
|
||||
/// Clears this array.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
Array.Clear(items, 0, length);
|
||||
length = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resizes this array.
|
||||
/// </summary>
|
||||
/// <param name="length">The new length.</param>
|
||||
/// <param name="trimExess">If exess memory should be trimmed.</param>
|
||||
public void Resize(int length, bool trimExess = false)
|
||||
{
|
||||
if (length < 0)
|
||||
throw new ArgumentOutOfRangeException("capacity");
|
||||
|
||||
if (length > items.Length)
|
||||
{
|
||||
IncreaseCapacity(length);
|
||||
}
|
||||
else if (length < this.length)
|
||||
{
|
||||
//Array.Clear(items, capacity, length - capacity);
|
||||
}
|
||||
|
||||
this.length = length;
|
||||
|
||||
if (trimExess)
|
||||
{
|
||||
TrimExcess();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trims any excess memory for this array.
|
||||
/// </summary>
|
||||
public void TrimExcess()
|
||||
{
|
||||
if (items.Length == length) // Nothing to do
|
||||
return;
|
||||
|
||||
T[] newItems = new T[length];
|
||||
Array.Copy(items, 0, newItems, 0, length);
|
||||
items = newItems;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new item to the end of this array.
|
||||
/// </summary>
|
||||
/// <param name="item">The new item.</param>
|
||||
public void Add(T item)
|
||||
{
|
||||
if (length >= items.Length)
|
||||
{
|
||||
IncreaseCapacity(items.Length << 1);
|
||||
}
|
||||
|
||||
items[length++] = item;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
79
LightlessSync/ThirdParty/MeshDecimator/Collections/UVChannels.cs
vendored
Normal file
79
LightlessSync/ThirdParty/MeshDecimator/Collections/UVChannels.cs
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
|
||||
namespace MeshDecimator.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// A collection of UV channels.
|
||||
/// </summary>
|
||||
/// <typeparam name="TVec">The UV vector type.</typeparam>
|
||||
internal sealed class UVChannels<TVec>
|
||||
{
|
||||
#region Fields
|
||||
private ResizableArray<TVec>[] channels = null;
|
||||
private TVec[][] channelsData = null;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Gets the channel collection data.
|
||||
/// </summary>
|
||||
public TVec[][] Data
|
||||
{
|
||||
get
|
||||
{
|
||||
for (int i = 0; i < Mesh.UVChannelCount; i++)
|
||||
{
|
||||
if (channels[i] != null)
|
||||
{
|
||||
channelsData[i] = channels[i].Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
channelsData[i] = null;
|
||||
}
|
||||
}
|
||||
return channelsData;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a specific channel by index.
|
||||
/// </summary>
|
||||
/// <param name="index">The channel index.</param>
|
||||
public ResizableArray<TVec> this[int index]
|
||||
{
|
||||
get { return channels[index]; }
|
||||
set { channels[index] = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
/// <summary>
|
||||
/// Creates a new collection of UV channels.
|
||||
/// </summary>
|
||||
public UVChannels()
|
||||
{
|
||||
channels = new ResizableArray<TVec>[Mesh.UVChannelCount];
|
||||
channelsData = new TVec[Mesh.UVChannelCount][];
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
/// <summary>
|
||||
/// Resizes all channels at once.
|
||||
/// </summary>
|
||||
/// <param name="capacity">The new capacity.</param>
|
||||
/// <param name="trimExess">If exess memory should be trimmed.</param>
|
||||
public void Resize(int capacity, bool trimExess = false)
|
||||
{
|
||||
for (int i = 0; i < Mesh.UVChannelCount; i++)
|
||||
{
|
||||
if (channels[i] != null)
|
||||
{
|
||||
channels[i].Resize(capacity, trimExess);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
21
LightlessSync/ThirdParty/MeshDecimator/LICENSE.md
vendored
Normal file
21
LightlessSync/ThirdParty/MeshDecimator/LICENSE.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017-2018 Mattias Edlund
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
286
LightlessSync/ThirdParty/MeshDecimator/Math/MathHelper.cs
vendored
Normal file
286
LightlessSync/ThirdParty/MeshDecimator/Math/MathHelper.cs
vendored
Normal file
@@ -0,0 +1,286 @@
|
||||
#region License
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright(c) 2017-2018 Mattias Edlund
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace MeshDecimator.Math
|
||||
{
|
||||
/// <summary>
|
||||
/// Math helpers.
|
||||
/// </summary>
|
||||
public static class MathHelper
|
||||
{
|
||||
#region Consts
|
||||
/// <summary>
|
||||
/// The Pi constant.
|
||||
/// </summary>
|
||||
public const float PI = 3.14159274f;
|
||||
|
||||
/// <summary>
|
||||
/// The Pi constant.
|
||||
/// </summary>
|
||||
public const double PId = 3.1415926535897932384626433832795;
|
||||
|
||||
/// <summary>
|
||||
/// Degrees to radian constant.
|
||||
/// </summary>
|
||||
public const float Deg2Rad = PI / 180f;
|
||||
|
||||
/// <summary>
|
||||
/// Degrees to radian constant.
|
||||
/// </summary>
|
||||
public const double Deg2Radd = PId / 180.0;
|
||||
|
||||
/// <summary>
|
||||
/// Radians to degrees constant.
|
||||
/// </summary>
|
||||
public const float Rad2Deg = 180f / PI;
|
||||
|
||||
/// <summary>
|
||||
/// Radians to degrees constant.
|
||||
/// </summary>
|
||||
public const double Rad2Degd = 180.0 / PId;
|
||||
#endregion
|
||||
|
||||
#region Min
|
||||
/// <summary>
|
||||
/// Returns the minimum of two values.
|
||||
/// </summary>
|
||||
/// <param name="val1">The first value.</param>
|
||||
/// <param name="val2">The second value.</param>
|
||||
/// <returns>The minimum value.</returns>
|
||||
public static int Min(int val1, int val2)
|
||||
{
|
||||
return (val1 < val2 ? val1 : val2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the minimum of three values.
|
||||
/// </summary>
|
||||
/// <param name="val1">The first value.</param>
|
||||
/// <param name="val2">The second value.</param>
|
||||
/// <param name="val3">The third value.</param>
|
||||
/// <returns>The minimum value.</returns>
|
||||
public static int Min(int val1, int val2, int val3)
|
||||
{
|
||||
return (val1 < val2 ? (val1 < val3 ? val1 : val3) : (val2 < val3 ? val2 : val3));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the minimum of two values.
|
||||
/// </summary>
|
||||
/// <param name="val1">The first value.</param>
|
||||
/// <param name="val2">The second value.</param>
|
||||
/// <returns>The minimum value.</returns>
|
||||
public static float Min(float val1, float val2)
|
||||
{
|
||||
return (val1 < val2 ? val1 : val2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the minimum of three values.
|
||||
/// </summary>
|
||||
/// <param name="val1">The first value.</param>
|
||||
/// <param name="val2">The second value.</param>
|
||||
/// <param name="val3">The third value.</param>
|
||||
/// <returns>The minimum value.</returns>
|
||||
public static float Min(float val1, float val2, float val3)
|
||||
{
|
||||
return (val1 < val2 ? (val1 < val3 ? val1 : val3) : (val2 < val3 ? val2 : val3));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the minimum of two values.
|
||||
/// </summary>
|
||||
/// <param name="val1">The first value.</param>
|
||||
/// <param name="val2">The second value.</param>
|
||||
/// <returns>The minimum value.</returns>
|
||||
public static double Min(double val1, double val2)
|
||||
{
|
||||
return (val1 < val2 ? val1 : val2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the minimum of three values.
|
||||
/// </summary>
|
||||
/// <param name="val1">The first value.</param>
|
||||
/// <param name="val2">The second value.</param>
|
||||
/// <param name="val3">The third value.</param>
|
||||
/// <returns>The minimum value.</returns>
|
||||
public static double Min(double val1, double val2, double val3)
|
||||
{
|
||||
return (val1 < val2 ? (val1 < val3 ? val1 : val3) : (val2 < val3 ? val2 : val3));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Max
|
||||
/// <summary>
|
||||
/// Returns the maximum of two values.
|
||||
/// </summary>
|
||||
/// <param name="val1">The first value.</param>
|
||||
/// <param name="val2">The second value.</param>
|
||||
/// <returns>The maximum value.</returns>
|
||||
public static int Max(int val1, int val2)
|
||||
{
|
||||
return (val1 > val2 ? val1 : val2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the maximum of three values.
|
||||
/// </summary>
|
||||
/// <param name="val1">The first value.</param>
|
||||
/// <param name="val2">The second value.</param>
|
||||
/// <param name="val3">The third value.</param>
|
||||
/// <returns>The maximum value.</returns>
|
||||
public static int Max(int val1, int val2, int val3)
|
||||
{
|
||||
return (val1 > val2 ? (val1 > val3 ? val1 : val3) : (val2 > val3 ? val2 : val3));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the maximum of two values.
|
||||
/// </summary>
|
||||
/// <param name="val1">The first value.</param>
|
||||
/// <param name="val2">The second value.</param>
|
||||
/// <returns>The maximum value.</returns>
|
||||
public static float Max(float val1, float val2)
|
||||
{
|
||||
return (val1 > val2 ? val1 : val2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the maximum of three values.
|
||||
/// </summary>
|
||||
/// <param name="val1">The first value.</param>
|
||||
/// <param name="val2">The second value.</param>
|
||||
/// <param name="val3">The third value.</param>
|
||||
/// <returns>The maximum value.</returns>
|
||||
public static float Max(float val1, float val2, float val3)
|
||||
{
|
||||
return (val1 > val2 ? (val1 > val3 ? val1 : val3) : (val2 > val3 ? val2 : val3));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the maximum of two values.
|
||||
/// </summary>
|
||||
/// <param name="val1">The first value.</param>
|
||||
/// <param name="val2">The second value.</param>
|
||||
/// <returns>The maximum value.</returns>
|
||||
public static double Max(double val1, double val2)
|
||||
{
|
||||
return (val1 > val2 ? val1 : val2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the maximum of three values.
|
||||
/// </summary>
|
||||
/// <param name="val1">The first value.</param>
|
||||
/// <param name="val2">The second value.</param>
|
||||
/// <param name="val3">The third value.</param>
|
||||
/// <returns>The maximum value.</returns>
|
||||
public static double Max(double val1, double val2, double val3)
|
||||
{
|
||||
return (val1 > val2 ? (val1 > val3 ? val1 : val3) : (val2 > val3 ? val2 : val3));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Clamping
|
||||
/// <summary>
|
||||
/// Clamps a value between a minimum and a maximum value.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to clamp.</param>
|
||||
/// <param name="min">The minimum value.</param>
|
||||
/// <param name="max">The maximum value.</param>
|
||||
/// <returns>The clamped value.</returns>
|
||||
public static float Clamp(float value, float min, float max)
|
||||
{
|
||||
return (value >= min ? (value <= max ? value : max) : min);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps a value between a minimum and a maximum value.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to clamp.</param>
|
||||
/// <param name="min">The minimum value.</param>
|
||||
/// <param name="max">The maximum value.</param>
|
||||
/// <returns>The clamped value.</returns>
|
||||
public static double Clamp(double value, double min, double max)
|
||||
{
|
||||
return (value >= min ? (value <= max ? value : max) : min);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps the value between 0 and 1.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to clamp.</param>
|
||||
/// <returns>The clamped value.</returns>
|
||||
public static float Clamp01(float value)
|
||||
{
|
||||
return (value > 0f ? (value < 1f ? value : 1f) : 0f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps the value between 0 and 1.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to clamp.</param>
|
||||
/// <returns>The clamped value.</returns>
|
||||
public static double Clamp01(double value)
|
||||
{
|
||||
return (value > 0.0 ? (value < 1.0 ? value : 1.0) : 0.0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Triangle Area
|
||||
/// <summary>
|
||||
/// Calculates the area of a triangle.
|
||||
/// </summary>
|
||||
/// <param name="p0">The first point.</param>
|
||||
/// <param name="p1">The second point.</param>
|
||||
/// <param name="p2">The third point.</param>
|
||||
/// <returns>The triangle area.</returns>
|
||||
public static float TriangleArea(ref Vector3 p0, ref Vector3 p1, ref Vector3 p2)
|
||||
{
|
||||
var dx = p1 - p0;
|
||||
var dy = p2 - p0;
|
||||
return dx.Magnitude * ((float)System.Math.Sin(Vector3.Angle(ref dx, ref dy) * Deg2Rad) * dy.Magnitude) * 0.5f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the area of a triangle.
|
||||
/// </summary>
|
||||
/// <param name="p0">The first point.</param>
|
||||
/// <param name="p1">The second point.</param>
|
||||
/// <param name="p2">The third point.</param>
|
||||
/// <returns>The triangle area.</returns>
|
||||
public static double TriangleArea(ref Vector3d p0, ref Vector3d p1, ref Vector3d p2)
|
||||
{
|
||||
var dx = p1 - p0;
|
||||
var dy = p2 - p0;
|
||||
return dx.Magnitude * (System.Math.Sin(Vector3d.Angle(ref dx, ref dy) * Deg2Radd) * dy.Magnitude) * 0.5f;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
303
LightlessSync/ThirdParty/MeshDecimator/Math/SymmetricMatrix.cs
vendored
Normal file
303
LightlessSync/ThirdParty/MeshDecimator/Math/SymmetricMatrix.cs
vendored
Normal file
@@ -0,0 +1,303 @@
|
||||
#region License
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright(c) 2017-2018 Mattias Edlund
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace MeshDecimator.Math
|
||||
{
|
||||
/// <summary>
|
||||
/// A symmetric matrix.
|
||||
/// </summary>
|
||||
public struct SymmetricMatrix
|
||||
{
|
||||
#region Fields
|
||||
/// <summary>
|
||||
/// The m11 component.
|
||||
/// </summary>
|
||||
public double m0;
|
||||
/// <summary>
|
||||
/// The m12 component.
|
||||
/// </summary>
|
||||
public double m1;
|
||||
/// <summary>
|
||||
/// The m13 component.
|
||||
/// </summary>
|
||||
public double m2;
|
||||
/// <summary>
|
||||
/// The m14 component.
|
||||
/// </summary>
|
||||
public double m3;
|
||||
/// <summary>
|
||||
/// The m22 component.
|
||||
/// </summary>
|
||||
public double m4;
|
||||
/// <summary>
|
||||
/// The m23 component.
|
||||
/// </summary>
|
||||
public double m5;
|
||||
/// <summary>
|
||||
/// The m24 component.
|
||||
/// </summary>
|
||||
public double m6;
|
||||
/// <summary>
|
||||
/// The m33 component.
|
||||
/// </summary>
|
||||
public double m7;
|
||||
/// <summary>
|
||||
/// The m34 component.
|
||||
/// </summary>
|
||||
public double m8;
|
||||
/// <summary>
|
||||
/// The m44 component.
|
||||
/// </summary>
|
||||
public double m9;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Gets the component value with a specific index.
|
||||
/// </summary>
|
||||
/// <param name="index">The component index.</param>
|
||||
/// <returns>The value.</returns>
|
||||
public double this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return m0;
|
||||
case 1:
|
||||
return m1;
|
||||
case 2:
|
||||
return m2;
|
||||
case 3:
|
||||
return m3;
|
||||
case 4:
|
||||
return m4;
|
||||
case 5:
|
||||
return m5;
|
||||
case 6:
|
||||
return m6;
|
||||
case 7:
|
||||
return m7;
|
||||
case 8:
|
||||
return m8;
|
||||
case 9:
|
||||
return m9;
|
||||
default:
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
/// <summary>
|
||||
/// Creates a symmetric matrix with a value in each component.
|
||||
/// </summary>
|
||||
/// <param name="c">The component value.</param>
|
||||
public SymmetricMatrix(double c)
|
||||
{
|
||||
this.m0 = c;
|
||||
this.m1 = c;
|
||||
this.m2 = c;
|
||||
this.m3 = c;
|
||||
this.m4 = c;
|
||||
this.m5 = c;
|
||||
this.m6 = c;
|
||||
this.m7 = c;
|
||||
this.m8 = c;
|
||||
this.m9 = c;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a symmetric matrix.
|
||||
/// </summary>
|
||||
/// <param name="m0">The m11 component.</param>
|
||||
/// <param name="m1">The m12 component.</param>
|
||||
/// <param name="m2">The m13 component.</param>
|
||||
/// <param name="m3">The m14 component.</param>
|
||||
/// <param name="m4">The m22 component.</param>
|
||||
/// <param name="m5">The m23 component.</param>
|
||||
/// <param name="m6">The m24 component.</param>
|
||||
/// <param name="m7">The m33 component.</param>
|
||||
/// <param name="m8">The m34 component.</param>
|
||||
/// <param name="m9">The m44 component.</param>
|
||||
public SymmetricMatrix(double m0, double m1, double m2, double m3,
|
||||
double m4, double m5, double m6, double m7, double m8, double m9)
|
||||
{
|
||||
this.m0 = m0;
|
||||
this.m1 = m1;
|
||||
this.m2 = m2;
|
||||
this.m3 = m3;
|
||||
this.m4 = m4;
|
||||
this.m5 = m5;
|
||||
this.m6 = m6;
|
||||
this.m7 = m7;
|
||||
this.m8 = m8;
|
||||
this.m9 = m9;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a symmetric matrix from a plane.
|
||||
/// </summary>
|
||||
/// <param name="a">The plane x-component.</param>
|
||||
/// <param name="b">The plane y-component</param>
|
||||
/// <param name="c">The plane z-component</param>
|
||||
/// <param name="d">The plane w-component</param>
|
||||
public SymmetricMatrix(double a, double b, double c, double d)
|
||||
{
|
||||
this.m0 = a * a;
|
||||
this.m1 = a * b;
|
||||
this.m2 = a * c;
|
||||
this.m3 = a * d;
|
||||
|
||||
this.m4 = b * b;
|
||||
this.m5 = b * c;
|
||||
this.m6 = b * d;
|
||||
|
||||
this.m7 = c * c;
|
||||
this.m8 = c * d;
|
||||
|
||||
this.m9 = d * d;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
/// <summary>
|
||||
/// Adds two matrixes together.
|
||||
/// </summary>
|
||||
/// <param name="a">The left hand side.</param>
|
||||
/// <param name="b">The right hand side.</param>
|
||||
/// <returns>The resulting matrix.</returns>
|
||||
public static SymmetricMatrix operator +(SymmetricMatrix a, SymmetricMatrix b)
|
||||
{
|
||||
return new SymmetricMatrix(
|
||||
a.m0 + b.m0, a.m1 + b.m1, a.m2 + b.m2, a.m3 + b.m3,
|
||||
a.m4 + b.m4, a.m5 + b.m5, a.m6 + b.m6,
|
||||
a.m7 + b.m7, a.m8 + b.m8,
|
||||
a.m9 + b.m9
|
||||
);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Internal Methods
|
||||
/// <summary>
|
||||
/// Determinant(0, 1, 2, 1, 4, 5, 2, 5, 7)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal double Determinant1()
|
||||
{
|
||||
double det =
|
||||
m0 * m4 * m7 +
|
||||
m2 * m1 * m5 +
|
||||
m1 * m5 * m2 -
|
||||
m2 * m4 * m2 -
|
||||
m0 * m5 * m5 -
|
||||
m1 * m1 * m7;
|
||||
return det;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determinant(1, 2, 3, 4, 5, 6, 5, 7, 8)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal double Determinant2()
|
||||
{
|
||||
double det =
|
||||
m1 * m5 * m8 +
|
||||
m3 * m4 * m7 +
|
||||
m2 * m6 * m5 -
|
||||
m3 * m5 * m5 -
|
||||
m1 * m6 * m7 -
|
||||
m2 * m4 * m8;
|
||||
return det;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determinant(0, 2, 3, 1, 5, 6, 2, 7, 8)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal double Determinant3()
|
||||
{
|
||||
double det =
|
||||
m0 * m5 * m8 +
|
||||
m3 * m1 * m7 +
|
||||
m2 * m6 * m2 -
|
||||
m3 * m5 * m2 -
|
||||
m0 * m6 * m7 -
|
||||
m2 * m1 * m8;
|
||||
return det;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determinant(0, 1, 3, 1, 4, 6, 2, 5, 8)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal double Determinant4()
|
||||
{
|
||||
double det =
|
||||
m0 * m4 * m8 +
|
||||
m3 * m1 * m5 +
|
||||
m1 * m6 * m2 -
|
||||
m3 * m4 * m2 -
|
||||
m0 * m6 * m5 -
|
||||
m1 * m1 * m8;
|
||||
return det;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
/// <summary>
|
||||
/// Computes the determinant of this matrix.
|
||||
/// </summary>
|
||||
/// <param name="a11">The a11 index.</param>
|
||||
/// <param name="a12">The a12 index.</param>
|
||||
/// <param name="a13">The a13 index.</param>
|
||||
/// <param name="a21">The a21 index.</param>
|
||||
/// <param name="a22">The a22 index.</param>
|
||||
/// <param name="a23">The a23 index.</param>
|
||||
/// <param name="a31">The a31 index.</param>
|
||||
/// <param name="a32">The a32 index.</param>
|
||||
/// <param name="a33">The a33 index.</param>
|
||||
/// <returns>The determinant value.</returns>
|
||||
public double Determinant(int a11, int a12, int a13,
|
||||
int a21, int a22, int a23,
|
||||
int a31, int a32, int a33)
|
||||
{
|
||||
double det =
|
||||
this[a11] * this[a22] * this[a33] +
|
||||
this[a13] * this[a21] * this[a32] +
|
||||
this[a12] * this[a23] * this[a31] -
|
||||
this[a13] * this[a22] * this[a31] -
|
||||
this[a11] * this[a23] * this[a32] -
|
||||
this[a12] * this[a21] * this[a33];
|
||||
return det;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
425
LightlessSync/ThirdParty/MeshDecimator/Math/Vector2.cs
vendored
Normal file
425
LightlessSync/ThirdParty/MeshDecimator/Math/Vector2.cs
vendored
Normal file
@@ -0,0 +1,425 @@
|
||||
#region License
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright(c) 2017-2018 Mattias Edlund
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace MeshDecimator.Math
|
||||
{
|
||||
/// <summary>
|
||||
/// A single precision 2D vector.
|
||||
/// </summary>
|
||||
public struct Vector2 : IEquatable<Vector2>
|
||||
{
|
||||
#region Static Read-Only
|
||||
/// <summary>
|
||||
/// The zero vector.
|
||||
/// </summary>
|
||||
public static readonly Vector2 zero = new Vector2(0, 0);
|
||||
#endregion
|
||||
|
||||
#region Consts
|
||||
/// <summary>
|
||||
/// The vector epsilon.
|
||||
/// </summary>
|
||||
public const float Epsilon = 9.99999944E-11f;
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
/// <summary>
|
||||
/// The x component.
|
||||
/// </summary>
|
||||
public float x;
|
||||
/// <summary>
|
||||
/// The y component.
|
||||
/// </summary>
|
||||
public float y;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Gets the magnitude of this vector.
|
||||
/// </summary>
|
||||
public float Magnitude
|
||||
{
|
||||
get { return (float)System.Math.Sqrt(x * x + y * y); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the squared magnitude of this vector.
|
||||
/// </summary>
|
||||
public float MagnitudeSqr
|
||||
{
|
||||
get { return (x * x + y * y); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a normalized vector from this vector.
|
||||
/// </summary>
|
||||
public Vector2 Normalized
|
||||
{
|
||||
get
|
||||
{
|
||||
Vector2 result;
|
||||
Normalize(ref this, out result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a specific component by index in this vector.
|
||||
/// </summary>
|
||||
/// <param name="index">The component index.</param>
|
||||
public float this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return x;
|
||||
case 1:
|
||||
return y;
|
||||
default:
|
||||
throw new IndexOutOfRangeException("Invalid Vector2 index!");
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
x = value;
|
||||
break;
|
||||
case 1:
|
||||
y = value;
|
||||
break;
|
||||
default:
|
||||
throw new IndexOutOfRangeException("Invalid Vector2 index!");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
/// <summary>
|
||||
/// Creates a new vector with one value for all components.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
public Vector2(float value)
|
||||
{
|
||||
this.x = value;
|
||||
this.y = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The x value.</param>
|
||||
/// <param name="y">The y value.</param>
|
||||
public Vector2(float x, float y)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
/// <summary>
|
||||
/// Adds two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector2 operator +(Vector2 a, Vector2 b)
|
||||
{
|
||||
return new Vector2(a.x + b.x, a.y + b.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector2 operator -(Vector2 a, Vector2 b)
|
||||
{
|
||||
return new Vector2(a.x - b.x, a.y - b.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the vector uniformly.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <param name="d">The scaling value.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector2 operator *(Vector2 a, float d)
|
||||
{
|
||||
return new Vector2(a.x * d, a.y * d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the vector uniformly.
|
||||
/// </summary>
|
||||
/// <param name="d">The scaling value.</param>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector2 operator *(float d, Vector2 a)
|
||||
{
|
||||
return new Vector2(a.x * d, a.y * d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the vector with a float.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <param name="d">The dividing float value.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector2 operator /(Vector2 a, float d)
|
||||
{
|
||||
return new Vector2(a.x / d, a.y / d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the vector from a zero vector.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector2 operator -(Vector2 a)
|
||||
{
|
||||
return new Vector2(-a.x, -a.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two vectors equals eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public static bool operator ==(Vector2 lhs, Vector2 rhs)
|
||||
{
|
||||
return (lhs - rhs).MagnitudeSqr < Epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two vectors don't equal eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <returns>If not equals.</returns>
|
||||
public static bool operator !=(Vector2 lhs, Vector2 rhs)
|
||||
{
|
||||
return (lhs - rhs).MagnitudeSqr >= Epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Explicitly converts from a double-precision vector into a single-precision vector.
|
||||
/// </summary>
|
||||
/// <param name="v">The double-precision vector.</param>
|
||||
public static explicit operator Vector2(Vector2d v)
|
||||
{
|
||||
return new Vector2((float)v.x, (float)v.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly converts from an integer vector into a single-precision vector.
|
||||
/// </summary>
|
||||
/// <param name="v">The integer vector.</param>
|
||||
public static implicit operator Vector2(Vector2i v)
|
||||
{
|
||||
return new Vector2(v.x, v.y);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
#region Instance
|
||||
/// <summary>
|
||||
/// Set x and y components of an existing vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The x value.</param>
|
||||
/// <param name="y">The y value.</param>
|
||||
public void Set(float x, float y)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies with another vector component-wise.
|
||||
/// </summary>
|
||||
/// <param name="scale">The vector to multiply with.</param>
|
||||
public void Scale(ref Vector2 scale)
|
||||
{
|
||||
x *= scale.x;
|
||||
y *= scale.y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes this vector.
|
||||
/// </summary>
|
||||
public void Normalize()
|
||||
{
|
||||
float mag = this.Magnitude;
|
||||
if (mag > Epsilon)
|
||||
{
|
||||
x /= mag;
|
||||
y /= mag;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps this vector between a specific range.
|
||||
/// </summary>
|
||||
/// <param name="min">The minimum component value.</param>
|
||||
/// <param name="max">The maximum component value.</param>
|
||||
public void Clamp(float min, float max)
|
||||
{
|
||||
if (x < min) x = min;
|
||||
else if (x > max) x = max;
|
||||
|
||||
if (y < min) y = min;
|
||||
else if (y > max) y = max;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Object
|
||||
/// <summary>
|
||||
/// Returns a hash code for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return x.GetHashCode() ^ y.GetHashCode() << 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this vector is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
if (!(other is Vector2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Vector2 vector = (Vector2)other;
|
||||
return (x == vector.x && y == vector.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this vector is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public bool Equals(Vector2 other)
|
||||
{
|
||||
return (x == other.x && y == other.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The string.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("({0}, {1})",
|
||||
x.ToString("F1", CultureInfo.InvariantCulture),
|
||||
y.ToString("F1", CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this vector.
|
||||
/// </summary>
|
||||
/// <param name="format">The float format.</param>
|
||||
/// <returns>The string.</returns>
|
||||
public string ToString(string format)
|
||||
{
|
||||
return string.Format("({0}, {1})",
|
||||
x.ToString(format, CultureInfo.InvariantCulture),
|
||||
y.ToString(format, CultureInfo.InvariantCulture));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Static
|
||||
/// <summary>
|
||||
/// Dot Product of two vectors.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
public static float Dot(ref Vector2 lhs, ref Vector2 rhs)
|
||||
{
|
||||
return lhs.x * rhs.x + lhs.y * rhs.y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a linear interpolation between two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector to interpolate from.</param>
|
||||
/// <param name="b">The vector to interpolate to.</param>
|
||||
/// <param name="t">The time fraction.</param>
|
||||
/// <param name="result">The resulting vector.</param>
|
||||
public static void Lerp(ref Vector2 a, ref Vector2 b, float t, out Vector2 result)
|
||||
{
|
||||
result = new Vector2(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies two vectors component-wise.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <param name="result">The resulting vector.</param>
|
||||
public static void Scale(ref Vector2 a, ref Vector2 b, out Vector2 result)
|
||||
{
|
||||
result = new Vector2(a.x * b.x, a.y * b.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes a vector.
|
||||
/// </summary>
|
||||
/// <param name="value">The vector to normalize.</param>
|
||||
/// <param name="result">The resulting normalized vector.</param>
|
||||
public static void Normalize(ref Vector2 value, out Vector2 result)
|
||||
{
|
||||
float mag = value.Magnitude;
|
||||
if (mag > Epsilon)
|
||||
{
|
||||
result = new Vector2(value.x / mag, value.y / mag);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = Vector2.zero;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
425
LightlessSync/ThirdParty/MeshDecimator/Math/Vector2d.cs
vendored
Normal file
425
LightlessSync/ThirdParty/MeshDecimator/Math/Vector2d.cs
vendored
Normal file
@@ -0,0 +1,425 @@
|
||||
#region License
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright(c) 2017-2018 Mattias Edlund
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace MeshDecimator.Math
|
||||
{
|
||||
/// <summary>
|
||||
/// A double precision 2D vector.
|
||||
/// </summary>
|
||||
public struct Vector2d : IEquatable<Vector2d>
|
||||
{
|
||||
#region Static Read-Only
|
||||
/// <summary>
|
||||
/// The zero vector.
|
||||
/// </summary>
|
||||
public static readonly Vector2d zero = new Vector2d(0, 0);
|
||||
#endregion
|
||||
|
||||
#region Consts
|
||||
/// <summary>
|
||||
/// The vector epsilon.
|
||||
/// </summary>
|
||||
public const double Epsilon = double.Epsilon;
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
/// <summary>
|
||||
/// The x component.
|
||||
/// </summary>
|
||||
public double x;
|
||||
/// <summary>
|
||||
/// The y component.
|
||||
/// </summary>
|
||||
public double y;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Gets the magnitude of this vector.
|
||||
/// </summary>
|
||||
public double Magnitude
|
||||
{
|
||||
get { return System.Math.Sqrt(x * x + y * y); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the squared magnitude of this vector.
|
||||
/// </summary>
|
||||
public double MagnitudeSqr
|
||||
{
|
||||
get { return (x * x + y * y); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a normalized vector from this vector.
|
||||
/// </summary>
|
||||
public Vector2d Normalized
|
||||
{
|
||||
get
|
||||
{
|
||||
Vector2d result;
|
||||
Normalize(ref this, out result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a specific component by index in this vector.
|
||||
/// </summary>
|
||||
/// <param name="index">The component index.</param>
|
||||
public double this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return x;
|
||||
case 1:
|
||||
return y;
|
||||
default:
|
||||
throw new IndexOutOfRangeException("Invalid Vector2d index!");
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
x = value;
|
||||
break;
|
||||
case 1:
|
||||
y = value;
|
||||
break;
|
||||
default:
|
||||
throw new IndexOutOfRangeException("Invalid Vector2d index!");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
/// <summary>
|
||||
/// Creates a new vector with one value for all components.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
public Vector2d(double value)
|
||||
{
|
||||
this.x = value;
|
||||
this.y = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The x value.</param>
|
||||
/// <param name="y">The y value.</param>
|
||||
public Vector2d(double x, double y)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
/// <summary>
|
||||
/// Adds two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector2d operator +(Vector2d a, Vector2d b)
|
||||
{
|
||||
return new Vector2d(a.x + b.x, a.y + b.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector2d operator -(Vector2d a, Vector2d b)
|
||||
{
|
||||
return new Vector2d(a.x - b.x, a.y - b.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the vector uniformly.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <param name="d">The scaling value.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector2d operator *(Vector2d a, double d)
|
||||
{
|
||||
return new Vector2d(a.x * d, a.y * d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the vector uniformly.
|
||||
/// </summary>
|
||||
/// <param name="d">The scaling value.</param>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector2d operator *(double d, Vector2d a)
|
||||
{
|
||||
return new Vector2d(a.x * d, a.y * d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the vector with a float.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <param name="d">The dividing float value.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector2d operator /(Vector2d a, double d)
|
||||
{
|
||||
return new Vector2d(a.x / d, a.y / d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the vector from a zero vector.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector2d operator -(Vector2d a)
|
||||
{
|
||||
return new Vector2d(-a.x, -a.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two vectors equals eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public static bool operator ==(Vector2d lhs, Vector2d rhs)
|
||||
{
|
||||
return (lhs - rhs).MagnitudeSqr < Epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two vectors don't equal eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <returns>If not equals.</returns>
|
||||
public static bool operator !=(Vector2d lhs, Vector2d rhs)
|
||||
{
|
||||
return (lhs - rhs).MagnitudeSqr >= Epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly converts from a single-precision vector into a double-precision vector.
|
||||
/// </summary>
|
||||
/// <param name="v">The single-precision vector.</param>
|
||||
public static implicit operator Vector2d(Vector2 v)
|
||||
{
|
||||
return new Vector2d(v.x, v.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly converts from an integer vector into a double-precision vector.
|
||||
/// </summary>
|
||||
/// <param name="v">The integer vector.</param>
|
||||
public static implicit operator Vector2d(Vector2i v)
|
||||
{
|
||||
return new Vector2d(v.x, v.y);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
#region Instance
|
||||
/// <summary>
|
||||
/// Set x and y components of an existing vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The x value.</param>
|
||||
/// <param name="y">The y value.</param>
|
||||
public void Set(double x, double y)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies with another vector component-wise.
|
||||
/// </summary>
|
||||
/// <param name="scale">The vector to multiply with.</param>
|
||||
public void Scale(ref Vector2d scale)
|
||||
{
|
||||
x *= scale.x;
|
||||
y *= scale.y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes this vector.
|
||||
/// </summary>
|
||||
public void Normalize()
|
||||
{
|
||||
double mag = this.Magnitude;
|
||||
if (mag > Epsilon)
|
||||
{
|
||||
x /= mag;
|
||||
y /= mag;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps this vector between a specific range.
|
||||
/// </summary>
|
||||
/// <param name="min">The minimum component value.</param>
|
||||
/// <param name="max">The maximum component value.</param>
|
||||
public void Clamp(double min, double max)
|
||||
{
|
||||
if (x < min) x = min;
|
||||
else if (x > max) x = max;
|
||||
|
||||
if (y < min) y = min;
|
||||
else if (y > max) y = max;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Object
|
||||
/// <summary>
|
||||
/// Returns a hash code for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return x.GetHashCode() ^ y.GetHashCode() << 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this vector is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
if (!(other is Vector2d))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Vector2d vector = (Vector2d)other;
|
||||
return (x == vector.x && y == vector.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this vector is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public bool Equals(Vector2d other)
|
||||
{
|
||||
return (x == other.x && y == other.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The string.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("({0}, {1})",
|
||||
x.ToString("F1", CultureInfo.InvariantCulture),
|
||||
y.ToString("F1", CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this vector.
|
||||
/// </summary>
|
||||
/// <param name="format">The float format.</param>
|
||||
/// <returns>The string.</returns>
|
||||
public string ToString(string format)
|
||||
{
|
||||
return string.Format("({0}, {1})",
|
||||
x.ToString(format, CultureInfo.InvariantCulture),
|
||||
y.ToString(format, CultureInfo.InvariantCulture));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Static
|
||||
/// <summary>
|
||||
/// Dot Product of two vectors.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
public static double Dot(ref Vector2d lhs, ref Vector2d rhs)
|
||||
{
|
||||
return lhs.x * rhs.x + lhs.y * rhs.y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a linear interpolation between two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector to interpolate from.</param>
|
||||
/// <param name="b">The vector to interpolate to.</param>
|
||||
/// <param name="t">The time fraction.</param>
|
||||
/// <param name="result">The resulting vector.</param>
|
||||
public static void Lerp(ref Vector2d a, ref Vector2d b, double t, out Vector2d result)
|
||||
{
|
||||
result = new Vector2d(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies two vectors component-wise.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <param name="result">The resulting vector.</param>
|
||||
public static void Scale(ref Vector2d a, ref Vector2d b, out Vector2d result)
|
||||
{
|
||||
result = new Vector2d(a.x * b.x, a.y * b.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes a vector.
|
||||
/// </summary>
|
||||
/// <param name="value">The vector to normalize.</param>
|
||||
/// <param name="result">The resulting normalized vector.</param>
|
||||
public static void Normalize(ref Vector2d value, out Vector2d result)
|
||||
{
|
||||
double mag = value.Magnitude;
|
||||
if (mag > Epsilon)
|
||||
{
|
||||
result = new Vector2d(value.x / mag, value.y / mag);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = Vector2d.zero;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
348
LightlessSync/ThirdParty/MeshDecimator/Math/Vector2i.cs
vendored
Normal file
348
LightlessSync/ThirdParty/MeshDecimator/Math/Vector2i.cs
vendored
Normal file
@@ -0,0 +1,348 @@
|
||||
#region License
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright(c) 2017-2018 Mattias Edlund
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace MeshDecimator.Math
|
||||
{
|
||||
/// <summary>
|
||||
/// A 2D integer vector.
|
||||
/// </summary>
|
||||
public struct Vector2i : IEquatable<Vector2i>
|
||||
{
|
||||
#region Static Read-Only
|
||||
/// <summary>
|
||||
/// The zero vector.
|
||||
/// </summary>
|
||||
public static readonly Vector2i zero = new Vector2i(0, 0);
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
/// <summary>
|
||||
/// The x component.
|
||||
/// </summary>
|
||||
public int x;
|
||||
/// <summary>
|
||||
/// The y component.
|
||||
/// </summary>
|
||||
public int y;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Gets the magnitude of this vector.
|
||||
/// </summary>
|
||||
public int Magnitude
|
||||
{
|
||||
get { return (int)System.Math.Sqrt(x * x + y * y); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the squared magnitude of this vector.
|
||||
/// </summary>
|
||||
public int MagnitudeSqr
|
||||
{
|
||||
get { return (x * x + y * y); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a specific component by index in this vector.
|
||||
/// </summary>
|
||||
/// <param name="index">The component index.</param>
|
||||
public int this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return x;
|
||||
case 1:
|
||||
return y;
|
||||
default:
|
||||
throw new IndexOutOfRangeException("Invalid Vector2i index!");
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
x = value;
|
||||
break;
|
||||
case 1:
|
||||
y = value;
|
||||
break;
|
||||
default:
|
||||
throw new IndexOutOfRangeException("Invalid Vector2i index!");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
/// <summary>
|
||||
/// Creates a new vector with one value for all components.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
public Vector2i(int value)
|
||||
{
|
||||
this.x = value;
|
||||
this.y = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The x value.</param>
|
||||
/// <param name="y">The y value.</param>
|
||||
public Vector2i(int x, int y)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
/// <summary>
|
||||
/// Adds two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector2i operator +(Vector2i a, Vector2i b)
|
||||
{
|
||||
return new Vector2i(a.x + b.x, a.y + b.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector2i operator -(Vector2i a, Vector2i b)
|
||||
{
|
||||
return new Vector2i(a.x - b.x, a.y - b.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the vector uniformly.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <param name="d">The scaling value.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector2i operator *(Vector2i a, int d)
|
||||
{
|
||||
return new Vector2i(a.x * d, a.y * d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the vector uniformly.
|
||||
/// </summary>
|
||||
/// <param name="d">The scaling value.</param>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector2i operator *(int d, Vector2i a)
|
||||
{
|
||||
return new Vector2i(a.x * d, a.y * d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the vector with a float.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <param name="d">The dividing float value.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector2i operator /(Vector2i a, int d)
|
||||
{
|
||||
return new Vector2i(a.x / d, a.y / d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the vector from a zero vector.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector2i operator -(Vector2i a)
|
||||
{
|
||||
return new Vector2i(-a.x, -a.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two vectors equals eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public static bool operator ==(Vector2i lhs, Vector2i rhs)
|
||||
{
|
||||
return (lhs.x == rhs.x && lhs.y == rhs.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two vectors don't equal eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <returns>If not equals.</returns>
|
||||
public static bool operator !=(Vector2i lhs, Vector2i rhs)
|
||||
{
|
||||
return (lhs.x != rhs.x || lhs.y != rhs.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Explicitly converts from a single-precision vector into an integer vector.
|
||||
/// </summary>
|
||||
/// <param name="v">The single-precision vector.</param>
|
||||
public static explicit operator Vector2i(Vector2 v)
|
||||
{
|
||||
return new Vector2i((int)v.x, (int)v.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Explicitly converts from a double-precision vector into an integer vector.
|
||||
/// </summary>
|
||||
/// <param name="v">The double-precision vector.</param>
|
||||
public static explicit operator Vector2i(Vector2d v)
|
||||
{
|
||||
return new Vector2i((int)v.x, (int)v.y);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
#region Instance
|
||||
/// <summary>
|
||||
/// Set x and y components of an existing vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The x value.</param>
|
||||
/// <param name="y">The y value.</param>
|
||||
public void Set(int x, int y)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies with another vector component-wise.
|
||||
/// </summary>
|
||||
/// <param name="scale">The vector to multiply with.</param>
|
||||
public void Scale(ref Vector2i scale)
|
||||
{
|
||||
x *= scale.x;
|
||||
y *= scale.y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps this vector between a specific range.
|
||||
/// </summary>
|
||||
/// <param name="min">The minimum component value.</param>
|
||||
/// <param name="max">The maximum component value.</param>
|
||||
public void Clamp(int min, int max)
|
||||
{
|
||||
if (x < min) x = min;
|
||||
else if (x > max) x = max;
|
||||
|
||||
if (y < min) y = min;
|
||||
else if (y > max) y = max;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Object
|
||||
/// <summary>
|
||||
/// Returns a hash code for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return x.GetHashCode() ^ y.GetHashCode() << 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this vector is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
if (!(other is Vector2i))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Vector2i vector = (Vector2i)other;
|
||||
return (x == vector.x && y == vector.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this vector is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public bool Equals(Vector2i other)
|
||||
{
|
||||
return (x == other.x && y == other.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The string.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("({0}, {1})",
|
||||
x.ToString(CultureInfo.InvariantCulture),
|
||||
y.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this vector.
|
||||
/// </summary>
|
||||
/// <param name="format">The integer format.</param>
|
||||
/// <returns>The string.</returns>
|
||||
public string ToString(string format)
|
||||
{
|
||||
return string.Format("({0}, {1})",
|
||||
x.ToString(format, CultureInfo.InvariantCulture),
|
||||
y.ToString(format, CultureInfo.InvariantCulture));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Static
|
||||
/// <summary>
|
||||
/// Multiplies two vectors component-wise.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <param name="result">The resulting vector.</param>
|
||||
public static void Scale(ref Vector2i a, ref Vector2i b, out Vector2i result)
|
||||
{
|
||||
result = new Vector2i(a.x * b.x, a.y * b.y);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
494
LightlessSync/ThirdParty/MeshDecimator/Math/Vector3.cs
vendored
Normal file
494
LightlessSync/ThirdParty/MeshDecimator/Math/Vector3.cs
vendored
Normal file
@@ -0,0 +1,494 @@
|
||||
#region License
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright(c) 2017-2018 Mattias Edlund
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace MeshDecimator.Math
|
||||
{
|
||||
/// <summary>
|
||||
/// A single precision 3D vector.
|
||||
/// </summary>
|
||||
public struct Vector3 : IEquatable<Vector3>
|
||||
{
|
||||
#region Static Read-Only
|
||||
/// <summary>
|
||||
/// The zero vector.
|
||||
/// </summary>
|
||||
public static readonly Vector3 zero = new Vector3(0, 0, 0);
|
||||
#endregion
|
||||
|
||||
#region Consts
|
||||
/// <summary>
|
||||
/// The vector epsilon.
|
||||
/// </summary>
|
||||
public const float Epsilon = 9.99999944E-11f;
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
/// <summary>
|
||||
/// The x component.
|
||||
/// </summary>
|
||||
public float x;
|
||||
/// <summary>
|
||||
/// The y component.
|
||||
/// </summary>
|
||||
public float y;
|
||||
/// <summary>
|
||||
/// The z component.
|
||||
/// </summary>
|
||||
public float z;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Gets the magnitude of this vector.
|
||||
/// </summary>
|
||||
public float Magnitude
|
||||
{
|
||||
get { return (float)System.Math.Sqrt(x * x + y * y + z * z); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the squared magnitude of this vector.
|
||||
/// </summary>
|
||||
public float MagnitudeSqr
|
||||
{
|
||||
get { return (x * x + y * y + z * z); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a normalized vector from this vector.
|
||||
/// </summary>
|
||||
public Vector3 Normalized
|
||||
{
|
||||
get
|
||||
{
|
||||
Vector3 result;
|
||||
Normalize(ref this, out result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a specific component by index in this vector.
|
||||
/// </summary>
|
||||
/// <param name="index">The component index.</param>
|
||||
public float this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return x;
|
||||
case 1:
|
||||
return y;
|
||||
case 2:
|
||||
return z;
|
||||
default:
|
||||
throw new IndexOutOfRangeException("Invalid Vector3 index!");
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
x = value;
|
||||
break;
|
||||
case 1:
|
||||
y = value;
|
||||
break;
|
||||
case 2:
|
||||
z = value;
|
||||
break;
|
||||
default:
|
||||
throw new IndexOutOfRangeException("Invalid Vector3 index!");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
/// <summary>
|
||||
/// Creates a new vector with one value for all components.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
public Vector3(float value)
|
||||
{
|
||||
this.x = value;
|
||||
this.y = value;
|
||||
this.z = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The x value.</param>
|
||||
/// <param name="y">The y value.</param>
|
||||
/// <param name="z">The z value.</param>
|
||||
public Vector3(float x, float y, float z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new vector from a double precision vector.
|
||||
/// </summary>
|
||||
/// <param name="vector">The double precision vector.</param>
|
||||
public Vector3(Vector3d vector)
|
||||
{
|
||||
this.x = (float)vector.x;
|
||||
this.y = (float)vector.y;
|
||||
this.z = (float)vector.z;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
/// <summary>
|
||||
/// Adds two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector3 operator +(Vector3 a, Vector3 b)
|
||||
{
|
||||
return new Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector3 operator -(Vector3 a, Vector3 b)
|
||||
{
|
||||
return new Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the vector uniformly.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <param name="d">The scaling value.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector3 operator *(Vector3 a, float d)
|
||||
{
|
||||
return new Vector3(a.x * d, a.y * d, a.z * d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the vector uniformly.
|
||||
/// </summary>
|
||||
/// <param name="d">The scaling value.</param>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector3 operator *(float d, Vector3 a)
|
||||
{
|
||||
return new Vector3(a.x * d, a.y * d, a.z * d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the vector with a float.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <param name="d">The dividing float value.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector3 operator /(Vector3 a, float d)
|
||||
{
|
||||
return new Vector3(a.x / d, a.y / d, a.z / d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the vector from a zero vector.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector3 operator -(Vector3 a)
|
||||
{
|
||||
return new Vector3(-a.x, -a.y, -a.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two vectors equals eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public static bool operator ==(Vector3 lhs, Vector3 rhs)
|
||||
{
|
||||
return (lhs - rhs).MagnitudeSqr < Epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two vectors don't equal eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <returns>If not equals.</returns>
|
||||
public static bool operator !=(Vector3 lhs, Vector3 rhs)
|
||||
{
|
||||
return (lhs - rhs).MagnitudeSqr >= Epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Explicitly converts from a double-precision vector into a single-precision vector.
|
||||
/// </summary>
|
||||
/// <param name="v">The double-precision vector.</param>
|
||||
public static explicit operator Vector3(Vector3d v)
|
||||
{
|
||||
return new Vector3((float)v.x, (float)v.y, (float)v.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly converts from an integer vector into a single-precision vector.
|
||||
/// </summary>
|
||||
/// <param name="v">The integer vector.</param>
|
||||
public static implicit operator Vector3(Vector3i v)
|
||||
{
|
||||
return new Vector3(v.x, v.y, v.z);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
#region Instance
|
||||
/// <summary>
|
||||
/// Set x, y and z components of an existing vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The x value.</param>
|
||||
/// <param name="y">The y value.</param>
|
||||
/// <param name="z">The z value.</param>
|
||||
public void Set(float x, float y, float z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies with another vector component-wise.
|
||||
/// </summary>
|
||||
/// <param name="scale">The vector to multiply with.</param>
|
||||
public void Scale(ref Vector3 scale)
|
||||
{
|
||||
x *= scale.x;
|
||||
y *= scale.y;
|
||||
z *= scale.z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes this vector.
|
||||
/// </summary>
|
||||
public void Normalize()
|
||||
{
|
||||
float mag = this.Magnitude;
|
||||
if (mag > Epsilon)
|
||||
{
|
||||
x /= mag;
|
||||
y /= mag;
|
||||
z /= mag;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = y = z = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps this vector between a specific range.
|
||||
/// </summary>
|
||||
/// <param name="min">The minimum component value.</param>
|
||||
/// <param name="max">The maximum component value.</param>
|
||||
public void Clamp(float min, float max)
|
||||
{
|
||||
if (x < min) x = min;
|
||||
else if (x > max) x = max;
|
||||
|
||||
if (y < min) y = min;
|
||||
else if (y > max) y = max;
|
||||
|
||||
if (z < min) z = min;
|
||||
else if (z > max) z = max;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Object
|
||||
/// <summary>
|
||||
/// Returns a hash code for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return x.GetHashCode() ^ y.GetHashCode() << 2 ^ z.GetHashCode() >> 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this vector is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
if (!(other is Vector3))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Vector3 vector = (Vector3)other;
|
||||
return (x == vector.x && y == vector.y && z == vector.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this vector is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public bool Equals(Vector3 other)
|
||||
{
|
||||
return (x == other.x && y == other.y && z == other.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The string.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("({0}, {1}, {2})",
|
||||
x.ToString("F1", CultureInfo.InvariantCulture),
|
||||
y.ToString("F1", CultureInfo.InvariantCulture),
|
||||
z.ToString("F1", CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this vector.
|
||||
/// </summary>
|
||||
/// <param name="format">The float format.</param>
|
||||
/// <returns>The string.</returns>
|
||||
public string ToString(string format)
|
||||
{
|
||||
return string.Format("({0}, {1}, {2})",
|
||||
x.ToString(format, CultureInfo.InvariantCulture),
|
||||
y.ToString(format, CultureInfo.InvariantCulture),
|
||||
z.ToString(format, CultureInfo.InvariantCulture));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Static
|
||||
/// <summary>
|
||||
/// Dot Product of two vectors.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
public static float Dot(ref Vector3 lhs, ref Vector3 rhs)
|
||||
{
|
||||
return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cross Product of two vectors.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <param name="result">The resulting vector.</param>
|
||||
public static void Cross(ref Vector3 lhs, ref Vector3 rhs, out Vector3 result)
|
||||
{
|
||||
result = new Vector3(lhs.y * rhs.z - lhs.z * rhs.y, lhs.z * rhs.x - lhs.x * rhs.z, lhs.x * rhs.y - lhs.y * rhs.x);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the angle between two vectors.
|
||||
/// </summary>
|
||||
/// <param name="from">The from vector.</param>
|
||||
/// <param name="to">The to vector.</param>
|
||||
/// <returns>The angle.</returns>
|
||||
public static float Angle(ref Vector3 from, ref Vector3 to)
|
||||
{
|
||||
Vector3 fromNormalized = from.Normalized;
|
||||
Vector3 toNormalized = to.Normalized;
|
||||
return (float)System.Math.Acos(MathHelper.Clamp(Vector3.Dot(ref fromNormalized, ref toNormalized), -1f, 1f)) * MathHelper.Rad2Deg;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a linear interpolation between two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector to interpolate from.</param>
|
||||
/// <param name="b">The vector to interpolate to.</param>
|
||||
/// <param name="t">The time fraction.</param>
|
||||
/// <param name="result">The resulting vector.</param>
|
||||
public static void Lerp(ref Vector3 a, ref Vector3 b, float t, out Vector3 result)
|
||||
{
|
||||
result = new Vector3(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies two vectors component-wise.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <param name="result">The resulting vector.</param>
|
||||
public static void Scale(ref Vector3 a, ref Vector3 b, out Vector3 result)
|
||||
{
|
||||
result = new Vector3(a.x * b.x, a.y * b.y, a.z * b.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes a vector.
|
||||
/// </summary>
|
||||
/// <param name="value">The vector to normalize.</param>
|
||||
/// <param name="result">The resulting normalized vector.</param>
|
||||
public static void Normalize(ref Vector3 value, out Vector3 result)
|
||||
{
|
||||
float mag = value.Magnitude;
|
||||
if (mag > Epsilon)
|
||||
{
|
||||
result = new Vector3(value.x / mag, value.y / mag, value.z / mag);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = Vector3.zero;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes both vectors and makes them orthogonal to each other.
|
||||
/// </summary>
|
||||
/// <param name="normal">The normal vector.</param>
|
||||
/// <param name="tangent">The tangent.</param>
|
||||
public static void OrthoNormalize(ref Vector3 normal, ref Vector3 tangent)
|
||||
{
|
||||
normal.Normalize();
|
||||
Vector3 proj = normal * Vector3.Dot(ref tangent, ref normal);
|
||||
tangent -= proj;
|
||||
tangent.Normalize();
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
481
LightlessSync/ThirdParty/MeshDecimator/Math/Vector3d.cs
vendored
Normal file
481
LightlessSync/ThirdParty/MeshDecimator/Math/Vector3d.cs
vendored
Normal file
@@ -0,0 +1,481 @@
|
||||
#region License
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright(c) 2017-2018 Mattias Edlund
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace MeshDecimator.Math
|
||||
{
|
||||
/// <summary>
|
||||
/// A double precision 3D vector.
|
||||
/// </summary>
|
||||
public struct Vector3d : IEquatable<Vector3d>
|
||||
{
|
||||
#region Static Read-Only
|
||||
/// <summary>
|
||||
/// The zero vector.
|
||||
/// </summary>
|
||||
public static readonly Vector3d zero = new Vector3d(0, 0, 0);
|
||||
#endregion
|
||||
|
||||
#region Consts
|
||||
/// <summary>
|
||||
/// The vector epsilon.
|
||||
/// </summary>
|
||||
public const double Epsilon = double.Epsilon;
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
/// <summary>
|
||||
/// The x component.
|
||||
/// </summary>
|
||||
public double x;
|
||||
/// <summary>
|
||||
/// The y component.
|
||||
/// </summary>
|
||||
public double y;
|
||||
/// <summary>
|
||||
/// The z component.
|
||||
/// </summary>
|
||||
public double z;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Gets the magnitude of this vector.
|
||||
/// </summary>
|
||||
public double Magnitude
|
||||
{
|
||||
get { return System.Math.Sqrt(x * x + y * y + z * z); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the squared magnitude of this vector.
|
||||
/// </summary>
|
||||
public double MagnitudeSqr
|
||||
{
|
||||
get { return (x * x + y * y + z * z); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a normalized vector from this vector.
|
||||
/// </summary>
|
||||
public Vector3d Normalized
|
||||
{
|
||||
get
|
||||
{
|
||||
Vector3d result;
|
||||
Normalize(ref this, out result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a specific component by index in this vector.
|
||||
/// </summary>
|
||||
/// <param name="index">The component index.</param>
|
||||
public double this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return x;
|
||||
case 1:
|
||||
return y;
|
||||
case 2:
|
||||
return z;
|
||||
default:
|
||||
throw new IndexOutOfRangeException("Invalid Vector3d index!");
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
x = value;
|
||||
break;
|
||||
case 1:
|
||||
y = value;
|
||||
break;
|
||||
case 2:
|
||||
z = value;
|
||||
break;
|
||||
default:
|
||||
throw new IndexOutOfRangeException("Invalid Vector3d index!");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
/// <summary>
|
||||
/// Creates a new vector with one value for all components.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
public Vector3d(double value)
|
||||
{
|
||||
this.x = value;
|
||||
this.y = value;
|
||||
this.z = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The x value.</param>
|
||||
/// <param name="y">The y value.</param>
|
||||
/// <param name="z">The z value.</param>
|
||||
public Vector3d(double x, double y, double z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new vector from a single precision vector.
|
||||
/// </summary>
|
||||
/// <param name="vector">The single precision vector.</param>
|
||||
public Vector3d(Vector3 vector)
|
||||
{
|
||||
this.x = vector.x;
|
||||
this.y = vector.y;
|
||||
this.z = vector.z;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
/// <summary>
|
||||
/// Adds two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector3d operator +(Vector3d a, Vector3d b)
|
||||
{
|
||||
return new Vector3d(a.x + b.x, a.y + b.y, a.z + b.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector3d operator -(Vector3d a, Vector3d b)
|
||||
{
|
||||
return new Vector3d(a.x - b.x, a.y - b.y, a.z - b.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the vector uniformly.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <param name="d">The scaling value.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector3d operator *(Vector3d a, double d)
|
||||
{
|
||||
return new Vector3d(a.x * d, a.y * d, a.z * d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the vector uniformly.
|
||||
/// </summary>
|
||||
/// <param name="d">The scaling value.</param>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector3d operator *(double d, Vector3d a)
|
||||
{
|
||||
return new Vector3d(a.x * d, a.y * d, a.z * d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the vector with a float.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <param name="d">The dividing float value.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector3d operator /(Vector3d a, double d)
|
||||
{
|
||||
return new Vector3d(a.x / d, a.y / d, a.z / d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the vector from a zero vector.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector3d operator -(Vector3d a)
|
||||
{
|
||||
return new Vector3d(-a.x, -a.y, -a.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two vectors equals eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public static bool operator ==(Vector3d lhs, Vector3d rhs)
|
||||
{
|
||||
return (lhs - rhs).MagnitudeSqr < Epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two vectors don't equal eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <returns>If not equals.</returns>
|
||||
public static bool operator !=(Vector3d lhs, Vector3d rhs)
|
||||
{
|
||||
return (lhs - rhs).MagnitudeSqr >= Epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly converts from a single-precision vector into a double-precision vector.
|
||||
/// </summary>
|
||||
/// <param name="v">The single-precision vector.</param>
|
||||
public static implicit operator Vector3d(Vector3 v)
|
||||
{
|
||||
return new Vector3d(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly converts from an integer vector into a double-precision vector.
|
||||
/// </summary>
|
||||
/// <param name="v">The integer vector.</param>
|
||||
public static implicit operator Vector3d(Vector3i v)
|
||||
{
|
||||
return new Vector3d(v.x, v.y, v.z);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
#region Instance
|
||||
/// <summary>
|
||||
/// Set x, y and z components of an existing vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The x value.</param>
|
||||
/// <param name="y">The y value.</param>
|
||||
/// <param name="z">The z value.</param>
|
||||
public void Set(double x, double y, double z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies with another vector component-wise.
|
||||
/// </summary>
|
||||
/// <param name="scale">The vector to multiply with.</param>
|
||||
public void Scale(ref Vector3d scale)
|
||||
{
|
||||
x *= scale.x;
|
||||
y *= scale.y;
|
||||
z *= scale.z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes this vector.
|
||||
/// </summary>
|
||||
public void Normalize()
|
||||
{
|
||||
double mag = this.Magnitude;
|
||||
if (mag > Epsilon)
|
||||
{
|
||||
x /= mag;
|
||||
y /= mag;
|
||||
z /= mag;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = y = z = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps this vector between a specific range.
|
||||
/// </summary>
|
||||
/// <param name="min">The minimum component value.</param>
|
||||
/// <param name="max">The maximum component value.</param>
|
||||
public void Clamp(double min, double max)
|
||||
{
|
||||
if (x < min) x = min;
|
||||
else if (x > max) x = max;
|
||||
|
||||
if (y < min) y = min;
|
||||
else if (y > max) y = max;
|
||||
|
||||
if (z < min) z = min;
|
||||
else if (z > max) z = max;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Object
|
||||
/// <summary>
|
||||
/// Returns a hash code for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return x.GetHashCode() ^ y.GetHashCode() << 2 ^ z.GetHashCode() >> 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this vector is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
if (!(other is Vector3d))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Vector3d vector = (Vector3d)other;
|
||||
return (x == vector.x && y == vector.y && z == vector.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this vector is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public bool Equals(Vector3d other)
|
||||
{
|
||||
return (x == other.x && y == other.y && z == other.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The string.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("({0}, {1}, {2})",
|
||||
x.ToString("F1", CultureInfo.InvariantCulture),
|
||||
y.ToString("F1", CultureInfo.InvariantCulture),
|
||||
z.ToString("F1", CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this vector.
|
||||
/// </summary>
|
||||
/// <param name="format">The float format.</param>
|
||||
/// <returns>The string.</returns>
|
||||
public string ToString(string format)
|
||||
{
|
||||
return string.Format("({0}, {1}, {2})",
|
||||
x.ToString(format, CultureInfo.InvariantCulture),
|
||||
y.ToString(format, CultureInfo.InvariantCulture),
|
||||
z.ToString(format, CultureInfo.InvariantCulture));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Static
|
||||
/// <summary>
|
||||
/// Dot Product of two vectors.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
public static double Dot(ref Vector3d lhs, ref Vector3d rhs)
|
||||
{
|
||||
return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cross Product of two vectors.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <param name="result">The resulting vector.</param>
|
||||
public static void Cross(ref Vector3d lhs, ref Vector3d rhs, out Vector3d result)
|
||||
{
|
||||
result = new Vector3d(lhs.y * rhs.z - lhs.z * rhs.y, lhs.z * rhs.x - lhs.x * rhs.z, lhs.x * rhs.y - lhs.y * rhs.x);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the angle between two vectors.
|
||||
/// </summary>
|
||||
/// <param name="from">The from vector.</param>
|
||||
/// <param name="to">The to vector.</param>
|
||||
/// <returns>The angle.</returns>
|
||||
public static double Angle(ref Vector3d from, ref Vector3d to)
|
||||
{
|
||||
Vector3d fromNormalized = from.Normalized;
|
||||
Vector3d toNormalized = to.Normalized;
|
||||
return System.Math.Acos(MathHelper.Clamp(Vector3d.Dot(ref fromNormalized, ref toNormalized), -1.0, 1.0)) * MathHelper.Rad2Degd;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a linear interpolation between two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector to interpolate from.</param>
|
||||
/// <param name="b">The vector to interpolate to.</param>
|
||||
/// <param name="t">The time fraction.</param>
|
||||
/// <param name="result">The resulting vector.</param>
|
||||
public static void Lerp(ref Vector3d a, ref Vector3d b, double t, out Vector3d result)
|
||||
{
|
||||
result = new Vector3d(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies two vectors component-wise.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <param name="result">The resulting vector.</param>
|
||||
public static void Scale(ref Vector3d a, ref Vector3d b, out Vector3d result)
|
||||
{
|
||||
result = new Vector3d(a.x * b.x, a.y * b.y, a.z * b.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes a vector.
|
||||
/// </summary>
|
||||
/// <param name="value">The vector to normalize.</param>
|
||||
/// <param name="result">The resulting normalized vector.</param>
|
||||
public static void Normalize(ref Vector3d value, out Vector3d result)
|
||||
{
|
||||
double mag = value.Magnitude;
|
||||
if (mag > Epsilon)
|
||||
{
|
||||
result = new Vector3d(value.x / mag, value.y / mag, value.z / mag);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = Vector3d.zero;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
368
LightlessSync/ThirdParty/MeshDecimator/Math/Vector3i.cs
vendored
Normal file
368
LightlessSync/ThirdParty/MeshDecimator/Math/Vector3i.cs
vendored
Normal file
@@ -0,0 +1,368 @@
|
||||
#region License
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright(c) 2017-2018 Mattias Edlund
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace MeshDecimator.Math
|
||||
{
|
||||
/// <summary>
|
||||
/// A 3D integer vector.
|
||||
/// </summary>
|
||||
public struct Vector3i : IEquatable<Vector3i>
|
||||
{
|
||||
#region Static Read-Only
|
||||
/// <summary>
|
||||
/// The zero vector.
|
||||
/// </summary>
|
||||
public static readonly Vector3i zero = new Vector3i(0, 0, 0);
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
/// <summary>
|
||||
/// The x component.
|
||||
/// </summary>
|
||||
public int x;
|
||||
/// <summary>
|
||||
/// The y component.
|
||||
/// </summary>
|
||||
public int y;
|
||||
/// <summary>
|
||||
/// The z component.
|
||||
/// </summary>
|
||||
public int z;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Gets the magnitude of this vector.
|
||||
/// </summary>
|
||||
public int Magnitude
|
||||
{
|
||||
get { return (int)System.Math.Sqrt(x * x + y * y + z * z); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the squared magnitude of this vector.
|
||||
/// </summary>
|
||||
public int MagnitudeSqr
|
||||
{
|
||||
get { return (x * x + y * y + z * z); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a specific component by index in this vector.
|
||||
/// </summary>
|
||||
/// <param name="index">The component index.</param>
|
||||
public int this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return x;
|
||||
case 1:
|
||||
return y;
|
||||
case 2:
|
||||
return z;
|
||||
default:
|
||||
throw new IndexOutOfRangeException("Invalid Vector3i index!");
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
x = value;
|
||||
break;
|
||||
case 1:
|
||||
y = value;
|
||||
break;
|
||||
case 2:
|
||||
z = value;
|
||||
break;
|
||||
default:
|
||||
throw new IndexOutOfRangeException("Invalid Vector3i index!");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
/// <summary>
|
||||
/// Creates a new vector with one value for all components.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
public Vector3i(int value)
|
||||
{
|
||||
this.x = value;
|
||||
this.y = value;
|
||||
this.z = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The x value.</param>
|
||||
/// <param name="y">The y value.</param>
|
||||
/// <param name="z">The z value.</param>
|
||||
public Vector3i(int x, int y, int z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
/// <summary>
|
||||
/// Adds two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector3i operator +(Vector3i a, Vector3i b)
|
||||
{
|
||||
return new Vector3i(a.x + b.x, a.y + b.y, a.z + b.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector3i operator -(Vector3i a, Vector3i b)
|
||||
{
|
||||
return new Vector3i(a.x - b.x, a.y - b.y, a.z - b.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the vector uniformly.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <param name="d">The scaling value.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector3i operator *(Vector3i a, int d)
|
||||
{
|
||||
return new Vector3i(a.x * d, a.y * d, a.z * d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the vector uniformly.
|
||||
/// </summary>
|
||||
/// <param name="d">The scaling value.</param>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector3i operator *(int d, Vector3i a)
|
||||
{
|
||||
return new Vector3i(a.x * d, a.y * d, a.z * d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the vector with a float.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <param name="d">The dividing float value.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector3i operator /(Vector3i a, int d)
|
||||
{
|
||||
return new Vector3i(a.x / d, a.y / d, a.z / d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the vector from a zero vector.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector3i operator -(Vector3i a)
|
||||
{
|
||||
return new Vector3i(-a.x, -a.y, -a.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two vectors equals eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public static bool operator ==(Vector3i lhs, Vector3i rhs)
|
||||
{
|
||||
return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two vectors don't equal eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <returns>If not equals.</returns>
|
||||
public static bool operator !=(Vector3i lhs, Vector3i rhs)
|
||||
{
|
||||
return (lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Explicitly converts from a single-precision vector into an integer vector.
|
||||
/// </summary>
|
||||
/// <param name="v">The single-precision vector.</param>
|
||||
public static implicit operator Vector3i(Vector3 v)
|
||||
{
|
||||
return new Vector3i((int)v.x, (int)v.y, (int)v.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Explicitly converts from a double-precision vector into an integer vector.
|
||||
/// </summary>
|
||||
/// <param name="v">The double-precision vector.</param>
|
||||
public static explicit operator Vector3i(Vector3d v)
|
||||
{
|
||||
return new Vector3i((int)v.x, (int)v.y, (int)v.z);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
#region Instance
|
||||
/// <summary>
|
||||
/// Set x, y and z components of an existing vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The x value.</param>
|
||||
/// <param name="y">The y value.</param>
|
||||
/// <param name="z">The z value.</param>
|
||||
public void Set(int x, int y, int z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies with another vector component-wise.
|
||||
/// </summary>
|
||||
/// <param name="scale">The vector to multiply with.</param>
|
||||
public void Scale(ref Vector3i scale)
|
||||
{
|
||||
x *= scale.x;
|
||||
y *= scale.y;
|
||||
z *= scale.z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps this vector between a specific range.
|
||||
/// </summary>
|
||||
/// <param name="min">The minimum component value.</param>
|
||||
/// <param name="max">The maximum component value.</param>
|
||||
public void Clamp(int min, int max)
|
||||
{
|
||||
if (x < min) x = min;
|
||||
else if (x > max) x = max;
|
||||
|
||||
if (y < min) y = min;
|
||||
else if (y > max) y = max;
|
||||
|
||||
if (z < min) z = min;
|
||||
else if (z > max) z = max;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Object
|
||||
/// <summary>
|
||||
/// Returns a hash code for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return x.GetHashCode() ^ y.GetHashCode() << 2 ^ z.GetHashCode() >> 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this vector is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
if (!(other is Vector3i))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Vector3i vector = (Vector3i)other;
|
||||
return (x == vector.x && y == vector.y && z == vector.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this vector is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public bool Equals(Vector3i other)
|
||||
{
|
||||
return (x == other.x && y == other.y && z == other.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The string.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("({0}, {1}, {2})",
|
||||
x.ToString(CultureInfo.InvariantCulture),
|
||||
y.ToString(CultureInfo.InvariantCulture),
|
||||
z.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this vector.
|
||||
/// </summary>
|
||||
/// <param name="format">The integer format.</param>
|
||||
/// <returns>The string.</returns>
|
||||
public string ToString(string format)
|
||||
{
|
||||
return string.Format("({0}, {1}, {2})",
|
||||
x.ToString(format, CultureInfo.InvariantCulture),
|
||||
y.ToString(format, CultureInfo.InvariantCulture),
|
||||
z.ToString(format, CultureInfo.InvariantCulture));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Static
|
||||
/// <summary>
|
||||
/// Multiplies two vectors component-wise.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <param name="result">The resulting vector.</param>
|
||||
public static void Scale(ref Vector3i a, ref Vector3i b, out Vector3i result)
|
||||
{
|
||||
result = new Vector3i(a.x * b.x, a.y * b.y, a.z * b.z);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
467
LightlessSync/ThirdParty/MeshDecimator/Math/Vector4.cs
vendored
Normal file
467
LightlessSync/ThirdParty/MeshDecimator/Math/Vector4.cs
vendored
Normal file
@@ -0,0 +1,467 @@
|
||||
#region License
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright(c) 2017-2018 Mattias Edlund
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace MeshDecimator.Math
|
||||
{
|
||||
/// <summary>
|
||||
/// A single precision 4D vector.
|
||||
/// </summary>
|
||||
public struct Vector4 : IEquatable<Vector4>
|
||||
{
|
||||
#region Static Read-Only
|
||||
/// <summary>
|
||||
/// The zero vector.
|
||||
/// </summary>
|
||||
public static readonly Vector4 zero = new Vector4(0, 0, 0, 0);
|
||||
#endregion
|
||||
|
||||
#region Consts
|
||||
/// <summary>
|
||||
/// The vector epsilon.
|
||||
/// </summary>
|
||||
public const float Epsilon = 9.99999944E-11f;
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
/// <summary>
|
||||
/// The x component.
|
||||
/// </summary>
|
||||
public float x;
|
||||
/// <summary>
|
||||
/// The y component.
|
||||
/// </summary>
|
||||
public float y;
|
||||
/// <summary>
|
||||
/// The z component.
|
||||
/// </summary>
|
||||
public float z;
|
||||
/// <summary>
|
||||
/// The w component.
|
||||
/// </summary>
|
||||
public float w;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Gets the magnitude of this vector.
|
||||
/// </summary>
|
||||
public float Magnitude
|
||||
{
|
||||
get { return (float)System.Math.Sqrt(x * x + y * y + z * z + w * w); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the squared magnitude of this vector.
|
||||
/// </summary>
|
||||
public float MagnitudeSqr
|
||||
{
|
||||
get { return (x * x + y * y + z * z + w * w); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a normalized vector from this vector.
|
||||
/// </summary>
|
||||
public Vector4 Normalized
|
||||
{
|
||||
get
|
||||
{
|
||||
Vector4 result;
|
||||
Normalize(ref this, out result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a specific component by index in this vector.
|
||||
/// </summary>
|
||||
/// <param name="index">The component index.</param>
|
||||
public float 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("Invalid Vector4 index!");
|
||||
}
|
||||
}
|
||||
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("Invalid Vector4 index!");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
/// <summary>
|
||||
/// Creates a new vector with one value for all components.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
public Vector4(float value)
|
||||
{
|
||||
this.x = value;
|
||||
this.y = value;
|
||||
this.z = value;
|
||||
this.w = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The x value.</param>
|
||||
/// <param name="y">The y value.</param>
|
||||
/// <param name="z">The z value.</param>
|
||||
/// <param name="w">The w value.</param>
|
||||
public Vector4(float x, float y, float z, float w)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.w = w;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
/// <summary>
|
||||
/// Adds two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector4 operator +(Vector4 a, Vector4 b)
|
||||
{
|
||||
return new Vector4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector4 operator -(Vector4 a, Vector4 b)
|
||||
{
|
||||
return new Vector4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the vector uniformly.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <param name="d">The scaling value.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector4 operator *(Vector4 a, float d)
|
||||
{
|
||||
return new Vector4(a.x * d, a.y * d, a.z * d, a.w * d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the vector uniformly.
|
||||
/// </summary>
|
||||
/// <param name="d">The scaling value.</param>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector4 operator *(float d, Vector4 a)
|
||||
{
|
||||
return new Vector4(a.x * d, a.y * d, a.z * d, a.w * d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the vector with a float.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <param name="d">The dividing float value.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector4 operator /(Vector4 a, float d)
|
||||
{
|
||||
return new Vector4(a.x / d, a.y / d, a.z / d, a.w / d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the vector from a zero vector.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector4 operator -(Vector4 a)
|
||||
{
|
||||
return new Vector4(-a.x, -a.y, -a.z, -a.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two vectors equals eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public static bool operator ==(Vector4 lhs, Vector4 rhs)
|
||||
{
|
||||
return (lhs - rhs).MagnitudeSqr < Epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two vectors don't equal eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <returns>If not equals.</returns>
|
||||
public static bool operator !=(Vector4 lhs, Vector4 rhs)
|
||||
{
|
||||
return (lhs - rhs).MagnitudeSqr >= Epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Explicitly converts from a double-precision vector into a single-precision vector.
|
||||
/// </summary>
|
||||
/// <param name="v">The double-precision vector.</param>
|
||||
public static explicit operator Vector4(Vector4d v)
|
||||
{
|
||||
return new Vector4((float)v.x, (float)v.y, (float)v.z, (float)v.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly converts from an integer vector into a single-precision vector.
|
||||
/// </summary>
|
||||
/// <param name="v">The integer vector.</param>
|
||||
public static implicit operator Vector4(Vector4i v)
|
||||
{
|
||||
return new Vector4(v.x, v.y, v.z, v.w);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
#region Instance
|
||||
/// <summary>
|
||||
/// Set x, y and z components of an existing vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The x value.</param>
|
||||
/// <param name="y">The y value.</param>
|
||||
/// <param name="z">The z value.</param>
|
||||
/// <param name="w">The w value.</param>
|
||||
public void Set(float x, float y, float z, float w)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.w = w;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies with another vector component-wise.
|
||||
/// </summary>
|
||||
/// <param name="scale">The vector to multiply with.</param>
|
||||
public void Scale(ref Vector4 scale)
|
||||
{
|
||||
x *= scale.x;
|
||||
y *= scale.y;
|
||||
z *= scale.z;
|
||||
w *= scale.w;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes this vector.
|
||||
/// </summary>
|
||||
public void Normalize()
|
||||
{
|
||||
float mag = this.Magnitude;
|
||||
if (mag > Epsilon)
|
||||
{
|
||||
x /= mag;
|
||||
y /= mag;
|
||||
z /= mag;
|
||||
w /= mag;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = y = z = w = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps this vector between a specific range.
|
||||
/// </summary>
|
||||
/// <param name="min">The minimum component value.</param>
|
||||
/// <param name="max">The maximum component value.</param>
|
||||
public void Clamp(float min, float max)
|
||||
{
|
||||
if (x < min) x = min;
|
||||
else if (x > max) x = max;
|
||||
|
||||
if (y < min) y = min;
|
||||
else if (y > max) y = max;
|
||||
|
||||
if (z < min) z = min;
|
||||
else if (z > max) z = max;
|
||||
|
||||
if (w < min) w = min;
|
||||
else if (w > max) w = max;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Object
|
||||
/// <summary>
|
||||
/// Returns a hash code for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return x.GetHashCode() ^ y.GetHashCode() << 2 ^ z.GetHashCode() >> 2 ^ w.GetHashCode() >> 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this vector is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
if (!(other is Vector4))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Vector4 vector = (Vector4)other;
|
||||
return (x == vector.x && y == vector.y && z == vector.z && w == vector.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this vector is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public bool Equals(Vector4 other)
|
||||
{
|
||||
return (x == other.x && y == other.y && z == other.z && w == other.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The string.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("({0}, {1}, {2}, {3})",
|
||||
x.ToString("F1", CultureInfo.InvariantCulture),
|
||||
y.ToString("F1", CultureInfo.InvariantCulture),
|
||||
z.ToString("F1", CultureInfo.InvariantCulture),
|
||||
w.ToString("F1", CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this vector.
|
||||
/// </summary>
|
||||
/// <param name="format">The float format.</param>
|
||||
/// <returns>The string.</returns>
|
||||
public string ToString(string format)
|
||||
{
|
||||
return string.Format("({0}, {1}, {2}, {3})",
|
||||
x.ToString(format, CultureInfo.InvariantCulture),
|
||||
y.ToString(format, CultureInfo.InvariantCulture),
|
||||
z.ToString(format, CultureInfo.InvariantCulture),
|
||||
w.ToString(format, CultureInfo.InvariantCulture));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Static
|
||||
/// <summary>
|
||||
/// Dot Product of two vectors.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
public static float Dot(ref Vector4 lhs, ref Vector4 rhs)
|
||||
{
|
||||
return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z + lhs.w * rhs.w;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a linear interpolation between two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector to interpolate from.</param>
|
||||
/// <param name="b">The vector to interpolate to.</param>
|
||||
/// <param name="t">The time fraction.</param>
|
||||
/// <param name="result">The resulting vector.</param>
|
||||
public static void Lerp(ref Vector4 a, ref Vector4 b, float t, out Vector4 result)
|
||||
{
|
||||
result = new Vector4(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t, a.w + (b.w - a.w) * t);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies two vectors component-wise.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <param name="result">The resulting vector.</param>
|
||||
public static void Scale(ref Vector4 a, ref Vector4 b, out Vector4 result)
|
||||
{
|
||||
result = new Vector4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes a vector.
|
||||
/// </summary>
|
||||
/// <param name="value">The vector to normalize.</param>
|
||||
/// <param name="result">The resulting normalized vector.</param>
|
||||
public static void Normalize(ref Vector4 value, out Vector4 result)
|
||||
{
|
||||
float mag = value.Magnitude;
|
||||
if (mag > Epsilon)
|
||||
{
|
||||
result = new Vector4(value.x / mag, value.y / mag, value.z / mag, value.w / mag);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = Vector4.zero;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
467
LightlessSync/ThirdParty/MeshDecimator/Math/Vector4d.cs
vendored
Normal file
467
LightlessSync/ThirdParty/MeshDecimator/Math/Vector4d.cs
vendored
Normal file
@@ -0,0 +1,467 @@
|
||||
#region License
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright(c) 2017-2018 Mattias Edlund
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace MeshDecimator.Math
|
||||
{
|
||||
/// <summary>
|
||||
/// A double precision 4D vector.
|
||||
/// </summary>
|
||||
public struct Vector4d : IEquatable<Vector4d>
|
||||
{
|
||||
#region Static Read-Only
|
||||
/// <summary>
|
||||
/// The zero vector.
|
||||
/// </summary>
|
||||
public static readonly Vector4d zero = new Vector4d(0, 0, 0, 0);
|
||||
#endregion
|
||||
|
||||
#region Consts
|
||||
/// <summary>
|
||||
/// The vector epsilon.
|
||||
/// </summary>
|
||||
public const double Epsilon = double.Epsilon;
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
/// <summary>
|
||||
/// The x component.
|
||||
/// </summary>
|
||||
public double x;
|
||||
/// <summary>
|
||||
/// The y component.
|
||||
/// </summary>
|
||||
public double y;
|
||||
/// <summary>
|
||||
/// The z component.
|
||||
/// </summary>
|
||||
public double z;
|
||||
/// <summary>
|
||||
/// The w component.
|
||||
/// </summary>
|
||||
public double w;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Gets the magnitude of this vector.
|
||||
/// </summary>
|
||||
public double Magnitude
|
||||
{
|
||||
get { return System.Math.Sqrt(x * x + y * y + z * z + w * w); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the squared magnitude of this vector.
|
||||
/// </summary>
|
||||
public double MagnitudeSqr
|
||||
{
|
||||
get { return (x * x + y * y + z * z + w * w); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a normalized vector from this vector.
|
||||
/// </summary>
|
||||
public Vector4d Normalized
|
||||
{
|
||||
get
|
||||
{
|
||||
Vector4d result;
|
||||
Normalize(ref this, out result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a specific component by index in this vector.
|
||||
/// </summary>
|
||||
/// <param name="index">The component index.</param>
|
||||
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("Invalid Vector4d index!");
|
||||
}
|
||||
}
|
||||
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("Invalid Vector4d index!");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
/// <summary>
|
||||
/// Creates a new vector with one value for all components.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
public Vector4d(double value)
|
||||
{
|
||||
this.x = value;
|
||||
this.y = value;
|
||||
this.z = value;
|
||||
this.w = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The x value.</param>
|
||||
/// <param name="y">The y value.</param>
|
||||
/// <param name="z">The z value.</param>
|
||||
/// <param name="w">The w value.</param>
|
||||
public Vector4d(double x, double y, double z, double w)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.w = w;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
/// <summary>
|
||||
/// Adds two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector4d operator +(Vector4d a, Vector4d b)
|
||||
{
|
||||
return new Vector4d(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector4d operator -(Vector4d a, Vector4d b)
|
||||
{
|
||||
return new Vector4d(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the vector uniformly.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <param name="d">The scaling value.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector4d operator *(Vector4d a, double d)
|
||||
{
|
||||
return new Vector4d(a.x * d, a.y * d, a.z * d, a.w * d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the vector uniformly.
|
||||
/// </summary>
|
||||
/// <param name="d">The scaling value.</param>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector4d operator *(double d, Vector4d a)
|
||||
{
|
||||
return new Vector4d(a.x * d, a.y * d, a.z * d, a.w * d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the vector with a float.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <param name="d">The dividing float value.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector4d operator /(Vector4d a, double d)
|
||||
{
|
||||
return new Vector4d(a.x / d, a.y / d, a.z / d, a.w / d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the vector from a zero vector.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector4d operator -(Vector4d a)
|
||||
{
|
||||
return new Vector4d(-a.x, -a.y, -a.z, -a.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two vectors equals eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public static bool operator ==(Vector4d lhs, Vector4d rhs)
|
||||
{
|
||||
return (lhs - rhs).MagnitudeSqr < Epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two vectors don't equal eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <returns>If not equals.</returns>
|
||||
public static bool operator !=(Vector4d lhs, Vector4d rhs)
|
||||
{
|
||||
return (lhs - rhs).MagnitudeSqr >= Epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly converts from a single-precision vector into a double-precision vector.
|
||||
/// </summary>
|
||||
/// <param name="v">The single-precision vector.</param>
|
||||
public static implicit operator Vector4d(Vector4 v)
|
||||
{
|
||||
return new Vector4d(v.x, v.y, v.z, v.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly converts from an integer vector into a double-precision vector.
|
||||
/// </summary>
|
||||
/// <param name="v">The integer vector.</param>
|
||||
public static implicit operator Vector4d(Vector4i v)
|
||||
{
|
||||
return new Vector4d(v.x, v.y, v.z, v.w);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
#region Instance
|
||||
/// <summary>
|
||||
/// Set x, y and z components of an existing vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The x value.</param>
|
||||
/// <param name="y">The y value.</param>
|
||||
/// <param name="z">The z value.</param>
|
||||
/// <param name="w">The w value.</param>
|
||||
public void Set(double x, double y, double z, double w)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.w = w;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies with another vector component-wise.
|
||||
/// </summary>
|
||||
/// <param name="scale">The vector to multiply with.</param>
|
||||
public void Scale(ref Vector4d scale)
|
||||
{
|
||||
x *= scale.x;
|
||||
y *= scale.y;
|
||||
z *= scale.z;
|
||||
w *= scale.w;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes this vector.
|
||||
/// </summary>
|
||||
public void Normalize()
|
||||
{
|
||||
double mag = this.Magnitude;
|
||||
if (mag > Epsilon)
|
||||
{
|
||||
x /= mag;
|
||||
y /= mag;
|
||||
z /= mag;
|
||||
w /= mag;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = y = z = w = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps this vector between a specific range.
|
||||
/// </summary>
|
||||
/// <param name="min">The minimum component value.</param>
|
||||
/// <param name="max">The maximum component value.</param>
|
||||
public void Clamp(double min, double max)
|
||||
{
|
||||
if (x < min) x = min;
|
||||
else if (x > max) x = max;
|
||||
|
||||
if (y < min) y = min;
|
||||
else if (y > max) y = max;
|
||||
|
||||
if (z < min) z = min;
|
||||
else if (z > max) z = max;
|
||||
|
||||
if (w < min) w = min;
|
||||
else if (w > max) w = max;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Object
|
||||
/// <summary>
|
||||
/// Returns a hash code for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return x.GetHashCode() ^ y.GetHashCode() << 2 ^ z.GetHashCode() >> 2 ^ w.GetHashCode() >> 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this vector is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
if (!(other is Vector4d))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Vector4d vector = (Vector4d)other;
|
||||
return (x == vector.x && y == vector.y && z == vector.z && w == vector.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this vector is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public bool Equals(Vector4d other)
|
||||
{
|
||||
return (x == other.x && y == other.y && z == other.z && w == other.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The string.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("({0}, {1}, {2}, {3})",
|
||||
x.ToString("F1", CultureInfo.InvariantCulture),
|
||||
y.ToString("F1", CultureInfo.InvariantCulture),
|
||||
z.ToString("F1", CultureInfo.InvariantCulture),
|
||||
w.ToString("F1", CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this vector.
|
||||
/// </summary>
|
||||
/// <param name="format">The float format.</param>
|
||||
/// <returns>The string.</returns>
|
||||
public string ToString(string format)
|
||||
{
|
||||
return string.Format("({0}, {1}, {2}, {3})",
|
||||
x.ToString(format, CultureInfo.InvariantCulture),
|
||||
y.ToString(format, CultureInfo.InvariantCulture),
|
||||
z.ToString(format, CultureInfo.InvariantCulture),
|
||||
w.ToString(format, CultureInfo.InvariantCulture));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Static
|
||||
/// <summary>
|
||||
/// Dot Product of two vectors.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
public static double Dot(ref Vector4d lhs, ref Vector4d rhs)
|
||||
{
|
||||
return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z + lhs.w * rhs.w;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a linear interpolation between two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector to interpolate from.</param>
|
||||
/// <param name="b">The vector to interpolate to.</param>
|
||||
/// <param name="t">The time fraction.</param>
|
||||
/// <param name="result">The resulting vector.</param>
|
||||
public static void Lerp(ref Vector4d a, ref Vector4d b, double t, out Vector4d result)
|
||||
{
|
||||
result = new Vector4d(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t, a.w + (b.w - a.w) * t);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies two vectors component-wise.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <param name="result">The resulting vector.</param>
|
||||
public static void Scale(ref Vector4d a, ref Vector4d b, out Vector4d result)
|
||||
{
|
||||
result = new Vector4d(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes a vector.
|
||||
/// </summary>
|
||||
/// <param name="value">The vector to normalize.</param>
|
||||
/// <param name="result">The resulting normalized vector.</param>
|
||||
public static void Normalize(ref Vector4d value, out Vector4d result)
|
||||
{
|
||||
double mag = value.Magnitude;
|
||||
if (mag > Epsilon)
|
||||
{
|
||||
result = new Vector4d(value.x / mag, value.y / mag, value.z / mag, value.w / mag);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = Vector4d.zero;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
388
LightlessSync/ThirdParty/MeshDecimator/Math/Vector4i.cs
vendored
Normal file
388
LightlessSync/ThirdParty/MeshDecimator/Math/Vector4i.cs
vendored
Normal file
@@ -0,0 +1,388 @@
|
||||
#region License
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright(c) 2017-2018 Mattias Edlund
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace MeshDecimator.Math
|
||||
{
|
||||
/// <summary>
|
||||
/// A 4D integer vector.
|
||||
/// </summary>
|
||||
public struct Vector4i : IEquatable<Vector4i>
|
||||
{
|
||||
#region Static Read-Only
|
||||
/// <summary>
|
||||
/// The zero vector.
|
||||
/// </summary>
|
||||
public static readonly Vector4i zero = new Vector4i(0, 0, 0, 0);
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
/// <summary>
|
||||
/// The x component.
|
||||
/// </summary>
|
||||
public int x;
|
||||
/// <summary>
|
||||
/// The y component.
|
||||
/// </summary>
|
||||
public int y;
|
||||
/// <summary>
|
||||
/// The z component.
|
||||
/// </summary>
|
||||
public int z;
|
||||
/// <summary>
|
||||
/// The w component.
|
||||
/// </summary>
|
||||
public int w;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Gets the magnitude of this vector.
|
||||
/// </summary>
|
||||
public int Magnitude
|
||||
{
|
||||
get { return (int)System.Math.Sqrt(x * x + y * y + z * z + w * w); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the squared magnitude of this vector.
|
||||
/// </summary>
|
||||
public int MagnitudeSqr
|
||||
{
|
||||
get { return (x * x + y * y + z * z + w * w); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a specific component by index in this vector.
|
||||
/// </summary>
|
||||
/// <param name="index">The component index.</param>
|
||||
public int 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("Invalid Vector4i index!");
|
||||
}
|
||||
}
|
||||
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("Invalid Vector4i index!");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
/// <summary>
|
||||
/// Creates a new vector with one value for all components.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
public Vector4i(int value)
|
||||
{
|
||||
this.x = value;
|
||||
this.y = value;
|
||||
this.z = value;
|
||||
this.w = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The x value.</param>
|
||||
/// <param name="y">The y value.</param>
|
||||
/// <param name="z">The z value.</param>
|
||||
/// <param name="w">The w value.</param>
|
||||
public Vector4i(int x, int y, int z, int w)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.w = w;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
/// <summary>
|
||||
/// Adds two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector4i operator +(Vector4i a, Vector4i b)
|
||||
{
|
||||
return new Vector4i(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts two vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector4i operator -(Vector4i a, Vector4i b)
|
||||
{
|
||||
return new Vector4i(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the vector uniformly.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <param name="d">The scaling value.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector4i operator *(Vector4i a, int d)
|
||||
{
|
||||
return new Vector4i(a.x * d, a.y * d, a.z * d, a.w * d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales the vector uniformly.
|
||||
/// </summary>
|
||||
/// <param name="d">The scaling value.</param>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector4i operator *(int d, Vector4i a)
|
||||
{
|
||||
return new Vector4i(a.x * d, a.y * d, a.z * d, a.w * d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divides the vector with a float.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <param name="d">The dividing float value.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector4i operator /(Vector4i a, int d)
|
||||
{
|
||||
return new Vector4i(a.x / d, a.y / d, a.z / d, a.w / d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the vector from a zero vector.
|
||||
/// </summary>
|
||||
/// <param name="a">The vector.</param>
|
||||
/// <returns>The resulting vector.</returns>
|
||||
public static Vector4i operator -(Vector4i a)
|
||||
{
|
||||
return new Vector4i(-a.x, -a.y, -a.z, -a.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two vectors equals eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public static bool operator ==(Vector4i lhs, Vector4i rhs)
|
||||
{
|
||||
return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two vectors don't equal eachother.
|
||||
/// </summary>
|
||||
/// <param name="lhs">The left hand side vector.</param>
|
||||
/// <param name="rhs">The right hand side vector.</param>
|
||||
/// <returns>If not equals.</returns>
|
||||
public static bool operator !=(Vector4i lhs, Vector4i rhs)
|
||||
{
|
||||
return (lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z || lhs.w != rhs.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Explicitly converts from a single-precision vector into an integer vector.
|
||||
/// </summary>
|
||||
/// <param name="v">The single-precision vector.</param>
|
||||
public static explicit operator Vector4i(Vector4 v)
|
||||
{
|
||||
return new Vector4i((int)v.x, (int)v.y, (int)v.z, (int)v.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Explicitly converts from a double-precision vector into an integer vector.
|
||||
/// </summary>
|
||||
/// <param name="v">The double-precision vector.</param>
|
||||
public static explicit operator Vector4i(Vector4d v)
|
||||
{
|
||||
return new Vector4i((int)v.x, (int)v.y, (int)v.z, (int)v.w);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
#region Instance
|
||||
/// <summary>
|
||||
/// Set x, y and z components of an existing vector.
|
||||
/// </summary>
|
||||
/// <param name="x">The x value.</param>
|
||||
/// <param name="y">The y value.</param>
|
||||
/// <param name="z">The z value.</param>
|
||||
/// <param name="w">The w value.</param>
|
||||
public void Set(int x, int y, int z, int w)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.w = w;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplies with another vector component-wise.
|
||||
/// </summary>
|
||||
/// <param name="scale">The vector to multiply with.</param>
|
||||
public void Scale(ref Vector4i scale)
|
||||
{
|
||||
x *= scale.x;
|
||||
y *= scale.y;
|
||||
z *= scale.z;
|
||||
w *= scale.w;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps this vector between a specific range.
|
||||
/// </summary>
|
||||
/// <param name="min">The minimum component value.</param>
|
||||
/// <param name="max">The maximum component value.</param>
|
||||
public void Clamp(int min, int max)
|
||||
{
|
||||
if (x < min) x = min;
|
||||
else if (x > max) x = max;
|
||||
|
||||
if (y < min) y = min;
|
||||
else if (y > max) y = max;
|
||||
|
||||
if (z < min) z = min;
|
||||
else if (z > max) z = max;
|
||||
|
||||
if (w < min) w = min;
|
||||
else if (w > max) w = max;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Object
|
||||
/// <summary>
|
||||
/// Returns a hash code for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The hash code.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return x.GetHashCode() ^ y.GetHashCode() << 2 ^ z.GetHashCode() >> 2 ^ w.GetHashCode() >> 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this vector is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
if (!(other is Vector4i))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Vector4i vector = (Vector4i)other;
|
||||
return (x == vector.x && y == vector.y && z == vector.z && w == vector.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if this vector is equal to another one.
|
||||
/// </summary>
|
||||
/// <param name="other">The other vector to compare to.</param>
|
||||
/// <returns>If equals.</returns>
|
||||
public bool Equals(Vector4i other)
|
||||
{
|
||||
return (x == other.x && y == other.y && z == other.z && w == other.w);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this vector.
|
||||
/// </summary>
|
||||
/// <returns>The string.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("({0}, {1}, {2}, {3})",
|
||||
x.ToString(CultureInfo.InvariantCulture),
|
||||
y.ToString(CultureInfo.InvariantCulture),
|
||||
z.ToString(CultureInfo.InvariantCulture),
|
||||
w.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a nicely formatted string for this vector.
|
||||
/// </summary>
|
||||
/// <param name="format">The integer format.</param>
|
||||
/// <returns>The string.</returns>
|
||||
public string ToString(string format)
|
||||
{
|
||||
return string.Format("({0}, {1}, {2}, {3})",
|
||||
x.ToString(format, CultureInfo.InvariantCulture),
|
||||
y.ToString(format, CultureInfo.InvariantCulture),
|
||||
z.ToString(format, CultureInfo.InvariantCulture),
|
||||
w.ToString(format, CultureInfo.InvariantCulture));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Static
|
||||
/// <summary>
|
||||
/// Multiplies two vectors component-wise.
|
||||
/// </summary>
|
||||
/// <param name="a">The first vector.</param>
|
||||
/// <param name="b">The second vector.</param>
|
||||
/// <param name="result">The resulting vector.</param>
|
||||
public static void Scale(ref Vector4i a, ref Vector4i b, out Vector4i result)
|
||||
{
|
||||
result = new Vector4i(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
955
LightlessSync/ThirdParty/MeshDecimator/Mesh.cs
vendored
Normal file
955
LightlessSync/ThirdParty/MeshDecimator/Mesh.cs
vendored
Normal file
@@ -0,0 +1,955 @@
|
||||
#region License
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright(c) 2017-2018 Mattias Edlund
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MeshDecimator.Math;
|
||||
|
||||
namespace MeshDecimator
|
||||
{
|
||||
/// <summary>
|
||||
/// A mesh.
|
||||
/// </summary>
|
||||
public sealed class Mesh
|
||||
{
|
||||
#region Consts
|
||||
/// <summary>
|
||||
/// The count of supported UV channels.
|
||||
/// </summary>
|
||||
public const int UVChannelCount = 4;
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
private Vector3d[] vertices = null;
|
||||
private int[][] indices = null;
|
||||
private Vector3[] normals = null;
|
||||
private Vector4[] tangents = null;
|
||||
private Vector2[][] uvs2D = null;
|
||||
private Vector3[][] uvs3D = null;
|
||||
private Vector4[][] uvs4D = null;
|
||||
private Vector4[] colors = null;
|
||||
private BoneWeight[] boneWeights = null;
|
||||
|
||||
private static readonly int[] emptyIndices = new int[0];
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Gets the count of vertices of this mesh.
|
||||
/// </summary>
|
||||
public int VertexCount
|
||||
{
|
||||
get { return vertices.Length; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the count of submeshes in this mesh.
|
||||
/// </summary>
|
||||
public int SubMeshCount
|
||||
{
|
||||
get { return indices.Length; }
|
||||
set
|
||||
{
|
||||
if (value <= 0)
|
||||
throw new ArgumentOutOfRangeException("value");
|
||||
|
||||
int[][] newIndices = new int[value][];
|
||||
Array.Copy(indices, 0, newIndices, 0, MathHelper.Min(indices.Length, newIndices.Length));
|
||||
indices = newIndices;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total count of triangles in this mesh.
|
||||
/// </summary>
|
||||
public int TriangleCount
|
||||
{
|
||||
get
|
||||
{
|
||||
int triangleCount = 0;
|
||||
for (int i = 0; i < indices.Length; i++)
|
||||
{
|
||||
if (indices[i] != null)
|
||||
{
|
||||
triangleCount += indices[i].Length / 3;
|
||||
}
|
||||
}
|
||||
return triangleCount;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the vertices for this mesh. Note that this resets all other vertex attributes.
|
||||
/// </summary>
|
||||
public Vector3d[] Vertices
|
||||
{
|
||||
get { return vertices; }
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
vertices = value;
|
||||
ClearVertexAttributes();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the combined indices for this mesh. Once set, the sub-mesh count gets set to 1.
|
||||
/// </summary>
|
||||
public int[] Indices
|
||||
{
|
||||
get
|
||||
{
|
||||
if (indices.Length == 1)
|
||||
{
|
||||
return indices[0] ?? emptyIndices;
|
||||
}
|
||||
else
|
||||
{
|
||||
List<int> indexList = new List<int>(TriangleCount * 3);
|
||||
for (int i = 0; i < indices.Length; i++)
|
||||
{
|
||||
if (indices[i] != null)
|
||||
{
|
||||
indexList.AddRange(indices[i]);
|
||||
}
|
||||
}
|
||||
return indexList.ToArray();
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
else if ((value.Length % 3) != 0)
|
||||
throw new ArgumentException("The index count must be multiple by 3.", "value");
|
||||
|
||||
SubMeshCount = 1;
|
||||
SetIndices(0, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the normals for this mesh.
|
||||
/// </summary>
|
||||
public Vector3[] Normals
|
||||
{
|
||||
get { return normals; }
|
||||
set
|
||||
{
|
||||
if (value != null && value.Length != vertices.Length)
|
||||
throw new ArgumentException(string.Format("The vertex normals must be as many as the vertices. Assigned: {0} Require: {1}", value.Length, vertices.Length));
|
||||
|
||||
normals = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tangents for this mesh.
|
||||
/// </summary>
|
||||
public Vector4[] Tangents
|
||||
{
|
||||
get { return tangents; }
|
||||
set
|
||||
{
|
||||
if (value != null && value.Length != vertices.Length)
|
||||
throw new ArgumentException(string.Format("The vertex tangents must be as many as the vertices. Assigned: {0} Require: {1}", value.Length, vertices.Length));
|
||||
|
||||
tangents = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the first UV set for this mesh.
|
||||
/// </summary>
|
||||
public Vector2[] UV1
|
||||
{
|
||||
get { return GetUVs2D(0); }
|
||||
set { SetUVs(0, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the second UV set for this mesh.
|
||||
/// </summary>
|
||||
public Vector2[] UV2
|
||||
{
|
||||
get { return GetUVs2D(1); }
|
||||
set { SetUVs(1, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the third UV set for this mesh.
|
||||
/// </summary>
|
||||
public Vector2[] UV3
|
||||
{
|
||||
get { return GetUVs2D(2); }
|
||||
set { SetUVs(2, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the fourth UV set for this mesh.
|
||||
/// </summary>
|
||||
public Vector2[] UV4
|
||||
{
|
||||
get { return GetUVs2D(3); }
|
||||
set { SetUVs(3, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the vertex colors for this mesh.
|
||||
/// </summary>
|
||||
public Vector4[] Colors
|
||||
{
|
||||
get { return colors; }
|
||||
set
|
||||
{
|
||||
if (value != null && value.Length != vertices.Length)
|
||||
throw new ArgumentException(string.Format("The vertex colors must be as many as the vertices. Assigned: {0} Require: {1}", value.Length, vertices.Length));
|
||||
|
||||
colors = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the vertex bone weights for this mesh.
|
||||
/// </summary>
|
||||
public BoneWeight[] BoneWeights
|
||||
{
|
||||
get { return boneWeights; }
|
||||
set
|
||||
{
|
||||
if (value != null && value.Length != vertices.Length)
|
||||
throw new ArgumentException(string.Format("The vertex bone weights must be as many as the vertices. Assigned: {0} Require: {1}", value.Length, vertices.Length));
|
||||
|
||||
boneWeights = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
/// <summary>
|
||||
/// Creates a new mesh.
|
||||
/// </summary>
|
||||
/// <param name="vertices">The mesh vertices.</param>
|
||||
/// <param name="indices">The mesh indices.</param>
|
||||
public Mesh(Vector3d[] vertices, int[] indices)
|
||||
{
|
||||
if (vertices == null)
|
||||
throw new ArgumentNullException("vertices");
|
||||
else if (indices == null)
|
||||
throw new ArgumentNullException("indices");
|
||||
else if ((indices.Length % 3) != 0)
|
||||
throw new ArgumentException("The index count must be multiple by 3.", "indices");
|
||||
|
||||
this.vertices = vertices;
|
||||
this.indices = new int[1][];
|
||||
this.indices[0] = indices;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new mesh.
|
||||
/// </summary>
|
||||
/// <param name="vertices">The mesh vertices.</param>
|
||||
/// <param name="indices">The mesh indices.</param>
|
||||
public Mesh(Vector3d[] vertices, int[][] indices)
|
||||
{
|
||||
if (vertices == null)
|
||||
throw new ArgumentNullException("vertices");
|
||||
else if (indices == null)
|
||||
throw new ArgumentNullException("indices");
|
||||
|
||||
for (int i = 0; i < indices.Length; i++)
|
||||
{
|
||||
if (indices[i] != null && (indices[i].Length % 3) != 0)
|
||||
throw new ArgumentException(string.Format("The index count must be multiple by 3 at sub-mesh index {0}.", i), "indices");
|
||||
}
|
||||
|
||||
this.vertices = vertices;
|
||||
this.indices = indices;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private void ClearVertexAttributes()
|
||||
{
|
||||
normals = null;
|
||||
tangents = null;
|
||||
uvs2D = null;
|
||||
uvs3D = null;
|
||||
uvs4D = null;
|
||||
colors = null;
|
||||
boneWeights = null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
#region Recalculate Normals
|
||||
/// <summary>
|
||||
/// Recalculates the normals for this mesh smoothly.
|
||||
/// </summary>
|
||||
public void RecalculateNormals()
|
||||
{
|
||||
int vertexCount = vertices.Length;
|
||||
Vector3[] normals = new Vector3[vertexCount];
|
||||
|
||||
int subMeshCount = this.indices.Length;
|
||||
for (int subMeshIndex = 0; subMeshIndex < subMeshCount; subMeshIndex++)
|
||||
{
|
||||
int[] indices = this.indices[subMeshIndex];
|
||||
if (indices == null)
|
||||
continue;
|
||||
|
||||
int indexCount = indices.Length;
|
||||
for (int i = 0; i < indexCount; i += 3)
|
||||
{
|
||||
int i0 = indices[i];
|
||||
int i1 = indices[i + 1];
|
||||
int i2 = indices[i + 2];
|
||||
|
||||
var v0 = (Vector3)vertices[i0];
|
||||
var v1 = (Vector3)vertices[i1];
|
||||
var v2 = (Vector3)vertices[i2];
|
||||
|
||||
var nx = v1 - v0;
|
||||
var ny = v2 - v0;
|
||||
Vector3 normal;
|
||||
Vector3.Cross(ref nx, ref ny, out normal);
|
||||
normal.Normalize();
|
||||
|
||||
normals[i0] += normal;
|
||||
normals[i1] += normal;
|
||||
normals[i2] += normal;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < vertexCount; i++)
|
||||
{
|
||||
normals[i].Normalize();
|
||||
}
|
||||
|
||||
this.normals = normals;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Recalculate Tangents
|
||||
/// <summary>
|
||||
/// Recalculates the tangents for this mesh.
|
||||
/// </summary>
|
||||
public void RecalculateTangents()
|
||||
{
|
||||
// Make sure we have the normals first
|
||||
if (normals == null)
|
||||
return;
|
||||
|
||||
// Also make sure that we have the first UV set
|
||||
bool uvIs2D = (uvs2D != null && uvs2D[0] != null);
|
||||
bool uvIs3D = (uvs3D != null && uvs3D[0] != null);
|
||||
bool uvIs4D = (uvs4D != null && uvs4D[0] != null);
|
||||
if (!uvIs2D && !uvIs3D && !uvIs4D)
|
||||
return;
|
||||
|
||||
int vertexCount = vertices.Length;
|
||||
|
||||
var tangents = new Vector4[vertexCount];
|
||||
var tan1 = new Vector3[vertexCount];
|
||||
var tan2 = new Vector3[vertexCount];
|
||||
|
||||
Vector2[] uv2D = (uvIs2D ? uvs2D[0] : null);
|
||||
Vector3[] uv3D = (uvIs3D ? uvs3D[0] : null);
|
||||
Vector4[] uv4D = (uvIs4D ? uvs4D[0] : null);
|
||||
|
||||
int subMeshCount = this.indices.Length;
|
||||
for (int subMeshIndex = 0; subMeshIndex < subMeshCount; subMeshIndex++)
|
||||
{
|
||||
int[] indices = this.indices[subMeshIndex];
|
||||
if (indices == null)
|
||||
continue;
|
||||
|
||||
int indexCount = indices.Length;
|
||||
for (int i = 0; i < indexCount; i += 3)
|
||||
{
|
||||
int i0 = indices[i];
|
||||
int i1 = indices[i + 1];
|
||||
int i2 = indices[i + 2];
|
||||
|
||||
var v0 = vertices[i0];
|
||||
var v1 = vertices[i1];
|
||||
var v2 = vertices[i2];
|
||||
|
||||
float s1, s2, t1, t2;
|
||||
if (uvIs2D)
|
||||
{
|
||||
var w0 = uv2D[i0];
|
||||
var w1 = uv2D[i1];
|
||||
var w2 = uv2D[i2];
|
||||
s1 = w1.x - w0.x;
|
||||
s2 = w2.x - w0.x;
|
||||
t1 = w1.y - w0.y;
|
||||
t2 = w2.y - w0.y;
|
||||
}
|
||||
else if (uvIs3D)
|
||||
{
|
||||
var w0 = uv3D[i0];
|
||||
var w1 = uv3D[i1];
|
||||
var w2 = uv3D[i2];
|
||||
s1 = w1.x - w0.x;
|
||||
s2 = w2.x - w0.x;
|
||||
t1 = w1.y - w0.y;
|
||||
t2 = w2.y - w0.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
var w0 = uv4D[i0];
|
||||
var w1 = uv4D[i1];
|
||||
var w2 = uv4D[i2];
|
||||
s1 = w1.x - w0.x;
|
||||
s2 = w2.x - w0.x;
|
||||
t1 = w1.y - w0.y;
|
||||
t2 = w2.y - w0.y;
|
||||
}
|
||||
|
||||
|
||||
float x1 = (float)(v1.x - v0.x);
|
||||
float x2 = (float)(v2.x - v0.x);
|
||||
float y1 = (float)(v1.y - v0.y);
|
||||
float y2 = (float)(v2.y - v0.y);
|
||||
float z1 = (float)(v1.z - v0.z);
|
||||
float z2 = (float)(v2.z - v0.z);
|
||||
float r = 1f / (s1 * t2 - s2 * t1);
|
||||
|
||||
var sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
|
||||
var tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
|
||||
|
||||
tan1[i0] += sdir;
|
||||
tan1[i1] += sdir;
|
||||
tan1[i2] += sdir;
|
||||
tan2[i0] += tdir;
|
||||
tan2[i1] += tdir;
|
||||
tan2[i2] += tdir;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < vertexCount; i++)
|
||||
{
|
||||
var n = normals[i];
|
||||
var t = tan1[i];
|
||||
|
||||
var tmp = (t - n * Vector3.Dot(ref n, ref t));
|
||||
tmp.Normalize();
|
||||
|
||||
Vector3 c;
|
||||
Vector3.Cross(ref n, ref t, out c);
|
||||
float dot = Vector3.Dot(ref c, ref tan2[i]);
|
||||
float w = (dot < 0f ? -1f : 1f);
|
||||
tangents[i] = new Vector4(tmp.x, tmp.y, tmp.z, w);
|
||||
}
|
||||
|
||||
this.tangents = tangents;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Triangles
|
||||
/// <summary>
|
||||
/// Returns the count of triangles for a specific sub-mesh in this mesh.
|
||||
/// </summary>
|
||||
/// <param name="subMeshIndex">The sub-mesh index.</param>
|
||||
/// <returns>The triangle count.</returns>
|
||||
public int GetTriangleCount(int subMeshIndex)
|
||||
{
|
||||
if (subMeshIndex < 0 || subMeshIndex >= indices.Length)
|
||||
throw new IndexOutOfRangeException();
|
||||
|
||||
return indices[subMeshIndex].Length / 3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the triangle indices of a specific sub-mesh in this mesh.
|
||||
/// </summary>
|
||||
/// <param name="subMeshIndex">The sub-mesh index.</param>
|
||||
/// <returns>The triangle indices.</returns>
|
||||
public int[] GetIndices(int subMeshIndex)
|
||||
{
|
||||
if (subMeshIndex < 0 || subMeshIndex >= indices.Length)
|
||||
throw new IndexOutOfRangeException();
|
||||
|
||||
return indices[subMeshIndex] ?? emptyIndices;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the triangle indices for all sub-meshes in this mesh.
|
||||
/// </summary>
|
||||
/// <returns>The sub-mesh triangle indices.</returns>
|
||||
public int[][] GetSubMeshIndices()
|
||||
{
|
||||
var subMeshIndices = new int[indices.Length][];
|
||||
for (int subMeshIndex = 0; subMeshIndex < indices.Length; subMeshIndex++)
|
||||
{
|
||||
subMeshIndices[subMeshIndex] = indices[subMeshIndex] ?? emptyIndices;
|
||||
}
|
||||
return subMeshIndices;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the triangle indices of a specific sub-mesh in this mesh.
|
||||
/// </summary>
|
||||
/// <param name="subMeshIndex">The sub-mesh index.</param>
|
||||
/// <param name="indices">The triangle indices.</param>
|
||||
public void SetIndices(int subMeshIndex, int[] indices)
|
||||
{
|
||||
if (subMeshIndex < 0 || subMeshIndex >= this.indices.Length)
|
||||
throw new IndexOutOfRangeException();
|
||||
else if (indices == null)
|
||||
throw new ArgumentNullException("indices");
|
||||
else if ((indices.Length % 3) != 0)
|
||||
throw new ArgumentException("The index count must be multiple by 3.", "indices");
|
||||
|
||||
this.indices[subMeshIndex] = indices;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UV Sets
|
||||
#region Getting
|
||||
/// <summary>
|
||||
/// Returns the UV dimension for a specific channel.
|
||||
/// </summary>
|
||||
/// <param name="channel"></param>
|
||||
/// <returns>The UV dimension count.</returns>
|
||||
public int GetUVDimension(int channel)
|
||||
{
|
||||
if (channel < 0 || channel >= UVChannelCount)
|
||||
throw new ArgumentOutOfRangeException("channel");
|
||||
|
||||
if (uvs2D != null && uvs2D[channel] != null)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
else if (uvs3D != null && uvs3D[channel] != null)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
else if (uvs4D != null && uvs4D[channel] != null)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the UVs (2D) from a specific channel.
|
||||
/// </summary>
|
||||
/// <param name="channel">The channel index.</param>
|
||||
/// <returns>The UVs.</returns>
|
||||
public Vector2[] GetUVs2D(int channel)
|
||||
{
|
||||
if (channel < 0 || channel >= UVChannelCount)
|
||||
throw new ArgumentOutOfRangeException("channel");
|
||||
|
||||
if (uvs2D != null && uvs2D[channel] != null)
|
||||
{
|
||||
return uvs2D[channel];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the UVs (3D) from a specific channel.
|
||||
/// </summary>
|
||||
/// <param name="channel">The channel index.</param>
|
||||
/// <returns>The UVs.</returns>
|
||||
public Vector3[] GetUVs3D(int channel)
|
||||
{
|
||||
if (channel < 0 || channel >= UVChannelCount)
|
||||
throw new ArgumentOutOfRangeException("channel");
|
||||
|
||||
if (uvs3D != null && uvs3D[channel] != null)
|
||||
{
|
||||
return uvs3D[channel];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the UVs (4D) from a specific channel.
|
||||
/// </summary>
|
||||
/// <param name="channel">The channel index.</param>
|
||||
/// <returns>The UVs.</returns>
|
||||
public Vector4[] GetUVs4D(int channel)
|
||||
{
|
||||
if (channel < 0 || channel >= UVChannelCount)
|
||||
throw new ArgumentOutOfRangeException("channel");
|
||||
|
||||
if (uvs4D != null && uvs4D[channel] != null)
|
||||
{
|
||||
return uvs4D[channel];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the UVs (2D) from a specific channel.
|
||||
/// </summary>
|
||||
/// <param name="channel">The channel index.</param>
|
||||
/// <param name="uvs">The UVs.</param>
|
||||
public void GetUVs(int channel, List<Vector2> uvs)
|
||||
{
|
||||
if (channel < 0 || channel >= UVChannelCount)
|
||||
throw new ArgumentOutOfRangeException("channel");
|
||||
else if (uvs == null)
|
||||
throw new ArgumentNullException("uvs");
|
||||
|
||||
uvs.Clear();
|
||||
if (uvs2D != null && uvs2D[channel] != null)
|
||||
{
|
||||
var uvData = uvs2D[channel];
|
||||
if (uvData != null)
|
||||
{
|
||||
uvs.AddRange(uvData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the UVs (3D) from a specific channel.
|
||||
/// </summary>
|
||||
/// <param name="channel">The channel index.</param>
|
||||
/// <param name="uvs">The UVs.</param>
|
||||
public void GetUVs(int channel, List<Vector3> uvs)
|
||||
{
|
||||
if (channel < 0 || channel >= UVChannelCount)
|
||||
throw new ArgumentOutOfRangeException("channel");
|
||||
else if (uvs == null)
|
||||
throw new ArgumentNullException("uvs");
|
||||
|
||||
uvs.Clear();
|
||||
if (uvs3D != null && uvs3D[channel] != null)
|
||||
{
|
||||
var uvData = uvs3D[channel];
|
||||
if (uvData != null)
|
||||
{
|
||||
uvs.AddRange(uvData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the UVs (4D) from a specific channel.
|
||||
/// </summary>
|
||||
/// <param name="channel">The channel index.</param>
|
||||
/// <param name="uvs">The UVs.</param>
|
||||
public void GetUVs(int channel, List<Vector4> uvs)
|
||||
{
|
||||
if (channel < 0 || channel >= UVChannelCount)
|
||||
throw new ArgumentOutOfRangeException("channel");
|
||||
else if (uvs == null)
|
||||
throw new ArgumentNullException("uvs");
|
||||
|
||||
uvs.Clear();
|
||||
if (uvs4D != null && uvs4D[channel] != null)
|
||||
{
|
||||
var uvData = uvs4D[channel];
|
||||
if (uvData != null)
|
||||
{
|
||||
uvs.AddRange(uvData);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Setting
|
||||
/// <summary>
|
||||
/// Sets the UVs (2D) for a specific channel.
|
||||
/// </summary>
|
||||
/// <param name="channel">The channel index.</param>
|
||||
/// <param name="uvs">The UVs.</param>
|
||||
public void SetUVs(int channel, Vector2[] uvs)
|
||||
{
|
||||
if (channel < 0 || channel >= UVChannelCount)
|
||||
throw new ArgumentOutOfRangeException("channel");
|
||||
|
||||
if (uvs != null && uvs.Length > 0)
|
||||
{
|
||||
if (uvs.Length != vertices.Length)
|
||||
throw new ArgumentException(string.Format("The vertex UVs must be as many as the vertices. Assigned: {0} Require: {1}", uvs.Length, vertices.Length));
|
||||
|
||||
if (uvs2D == null)
|
||||
uvs2D = new Vector2[UVChannelCount][];
|
||||
|
||||
int uvCount = uvs.Length;
|
||||
var uvSet = new Vector2[uvCount];
|
||||
uvs2D[channel] = uvSet;
|
||||
uvs.CopyTo(uvSet, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uvs2D != null)
|
||||
{
|
||||
uvs2D[channel] = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (uvs3D != null)
|
||||
{
|
||||
uvs3D[channel] = null;
|
||||
}
|
||||
if (uvs4D != null)
|
||||
{
|
||||
uvs4D[channel] = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the UVs (3D) for a specific channel.
|
||||
/// </summary>
|
||||
/// <param name="channel">The channel index.</param>
|
||||
/// <param name="uvs">The UVs.</param>
|
||||
public void SetUVs(int channel, Vector3[] uvs)
|
||||
{
|
||||
if (channel < 0 || channel >= UVChannelCount)
|
||||
throw new ArgumentOutOfRangeException("channel");
|
||||
|
||||
if (uvs != null && uvs.Length > 0)
|
||||
{
|
||||
int uvCount = uvs.Length;
|
||||
if (uvCount != vertices.Length)
|
||||
throw new ArgumentException(string.Format("The vertex UVs must be as many as the vertices. Assigned: {0} Require: {1}", uvCount, vertices.Length), "uvs");
|
||||
|
||||
if (uvs3D == null)
|
||||
uvs3D = new Vector3[UVChannelCount][];
|
||||
|
||||
var uvSet = new Vector3[uvCount];
|
||||
uvs3D[channel] = uvSet;
|
||||
uvs.CopyTo(uvSet, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uvs3D != null)
|
||||
{
|
||||
uvs3D[channel] = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (uvs2D != null)
|
||||
{
|
||||
uvs2D[channel] = null;
|
||||
}
|
||||
if (uvs4D != null)
|
||||
{
|
||||
uvs4D[channel] = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the UVs (4D) for a specific channel.
|
||||
/// </summary>
|
||||
/// <param name="channel">The channel index.</param>
|
||||
/// <param name="uvs">The UVs.</param>
|
||||
public void SetUVs(int channel, Vector4[] uvs)
|
||||
{
|
||||
if (channel < 0 || channel >= UVChannelCount)
|
||||
throw new ArgumentOutOfRangeException("channel");
|
||||
|
||||
if (uvs != null && uvs.Length > 0)
|
||||
{
|
||||
int uvCount = uvs.Length;
|
||||
if (uvCount != vertices.Length)
|
||||
throw new ArgumentException(string.Format("The vertex UVs must be as many as the vertices. Assigned: {0} Require: {1}", uvCount, vertices.Length), "uvs");
|
||||
|
||||
if (uvs4D == null)
|
||||
uvs4D = new Vector4[UVChannelCount][];
|
||||
|
||||
var uvSet = new Vector4[uvCount];
|
||||
uvs4D[channel] = uvSet;
|
||||
uvs.CopyTo(uvSet, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uvs4D != null)
|
||||
{
|
||||
uvs4D[channel] = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (uvs2D != null)
|
||||
{
|
||||
uvs2D[channel] = null;
|
||||
}
|
||||
if (uvs3D != null)
|
||||
{
|
||||
uvs3D[channel] = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the UVs (2D) for a specific channel.
|
||||
/// </summary>
|
||||
/// <param name="channel">The channel index.</param>
|
||||
/// <param name="uvs">The UVs.</param>
|
||||
public void SetUVs(int channel, List<Vector2> uvs)
|
||||
{
|
||||
if (channel < 0 || channel >= UVChannelCount)
|
||||
throw new ArgumentOutOfRangeException("channel");
|
||||
|
||||
if (uvs != null && uvs.Count > 0)
|
||||
{
|
||||
int uvCount = uvs.Count;
|
||||
if (uvCount != vertices.Length)
|
||||
throw new ArgumentException(string.Format("The vertex UVs must be as many as the vertices. Assigned: {0} Require: {1}", uvCount, vertices.Length), "uvs");
|
||||
|
||||
if (uvs2D == null)
|
||||
uvs2D = new Vector2[UVChannelCount][];
|
||||
|
||||
var uvSet = new Vector2[uvCount];
|
||||
uvs2D[channel] = uvSet;
|
||||
uvs.CopyTo(uvSet, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uvs2D != null)
|
||||
{
|
||||
uvs2D[channel] = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (uvs3D != null)
|
||||
{
|
||||
uvs3D[channel] = null;
|
||||
}
|
||||
if (uvs4D != null)
|
||||
{
|
||||
uvs4D[channel] = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the UVs (3D) for a specific channel.
|
||||
/// </summary>
|
||||
/// <param name="channel">The channel index.</param>
|
||||
/// <param name="uvs">The UVs.</param>
|
||||
public void SetUVs(int channel, List<Vector3> uvs)
|
||||
{
|
||||
if (channel < 0 || channel >= UVChannelCount)
|
||||
throw new ArgumentOutOfRangeException("channel");
|
||||
|
||||
if (uvs != null && uvs.Count > 0)
|
||||
{
|
||||
int uvCount = uvs.Count;
|
||||
if (uvCount != vertices.Length)
|
||||
throw new ArgumentException(string.Format("The vertex UVs must be as many as the vertices. Assigned: {0} Require: {1}", uvCount, vertices.Length), "uvs");
|
||||
|
||||
if (uvs3D == null)
|
||||
uvs3D = new Vector3[UVChannelCount][];
|
||||
|
||||
var uvSet = new Vector3[uvCount];
|
||||
uvs3D[channel] = uvSet;
|
||||
uvs.CopyTo(uvSet, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uvs3D != null)
|
||||
{
|
||||
uvs3D[channel] = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (uvs2D != null)
|
||||
{
|
||||
uvs2D[channel] = null;
|
||||
}
|
||||
if (uvs4D != null)
|
||||
{
|
||||
uvs4D[channel] = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the UVs (4D) for a specific channel.
|
||||
/// </summary>
|
||||
/// <param name="channel">The channel index.</param>
|
||||
/// <param name="uvs">The UVs.</param>
|
||||
public void SetUVs(int channel, List<Vector4> uvs)
|
||||
{
|
||||
if (channel < 0 || channel >= UVChannelCount)
|
||||
throw new ArgumentOutOfRangeException("channel");
|
||||
|
||||
if (uvs != null && uvs.Count > 0)
|
||||
{
|
||||
int uvCount = uvs.Count;
|
||||
if (uvCount != vertices.Length)
|
||||
throw new ArgumentException(string.Format("The vertex UVs must be as many as the vertices. Assigned: {0} Require: {1}", uvCount, vertices.Length), "uvs");
|
||||
|
||||
if (uvs4D == null)
|
||||
uvs4D = new Vector4[UVChannelCount][];
|
||||
|
||||
var uvSet = new Vector4[uvCount];
|
||||
uvs4D[channel] = uvSet;
|
||||
uvs.CopyTo(uvSet, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uvs4D != null)
|
||||
{
|
||||
uvs4D[channel] = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (uvs2D != null)
|
||||
{
|
||||
uvs2D[channel] = null;
|
||||
}
|
||||
if (uvs3D != null)
|
||||
{
|
||||
uvs3D[channel] = null;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region To String
|
||||
/// <summary>
|
||||
/// Returns the text-representation of this mesh.
|
||||
/// </summary>
|
||||
/// <returns>The text-representation.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("Vertices: {0}", vertices.Length);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
180
LightlessSync/ThirdParty/MeshDecimator/MeshDecimation.cs
vendored
Normal file
180
LightlessSync/ThirdParty/MeshDecimator/MeshDecimation.cs
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
#region License
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright(c) 2017-2018 Mattias Edlund
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using MeshDecimator.Algorithms;
|
||||
|
||||
namespace MeshDecimator
|
||||
{
|
||||
#region Algorithm
|
||||
/// <summary>
|
||||
/// The decimation algorithms.
|
||||
/// </summary>
|
||||
public enum Algorithm
|
||||
{
|
||||
/// <summary>
|
||||
/// The default algorithm.
|
||||
/// </summary>
|
||||
Default,
|
||||
/// <summary>
|
||||
/// The fast quadric mesh simplification algorithm.
|
||||
/// </summary>
|
||||
FastQuadricMesh
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The mesh decimation API.
|
||||
/// </summary>
|
||||
public static class MeshDecimation
|
||||
{
|
||||
#region Public Methods
|
||||
#region Create Algorithm
|
||||
/// <summary>
|
||||
/// Creates a specific decimation algorithm.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The desired algorithm.</param>
|
||||
/// <returns>The decimation algorithm.</returns>
|
||||
public static DecimationAlgorithm CreateAlgorithm(Algorithm algorithm)
|
||||
{
|
||||
DecimationAlgorithm alg = null;
|
||||
|
||||
switch (algorithm)
|
||||
{
|
||||
case Algorithm.Default:
|
||||
case Algorithm.FastQuadricMesh:
|
||||
alg = new FastQuadricMeshSimplification();
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("The specified algorithm is not supported.", "algorithm");
|
||||
}
|
||||
|
||||
return alg;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Decimate Mesh
|
||||
/// <summary>
|
||||
/// Decimates a mesh.
|
||||
/// </summary>
|
||||
/// <param name="mesh">The mesh to decimate.</param>
|
||||
/// <param name="targetTriangleCount">The target triangle count.</param>
|
||||
/// <returns>The decimated mesh.</returns>
|
||||
public static Mesh DecimateMesh(Mesh mesh, int targetTriangleCount)
|
||||
{
|
||||
return DecimateMesh(Algorithm.Default, mesh, targetTriangleCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decimates a mesh.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The desired algorithm.</param>
|
||||
/// <param name="mesh">The mesh to decimate.</param>
|
||||
/// <param name="targetTriangleCount">The target triangle count.</param>
|
||||
/// <returns>The decimated mesh.</returns>
|
||||
public static Mesh DecimateMesh(Algorithm algorithm, Mesh mesh, int targetTriangleCount)
|
||||
{
|
||||
if (mesh == null)
|
||||
throw new ArgumentNullException("mesh");
|
||||
|
||||
var decimationAlgorithm = CreateAlgorithm(algorithm);
|
||||
return DecimateMesh(decimationAlgorithm, mesh, targetTriangleCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decimates a mesh.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The decimation algorithm.</param>
|
||||
/// <param name="mesh">The mesh to decimate.</param>
|
||||
/// <param name="targetTriangleCount">The target triangle count.</param>
|
||||
/// <returns>The decimated mesh.</returns>
|
||||
public static Mesh DecimateMesh(DecimationAlgorithm algorithm, Mesh mesh, int targetTriangleCount)
|
||||
{
|
||||
if (algorithm == null)
|
||||
throw new ArgumentNullException("algorithm");
|
||||
else if (mesh == null)
|
||||
throw new ArgumentNullException("mesh");
|
||||
|
||||
int currentTriangleCount = mesh.TriangleCount;
|
||||
if (targetTriangleCount > currentTriangleCount)
|
||||
targetTriangleCount = currentTriangleCount;
|
||||
else if (targetTriangleCount < 0)
|
||||
targetTriangleCount = 0;
|
||||
|
||||
algorithm.Initialize(mesh);
|
||||
algorithm.DecimateMesh(targetTriangleCount);
|
||||
return algorithm.ToMesh();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Decimate Mesh Lossless
|
||||
/// <summary>
|
||||
/// Decimates a mesh without losing any quality.
|
||||
/// </summary>
|
||||
/// <param name="mesh">The mesh to decimate.</param>
|
||||
/// <returns>The decimated mesh.</returns>
|
||||
public static Mesh DecimateMeshLossless(Mesh mesh)
|
||||
{
|
||||
return DecimateMeshLossless(Algorithm.Default, mesh);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decimates a mesh without losing any quality.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The desired algorithm.</param>
|
||||
/// <param name="mesh">The mesh to decimate.</param>
|
||||
/// <returns>The decimated mesh.</returns>
|
||||
public static Mesh DecimateMeshLossless(Algorithm algorithm, Mesh mesh)
|
||||
{
|
||||
if (mesh == null)
|
||||
throw new ArgumentNullException("mesh");
|
||||
|
||||
var decimationAlgorithm = CreateAlgorithm(algorithm);
|
||||
return DecimateMeshLossless(decimationAlgorithm, mesh);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decimates a mesh without losing any quality.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The decimation algorithm.</param>
|
||||
/// <param name="mesh">The mesh to decimate.</param>
|
||||
/// <returns>The decimated mesh.</returns>
|
||||
public static Mesh DecimateMeshLossless(DecimationAlgorithm algorithm, Mesh mesh)
|
||||
{
|
||||
if (algorithm == null)
|
||||
throw new ArgumentNullException("algorithm");
|
||||
else if (mesh == null)
|
||||
throw new ArgumentNullException("mesh");
|
||||
|
||||
int currentTriangleCount = mesh.TriangleCount;
|
||||
algorithm.Initialize(mesh);
|
||||
algorithm.DecimateMeshLossless();
|
||||
return algorithm.ToMesh();
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user