mirror of
https://github.com/Ryujinx/Opentk.git
synced 2024-12-23 18:25:38 +00:00
Merge branch 'develop' into glwidget-gtk3
This commit is contained in:
commit
e78036818b
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -174,6 +174,8 @@ temp/
|
|||
|
||||
# Test results produced by build
|
||||
TestResults.xml
|
||||
output.mlpd
|
||||
coverage.xml
|
||||
|
||||
# Nuget outputs
|
||||
nuget/*.nupkg
|
||||
|
|
|
@ -7,3 +7,8 @@ before_install:
|
|||
|
||||
script:
|
||||
- ./build.sh NuGet
|
||||
|
||||
after_script:
|
||||
- mono --debug --profile=log:coverage,covfilter=+OpenTK,covfilter=-OpenTK.Tests,covfilter=-FSharp.Core,covfilter=-FsCheck,covfilter=-xunit.assert "packages/xunit.runner.console/tools/xunit.console.exe" "tests/OpenTK.Tests/bin/Release/OpenTK.Tests.dll" -parallel none
|
||||
- mprof-report --reports=coverage --coverage-out=coverage.xml output.mlpd
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
|
14
OpenTK.sln
14
OpenTK.sln
|
@ -21,8 +21,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTK.GLWidget", "src\Open
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{1857BB8E-1A35-4EBF-9F6D-685F11DC025B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTK.Tests", "tests\OpenTK.Tests\OpenTK.Tests.csproj", "{930A780C-A67C-422F-9EED-DB38DAA47AB0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.API.Desktop", "tests\Test.API.Desktop\Test.API.Desktop.csproj", "{C4DDD20F-CB4E-43F4-A75C-4A3D668E1F99}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".paket", ".paket", "{F1A57014-71CE-4032-A652-01B7E35E14DB}"
|
||||
|
@ -38,6 +36,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "project", "project", "{5EEE
|
|||
RELEASE_NOTES.md = RELEASE_NOTES.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "OpenTK.Tests", "tests\OpenTK.Tests\OpenTK.Tests.fsproj", "{6801C263-ADDA-4A7B-979D-649BCB5A1DF7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -76,21 +76,21 @@ Global
|
|||
{A625BE87-0000-0000-0000-000000000000}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A625BE87-0000-0000-0000-000000000000}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A625BE87-0000-0000-0000-000000000000}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{930A780C-A67C-422F-9EED-DB38DAA47AB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{930A780C-A67C-422F-9EED-DB38DAA47AB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{930A780C-A67C-422F-9EED-DB38DAA47AB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{930A780C-A67C-422F-9EED-DB38DAA47AB0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C4DDD20F-CB4E-43F4-A75C-4A3D668E1F99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C4DDD20F-CB4E-43F4-A75C-4A3D668E1F99}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C4DDD20F-CB4E-43F4-A75C-4A3D668E1F99}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C4DDD20F-CB4E-43F4-A75C-4A3D668E1F99}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6801C263-ADDA-4A7B-979D-649BCB5A1DF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6801C263-ADDA-4A7B-979D-649BCB5A1DF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6801C263-ADDA-4A7B-979D-649BCB5A1DF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6801C263-ADDA-4A7B-979D-649BCB5A1DF7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{930A780C-A67C-422F-9EED-DB38DAA47AB0} = {1857BB8E-1A35-4EBF-9F6D-685F11DC025B}
|
||||
{C4DDD20F-CB4E-43F4-A75C-4A3D668E1F99} = {1857BB8E-1A35-4EBF-9F6D-685F11DC025B}
|
||||
{6801C263-ADDA-4A7B-979D-649BCB5A1DF7} = {1857BB8E-1A35-4EBF-9F6D-685F11DC025B}
|
||||
EndGlobalSection
|
||||
GlobalSection(MonoDevelopProperties) = preSolution
|
||||
StartupItem = Source\Examples\OpenTK.Examples.csproj
|
||||
|
|
|
@ -86,8 +86,9 @@ let activeProjects =
|
|||
f
|
||||
-- "**/OpenTK.Android.csproj"
|
||||
-- "**/OpenTK.iOS.csproj"
|
||||
|
||||
|
||||
!! "src/**/*.??proj"
|
||||
++ "tests/**/OpenTK.Tests.fsproj"
|
||||
-- "**/OpenTK.GLWidget.csproj"
|
||||
|> xamarinFilter
|
||||
|
||||
|
@ -194,7 +195,7 @@ Target "All" DoNothing
|
|||
==> "AssemblyInfo"
|
||||
==> "Build"
|
||||
==> "CopyBinaries"
|
||||
// ==> "RunTests"
|
||||
==> "RunTests"
|
||||
==> "All"
|
||||
|
||||
"All"
|
||||
|
|
|
@ -3,6 +3,7 @@ source https://nuget.org/api/v2
|
|||
#Open packages
|
||||
|
||||
nuget FSharp.Formatting
|
||||
nuget FsCheck
|
||||
nuget FsCheck.Xunit
|
||||
nuget xunit.runner.console
|
||||
nuget xunit.assert
|
||||
|
|
|
@ -11,7 +11,12 @@ using System.Reflection;
|
|||
[assembly: AssemblyCopyrightAttribute("Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.")]
|
||||
namespace System {
|
||||
internal static class AssemblyVersionInformation {
|
||||
internal const string Version = "3.0.0";
|
||||
internal const string InformationalVersion = "3.0.0";
|
||||
internal const System.String AssemblyTitle = "Generator.Bind";
|
||||
internal const System.String AssemblyProduct = "OpenTK";
|
||||
internal const System.String AssemblyDescription = "A set of fast, low-level C# bindings for OpenGL, OpenGL ES and OpenAL.";
|
||||
internal const System.String AssemblyVersion = "3.0.0";
|
||||
internal const System.String AssemblyFileVersion = "3.0.0";
|
||||
internal const System.Boolean CLSCompliant = true;
|
||||
internal const System.String AssemblyCopyright = "Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,12 @@ using System.Reflection;
|
|||
[assembly: AssemblyCopyrightAttribute("Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.")]
|
||||
namespace System {
|
||||
internal static class AssemblyVersionInformation {
|
||||
internal const string Version = "3.0.0";
|
||||
internal const string InformationalVersion = "3.0.0";
|
||||
internal const System.String AssemblyTitle = "Generator.Convert";
|
||||
internal const System.String AssemblyProduct = "OpenTK";
|
||||
internal const System.String AssemblyDescription = "A set of fast, low-level C# bindings for OpenGL, OpenGL ES and OpenAL.";
|
||||
internal const System.String AssemblyVersion = "3.0.0";
|
||||
internal const System.String AssemblyFileVersion = "3.0.0";
|
||||
internal const System.Boolean CLSCompliant = true;
|
||||
internal const System.String AssemblyCopyright = "Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,58 +90,65 @@ namespace OpenTK.Rewrite
|
|||
}
|
||||
|
||||
// Load assembly and process all modules
|
||||
using (AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(file, read_params))
|
||||
try
|
||||
{
|
||||
var rewritten = assembly.CustomAttributes.FirstOrDefault(a => a.AttributeType.Name == "RewrittenAttribute");
|
||||
if (rewritten == null)
|
||||
using (AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(file, read_params))
|
||||
{
|
||||
foreach (var module in assembly.Modules)
|
||||
var rewritten = assembly.CustomAttributes.FirstOrDefault(a => a.AttributeType.Name == "RewrittenAttribute");
|
||||
if (rewritten == null)
|
||||
{
|
||||
foreach (var reference in module.AssemblyReferences)
|
||||
foreach (var module in assembly.Modules)
|
||||
{
|
||||
try
|
||||
foreach (var reference in module.AssemblyReferences)
|
||||
{
|
||||
var resolved = module.AssemblyResolver.Resolve(reference);
|
||||
if (reference.Name == "mscorlib")
|
||||
try
|
||||
{
|
||||
mscorlib = resolved;
|
||||
var resolved = module.AssemblyResolver.Resolve(reference);
|
||||
if (reference.Name == "mscorlib")
|
||||
{
|
||||
mscorlib = resolved;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.Error.WriteLine(e.ToString());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
}
|
||||
|
||||
if (mscorlib == null)
|
||||
{
|
||||
Console.Error.WriteLine("Failed to locate mscorlib");
|
||||
return;
|
||||
}
|
||||
TypeMarshal = mscorlib.MainModule.GetType("System.Runtime.InteropServices.Marshal");
|
||||
TypeStringBuilder = mscorlib.MainModule.GetType("System.Text.StringBuilder");
|
||||
TypeVoid = mscorlib.MainModule.GetType("System.Void");
|
||||
TypeIntPtr = mscorlib.MainModule.GetType("System.IntPtr");
|
||||
TypeInt32 = mscorlib.MainModule.GetType("System.Int32");
|
||||
|
||||
TypeBindingsBase = assembly.Modules.Select(m => m.GetType("OpenTK.BindingsBase")).First();
|
||||
|
||||
foreach (var module in assembly.Modules)
|
||||
{
|
||||
foreach (var type in module.Types)
|
||||
{
|
||||
Console.Error.WriteLine(e.ToString());
|
||||
Rewrite(type, optionsEnumerated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mscorlib == null)
|
||||
else
|
||||
{
|
||||
Console.Error.WriteLine("Failed to locate mscorlib");
|
||||
return;
|
||||
Console.Error.WriteLine("Error: assembly has already been rewritten");
|
||||
}
|
||||
TypeMarshal = mscorlib.MainModule.GetType("System.Runtime.InteropServices.Marshal");
|
||||
TypeStringBuilder = mscorlib.MainModule.GetType("System.Text.StringBuilder");
|
||||
TypeVoid = mscorlib.MainModule.GetType("System.Void");
|
||||
TypeIntPtr = mscorlib.MainModule.GetType("System.IntPtr");
|
||||
TypeInt32 = mscorlib.MainModule.GetType("System.Int32");
|
||||
|
||||
TypeBindingsBase = assembly.Modules.Select(m => m.GetType("OpenTK.BindingsBase")).First();
|
||||
|
||||
foreach (var module in assembly.Modules)
|
||||
{
|
||||
foreach (var type in module.Types)
|
||||
{
|
||||
Rewrite(type, optionsEnumerated);
|
||||
}
|
||||
}
|
||||
// Save rewritten assembly
|
||||
assembly.Write(write_params);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error.WriteLine("Error: assembly has already been rewritten");
|
||||
}
|
||||
|
||||
// Save rewritten assembly
|
||||
assembly.Write(write_params);
|
||||
}
|
||||
catch (InvalidOperationException inex)
|
||||
{
|
||||
Console.WriteLine("Failed to load the assembly. It may already have been rewritten, and the debug symbols no longer match.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,12 @@ using System.Reflection;
|
|||
[assembly: AssemblyCopyrightAttribute("Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.")]
|
||||
namespace System {
|
||||
internal static class AssemblyVersionInformation {
|
||||
internal const string Version = "3.0.0";
|
||||
internal const string InformationalVersion = "3.0.0";
|
||||
internal const System.String AssemblyTitle = "Generator.Rewrite";
|
||||
internal const System.String AssemblyProduct = "OpenTK";
|
||||
internal const System.String AssemblyDescription = "A set of fast, low-level C# bindings for OpenGL, OpenGL ES and OpenAL.";
|
||||
internal const System.String AssemblyVersion = "3.0.0";
|
||||
internal const System.String AssemblyFileVersion = "3.0.0";
|
||||
internal const System.Boolean CLSCompliant = true;
|
||||
internal const System.String AssemblyCopyright = "Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,12 @@ using System.Reflection;
|
|||
[assembly: AssemblyCopyrightAttribute("Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.")]
|
||||
namespace System {
|
||||
internal static class AssemblyVersionInformation {
|
||||
internal const string Version = "3.0.0";
|
||||
internal const string InformationalVersion = "3.0.0";
|
||||
internal const System.String AssemblyTitle = "OpenTK.GLControl";
|
||||
internal const System.String AssemblyProduct = "OpenTK";
|
||||
internal const System.String AssemblyDescription = "A set of fast, low-level C# bindings for OpenGL, OpenGL ES and OpenAL.";
|
||||
internal const System.String AssemblyVersion = "3.0.0";
|
||||
internal const System.String AssemblyFileVersion = "3.0.0";
|
||||
internal const System.Boolean CLSCompliant = true;
|
||||
internal const System.String AssemblyCopyright = "Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@
|
|||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Choose>
|
||||
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.1' Or $(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6' Or $(TargetFrameworkVersion) == 'v4.6.1' Or $(TargetFrameworkVersion) == 'v4.6.2' Or $(TargetFrameworkVersion) == 'v4.6.3')">
|
||||
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.1' Or $(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6' Or $(TargetFrameworkVersion) == 'v4.6.1' Or $(TargetFrameworkVersion) == 'v4.6.2' Or $(TargetFrameworkVersion) == 'v4.6.3' Or $(TargetFrameworkVersion) == 'v4.7')">
|
||||
<PropertyGroup>
|
||||
<__paket__GtkSharp_targets>net45\GtkSharp</__paket__GtkSharp_targets>
|
||||
</PropertyGroup>
|
||||
|
@ -126,7 +126,7 @@
|
|||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Choose>
|
||||
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.1' Or $(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6' Or $(TargetFrameworkVersion) == 'v4.6.1' Or $(TargetFrameworkVersion) == 'v4.6.2' Or $(TargetFrameworkVersion) == 'v4.6.3')">
|
||||
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.1' Or $(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6' Or $(TargetFrameworkVersion) == 'v4.6.1' Or $(TargetFrameworkVersion) == 'v4.6.2' Or $(TargetFrameworkVersion) == 'v4.6.3' Or $(TargetFrameworkVersion) == 'v4.7')">
|
||||
<ItemGroup>
|
||||
<Reference Include="cairo-sharp">
|
||||
<HintPath>..\..\packages\GtkSharp\lib\net45\cairo-sharp.dll</HintPath>
|
||||
|
|
|
@ -11,7 +11,12 @@ using System.Reflection;
|
|||
[assembly: AssemblyCopyrightAttribute("Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.")]
|
||||
namespace System {
|
||||
internal static class AssemblyVersionInformation {
|
||||
internal const string Version = "3.0.0";
|
||||
internal const string InformationalVersion = "3.0.0";
|
||||
internal const System.String AssemblyTitle = "OpenTK.GLWidget";
|
||||
internal const System.String AssemblyProduct = "OpenTK";
|
||||
internal const System.String AssemblyDescription = "A set of fast, low-level C# bindings for OpenGL, OpenGL ES and OpenAL.";
|
||||
internal const System.String AssemblyVersion = "3.0.0";
|
||||
internal const System.String AssemblyFileVersion = "3.0.0";
|
||||
internal const System.Boolean CLSCompliant = true;
|
||||
internal const System.String AssemblyCopyright = "Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,13 +3,14 @@
|
|||
* Copyright (c) 2006-2008 the OpenTK Team.
|
||||
* This notice may not be removed from any source distribution.
|
||||
* See license.txt for licensing detailed licensing details.
|
||||
*
|
||||
*
|
||||
* Contributions by Andy Gill, James Talton and Georg Wächter.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenTK
|
||||
|
@ -326,8 +327,149 @@ namespace OpenTK
|
|||
return Math.Max(Math.Min(n, max), min);
|
||||
}
|
||||
|
||||
#endregion
|
||||
private static unsafe int FloatToInt32Bits(float f) {
|
||||
return *((int*) &f);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
/// <summary>
|
||||
/// Approximates floating point equality with a maximum number of different bits.
|
||||
/// This is typically used in place of an epsilon comparison.
|
||||
/// see: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
|
||||
/// see: https://stackoverflow.com/questions/3874627/floating-point-comparison-functions-for-c-sharp
|
||||
/// </summary>
|
||||
/// <param name="a">the first value to compare</param>
|
||||
/// <param name="b">>the second value to compare</param>
|
||||
/// <param name="maxDeltaBits">the number of floating point bits to check</param>
|
||||
/// <returns></returns>
|
||||
public static bool ApproximatelyEqual(float a, float b, int maxDeltaBits) {
|
||||
// we use longs here, otherwise we run into a two's complement problem, causing this to fail with -2 and 2.0
|
||||
long aInt = FloatToInt32Bits(a);
|
||||
if (aInt < 0)
|
||||
aInt = Int32.MinValue - aInt;
|
||||
|
||||
long bInt = FloatToInt32Bits(b);
|
||||
if (bInt < 0)
|
||||
bInt = Int32.MinValue - bInt;
|
||||
|
||||
long intDiff = Math.Abs(aInt - bInt);
|
||||
return intDiff <= (1 << maxDeltaBits);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Approximates double-precision floating point equality by an epsilon (maximum error) value.
|
||||
/// This method is designed as a "fits-all" solution and attempts to handle as many cases as possible.
|
||||
/// </summary>
|
||||
/// <param name="a">The first float.</param>
|
||||
/// <param name="b">The second float.</param>
|
||||
/// <param name="epsilon">The maximum error between the two.</param>
|
||||
/// <returns><value>true</value> if the values are approximately equal within the error margin; otherwise, <value>false</value>.</returns>
|
||||
[SuppressMessage("ReSharper", "CompareOfFloatsByEqualityOperator")]
|
||||
public static bool ApproximatelyEqualEpsilon(double a, double b, double epsilon)
|
||||
{
|
||||
const double doubleNormal = (1L << 52) * double.Epsilon;
|
||||
double absA = Math.Abs(a);
|
||||
double absB = Math.Abs(b);
|
||||
double diff = Math.Abs(a - b);
|
||||
|
||||
if (a == b)
|
||||
{
|
||||
// Shortcut, handles infinities
|
||||
return true;
|
||||
}
|
||||
|
||||
if (a == 0.0f || b == 0.0f || diff < doubleNormal)
|
||||
{
|
||||
// a or b is zero, or both are extremely close to it.
|
||||
// relative error is less meaningful here
|
||||
return diff < (epsilon * doubleNormal);
|
||||
}
|
||||
|
||||
// use relative error
|
||||
return diff / Math.Min((absA + absB), double.MaxValue) < epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Approximates single-precision floating point equality by an epsilon (maximum error) value.
|
||||
/// This method is designed as a "fits-all" solution and attempts to handle as many cases as possible.
|
||||
/// </summary>
|
||||
/// <param name="a">The first float.</param>
|
||||
/// <param name="b">The second float.</param>
|
||||
/// <param name="epsilon">The maximum error between the two.</param>
|
||||
/// <returns><value>true</value> if the values are approximately equal within the error margin; otherwise, <value>false</value>.</returns>
|
||||
[SuppressMessage("ReSharper", "CompareOfFloatsByEqualityOperator")]
|
||||
public static bool ApproximatelyEqualEpsilon(float a, float b, float epsilon)
|
||||
{
|
||||
const float floatNormal = (1 << 23) * float.Epsilon;
|
||||
float absA = Math.Abs(a);
|
||||
float absB = Math.Abs(b);
|
||||
float diff = Math.Abs(a - b);
|
||||
|
||||
if (a == b)
|
||||
{
|
||||
// Shortcut, handles infinities
|
||||
return true;
|
||||
}
|
||||
|
||||
if (a == 0.0f || b == 0.0f || diff < floatNormal)
|
||||
{
|
||||
// a or b is zero, or both are extremely close to it.
|
||||
// relative error is less meaningful here
|
||||
return diff < (epsilon * floatNormal);
|
||||
}
|
||||
|
||||
// use relative error
|
||||
float relativeError = diff / Math.Min((absA + absB), float.MaxValue);
|
||||
return relativeError < epsilon;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Approximates equivalence between two single-precision floating-point numbers on a direct human scale.
|
||||
/// It is important to note that this does not approximate equality - instead, it merely checks whether or not
|
||||
/// two numbers could be considered equivalent to each other within a certain tolerance. The tolerance is
|
||||
/// inclusive.
|
||||
/// </summary>
|
||||
/// <param name="a">The first value to compare.</param>
|
||||
/// <param name="b">The second value to compare·</param>
|
||||
/// <param name="tolerance">The tolerance within which the two values would be considered equivalent.</param>
|
||||
/// <returns>Whether or not the values can be considered equivalent within the tolerance.</returns>
|
||||
[SuppressMessage("ReSharper", "CompareOfFloatsByEqualityOperator")]
|
||||
public static bool ApproximatelyEquivalent(float a, float b, float tolerance)
|
||||
{
|
||||
if (a == b)
|
||||
{
|
||||
// Early bailout, handles infinities
|
||||
return true;
|
||||
}
|
||||
|
||||
float diff = Math.Abs(a - b);
|
||||
return diff <= tolerance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Approximates equivalence between two double-precision floating-point numbers on a direct human scale.
|
||||
/// It is important to note that this does not approximate equality - instead, it merely checks whether or not
|
||||
/// two numbers could be considered equivalent to each other within a certain tolerance. The tolerance is
|
||||
/// inclusive.
|
||||
/// </summary>
|
||||
/// <param name="a">The first value to compare.</param>
|
||||
/// <param name="b">The second value to compare·</param>
|
||||
/// <param name="tolerance">The tolerance within which the two values would be considered equivalent.</param>
|
||||
/// <returns>Whether or not the values can be considered equivalent within the tolerance.</returns>
|
||||
[SuppressMessage("ReSharper", "CompareOfFloatsByEqualityOperator")]
|
||||
public static bool ApproximatelyEquivalent(double a, double b, double tolerance)
|
||||
{
|
||||
if (a == b)
|
||||
{
|
||||
// Early bailout, handles infinities
|
||||
return true;
|
||||
}
|
||||
|
||||
double diff = Math.Abs(a - b);
|
||||
return diff <= tolerance;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -623,7 +623,8 @@ namespace OpenTK
|
|||
/// <param name="result">Result of the operation.</param>
|
||||
public static void Divide(ref Vector2 vector, float scale, out Vector2 result)
|
||||
{
|
||||
Multiply(ref vector, 1 / scale, out result);
|
||||
result.X = vector.X / scale;
|
||||
result.Y = vector.Y / scale;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -654,7 +655,7 @@ namespace OpenTK
|
|||
#region ComponentMin
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise minimum of two vectors
|
||||
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
|
@ -667,7 +668,7 @@ namespace OpenTK
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise minimum of two vectors
|
||||
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
|
@ -683,7 +684,7 @@ namespace OpenTK
|
|||
#region ComponentMax
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise maximum of two vectors
|
||||
/// Returns a vector created from the largest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
|
@ -696,7 +697,7 @@ namespace OpenTK
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise maximum of two vectors
|
||||
/// Returns a vector created from the largest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
|
@ -709,6 +710,64 @@ namespace OpenTK
|
|||
|
||||
#endregion
|
||||
|
||||
#region MagnitudeMin
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector2 with the minimum magnitude. If the magnitudes are equal, the second vector
|
||||
/// is selected.
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <returns>The minimum Vector2</returns>
|
||||
public static Vector2 MagnitudeMin(Vector2 left, Vector2 right)
|
||||
{
|
||||
return left.LengthSquared < right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector2 with the minimum magnitude. If the magnitudes are equal, the second vector
|
||||
/// is selected.
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <param name="result">The magnitude-wise minimum</param>
|
||||
/// <returns>The minimum Vector2</returns>
|
||||
public static void MagnitudeMin(ref Vector2 left, ref Vector2 right, out Vector2 result)
|
||||
{
|
||||
result = left.LengthSquared < right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MagnitudeMax
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector2 with the maximum magnitude. If the magnitudes are equal, the first vector
|
||||
/// is selected.
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <returns>The maximum Vector2</returns>
|
||||
public static Vector2 MagnitudeMax(Vector2 left, Vector2 right)
|
||||
{
|
||||
return left.LengthSquared >= right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector2 with the maximum magnitude. If the magnitudes are equal, the first vector
|
||||
/// is selected.
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <param name="result">The magnitude-wise maximum</param>
|
||||
/// <returns>The maximum Vector2</returns>
|
||||
public static void MagnitudeMax(ref Vector2 left, ref Vector2 right, out Vector2 result)
|
||||
{
|
||||
result = left.LengthSquared >= right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Min
|
||||
|
||||
/// <summary>
|
||||
|
@ -717,6 +776,7 @@ namespace OpenTK
|
|||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <returns>The minimum Vector3</returns>
|
||||
[Obsolete("Use MagnitudeMin() instead.")]
|
||||
public static Vector2 Min(Vector2 left, Vector2 right)
|
||||
{
|
||||
return left.LengthSquared < right.LengthSquared ? left : right;
|
||||
|
@ -732,6 +792,7 @@ namespace OpenTK
|
|||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <returns>The minimum Vector3</returns>
|
||||
[Obsolete("Use MagnitudeMax() instead.")]
|
||||
public static Vector2 Max(Vector2 left, Vector2 right)
|
||||
{
|
||||
return left.LengthSquared >= right.LengthSquared ? left : right;
|
||||
|
@ -1074,7 +1135,7 @@ namespace OpenTK
|
|||
vec.Y *= scale.Y;
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Divides the specified instance by a scalar.
|
||||
/// </summary>
|
||||
|
@ -1083,9 +1144,8 @@ namespace OpenTK
|
|||
/// <returns>Result of the division.</returns>
|
||||
public static Vector2 operator /(Vector2 vec, float scale)
|
||||
{
|
||||
float mult = 1.0f / scale;
|
||||
vec.X *= mult;
|
||||
vec.Y *= mult;
|
||||
vec.X /= scale;
|
||||
vec.Y /= scale;
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
|
|
@ -541,7 +541,8 @@ namespace OpenTK
|
|||
/// <param name="result">Result of the operation.</param>
|
||||
public static void Divide(ref Vector2d vector, double scale, out Vector2d result)
|
||||
{
|
||||
Multiply(ref vector, 1 / scale, out result);
|
||||
result.X = vector.X / scale;
|
||||
result.Y = vector.Y / scale;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -577,6 +578,7 @@ namespace OpenTK
|
|||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>The component-wise minimum</returns>
|
||||
[Obsolete("Use ComponentMin() instead.")]
|
||||
public static Vector2d Min(Vector2d a, Vector2d b)
|
||||
{
|
||||
a.X = a.X < b.X ? a.X : b.X;
|
||||
|
@ -590,6 +592,7 @@ namespace OpenTK
|
|||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">The component-wise minimum</param>
|
||||
[Obsolete("Use ComponentMin() instead.")]
|
||||
public static void Min(ref Vector2d a, ref Vector2d b, out Vector2d result)
|
||||
{
|
||||
result.X = a.X < b.X ? a.X : b.X;
|
||||
|
@ -606,6 +609,7 @@ namespace OpenTK
|
|||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>The component-wise maximum</returns>
|
||||
[Obsolete("Use ComponentMax() instead.")]
|
||||
public static Vector2d Max(Vector2d a, Vector2d b)
|
||||
{
|
||||
a.X = a.X > b.X ? a.X : b.X;
|
||||
|
@ -619,6 +623,7 @@ namespace OpenTK
|
|||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">The component-wise maximum</param>
|
||||
[Obsolete("Use ComponentMax() instead.")]
|
||||
public static void Max(ref Vector2d a, ref Vector2d b, out Vector2d result)
|
||||
{
|
||||
result.X = a.X > b.X ? a.X : b.X;
|
||||
|
@ -627,6 +632,122 @@ namespace OpenTK
|
|||
|
||||
#endregion
|
||||
|
||||
#region ComponentMin
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>The component-wise minimum</returns>
|
||||
public static Vector2d ComponentMin(Vector2d a, Vector2d b)
|
||||
{
|
||||
a.X = a.X < b.X ? a.X : b.X;
|
||||
a.Y = a.Y < b.Y ? a.Y : b.Y;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">The component-wise minimum</param>
|
||||
public static void ComponentMin(ref Vector2d a, ref Vector2d b, out Vector2d result)
|
||||
{
|
||||
result.X = a.X < b.X ? a.X : b.X;
|
||||
result.Y = a.Y < b.Y ? a.Y : b.Y;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ComponentMax
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector created from the largest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>The component-wise maximum</returns>
|
||||
public static Vector2d ComponentMax(Vector2d a, Vector2d b)
|
||||
{
|
||||
a.X = a.X > b.X ? a.X : b.X;
|
||||
a.Y = a.Y > b.Y ? a.Y : b.Y;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector created from the largest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">The component-wise maximum</param>
|
||||
public static void ComponentMax(ref Vector2d a, ref Vector2d b, out Vector2d result)
|
||||
{
|
||||
result.X = a.X > b.X ? a.X : b.X;
|
||||
result.Y = a.Y > b.Y ? a.Y : b.Y;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MagnitudeMin
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector2d with the minimum magnitude. If the magnitudes are equal, the second vector
|
||||
/// is selected.
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <returns>The minimum Vector2d</returns>
|
||||
public static Vector2d MagnitudeMin(Vector2d left, Vector2d right)
|
||||
{
|
||||
return left.LengthSquared < right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector2d with the minimum magnitude. If the magnitudes are equal, the second vector
|
||||
/// is selected.
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <param name="result">The magnitude-wise minimum</param>
|
||||
/// <returns>The minimum Vector2d</returns>
|
||||
public static void MagnitudeMin(ref Vector2d left, ref Vector2d right, out Vector2d result)
|
||||
{
|
||||
result = left.LengthSquared < right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MagnitudeMax
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector2d with the minimum magnitude. If the magnitudes are equal, the first vector
|
||||
/// is selected.
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <returns>The minimum Vector2d</returns>
|
||||
public static Vector2d MagnitudeMax(Vector2d left, Vector2d right)
|
||||
{
|
||||
return left.LengthSquared >= right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector2d with the maximum magnitude. If the magnitudes are equal, the first vector
|
||||
/// is selected.
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <param name="result">The magnitude-wise maximum</param>
|
||||
/// <returns>The maximum Vector2d</returns>
|
||||
public static void MagnitudeMax(ref Vector2d left, ref Vector2d right, out Vector2d result)
|
||||
{
|
||||
result = left.LengthSquared >= right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Clamp
|
||||
|
||||
/// <summary>
|
||||
|
@ -936,7 +1057,7 @@ namespace OpenTK
|
|||
vec.Y *= scale.Y;
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Divides an instance by a scalar.
|
||||
/// </summary>
|
||||
|
@ -945,9 +1066,8 @@ namespace OpenTK
|
|||
/// <returns>The result of the operation.</returns>
|
||||
public static Vector2d operator /(Vector2d vec, double f)
|
||||
{
|
||||
double mult = 1.0 / f;
|
||||
vec.X *= mult;
|
||||
vec.Y *= mult;
|
||||
vec.X /= f;
|
||||
vec.Y /= f;
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
|
|
@ -629,7 +629,9 @@ namespace OpenTK
|
|||
/// <param name="result">Result of the operation.</param>
|
||||
public static void Divide(ref Vector3 vector, float scale, out Vector3 result)
|
||||
{
|
||||
Multiply(ref vector, 1 / scale, out result);
|
||||
result.X = vector.X / scale;
|
||||
result.Y = vector.Y / scale;
|
||||
result.Z = vector.Z / scale;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -660,7 +662,7 @@ namespace OpenTK
|
|||
#region ComponentMin
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise minimum of two vectors
|
||||
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
|
@ -674,7 +676,7 @@ namespace OpenTK
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise minimum of two vectors
|
||||
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
|
@ -691,7 +693,7 @@ namespace OpenTK
|
|||
#region ComponentMax
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise maximum of two vectors
|
||||
/// Returns a vector created from the largest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
|
@ -705,7 +707,7 @@ namespace OpenTK
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise maximum of two vectors
|
||||
/// Returns a vector created from the largest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
|
@ -719,6 +721,64 @@ namespace OpenTK
|
|||
|
||||
#endregion
|
||||
|
||||
#region MagnitudeMin
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector3 with the minimum magnitude. If the magnitudes are equal, the second vector
|
||||
/// is selected.
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <returns>The minimum Vector3</returns>
|
||||
public static Vector3 MagnitudeMin(Vector3 left, Vector3 right)
|
||||
{
|
||||
return left.LengthSquared < right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector3 with the minimum magnitude. If the magnitudes are equal, the second vector
|
||||
/// is selected.
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <param name="result">The magnitude-wise minimum</param>
|
||||
/// <returns>The minimum Vector3</returns>
|
||||
public static void MagnitudeMin(ref Vector3 left, ref Vector3 right, out Vector3 result)
|
||||
{
|
||||
result = left.LengthSquared < right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MagnitudeMax
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector3 with the maximum magnitude. If the magnitudes are equal, the first vector
|
||||
/// is selected.
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <returns>The maximum Vector3</returns>
|
||||
public static Vector3 MagnitudeMax(Vector3 left, Vector3 right)
|
||||
{
|
||||
return left.LengthSquared >= right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector3 with the maximum magnitude. If the magnitudes are equal, the first vector
|
||||
/// is selected.
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <param name="result">The magnitude-wise maximum</param>
|
||||
/// <returns>The maximum Vector3</returns>
|
||||
public static void MagnitudeMax(ref Vector3 left, ref Vector3 right, out Vector3 result)
|
||||
{
|
||||
result = left.LengthSquared >= right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Min
|
||||
|
||||
/// <summary>
|
||||
|
@ -727,6 +787,7 @@ namespace OpenTK
|
|||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <returns>The minimum Vector3</returns>
|
||||
[Obsolete("Use MagnitudeMin() instead.")]
|
||||
public static Vector3 Min(Vector3 left, Vector3 right)
|
||||
{
|
||||
return left.LengthSquared < right.LengthSquared ? left : right;
|
||||
|
@ -742,6 +803,7 @@ namespace OpenTK
|
|||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <returns>The minimum Vector3</returns>
|
||||
[Obsolete("Use MagnitudeMax() instead.")]
|
||||
public static Vector3 Max(Vector3 left, Vector3 right)
|
||||
{
|
||||
return left.LengthSquared >= right.LengthSquared ? left : right;
|
||||
|
@ -1270,10 +1332,10 @@ namespace OpenTK
|
|||
{
|
||||
Vector4 result;
|
||||
|
||||
result.X =
|
||||
vector.X * worldViewProjection.M11 +
|
||||
vector.Y * worldViewProjection.M21 +
|
||||
vector.Z * worldViewProjection.M31 +
|
||||
result.X =
|
||||
vector.X * worldViewProjection.M11 +
|
||||
vector.Y * worldViewProjection.M21 +
|
||||
vector.Z * worldViewProjection.M31 +
|
||||
worldViewProjection.M41;
|
||||
|
||||
result.Y =
|
||||
|
@ -1574,10 +1636,9 @@ namespace OpenTK
|
|||
/// <returns>The result of the calculation.</returns>
|
||||
public static Vector3 operator /(Vector3 vec, float scale)
|
||||
{
|
||||
float mult = 1.0f / scale;
|
||||
vec.X *= mult;
|
||||
vec.Y *= mult;
|
||||
vec.Z *= mult;
|
||||
vec.X /= scale;
|
||||
vec.Y /= scale;
|
||||
vec.Z /= scale;
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
|
|
@ -627,7 +627,9 @@ namespace OpenTK
|
|||
/// <param name="result">Result of the operation.</param>
|
||||
public static void Divide(ref Vector3d vector, double scale, out Vector3d result)
|
||||
{
|
||||
Multiply(ref vector, 1 / scale, out result);
|
||||
result.X = vector.X / scale;
|
||||
result.Y = vector.Y / scale;
|
||||
result.Z = vector.Z / scale;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -658,7 +660,7 @@ namespace OpenTK
|
|||
#region ComponentMin
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise minimum of two vectors
|
||||
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
|
@ -672,7 +674,7 @@ namespace OpenTK
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise minimum of two vectors
|
||||
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
|
@ -689,7 +691,7 @@ namespace OpenTK
|
|||
#region ComponentMax
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise maximum of two vectors
|
||||
/// Returns a vector created from the largest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
|
@ -703,7 +705,7 @@ namespace OpenTK
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise maximum of two vectors
|
||||
/// Returns a vector created from the largest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
|
@ -717,6 +719,60 @@ namespace OpenTK
|
|||
|
||||
#endregion
|
||||
|
||||
#region MagnitudeMin
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector3d with the minimum magnitude
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <returns>The minimum Vector3d</returns>
|
||||
public static Vector3d MagnitudeMin(Vector3d left, Vector3d right)
|
||||
{
|
||||
return left.LengthSquared < right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector3d with the minimum magnitude
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <param name="result">The magnitude-wise minimum</param>
|
||||
/// <returns>The minimum Vector3d</returns>
|
||||
public static void MagnitudeMin(ref Vector3d left, ref Vector3d right, out Vector3d result)
|
||||
{
|
||||
result = left.LengthSquared < right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MagnitudeMax
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector3d with the minimum magnitude
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <returns>The minimum Vector3d</returns>
|
||||
public static Vector3d MagnitudeMax(Vector3d left, Vector3d right)
|
||||
{
|
||||
return left.LengthSquared >= right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector3d with the maximum magnitude
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <param name="result">The magnitude-wise maximum</param>
|
||||
/// <returns>The maximum Vector3d</returns>
|
||||
public static void MagnitudeMax(ref Vector3d left, ref Vector3d right, out Vector3d result)
|
||||
{
|
||||
result = left.LengthSquared >= right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Min
|
||||
|
||||
/// <summary>
|
||||
|
@ -725,6 +781,7 @@ namespace OpenTK
|
|||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <returns>The minimum Vector3</returns>
|
||||
[Obsolete("Use MagnitudeMin() instead.")]
|
||||
public static Vector3d Min(Vector3d left, Vector3d right)
|
||||
{
|
||||
return left.LengthSquared < right.LengthSquared ? left : right;
|
||||
|
@ -740,6 +797,7 @@ namespace OpenTK
|
|||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <returns>The minimum Vector3</returns>
|
||||
[Obsolete("Use MagnitudeMax() instead.")]
|
||||
public static Vector3d Max(Vector3d left, Vector3d right)
|
||||
{
|
||||
return left.LengthSquared >= right.LengthSquared ? left : right;
|
||||
|
@ -1372,7 +1430,7 @@ namespace OpenTK
|
|||
vec.Z *= scale;
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Component-wise multiplication between the specified instance by a scale vector.
|
||||
/// </summary>
|
||||
|
@ -1386,7 +1444,7 @@ namespace OpenTK
|
|||
vec.Z *= scale.Z;
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Divides an instance by a scalar.
|
||||
/// </summary>
|
||||
|
@ -1395,10 +1453,9 @@ namespace OpenTK
|
|||
/// <returns>The result of the calculation.</returns>
|
||||
public static Vector3d operator /(Vector3d vec, double scale)
|
||||
{
|
||||
double mult = 1 / scale;
|
||||
vec.X *= mult;
|
||||
vec.Y *= mult;
|
||||
vec.Z *= mult;
|
||||
vec.X /= scale;
|
||||
vec.Y /= scale;
|
||||
vec.Z /= scale;
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
|
|
@ -514,11 +514,10 @@ namespace OpenTK
|
|||
/// <returns>Result of the division</returns>
|
||||
public static Vector4 Div(Vector4 a, float f)
|
||||
{
|
||||
float mult = 1.0f / f;
|
||||
a.X *= mult;
|
||||
a.Y *= mult;
|
||||
a.Z *= mult;
|
||||
a.W *= mult;
|
||||
a.X /= f;
|
||||
a.Y /= f;
|
||||
a.Z /= f;
|
||||
a.W /= f;
|
||||
return a;
|
||||
}
|
||||
|
||||
|
@ -530,11 +529,10 @@ namespace OpenTK
|
|||
/// <param name="result">Result of the division</param>
|
||||
public static void Div(ref Vector4 a, float f, out Vector4 result)
|
||||
{
|
||||
float mult = 1.0f / f;
|
||||
result.X = a.X * mult;
|
||||
result.Y = a.Y * mult;
|
||||
result.Z = a.Z * mult;
|
||||
result.W = a.W * mult;
|
||||
result.X = a.X / f;
|
||||
result.Y = a.Y / f;
|
||||
result.Z = a.Z / f;
|
||||
result.W = a.W / f;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -667,7 +665,10 @@ namespace OpenTK
|
|||
/// <param name="result">Result of the operation.</param>
|
||||
public static void Divide(ref Vector4 vector, float scale, out Vector4 result)
|
||||
{
|
||||
Multiply(ref vector, 1 / scale, out result);
|
||||
result.X = vector.X / scale;
|
||||
result.Y = vector.Y / scale;
|
||||
result.Z = vector.Z / scale;
|
||||
result.W = vector.W / scale;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -703,6 +704,7 @@ namespace OpenTK
|
|||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>The component-wise minimum</returns>
|
||||
[Obsolete("Use ComponentMin() instead.")]
|
||||
public static Vector4 Min(Vector4 a, Vector4 b)
|
||||
{
|
||||
a.X = a.X < b.X ? a.X : b.X;
|
||||
|
@ -718,6 +720,7 @@ namespace OpenTK
|
|||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">The component-wise minimum</param>
|
||||
[Obsolete("Use ComponentMin() instead.")]
|
||||
public static void Min(ref Vector4 a, ref Vector4 b, out Vector4 result)
|
||||
{
|
||||
result.X = a.X < b.X ? a.X : b.X;
|
||||
|
@ -736,6 +739,7 @@ namespace OpenTK
|
|||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>The component-wise maximum</returns>
|
||||
[Obsolete("Use ComponentMax() instead.")]
|
||||
public static Vector4 Max(Vector4 a, Vector4 b)
|
||||
{
|
||||
a.X = a.X > b.X ? a.X : b.X;
|
||||
|
@ -751,6 +755,7 @@ namespace OpenTK
|
|||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">The component-wise maximum</param>
|
||||
[Obsolete("Use ComponentMax() instead.")]
|
||||
public static void Max(ref Vector4 a, ref Vector4 b, out Vector4 result)
|
||||
{
|
||||
result.X = a.X > b.X ? a.X : b.X;
|
||||
|
@ -761,6 +766,130 @@ namespace OpenTK
|
|||
|
||||
#endregion
|
||||
|
||||
#region ComponentMin
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>The component-wise minimum</returns>
|
||||
public static Vector4 ComponentMin(Vector4 a, Vector4 b)
|
||||
{
|
||||
a.X = a.X < b.X ? a.X : b.X;
|
||||
a.Y = a.Y < b.Y ? a.Y : b.Y;
|
||||
a.Z = a.Z < b.Z ? a.Z : b.Z;
|
||||
a.W = a.W < b.W ? a.W : b.W;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">The component-wise minimum</param>
|
||||
public static void ComponentMin(ref Vector4 a, ref Vector4 b, out Vector4 result)
|
||||
{
|
||||
result.X = a.X < b.X ? a.X : b.X;
|
||||
result.Y = a.Y < b.Y ? a.Y : b.Y;
|
||||
result.Z = a.Z < b.Z ? a.Z : b.Z;
|
||||
result.W = a.W < b.W ? a.W : b.W;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ComponentMax
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector created from the largest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>The component-wise maximum</returns>
|
||||
public static Vector4 ComponentMax(Vector4 a, Vector4 b)
|
||||
{
|
||||
a.X = a.X > b.X ? a.X : b.X;
|
||||
a.Y = a.Y > b.Y ? a.Y : b.Y;
|
||||
a.Z = a.Z > b.Z ? a.Z : b.Z;
|
||||
a.W = a.W > b.W ? a.W : b.W;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector created from the largest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">The component-wise maximum</param>
|
||||
public static void ComponentMax(ref Vector4 a, ref Vector4 b, out Vector4 result)
|
||||
{
|
||||
result.X = a.X > b.X ? a.X : b.X;
|
||||
result.Y = a.Y > b.Y ? a.Y : b.Y;
|
||||
result.Z = a.Z > b.Z ? a.Z : b.Z;
|
||||
result.W = a.W > b.W ? a.W : b.W;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MagnitudeMin
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector4 with the minimum magnitude. If the magnitudes are equal, the second vector
|
||||
/// is selected.
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <returns>The minimum Vector4</returns>
|
||||
public static Vector4 MagnitudeMin(Vector4 left, Vector4 right)
|
||||
{
|
||||
return left.LengthSquared < right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector4 with the minimum magnitude. If the magnitudes are equal, the second vector
|
||||
/// is selected.
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <param name="result">The magnitude-wise minimum</param>
|
||||
/// <returns>The minimum Vector4</returns>
|
||||
public static void MagnitudeMin(ref Vector4 left, ref Vector4 right, out Vector4 result)
|
||||
{
|
||||
result = left.LengthSquared < right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MagnitudeMax
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector4 with the maximum magnitude. If the magnitudes are equal, the first vector
|
||||
/// is selected.
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <returns>The maximum Vector4</returns>
|
||||
public static Vector4 MagnitudeMax(Vector4 left, Vector4 right)
|
||||
{
|
||||
return left.LengthSquared >= right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector4 with the maximum magnitude. If the magnitudes are equal, the first vector
|
||||
/// is selected.
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <param name="result">The magnitude-wise maximum</param>
|
||||
/// <returns>The maximum Vector4</returns>
|
||||
public static void MagnitudeMax(ref Vector4 left, ref Vector4 right, out Vector4 result)
|
||||
{
|
||||
result = left.LengthSquared >= right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Clamp
|
||||
|
||||
/// <summary>
|
||||
|
@ -774,8 +903,8 @@ namespace OpenTK
|
|||
{
|
||||
vec.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
|
||||
vec.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
|
||||
vec.Z = vec.X < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
|
||||
vec.W = vec.Y < min.W ? min.W : vec.W > max.W ? max.W : vec.W;
|
||||
vec.Z = vec.Z < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
|
||||
vec.W = vec.W < min.W ? min.W : vec.W > max.W ? max.W : vec.W;
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
@ -790,8 +919,8 @@ namespace OpenTK
|
|||
{
|
||||
result.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
|
||||
result.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
|
||||
result.Z = vec.X < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
|
||||
result.W = vec.Y < min.W ? min.W : vec.W > max.W ? max.W : vec.W;
|
||||
result.Z = vec.Z < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
|
||||
result.W = vec.W < min.W ? min.W : vec.W > max.W ? max.W : vec.W;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -1514,7 +1643,7 @@ namespace OpenTK
|
|||
vec.W *= scale;
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Component-wise multiplication between the specified instance by a scale vector.
|
||||
/// </summary>
|
||||
|
@ -1577,11 +1706,10 @@ namespace OpenTK
|
|||
/// <returns>The result of the calculation.</returns>
|
||||
public static Vector4 operator /(Vector4 vec, float scale)
|
||||
{
|
||||
float mult = 1.0f / scale;
|
||||
vec.X *= mult;
|
||||
vec.Y *= mult;
|
||||
vec.Z *= mult;
|
||||
vec.W *= mult;
|
||||
vec.X /= scale;
|
||||
vec.Y /= scale;
|
||||
vec.Z /= scale;
|
||||
vec.W /= scale;
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ namespace OpenTK
|
|||
#endregion
|
||||
|
||||
#region Public Members
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value at the index of the Vector.
|
||||
/// </summary>
|
||||
|
@ -669,7 +669,10 @@ namespace OpenTK
|
|||
/// <param name="result">Result of the operation.</param>
|
||||
public static void Divide(ref Vector4d vector, double scale, out Vector4d result)
|
||||
{
|
||||
Multiply(ref vector, 1 / scale, out result);
|
||||
result.X = vector.X / scale;
|
||||
result.Y = vector.Y / scale;
|
||||
result.Z = vector.Z / scale;
|
||||
result.W = vector.W / scale;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -705,6 +708,7 @@ namespace OpenTK
|
|||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>The component-wise minimum</returns>
|
||||
[Obsolete("Use ComponentMin() instead.")]
|
||||
public static Vector4d Min(Vector4d a, Vector4d b)
|
||||
{
|
||||
a.X = a.X < b.X ? a.X : b.X;
|
||||
|
@ -720,6 +724,7 @@ namespace OpenTK
|
|||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">The component-wise minimum</param>
|
||||
[Obsolete("Use ComponentMin() instead.")]
|
||||
public static void Min(ref Vector4d a, ref Vector4d b, out Vector4d result)
|
||||
{
|
||||
result.X = a.X < b.X ? a.X : b.X;
|
||||
|
@ -738,6 +743,7 @@ namespace OpenTK
|
|||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>The component-wise maximum</returns>
|
||||
[Obsolete("Use ComponentMax() instead.")]
|
||||
public static Vector4d Max(Vector4d a, Vector4d b)
|
||||
{
|
||||
a.X = a.X > b.X ? a.X : b.X;
|
||||
|
@ -753,6 +759,7 @@ namespace OpenTK
|
|||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">The component-wise maximum</param>
|
||||
[Obsolete("Use ComponentMax() instead.")]
|
||||
public static void Max(ref Vector4d a, ref Vector4d b, out Vector4d result)
|
||||
{
|
||||
result.X = a.X > b.X ? a.X : b.X;
|
||||
|
@ -763,6 +770,126 @@ namespace OpenTK
|
|||
|
||||
#endregion
|
||||
|
||||
#region ComponentMin
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>The component-wise minimum</returns>
|
||||
public static Vector4d ComponentMin(Vector4d a, Vector4d b)
|
||||
{
|
||||
a.X = a.X < b.X ? a.X : b.X;
|
||||
a.Y = a.Y < b.Y ? a.Y : b.Y;
|
||||
a.Z = a.Z < b.Z ? a.Z : b.Z;
|
||||
a.W = a.W < b.W ? a.W : b.W;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector created from the smallest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">The component-wise minimum</param>
|
||||
public static void ComponentMin(ref Vector4d a, ref Vector4d b, out Vector4d result)
|
||||
{
|
||||
result.X = a.X < b.X ? a.X : b.X;
|
||||
result.Y = a.Y < b.Y ? a.Y : b.Y;
|
||||
result.Z = a.Z < b.Z ? a.Z : b.Z;
|
||||
result.W = a.W < b.W ? a.W : b.W;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ComponentMax
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector created from the largest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>The component-wise maximum</returns>
|
||||
public static Vector4d ComponentMax(Vector4d a, Vector4d b)
|
||||
{
|
||||
a.X = a.X > b.X ? a.X : b.X;
|
||||
a.Y = a.Y > b.Y ? a.Y : b.Y;
|
||||
a.Z = a.Z > b.Z ? a.Z : b.Z;
|
||||
a.W = a.W > b.W ? a.W : b.W;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vector created from the largest of the corresponding components of the given vectors.
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">The component-wise maximum</param>
|
||||
public static void ComponentMax(ref Vector4d a, ref Vector4d b, out Vector4d result)
|
||||
{
|
||||
result.X = a.X > b.X ? a.X : b.X;
|
||||
result.Y = a.Y > b.Y ? a.Y : b.Y;
|
||||
result.Z = a.Z > b.Z ? a.Z : b.Z;
|
||||
result.W = a.W > b.W ? a.W : b.W;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MagnitudeMin
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector4d with the minimum magnitude
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <returns>The minimum Vector4d</returns>
|
||||
public static Vector4d MagnitudeMin(Vector4d left, Vector4d right)
|
||||
{
|
||||
return left.LengthSquared < right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector4d with the minimum magnitude
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <param name="result">The magnitude-wise minimum</param>
|
||||
/// <returns>The minimum Vector4d</returns>
|
||||
public static void MagnitudeMin(ref Vector4d left, ref Vector4d right, out Vector4d result)
|
||||
{
|
||||
result = left.LengthSquared < right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MagnitudeMax
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector4d with the minimum magnitude
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <returns>The minimum Vector4d</returns>
|
||||
public static Vector4d MagnitudeMax(Vector4d left, Vector4d right)
|
||||
{
|
||||
return left.LengthSquared >= right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Vector4d with the maximum magnitude
|
||||
/// </summary>
|
||||
/// <param name="left">Left operand</param>
|
||||
/// <param name="right">Right operand</param>
|
||||
/// <param name="result">The magnitude-wise maximum</param>
|
||||
/// <returns>The maximum Vector4d</returns>
|
||||
public static void MagnitudeMax(ref Vector4d left, ref Vector4d right, out Vector4d result)
|
||||
{
|
||||
result = left.LengthSquared >= right.LengthSquared ? left : right;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Clamp
|
||||
|
||||
/// <summary>
|
||||
|
@ -1493,7 +1620,7 @@ namespace OpenTK
|
|||
vec.W *= scale;
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Component-wise multiplication between the specified instance by a scale vector.
|
||||
/// </summary>
|
||||
|
@ -1517,11 +1644,10 @@ namespace OpenTK
|
|||
/// <returns>The result of the calculation.</returns>
|
||||
public static Vector4d operator /(Vector4d vec, double scale)
|
||||
{
|
||||
double mult = 1 / scale;
|
||||
vec.X *= mult;
|
||||
vec.Y *= mult;
|
||||
vec.Z *= mult;
|
||||
vec.W *= mult;
|
||||
vec.X /= scale;
|
||||
vec.Y /= scale;
|
||||
vec.Z /= scale;
|
||||
vec.W /= scale;
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,12 @@ using System.Reflection;
|
|||
[assembly: AssemblyCopyrightAttribute("Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.")]
|
||||
namespace System {
|
||||
internal static class AssemblyVersionInformation {
|
||||
internal const string Version = "3.0.0";
|
||||
internal const string InformationalVersion = "3.0.0";
|
||||
internal const System.String AssemblyTitle = "OpenTK";
|
||||
internal const System.String AssemblyProduct = "OpenTK";
|
||||
internal const System.String AssemblyDescription = "A set of fast, low-level C# bindings for OpenGL, OpenGL ES and OpenAL.";
|
||||
internal const System.String AssemblyVersion = "3.0.0";
|
||||
internal const System.String AssemblyFileVersion = "3.0.0";
|
||||
internal const System.Boolean CLSCompliant = true;
|
||||
internal const System.String AssemblyCopyright = "Copyright (c) 2006 - 2016 Stefanos Apostolopoulos <stapostol@gmail.com> for the Open Toolkit library.";
|
||||
}
|
||||
}
|
||||
|
|
17
tests/OpenTK.Tests/App.config
Normal file
17
tests/OpenTK.Tests/App.config
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.4.0.0" newVersion="4.4.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
<!--<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
|
||||
</startup>-->
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
|
||||
</startup>
|
||||
</configuration>
|
41
tests/OpenTK.Tests/AssemblyInfo.fs
Normal file
41
tests/OpenTK.Tests/AssemblyInfo.fs
Normal file
|
@ -0,0 +1,41 @@
|
|||
namespace OpenTK.Tests.AssemblyInfo
|
||||
|
||||
open System.Reflection
|
||||
open System.Runtime.CompilerServices
|
||||
open System.Runtime.InteropServices
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[<assembly: AssemblyTitle("OpenTK.Tests")>]
|
||||
[<assembly: AssemblyDescription("")>]
|
||||
[<assembly: AssemblyConfiguration("")>]
|
||||
[<assembly: AssemblyCompany("")>]
|
||||
[<assembly: AssemblyProduct("OpenTK.Tests")>]
|
||||
[<assembly: AssemblyCopyright("Copyright © 2017")>]
|
||||
[<assembly: AssemblyTrademark("")>]
|
||||
[<assembly: AssemblyCulture("")>]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[<assembly: ComVisible(false)>]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[<assembly: Guid("6801c263-adda-4a7b-979d-649bcb5a1df7")>]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [<assembly: AssemblyVersion("1.0.*")>]
|
||||
[<assembly: AssemblyVersion("1.0.0.0")>]
|
||||
[<assembly: AssemblyFileVersion("1.0.0.0")>]
|
||||
|
||||
do
|
||||
()
|
76
tests/OpenTK.Tests/Assertions.fs
Normal file
76
tests/OpenTK.Tests/Assertions.fs
Normal file
|
@ -0,0 +1,76 @@
|
|||
namespace OpenTK.Tests
|
||||
|
||||
open Xunit
|
||||
open FsCheck
|
||||
open FsCheck.Xunit
|
||||
open System
|
||||
open OpenTK
|
||||
|
||||
[<AutoOpen>]
|
||||
module private AssertHelpers =
|
||||
[<Literal>]
|
||||
let private BitAccuracy = 16
|
||||
|
||||
[<Literal>]
|
||||
let private EquivalenceTolerance = 0.00005f
|
||||
|
||||
let approxEq a b = MathHelper.ApproximatelyEquivalent(a, b, EquivalenceTolerance)
|
||||
|
||||
let approxEqDelta a b = MathHelper.ApproximatelyEqual(a,b,BitAccuracy)
|
||||
|
||||
let approxEqSingleEpsilon a b = MathHelper.ApproximatelyEqualEpsilon(a, b, 0.00001f)
|
||||
let approxEqDoubleEpsilon a b = MathHelper.ApproximatelyEqualEpsilon(a, b, 0.00001)
|
||||
|
||||
let approxEqSingleEpsilonWithError (a, b, c : float32) = MathHelper.ApproximatelyEqualEpsilon(a, b, c)
|
||||
let approxEqDoubleEpsilonWithError (a, b, c : float) = MathHelper.ApproximatelyEqualEpsilon(a, b, c)
|
||||
|
||||
let anyZero2 (a : Vector2) = (approxEq a.X 0.0f || approxEq a.Y 0.0f)
|
||||
let anyZero3 (a : Vector3) = (approxEq a.X 0.0f || approxEq a.Y 0.0f || approxEq a.Z 0.0f)
|
||||
let anyZero4 (a : Vector4) = (approxEq a.X 0.0f || approxEq a.Y 0.0f || approxEq a.Z 0.0f || approxEq a.W 0.0f)
|
||||
|
||||
/// We use a full type here instead of a module, as the overloading semantics are more suitable for our desired goal.
|
||||
[<Sealed>]
|
||||
type internal Assert =
|
||||
|
||||
static member ApproximatelyEquivalent(a : Vector2,b : Vector2) =
|
||||
if not <| approxEq a.X b.X && approxEq a.Y b.Y then raise <| new Xunit.Sdk.EqualException(a,b)
|
||||
|
||||
static member ApproximatelyEquivalent(a : Vector3,b : Vector3) =
|
||||
if not <| approxEq a.X b.X && approxEq a.Y b.Y && approxEq a.Z b.Z then raise <| new Xunit.Sdk.EqualException(a,b)
|
||||
|
||||
static member ApproximatelyEquivalent(a : Vector4,b : Vector4) =
|
||||
if not <| approxEq a.X b.X && approxEq a.Y b.Y && approxEq a.Z b.Z && approxEq a.W b.W then
|
||||
raise <| new Xunit.Sdk.EqualException(a,b)
|
||||
|
||||
static member ApproximatelyEquivalent(a : float32,b : float32) =
|
||||
if not <| approxEq a b then raise <| new Xunit.Sdk.EqualException(a,b)
|
||||
|
||||
|
||||
static member ApproximatelyEqualEpsilon(a : float32, b : float32) =
|
||||
if not <| approxEqSingleEpsilon a b then raise <| new Xunit.Sdk.EqualException(a,b)
|
||||
|
||||
static member ApproximatelyEqualEpsilon(a : float32, b : float32, c : float32) =
|
||||
if not <| approxEqSingleEpsilonWithError(a, b, c) then raise <| new Xunit.Sdk.EqualException(a,b)
|
||||
|
||||
|
||||
static member ApproximatelyEqualEpsilon(a : float, b : float) =
|
||||
if not <| approxEqDoubleEpsilon a b then raise <| new Xunit.Sdk.EqualException(a,b)
|
||||
|
||||
static member ApproximatelyEqualEpsilon(a : float, b : float, c : float) =
|
||||
if not <| approxEqDoubleEpsilonWithError(a, b, c) then raise <| new Xunit.Sdk.EqualException(a,b)
|
||||
|
||||
|
||||
static member NotApproximatelyEqualEpsilon(a : float32, b : float32) =
|
||||
if approxEqSingleEpsilon a b then raise <| new Xunit.Sdk.EqualException(a,b)
|
||||
|
||||
static member NotApproximatelyEqualEpsilon(a : float32, b : float32, c : float32) =
|
||||
if approxEqSingleEpsilonWithError(a, b, c) then raise <| new Xunit.Sdk.EqualException(a,b)
|
||||
|
||||
|
||||
static member NotApproximatelyEqualEpsilon(a : float, b : float) =
|
||||
if approxEqDoubleEpsilon a b then raise <| new Xunit.Sdk.EqualException(a,b)
|
||||
|
||||
static member NotApproximatelyEqualEpsilon(a : float, b : float, c : float) =
|
||||
if approxEqDoubleEpsilonWithError(a, b, c) then raise <| new Xunit.Sdk.EqualException(a,b)
|
||||
|
||||
static member ThrowsIndexExn(f:unit -> unit) = Assert.Throws<IndexOutOfRangeException>(f) |> ignore
|
80
tests/OpenTK.Tests/Generators.fs
Normal file
80
tests/OpenTK.Tests/Generators.fs
Normal file
|
@ -0,0 +1,80 @@
|
|||
namespace OpenTK.Tests
|
||||
|
||||
open Xunit
|
||||
open FsCheck
|
||||
open FsCheck.Xunit
|
||||
open System
|
||||
open OpenTK
|
||||
|
||||
[<AutoOpen>]
|
||||
module private Generators =
|
||||
let private isValidFloat f = not (Single.IsNaN f || Single.IsInfinity f || Single.IsInfinity (f * f) || f = Single.MinValue || f = Single.MaxValue )
|
||||
let private isValidDouble d = not (Double.IsNaN d || Double.IsInfinity d || Double.IsInfinity (d * d)|| d = Double.MinValue || d = Double.MaxValue)
|
||||
let singleArb = Arb.Default.Float32() |> Arb.toGen |> Gen.filter isValidFloat
|
||||
let single = singleArb |> Arb.fromGen
|
||||
|
||||
let double =
|
||||
Arb.Default.Float() |> Arb.toGen
|
||||
|> Gen.filter isValidDouble
|
||||
|> Arb.fromGen
|
||||
|
||||
let vec2 =
|
||||
singleArb
|
||||
|> Gen.two
|
||||
|> Gen.map Vector2
|
||||
|> Gen.filter (fun v -> not <| (Single.IsNaN v.Length || Single.IsInfinity v.Length ))
|
||||
|> Arb.fromGen
|
||||
|
||||
let vec3 =
|
||||
singleArb
|
||||
|> Gen.three
|
||||
|> Gen.map Vector3
|
||||
|> Gen.filter (fun v -> not <| (Single.IsNaN v.Length || Single.IsInfinity v.Length ))
|
||||
|> Arb.fromGen
|
||||
|
||||
let vec4 =
|
||||
singleArb
|
||||
|> Gen.four
|
||||
|> Gen.map Vector4
|
||||
|> Gen.filter (fun v -> not <| (Single.IsNaN v.Length || Single.IsInfinity v.Length ))
|
||||
|> Arb.fromGen
|
||||
|
||||
let quat =
|
||||
singleArb
|
||||
|> Gen.three
|
||||
|> Gen.map (fun (x,y,z) -> Quaternion(x,y,z,0.0f) |> Quaternion.Normalize)
|
||||
|> Gen.filter (fun q -> not <| (Single.IsNaN q.Length || Single.IsInfinity q.Length ))
|
||||
|> Arb.fromGen
|
||||
|
||||
let mat2 =
|
||||
singleArb
|
||||
|> Gen.four
|
||||
|> Gen.map Matrix2
|
||||
|> Arb.fromGen
|
||||
|
||||
let mat3 =
|
||||
vec3
|
||||
|> Arb.toGen
|
||||
|> Gen.three
|
||||
|> Gen.map Matrix3
|
||||
|> Arb.fromGen
|
||||
|
||||
let mat4 =
|
||||
vec4
|
||||
|> Arb.toGen
|
||||
|> Gen.four
|
||||
|> Gen.map Matrix4
|
||||
|> Arb.fromGen
|
||||
|
||||
type OpenTKGen =
|
||||
static member Single() = single
|
||||
static member float32() = single
|
||||
static member Double() = double
|
||||
static member float() = double
|
||||
static member Vector2() = vec2
|
||||
static member Vector3() = vec3
|
||||
static member Vector4() = vec4
|
||||
static member Quaternion() = quat
|
||||
static member Matrix2() = mat2
|
||||
static member Matrix3() = mat3
|
||||
static member Matrix4() = mat4
|
352
tests/OpenTK.Tests/MathHelperTests.fs
Normal file
352
tests/OpenTK.Tests/MathHelperTests.fs
Normal file
|
@ -0,0 +1,352 @@
|
|||
namespace OpenTK.Tests
|
||||
|
||||
open Xunit
|
||||
open FsCheck
|
||||
open FsCheck.Xunit
|
||||
open System
|
||||
open OpenTK
|
||||
|
||||
module MathHelper =
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module ``ApproximatelyEqual (delta)`` =
|
||||
/// This test ensures that approximately equal can never get it 'wrong' about the values.
|
||||
[<Property>]
|
||||
let ``ApproximatelyEqual is never incorrect`` (a : float32,b : float32,bits : int32) =
|
||||
let clamped = max 0 (min bits 24)
|
||||
let areApproxEqual = MathHelper.ApproximatelyEqual(a,b,clamped)
|
||||
let areExactlyEqual = a = b
|
||||
let isWrong = areExactlyEqual && not areApproxEqual
|
||||
Assert.False(isWrong)
|
||||
|
||||
[<Property>]
|
||||
let ``ApproximatelyEqual can return true if some values are not exactly equal`` (a : float32,b : float32,bits : int32) =
|
||||
let clamped = max 0 (min bits 24)
|
||||
let areApproxEqual = MathHelper.ApproximatelyEqual(a,b,clamped)
|
||||
let areExactlyEqual = a = b
|
||||
let isWrong = areExactlyEqual && not areApproxEqual
|
||||
let p = new PropertyAttribute()
|
||||
Assert.False(isWrong)
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual correctly approximates equality``() =
|
||||
let a = 0.000000001f
|
||||
let b = 0.0000000010000001f
|
||||
Assert.NotEqual(a,b)
|
||||
[ 1..24 ] |> List.iter (fun i -> Assert.True(MathHelper.ApproximatelyEqual(a,b,i)))
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual reports very different values as non-equal even with high bit count``() =
|
||||
let a = 2.0f
|
||||
let b = 1.0f
|
||||
Assert.NotEqual(a,b)
|
||||
Assert.False(MathHelper.ApproximatelyEqual(a,b,10))
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual works with single zero value``() =
|
||||
let a = 1.0f
|
||||
let b = 0.0f
|
||||
Assert.NotEqual(a,b)
|
||||
Assert.False(MathHelper.ApproximatelyEqual(a,b,0))
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual works with both zero values``() =
|
||||
let a = 0.0f
|
||||
let b = 0.0f
|
||||
Assert.Equal(a,b)
|
||||
Assert.True(MathHelper.ApproximatelyEqual(a,b,0))
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module ``ApproximatelyEqual (single-precision epsilon)`` =
|
||||
//
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (single precision) is correct for large positive values``() =
|
||||
Assert.ApproximatelyEqualEpsilon(1000000.0f, 1000001.0f);
|
||||
Assert.ApproximatelyEqualEpsilon(1000001.0f, 1000000.0f);
|
||||
Assert.NotApproximatelyEqualEpsilon(10000.0f, 10001.0f);
|
||||
Assert.NotApproximatelyEqualEpsilon(10001.0f, 10000.0f);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (single precision) is correct for large negative values``() =
|
||||
Assert.ApproximatelyEqualEpsilon(-1000000.0f, -1000001.0f);
|
||||
Assert.ApproximatelyEqualEpsilon(-1000001.0f, -1000000.0f);
|
||||
Assert.NotApproximatelyEqualEpsilon(-10000.0f, -10001.0f);
|
||||
Assert.NotApproximatelyEqualEpsilon(-10001.0f, -10000.0f);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (single precision) is correct for positive values around 1``() =
|
||||
Assert.ApproximatelyEqualEpsilon(1.0000001f, 1.0000002f);
|
||||
Assert.ApproximatelyEqualEpsilon(1.0000002f, 1.0000001f);
|
||||
Assert.NotApproximatelyEqualEpsilon(1.0002f, 1.0001f);
|
||||
Assert.NotApproximatelyEqualEpsilon(1.0001f, 1.0002f);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (single precision) is correct for negative values around -1``() =
|
||||
Assert.ApproximatelyEqualEpsilon(-1.000001f, -1.000002f);
|
||||
Assert.ApproximatelyEqualEpsilon(-1.000002f, -1.000001f);
|
||||
Assert.NotApproximatelyEqualEpsilon(-1.0001f, -1.0002f);
|
||||
Assert.NotApproximatelyEqualEpsilon(-1.0002f, -1.0001f);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (single precision) is correct for values between 1 and 0``() =
|
||||
Assert.ApproximatelyEqualEpsilon(0.000000001000001f, 0.000000001000002f);
|
||||
Assert.ApproximatelyEqualEpsilon(0.000000001000002f, 0.000000001000001f);
|
||||
Assert.NotApproximatelyEqualEpsilon(0.000000000001002f, 0.000000000001001f);
|
||||
Assert.NotApproximatelyEqualEpsilon(0.000000000001001f, 0.000000000001002f);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (single precision) is correct for values between -1 and 0``() =
|
||||
Assert.ApproximatelyEqualEpsilon(-0.000000001000001f, -0.000000001000002f);
|
||||
Assert.ApproximatelyEqualEpsilon(-0.000000001000002f, -0.000000001000001f);
|
||||
Assert.NotApproximatelyEqualEpsilon(-0.000000000001002f, -0.000000000001001f);
|
||||
Assert.NotApproximatelyEqualEpsilon(-0.000000000001001f, -0.000000000001002f);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (single precision) is correct for comparisons involving 0``() =
|
||||
Assert.ApproximatelyEqualEpsilon(0.0f, 0.0f);
|
||||
Assert.ApproximatelyEqualEpsilon(0.0f, -0.0f);
|
||||
Assert.ApproximatelyEqualEpsilon(-0.0f, -0.0f);
|
||||
Assert.NotApproximatelyEqualEpsilon(0.00000001f, 0.0f);
|
||||
Assert.NotApproximatelyEqualEpsilon(0.0f, 0.00000001f);
|
||||
Assert.NotApproximatelyEqualEpsilon(-0.00000001f, 0.0f);
|
||||
Assert.NotApproximatelyEqualEpsilon(0.0f, -0.00000001f);
|
||||
|
||||
Assert.ApproximatelyEqualEpsilon(0.0f, 1e-40f, 0.01f);
|
||||
Assert.ApproximatelyEqualEpsilon(1e-40f, 0.0f, 0.01f);
|
||||
Assert.NotApproximatelyEqualEpsilon(1e-40f, 0.0f, 0.000001f);
|
||||
Assert.NotApproximatelyEqualEpsilon(0.0f, 1e-40f, 0.000001f);
|
||||
|
||||
Assert.ApproximatelyEqualEpsilon(0.0f, -1e-40f, 0.1f);
|
||||
Assert.ApproximatelyEqualEpsilon(-1e-40f, 0.0f, 0.1f);
|
||||
Assert.NotApproximatelyEqualEpsilon(-1e-40f, 0.0f, 0.00000001f);
|
||||
Assert.NotApproximatelyEqualEpsilon(0.0f, -1e-40f, 0.00000001f);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (single precision) is correct for extreme values with overflow potential``() =
|
||||
Assert.ApproximatelyEqualEpsilon(System.Single.MaxValue, System.Single.MaxValue);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.MaxValue, -System.Single.MaxValue);
|
||||
Assert.NotApproximatelyEqualEpsilon(-System.Single.MaxValue, System.Single.MaxValue);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.MaxValue, System.Single.MaxValue / 2.0f);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.MaxValue, -System.Single.MaxValue / 2.0f);
|
||||
Assert.NotApproximatelyEqualEpsilon(-System.Single.MaxValue, System.Single.MaxValue / 2.0f);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (single precision) is correct for values involving infinities``() =
|
||||
Assert.ApproximatelyEqualEpsilon(System.Single.PositiveInfinity, System.Single.PositiveInfinity);
|
||||
Assert.ApproximatelyEqualEpsilon(System.Single.NegativeInfinity, System.Single.NegativeInfinity);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.NegativeInfinity, System.Single.PositiveInfinity);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.PositiveInfinity, System.Single.MaxValue);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.NegativeInfinity, -System.Single.MaxValue);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (single precision) is correct for values involving NaN``() =
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, System.Single.NaN);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, 0.0f);
|
||||
Assert.NotApproximatelyEqualEpsilon(-0.0f, System.Single.NaN);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, -0.0f);
|
||||
Assert.NotApproximatelyEqualEpsilon(0.0f, System.Single.NaN);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, System.Single.PositiveInfinity);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.PositiveInfinity, System.Single.NaN);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, System.Single.NegativeInfinity);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.NegativeInfinity, System.Single.NaN);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, System.Single.MaxValue);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.MaxValue, System.Single.NaN);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, -System.Single.MaxValue);
|
||||
Assert.NotApproximatelyEqualEpsilon(-System.Single.MaxValue, System.Single.NaN);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, System.Single.Epsilon);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.Epsilon, System.Single.NaN);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.NaN, -System.Single.Epsilon);
|
||||
Assert.NotApproximatelyEqualEpsilon(-System.Single.Epsilon, System.Single.NaN);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (single precision) is correct for values on opposite sides of 0``() =
|
||||
Assert.NotApproximatelyEqualEpsilon(1.000000001f, -1.0f);
|
||||
Assert.NotApproximatelyEqualEpsilon(-1.0f, 1.000000001f);
|
||||
Assert.NotApproximatelyEqualEpsilon(-1.000000001f, 1.0f);
|
||||
Assert.NotApproximatelyEqualEpsilon(1.0f, -1.000000001f);
|
||||
Assert.ApproximatelyEqualEpsilon(10.0f * System.Single.Epsilon, 10.0f * -System.Single.Epsilon);
|
||||
Assert.NotApproximatelyEqualEpsilon(10000.0f * System.Single.Epsilon, 10000.0f * -System.Single.Epsilon);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (single precision) is correct for values very close to 0``() =
|
||||
Assert.ApproximatelyEqualEpsilon(System.Single.Epsilon, System.Single.Epsilon);
|
||||
Assert.ApproximatelyEqualEpsilon(System.Single.Epsilon, -System.Single.Epsilon);
|
||||
Assert.ApproximatelyEqualEpsilon(-System.Single.Epsilon, System.Single.Epsilon);
|
||||
Assert.ApproximatelyEqualEpsilon(System.Single.Epsilon, 0.0f);
|
||||
Assert.ApproximatelyEqualEpsilon(0.0f, System.Single.Epsilon);
|
||||
Assert.ApproximatelyEqualEpsilon(-System.Single.Epsilon, 0.0f);
|
||||
Assert.ApproximatelyEqualEpsilon(0.0f, -System.Single.Epsilon);
|
||||
|
||||
Assert.NotApproximatelyEqualEpsilon(0.000000001f, -System.Single.Epsilon);
|
||||
Assert.NotApproximatelyEqualEpsilon(0.000000001f, System.Single.Epsilon);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Single.Epsilon, 0.000000001f);
|
||||
Assert.NotApproximatelyEqualEpsilon(-System.Single.Epsilon, 0.000000001f);
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module ``ApproximatelyEqual (double-precision epsilon)`` =
|
||||
//
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (double precision) is correct for large positive values``() =
|
||||
Assert.ApproximatelyEqualEpsilon(1000000.0, 1000001.0);
|
||||
Assert.ApproximatelyEqualEpsilon(1000001.0, 1000000.0);
|
||||
Assert.NotApproximatelyEqualEpsilon(10000.0, 10001.0);
|
||||
Assert.NotApproximatelyEqualEpsilon(10001.0, 10000.0);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (double precision) is correct for large negative values``() =
|
||||
Assert.ApproximatelyEqualEpsilon(-1000000.0, -1000001.0);
|
||||
Assert.ApproximatelyEqualEpsilon(-1000001.0, -1000000.0);
|
||||
Assert.NotApproximatelyEqualEpsilon(-10000.0, -10001.0);
|
||||
Assert.NotApproximatelyEqualEpsilon(-10001.0, -10000.0);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (double precision) is correct for positive values around 1``() =
|
||||
Assert.ApproximatelyEqualEpsilon(1.0000001, 1.0000002);
|
||||
Assert.ApproximatelyEqualEpsilon(1.0000002, 1.0000001);
|
||||
Assert.NotApproximatelyEqualEpsilon(1.0002, 1.0001);
|
||||
Assert.NotApproximatelyEqualEpsilon(1.0001, 1.0002);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (double precision) is correct for negative values around -1``() =
|
||||
Assert.ApproximatelyEqualEpsilon(-1.000001, -1.000002);
|
||||
Assert.ApproximatelyEqualEpsilon(-1.000002, -1.000001);
|
||||
Assert.NotApproximatelyEqualEpsilon(-1.0001, -1.0002);
|
||||
Assert.NotApproximatelyEqualEpsilon(-1.0002, -1.0001);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (double precision) is correct for values between 1 and 0``() =
|
||||
Assert.ApproximatelyEqualEpsilon(0.000000001000001, 0.000000001000002);
|
||||
Assert.ApproximatelyEqualEpsilon(0.000000001000002, 0.000000001000001);
|
||||
Assert.NotApproximatelyEqualEpsilon(0.000000000001002, 0.000000000001001);
|
||||
Assert.NotApproximatelyEqualEpsilon(0.000000000001001, 0.000000000001002);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (double precision) is correct for values between -1 and 0``() =
|
||||
Assert.ApproximatelyEqualEpsilon(-0.000000001000001, -0.000000001000002);
|
||||
Assert.ApproximatelyEqualEpsilon(-0.000000001000002, -0.000000001000001);
|
||||
Assert.NotApproximatelyEqualEpsilon(-0.000000000001002, -0.000000000001001);
|
||||
Assert.NotApproximatelyEqualEpsilon(-0.000000000001001, -0.000000000001002);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (double precision) is correct for comparisons involving 0``() =
|
||||
Assert.ApproximatelyEqualEpsilon(0.0, 0.0);
|
||||
Assert.ApproximatelyEqualEpsilon(0.0, -0.0);
|
||||
Assert.ApproximatelyEqualEpsilon(-0.0, -0.0);
|
||||
Assert.NotApproximatelyEqualEpsilon(0.00000001, 0.0);
|
||||
Assert.NotApproximatelyEqualEpsilon(0.0, 0.00000001);
|
||||
Assert.NotApproximatelyEqualEpsilon(-0.00000001, 0.0);
|
||||
Assert.NotApproximatelyEqualEpsilon(0.0, -0.00000001);
|
||||
|
||||
Assert.ApproximatelyEqualEpsilon(0.0, 1e-310, 0.01);
|
||||
Assert.ApproximatelyEqualEpsilon(1e-310, 0.0, 0.01);
|
||||
Assert.NotApproximatelyEqualEpsilon(1e-310, 0.0, 0.000001);
|
||||
Assert.NotApproximatelyEqualEpsilon(0.0, 1e-310, 0.000001);
|
||||
|
||||
Assert.ApproximatelyEqualEpsilon(0.0, -1e-310, 0.1);
|
||||
Assert.ApproximatelyEqualEpsilon(-1e-310, 0.0, 0.1);
|
||||
Assert.NotApproximatelyEqualEpsilon(-1e-310, 0.0, 0.00000001);
|
||||
Assert.NotApproximatelyEqualEpsilon(0.0, -1e-310, 0.00000001);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (double precision) is correct for extreme values with overflow potential``() =
|
||||
Assert.ApproximatelyEqualEpsilon(System.Double.MaxValue, System.Double.MaxValue);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.MaxValue, -System.Double.MaxValue);
|
||||
Assert.NotApproximatelyEqualEpsilon(-System.Double.MaxValue, System.Double.MaxValue);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.MaxValue, System.Double.MaxValue / 2.0);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.MaxValue, -System.Double.MaxValue / 2.0);
|
||||
Assert.NotApproximatelyEqualEpsilon(-System.Double.MaxValue, System.Double.MaxValue / 2.0);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (double precision) is correct for values involving infinities``() =
|
||||
Assert.ApproximatelyEqualEpsilon(System.Double.PositiveInfinity, System.Double.PositiveInfinity);
|
||||
Assert.ApproximatelyEqualEpsilon(System.Double.NegativeInfinity, System.Double.NegativeInfinity);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.NegativeInfinity, System.Double.PositiveInfinity);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.PositiveInfinity, System.Double.MaxValue);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.NegativeInfinity, -System.Double.MaxValue);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (double precision) is correct for values involving NaN``() =
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, System.Double.NaN);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, 0.0);
|
||||
Assert.NotApproximatelyEqualEpsilon(-0.0, System.Double.NaN);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, -0.0);
|
||||
Assert.NotApproximatelyEqualEpsilon(0.0, System.Double.NaN);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, System.Double.PositiveInfinity);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.PositiveInfinity, System.Double.NaN);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, System.Double.NegativeInfinity);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.NegativeInfinity, System.Double.NaN);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, System.Double.MaxValue);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.MaxValue, System.Double.NaN);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, -System.Double.MaxValue);
|
||||
Assert.NotApproximatelyEqualEpsilon(-System.Double.MaxValue, System.Double.NaN);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, System.Double.Epsilon);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.Epsilon, System.Double.NaN);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.NaN, -System.Double.Epsilon);
|
||||
Assert.NotApproximatelyEqualEpsilon(-System.Double.Epsilon, System.Double.NaN);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (double precision) is correct for values on opposite sides of 0``() =
|
||||
Assert.NotApproximatelyEqualEpsilon(1.000000001, -1.0);
|
||||
Assert.NotApproximatelyEqualEpsilon(-1.0, 1.000000001);
|
||||
Assert.NotApproximatelyEqualEpsilon(-1.000000001, 1.0);
|
||||
Assert.NotApproximatelyEqualEpsilon(1.0, -1.000000001);
|
||||
Assert.ApproximatelyEqualEpsilon(10.0 * System.Double.Epsilon, 10.0 * -System.Double.Epsilon);
|
||||
Assert.NotApproximatelyEqualEpsilon(100000000000.0 * System.Double.Epsilon, 100000000000.0 * -System.Double.Epsilon);
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEqual (double precision) is correct for values very close to 0``() =
|
||||
Assert.ApproximatelyEqualEpsilon(System.Double.Epsilon, System.Double.Epsilon);
|
||||
Assert.ApproximatelyEqualEpsilon(System.Double.Epsilon, -System.Double.Epsilon);
|
||||
Assert.ApproximatelyEqualEpsilon(-System.Double.Epsilon, System.Double.Epsilon);
|
||||
Assert.ApproximatelyEqualEpsilon(System.Double.Epsilon, 0.0);
|
||||
Assert.ApproximatelyEqualEpsilon(0.0, System.Double.Epsilon);
|
||||
Assert.ApproximatelyEqualEpsilon(-System.Double.Epsilon, 0.0);
|
||||
Assert.ApproximatelyEqualEpsilon(0.0, -System.Double.Epsilon);
|
||||
|
||||
Assert.NotApproximatelyEqualEpsilon(0.000000001, -System.Double.Epsilon);
|
||||
Assert.NotApproximatelyEqualEpsilon(0.000000001, System.Double.Epsilon);
|
||||
Assert.NotApproximatelyEqualEpsilon(System.Double.Epsilon, 0.000000001);
|
||||
Assert.NotApproximatelyEqualEpsilon(-System.Double.Epsilon, 0.000000001);
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module ``ApproximatelyEquivalent (tolerance diff)`` =
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEquivalent correctly approximates equivalence where the difference falls below the tolerance``() =
|
||||
let a = 0.0001f
|
||||
let b = 0.00019f
|
||||
Assert.NotEqual(a,b)
|
||||
Assert.True(MathHelper.ApproximatelyEquivalent(a, b, 0.0001f))
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEquivalent correctly approximates equivalence where the difference is the tolerance``() =
|
||||
let a = 0.0001f
|
||||
let b = 0.0002f
|
||||
Assert.NotEqual(a,b)
|
||||
Assert.True(MathHelper.ApproximatelyEquivalent(a, b, 0.0001f))
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEquivalent correctly approximates inequivalence where the difference exceeds the tolerance``() =
|
||||
let a = 0.0001f
|
||||
let b = 0.00021f
|
||||
Assert.NotEqual(a,b)
|
||||
Assert.False(MathHelper.ApproximatelyEquivalent(a, b, 0.0001f))
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEquivalent reports very different values as non-equal even with a high tolerance``() =
|
||||
let a = 3.0f
|
||||
let b = 1.0f
|
||||
Assert.NotEqual(a,b)
|
||||
Assert.False(MathHelper.ApproximatelyEquivalent(a, b, 1.0f))
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEquivalent works with single zero value``() =
|
||||
let a = 1.0f
|
||||
let b = 0.0f
|
||||
Assert.NotEqual(a,b)
|
||||
Assert.False(MathHelper.ApproximatelyEquivalent(a, b, 0.0001f))
|
||||
|
||||
[<Fact>]
|
||||
let ``ApproximatelyEquivalent works with both zero values``() =
|
||||
let a = 0.0f
|
||||
let b = 0.0f
|
||||
Assert.Equal(a,b)
|
||||
Assert.True(MathHelper.ApproximatelyEquivalent(a, b, 0.0001f))
|
|
@ -1,289 +0,0 @@
|
|||
using System;
|
||||
using NUnit.Framework;
|
||||
using OpenTK;
|
||||
|
||||
namespace OpenTK.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class Matrix4Test
|
||||
{
|
||||
[Test]
|
||||
public void Matrix4_SixteenValueConstructor()
|
||||
{
|
||||
Matrix4 A = new Matrix4( 0, 1, 2, 3,
|
||||
4, 5, 6, 7,
|
||||
8, 9, 10, 11,
|
||||
12, 13, 14, 15);
|
||||
|
||||
Assert.AreEqual(0, A.M11);
|
||||
Assert.AreEqual(1, A.M12);
|
||||
Assert.AreEqual(2, A.M13);
|
||||
Assert.AreEqual(3, A.M14);
|
||||
|
||||
Assert.AreEqual(4, A.M21);
|
||||
Assert.AreEqual(5, A.M22);
|
||||
Assert.AreEqual(6, A.M23);
|
||||
Assert.AreEqual(7, A.M24);
|
||||
|
||||
Assert.AreEqual(8, A.M31);
|
||||
Assert.AreEqual(9, A.M32);
|
||||
Assert.AreEqual(10, A.M33);
|
||||
Assert.AreEqual(11, A.M34);
|
||||
|
||||
Assert.AreEqual(12, A.M41);
|
||||
Assert.AreEqual(13, A.M42);
|
||||
Assert.AreEqual(14, A.M43);
|
||||
Assert.AreEqual(15, A.M44);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Matrix4_Matrix3Constructor()
|
||||
{
|
||||
Matrix3 B = new Matrix3( 1, 2, 3,
|
||||
4, 5, 6,
|
||||
7, 8, 9);
|
||||
|
||||
Matrix4 A = new Matrix4(B);
|
||||
|
||||
Assert.AreEqual(B.M11, A.M11);
|
||||
Assert.AreEqual(B.M12, A.M12);
|
||||
Assert.AreEqual(B.M13, A.M13);
|
||||
|
||||
Assert.AreEqual(B.M21, A.M21);
|
||||
Assert.AreEqual(B.M22, A.M22);
|
||||
Assert.AreEqual(B.M23, A.M23);
|
||||
|
||||
Assert.AreEqual(B.M31, A.M31);
|
||||
Assert.AreEqual(B.M32, A.M32);
|
||||
Assert.AreEqual(B.M33, A.M33);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Matrix4_FourVector4Constructor()
|
||||
{
|
||||
Vector4 V = new Vector4(1, 2, 3, 4);
|
||||
Vector4 U = new Vector4(5, 6, 7, 8);
|
||||
Vector4 S = new Vector4(9, 10, 11, 12);
|
||||
Vector4 T = new Vector4(13, 14, 15, 16);
|
||||
|
||||
Matrix4 A = new Matrix4(V, U, S, T);
|
||||
|
||||
Assert.AreEqual(V.X, A.M11);
|
||||
Assert.AreEqual(V.Y, A.M12);
|
||||
Assert.AreEqual(V.Z, A.M13);
|
||||
Assert.AreEqual(V.W, A.M14);
|
||||
|
||||
Assert.AreEqual(U.X, A.M21);
|
||||
Assert.AreEqual(U.Y, A.M22);
|
||||
Assert.AreEqual(U.Z, A.M23);
|
||||
Assert.AreEqual(U.W, A.M24);
|
||||
|
||||
Assert.AreEqual(S.X, A.M31);
|
||||
Assert.AreEqual(S.Y, A.M32);
|
||||
Assert.AreEqual(S.Z, A.M33);
|
||||
Assert.AreEqual(S.W, A.M34);
|
||||
|
||||
Assert.AreEqual(T.X, A.M41);
|
||||
Assert.AreEqual(T.Y, A.M42);
|
||||
Assert.AreEqual(T.Z, A.M43);
|
||||
Assert.AreEqual(T.W, A.M44);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Matrix4_Equal_operator()
|
||||
{
|
||||
Matrix4 A = new Matrix4( 0, 1, 2, 3,
|
||||
4, 5, 6, 7,
|
||||
8, 9, 10, 11,
|
||||
12, 13, 14, 15);
|
||||
|
||||
Matrix4 B = new Matrix4( 0, 1, 2, 3,
|
||||
4, 5, 6, 7,
|
||||
8, 9, 10, 11,
|
||||
12, 13, 14, 15);
|
||||
|
||||
Assert.IsTrue(A == B);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Matrix4_Matrix4TimesMatrix4_operator()
|
||||
{
|
||||
Matrix4 A = new Matrix4( 0, 1, 2, 3,
|
||||
4, 5, 6, 7,
|
||||
8, 9, 10, 11,
|
||||
12, 13, 14, 15);
|
||||
|
||||
Matrix4 B = new Matrix4( 0, 1, 2, 3,
|
||||
4, 5, 6, 7,
|
||||
8, 9, 10, 11,
|
||||
12, 13, 14, 15);
|
||||
|
||||
Matrix4 expected = new Matrix4( 56, 62, 68, 74,
|
||||
152, 174, 196, 218,
|
||||
248, 286, 324, 362,
|
||||
344, 398, 452, 506);
|
||||
|
||||
Matrix4 result = A * B;
|
||||
Assert.IsTrue(expected == result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Matrix4_Matrix4PlusMatrix4_operator()
|
||||
{
|
||||
Matrix4 A = new Matrix4( 0, 1, 2, 3,
|
||||
4, 5, 6, 7,
|
||||
8, 9, 10, 11,
|
||||
12, 13, 14, 15);
|
||||
|
||||
Matrix4 B = new Matrix4( 0, 1, 2, 3,
|
||||
4, 5, 6, 7,
|
||||
8, 9, 10, 11,
|
||||
12, 13, 14, 15);
|
||||
|
||||
Matrix4 expected = new Matrix4( 0, 2, 4, 6,
|
||||
8, 10, 12, 14,
|
||||
16, 18, 20, 22,
|
||||
24, 26, 28, 30);
|
||||
|
||||
Matrix4 result = A + B;
|
||||
Assert.IsTrue(expected == result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Matrix4_Matrix4MinusMatrix4_operator()
|
||||
{
|
||||
Matrix4 A = new Matrix4( 0, 1, 2, 3,
|
||||
4, 5, 6, 7,
|
||||
8, 9, 10, 11,
|
||||
12, 13, 14, 15);
|
||||
|
||||
Matrix4 B = new Matrix4( 0, 1, 2, 3,
|
||||
4, 5, 6, 7,
|
||||
8, 9, 10, 11,
|
||||
12, 13, 14, 15);
|
||||
|
||||
Matrix4 expected = new Matrix4( 0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0);
|
||||
|
||||
Matrix4 result = A - B;
|
||||
Assert.IsTrue(expected == result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Matrix4_Index_Operator()
|
||||
{
|
||||
Matrix4 A = new Matrix4();
|
||||
A[0, 0] = 0;
|
||||
A[0, 1] = 1;
|
||||
A[0, 2] = 2;
|
||||
A[0, 3] = 3;
|
||||
A[1, 0] = 4;
|
||||
A[1, 1] = 5;
|
||||
A[1, 2] = 6;
|
||||
A[1, 3] = 7;
|
||||
A[2, 0] = 8;
|
||||
A[2, 1] = 9;
|
||||
A[2, 2] = 10;
|
||||
A[2, 3] = 11;
|
||||
A[3, 0] = 12;
|
||||
A[3, 1] = 13;
|
||||
A[3, 2] = 14;
|
||||
A[3, 3] = 15;
|
||||
Assert.AreEqual(0, A[0, 0]);
|
||||
Assert.AreEqual(1, A[0, 1]);
|
||||
Assert.AreEqual(2, A[0, 2]);
|
||||
Assert.AreEqual(3, A[0, 3]);
|
||||
Assert.AreEqual(4, A[1, 0]);
|
||||
Assert.AreEqual(5, A[1, 1]);
|
||||
Assert.AreEqual(6, A[1, 2]);
|
||||
Assert.AreEqual(7, A[1, 3]);
|
||||
Assert.AreEqual(8, A[2, 0]);
|
||||
Assert.AreEqual(9, A[2, 1]);
|
||||
Assert.AreEqual(10, A[2, 2]);
|
||||
Assert.AreEqual(11, A[2, 3]);
|
||||
Assert.AreEqual(12, A[3, 0]);
|
||||
Assert.AreEqual(13, A[3, 1]);
|
||||
Assert.AreEqual(14, A[3, 2]);
|
||||
Assert.AreEqual(15, A[3, 3]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Matrix4_Index_NegativeIndexException()
|
||||
{
|
||||
Matrix4 A = new Matrix4();
|
||||
bool negativeIndexException = false;
|
||||
try
|
||||
{
|
||||
A[-1, 2] = 0;
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
negativeIndexException = true;
|
||||
}
|
||||
Assert.IsTrue(negativeIndexException);
|
||||
|
||||
negativeIndexException = false;
|
||||
try
|
||||
{
|
||||
A[1, -2] = 0;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
negativeIndexException = true;
|
||||
}
|
||||
Assert.IsTrue(negativeIndexException);
|
||||
|
||||
negativeIndexException = false;
|
||||
try
|
||||
{
|
||||
A[-1, -2] = 0;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
negativeIndexException = true;
|
||||
}
|
||||
Assert.IsTrue(negativeIndexException);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Matrix4_Index_LargeIndexException()
|
||||
{
|
||||
Matrix4 A = new Matrix4();
|
||||
bool largeIndexException = false;
|
||||
try
|
||||
{
|
||||
A[5, 2] = 0;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
largeIndexException = true;
|
||||
}
|
||||
Assert.IsTrue(largeIndexException);
|
||||
|
||||
largeIndexException = false;
|
||||
try
|
||||
{
|
||||
A[1, 6] = 0;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
largeIndexException = true;
|
||||
}
|
||||
Assert.IsTrue(largeIndexException);
|
||||
|
||||
largeIndexException = false;
|
||||
try
|
||||
{
|
||||
A[7, 12] = 0;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
largeIndexException = true;
|
||||
}
|
||||
Assert.IsTrue(largeIndexException);
|
||||
}
|
||||
}
|
||||
}
|
396
tests/OpenTK.Tests/Matrix4Tests.fs
Normal file
396
tests/OpenTK.Tests/Matrix4Tests.fs
Normal file
|
@ -0,0 +1,396 @@
|
|||
namespace OpenTK.Tests
|
||||
|
||||
open Xunit
|
||||
open FsCheck
|
||||
open FsCheck.Xunit
|
||||
open System
|
||||
open OpenTK
|
||||
|
||||
module Matrix4 =
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Constructors =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Sixteen value constructor sets all components to the correct values`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =
|
||||
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
|
||||
|
||||
Assert.Equal(a, A.M11)
|
||||
Assert.Equal(b, A.M12)
|
||||
Assert.Equal(c, A.M13)
|
||||
Assert.Equal(d, A.M14)
|
||||
|
||||
Assert.Equal(e, A.M21)
|
||||
Assert.Equal(f, A.M22)
|
||||
Assert.Equal(g, A.M23)
|
||||
Assert.Equal(h, A.M24)
|
||||
|
||||
Assert.Equal(i, A.M31)
|
||||
Assert.Equal(j, A.M32)
|
||||
Assert.Equal(k, A.M33)
|
||||
Assert.Equal(l, A.M34)
|
||||
|
||||
Assert.Equal(m, A.M41)
|
||||
Assert.Equal(n, A.M42)
|
||||
Assert.Equal(o, A.M43)
|
||||
Assert.Equal(p, A.M44)
|
||||
|
||||
[<Property>]
|
||||
let ``Matrix3 partial constructor sets all components to the correct values`` (a, b, c, d, e, f, g, h, i) =
|
||||
let B = Matrix3(a, b, c, d, e, f, g, h, i)
|
||||
let A = Matrix4(B)
|
||||
|
||||
Assert.Equal(a, A.M11)
|
||||
Assert.Equal(b, A.M12)
|
||||
Assert.Equal(c, A.M13)
|
||||
Assert.Equal(0.0f, A.M14)
|
||||
|
||||
Assert.Equal(d, A.M21)
|
||||
Assert.Equal(e, A.M22)
|
||||
Assert.Equal(f, A.M23)
|
||||
Assert.Equal(0.0f, A.M24)
|
||||
|
||||
Assert.Equal(g, A.M31)
|
||||
Assert.Equal(h, A.M32)
|
||||
Assert.Equal(i, A.M33)
|
||||
Assert.Equal(0.0f, A.M34)
|
||||
|
||||
Assert.Equal(0.0f, A.M41)
|
||||
Assert.Equal(0.0f, A.M42)
|
||||
Assert.Equal(0.0f, A.M43)
|
||||
Assert.Equal(1.0f, A.M44)
|
||||
|
||||
[<Property>]
|
||||
let ``Four-vector4 constructor sets all components to the correct values`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =
|
||||
let v1 = Vector4(a, b, c, d)
|
||||
let v2 = Vector4(e, f, g, h)
|
||||
let v3 = Vector4(i, j, k, l)
|
||||
let v4 = Vector4(m, n, o, p)
|
||||
|
||||
let A = Matrix4(v1, v2, v3, v4)
|
||||
|
||||
Assert.Equal(a, A.M11)
|
||||
Assert.Equal(b, A.M12)
|
||||
Assert.Equal(c, A.M13)
|
||||
Assert.Equal(d, A.M14)
|
||||
|
||||
Assert.Equal(e, A.M21)
|
||||
Assert.Equal(f, A.M22)
|
||||
Assert.Equal(g, A.M23)
|
||||
Assert.Equal(h, A.M24)
|
||||
|
||||
Assert.Equal(i, A.M31)
|
||||
Assert.Equal(j, A.M32)
|
||||
Assert.Equal(k, A.M33)
|
||||
Assert.Equal(l, A.M34)
|
||||
|
||||
Assert.Equal(m, A.M41)
|
||||
Assert.Equal(n, A.M42)
|
||||
Assert.Equal(o, A.M43)
|
||||
Assert.Equal(p, A.M44)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Equality =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Two matrices with identical values are equal`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =
|
||||
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
|
||||
let B = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
|
||||
let equality = A = B
|
||||
|
||||
Assert.True(equality)
|
||||
|
||||
[<Property>]
|
||||
let ``A matrix is not equal to an object which is not a matrix`` (a : Matrix4, b : Vector3) =
|
||||
Assert.False(a.Equals(b))
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Multiplication =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Matrix multiplication is done by row/column multiplication and summation`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =
|
||||
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
|
||||
let B = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
|
||||
|
||||
let R11 = a*a + b*e + c*i + d*m
|
||||
let R12 = a*b + b*f + c*j + d*n
|
||||
let R13 = a*c + b*g + c*k + d*o
|
||||
let R14 = a*d + b*h + c*l + d*p
|
||||
|
||||
let R21 = e*a + f*e + g*i + h*m
|
||||
let R22 = e*b + f*f + g*j + h*n
|
||||
let R23 = e*c + f*g + g*k + h*o
|
||||
let R24 = e*d + f*h + g*l + h*p
|
||||
|
||||
let R31 = i*a + j*e + k*i + l*m
|
||||
let R32 = i*b + j*f + k*j + l*n
|
||||
let R33 = i*c + j*g + k*k + l*o
|
||||
let R34 = i*d + j*h + k*l + l*p
|
||||
|
||||
let R41 = m*a + n*e + o*i + p*m
|
||||
let R42 = m*b + n*f + o*j + p*n
|
||||
let R43 = m*c + n*g + o*k + p*o
|
||||
let R44 = m*d + n*h + o*l + p*p
|
||||
|
||||
let AB = A*B
|
||||
|
||||
Assert.Equal(R11, AB.M11)
|
||||
Assert.Equal(R12, AB.M12)
|
||||
Assert.Equal(R13, AB.M13)
|
||||
Assert.Equal(R14, AB.M14)
|
||||
|
||||
Assert.Equal(R21, AB.M21)
|
||||
Assert.Equal(R22, AB.M22)
|
||||
Assert.Equal(R23, AB.M23)
|
||||
Assert.Equal(R24, AB.M24)
|
||||
|
||||
Assert.Equal(R31, AB.M31)
|
||||
Assert.Equal(R32, AB.M32)
|
||||
Assert.Equal(R33, AB.M33)
|
||||
Assert.Equal(R34, AB.M34)
|
||||
|
||||
Assert.Equal(R41, AB.M41)
|
||||
Assert.Equal(R42, AB.M42)
|
||||
Assert.Equal(R43, AB.M43)
|
||||
Assert.Equal(R44, AB.M44)
|
||||
|
||||
[<Property>]
|
||||
let ``Matrix multiplication by scalar is the same as row multiplication by scalar`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, scalar : float32) =
|
||||
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
|
||||
|
||||
let R1 = Vector4(a, b, c, d) * scalar
|
||||
let R2 = Vector4(e, f, g, h) * scalar
|
||||
let R3 = Vector4(i, j, k, l) * scalar
|
||||
let R4 = Vector4(m, n, o, p) * scalar
|
||||
|
||||
let AScaled = A * scalar
|
||||
|
||||
Assert.Equal(R1, AScaled.Row0)
|
||||
Assert.Equal(R2, AScaled.Row1)
|
||||
Assert.Equal(R3, AScaled.Row2)
|
||||
Assert.Equal(R4, AScaled.Row3)
|
||||
|
||||
[<Property>]
|
||||
let ``Static method matrix multiplication by scalar is the same as row multiplication by scalar`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, scalar : float32) =
|
||||
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
|
||||
|
||||
let R1 = Vector4(a, b, c, d) * scalar
|
||||
let R2 = Vector4(e, f, g, h) * scalar
|
||||
let R3 = Vector4(i, j, k, l) * scalar
|
||||
let R4 = Vector4(m, n, o, p) * scalar
|
||||
|
||||
let AScaled = Matrix4.Mult(A, scalar)
|
||||
|
||||
Assert.Equal(R1, AScaled.Row0)
|
||||
Assert.Equal(R2, AScaled.Row1)
|
||||
Assert.Equal(R3, AScaled.Row2)
|
||||
Assert.Equal(R4, AScaled.Row3)
|
||||
|
||||
[<Property>]
|
||||
let ``Static method matrix multiplication by reference by scalar is the same as row multiplication by scalar`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, scalar : float32) =
|
||||
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
|
||||
|
||||
let R1 = Vector4(a, b, c, d) * scalar
|
||||
let R2 = Vector4(e, f, g, h) * scalar
|
||||
let R3 = Vector4(i, j, k, l) * scalar
|
||||
let R4 = Vector4(m, n, o, p) * scalar
|
||||
|
||||
let AScaled = Matrix4.Mult(ref A, scalar)
|
||||
|
||||
Assert.Equal(R1, AScaled.Row0)
|
||||
Assert.Equal(R2, AScaled.Row1)
|
||||
Assert.Equal(R3, AScaled.Row2)
|
||||
Assert.Equal(R4, AScaled.Row3)
|
||||
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Addition =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Matrix addition adds corresponding components`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =
|
||||
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
|
||||
let B = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
|
||||
|
||||
let sum = A + B
|
||||
|
||||
Assert.Equal(a + a, sum.M11)
|
||||
Assert.Equal(b + b, sum.M12)
|
||||
Assert.Equal(c + c, sum.M13)
|
||||
Assert.Equal(d + d, sum.M14)
|
||||
|
||||
Assert.Equal(e + e, sum.M21)
|
||||
Assert.Equal(f + f, sum.M22)
|
||||
Assert.Equal(g + g, sum.M23)
|
||||
Assert.Equal(h + h, sum.M24)
|
||||
|
||||
Assert.Equal(i + i, sum.M31)
|
||||
Assert.Equal(j + j, sum.M32)
|
||||
Assert.Equal(k + k, sum.M33)
|
||||
Assert.Equal(l + l, sum.M34)
|
||||
|
||||
Assert.Equal(m + m, sum.M41)
|
||||
Assert.Equal(n + n, sum.M42)
|
||||
Assert.Equal(o + o, sum.M43)
|
||||
Assert.Equal(p + p, sum.M44)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Subtraction =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Matrix subtraction subtracts corresponding components`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =
|
||||
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
|
||||
let B = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
|
||||
|
||||
let sub = A - B
|
||||
|
||||
Assert.Equal(a - a, sub.M11)
|
||||
Assert.Equal(b - b, sub.M12)
|
||||
Assert.Equal(c - c, sub.M13)
|
||||
Assert.Equal(d - d, sub.M14)
|
||||
|
||||
Assert.Equal(e - e, sub.M21)
|
||||
Assert.Equal(f - f, sub.M22)
|
||||
Assert.Equal(g - g, sub.M23)
|
||||
Assert.Equal(h - h, sub.M24)
|
||||
|
||||
Assert.Equal(i - i, sub.M31)
|
||||
Assert.Equal(j - j, sub.M32)
|
||||
Assert.Equal(k - k, sub.M33)
|
||||
Assert.Equal(l - l, sub.M34)
|
||||
|
||||
Assert.Equal(m - m, sub.M41)
|
||||
Assert.Equal(n - n, sub.M42)
|
||||
Assert.Equal(o - o, sub.M43)
|
||||
Assert.Equal(p - p, sub.M44)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Indexing =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Matrix set indexing sets correct components`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =
|
||||
let mutable A = Matrix4()
|
||||
|
||||
A.[0, 0] <- a
|
||||
A.[0, 1] <- b
|
||||
A.[0, 2] <- c
|
||||
A.[0, 3] <- d
|
||||
|
||||
A.[1, 0] <- e
|
||||
A.[1, 1] <- f
|
||||
A.[1, 2] <- g
|
||||
A.[1, 3] <- h
|
||||
|
||||
A.[2, 0] <- i
|
||||
A.[2, 1] <- j
|
||||
A.[2, 2] <- k
|
||||
A.[2, 3] <- l
|
||||
|
||||
A.[3, 0] <- m
|
||||
A.[3, 1] <- n
|
||||
A.[3, 2] <- o
|
||||
A.[3, 3] <- p
|
||||
|
||||
Assert.Equal(a, A.M11)
|
||||
Assert.Equal(b, A.M12)
|
||||
Assert.Equal(c, A.M13)
|
||||
Assert.Equal(d, A.M14)
|
||||
|
||||
Assert.Equal(e, A.M21)
|
||||
Assert.Equal(f, A.M22)
|
||||
Assert.Equal(g, A.M23)
|
||||
Assert.Equal(h, A.M24)
|
||||
|
||||
Assert.Equal(i, A.M31)
|
||||
Assert.Equal(j, A.M32)
|
||||
Assert.Equal(k, A.M33)
|
||||
Assert.Equal(l, A.M34)
|
||||
|
||||
Assert.Equal(m, A.M41)
|
||||
Assert.Equal(n, A.M42)
|
||||
Assert.Equal(o, A.M43)
|
||||
Assert.Equal(p, A.M44)
|
||||
|
||||
[<Property>]
|
||||
let ``Matrix get indexing accesses the correct components`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =
|
||||
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
|
||||
|
||||
Assert.Equal(a, A.[0, 0])
|
||||
Assert.Equal(b, A.[0, 1])
|
||||
Assert.Equal(c, A.[0, 2])
|
||||
Assert.Equal(d, A.[0, 3])
|
||||
|
||||
Assert.Equal(e, A.[1, 0])
|
||||
Assert.Equal(f, A.[1, 1])
|
||||
Assert.Equal(g, A.[1, 2])
|
||||
Assert.Equal(h, A.[1, 3])
|
||||
|
||||
Assert.Equal(i, A.[2, 0])
|
||||
Assert.Equal(j, A.[2, 1])
|
||||
Assert.Equal(k, A.[2, 2])
|
||||
Assert.Equal(l, A.[2, 3])
|
||||
|
||||
Assert.Equal(m, A.[3, 0])
|
||||
Assert.Equal(n, A.[3, 1])
|
||||
Assert.Equal(o, A.[3, 2])
|
||||
Assert.Equal(p, A.[3, 3])
|
||||
|
||||
|
||||
[<Property>]
|
||||
let ``Indexed set operator throws exception for negative indices`` (b : Matrix4, x : float32) =
|
||||
let mutable a = b
|
||||
|
||||
|
||||
|
||||
(fun() -> a.[-1, 2] <- x) |> Assert.ThrowsIndexExn
|
||||
(fun() -> a.[1, -2] <- x) |> Assert.ThrowsIndexExn
|
||||
(fun() -> a.[-1, -2] <- x) |> Assert.ThrowsIndexExn
|
||||
|
||||
[<Property>]
|
||||
let ``Indexed get operator throws exception for negative indices`` (a : Matrix4) =
|
||||
(fun() -> a.[-1, 2] |> ignore) |> Assert.ThrowsIndexExn
|
||||
(fun() -> a.[1, -2] |> ignore) |> Assert.ThrowsIndexExn
|
||||
(fun() -> a.[-1, -2] |> ignore) |> Assert.ThrowsIndexExn
|
||||
|
||||
[<Property>]
|
||||
let ``Indexed set operator throws exception for large indices`` (a : Matrix4, x : float32) =
|
||||
let mutable b = a
|
||||
(fun() -> b.[5, 2] <- x) |> Assert.ThrowsIndexExn
|
||||
(fun() -> b.[1, 6] <- x) |> Assert.ThrowsIndexExn
|
||||
(fun() -> b.[7, 12] <- x) |> Assert.ThrowsIndexExn
|
||||
|
||||
[<Property>]
|
||||
let ``Indexed get operator throws exception for large indices`` (a : Matrix4) =
|
||||
(fun() -> a.[5, 2] |> ignore) |> Assert.ThrowsIndexExn
|
||||
(fun() -> a.[1, 6] |> ignore) |> Assert.ThrowsIndexExn
|
||||
(fun() -> a.[7, 12] |> ignore) |> Assert.ThrowsIndexExn
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module ``Row and column properties`` =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Matrix row properties return the correct components`` (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) =
|
||||
let A = Matrix4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)
|
||||
|
||||
let R0 = A.Row0
|
||||
let R1 = A.Row1
|
||||
let R2 = A.Row2
|
||||
let R3 = A.Row3
|
||||
|
||||
Assert.Equal(a, R0.X)
|
||||
Assert.Equal(b, R0.Y)
|
||||
Assert.Equal(c, R0.Z)
|
||||
Assert.Equal(d, R0.W)
|
||||
|
||||
Assert.Equal(e, R1.X)
|
||||
Assert.Equal(f, R1.Y)
|
||||
Assert.Equal(g, R1.Z)
|
||||
Assert.Equal(h, R1.W)
|
||||
|
||||
Assert.Equal(i, R2.X)
|
||||
Assert.Equal(j, R2.Y)
|
||||
Assert.Equal(k, R2.Z)
|
||||
Assert.Equal(l, R2.W)
|
||||
|
||||
Assert.Equal(m, R3.X)
|
||||
Assert.Equal(n, R3.Y)
|
||||
Assert.Equal(o, R3.Z)
|
||||
Assert.Equal(p, R3.W)
|
|
@ -1,87 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{930A780C-A67C-422F-9EED-DB38DAA47AB0}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>OpenTK.Tests</RootNamespace>
|
||||
<AssemblyName>OpenTK.Tests</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="nunit.core, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="nunit.core.interfaces, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.interfaces.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="nunit.util, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\NUnitTestAdapter.2.0.0\lib\nunit.util.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="NUnit.VisualStudio.TestAdapter, Version=2.0.0.0, Culture=neutral, PublicKeyToken=4cb40d35494691ac, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\NUnitTestAdapter.2.0.0\lib\NUnit.VisualStudio.TestAdapter.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Matrix4Test.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Vector3Tests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\OpenTK\OpenTK.csproj">
|
||||
<Project>{a37a7e14-0000-0000-0000-000000000000}</Project>
|
||||
<Name>OpenTK</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
1589
tests/OpenTK.Tests/OpenTK.Tests.fsproj
Normal file
1589
tests/OpenTK.Tests/OpenTK.Tests.fsproj
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,36 +0,0 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("OpenTK.Tests")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("OpenTK.Tests")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("8a03c40d-007c-4a15-ab0c-2111969ea6df")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
603
tests/OpenTK.Tests/Vector2Tests.fs
Normal file
603
tests/OpenTK.Tests/Vector2Tests.fs
Normal file
|
@ -0,0 +1,603 @@
|
|||
namespace OpenTK.Tests
|
||||
|
||||
open Xunit
|
||||
open FsCheck
|
||||
open FsCheck.Xunit
|
||||
open System
|
||||
open System.Runtime.InteropServices
|
||||
open OpenTK
|
||||
|
||||
module Vector2 =
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Constructors =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Single value constructor sets all components to the same value`` (f : float32) =
|
||||
let v = Vector2(f)
|
||||
Assert.Equal(f,v.X)
|
||||
Assert.Equal(f,v.Y)
|
||||
|
||||
[<Property>]
|
||||
let ``Two value constructor sets all components correctly`` (x,y) =
|
||||
let v = Vector2(x,y)
|
||||
Assert.Equal(x,v.X)
|
||||
Assert.Equal(y,v.Y)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Clamping =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Clamping one vector between two other vectors clamps all components between corresponding components`` (a : Vector2, b : Vector2, w : Vector2) =
|
||||
let res = Vector2.Clamp(w, a, b)
|
||||
|
||||
let expX = if w.X < a.X then a.X else if w.X > b.X then b.X else w.X
|
||||
let expY = if w.Y < a.Y then a.Y else if w.Y > b.Y then b.Y else w.Y
|
||||
|
||||
Assert.Equal(expX, res.X)
|
||||
Assert.Equal(expY, res.Y)
|
||||
|
||||
[<Property>]
|
||||
let ``Clamping one vector between two other vectors by reference clamps all components`` (a : Vector2, b : Vector2, w : Vector2) =
|
||||
let res = Vector2.Clamp(ref w, ref a, ref b)
|
||||
|
||||
let expX = if w.X < a.X then a.X else if w.X > b.X then b.X else w.X
|
||||
let expY = if w.Y < a.Y then a.Y else if w.Y > b.Y then b.Y else w.Y
|
||||
|
||||
Assert.Equal(expX, res.X)
|
||||
Assert.Equal(expY, res.Y)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Length =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Length is always >= 0`` (a : Vector2) =
|
||||
//
|
||||
Assert.True(a.Length >= 0.0f)
|
||||
|
||||
[<Property>]
|
||||
let ``Length follows the pythagorean theorem`` (a, b) =
|
||||
let v = Vector2(a, b)
|
||||
let l = System.Math.Sqrt((float)(a * a + b * b))
|
||||
|
||||
Assert.Equal((float32)l, v.Length)
|
||||
|
||||
[<Property>]
|
||||
let ``Fast length method works`` (a, b) =
|
||||
let v = Vector2(a, b)
|
||||
let l = 1.0f / MathHelper.InverseSqrtFast(a * a + b * b)
|
||||
|
||||
Assert.Equal(l, v.LengthFast)
|
||||
|
||||
[<Property>]
|
||||
let ``Length squared method works`` (a, b) =
|
||||
let v = Vector2(a, b)
|
||||
let lsq = a * a + b * b
|
||||
|
||||
Assert.Equal(lsq, v.LengthSquared)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module ``Unit vectors and perpendicularity`` =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Perpendicular vector to the right is correct`` (a, b) =
|
||||
let v = Vector2(a, b)
|
||||
let perp = Vector2(b, -a)
|
||||
|
||||
Assert.Equal(perp, v.PerpendicularRight)
|
||||
|
||||
[<Property>]
|
||||
let ``Perpendicular vector to the left is correct`` (a, b) =
|
||||
let v = Vector2(a, b)
|
||||
let perp = Vector2(-b, a)
|
||||
|
||||
Assert.Equal(perp, v.PerpendicularLeft)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Indexing =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Index operator accesses the correct components`` (x, y) =
|
||||
let v = Vector2(x, y)
|
||||
|
||||
Assert.Equal(x, v.[0])
|
||||
Assert.Equal(y, v.[1])
|
||||
|
||||
[<Property>]
|
||||
let ``Indexed set operator throws exception for negative indices`` (x, y) =
|
||||
let mutable v = Vector2(x, y)
|
||||
|
||||
(fun() -> v.[-1] <- x) |> Assert.ThrowsIndexExn
|
||||
|
||||
[<Property>]
|
||||
let ``Indexed get operator throws exception for negative indices`` (x, y) =
|
||||
let mutable v = Vector2(x, y)
|
||||
|
||||
(fun() -> v.[-1] |> ignore) |> Assert.ThrowsIndexExn
|
||||
|
||||
[<Property>]
|
||||
let ``Indexed set operator throws exception for large indices`` (x, y) =
|
||||
let mutable v = Vector2(x, y)
|
||||
|
||||
(fun() -> v.[2] <- x) |> Assert.ThrowsIndexExn
|
||||
|
||||
[<Property>]
|
||||
let ``Indexed get operator throws exception for large indices`` (x, y) =
|
||||
let mutable v = Vector2(x, y)
|
||||
|
||||
(fun() -> v.[2] |> ignore) |> Assert.ThrowsIndexExn
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module ``Simple Properties`` =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector equality is by component`` (a : Vector2,b : Vector2) =
|
||||
//
|
||||
Assert.Equal((a.X = b.X && a.Y = b.Y),(a = b))
|
||||
|
||||
[<Property>]
|
||||
let ``Vector length is always >= 0`` (a : Vector2) =
|
||||
//
|
||||
Assert.True(a.Length >= 0.0f)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Addition =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector addition is the same as component addition`` (a : Vector2,b : Vector2) =
|
||||
let c = a + b
|
||||
Assert.ApproximatelyEquivalent(a.X + b.X,c.X)
|
||||
Assert.ApproximatelyEquivalent(a.Y + b.Y,c.Y)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector addition is commutative`` (a : Vector2,b : Vector2) =
|
||||
let c = a + b
|
||||
let c2 = b + a
|
||||
Assert.ApproximatelyEquivalent(c,c2)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector addition is associative`` (a : Vector2,b : Vector2,c : Vector2) =
|
||||
let r1 = (a + b) + c
|
||||
let r2 = a + (b + c)
|
||||
Assert.ApproximatelyEquivalent(r1,r2)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector2 addition method is the same as component addition`` (a : Vector2, b : Vector2) =
|
||||
|
||||
let v1 = Vector2(a.X + b.X, a.Y + b.Y)
|
||||
let sum = Vector2.Add(a, b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector2 addition method by reference is the same as component addition`` (a : Vector2, b : Vector2) =
|
||||
|
||||
let v1 = Vector2(a.X + b.X, a.Y + b.Y)
|
||||
let sum = Vector2.Add(ref a, ref b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Multiplication =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector2 multiplication is the same as component multiplication`` (a : Vector2, b : Vector2) =
|
||||
let c = a * b
|
||||
Assert.Equal(a.X * b.X,c.X)
|
||||
Assert.Equal(a.Y * b.Y,c.Y)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector2 multiplication is commutative`` (a : Vector2, b : Vector2) =
|
||||
let r1 = a * b
|
||||
let r2 = b * a
|
||||
Assert.Equal(r1,r2)
|
||||
|
||||
[<Property>]
|
||||
let ``Left-handed Vector2-scalar multiplication is the same as component-scalar multiplication`` (a : Vector2, f : float32) =
|
||||
let r = a * f
|
||||
|
||||
Assert.Equal(a.X * f,r.X)
|
||||
Assert.Equal(a.Y * f,r.Y)
|
||||
|
||||
[<Property>]
|
||||
let ``Right-handed Vector2-scalar multiplication is the same as component-scalar multiplication`` (a : Vector2, f : float32) =
|
||||
let r = f * a
|
||||
Assert.Equal(a.X * f,r.X)
|
||||
Assert.Equal(a.Y * f,r.Y)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector2 multiplication method is the same as component multiplication`` (a : Vector2, b : Vector2) =
|
||||
|
||||
let v1 = Vector2(a.X * b.X, a.Y * b.Y)
|
||||
let sum = Vector2.Multiply(a, b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector2 multiplication method by reference is the same as component multiplication`` (a : Vector2, b : Vector2) =
|
||||
|
||||
let v1 = Vector2(a.X * b.X, a.Y * b.Y)
|
||||
let sum = Vector2.Multiply(ref a, ref b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static method Vector2-scalar multiplication is the same as component-scalar multiplication`` (a : Vector2, f : float32) =
|
||||
let r = Vector2.Multiply(a, f)
|
||||
|
||||
Assert.Equal(a.X * f,r.X)
|
||||
Assert.Equal(a.Y * f,r.Y)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Subtraction =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector2 subtraction is the same as component subtraction`` (a : Vector2, b : Vector2) =
|
||||
let c = a - b
|
||||
Assert.Equal(a.X - b.X,c.X)
|
||||
Assert.Equal(a.Y - b.Y,c.Y)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector2 subtraction method is the same as component addition`` (a : Vector2, b : Vector2) =
|
||||
|
||||
let v1 = Vector2(a.X - b.X, a.Y - b.Y)
|
||||
let sum = Vector2.Subtract(a, b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector2 subtraction method by reference is the same as component addition`` (a : Vector2, b : Vector2) =
|
||||
|
||||
let v1 = Vector2(a.X - b.X, a.Y - b.Y)
|
||||
let sum = Vector2.Subtract(ref a, ref b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Division =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector2-float division is the same as component-float division`` (a : Vector2, f : float32) =
|
||||
if not (approxEq f 0.0f) then
|
||||
let r = a / f
|
||||
|
||||
Assert.ApproximatelyEquivalent(a.X / f,r.X)
|
||||
Assert.ApproximatelyEquivalent(a.Y / f,r.Y)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector2-Vector2 division method is the same as component division`` (a : Vector2, b : Vector2) =
|
||||
if not (anyZero2 a || anyZero2 b) then
|
||||
let v1 = Vector2(a.X / b.X, a.Y / b.Y)
|
||||
let sum = Vector2.Divide(a, b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector2-Vector2 divison method by reference `` (a : Vector2, b : Vector2) =
|
||||
if not (anyZero2 a || anyZero2 b) then
|
||||
let v1 = Vector2(a.X / b.X, a.Y / b.Y)
|
||||
let sum = Vector2.Divide(ref a, ref b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector2-scalar division method is the same as component division`` (a : Vector2, b : float32) =
|
||||
if not (approxEq b 0.0f) then
|
||||
let v1 = Vector2(a.X / b, a.Y / b)
|
||||
let sum = Vector2.Divide(a, b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector2-scalar divison method by reference is the same as component division`` (a : Vector2, b : float32) =
|
||||
if not (approxEq b 0.0f) then
|
||||
let v1 = Vector2(a.X / b, a.Y / b)
|
||||
let sum = Vector2.Divide(ref a, b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Negation =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector negation operator negates all components`` (x, y) =
|
||||
let v = Vector2(x, y)
|
||||
let vNeg = -v
|
||||
Assert.Equal(-x, vNeg.X)
|
||||
Assert.Equal(-y, vNeg.Y)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Equality =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector equality operator is by component`` (x, y) =
|
||||
let v1 = Vector2(x, y)
|
||||
let v2 = Vector2(x, y)
|
||||
let equality = v1 = v2
|
||||
|
||||
Assert.True(equality)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector inequality operator is by component`` (x, y) =
|
||||
let v1 = Vector2(x, y)
|
||||
let v2 = Vector2(x + 1.0f , y + 1.0f)
|
||||
let inequality = v1 <> v2
|
||||
|
||||
Assert.True(inequality)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector equality method is by component`` (x, y) =
|
||||
let v1 = Vector2(x, y)
|
||||
let v2 = Vector2(x, y)
|
||||
let notVector = Matrix2()
|
||||
|
||||
let equality = v1.Equals(v2)
|
||||
let inequalityByOtherType = v1.Equals(notVector)
|
||||
|
||||
Assert.True(equality)
|
||||
Assert.False(inequalityByOtherType)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Swizzling =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector swizzling returns the correct composites`` (x, y) =
|
||||
let v1 = Vector2(x, y)
|
||||
let v2 = Vector2(y, x)
|
||||
|
||||
let v1yx = v1.Yx;
|
||||
Assert.Equal(v2, v1yx);
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Interpolation =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Linear interpolation is by component`` (a : Vector2, b : Vector2, q) =
|
||||
|
||||
let blend = q
|
||||
|
||||
let rX = blend * (b.X - a.X) + a.X
|
||||
let rY = blend * (b.Y - a.Y) + a.Y
|
||||
let vExp = Vector2(rX, rY)
|
||||
|
||||
Assert.Equal(vExp, Vector2.Lerp(a, b, q))
|
||||
|
||||
let vRes = Vector2.Lerp(ref a, ref b, q)
|
||||
Assert.Equal(vExp, vRes)
|
||||
|
||||
[<Property>]
|
||||
let ``Barycentric interpolation follows the barycentric formula`` (a : Vector2, b : Vector2, c : Vector2, u, v) =
|
||||
|
||||
let r = a + u * (b - a) + v * (c - a)
|
||||
|
||||
Assert.Equal(r, Vector2.BaryCentric(a, b, c, u, v))
|
||||
|
||||
let vRes = Vector2.BaryCentric(ref a, ref b, ref c, u, v)
|
||||
Assert.Equal(r, vRes)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module ``Vector products`` =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Dot product follows the dot product formula`` (a : Vector2, b : Vector2) =
|
||||
let dot = a.X * b.X + a.Y * b.Y
|
||||
|
||||
Assert.Equal(dot, Vector2.Dot(a, b));
|
||||
|
||||
let vRes = Vector2.Dot(ref a, ref b)
|
||||
Assert.Equal(dot, vRes)
|
||||
|
||||
[<Property>]
|
||||
let ``Perpendicular dot product follows the perpendicular dot product formula`` (a : Vector2, b : Vector2) =
|
||||
let perpDot = a.X * b.Y - a.Y * b.X
|
||||
|
||||
Assert.Equal(perpDot, Vector2.PerpDot(a, b));
|
||||
|
||||
let vRes = Vector2.PerpDot(ref a, ref b)
|
||||
Assert.Equal(perpDot, vRes)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Normalization =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Normalization creates a new unit length vector with the correct components`` (a, b) =
|
||||
let v = Vector2(a, b)
|
||||
let l = v.Length
|
||||
|
||||
// Dividing by zero is not supported
|
||||
if not (approxEq l 0.0f) then
|
||||
let norm = v.Normalized()
|
||||
|
||||
Assert.ApproximatelyEquivalent(v.X / l, norm.X)
|
||||
Assert.ApproximatelyEquivalent(v.Y / l, norm.Y)
|
||||
|
||||
[<Property>]
|
||||
let ``Normalization of instance transforms the instance into a unit length vector with the correct components`` (a, b) =
|
||||
let v = Vector2(a, b)
|
||||
let l = v.Length
|
||||
|
||||
if not (approxEq l 0.0f) then
|
||||
let norm = Vector2(a, b)
|
||||
norm.Normalize()
|
||||
|
||||
Assert.ApproximatelyEquivalent(v.X / l, norm.X)
|
||||
Assert.ApproximatelyEquivalent(v.Y / l, norm.Y)
|
||||
|
||||
[<Property>]
|
||||
let ``Fast approximate normalization of instance transforms the instance into a unit length vector with the correct components`` (a, b) =
|
||||
let v = Vector2(a, b)
|
||||
let norm = Vector2(a, b)
|
||||
norm.NormalizeFast()
|
||||
|
||||
let scale = MathHelper.InverseSqrtFast(a * a + b * b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v.X * scale, norm.X)
|
||||
Assert.ApproximatelyEquivalent(v.Y * scale, norm.Y)
|
||||
|
||||
[<Property>]
|
||||
let ``Normalization by reference is the same as division by magnitude`` (a : Vector2) =
|
||||
// Zero-length vectors can't be normalized
|
||||
if not (approxEq a.Length 0.0f) then
|
||||
let norm = a / a.Length
|
||||
let vRes = Vector2.Normalize(ref a)
|
||||
|
||||
Assert.ApproximatelyEquivalent(norm, vRes)
|
||||
|
||||
[<Property>]
|
||||
let ``Normalization is the same as division by magnitude`` (a : Vector2) =
|
||||
// Zero-length vectors can't be normalized
|
||||
if not (approxEq a.Length 0.0f) then
|
||||
let norm = a / a.Length
|
||||
|
||||
Assert.ApproximatelyEquivalent(norm, Vector2.Normalize(a));
|
||||
|
||||
[<Property>]
|
||||
let ``Fast approximate normalization by reference is the same as multiplication by the fast inverse square`` (a : Vector2) =
|
||||
let scale = MathHelper.InverseSqrtFast(a.X * a.X + a.Y * a.Y)
|
||||
|
||||
let norm = a * scale
|
||||
let vRes = Vector2.NormalizeFast(ref a)
|
||||
|
||||
Assert.ApproximatelyEquivalent(norm, vRes)
|
||||
|
||||
[<Property>]
|
||||
let ``Fast approximate normalization is the same as multiplication by the fast inverse square`` (a : Vector2) =
|
||||
let scale = MathHelper.InverseSqrtFast(a.X * a.X + a.Y * a.Y)
|
||||
|
||||
let norm = a * scale
|
||||
|
||||
Assert.ApproximatelyEquivalent(norm, Vector2.NormalizeFast(a));
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module ``Magnitude min and max`` =
|
||||
//
|
||||
[<Property>]
|
||||
let ``MagnitudeMin selects the vector with equal or lesser magnitude given two vectors`` (v1 : Vector2, v2: Vector2) =
|
||||
// Results do not matter for equal vectors
|
||||
if not (v1 = v2) then
|
||||
let l1 = v1.LengthSquared
|
||||
let l2 = v2.LengthSquared
|
||||
|
||||
let vMin = Vector2.MagnitudeMin(v1, v2)
|
||||
|
||||
if vMin = v1 then
|
||||
let v1ShorterThanv2 = l1 < l2
|
||||
Assert.True(v1ShorterThanv2)
|
||||
else
|
||||
let v2ShorterThanOrEqualTov1 = l2 <= l1
|
||||
Assert.True(v2ShorterThanOrEqualTov1)
|
||||
|
||||
[<Property>]
|
||||
let ``MagnitudeMax selects the vector with equal or greater magnitude given two vectors`` (v1 : Vector2, v2: Vector2) =
|
||||
// Results do not matter for equal vectors
|
||||
if not (v1 = v2) then
|
||||
let l1 = v1.LengthSquared
|
||||
let l2 = v2.LengthSquared
|
||||
|
||||
let vMin = Vector2.MagnitudeMax(v1, v2)
|
||||
|
||||
if vMin = v1 then
|
||||
let v1LongerThanOrEqualTov2 = l1 >= l2
|
||||
Assert.True(v1LongerThanOrEqualTov2)
|
||||
else
|
||||
let v2LongerThanv1 = l2 > l1
|
||||
Assert.True(v2LongerThanv1)
|
||||
|
||||
[<Property>]
|
||||
let ``MagnitudeMin by reference selects the vector with equal or lesser magnitude given two vectors`` (v1 : Vector2, v2: Vector2) =
|
||||
// Results do not matter for equal vectors
|
||||
if not (v1 = v2) then
|
||||
let l1 = v1.LengthSquared
|
||||
let l2 = v2.LengthSquared
|
||||
|
||||
let vMin = Vector2.MagnitudeMin(ref v1, ref v2)
|
||||
|
||||
if vMin = v1 then
|
||||
let v1ShorterThanv2 = l1 < l2
|
||||
Assert.True(v1ShorterThanv2)
|
||||
else
|
||||
let v2ShorterThanOrEqualTov1 = l2 <= l1
|
||||
Assert.True(v2ShorterThanOrEqualTov1)
|
||||
|
||||
[<Property>]
|
||||
let ``MagnitudeMax by reference selects the vector with equal greater magnitude given two vectors`` (v1 : Vector2, v2: Vector2) =
|
||||
// Results do not matter for equal vectors
|
||||
if not (v1 = v2) then
|
||||
let l1 = v1.LengthSquared
|
||||
let l2 = v2.LengthSquared
|
||||
|
||||
let vMin = Vector2.MagnitudeMax(ref v1, ref v2)
|
||||
|
||||
if vMin = v1 then
|
||||
let v1LongerThanOrEqualTov2 = l1 >= l2
|
||||
Assert.True(v1LongerThanOrEqualTov2)
|
||||
else
|
||||
let v2LongerThanv1 = l2 > l1
|
||||
Assert.True(v2LongerThanv1)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module ``Component min and max`` =
|
||||
//
|
||||
[<Property>]
|
||||
let ``ComponentMin creates a new vector from the smallest components of given vectors`` (v1 : Vector2, v2: Vector2) =
|
||||
let vMin = Vector2.ComponentMin(v1, v2)
|
||||
let isComponentSmallest smallComp comp1 comp2 = smallComp <= comp1 && smallComp <= comp2
|
||||
|
||||
Assert.True(isComponentSmallest vMin.X v1.X v2.X)
|
||||
Assert.True(isComponentSmallest vMin.Y v1.Y v2.Y)
|
||||
|
||||
[<Property>]
|
||||
let ``ComponentMax creates a new vector from the greatest components of given vectors`` (v1 : Vector2, v2: Vector2) =
|
||||
let vMax = Vector2.ComponentMax(v1, v2)
|
||||
let isComponentLargest largeComp comp1 comp2 = largeComp >= comp1 && largeComp >= comp2
|
||||
|
||||
Assert.True(isComponentLargest vMax.X v1.X v2.X)
|
||||
Assert.True(isComponentLargest vMax.Y v1.Y v2.Y)
|
||||
|
||||
[<Property>]
|
||||
let ``ComponentMin by reference creates a new vector from the smallest components of given vectors`` (v1 : Vector2, v2: Vector2) =
|
||||
let vMin = Vector2.ComponentMin(ref v1, ref v2)
|
||||
let isComponentSmallest smallComp comp1 comp2 = smallComp <= comp1 && smallComp <= comp2
|
||||
|
||||
Assert.True(isComponentSmallest vMin.X v1.X v2.X)
|
||||
Assert.True(isComponentSmallest vMin.Y v1.Y v2.Y)
|
||||
|
||||
[<Property>]
|
||||
let ``ComponentMax by reference creates a new vector from the greatest components of given vectors`` (v1 : Vector2, v2: Vector2) =
|
||||
let vMax = Vector2.ComponentMax(ref v1, ref v2)
|
||||
let isComponentLargest largeComp comp1 comp2 = largeComp >= comp1 && largeComp >= comp2
|
||||
|
||||
Assert.True(isComponentLargest vMax.X v1.X v2.X)
|
||||
Assert.True(isComponentLargest vMax.Y v1.Y v2.Y)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Transformation =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Transformation by quaternion is the same as multiplication by quaternion and its conjugate`` (v : Vector2, q : Quaternion) =
|
||||
let vectorQuat = Quaternion(v.X, v.Y, 0.0f, 0.0f)
|
||||
let inverse = Quaternion.Invert(q)
|
||||
|
||||
let transformedQuat = q * vectorQuat * inverse
|
||||
let transformedVector = Vector2(transformedQuat.X, transformedQuat.Y)
|
||||
|
||||
Assert.ApproximatelyEquivalent(transformedVector, Vector2.Transform(v, q))
|
||||
|
||||
[<Property>]
|
||||
let ``Transformation by quaternion by reference is the same as multiplication by quaternion and its conjugate`` (v : Vector2, q : Quaternion) =
|
||||
let vectorQuat = Quaternion(v.X, v.Y, 0.0f, 0.0f)
|
||||
let inverse = Quaternion.Invert(q)
|
||||
|
||||
let transformedQuat = q * vectorQuat * inverse
|
||||
let transformedVector = Vector2(transformedQuat.X, transformedQuat.Y)
|
||||
|
||||
Assert.ApproximatelyEquivalent(transformedVector, Vector2.Transform(ref v, ref q))
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Serialization =
|
||||
//
|
||||
[<Property>]
|
||||
let ``The absolute size of a Vector2 is always the size of its components`` (v : Vector2) =
|
||||
let expectedSize = sizeof<float32> * 2
|
||||
|
||||
Assert.Equal(expectedSize, Vector2.SizeInBytes)
|
||||
Assert.Equal(expectedSize, Marshal.SizeOf(Vector2()))
|
|
@ -1,439 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using OpenTK;
|
||||
|
||||
namespace OpenTK.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class Vector3Tests
|
||||
{
|
||||
[Test]
|
||||
public void Vector3_SingleValueConstructor()
|
||||
{
|
||||
Vector3 V = new Vector3(1);
|
||||
Assert.AreEqual(1, V.X);
|
||||
Assert.AreEqual(1, V.Y);
|
||||
Assert.AreEqual(1, V.Z);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_ThreeValueConstructor()
|
||||
{
|
||||
Vector3 V = new Vector3(1,2,3);
|
||||
Assert.AreEqual(1, V.X);
|
||||
Assert.AreEqual(2, V.Y);
|
||||
Assert.AreEqual(3, V.Z);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Vector2Constructor()
|
||||
{
|
||||
Vector2 T = new Vector2(1, 2);
|
||||
Vector3 V = new Vector3(T);
|
||||
Assert.AreEqual(T.X, V.X);
|
||||
Assert.AreEqual(T.Y, V.Y);
|
||||
Assert.AreEqual(0, V.Z);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Vector3Constructor()
|
||||
{
|
||||
Vector3 U = new Vector3(1, 2, 3);
|
||||
Vector3 V = new Vector3(U);
|
||||
Assert.IsTrue(U == V);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Vector4Constructor()
|
||||
{
|
||||
Vector4 T = new Vector4(1, 2, 3, 0);
|
||||
Vector3 V = new Vector3(T);
|
||||
Assert.AreEqual(T.X, V.X);
|
||||
Assert.AreEqual(T.Y, V.Y);
|
||||
Assert.AreEqual(T.Z, V.Z);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Index_operator()
|
||||
{
|
||||
Vector3 V = new Vector3();
|
||||
V[0] = 1; V[1] = 2; V[2] = 3;
|
||||
Assert.AreEqual(1, V[0]);
|
||||
Assert.AreEqual(2, V[1]);
|
||||
Assert.AreEqual(3, V[2]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Index_NegativeExceptin()
|
||||
{
|
||||
//the syntax for an expected exception changes from
|
||||
//NUnit 2.6.4 / Microsoft Unit Test to NUnit 3+
|
||||
//but a try-catch block is always guaranteed to work
|
||||
Vector3 V = new Vector3();
|
||||
bool negativeIndexExceptionFound = false;
|
||||
try
|
||||
{
|
||||
V[-1] = 5;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
negativeIndexExceptionFound = true;
|
||||
}
|
||||
Assert.IsTrue(negativeIndexExceptionFound);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Index_LargeIndexExceptin()
|
||||
{
|
||||
//the syntax for an expected exception changes from
|
||||
//NUnit 2.6.4 / Microsoft Unit Test to NUnit 3+
|
||||
//but a try-catch block is always guaranteed to work
|
||||
Vector3 V = new Vector3();
|
||||
bool largeIndexExceptionFound = false;
|
||||
try
|
||||
{
|
||||
V[3] = 6;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
largeIndexExceptionFound = true;
|
||||
}
|
||||
Assert.IsTrue(largeIndexExceptionFound);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Length()
|
||||
{
|
||||
float X = 1, Y = 2, Z = 2;
|
||||
Vector3 U = new Vector3(X, Y, Z);
|
||||
Assert.AreEqual((float)System.Math.Sqrt(X * X + Y * Y + Z * Z), U.Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_LengthFast()
|
||||
{
|
||||
float X = 1, Y = 2, Z = 2;
|
||||
Vector3 U = new Vector3(X, Y, Z);
|
||||
Assert.AreEqual(1.0f / MathHelper.InverseSqrtFast(X * X + Y * Y + Z * Z), U.LengthFast);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Normalized()
|
||||
{
|
||||
float X = 2, Y = 4, Z = 16;
|
||||
Vector3 U = new Vector3(X, Y, Z);
|
||||
float length = U.Length;
|
||||
Vector3 V = U.Normalized();
|
||||
Assert.AreEqual(U.X / length, V.X);
|
||||
Assert.AreEqual(U.Y / length, V.Y);
|
||||
Assert.AreEqual(U.Z / length, V.Z);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_NormalizeFast_Instance()
|
||||
{
|
||||
float X = 2, Y = 4, Z = 16;
|
||||
Vector3 U = new Vector3(X, Y, Z);
|
||||
Vector3 V = U;
|
||||
V.NormalizeFast();
|
||||
float scale = MathHelper.InverseSqrtFast(X * X + Y * Y + Z * Z);
|
||||
Assert.AreEqual(U.X * scale, V.X);
|
||||
Assert.AreEqual(U.Y * scale, V.Y);
|
||||
Assert.AreEqual(U.Z * scale, V.Z);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Add()
|
||||
{
|
||||
Vector3 T = new Vector3(7, 8, 9);
|
||||
Vector3 U = new Vector3(23, 89, -34);
|
||||
Vector3 V = Vector3.Add(T, U);
|
||||
Assert.AreEqual(T.X + U.X, V.X);
|
||||
Assert.AreEqual(T.Y + U.Y, V.Y);
|
||||
Assert.AreEqual(T.Z + U.Z, V.Z);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Subtract()
|
||||
{
|
||||
Vector3 T = new Vector3(7, 8, 9);
|
||||
Vector3 U = new Vector3(23, 89, -34);
|
||||
Vector3 V = Vector3.Subtract(T, U);
|
||||
Assert.AreEqual(T.X - U.X, V.X);
|
||||
Assert.AreEqual(T.Y - U.Y, V.Y);
|
||||
Assert.AreEqual(T.Z - U.Z, V.Z);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Multiply_Scalar()
|
||||
{
|
||||
float scalar = 5.5f;
|
||||
Vector3 U = new Vector3(23, 89, -34);
|
||||
Vector3 V = Vector3.Multiply(U, scalar);
|
||||
Assert.AreEqual(U.X * scalar, V.X);
|
||||
Assert.AreEqual(U.Y * scalar, V.Y);
|
||||
Assert.AreEqual(U.Z * scalar, V.Z);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Multiply_Componentwise()
|
||||
{
|
||||
Vector3 T = new Vector3(7, 8, 0.5f);
|
||||
Vector3 U = new Vector3(23, 89, -34);
|
||||
Vector3 V = Vector3.Multiply(T, U);
|
||||
Assert.AreEqual(T.X * U.X, V.X);
|
||||
Assert.AreEqual(T.Y * U.Y, V.Y);
|
||||
Assert.AreEqual(T.Z * U.Z, V.Z);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Divide_Scalar()
|
||||
{
|
||||
float scalar = 5.5f;
|
||||
Vector3 U = new Vector3(23, 89, -34);
|
||||
Vector3 V = Vector3.Divide(U, scalar);
|
||||
//we have to account for a small amount of round off error
|
||||
//in this division test
|
||||
Assert.IsTrue(Math.Abs((U.X / scalar) - V.X) < 1e-5);
|
||||
Assert.IsTrue(Math.Abs((U.Y / scalar) - V.Y) < 1e-5);
|
||||
Assert.IsTrue(Math.Abs((U.Z / scalar) - V.Z) < 1e-5);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_ComponentMin()
|
||||
{
|
||||
Vector3 T = new Vector3(1, 55, -100);
|
||||
Vector3 U = new Vector3(24, 3, 1);
|
||||
Vector3 V = Vector3.ComponentMin(T, U);
|
||||
Assert.AreEqual(1, V.X);
|
||||
Assert.AreEqual(3, V.Y);
|
||||
Assert.AreEqual(-100, V.Z);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_ComponentMinOut()
|
||||
{
|
||||
Vector3 T = new Vector3(1, 55, -100);
|
||||
Vector3 U = new Vector3(24, 3, 1);
|
||||
Vector3 V;
|
||||
Vector3.ComponentMin(ref T, ref U, out V);
|
||||
Assert.AreEqual(1, V.X);
|
||||
Assert.AreEqual(3, V.Y);
|
||||
Assert.AreEqual(-100, V.Z);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_ComponentMax()
|
||||
{
|
||||
Vector3 T = new Vector3(1, 55, -100);
|
||||
Vector3 U = new Vector3(24, 3, 1);
|
||||
Vector3 V = Vector3.ComponentMax(T, U);
|
||||
Assert.AreEqual(24, V.X);
|
||||
Assert.AreEqual(55, V.Y);
|
||||
Assert.AreEqual(1, V.Z);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_ComponentMaxOut()
|
||||
{
|
||||
Vector3 T = new Vector3(1, 55, -100);
|
||||
Vector3 U = new Vector3(24, 3, 1);
|
||||
Vector3 V;
|
||||
Vector3.ComponentMax(ref T, ref U, out V);
|
||||
Assert.AreEqual(24, V.X);
|
||||
Assert.AreEqual(55, V.Y);
|
||||
Assert.AreEqual(1, V.Z);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Min()
|
||||
{
|
||||
Vector3 T = new Vector3(1, 2, 3);
|
||||
Vector3 U = new Vector3(24, 300, 88);
|
||||
Vector3 result = Vector3.Min(T, U);
|
||||
Assert.IsTrue(result == T);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Max()
|
||||
{
|
||||
Vector3 T = new Vector3(1, 2, 3);
|
||||
Vector3 U = new Vector3(24, 300, 88);
|
||||
Vector3 result = Vector3.Max(T, U);
|
||||
Assert.IsTrue(result == U);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Clamp()
|
||||
{
|
||||
Vector3 V = new Vector3(-6, 302, -22);
|
||||
Vector3 min = new Vector3(-5, -10, -20);
|
||||
Vector3 max = new Vector3(24, 300, 55);
|
||||
Vector3 result = Vector3.Clamp(V, min, max);
|
||||
Assert.AreEqual(result.X, -5);
|
||||
Assert.AreEqual(result.Y, 300);
|
||||
Assert.AreEqual(result.Z, -20);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_ClampOut()
|
||||
{
|
||||
Vector3 V = new Vector3(-6, 302, -22);
|
||||
Vector3 min = new Vector3(-5, -10, -20);
|
||||
Vector3 max = new Vector3(24, 300, 55);
|
||||
Vector3 result;
|
||||
Vector3.Clamp(ref V, ref min, ref max, out result);
|
||||
Assert.AreEqual(result.X, -5);
|
||||
Assert.AreEqual(result.Y, 300);
|
||||
Assert.AreEqual(result.Z, -20);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Normalize()
|
||||
{
|
||||
float X = 64, Y = 144, Z = 16;
|
||||
Vector3 U = new Vector3(X, Y, Z);
|
||||
Vector3 V = Vector3.Normalize(U);
|
||||
float length = U.Length;
|
||||
Assert.IsTrue(Math.Abs((U.X / length) - V.X) < 1e-5);
|
||||
Assert.IsTrue(Math.Abs((U.Y / length) - V.Y) < 1e-5);
|
||||
Assert.IsTrue(Math.Abs((U.Z / length) - V.Z) < 1e-5);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_NormalizeOut()
|
||||
{
|
||||
float X = 64, Y = 144, Z = 16;
|
||||
Vector3 U = new Vector3(X, Y, Z);
|
||||
Vector3 V;
|
||||
Vector3.Normalize(ref U, out V);
|
||||
float length = U.Length;
|
||||
Assert.IsTrue(Math.Abs((U.X / length) - V.X) < 1e-5);
|
||||
Assert.IsTrue(Math.Abs((U.Y / length) - V.Y) < 1e-5);
|
||||
Assert.IsTrue(Math.Abs((U.Z / length) - V.Z) < 1e-5);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_NormalizeFast_Static()
|
||||
{
|
||||
float X = 64, Y = 144, Z = 16;
|
||||
Vector3 U = new Vector3(X, Y, Z);
|
||||
Vector3 V = Vector3.NormalizeFast(U);
|
||||
float scale = MathHelper.InverseSqrtFast(X * X + Y * Y + Z * Z);
|
||||
Assert.AreEqual(U.X * scale, V.X);
|
||||
Assert.AreEqual(U.Y * scale, V.Y);
|
||||
Assert.AreEqual(U.Z * scale, V.Z);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_NormalizeFast()
|
||||
{
|
||||
float X = 64, Y = 144, Z = 16;
|
||||
Vector3 U = new Vector3(X, Y, Z);
|
||||
Vector3 V;
|
||||
Vector3.NormalizeFast(ref U, out V);
|
||||
float scale = MathHelper.InverseSqrtFast(X * X + Y * Y + Z * Z);
|
||||
Assert.AreEqual(U.X * scale, V.X);
|
||||
Assert.AreEqual(U.Y * scale, V.Y);
|
||||
Assert.AreEqual(U.Z * scale, V.Z);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Dot()
|
||||
{
|
||||
Vector3 T = new Vector3(7, 8, 9);
|
||||
Vector3 U = new Vector3(23, 89, -34);
|
||||
float dot = Vector3.Dot(T, U);
|
||||
float expected = T.X * U.X + T.Y * U.Y + T.Z * U.Z;
|
||||
Assert.AreEqual(expected, dot);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Cross()
|
||||
{
|
||||
Vector3 T = new Vector3(7, 8, 9);
|
||||
Vector3 U = new Vector3(23, 89, -34);
|
||||
Vector3 expected = new Vector3(-1073, 445, 439);
|
||||
Vector3 result = Vector3.Cross(T, U);
|
||||
Assert.IsTrue(expected == result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Lerp()
|
||||
{
|
||||
Vector3 T = new Vector3(7, 8, 9);
|
||||
Vector3 U = new Vector3(23, 89, -34);
|
||||
float blend = 0.25f;
|
||||
Vector3 expected = blend * (U - T) + T;
|
||||
Vector3 result = Vector3.Lerp(T, U, blend);
|
||||
Assert.IsTrue(expected == result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_LerpOut()
|
||||
{
|
||||
Vector3 T = new Vector3(7, 8, 9);
|
||||
Vector3 U = new Vector3(23, 89, -34);
|
||||
float blend = 0.25f;
|
||||
Vector3 expected = blend * (U - T) + T;
|
||||
Vector3 result;
|
||||
Vector3.Lerp(ref T, ref U, blend, out result);
|
||||
Assert.IsTrue(expected == result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_BaryCentric()
|
||||
{
|
||||
Vector3 a = new Vector3(7, 8, 9);
|
||||
Vector3 b = new Vector3(23, 89, -34);
|
||||
Vector3 c = new Vector3(88, -42, 39);
|
||||
float u = 0.25f;
|
||||
float v = 0.75f;
|
||||
Vector3 expected = a + u * (b - a) + v * (c - a);
|
||||
Vector3 result = Vector3.BaryCentric(a, b, c, u, v);
|
||||
Assert.IsTrue(expected == result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_BaryCentricOut()
|
||||
{
|
||||
Vector3 a = new Vector3(7, 8, 9);
|
||||
Vector3 b = new Vector3(23, 89, -34);
|
||||
Vector3 c = new Vector3(88, -42, 39);
|
||||
float u = 0.25f;
|
||||
float v = 0.75f;
|
||||
Vector3 expected = a + u * (b - a) + v * (c - a);
|
||||
Vector3 result;
|
||||
Vector3.BaryCentric(ref a, ref b, ref c, u, v, out result);
|
||||
Assert.IsTrue(expected == result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Matrix3TimesVector3_operator()
|
||||
{
|
||||
Matrix3 A = new Matrix3();
|
||||
A[0, 0] = 16; A[0, 1] = 15; A[0, 2] = 14;
|
||||
A[1, 0] = 12; A[1, 1] = 11; A[1, 2] = 10;
|
||||
A[2, 0] = 8; A[2, 1] = 7; A[2, 2] = 6;
|
||||
|
||||
Vector3 input = new Vector3(1, 5, 9);
|
||||
Vector3 result = A * input;
|
||||
OpenTK.Vector3 expected = new OpenTK.Vector3(217, 157, 97);
|
||||
Assert.IsTrue(expected == result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Vector3_Equal_operator()
|
||||
{
|
||||
Vector3 V = new Vector3(1, 2, 3);
|
||||
Vector3 U = new Vector3(1, 2, 3);
|
||||
Assert.IsTrue(U == V);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
754
tests/OpenTK.Tests/Vector3Tests.fs
Normal file
754
tests/OpenTK.Tests/Vector3Tests.fs
Normal file
|
@ -0,0 +1,754 @@
|
|||
namespace OpenTK.Tests
|
||||
|
||||
open Xunit
|
||||
open FsCheck
|
||||
open FsCheck.Xunit
|
||||
open System
|
||||
open System.Runtime.InteropServices
|
||||
open OpenTK
|
||||
|
||||
module Vector3 =
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Constructors =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Triple value constructor sets all components to the correct values`` (a, b, c) =
|
||||
let v = Vector3(a, b, c)
|
||||
|
||||
Assert.Equal(a, v.X)
|
||||
Assert.Equal(b, v.Y)
|
||||
Assert.Equal(c, v.Z)
|
||||
|
||||
[<Property>]
|
||||
let ``Single value constructor sets all components to the correct values`` (a : float32) =
|
||||
let v = Vector3(a)
|
||||
|
||||
Assert.Equal(a, v.X)
|
||||
Assert.Equal(a, v.Y)
|
||||
Assert.Equal(a, v.Z)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector2 value constructor sets all components to the correct values`` (a, b) =
|
||||
let v1 = Vector2(a, b)
|
||||
let v2 = Vector3(v1)
|
||||
|
||||
Assert.Equal(v1.X, v2.X)
|
||||
Assert.Equal(v1.Y, v2.Y)
|
||||
|
||||
Assert.Equal(a, v2.X)
|
||||
Assert.Equal(b, v2.Y)
|
||||
Assert.Equal(0.0f, v2.Z)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector3 value constructor sets all components to the correct values`` (a, b, c) =
|
||||
let v1 = Vector3(a, b, c)
|
||||
let v2 = Vector3(v1)
|
||||
|
||||
Assert.Equal(v1.X, v2.X)
|
||||
Assert.Equal(v1.Y, v2.Y)
|
||||
Assert.Equal(v1.Z, v2.Z)
|
||||
|
||||
Assert.Equal(a, v2.X)
|
||||
Assert.Equal(b, v2.Y)
|
||||
Assert.Equal(c, v2.Z)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector4 value constructor sets all components to the correct values`` (a, b, c, d) =
|
||||
let v1 = Vector4(a, b, c, d)
|
||||
let v2 = Vector3(v1)
|
||||
|
||||
Assert.Equal(v1.X, v2.X)
|
||||
Assert.Equal(v1.Y, v2.Y)
|
||||
Assert.Equal(v1.Z, v2.Z)
|
||||
|
||||
Assert.Equal(a, v2.X)
|
||||
Assert.Equal(b, v2.Y)
|
||||
Assert.Equal(c, v2.Z)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Indexing =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Index operator accesses the correct components`` (x, y, z) =
|
||||
let v = Vector3(x, y, z)
|
||||
|
||||
Assert.Equal(x, v.[0])
|
||||
Assert.Equal(y, v.[1])
|
||||
Assert.Equal(z, v.[2])
|
||||
|
||||
[<Property>]
|
||||
let ``Indexed set operator throws exception for negative indices`` (x, y, z) =
|
||||
let mutable v = Vector3(x, y, z)
|
||||
|
||||
(fun() -> v.[-1] <- x) |> Assert.ThrowsIndexExn
|
||||
|
||||
[<Property>]
|
||||
let ``Indexed get operator throws exception for negative indices`` (x, y, z) =
|
||||
let mutable v = Vector3(x, y, z)
|
||||
|
||||
(fun() -> v.[-1] |> ignore) |> Assert.ThrowsIndexExn
|
||||
|
||||
[<Property>]
|
||||
let ``Indexed set operator throws exception for large indices`` (x, y, z) =
|
||||
let mutable v = Vector3(x, y, z)
|
||||
|
||||
(fun() -> v.[4] <- x) |> Assert.ThrowsIndexExn
|
||||
|
||||
[<Property>]
|
||||
let ``Indexed get operator throws exception for large indices`` (x, y, z) =
|
||||
let mutable v = Vector3(x, y, z)
|
||||
|
||||
(fun() -> v.[4] |> ignore) |> Assert.ThrowsIndexExn
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Length =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Length method follows the pythagorean theorem`` (a, b, c) =
|
||||
let v = Vector3(a, b, c)
|
||||
let l = System.Math.Sqrt((float)(a * a + b * b + c * c))
|
||||
|
||||
Assert.Equal((float32)l, v.Length)
|
||||
|
||||
[<Property>]
|
||||
let ``Fast length method is the same as one divided by the fast inverse square`` (a, b, c) =
|
||||
let v = Vector3(a, b, c)
|
||||
let l = 1.0f / MathHelper.InverseSqrtFast(a * a + b * b + c * c)
|
||||
|
||||
Assert.Equal(l, v.LengthFast)
|
||||
|
||||
[<Property>]
|
||||
let ``Length squared method returns each component squared and summed`` (a, b, c) =
|
||||
let v = Vector3(a, b, c)
|
||||
let lsq = a * a + b * b + c * c
|
||||
|
||||
Assert.Equal(lsq, v.LengthSquared)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Normalization =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Normalization creates a new unit length vector with the correct components`` (a, b, c) =
|
||||
let v = Vector3(a, b, c)
|
||||
let l = v.Length
|
||||
|
||||
// Dividing by zero is not supported
|
||||
if not (approxEq l 0.0f) then
|
||||
let norm = v.Normalized()
|
||||
|
||||
Assert.ApproximatelyEquivalent(v.X / l, norm.X)
|
||||
Assert.ApproximatelyEquivalent(v.Y / l, norm.Y)
|
||||
Assert.ApproximatelyEquivalent(v.Z / l, norm.Z)
|
||||
|
||||
[<Property>]
|
||||
let ``Normalization of instance transforms the instance into a unit length vector with the correct components`` (a, b, c) =
|
||||
let v = Vector3(a, b, c)
|
||||
let l = v.Length
|
||||
|
||||
if not (approxEq l 0.0f) then
|
||||
let norm = Vector3(a, b, c)
|
||||
norm.Normalize()
|
||||
|
||||
Assert.ApproximatelyEquivalent(v.X / l, norm.X)
|
||||
Assert.ApproximatelyEquivalent(v.Y / l, norm.Y)
|
||||
Assert.ApproximatelyEquivalent(v.Z / l, norm.Z)
|
||||
|
||||
[<Property>]
|
||||
let ``Fast approximate normalization of instance transforms the instance into a unit length vector with the correct components`` (a, b, c) =
|
||||
let v = Vector3(a, b, c)
|
||||
let norm = Vector3(a, b, c)
|
||||
norm.NormalizeFast()
|
||||
|
||||
let scale = MathHelper.InverseSqrtFast(a * a + b * b + c * c)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v.X * scale, norm.X)
|
||||
Assert.ApproximatelyEquivalent(v.Y * scale, norm.Y)
|
||||
Assert.ApproximatelyEquivalent(v.Z * scale, norm.Z)
|
||||
|
||||
[<Property>]
|
||||
let ``Normalization by reference is the same as division by magnitude`` (a : Vector3) =
|
||||
// Zero-length vectors can't be normalized
|
||||
if not (approxEq a.Length 0.0f) then
|
||||
let norm = a / a.Length
|
||||
let vRes = Vector3.Normalize(ref a)
|
||||
|
||||
Assert.ApproximatelyEquivalent(norm, vRes)
|
||||
|
||||
[<Property>]
|
||||
let ``Normalization is the same as division by magnitude`` (a : Vector3) =
|
||||
// Zero-length vectors can't be normalized
|
||||
if not (approxEq a.Length 0.0f) then
|
||||
let norm = a / a.Length
|
||||
|
||||
Assert.ApproximatelyEquivalent(norm, Vector3.Normalize(a));
|
||||
|
||||
[<Property>]
|
||||
let ``Fast approximate normalization by reference is the same as multiplication by the fast inverse square`` (a : Vector3) =
|
||||
let scale = MathHelper.InverseSqrtFast(a.X * a.X + a.Y * a.Y + a.Z * a.Z)
|
||||
|
||||
let norm = a * scale
|
||||
let vRes = Vector3.NormalizeFast(ref a)
|
||||
|
||||
Assert.ApproximatelyEquivalent(norm, vRes)
|
||||
|
||||
[<Property>]
|
||||
let ``Fast approximate normalization is the same as multiplication by fast inverse square`` (a : Vector3) =
|
||||
let scale = MathHelper.InverseSqrtFast(a.X * a.X + a.Y * a.Y + a.Z * a.Z)
|
||||
|
||||
let norm = a * scale
|
||||
|
||||
Assert.ApproximatelyEquivalent(norm, Vector3.NormalizeFast(a));
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Addition =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector3 addition is the same as component addition`` (a : Vector3, b : Vector3) =
|
||||
let c = a + b
|
||||
|
||||
Assert.ApproximatelyEquivalent(a.X + b.X,c.X)
|
||||
Assert.ApproximatelyEquivalent(a.Y + b.Y,c.Y)
|
||||
Assert.ApproximatelyEquivalent(a.Z + b.Z,c.Z)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector3 addition is commutative`` (a : Vector3, b : Vector3) =
|
||||
let c = a + b
|
||||
let c2 = b + a
|
||||
|
||||
Assert.ApproximatelyEquivalent(c, c2)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector3 addition is associative`` (a : Vector3, b : Vector3, c : Vector3) =
|
||||
let r1 = (a + b) + c
|
||||
let r2 = a + (b + c)
|
||||
|
||||
Assert.ApproximatelyEquivalent(r1, r2)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector3 addition method is the same as component addition`` (a : Vector3, b : Vector3) =
|
||||
|
||||
let v1 = Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z)
|
||||
let sum = Vector3.Add(a, b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector3 addition method by reference is the same as component addition`` (a : Vector3, b : Vector3) =
|
||||
|
||||
let v1 = Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z)
|
||||
let sum = Vector3.Add(ref a, ref b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Subtraction =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector3 subtraction is the same as component subtraction`` (a : Vector3, b : Vector3) =
|
||||
let c = a - b
|
||||
|
||||
Assert.Equal(a.X - b.X,c.X)
|
||||
Assert.Equal(a.Y - b.Y,c.Y)
|
||||
Assert.Equal(a.Z - b.Z,c.Z)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector3 subtraction method is the same as component addition`` (a : Vector3, b : Vector3) =
|
||||
|
||||
let v1 = Vector3(a.X - b.X, a.Y - b.Y, a.Z - b.Z)
|
||||
let sum = Vector3.Subtract(a, b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector3 subtraction method by reference is the same as component addition`` (a : Vector3, b : Vector3) =
|
||||
|
||||
let v1 = Vector3(a.X - b.X, a.Y - b.Y, a.Z - b.Z)
|
||||
let sum = Vector3.Subtract(ref a, ref b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Multiplication =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector3 multiplication is the same as component multiplication`` (a : Vector3, b : Vector3) =
|
||||
let c = a * b
|
||||
|
||||
Assert.Equal(a.X * b.X,c.X)
|
||||
Assert.Equal(a.Y * b.Y,c.Y)
|
||||
Assert.Equal(a.Z * b.Z,c.Z)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector3 multiplication is commutative`` (a : Vector3, b : Vector3) =
|
||||
let r1 = a * b
|
||||
let r2 = b * a
|
||||
|
||||
Assert.Equal(r1, r2)
|
||||
|
||||
[<Property>]
|
||||
let ``Left-handed Vector3-scalar multiplication is the same as component-scalar multiplication`` (a : Vector3, f : float32) =
|
||||
let r = a * f
|
||||
|
||||
Assert.Equal(a.X * f,r.X)
|
||||
Assert.Equal(a.Y * f,r.Y)
|
||||
Assert.Equal(a.Z * f,r.Z)
|
||||
|
||||
[<Property>]
|
||||
let ``Right-handed Vector3-scalar multiplication is the same as component-scalar multiplication`` (a : Vector3, f : float32) =
|
||||
let r = f * a
|
||||
Assert.Equal(a.X * f,r.X)
|
||||
Assert.Equal(a.Y * f,r.Y)
|
||||
Assert.Equal(a.Z * f,r.Z)
|
||||
|
||||
[<Property>]
|
||||
let ``Static method Vector3-scalar multiplication is the same as component-scalar multiplication`` (a : Vector3, f : float32) =
|
||||
let r = Vector3.Multiply(a, f)
|
||||
|
||||
Assert.Equal(a.X * f,r.X)
|
||||
Assert.Equal(a.Y * f,r.Y)
|
||||
Assert.Equal(a.Z * f,r.Z)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector3-Matrix3 multiplication using right-handed notation is the same as vector/row multiplication and summation`` (a : Matrix3, b : Vector3) =
|
||||
let res = a*b
|
||||
|
||||
let c1 = b.X * a.M11 + b.Y * a.M12 + b.Z * a.M13
|
||||
let c2 = b.X * a.M21 + b.Y * a.M22 + b.Z * a.M23
|
||||
let c3 = b.X * a.M31 + b.Y * a.M32 + b.Z * a.M33
|
||||
|
||||
let exp = Vector3(c1, c2, c3)
|
||||
|
||||
Assert.Equal(exp, res)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector3-Matrix3 multiplication using left-handed notation is the same as vector/column multiplication and summation`` (a : Matrix3, b : Vector3) =
|
||||
let res = b*a
|
||||
|
||||
let c1 = b.X * a.M11 + b.Y * a.M21 + b.Z * a.M31
|
||||
let c2 = b.X * a.M12 + b.Y * a.M22 + b.Z * a.M32
|
||||
let c3 = b.X * a.M13 + b.Y * a.M23 + b.Z * a.M33
|
||||
|
||||
let exp = Vector3(c1, c2, c3)
|
||||
|
||||
Assert.Equal(exp, res)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector3 multiplication method is the same as component multiplication`` (a : Vector3, b : Vector3) =
|
||||
|
||||
let v1 = Vector3(a.X * b.X, a.Y * b.Y, a.Z * b.Z)
|
||||
let sum = Vector3.Multiply(a, b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector3 multiplication method by reference is the same as component multiplication`` (a : Vector3, b : Vector3) =
|
||||
|
||||
let v1 = Vector3(a.X * b.X, a.Y * b.Y, a.Z * b.Z)
|
||||
let sum = Vector3.Multiply(ref a, ref b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Division =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector3-float division is the same as component-float division`` (a : Vector3, f : float32) =
|
||||
if not (approxEq f 0.0f) then // we don't support diving by zero.
|
||||
let r = a / f
|
||||
|
||||
Assert.ApproximatelyEquivalent(a.X / f,r.X)
|
||||
Assert.ApproximatelyEquivalent(a.Y / f,r.Y)
|
||||
Assert.ApproximatelyEquivalent(a.Z / f,r.Z)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector3-Vector3 division method is the same as component division`` (a : Vector3, b : Vector3) =
|
||||
if not (anyZero3 a || anyZero3 b) then
|
||||
let v1 = Vector3(a.X / b.X, a.Y / b.Y, a.Z / b.Z)
|
||||
let sum = Vector3.Divide(a, b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector3-Vector3 divison method by reference is the same as component division`` (a : Vector3, b : Vector3) =
|
||||
if not (anyZero3 a || anyZero3 b) then
|
||||
let v1 = Vector3(a.X / b.X, a.Y / b.Y, a.Z / b.Z)
|
||||
let sum = Vector3.Divide(ref a, ref b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector3-scalar division method is the same as component division`` (a : Vector3, b : float32) =
|
||||
if not (approxEq b 0.0f) then // we don't support diving by zero.
|
||||
let v1 = Vector3(a.X / b, a.Y / b, a.Z / b)
|
||||
let sum = Vector3.Divide(a, b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector3-scalar divison method by reference is the same as component division`` (a : Vector3, b : float32) =
|
||||
if not (approxEq b 0.0f) then // we don't support diving by zero.
|
||||
let v1 = Vector3(a.X / b, a.Y / b, a.Z / b)
|
||||
let sum = Vector3.Divide(ref a, b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Negation =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector negation operator negates all components`` (x, y, z) =
|
||||
let v = Vector3(x, y, z)
|
||||
let vNeg = -v
|
||||
Assert.Equal(-x, vNeg.X)
|
||||
Assert.Equal(-y, vNeg.Y)
|
||||
Assert.Equal(-z, vNeg.Z)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Equality =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector equality operator is by component`` (x, y, z) =
|
||||
let v1 = Vector3(x, y, z)
|
||||
let v2 = Vector3(x, y, z)
|
||||
let equality = v1 = v2
|
||||
|
||||
Assert.True(equality)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector inequality operator is by component`` (x, y, z) =
|
||||
let v1 = Vector3(x, y, z)
|
||||
let v2 = Vector3(x + 1.0f , y + 1.0f, z + 1.0f)
|
||||
let inequality = v1 <> v2
|
||||
|
||||
Assert.True(inequality)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector equality method is by component`` (x, y, z) =
|
||||
let v1 = Vector3(x, y, z)
|
||||
let v2 = Vector3(x, y, z)
|
||||
let notVector = Matrix2()
|
||||
|
||||
let equality = v1.Equals(v2)
|
||||
let inequalityByOtherType = v1.Equals(notVector)
|
||||
|
||||
Assert.True(equality)
|
||||
Assert.False(inequalityByOtherType)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Swizzling =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector swizzling returns the correct composite for X-primary components`` (x, y, z) =
|
||||
let v = Vector3(x, y, z)
|
||||
|
||||
let xyz = Vector3(x, y, z)
|
||||
let xzy = Vector3(x, z, y)
|
||||
let xy = Vector2(x, y)
|
||||
let xz = Vector2(x, z)
|
||||
|
||||
Assert.Equal(xyz, v);
|
||||
Assert.Equal(xzy, v.Xzy);
|
||||
Assert.Equal(xy, v.Xy);
|
||||
Assert.Equal(xz, v.Xz);
|
||||
|
||||
[<Property>]
|
||||
let ``Vector swizzling returns the correct composite for Y-primary components`` (x, y, z) =
|
||||
let v = Vector3(x, y, z)
|
||||
|
||||
let yxz = Vector3(y, x, z)
|
||||
let yzx = Vector3(y, z, x)
|
||||
let yx = Vector2(y, x)
|
||||
let yz = Vector2(y, z)
|
||||
|
||||
Assert.Equal(yxz, v.Yxz);
|
||||
Assert.Equal(yzx, v.Yzx);
|
||||
Assert.Equal(yx, v.Yx);
|
||||
Assert.Equal(yz, v.Yz);
|
||||
|
||||
[<Property>]
|
||||
let ``Vector swizzling returns the correct composite for Z-primary components`` (x, y, z) =
|
||||
let v = Vector3(x, y, z)
|
||||
|
||||
let zxy = Vector3(z, x, y)
|
||||
let zyx = Vector3(z, y, x)
|
||||
let zx = Vector2(z, x)
|
||||
let zy = Vector2(z, y);
|
||||
|
||||
Assert.Equal(zxy, v.Zxy);
|
||||
Assert.Equal(zyx, v.Zyx);
|
||||
Assert.Equal(zx, v.Zx);
|
||||
Assert.Equal(zy, v.Zy);
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Interpolation =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Linear interpolation is by component`` (a : Vector3, b : Vector3, q) =
|
||||
|
||||
let blend = q
|
||||
|
||||
let rX = blend * (b.X - a.X) + a.X
|
||||
let rY = blend * (b.Y - a.Y) + a.Y
|
||||
let rZ = blend * (b.Z - a.Z) + a.Z
|
||||
let vExp = Vector3(rX, rY, rZ)
|
||||
|
||||
Assert.Equal(vExp, Vector3.Lerp(a, b, q))
|
||||
|
||||
let vRes = Vector3.Lerp(ref a, ref b, q)
|
||||
Assert.Equal(vExp, vRes)
|
||||
|
||||
[<Property>]
|
||||
let ``Barycentric interpolation follows the barycentric formula`` (a : Vector3, b : Vector3, c : Vector3, u, v) =
|
||||
|
||||
let r = a + u * (b - a) + v * (c - a)
|
||||
|
||||
Assert.Equal(r, Vector3.BaryCentric(a, b, c, u, v))
|
||||
|
||||
let vRes = Vector3.BaryCentric(ref a, ref b, ref c, u, v)
|
||||
Assert.Equal(r, vRes)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module ``Vector products`` =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Dot product follows the dot product formula`` (a : Vector3, b : Vector3) =
|
||||
let dot = a.X * b.X + a.Y * b.Y + a.Z * b.Z
|
||||
|
||||
Assert.Equal(dot, Vector3.Dot(a, b));
|
||||
|
||||
let vRes = Vector3.Dot(ref a, ref b)
|
||||
Assert.Equal(dot, vRes)
|
||||
|
||||
[<Property>]
|
||||
let ``Cross product follows the cross product formula`` (a : Vector3, b : Vector3) =
|
||||
let crossX = a.Y * b.Z - a.Z * b.Y
|
||||
let crossY = a.Z * b.X - a.X * b.Z
|
||||
let crossZ = a.X * b.Y - a.Y * b.X
|
||||
let cross = Vector3(crossX, crossY, crossZ)
|
||||
|
||||
Assert.Equal(cross, Vector3.Cross(a, b));
|
||||
|
||||
let vRes = Vector3.Cross(ref a, ref b)
|
||||
Assert.Equal(cross, vRes)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module ``Magnitude min and max`` =
|
||||
//
|
||||
[<Property>]
|
||||
let ``MagnitudeMin selects the vector with equal or lesser magnitude given two vectors`` (v1 : Vector3, v2: Vector3) =
|
||||
// Results do not matter for equal vectors
|
||||
if not (v1 = v2) then
|
||||
let l1 = v1.LengthSquared
|
||||
let l2 = v2.LengthSquared
|
||||
|
||||
let vMin = Vector3.MagnitudeMin(v1, v2)
|
||||
|
||||
if vMin = v1 then
|
||||
let v1ShorterThanv2 = l1 < l2
|
||||
Assert.True(v1ShorterThanv2)
|
||||
else
|
||||
let v2ShorterThanOrEqualTov1 = l2 <= l1
|
||||
Assert.True(v2ShorterThanOrEqualTov1)
|
||||
|
||||
[<Property>]
|
||||
let ``MagnitudeMax selects the vector with equal or greater magnitude given two vectors`` (v1 : Vector3, v2: Vector3) =
|
||||
// Results do not matter for equal vectors
|
||||
if not (v1 = v2) then
|
||||
let l1 = v1.LengthSquared
|
||||
let l2 = v2.LengthSquared
|
||||
|
||||
let vMin = Vector3.MagnitudeMax(v1, v2)
|
||||
|
||||
if vMin = v1 then
|
||||
let v1LongerThanOrEqualTov2 = l1 >= l2
|
||||
Assert.True(v1LongerThanOrEqualTov2)
|
||||
else
|
||||
let v2LongerThanv1 = l2 > l1
|
||||
Assert.True(v2LongerThanv1)
|
||||
|
||||
[<Property>]
|
||||
let ``MagnitudeMin by reference selects the vector with equal or lesser magnitude given two vectors`` (v1 : Vector3, v2: Vector3) =
|
||||
// Results do not matter for equal vectors
|
||||
if not (v1 = v2) then
|
||||
let l1 = v1.LengthSquared
|
||||
let l2 = v2.LengthSquared
|
||||
|
||||
let vMin = Vector3.MagnitudeMin(ref v1, ref v2)
|
||||
|
||||
if vMin = v1 then
|
||||
let v1ShorterThanv2 = l1 < l2
|
||||
Assert.True(v1ShorterThanv2)
|
||||
else
|
||||
let v2ShorterThanOrEqualTov1 = l2 <= l1
|
||||
Assert.True(v2ShorterThanOrEqualTov1)
|
||||
|
||||
[<Property>]
|
||||
let ``MagnitudeMax by reference selects the vector with equal or greater magnitude given two vectors`` (v1 : Vector3, v2: Vector3) =
|
||||
// Results do not matter for equal vectors
|
||||
if not (v1 = v2) then
|
||||
let l1 = v1.LengthSquared
|
||||
let l2 = v2.LengthSquared
|
||||
|
||||
let vMin = Vector3.MagnitudeMax(ref v1, ref v2)
|
||||
|
||||
if vMin = v1 then
|
||||
let v1LongerThanOrEqualTov2 = l1 >= l2
|
||||
Assert.True(v1LongerThanOrEqualTov2)
|
||||
else
|
||||
let v2LongerThanv1 = l2 > l1
|
||||
Assert.True(v2LongerThanv1)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module ``Component min and max`` =
|
||||
//
|
||||
[<Property>]
|
||||
let ``ComponentMin creates a new vector from the smallest components of given vectors`` (v1 : Vector3, v2: Vector3) =
|
||||
let vMin = Vector3.ComponentMin(v1, v2)
|
||||
let isComponentSmallest smallComp comp1 comp2 = smallComp <= comp1 && smallComp <= comp2
|
||||
|
||||
Assert.True(isComponentSmallest vMin.X v1.X v2.X)
|
||||
Assert.True(isComponentSmallest vMin.Y v1.Y v2.Y)
|
||||
Assert.True(isComponentSmallest vMin.Z v1.Z v2.Z)
|
||||
|
||||
[<Property>]
|
||||
let ``ComponentMax creates a new vector from the greatest components of given vectors`` (v1 : Vector3, v2: Vector3) =
|
||||
let vMax = Vector3.ComponentMax(v1, v2)
|
||||
let isComponentLargest largeComp comp1 comp2 = largeComp >= comp1 && largeComp >= comp2
|
||||
|
||||
Assert.True(isComponentLargest vMax.X v1.X v2.X)
|
||||
Assert.True(isComponentLargest vMax.Y v1.Y v2.Y)
|
||||
Assert.True(isComponentLargest vMax.Z v1.Z v2.Z)
|
||||
|
||||
[<Property>]
|
||||
let ``ComponentMin by reference creates a new vector from the smallest components of given vectors`` (v1 : Vector3, v2: Vector3) =
|
||||
let vMin = Vector3.ComponentMin(ref v1, ref v2)
|
||||
let isComponentSmallest smallComp comp1 comp2 = smallComp <= comp1 && smallComp <= comp2
|
||||
|
||||
Assert.True(isComponentSmallest vMin.X v1.X v2.X)
|
||||
Assert.True(isComponentSmallest vMin.Y v1.Y v2.Y)
|
||||
Assert.True(isComponentSmallest vMin.Z v1.Z v2.Z)
|
||||
|
||||
[<Property>]
|
||||
let ``ComponentMax by reference creates a new vector from the greatest components of given vectors`` (v1 : Vector3, v2: Vector3) =
|
||||
let vMax = Vector3.ComponentMax(ref v1, ref v2)
|
||||
let isComponentLargest largeComp comp1 comp2 = largeComp >= comp1 && largeComp >= comp2
|
||||
|
||||
Assert.True(isComponentLargest vMax.X v1.X v2.X)
|
||||
Assert.True(isComponentLargest vMax.Y v1.Y v2.Y)
|
||||
Assert.True(isComponentLargest vMax.Z v1.Z v2.Z)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Clamping =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Clamping one vector between two other vectors clamps all components between corresponding components`` (a : Vector3, b : Vector3, w : Vector3) =
|
||||
let res = Vector3.Clamp(w, a, b)
|
||||
|
||||
let expX = if w.X < a.X then a.X else if w.X > b.X then b.X else w.X
|
||||
let expY = if w.Y < a.Y then a.Y else if w.Y > b.Y then b.Y else w.Y
|
||||
let expZ = if w.Z < a.Z then a.Z else if w.Z > b.Z then b.Z else w.Z
|
||||
|
||||
Assert.Equal(expX, res.X)
|
||||
Assert.Equal(expY, res.Y)
|
||||
Assert.Equal(expZ, res.Z)
|
||||
|
||||
[<Property>]
|
||||
let ``Clamping one vector between two other vectors by reference clamps all components between corresponding components`` (a : Vector3, b : Vector3, w : Vector3) =
|
||||
let res = Vector3.Clamp(ref w, ref a, ref b)
|
||||
|
||||
let expX = if w.X < a.X then a.X else if w.X > b.X then b.X else w.X
|
||||
let expY = if w.Y < a.Y then a.Y else if w.Y > b.Y then b.Y else w.Y
|
||||
let expZ = if w.Z < a.Z then a.Z else if w.Z > b.Z then b.Z else w.Z
|
||||
|
||||
Assert.Equal(expX, res.X)
|
||||
Assert.Equal(expY, res.Y)
|
||||
Assert.Equal(expZ, res.Z)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module ``Unit vectors``=
|
||||
//
|
||||
[<Property>]
|
||||
let ``Unit X is correct`` =
|
||||
let unitX = Vector3(1.0f, 0.0f, 0.0f)
|
||||
|
||||
Assert.Equal(Vector3.UnitX, unitX)
|
||||
|
||||
[<Property>]
|
||||
let ``Unit Y is correct`` =
|
||||
let unitY = Vector3(0.0f, 1.0f, 0.0f)
|
||||
|
||||
Assert.Equal(Vector3.UnitY, unitY)
|
||||
|
||||
[<Property>]
|
||||
let ``Unit Z is correct`` =
|
||||
let unitZ = Vector3(0.0f, 0.0f, 1.0f)
|
||||
|
||||
Assert.Equal(Vector3.UnitZ, unitZ)
|
||||
|
||||
[<Property>]
|
||||
let ``Unit zero is correct`` =
|
||||
let unitZero = Vector3(0.0f, 0.0f, 0.0f)
|
||||
|
||||
Assert.Equal(Vector3.Zero, unitZero)
|
||||
|
||||
[<Property>]
|
||||
let ``Unit one is correct`` =
|
||||
let unitOne = Vector3(1.0f, 1.0f, 1.0f)
|
||||
|
||||
Assert.Equal(Vector3.One, unitOne)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Serialization =
|
||||
//
|
||||
[<Property>]
|
||||
let ``The absolute size of a Vector3 is always the size of its components`` (v : Vector3) =
|
||||
let expectedSize = sizeof<float32> * 3
|
||||
|
||||
Assert.Equal(expectedSize, Vector3.SizeInBytes)
|
||||
Assert.Equal(expectedSize, Marshal.SizeOf(Vector3()))
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Transformation =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Transformation by quaternion is the same as multiplication by quaternion and its conjugate`` (v : Vector3, q : Quaternion) =
|
||||
let vectorQuat = Quaternion(v.X, v.Y, v.Z, 0.0f)
|
||||
let inverse = Quaternion.Invert(q)
|
||||
|
||||
let transformedQuat = q * vectorQuat * inverse
|
||||
let transformedVector = transformedQuat.Xyz
|
||||
|
||||
Assert.ApproximatelyEquivalent(transformedVector, Vector3.Transform(v, q))
|
||||
|
||||
[<Property>]
|
||||
let ``Transformation by quaternion by reference is the same as multiplication by quaternion and its conjugate`` (v : Vector3, q : Quaternion) =
|
||||
let vectorQuat = Quaternion(v.X, v.Y, v.Z, 0.0f)
|
||||
let inverse = Quaternion.Invert(q)
|
||||
|
||||
let transformedQuat = q * vectorQuat * inverse
|
||||
let transformedVector = transformedQuat.Xyz
|
||||
|
||||
Assert.ApproximatelyEquivalent(transformedVector, Vector3.Transform(ref v, ref q))
|
||||
|
||||
[<Property>]
|
||||
let ``Transformation by quaternion by multiplication using right-handed notation is the same as multiplication by quaternion and its conjugate`` (v : Vector3, q : Quaternion) =
|
||||
let vectorQuat = Quaternion(v.X, v.Y, v.Z, 0.0f)
|
||||
let inverse = Quaternion.Invert(q)
|
||||
|
||||
let transformedQuat = q * vectorQuat * inverse
|
||||
let transformedVector = transformedQuat.Xyz
|
||||
|
||||
Assert.ApproximatelyEquivalent(transformedVector, q * v)
|
||||
|
||||
[<Property>]
|
||||
let ``Transformation by identity quaternion does not alter vector`` (v : Vector3) =
|
||||
let q = Quaternion.Identity
|
||||
let vectorQuat = Quaternion(v.X, v.Y, v.Z, 0.0f)
|
||||
let inverse = Quaternion.Invert(q)
|
||||
|
||||
let transformedQuat = q * vectorQuat * inverse
|
||||
let transformedVector = transformedQuat.Xyz
|
||||
|
||||
Assert.ApproximatelyEquivalent(v, transformedVector)
|
||||
Assert.ApproximatelyEquivalent(v, Vector3.Transform(v, q))
|
||||
Assert.ApproximatelyEquivalent(transformedVector, Vector3.Transform(v, q))
|
923
tests/OpenTK.Tests/Vector4Tests.fs
Normal file
923
tests/OpenTK.Tests/Vector4Tests.fs
Normal file
|
@ -0,0 +1,923 @@
|
|||
namespace OpenTK.Tests
|
||||
|
||||
open Xunit
|
||||
open FsCheck
|
||||
open FsCheck.Xunit
|
||||
open System
|
||||
open System.Runtime.InteropServices
|
||||
open OpenTK
|
||||
|
||||
module Vector4 =
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Constructors =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Triple value constructor sets all components to the correct values`` (x, y, z, w) =
|
||||
let v = Vector4(x, y, z, w)
|
||||
|
||||
Assert.Equal(x, v.X)
|
||||
Assert.Equal(y, v.Y)
|
||||
Assert.Equal(z, v.Z)
|
||||
Assert.Equal(w, v.W)
|
||||
|
||||
[<Property>]
|
||||
let ``Single value constructor sets all components to the correct values`` (a : float32) =
|
||||
let v = Vector4(a)
|
||||
|
||||
Assert.Equal(a, v.X)
|
||||
Assert.Equal(a, v.Y)
|
||||
Assert.Equal(a, v.Z)
|
||||
Assert.Equal(a, v.W)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector2 value constructor sets all components to the correct values`` (x, y) =
|
||||
let v1 = Vector2(x, y)
|
||||
let v2 = Vector4(v1)
|
||||
|
||||
Assert.Equal(v1.X, v2.X)
|
||||
Assert.Equal(v1.Y, v2.Y)
|
||||
|
||||
Assert.Equal(x, v2.X)
|
||||
Assert.Equal(y, v2.Y)
|
||||
Assert.Equal(0.0f, v2.Z)
|
||||
Assert.Equal(0.0f, v2.W)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector3 value constructor sets all components to the correct values`` (x, y, z) =
|
||||
let v1 = Vector3(x, y, z)
|
||||
let v2 = Vector4(v1)
|
||||
|
||||
Assert.Equal(v1.X, v2.X)
|
||||
Assert.Equal(v1.Y, v2.Y)
|
||||
Assert.Equal(v1.Z, v2.Z)
|
||||
|
||||
Assert.Equal(x, v2.X)
|
||||
Assert.Equal(y, v2.Y)
|
||||
Assert.Equal(z, v2.Z)
|
||||
Assert.Equal(0.0f, v2.W)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector3 value and scalar constructor sets all components to the correct values`` (x, y, z, w) =
|
||||
let v1 = Vector3(x, y, z)
|
||||
let v2 = Vector4(v1, w)
|
||||
|
||||
Assert.Equal(v1.X, v2.X)
|
||||
Assert.Equal(v1.Y, v2.Y)
|
||||
Assert.Equal(v1.Z, v2.Z)
|
||||
|
||||
Assert.Equal(x, v2.X)
|
||||
Assert.Equal(y, v2.Y)
|
||||
Assert.Equal(z, v2.Z)
|
||||
Assert.Equal(w, v2.W)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector4 value constructor sets all components to the correct values`` (x, y, z, w) =
|
||||
let v1 = Vector4(x, y, z, w)
|
||||
let v2 = Vector4(v1)
|
||||
|
||||
Assert.Equal(v1.X, v2.X)
|
||||
Assert.Equal(v1.Y, v2.Y)
|
||||
Assert.Equal(v1.Z, v2.Z)
|
||||
Assert.Equal(v1.W, v2.W)
|
||||
|
||||
Assert.Equal(x, v2.X)
|
||||
Assert.Equal(y, v2.Y)
|
||||
Assert.Equal(z, v2.Z)
|
||||
Assert.Equal(w, v2.W)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Indexing =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Index operator accesses the correct components`` (x, y, z, w) =
|
||||
let v = Vector4(x, y, z, w)
|
||||
|
||||
Assert.Equal(x, v.[0])
|
||||
Assert.Equal(y, v.[1])
|
||||
Assert.Equal(z, v.[2])
|
||||
Assert.Equal(w, v.[3])
|
||||
|
||||
[<Property>]
|
||||
let ``Indexed set operator throws exception for negative indices`` (x, y, z, w) =
|
||||
let mutable v = Vector4(x, y, z, w)
|
||||
|
||||
(fun() -> v.[-1] <- x) |> Assert.ThrowsIndexExn
|
||||
|
||||
[<Property>]
|
||||
let ``Indexed get operator throws exception for negative indices`` (x, y, z, w) =
|
||||
let mutable v = Vector4(x, y, z, w)
|
||||
|
||||
(fun() -> v.[-1] |> ignore) |> Assert.ThrowsIndexExn
|
||||
|
||||
[<Property>]
|
||||
let ``Indexed set operator throws exception for large indices`` (x, y, z, w) =
|
||||
let mutable v = Vector4(x, y, z, w)
|
||||
|
||||
(fun() -> v.[4] <- x) |> Assert.ThrowsIndexExn
|
||||
|
||||
[<Property>]
|
||||
let ``Indexed get operator throws exception for large indices`` (x, y, z, w) =
|
||||
let mutable v = Vector4(x, y, z, w)
|
||||
|
||||
(fun() -> v.[4] |> ignore) |> Assert.ThrowsIndexExn
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Length =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Length method follows the pythagorean theorem`` (x, y, z, w) =
|
||||
let v = Vector4(x, y, z, w)
|
||||
let l = System.Math.Sqrt((float)(x * x + y * y + z * z + w * w))
|
||||
|
||||
Assert.Equal((float32)l, v.Length)
|
||||
|
||||
[<Property>]
|
||||
let ``Fast length method is the same as one divided by the fast inverse square`` (x, y, z, w) =
|
||||
let v = Vector4(x, y, z, w)
|
||||
let l = 1.0f / MathHelper.InverseSqrtFast(x * x + y * y + z * z + w * w)
|
||||
|
||||
Assert.Equal(l, v.LengthFast)
|
||||
|
||||
[<Property>]
|
||||
let ``Length squared method returns each component squared and summed`` (x, y, z, w) =
|
||||
let v = Vector4(x, y, z, w)
|
||||
let lsq = x * x + y * y + z * z + w * w
|
||||
|
||||
Assert.Equal(lsq, v.LengthSquared)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Normalization =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Normalization creates a new unit length vector with the correct components`` (x, y, z, w) =
|
||||
let v = Vector4(x, y, z, w)
|
||||
let l = v.Length
|
||||
|
||||
// Zero-length vectors can't be normalized
|
||||
if not (approxEq l 0.0f) then
|
||||
let norm = v.Normalized()
|
||||
|
||||
Assert.ApproximatelyEquivalent(v.X / l, norm.X)
|
||||
Assert.ApproximatelyEquivalent(v.Y / l, norm.Y)
|
||||
Assert.ApproximatelyEquivalent(v.Z / l, norm.Z)
|
||||
Assert.ApproximatelyEquivalent(v.W / l, norm.W)
|
||||
|
||||
[<Property>]
|
||||
let ``Normalization of instance transforms the instance into a unit length vector with the correct components`` (x, y, z, w) =
|
||||
let v = Vector4(x, y, z, w)
|
||||
let l = v.Length
|
||||
|
||||
// Zero-length vectors can't be normalized
|
||||
if not (approxEq l 0.0f) then
|
||||
let norm = Vector4(x, y, z, w)
|
||||
norm.Normalize()
|
||||
|
||||
Assert.ApproximatelyEquivalent(v.X / l, norm.X)
|
||||
Assert.ApproximatelyEquivalent(v.Y / l, norm.Y)
|
||||
Assert.ApproximatelyEquivalent(v.Z / l, norm.Z)
|
||||
Assert.ApproximatelyEquivalent(v.W / l, norm.W)
|
||||
|
||||
[<Property>]
|
||||
let ``Fast approximate normalization of instance transforms the instance into a unit length vector with the correct components`` (x, y, z, w) =
|
||||
let v = Vector4(x, y, z, w)
|
||||
let norm = Vector4(x, y, z, w)
|
||||
norm.NormalizeFast()
|
||||
|
||||
let scale = MathHelper.InverseSqrtFast(x * x + y * y + z * z + w * w)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v.X * scale, norm.X)
|
||||
Assert.ApproximatelyEquivalent(v.Y * scale, norm.Y)
|
||||
Assert.ApproximatelyEquivalent(v.Z * scale, norm.Z)
|
||||
Assert.ApproximatelyEquivalent(v.W * scale, norm.W)
|
||||
|
||||
[<Property>]
|
||||
let ``Normalization by reference is the same as division by magnitude`` (a : Vector4) =
|
||||
// Zero-length vectors can't be normalized
|
||||
if not (approxEq a.Length 0.0f) then
|
||||
let norm = a / a.Length
|
||||
let vRes = Vector4.Normalize(ref a)
|
||||
|
||||
Assert.ApproximatelyEquivalent(norm, vRes)
|
||||
|
||||
[<Property>]
|
||||
let ``Normalization is the same as division by magnitude`` (a : Vector4) =
|
||||
// Zero-length vectors can't be normalized
|
||||
if not (approxEq a.Length 0.0f) then
|
||||
let norm = a / a.Length
|
||||
|
||||
Assert.ApproximatelyEquivalent(norm, Vector4.Normalize(a));
|
||||
|
||||
[<Property>]
|
||||
let ``Fast approximate normalization by reference is the same as multiplication by the fast inverse square`` (a : Vector4) =
|
||||
let scale = MathHelper.InverseSqrtFast(a.X * a.X + a.Y * a.Y + a.Z * a.Z + a.W * a.W)
|
||||
|
||||
let norm = a * scale
|
||||
let vRes = Vector4.NormalizeFast(ref a)
|
||||
|
||||
Assert.ApproximatelyEquivalent(norm, vRes)
|
||||
|
||||
[<Property>]
|
||||
let ``Fast approximate normalization is the same as multiplication by the fast inverse square`` (a : Vector4) =
|
||||
let scale = MathHelper.InverseSqrtFast(a.X * a.X + a.Y * a.Y + a.Z * a.Z + a.W * a.W)
|
||||
let norm = a * scale
|
||||
|
||||
Assert.ApproximatelyEquivalent(norm, Vector4.NormalizeFast(a));
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Addition =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector4 addition is the same as component addition`` (a : Vector4, b : Vector4) =
|
||||
let c = a + b
|
||||
|
||||
Assert.ApproximatelyEquivalent(a.X + b.X,c.X)
|
||||
Assert.ApproximatelyEquivalent(a.Y + b.Y,c.Y)
|
||||
Assert.ApproximatelyEquivalent(a.Z + b.Z,c.Z)
|
||||
Assert.ApproximatelyEquivalent(a.W + b.W,c.W)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector4 addition is commutative`` (a : Vector4, b : Vector4) =
|
||||
let c = a + b
|
||||
let c2 = b + a
|
||||
|
||||
Assert.ApproximatelyEquivalent(c, c2)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector4 addition is associative`` (a : Vector4, b : Vector4, c : Vector4) =
|
||||
let r1 = (a + b) + c
|
||||
let r2 = a + (b + c)
|
||||
|
||||
Assert.ApproximatelyEquivalent(r1, r2)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector4 addition method is the same as component addition`` (a : Vector4, b : Vector4) =
|
||||
|
||||
let v1 = Vector4(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W)
|
||||
let sum = Vector4.Add(a, b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector4 addition method by reference is the same as component addition`` (a : Vector4, b : Vector4) =
|
||||
|
||||
let v1 = Vector4(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W)
|
||||
let sum = Vector4.Add(ref a, ref b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Subtraction =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector4 subtraction is the same as component subtraction`` (a : Vector4, b : Vector4) =
|
||||
let c = a - b
|
||||
|
||||
Assert.Equal(a.X - b.X,c.X)
|
||||
Assert.Equal(a.Y - b.Y,c.Y)
|
||||
Assert.Equal(a.Z - b.Z,c.Z)
|
||||
Assert.Equal(a.W - b.W,c.W)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector4 subtraction method is the same as component addition`` (a : Vector4, b : Vector4) =
|
||||
|
||||
let v1 = Vector4(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W)
|
||||
let sum = Vector4.Subtract(a, b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector4 subtraction method by reference is the same as component addition`` (a : Vector4, b : Vector4) =
|
||||
|
||||
let v1 = Vector4(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W)
|
||||
let sum = Vector4.Subtract(ref a, ref b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Multiplication =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector4 multiplication is the same as component multiplication`` (a : Vector4, b : Vector4) =
|
||||
let c = a * b
|
||||
|
||||
Assert.Equal(a.X * b.X,c.X)
|
||||
Assert.Equal(a.Y * b.Y,c.Y)
|
||||
Assert.Equal(a.Z * b.Z,c.Z)
|
||||
Assert.Equal(a.W * b.W,c.W)
|
||||
|
||||
|
||||
[<Property>]
|
||||
let ``Vector4 multiplication is commutative`` (a : Vector4, b : Vector4) =
|
||||
let r1 = a * b
|
||||
let r2 = b * a
|
||||
|
||||
Assert.Equal(r1, r2)
|
||||
|
||||
[<Property>]
|
||||
let ``Left-handed Vector4-scalar multiplication is the same as component-scalar multiplication`` (a : Vector4, f : float32) =
|
||||
let r = a * f
|
||||
|
||||
Assert.Equal(a.X * f,r.X)
|
||||
Assert.Equal(a.Y * f,r.Y)
|
||||
Assert.Equal(a.Z * f,r.Z)
|
||||
Assert.Equal(a.W * f,r.W)
|
||||
|
||||
[<Property>]
|
||||
let ``Right-handed Vector4-scalar multiplication is the same as component-scalar multiplication`` (a : Vector4, f : float32) =
|
||||
let r = f * a
|
||||
Assert.Equal(a.X * f,r.X)
|
||||
Assert.Equal(a.Y * f,r.Y)
|
||||
Assert.Equal(a.Z * f,r.Z)
|
||||
Assert.Equal(a.W * f,r.W)
|
||||
|
||||
[<Property>]
|
||||
let ``Static method Vector4-scalar multiplication is the same as component-scalar multiplication`` (a : Vector4, f : float32) =
|
||||
let r = Vector4.Multiply(a, f)
|
||||
|
||||
Assert.Equal(a.X * f,r.X)
|
||||
Assert.Equal(a.Y * f,r.Y)
|
||||
Assert.Equal(a.Z * f,r.Z)
|
||||
Assert.Equal(a.W * f,r.W)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector4-Matrix4 multiplication using right-handed notation is the same as vector/row multiplication and summation`` (a : Matrix4, b : Vector4) =
|
||||
let res = a*b
|
||||
|
||||
let c1 = b.X * a.M11 + b.Y * a.M12 + b.Z * a.M13 + b.W * a.M14
|
||||
let c2 = b.X * a.M21 + b.Y * a.M22 + b.Z * a.M23 + b.W * a.M24
|
||||
let c3 = b.X * a.M31 + b.Y * a.M32 + b.Z * a.M33 + b.W * a.M34
|
||||
let c4 = b.X * a.M41 + b.Y * a.M42 + b.Z * a.M43 + b.W * a.M44
|
||||
|
||||
let exp = Vector4(c1, c2, c3, c4)
|
||||
|
||||
Assert.Equal(exp, res)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector4-Matrix4 multiplication using left-handed notation is the same as vector/column multiplication and summation`` (a : Matrix4, b : Vector4) =
|
||||
let res = b*a
|
||||
|
||||
let c1 = b.X * a.M11 + b.Y * a.M21 + b.Z * a.M31 + b.W * a.M41
|
||||
let c2 = b.X * a.M12 + b.Y * a.M22 + b.Z * a.M32 + b.W * a.M42
|
||||
let c3 = b.X * a.M13 + b.Y * a.M23 + b.Z * a.M33 + b.W * a.M43
|
||||
let c4 = b.X * a.M14 + b.Y * a.M24 + b.Z * a.M34 + b.W * a.M44
|
||||
|
||||
let exp = Vector4(c1, c2, c3, c4)
|
||||
|
||||
Assert.Equal(exp, res)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector4 multiplication method is the same as component multiplication`` (a : Vector4, b : Vector4) =
|
||||
|
||||
let v1 = Vector4(a.X * b.X, a.Y * b.Y, a.Z * b.Z, a.W * b.W)
|
||||
let sum = Vector4.Multiply(a, b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector4 multiplication method by reference is the same as component multiplication`` (a : Vector4, b : Vector4) =
|
||||
|
||||
let v1 = Vector4(a.X * b.X, a.Y * b.Y, a.Z * b.Z, a.W * b.W)
|
||||
let sum = Vector4.Multiply(ref a, ref b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Division =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector4-float division is the same as component-float division`` (a : Vector4, f : float32) =
|
||||
if not (approxEq f 0.0f) then // we don't support diving by zero.
|
||||
let r = a / f
|
||||
|
||||
Assert.ApproximatelyEquivalent(a.X / f, r.X)
|
||||
Assert.ApproximatelyEquivalent(a.Y / f, r.Y)
|
||||
Assert.ApproximatelyEquivalent(a.Z / f, r.Z)
|
||||
Assert.ApproximatelyEquivalent(a.W / f, r.W)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector4-Vector4 division method is the same as component division`` (a : Vector4, b : Vector4) =
|
||||
if not (anyZero4 a || anyZero4 b) then
|
||||
let v1 = Vector4(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W)
|
||||
let sum = Vector4.Divide(a, b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector4-Vector4 divison method by reference is the same as component division`` (a : Vector4, b : Vector4) =
|
||||
if not (anyZero4 a || anyZero4 b) then
|
||||
let v1 = Vector4(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W)
|
||||
let sum = Vector4.Divide(ref a, ref b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector4-scalar division method is the same as component division`` (a : Vector4, b : float32) =
|
||||
if not (approxEq b 0.0f) then // we don't support diving by zero.
|
||||
let v1 = Vector4(a.X / b, a.Y / b, a.Z / b, a.W / b)
|
||||
let sum = Vector4.Divide(a, b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Property>]
|
||||
let ``Static Vector4-scalar divison method by reference is the same as component division`` (a : Vector4, b : float32) =
|
||||
if not (approxEq b 0.0f) then // we don't support diving by zero.
|
||||
let v1 = Vector4(a.X / b, a.Y / b, a.Z / b, a.W / b)
|
||||
let sum = Vector4.Divide(ref a, b)
|
||||
|
||||
Assert.ApproximatelyEquivalent(v1, sum)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Negation =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector negation operator negates all components`` (x, y, z, w) =
|
||||
let v = Vector4(x, y, z, w)
|
||||
let vNeg = -v
|
||||
Assert.Equal(-x, vNeg.X)
|
||||
Assert.Equal(-y, vNeg.Y)
|
||||
Assert.Equal(-z, vNeg.Z)
|
||||
Assert.Equal(-w, vNeg.W)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Equality =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector equality operator is by component`` (x, y, z, w) =
|
||||
let v1 = Vector4(x, y, z, w)
|
||||
let v2 = Vector4(x, y, z, w)
|
||||
let equality = v1 = v2
|
||||
|
||||
Assert.True(equality)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector inequality operator is by component`` (x, y, z, w) =
|
||||
let v1 = Vector4(x, y, z, w)
|
||||
let v2 = Vector4(x + 1.0f , y + 1.0f, z + 1.0f, w + 1.0f)
|
||||
let inequality = v1 <> v2
|
||||
|
||||
Assert.True(inequality)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector equality method is by component`` (x, y, z, w) =
|
||||
let v1 = Vector4(x, y, z, w)
|
||||
let v2 = Vector4(x, y, z, w)
|
||||
let notVector = Matrix2()
|
||||
|
||||
let equality = v1.Equals(v2)
|
||||
let inequalityByOtherType = v1.Equals(notVector)
|
||||
|
||||
Assert.True(equality)
|
||||
Assert.False(inequalityByOtherType)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector equality method returns false for other classes`` (x, y, z, w) =
|
||||
let v1 = Vector4(x, y, z, w)
|
||||
let notVector = Matrix2()
|
||||
|
||||
let inequalityByOtherType = v1.Equals(notVector)
|
||||
|
||||
Assert.False(inequalityByOtherType)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Swizzling =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Vector swizzling returns the correct composite for X-primary components`` (x, y, z, w) =
|
||||
|
||||
let v = Vector4(x, y, z, w)
|
||||
|
||||
let xyzw = v
|
||||
let xywz = Vector4(x, y, w, z)
|
||||
let xzyw = Vector4(x, z, y, w)
|
||||
let xzwy = Vector4(x, z, w, y)
|
||||
let xwyz = Vector4(x, w, y, z)
|
||||
let xwzy = Vector4(x, w, z, y)
|
||||
|
||||
let xyz = Vector3(x, y, z)
|
||||
let xyw = Vector3(x, y, w)
|
||||
let xzy = Vector3(x, z, y)
|
||||
let xzw = Vector3(x, z, w)
|
||||
let xwy = Vector3(x, w, y)
|
||||
let xwz = Vector3(x, w, z)
|
||||
|
||||
let xy = Vector2(x, y)
|
||||
let xz = Vector2(x, z)
|
||||
let xw = Vector2(x, w)
|
||||
|
||||
// X primary
|
||||
Assert.Equal(xyzw, v)
|
||||
Assert.Equal(xywz, v.Xywz)
|
||||
Assert.Equal(xzyw, v.Xzyw)
|
||||
Assert.Equal(xzwy, v.Xzwy)
|
||||
Assert.Equal(xwyz, v.Xwyz)
|
||||
Assert.Equal(xwzy, v.Xwzy)
|
||||
|
||||
Assert.Equal(xyz, v.Xyz)
|
||||
Assert.Equal(xyw, v.Xyw)
|
||||
Assert.Equal(xzy, v.Xzy)
|
||||
Assert.Equal(xzw, v.Xzw)
|
||||
Assert.Equal(xwy, v.Xwy)
|
||||
Assert.Equal(xwz, v.Xwz)
|
||||
|
||||
Assert.Equal(xy, v.Xy)
|
||||
Assert.Equal(xz, v.Xz)
|
||||
Assert.Equal(xw, v.Xw)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector swizzling returns the correct composite for Y-primary components`` (x, y, z, w) =
|
||||
|
||||
let v = Vector4(x, y, z, w)
|
||||
|
||||
let yxzw = Vector4(y, x, z, w)
|
||||
let yxwz = Vector4(y, x, w, z)
|
||||
let yyzw = Vector4(y, y, z, w)
|
||||
let yywz = Vector4(y, y, w, z)
|
||||
let yzxw = Vector4(y, z, x, w)
|
||||
let yzwx = Vector4(y, z, w, x)
|
||||
let ywxz = Vector4(y, w, x, z)
|
||||
let ywzx = Vector4(y, w, z, x)
|
||||
|
||||
let yxz = Vector3(y, x, z)
|
||||
let yxw = Vector3(y, x, w)
|
||||
let yzx = Vector3(y, z, x)
|
||||
let yzw = Vector3(y, z, w)
|
||||
let ywx = Vector3(y, w, x)
|
||||
let ywz = Vector3(y, w, z)
|
||||
|
||||
let yx = Vector2(y, x)
|
||||
let yz = Vector2(y, z)
|
||||
let yw = Vector2(y, w)
|
||||
|
||||
// Y primary
|
||||
Assert.Equal(yxzw, v.Yxzw)
|
||||
Assert.Equal(yxwz, v.Yxwz)
|
||||
Assert.Equal(yyzw, v.Yyzw)
|
||||
Assert.Equal(yywz, v.Yywz)
|
||||
Assert.Equal(yzxw, v.Yzxw)
|
||||
Assert.Equal(yzwx, v.Yzwx)
|
||||
Assert.Equal(ywxz, v.Ywxz)
|
||||
Assert.Equal(ywzx, v.Ywzx)
|
||||
|
||||
Assert.Equal(yxz, v.Yxz)
|
||||
Assert.Equal(yxw, v.Yxw)
|
||||
Assert.Equal(yzx, v.Yzx)
|
||||
Assert.Equal(yzw, v.Yzw)
|
||||
Assert.Equal(ywx, v.Ywx)
|
||||
Assert.Equal(ywz, v.Ywz)
|
||||
|
||||
Assert.Equal(yx, v.Yx)
|
||||
Assert.Equal(yz, v.Yz)
|
||||
Assert.Equal(yw, v.Yw)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector swizzling returns the correct composite for Z-primary components`` (x, y, z, w) =
|
||||
|
||||
let v = Vector4(x, y, z, w)
|
||||
|
||||
let zxyw = Vector4(z, x, y, w)
|
||||
let zxwy = Vector4(z, x, w, y)
|
||||
let zyxw = Vector4(z, y, x, w)
|
||||
let zywx = Vector4(z, y, w, x)
|
||||
let zwxy = Vector4(z, w, x, y)
|
||||
let zwyx = Vector4(z, w, y, x)
|
||||
let zwzy = Vector4(z, w, z, y)
|
||||
|
||||
let zxy = Vector3(z, x, y)
|
||||
let zxw = Vector3(z, x, w)
|
||||
let zyx = Vector3(z, y, x)
|
||||
let zyw = Vector3(z, y, w)
|
||||
let zwx = Vector3(z, w, x)
|
||||
let zwy = Vector3(z, w, y)
|
||||
|
||||
let zx = Vector2(z, x)
|
||||
let zy = Vector2(z, y)
|
||||
let zw = Vector2(z, w)
|
||||
|
||||
// Z primary
|
||||
Assert.Equal(zxyw, v.Zxyw)
|
||||
Assert.Equal(zxwy, v.Zxwy)
|
||||
Assert.Equal(zyxw, v.Zyxw)
|
||||
Assert.Equal(zywx, v.Zywx)
|
||||
Assert.Equal(zwxy, v.Zwxy)
|
||||
Assert.Equal(zwyx, v.Zwyx)
|
||||
Assert.Equal(zwzy, v.Zwzy)
|
||||
|
||||
Assert.Equal(zxy, v.Zxy)
|
||||
Assert.Equal(zxw, v.Zxw)
|
||||
Assert.Equal(zyx, v.Zyx)
|
||||
Assert.Equal(zyw, v.Zyw)
|
||||
Assert.Equal(zwx, v.Zwx)
|
||||
Assert.Equal(zwy, v.Zwy)
|
||||
|
||||
Assert.Equal(zx, v.Zx)
|
||||
Assert.Equal(zy, v.Zy)
|
||||
Assert.Equal(zw, v.Zw)
|
||||
|
||||
[<Property>]
|
||||
let ``Vector swizzling returns the correct composite for W-primary components`` (x, y, z, w) =
|
||||
|
||||
let v = Vector4(x, y, z, w)
|
||||
|
||||
let wxyz = Vector4(w, x, y, z)
|
||||
let wxzy = Vector4(w, x, z, y)
|
||||
let wyxz = Vector4(w, y, x, z)
|
||||
let wyzx = Vector4(w, y, z, x)
|
||||
let wzxy = Vector4(w, z, x, y)
|
||||
let wzyx = Vector4(w, z, y, x)
|
||||
let wzyw = Vector4(w, z, y, w)
|
||||
|
||||
let wxy = Vector3(w, x, y)
|
||||
let wxz = Vector3(w, x, z)
|
||||
let wyx = Vector3(w, y, x)
|
||||
let wyz = Vector3(w, y, z)
|
||||
let wzx = Vector3(w, z, x)
|
||||
let wzy = Vector3(w, z, y)
|
||||
|
||||
let wx = Vector2(w, x)
|
||||
let wy = Vector2(w, y)
|
||||
let wz = Vector2(w, z)
|
||||
|
||||
// W primary
|
||||
Assert.Equal(wxyz, v.Wxyz)
|
||||
Assert.Equal(wxzy, v.Wxzy)
|
||||
Assert.Equal(wyxz, v.Wyxz)
|
||||
Assert.Equal(wyzx, v.Wyzx)
|
||||
Assert.Equal(wzxy, v.Wzxy)
|
||||
Assert.Equal(wzyx, v.Wzyx)
|
||||
Assert.Equal(wzyw, v.Wzyw)
|
||||
|
||||
Assert.Equal(wxy, v.Wxy)
|
||||
Assert.Equal(wxz, v.Wxz)
|
||||
Assert.Equal(wyx, v.Wyx)
|
||||
Assert.Equal(wyz, v.Wyz)
|
||||
Assert.Equal(wzx, v.Wzx)
|
||||
Assert.Equal(wzy, v.Wzy)
|
||||
|
||||
Assert.Equal(wx, v.Wx)
|
||||
Assert.Equal(wy, v.Wy)
|
||||
Assert.Equal(wz, v.Wz)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Interpolation =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Linear interpolation is by component`` (a : Vector4, b : Vector4, q) =
|
||||
|
||||
let blend = q
|
||||
|
||||
let rX = blend * (b.X - a.X) + a.X
|
||||
let rY = blend * (b.Y - a.Y) + a.Y
|
||||
let rZ = blend * (b.Z - a.Z) + a.Z
|
||||
let rW = blend * (b.W - a.W) + a.W
|
||||
let vExp = Vector4(rX, rY, rZ, rW)
|
||||
|
||||
Assert.Equal(vExp, Vector4.Lerp(a, b, q))
|
||||
|
||||
let vRes = Vector4.Lerp(ref a, ref b, q)
|
||||
Assert.Equal(vExp, vRes)
|
||||
|
||||
[<Property>]
|
||||
let ``Barycentric interpolation follows the barycentric formula`` (a : Vector4, b : Vector4, c : Vector4, u, v) =
|
||||
|
||||
let r = a + u * (b - a) + v * (c - a)
|
||||
|
||||
Assert.Equal(r, Vector4.BaryCentric(a, b, c, u, v))
|
||||
|
||||
let vRes = Vector4.BaryCentric(ref a, ref b, ref c, u, v)
|
||||
Assert.Equal(r, vRes)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module ``Vector products`` =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Dot product method follows the dot product formula`` (a : Vector4, b : Vector4) =
|
||||
let dot = a.X * b.X + a.Y * b.Y + a.Z * b.Z + a.W * b.W
|
||||
|
||||
Assert.Equal(dot, Vector4.Dot(a, b));
|
||||
|
||||
let vRes = Vector4.Dot(ref a, ref b)
|
||||
Assert.Equal(dot, vRes)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module ``Magnitude min and max`` =
|
||||
//
|
||||
[<Property>]
|
||||
let ``MagnitudeMin selects the vector with equal or lesser magnitude given two vectors`` (v1 : Vector4, v2: Vector4) =
|
||||
// Results do not matter for equal vectors
|
||||
if not (v1 = v2) then
|
||||
let l1 = v1.LengthSquared
|
||||
let l2 = v2.LengthSquared
|
||||
|
||||
let vMin = Vector4.MagnitudeMin(v1, v2)
|
||||
|
||||
if vMin = v1 then
|
||||
let v1ShorterThanv2 = l1 < l2
|
||||
Assert.True(v1ShorterThanv2)
|
||||
else
|
||||
let v2ShorterThanOrEqualTov1 = l2 <= l1
|
||||
Assert.True(v2ShorterThanOrEqualTov1)
|
||||
|
||||
[<Property>]
|
||||
let ``MagnitudeMax selects the vector with equal or greater magnitude given two vectors`` (v1 : Vector4, v2: Vector4) =
|
||||
// Results do not matter for equal vectors
|
||||
if not (v1 = v2) then
|
||||
let l1 = v1.LengthSquared
|
||||
let l2 = v2.LengthSquared
|
||||
|
||||
let vMin = Vector4.MagnitudeMax(v1, v2)
|
||||
|
||||
if vMin = v1 then
|
||||
let v1LongerThanOrEqualTov2 = l1 >= l2
|
||||
Assert.True(v1LongerThanOrEqualTov2)
|
||||
else
|
||||
let v2LongerThanv1 = l2 > l1
|
||||
Assert.True(v2LongerThanv1)
|
||||
|
||||
[<Property>]
|
||||
let ``MagnitudeMin by reference selects the vector with equal or lesser magnitude given two vectors`` (v1 : Vector4, v2: Vector4) =
|
||||
// Results do not matter for equal vectors
|
||||
if not (v1 = v2) then
|
||||
let l1 = v1.LengthSquared
|
||||
let l2 = v2.LengthSquared
|
||||
|
||||
let vMin = Vector4.MagnitudeMin(ref v1, ref v2)
|
||||
|
||||
if vMin = v1 then
|
||||
let v1ShorterThanv2 = l1 < l2
|
||||
Assert.True(v1ShorterThanv2)
|
||||
else
|
||||
let v2ShorterThanOrEqualTov1 = l2 <= l1
|
||||
Assert.True(v2ShorterThanOrEqualTov1)
|
||||
|
||||
[<Property>]
|
||||
let ``MagnitudeMax by reference selects the vector with equal or greater magnitude given two vectors`` (v1 : Vector4, v2: Vector4) =
|
||||
// Results do not matter for equal vectors
|
||||
if not (v1 = v2) then
|
||||
let l1 = v1.LengthSquared
|
||||
let l2 = v2.LengthSquared
|
||||
|
||||
let vMin = Vector4.MagnitudeMax(ref v1, ref v2)
|
||||
|
||||
if vMin = v1 then
|
||||
let v1LongerThanOrEqualTov2 = l1 >= l2
|
||||
Assert.True(v1LongerThanOrEqualTov2)
|
||||
else
|
||||
let v2LongerThanv1 = l2 > l1
|
||||
Assert.True(v2LongerThanv1)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module ``Component min and max`` =
|
||||
//
|
||||
[<Property>]
|
||||
let ``ComponentMin creates a new vector from the smallest components of given vectors`` (v1 : Vector4, v2: Vector4) =
|
||||
let vMin = Vector4.ComponentMin(v1, v2)
|
||||
let isComponentSmallest smallComp comp1 comp2 = smallComp <= comp1 && smallComp <= comp2
|
||||
|
||||
Assert.True(isComponentSmallest vMin.X v1.X v2.X)
|
||||
Assert.True(isComponentSmallest vMin.Y v1.Y v2.Y)
|
||||
Assert.True(isComponentSmallest vMin.Z v1.Z v2.Z)
|
||||
Assert.True(isComponentSmallest vMin.W v1.W v2.W)
|
||||
|
||||
[<Property>]
|
||||
let ``ComponentMax creates a new vector from the greatest components of given vectors`` (v1 : Vector4, v2: Vector4) =
|
||||
let vMax = Vector4.ComponentMax(v1, v2)
|
||||
let isComponentLargest largeComp comp1 comp2 = largeComp >= comp1 && largeComp >= comp2
|
||||
|
||||
Assert.True(isComponentLargest vMax.X v1.X v2.X)
|
||||
Assert.True(isComponentLargest vMax.Y v1.Y v2.Y)
|
||||
Assert.True(isComponentLargest vMax.Z v1.Z v2.Z)
|
||||
Assert.True(isComponentLargest vMax.W v1.W v2.W)
|
||||
|
||||
[<Property>]
|
||||
let ``ComponentMin by reference creates a new vector from the smallest components of given vectors`` (v1 : Vector4, v2: Vector4) =
|
||||
let vMin = Vector4.ComponentMin(ref v1, ref v2)
|
||||
let isComponentSmallest smallComp comp1 comp2 = smallComp <= comp1 && smallComp <= comp2
|
||||
|
||||
Assert.True(isComponentSmallest vMin.X v1.X v2.X)
|
||||
Assert.True(isComponentSmallest vMin.Y v1.Y v2.Y)
|
||||
Assert.True(isComponentSmallest vMin.Z v1.Z v2.Z)
|
||||
Assert.True(isComponentSmallest vMin.W v1.W v2.W)
|
||||
|
||||
[<Property>]
|
||||
let ``ComponentMax by reference creates a new vector from the greatest components of given vectors`` (v1 : Vector4, v2: Vector4) =
|
||||
let vMax = Vector4.ComponentMax(ref v1, ref v2)
|
||||
let isComponentLargest largeComp comp1 comp2 = largeComp >= comp1 && largeComp >= comp2
|
||||
|
||||
Assert.True(isComponentLargest vMax.X v1.X v2.X)
|
||||
Assert.True(isComponentLargest vMax.Y v1.Y v2.Y)
|
||||
Assert.True(isComponentLargest vMax.Z v1.Z v2.Z)
|
||||
Assert.True(isComponentLargest vMax.W v1.W v2.W)
|
||||
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Clamping =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Clamping one vector between two other vectors clamps all components between corresponding components`` (a : Vector4, b : Vector4, w : Vector4) =
|
||||
let expX = if w.X < a.X then a.X else if w.X > b.X then b.X else w.X
|
||||
let expY = if w.Y < a.Y then a.Y else if w.Y > b.Y then b.Y else w.Y
|
||||
let expZ = if w.Z < a.Z then a.Z else if w.Z > b.Z then b.Z else w.Z
|
||||
let expW = if w.W < a.W then a.W else if w.W > b.W then b.W else w.W
|
||||
|
||||
let res = Vector4.Clamp(w, a, b)
|
||||
|
||||
Assert.Equal(expX, res.X)
|
||||
Assert.Equal(expY, res.Y)
|
||||
Assert.Equal(expZ, res.Z)
|
||||
Assert.Equal(expW, res.W)
|
||||
|
||||
[<Property>]
|
||||
let ``Clamping one vector between two other vectors by reference clamps all components between corresponding components`` (a : Vector4, b : Vector4, w : Vector4) =
|
||||
let expX = if w.X < a.X then a.X else if w.X > b.X then b.X else w.X
|
||||
let expY = if w.Y < a.Y then a.Y else if w.Y > b.Y then b.Y else w.Y
|
||||
let expZ = if w.Z < a.Z then a.Z else if w.Z > b.Z then b.Z else w.Z
|
||||
let expW = if w.W < a.W then a.W else if w.W > b.W then b.W else w.W
|
||||
|
||||
let res = Vector4.Clamp(ref w, ref a, ref b)
|
||||
|
||||
Assert.Equal(expX, res.X)
|
||||
Assert.Equal(expY, res.Y)
|
||||
Assert.Equal(expZ, res.Z)
|
||||
Assert.Equal(expW, res.W)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module ``Unit vectors``=
|
||||
//
|
||||
[<Property>]
|
||||
let ``Unit X is correct`` =
|
||||
let unitX = Vector4(1.0f, 0.0f, 0.0f, 0.0f)
|
||||
|
||||
Assert.Equal(Vector4.UnitX, unitX)
|
||||
|
||||
[<Property>]
|
||||
let ``Unit Y is correct`` =
|
||||
let unitY = Vector4(0.0f, 1.0f, 0.0f, 0.0f)
|
||||
|
||||
Assert.Equal(Vector4.UnitY, unitY)
|
||||
|
||||
[<Property>]
|
||||
let ``Unit Z is correct`` =
|
||||
let unitZ = Vector4(0.0f, 0.0f, 1.0f, 0.0f)
|
||||
|
||||
Assert.Equal(Vector4.UnitZ, unitZ)
|
||||
|
||||
[<Property>]
|
||||
let ``Unit W is correct`` =
|
||||
let unitW = Vector4(0.0f, 0.0f, 0.0f, 1.0f)
|
||||
|
||||
Assert.Equal(Vector4.UnitW, unitW)
|
||||
|
||||
[<Property>]
|
||||
let ``Unit zero is correct`` =
|
||||
let unitZero = Vector4(0.0f, 0.0f, 0.0f, 0.0f)
|
||||
|
||||
Assert.Equal(Vector4.Zero, unitZero)
|
||||
|
||||
[<Property>]
|
||||
let ``Unit one is correct`` =
|
||||
let unitOne = Vector4(1.0f, 1.0f, 1.0f, 1.0f)
|
||||
|
||||
Assert.Equal(Vector4.One, unitOne)
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Serialization =
|
||||
//
|
||||
[<Property>]
|
||||
let ``The absolute size of a Vector4 is always the size of its components`` (v : Vector4) =
|
||||
let expectedSize = sizeof<float32> * 4
|
||||
|
||||
Assert.Equal(expectedSize, Vector4.SizeInBytes)
|
||||
Assert.Equal(expectedSize, Marshal.SizeOf(Vector4()))
|
||||
|
||||
[<Properties(Arbitrary = [| typeof<OpenTKGen> |])>]
|
||||
module Transformation =
|
||||
//
|
||||
[<Property>]
|
||||
let ``Transformation by quaternion with static method is the same as multiplication by quaternion and its conjugate`` (v : Vector4, q : Quaternion) =
|
||||
let vectorQuat = Quaternion(v.X, v.Y, v.Z, v.W)
|
||||
let inverse = Quaternion.Invert(q)
|
||||
|
||||
let transformedQuat = q * vectorQuat * inverse
|
||||
let transformedVector = Vector4(transformedQuat.X, transformedQuat.Y, transformedQuat.Z, transformedQuat.W)
|
||||
|
||||
Assert.ApproximatelyEquivalent(transformedVector, Vector4.Transform(v, q))
|
||||
|
||||
[<Property>]
|
||||
let ``Transformation by quaternion with static method by reference is the same as multiplication by quaternion and its conjugate`` (v : Vector4, q : Quaternion) =
|
||||
let vectorQuat = Quaternion(v.X, v.Y, v.Z, v.W)
|
||||
let inverse = Quaternion.Invert(q)
|
||||
|
||||
let transformedQuat = q * vectorQuat * inverse
|
||||
let transformedVector = Vector4(transformedQuat.X, transformedQuat.Y,transformedQuat.Z, transformedQuat.W)
|
||||
|
||||
Assert.ApproximatelyEquivalent(transformedVector, Vector4.Transform(ref v, ref q))
|
||||
|
||||
[<Property>]
|
||||
let ``Transformation by quaternion by multiplication using right-handed notation is the same as multiplication by quaternion and its conjugate`` (v : Vector4, q : Quaternion) =
|
||||
let vectorQuat = Quaternion(v.X, v.Y, v.Z, v.W)
|
||||
let inverse = Quaternion.Invert(q)
|
||||
|
||||
let transformedQuat = q * vectorQuat * inverse
|
||||
let transformedVector = Vector4(transformedQuat.X, transformedQuat.Y, transformedQuat.Z, transformedQuat.W)
|
||||
|
||||
Assert.ApproximatelyEquivalent(transformedVector, q * v)
|
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="NUnit" version="2.6.4" targetFramework="net45" />
|
||||
<package id="NUnitTestAdapter" version="2.0.0" targetFramework="net45" />
|
||||
</packages>
|
2
tests/OpenTK.Tests/paket.references
Normal file
2
tests/OpenTK.Tests/paket.references
Normal file
|
@ -0,0 +1,2 @@
|
|||
FsCheck.Xunit
|
||||
xunit.assert
|
Loading…
Reference in a new issue