diff --git a/SharpDX.sln b/SharpDX.sln index ba3ca8796..4bf89782f 100644 --- a/SharpDX.sln +++ b/SharpDX.sln @@ -1,1013 +1,1197 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.30324.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sources", "Sources", "{CC8DB471-0644-430D-9D4B-808A2475BEC0}" - ProjectSection(SolutionItems) = preProject - Source\Mapping.Direct3D1x.xml = Source\Mapping.Direct3D1x.xml - Source\Mapping.xml = Source\Mapping.xml - Source\SharedAssemblyInfo.cs = Source\SharedAssemblyInfo.cs - Source\SharedAssemblyInfo.cs = Source\SharedAssemblyInfo.cs - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{F1AF9A3B-7856-46C9-992A-391E5455BF1F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX", "Source\SharpDX\SharpDX.csproj", "{D0BCD56A-41C4-4A4E-8590-26864CED07FF}" - ProjectSection(ProjectDependencies) = postProject - {31F85A16-CB01-4456-BE3C-76E9FF3A1343} = {31F85A16-CB01-4456-BE3C-76E9FF3A1343} - {4E2D9A17-2195-4A51-AAE3-924517440293} = {4E2D9A17-2195-4A51-AAE3-924517440293} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.D3DCompiler", "Source\SharpDX.D3DCompiler\SharpDX.D3DCompiler.csproj", "{361D3F81-A48A-47F2-80DF-CA4F9536CB4E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Direct2D1", "Source\SharpDX.Direct2D1\SharpDX.Direct2D1.csproj", "{C97878F4-1510-4BBA-8153-BD71DA7D50D8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Direct3D10", "Source\SharpDX.Direct3D10\SharpDX.Direct3D10.csproj", "{618AFA87-81A8-4B1C-8876-5457D49F2DEF}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Direct3D11", "Source\SharpDX.Direct3D11\SharpDX.Direct3D11.csproj", "{736DFB52-1AFE-4EFF-9710-89046AB5B1F9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.DirectSound", "Source\SharpDX.DirectSound\SharpDX.DirectSound.csproj", "{E927F2D5-8E27-462A-8687-CB207EE01164}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.DXGI", "Source\SharpDX.DXGI\SharpDX.DXGI.csproj", "{3FC6DE77-B412-4101-9E64-6B9AA831179B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.XAudio2", "Source\SharpDX.XAudio2\SharpDX.XAudio2.csproj", "{4995127E-0B8E-45B8-80C4-6BAC1BBE3783}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Direct3D9", "Source\SharpDX.Direct3D9\SharpDX.Direct3D9.csproj", "{B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.DirectInput", "Source\SharpDX.DirectInput\SharpDX.DirectInput.csproj", "{112F146B-7C01-490B-B943-EA9341ACCAF2}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SharpDX.WP8", "Source\SharpDX.WP8\SharpDX.WP8.vcxproj", "{C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpCli", "Source\Tools\SharpCli\SharpCli.csproj", "{4E2D9A17-2195-4A51-AAE3-924517440293}" - ProjectSection(ProjectDependencies) = postProject - {5E597A82-9DE9-4BA5-AD76-51202190E951} = {5E597A82-9DE9-4BA5-AD76-51202190E951} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpGen", "Source\Tools\SharpGen\SharpGen.csproj", "{31F85A16-CB01-4456-BE3C-76E9FF3A1343}" - ProjectSection(ProjectDependencies) = postProject - {5E597A82-9DE9-4BA5-AD76-51202190E951} = {5E597A82-9DE9-4BA5-AD76-51202190E951} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpPak", "Source\Tools\SharpPak\SharpPak.csproj", "{5E597A82-9DE9-4BA5-AD76-51202190E951}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Documentation", "Documentation\Documentation.csproj", "{9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{57C5C966-ADB2-43F2-BB54-99BCB56C9F10}" - ProjectSection(SolutionItems) = preProject - ChangeLog.txt = ChangeLog.txt - README.markdown = README.markdown - ReleaseNotes.html = ReleaseNotes.html - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{1B526C0E-EE4A-4E8F-BF8F-8C7397FB4918}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.XACT3", "Source\SharpDX.XACT3\SharpDX.XACT3.csproj", "{4939860C-5D5B-4D56-89C8-1980A9EBB392}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.RawInput", "Source\SharpDX.RawInput\SharpDX.RawInput.csproj", "{05D17A7B-F200-48C0-B8F9-B7211665A17F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.XInput", "Source\SharpDX.XInput\SharpDX.XInput.csproj", "{764D7CE5-F78B-432E-A849-E40BA44522D6}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{E462D87D-C180-4114-B8C8-914E6735BF44}" - ProjectSection(SolutionItems) = preProject - Source\Install.ps1 = Source\Install.ps1 - Build\SharpDX.build = Build\SharpDX.build - Build\SharpDX.PostSettings.targets = Build\SharpDX.PostSettings.targets - Build\SharpDX.PreSettings.targets = Build\SharpDX.PreSettings.targets - Build\SharpDX.targets = Build\SharpDX.targets - Build\SharpDX.Toolkit.targets = Build\SharpDX.Toolkit.targets - Source\uninstall.ps1 = Source\uninstall.ps1 - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Tests", "Source\Tests\SharpDX.Tests\SharpDX.Tests.csproj", "{931FA266-E756-41CA-9736-8B29235DC999}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Animation", "Source\SharpDX.Animation\SharpDX.Animation.csproj", "{874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.MediaFoundation", "Source\SharpDX.MediaFoundation\SharpDX.MediaFoundation.csproj", "{CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Direct3D11.Effects", "Source\SharpDX.Direct3D11.Effects\SharpDX.Direct3D11.Effects.csproj", "{BBB50A46-3291-4C62-B884-D1AB64F71EA5}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Toolkit", "Toolkit", "{529B140D-B91D-49EA-B173-9ADD6AB2A2A3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Toolkit.Graphics", "Source\Toolkit\SharpDX.Toolkit.Graphics\SharpDX.Toolkit.Graphics.csproj", "{53EF08A7-4224-434C-A62C-F29807C1C750}" - ProjectSection(ProjectDependencies) = postProject - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702} = {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702} - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8} = {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Toolkit.Graphics.Tests", "Source\Tests\SharpDX.Toolkit.Graphics.Tests\SharpDX.Toolkit.Graphics.Tests.csproj", "{4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Toolkit", "Source\Toolkit\SharpDX.Toolkit\SharpDX.Toolkit.csproj", "{9FF0707C-75BB-4984-A01F-B9EAAD293F6C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Toolkit.Compiler", "Source\Toolkit\SharpDX.Toolkit.Compiler\SharpDX.Toolkit.Compiler.csproj", "{8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tkfxc", "Source\Toolkit\tkfxc\tkfxc.csproj", "{BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpGitLog", "Source\Tools\SharpGitLog\SharpGitLog.csproj", "{15BA35B5-3E54-4715-8857-36F4F96F51FB}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tkfont", "Source\Toolkit\tkfont\tkfont.csproj", "{7329B02D-C504-482A-A156-181D48CE493C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Toolkit.Game", "Source\Toolkit\SharpDX.Toolkit.Game\SharpDX.Toolkit.Game.csproj", "{B2516A23-1A99-4263-964A-B820FD07FA80}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Toolkit.Input", "Source\Toolkit\SharpDX.Toolkit.Input\SharpDX.Toolkit.Input.csproj", "{46452614-6B06-400F-A74C-1632C79B762C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Toolkit.CompilerTask", "Source\Toolkit\SharpDX.Toolkit.CompilerTask\SharpDX.Toolkit.CompilerTask.csproj", "{90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tkmodel", "Source\Toolkit\tkmodel\tkmodel.csproj", "{76FD0713-F217-4485-89B3-C6423DB46C58}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Toolkit.Yaml", "Source\Toolkit\SharpDX.Toolkit.Yaml\SharpDX.Toolkit.Yaml.csproj", "{ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Toolkit.Audio", "Source\Toolkit\SharpDX.Toolkit.Audio\SharpDX.Toolkit.Audio.csproj", "{1FA327C8-6C48-4FFC-9235-B98B7521B79D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.DirectComposition", "Source\SharpDX.DirectComposition\SharpDX.DirectComposition.csproj", "{FBE5DD99-00A0-4FED-A116-941A46A0C0D0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.DirectManipulation", "Source\SharpDX.DirectManipulation\SharpDX.DirectManipulation.csproj", "{F826CCCE-4B72-47F4-9493-DFCB51C106B7}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|DIRECTX11_2 = Debug|DIRECTX11_2 - Debug|Net20 = Debug|Net20 - Debug|Net40 = Debug|Net40 - Debug|Win8 = Debug|Win8 - Debug|WP81 = Debug|WP81 - Debug|WP8-ARM = Debug|WP8-ARM - Debug|WP8-x86 = Debug|WP8-x86 - Release|DIRECTX11_2 = Release|DIRECTX11_2 - Release|Net20 = Release|Net20 - Release|Net40 = Release|Net40 - Release|Win8 = Release|Win8 - Release|WP81 = Release|WP81 - Release|WP8-ARM = Release|WP8-ARM - Release|WP8-x86 = Release|WP8-x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|Net20.ActiveCfg = Debug|Net20 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|Net20.Build.0 = Debug|Net20 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|Net40.ActiveCfg = Debug|Net40 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|Net40.Build.0 = Debug|Net40 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|Win8.ActiveCfg = Debug|Win8 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|Win8.Build.0 = Debug|Win8 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|WP81.ActiveCfg = Debug|WP81 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|WP81.Build.0 = Debug|WP81 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|Net20.ActiveCfg = Release|Net20 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|Net20.Build.0 = Release|Net20 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|Net40.ActiveCfg = Release|Net40 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|Net40.Build.0 = Release|Net40 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|Win8.ActiveCfg = Release|Win8 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|Win8.Build.0 = Release|Win8 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|WP81.ActiveCfg = Release|WP81 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|WP81.Build.0 = Release|WP81 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|WP8-ARM.Build.0 = Release|WP8-ARM - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|WP8-x86.Build.0 = Release|WP8-x86 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|Net20.ActiveCfg = Debug|Net20 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|Net20.Build.0 = Debug|Net20 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|Net40.ActiveCfg = Debug|Net40 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|Net40.Build.0 = Debug|Net40 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|Win8.ActiveCfg = Debug|Win8 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|Win8.Build.0 = Debug|Win8 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|WP81.ActiveCfg = Debug|WP81 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|WP81.Build.0 = Debug|WP81 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|Net20.ActiveCfg = Release|Net20 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|Net20.Build.0 = Release|Net20 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|Net40.ActiveCfg = Release|Net40 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|Net40.Build.0 = Release|Net40 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|Win8.ActiveCfg = Release|Win8 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|Win8.Build.0 = Release|Win8 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|WP81.ActiveCfg = Release|WP81 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|WP81.Build.0 = Release|WP81 - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|Net20.ActiveCfg = Debug|Net20 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|Net20.Build.0 = Debug|Net20 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|Net40.ActiveCfg = Debug|Net40 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|Net40.Build.0 = Debug|Net40 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|Win8.ActiveCfg = Debug|Win8 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|Win8.Build.0 = Debug|Win8 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|WP81.ActiveCfg = Debug|WP81 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|WP81.Build.0 = Debug|WP81 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|Net20.ActiveCfg = Release|Net20 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|Net20.Build.0 = Release|Net20 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|Net40.ActiveCfg = Release|Net40 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|Net40.Build.0 = Release|Net40 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|Win8.ActiveCfg = Release|Win8 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|Win8.Build.0 = Release|Win8 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|WP81.ActiveCfg = Release|WP81 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|WP81.Build.0 = Release|WP81 - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|Net20.ActiveCfg = Debug|Net20 - {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|Net20.Build.0 = Debug|Net20 - {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|Net40.ActiveCfg = Debug|Net40 - {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|Net40.Build.0 = Debug|Net40 - {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|Win8.ActiveCfg = Debug|Win8 - {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|WP81.ActiveCfg = Debug|WP81 - {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|Net20.ActiveCfg = Release|Net20 - {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|Net20.Build.0 = Release|Net20 - {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|Net40.ActiveCfg = Release|Net40 - {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|Net40.Build.0 = Release|Net40 - {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|Win8.ActiveCfg = Release|Win8 - {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|WP81.ActiveCfg = Release|WP81 - {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|Net20.ActiveCfg = Debug|Net20 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|Net20.Build.0 = Debug|Net20 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|Net40.ActiveCfg = Debug|Net40 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|Net40.Build.0 = Debug|Net40 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|Win8.ActiveCfg = Debug|Win8 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|Win8.Build.0 = Debug|Win8 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|WP81.ActiveCfg = Debug|WP81 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|WP81.Build.0 = Debug|WP81 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|Net20.ActiveCfg = Release|Net20 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|Net20.Build.0 = Release|Net20 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|Net40.ActiveCfg = Release|Net40 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|Net40.Build.0 = Release|Net40 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|Win8.ActiveCfg = Release|Win8 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|Win8.Build.0 = Release|Win8 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|WP81.ActiveCfg = Release|WP81 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|WP81.Build.0 = Release|WP81 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|WP8-ARM.Build.0 = Release|WP8-ARM - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|WP8-x86.Build.0 = Release|WP8-x86 - {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|Net20.ActiveCfg = Debug|Net20 - {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|Net20.Build.0 = Debug|Net20 - {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|Net40.ActiveCfg = Debug|Net40 - {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|Net40.Build.0 = Debug|Net40 - {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|Win8.ActiveCfg = Debug|Win8 - {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|WP81.ActiveCfg = Debug|WP81 - {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|Net20.ActiveCfg = Release|Net20 - {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|Net20.Build.0 = Release|Net20 - {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|Net40.ActiveCfg = Release|Net40 - {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|Net40.Build.0 = Release|Net40 - {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|Win8.ActiveCfg = Release|Win8 - {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|WP81.ActiveCfg = Release|WP81 - {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|Net20.ActiveCfg = Debug|Net20 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|Net20.Build.0 = Debug|Net20 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|Net40.ActiveCfg = Debug|Net40 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|Net40.Build.0 = Debug|Net40 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|Win8.ActiveCfg = Debug|Win8 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|Win8.Build.0 = Debug|Win8 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|WP81.ActiveCfg = Debug|WP81 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|WP81.Build.0 = Debug|WP81 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|Net20.ActiveCfg = Release|Net20 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|Net20.Build.0 = Release|Net20 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|Net40.ActiveCfg = Release|Net40 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|Net40.Build.0 = Release|Net40 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|Win8.ActiveCfg = Release|Win8 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|Win8.Build.0 = Release|Win8 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|WP81.ActiveCfg = Release|WP81 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|WP81.Build.0 = Release|WP81 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|WP8-ARM.Build.0 = Release|WP8-ARM - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|WP8-x86.Build.0 = Release|WP8-x86 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|Net20.ActiveCfg = Debug|Net20 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|Net20.Build.0 = Debug|Net20 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|Net40.ActiveCfg = Debug|Net40 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|Net40.Build.0 = Debug|Net40 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|Win8.ActiveCfg = Debug|Win8 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|Win8.Build.0 = Debug|Win8 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|WP81.ActiveCfg = Debug|WP81 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|WP81.Build.0 = Debug|WP81 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|Net20.ActiveCfg = Release|Net20 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|Net20.Build.0 = Release|Net20 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|Net40.ActiveCfg = Release|Net40 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|Net40.Build.0 = Release|Net40 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|Win8.ActiveCfg = Release|Win8 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|Win8.Build.0 = Release|Win8 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|WP81.ActiveCfg = Release|WP81 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|WP81.Build.0 = Release|WP81 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|WP8-ARM.Build.0 = Release|WP8-ARM - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|WP8-x86.Build.0 = Release|WP8-x86 - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|Net20.ActiveCfg = Debug|Net20 - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|Net20.Build.0 = Debug|Net20 - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|Net40.ActiveCfg = Debug|Net40 - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|Net40.Build.0 = Debug|Net40 - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|Win8.ActiveCfg = Debug|Win8 - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|WP81.ActiveCfg = Debug|WP81 - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|Net20.ActiveCfg = Release|Net20 - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|Net20.Build.0 = Release|Net20 - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|Net40.ActiveCfg = Release|Net40 - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|Net40.Build.0 = Release|Net40 - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|Win8.ActiveCfg = Release|Win8 - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|WP81.ActiveCfg = Release|WP81 - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|Net20.ActiveCfg = Debug|Net20 - {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|Net20.Build.0 = Debug|Net20 - {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|Net40.ActiveCfg = Debug|Net40 - {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|Net40.Build.0 = Debug|Net40 - {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|Win8.ActiveCfg = Debug|Win8 - {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|WP81.ActiveCfg = Debug|WP81 - {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|Net20.ActiveCfg = Release|Net20 - {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|Net20.Build.0 = Release|Net20 - {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|Net40.ActiveCfg = Release|Net40 - {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|Net40.Build.0 = Release|Net40 - {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|Win8.ActiveCfg = Release|Win8 - {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|WP81.ActiveCfg = Release|WP81 - {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|DIRECTX11_2.ActiveCfg = Debug|Win32 - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|Net20.ActiveCfg = Debug|Win32 - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|Net40.ActiveCfg = Debug|Win32 - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|Win8.ActiveCfg = Debug|Win32 - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|WP81.ActiveCfg = Debug|Win32 - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|WP8-ARM.ActiveCfg = Debug|ARM - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|WP8-ARM.Build.0 = Debug|ARM - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|WP8-x86.ActiveCfg = Debug|Win32 - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|WP8-x86.Build.0 = Debug|Win32 - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|DIRECTX11_2.ActiveCfg = Release|Win32 - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|Net20.ActiveCfg = Release|Win32 - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|Net40.ActiveCfg = Release|Win32 - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|Win8.ActiveCfg = Release|Win32 - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|WP81.ActiveCfg = Release|Win32 - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|WP8-ARM.ActiveCfg = Release|ARM - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|WP8-ARM.Build.0 = Release|ARM - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|WP8-x86.ActiveCfg = Release|Win32 - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|WP8-x86.Build.0 = Release|Win32 - {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|DIRECTX11_2.ActiveCfg = Debug|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|DIRECTX11_2.Build.0 = Debug|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|Net20.ActiveCfg = Debug|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|Net20.Build.0 = Debug|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|Net40.ActiveCfg = Debug|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|Net40.Build.0 = Debug|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|Win8.ActiveCfg = Debug|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|WP81.ActiveCfg = Debug|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|WP81.Build.0 = Debug|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|WP8-ARM.ActiveCfg = Debug|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|WP8-ARM.Build.0 = Debug|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|WP8-x86.ActiveCfg = Debug|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|WP8-x86.Build.0 = Debug|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|DIRECTX11_2.ActiveCfg = Release|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|DIRECTX11_2.Build.0 = Release|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|Net20.ActiveCfg = Release|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|Net20.Build.0 = Release|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|Net40.ActiveCfg = Release|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|Net40.Build.0 = Release|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|Win8.ActiveCfg = Release|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|Win8.Build.0 = Release|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|WP81.ActiveCfg = Release|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|WP81.Build.0 = Release|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|WP8-ARM.ActiveCfg = Release|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|WP8-ARM.Build.0 = Release|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|WP8-x86.ActiveCfg = Release|Any CPU - {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|WP8-x86.Build.0 = Release|Any CPU - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|Net20.ActiveCfg = Debug|Net20 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|Net20.Build.0 = Debug|Net20 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|Net40.ActiveCfg = Debug|Net40 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|Net40.Build.0 = Debug|Net40 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|Win8.ActiveCfg = Debug|Win8 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|Win8.Build.0 = Debug|Win8 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|WP81.ActiveCfg = Debug|WP81 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|WP81.Build.0 = Debug|WP81 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|Net20.ActiveCfg = Release|Net20 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|Net20.Build.0 = Release|Net20 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|Net40.ActiveCfg = Release|Net40 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|Net40.Build.0 = Release|Net40 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|Win8.ActiveCfg = Release|Win8 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|Win8.Build.0 = Release|Win8 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|WP81.ActiveCfg = Release|WP81 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|WP81.Build.0 = Release|WP81 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|WP8-ARM.Build.0 = Release|WP8-ARM - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|WP8-x86.Build.0 = Release|WP8-x86 - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|DIRECTX11_2.ActiveCfg = Debug|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|DIRECTX11_2.Build.0 = Debug|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|Net20.ActiveCfg = Debug|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|Net20.Build.0 = Debug|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|Net40.ActiveCfg = Debug|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|Net40.Build.0 = Debug|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|Win8.ActiveCfg = Debug|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|WP81.ActiveCfg = Debug|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|WP81.Build.0 = Debug|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|WP8-ARM.ActiveCfg = Debug|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|WP8-x86.ActiveCfg = Debug|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|DIRECTX11_2.ActiveCfg = Release|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|DIRECTX11_2.Build.0 = Release|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|Net20.ActiveCfg = Release|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|Net20.Build.0 = Release|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|Net40.ActiveCfg = Release|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|Net40.Build.0 = Release|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|Win8.ActiveCfg = Release|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|Win8.Build.0 = Release|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|WP81.ActiveCfg = Release|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|WP81.Build.0 = Release|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|WP8-ARM.ActiveCfg = Release|Any CPU - {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|WP8-x86.ActiveCfg = Release|Any CPU - {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Debug|DIRECTX11_2.ActiveCfg = Debug|Any CPU - {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Debug|Net20.ActiveCfg = Debug|Any CPU - {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Debug|Net40.ActiveCfg = Debug|Any CPU - {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Debug|Win8.ActiveCfg = Debug|Any CPU - {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Debug|WP81.ActiveCfg = Debug|Any CPU - {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Debug|WP8-ARM.ActiveCfg = Debug|Any CPU - {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Debug|WP8-x86.ActiveCfg = Debug|Any CPU - {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Release|DIRECTX11_2.ActiveCfg = Release|Any CPU - {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Release|Net20.ActiveCfg = Release|Any CPU - {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Release|Net40.ActiveCfg = Release|Any CPU - {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Release|Win8.ActiveCfg = Release|Any CPU - {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Release|WP81.ActiveCfg = Release|Any CPU - {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Release|WP8-ARM.ActiveCfg = Release|Any CPU - {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Release|WP8-x86.ActiveCfg = Release|Any CPU - {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|Net20.ActiveCfg = Debug|Net20 - {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|Net20.Build.0 = Debug|Net20 - {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|Net40.ActiveCfg = Debug|Net40 - {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|Net40.Build.0 = Debug|Net40 - {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|Win8.ActiveCfg = Debug|Win8 - {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|WP81.ActiveCfg = Debug|WP81 - {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|Net20.ActiveCfg = Release|Net20 - {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|Net20.Build.0 = Release|Net20 - {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|Net40.ActiveCfg = Release|Net40 - {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|Net40.Build.0 = Release|Net40 - {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|Win8.ActiveCfg = Release|Win8 - {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|WP81.ActiveCfg = Release|WP81 - {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|Net20.ActiveCfg = Debug|Net20 - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|Net20.Build.0 = Debug|Net20 - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|Net40.ActiveCfg = Debug|Net40 - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|Net40.Build.0 = Debug|Net40 - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|Win8.ActiveCfg = Debug|Win8 - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|WP81.ActiveCfg = Debug|WP81 - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|Net20.ActiveCfg = Release|Net20 - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|Net20.Build.0 = Release|Net20 - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|Net40.ActiveCfg = Release|Net40 - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|Net40.Build.0 = Release|Net40 - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|Win8.ActiveCfg = Release|Win8 - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|WP81.ActiveCfg = Release|WP81 - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|Net20.ActiveCfg = Debug|Net20 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|Net20.Build.0 = Debug|Net20 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|Net40.ActiveCfg = Debug|Net40 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|Net40.Build.0 = Debug|Net40 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|Win8.ActiveCfg = Debug|Win8 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|Win8.Build.0 = Debug|Win8 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|WP81.ActiveCfg = Debug|WP81 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|Net20.ActiveCfg = Release|Net20 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|Net20.Build.0 = Release|Net20 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|Net40.ActiveCfg = Release|Net40 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|Net40.Build.0 = Release|Net40 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|Win8.ActiveCfg = Release|Win8 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|Win8.Build.0 = Release|Win8 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|WP81.ActiveCfg = Release|WP81 - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {931FA266-E756-41CA-9736-8B29235DC999}.Debug|DIRECTX11_2.ActiveCfg = Debug|Any CPU - {931FA266-E756-41CA-9736-8B29235DC999}.Debug|DIRECTX11_2.Build.0 = Debug|Any CPU - {931FA266-E756-41CA-9736-8B29235DC999}.Debug|Net20.ActiveCfg = Debug|Any CPU - {931FA266-E756-41CA-9736-8B29235DC999}.Debug|Net20.Build.0 = Debug|Any CPU - {931FA266-E756-41CA-9736-8B29235DC999}.Debug|Net40.ActiveCfg = Debug|Any CPU - {931FA266-E756-41CA-9736-8B29235DC999}.Debug|Net40.Build.0 = Debug|Any CPU - {931FA266-E756-41CA-9736-8B29235DC999}.Debug|Win8.ActiveCfg = Debug|Any CPU - {931FA266-E756-41CA-9736-8B29235DC999}.Debug|WP81.ActiveCfg = Debug|Any CPU - {931FA266-E756-41CA-9736-8B29235DC999}.Debug|WP8-ARM.ActiveCfg = Debug|Any CPU - {931FA266-E756-41CA-9736-8B29235DC999}.Debug|WP8-x86.ActiveCfg = Debug|Any CPU - {931FA266-E756-41CA-9736-8B29235DC999}.Release|DIRECTX11_2.ActiveCfg = Release|Any CPU - {931FA266-E756-41CA-9736-8B29235DC999}.Release|Net20.ActiveCfg = Release|Any CPU - {931FA266-E756-41CA-9736-8B29235DC999}.Release|Net40.ActiveCfg = Release|Any CPU - {931FA266-E756-41CA-9736-8B29235DC999}.Release|Win8.ActiveCfg = Release|Any CPU - {931FA266-E756-41CA-9736-8B29235DC999}.Release|WP81.ActiveCfg = Release|Any CPU - {931FA266-E756-41CA-9736-8B29235DC999}.Release|WP8-ARM.ActiveCfg = Release|Any CPU - {931FA266-E756-41CA-9736-8B29235DC999}.Release|WP8-x86.ActiveCfg = Release|Any CPU - {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Debug|Net20.ActiveCfg = Debug|Net20 - {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Debug|Net20.Build.0 = Debug|Net20 - {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Debug|Net40.ActiveCfg = Debug|Net40 - {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Debug|Win8.ActiveCfg = Debug|Win8 - {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Debug|WP81.ActiveCfg = Debug|WP81 - {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Release|Net20.ActiveCfg = Release|Net20 - {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Release|Net40.ActiveCfg = Release|Net40 - {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Release|Win8.ActiveCfg = Release|Win8 - {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Release|WP81.ActiveCfg = Release|WP81 - {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|Net20.ActiveCfg = Debug|Net20 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|Net20.Build.0 = Debug|Net20 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|Net40.ActiveCfg = Debug|Net40 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|Net40.Build.0 = Debug|Net40 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|Win8.ActiveCfg = Debug|Win8 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|Win8.Build.0 = Debug|Win8 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|WP81.ActiveCfg = Debug|WP81 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|WP81.Build.0 = Debug|WP81 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|Net20.ActiveCfg = Release|Net20 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|Net20.Build.0 = Release|Net20 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|Net40.ActiveCfg = Release|Net40 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|Net40.Build.0 = Release|Net40 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|Win8.ActiveCfg = Release|Win8 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|Win8.Build.0 = Release|Win8 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|WP81.ActiveCfg = Release|WP81 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|WP81.Build.0 = Release|WP81 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|WP8-ARM.Build.0 = Release|WP8-ARM - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|WP8-x86.Build.0 = Release|WP8-x86 - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|Net20.ActiveCfg = Debug|Net20 - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|Net20.Build.0 = Debug|Net20 - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|Net40.ActiveCfg = Debug|Net40 - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|Net40.Build.0 = Debug|Net40 - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|Win8.ActiveCfg = Debug|Win8 - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|WP81.ActiveCfg = Debug|WP81 - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|Net20.ActiveCfg = Release|Net20 - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|Net20.Build.0 = Release|Net20 - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|Net40.ActiveCfg = Release|Net40 - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|Net40.Build.0 = Release|Net40 - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|Win8.ActiveCfg = Release|Win8 - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|WP81.ActiveCfg = Release|WP81 - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|Net20.ActiveCfg = Debug|Net20 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|Net20.Build.0 = Debug|Net20 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|Net40.ActiveCfg = Debug|Net40 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|Net40.Build.0 = Debug|Net40 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|Win8.ActiveCfg = Debug|Win8 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|Win8.Build.0 = Debug|Win8 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|WP81.ActiveCfg = Debug|WP81 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|WP81.Build.0 = Debug|WP81 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM - {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|Net20.ActiveCfg = Release|Net20 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|Net20.Build.0 = Release|Net20 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|Net40.ActiveCfg = Release|Net40 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|Net40.Build.0 = Release|Net40 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|Win8.ActiveCfg = Release|Win8 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|Win8.Build.0 = Release|Win8 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|WP81.ActiveCfg = Release|WP81 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|WP81.Build.0 = Release|WP81 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|WP8-ARM.Build.0 = Release|WP8-ARM - {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|WP8-x86.Build.0 = Release|WP8-x86 - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|DIRECTX11_2.ActiveCfg = Debug|Any CPU - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|DIRECTX11_2.Build.0 = Debug|Any CPU - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|Net20.ActiveCfg = Debug|Any CPU - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|Net20.Build.0 = Debug|Any CPU - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|Net40.ActiveCfg = Debug|Any CPU - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|Net40.Build.0 = Debug|Any CPU - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|Win8.ActiveCfg = Debug|Any CPU - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|WP81.ActiveCfg = Debug|Any CPU - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|WP8-ARM.ActiveCfg = Debug|Any CPU - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|WP8-x86.ActiveCfg = Debug|Any CPU - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|DIRECTX11_2.ActiveCfg = Release|Any CPU - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|Net20.ActiveCfg = Release|Any CPU - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|Net20.Build.0 = Release|Any CPU - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|Net40.ActiveCfg = Release|Any CPU - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|Net40.Build.0 = Release|Any CPU - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|Win8.ActiveCfg = Release|Any CPU - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|WP81.ActiveCfg = Release|Any CPU - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|WP8-ARM.ActiveCfg = Release|Any CPU - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|WP8-x86.ActiveCfg = Release|Any CPU - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|Net20.ActiveCfg = Debug|Net20 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|Net20.Build.0 = Debug|Net20 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|Net40.ActiveCfg = Debug|Net40 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|Net40.Build.0 = Debug|Net40 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|Win8.ActiveCfg = Debug|Win8 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|Win8.Build.0 = Debug|Win8 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|WP81.ActiveCfg = Debug|WP81 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|WP81.Build.0 = Debug|WP81 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|Net20.ActiveCfg = Release|Net20 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|Net20.Build.0 = Release|Net20 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|Net40.ActiveCfg = Release|Net40 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|Net40.Build.0 = Release|Net40 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|Win8.ActiveCfg = Release|Win8 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|Win8.Build.0 = Release|Win8 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|WP81.ActiveCfg = Release|WP81 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|WP81.Build.0 = Release|WP81 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|WP8-ARM.Build.0 = Release|WP8-ARM - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|WP8-x86.Build.0 = Release|WP8-x86 - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|Net20.ActiveCfg = Debug|Net20 - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|Net20.Build.0 = Debug|Net20 - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|Net40.ActiveCfg = Debug|Net40 - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|Net40.Build.0 = Debug|Net40 - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|Win8.ActiveCfg = Debug|Win8 - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|WP81.ActiveCfg = Debug|WP81 - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|Net20.ActiveCfg = Release|Net20 - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|Net20.Build.0 = Release|Net20 - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|Net40.ActiveCfg = Release|Net40 - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|Net40.Build.0 = Release|Net40 - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|Win8.ActiveCfg = Release|Win8 - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|WP81.ActiveCfg = Release|WP81 - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|Net20.ActiveCfg = Debug|Net20 - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|Net20.Build.0 = Debug|Net20 - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|Net40.ActiveCfg = Debug|Net40 - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|Net40.Build.0 = Debug|Net40 - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|Win8.ActiveCfg = Debug|Win8 - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|WP81.ActiveCfg = Debug|WP81 - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|Net20.ActiveCfg = Release|Net20 - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|Net20.Build.0 = Release|Net20 - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|Net40.ActiveCfg = Release|Net40 - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|Net40.Build.0 = Release|Net40 - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|Win8.ActiveCfg = Release|Win8 - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|WP81.ActiveCfg = Release|WP81 - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|DIRECTX11_2.ActiveCfg = Debug|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|DIRECTX11_2.Build.0 = Debug|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|Net20.ActiveCfg = Debug|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|Net20.Build.0 = Debug|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|Net40.ActiveCfg = Debug|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|Net40.Build.0 = Debug|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|Win8.ActiveCfg = Debug|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|Win8.Build.0 = Debug|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|WP81.ActiveCfg = Debug|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|WP81.Build.0 = Debug|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|WP8-ARM.ActiveCfg = Debug|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|WP8-x86.ActiveCfg = Debug|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|DIRECTX11_2.ActiveCfg = Release|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|DIRECTX11_2.Build.0 = Release|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|Net20.ActiveCfg = Release|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|Net20.Build.0 = Release|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|Net40.ActiveCfg = Release|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|Net40.Build.0 = Release|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|Win8.ActiveCfg = Release|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|Win8.Build.0 = Release|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|WP81.ActiveCfg = Release|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|WP81.Build.0 = Release|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|WP8-ARM.ActiveCfg = Release|Any CPU - {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|WP8-x86.ActiveCfg = Release|Any CPU - {7329B02D-C504-482A-A156-181D48CE493C}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {7329B02D-C504-482A-A156-181D48CE493C}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {7329B02D-C504-482A-A156-181D48CE493C}.Debug|Net20.ActiveCfg = Debug|Net20 - {7329B02D-C504-482A-A156-181D48CE493C}.Debug|Net20.Build.0 = Debug|Net20 - {7329B02D-C504-482A-A156-181D48CE493C}.Debug|Net40.ActiveCfg = Debug|Net40 - {7329B02D-C504-482A-A156-181D48CE493C}.Debug|Net40.Build.0 = Debug|Net40 - {7329B02D-C504-482A-A156-181D48CE493C}.Debug|Win8.ActiveCfg = Debug|Win8 - {7329B02D-C504-482A-A156-181D48CE493C}.Debug|WP81.ActiveCfg = Debug|WP81 - {7329B02D-C504-482A-A156-181D48CE493C}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {7329B02D-C504-482A-A156-181D48CE493C}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {7329B02D-C504-482A-A156-181D48CE493C}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {7329B02D-C504-482A-A156-181D48CE493C}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {7329B02D-C504-482A-A156-181D48CE493C}.Release|Net20.ActiveCfg = Release|Net20 - {7329B02D-C504-482A-A156-181D48CE493C}.Release|Net20.Build.0 = Release|Net20 - {7329B02D-C504-482A-A156-181D48CE493C}.Release|Net40.ActiveCfg = Release|Net40 - {7329B02D-C504-482A-A156-181D48CE493C}.Release|Net40.Build.0 = Release|Net40 - {7329B02D-C504-482A-A156-181D48CE493C}.Release|Win8.ActiveCfg = Release|Win8 - {7329B02D-C504-482A-A156-181D48CE493C}.Release|WP81.ActiveCfg = Release|WP81 - {7329B02D-C504-482A-A156-181D48CE493C}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {7329B02D-C504-482A-A156-181D48CE493C}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|Net20.ActiveCfg = Debug|Net20 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|Net20.Build.0 = Debug|Net20 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|Net40.ActiveCfg = Debug|Net40 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|Net40.Build.0 = Debug|Net40 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|Win8.ActiveCfg = Debug|Win8 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|Win8.Build.0 = Debug|Win8 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|WP81.ActiveCfg = Debug|WP81 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|WP81.Build.0 = Debug|WP81 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM - {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|Net20.ActiveCfg = Release|Net20 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|Net20.Build.0 = Release|Net20 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|Net40.ActiveCfg = Release|Net40 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|Net40.Build.0 = Release|Net40 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|Win8.ActiveCfg = Release|Win8 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|Win8.Build.0 = Release|Win8 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|WP81.ActiveCfg = Release|WP81 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|WP81.Build.0 = Release|WP81 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|WP8-ARM.Build.0 = Release|WP8-ARM - {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|WP8-x86.Build.0 = Release|WP8-x86 - {46452614-6B06-400F-A74C-1632C79B762C}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {46452614-6B06-400F-A74C-1632C79B762C}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {46452614-6B06-400F-A74C-1632C79B762C}.Debug|Net20.ActiveCfg = Debug|Net20 - {46452614-6B06-400F-A74C-1632C79B762C}.Debug|Net20.Build.0 = Debug|Net20 - {46452614-6B06-400F-A74C-1632C79B762C}.Debug|Net40.ActiveCfg = Debug|Net40 - {46452614-6B06-400F-A74C-1632C79B762C}.Debug|Net40.Build.0 = Debug|Net40 - {46452614-6B06-400F-A74C-1632C79B762C}.Debug|Win8.ActiveCfg = Debug|Win8 - {46452614-6B06-400F-A74C-1632C79B762C}.Debug|Win8.Build.0 = Debug|Win8 - {46452614-6B06-400F-A74C-1632C79B762C}.Debug|WP81.ActiveCfg = Debug|WP81 - {46452614-6B06-400F-A74C-1632C79B762C}.Debug|WP81.Build.0 = Debug|WP81 - {46452614-6B06-400F-A74C-1632C79B762C}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {46452614-6B06-400F-A74C-1632C79B762C}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM - {46452614-6B06-400F-A74C-1632C79B762C}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {46452614-6B06-400F-A74C-1632C79B762C}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 - {46452614-6B06-400F-A74C-1632C79B762C}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {46452614-6B06-400F-A74C-1632C79B762C}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {46452614-6B06-400F-A74C-1632C79B762C}.Release|Net20.ActiveCfg = Release|Net20 - {46452614-6B06-400F-A74C-1632C79B762C}.Release|Net20.Build.0 = Release|Net20 - {46452614-6B06-400F-A74C-1632C79B762C}.Release|Net40.ActiveCfg = Release|Net40 - {46452614-6B06-400F-A74C-1632C79B762C}.Release|Net40.Build.0 = Release|Net40 - {46452614-6B06-400F-A74C-1632C79B762C}.Release|Win8.ActiveCfg = Release|Win8 - {46452614-6B06-400F-A74C-1632C79B762C}.Release|Win8.Build.0 = Release|Win8 - {46452614-6B06-400F-A74C-1632C79B762C}.Release|WP81.ActiveCfg = Release|WP81 - {46452614-6B06-400F-A74C-1632C79B762C}.Release|WP81.Build.0 = Release|WP81 - {46452614-6B06-400F-A74C-1632C79B762C}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {46452614-6B06-400F-A74C-1632C79B762C}.Release|WP8-ARM.Build.0 = Release|WP8-ARM - {46452614-6B06-400F-A74C-1632C79B762C}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {46452614-6B06-400F-A74C-1632C79B762C}.Release|WP8-x86.Build.0 = Release|WP8-x86 - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|Net20.ActiveCfg = Debug|Net20 - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|Net40.ActiveCfg = Debug|Net40 - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|Net40.Build.0 = Debug|Net40 - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|Win8.ActiveCfg = Debug|Win8 - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|WP81.ActiveCfg = Debug|WP81 - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|Net20.ActiveCfg = Release|Net20 - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|Net40.ActiveCfg = Release|Net40 - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|Net40.Build.0 = Release|Net40 - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|Win8.ActiveCfg = Release|Win8 - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|WP81.ActiveCfg = Release|WP81 - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|Net20.ActiveCfg = Debug|Net20 - {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|Net20.Build.0 = Debug|Net20 - {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|Net40.ActiveCfg = Debug|Net40 - {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|Net40.Build.0 = Debug|Net40 - {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|Win8.ActiveCfg = Debug|Win8 - {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|WP81.ActiveCfg = Debug|WP81 - {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|Net20.ActiveCfg = Release|Net20 - {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|Net20.Build.0 = Release|Net20 - {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|Net40.ActiveCfg = Release|Net40 - {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|Net40.Build.0 = Release|Net40 - {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|Win8.ActiveCfg = Release|Win8 - {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|WP81.ActiveCfg = Release|WP81 - {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|Net20.ActiveCfg = Debug|Net20 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|Net20.Build.0 = Debug|Net20 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|Net40.ActiveCfg = Debug|Net40 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|Net40.Build.0 = Debug|Net40 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|Win8.ActiveCfg = Debug|Win8 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|Win8.Build.0 = Debug|Win8 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|WP81.ActiveCfg = Debug|WP81 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|WP81.Build.0 = Debug|WP81 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|Net20.ActiveCfg = Release|Net20 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|Net20.Build.0 = Release|Net20 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|Net40.ActiveCfg = Release|Net40 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|Net40.Build.0 = Release|Net40 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|Win8.ActiveCfg = Release|Win8 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|Win8.Build.0 = Release|Win8 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|WP81.ActiveCfg = Release|WP81 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|WP81.Build.0 = Release|WP81 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|WP8-ARM.Build.0 = Release|WP8-ARM - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|WP8-x86.Build.0 = Release|WP8-x86 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|Net20.ActiveCfg = Debug|Net20 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|Net20.Build.0 = Debug|Net20 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|Net40.ActiveCfg = Debug|Net40 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|Net40.Build.0 = Debug|Net40 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|Win8.ActiveCfg = Debug|Win8 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|Win8.Build.0 = Debug|Win8 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|WP81.ActiveCfg = Debug|WP81 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|WP81.Build.0 = Debug|WP81 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|Net20.ActiveCfg = Release|Net20 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|Net20.Build.0 = Release|Net20 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|Net40.ActiveCfg = Release|Net40 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|Net40.Build.0 = Release|Net40 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|Win8.ActiveCfg = Release|Win8 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|Win8.Build.0 = Release|Win8 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|WP81.ActiveCfg = Release|WP81 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|WP81.Build.0 = Release|WP81 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|WP8-ARM.Build.0 = Release|WP8-ARM - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|WP8-x86.Build.0 = Release|WP8-x86 - {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Debug|Net20.ActiveCfg = Debug|Net20 - {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Debug|Net40.ActiveCfg = Debug|Net40 - {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Debug|Win8.ActiveCfg = Debug|Win8 - {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Debug|WP81.ActiveCfg = Debug|WP81 - {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Release|Net20.ActiveCfg = Release|Net20 - {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Release|Net40.ActiveCfg = Release|Net40 - {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Release|Win8.ActiveCfg = Release|Win8 - {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Release|WP81.ActiveCfg = Release|WP81 - {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 - {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 - {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Debug|Net20.ActiveCfg = Debug|Net20 - {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Debug|Net40.ActiveCfg = Debug|Net40 - {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Debug|Win8.ActiveCfg = Debug|Win8 - {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Debug|WP81.ActiveCfg = Debug|WP81 - {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM - {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 - {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 - {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 - {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Release|Net20.ActiveCfg = Release|Net20 - {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Release|Net40.ActiveCfg = Release|Net40 - {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Release|Win8.ActiveCfg = Release|Win8 - {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Release|WP81.ActiveCfg = Release|WP81 - {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM - {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {D0BCD56A-41C4-4A4E-8590-26864CED07FF} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - {361D3F81-A48A-47F2-80DF-CA4F9536CB4E} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - {C97878F4-1510-4BBA-8153-BD71DA7D50D8} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - {618AFA87-81A8-4B1C-8876-5457D49F2DEF} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - {736DFB52-1AFE-4EFF-9710-89046AB5B1F9} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - {E927F2D5-8E27-462A-8687-CB207EE01164} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - {3FC6DE77-B412-4101-9E64-6B9AA831179B} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - {4995127E-0B8E-45B8-80C4-6BAC1BBE3783} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - {112F146B-7C01-490B-B943-EA9341ACCAF2} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - {4E2D9A17-2195-4A51-AAE3-924517440293} = {F1AF9A3B-7856-46C9-992A-391E5455BF1F} - {31F85A16-CB01-4456-BE3C-76E9FF3A1343} = {F1AF9A3B-7856-46C9-992A-391E5455BF1F} - {5E597A82-9DE9-4BA5-AD76-51202190E951} = {F1AF9A3B-7856-46C9-992A-391E5455BF1F} - {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB} = {57C5C966-ADB2-43F2-BB54-99BCB56C9F10} - {4939860C-5D5B-4D56-89C8-1980A9EBB392} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - {05D17A7B-F200-48C0-B8F9-B7211665A17F} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - {764D7CE5-F78B-432E-A849-E40BA44522D6} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - {931FA266-E756-41CA-9736-8B29235DC999} = {1B526C0E-EE4A-4E8F-BF8F-8C7397FB4918} - {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - {BBB50A46-3291-4C62-B884-D1AB64F71EA5} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - {53EF08A7-4224-434C-A62C-F29807C1C750} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} - {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9} = {1B526C0E-EE4A-4E8F-BF8F-8C7397FB4918} - {9FF0707C-75BB-4984-A01F-B9EAAD293F6C} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} - {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} - {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} - {15BA35B5-3E54-4715-8857-36F4F96F51FB} = {F1AF9A3B-7856-46C9-992A-391E5455BF1F} - {7329B02D-C504-482A-A156-181D48CE493C} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} - {B2516A23-1A99-4263-964A-B820FD07FA80} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} - {46452614-6B06-400F-A74C-1632C79B762C} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} - {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} - {76FD0713-F217-4485-89B3-C6423DB46C58} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} - {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} - {1FA327C8-6C48-4FFC-9235-B98B7521B79D} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} - {FBE5DD99-00A0-4FED-A116-941A46A0C0D0} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - {F826CCCE-4B72-47F4-9493-DFCB51C106B7} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.30501.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sources", "Sources", "{CC8DB471-0644-430D-9D4B-808A2475BEC0}" + ProjectSection(SolutionItems) = preProject + Source\Mapping.Direct3D1x.xml = Source\Mapping.Direct3D1x.xml + Source\Mapping.xml = Source\Mapping.xml + Source\SharedAssemblyInfo.cs = Source\SharedAssemblyInfo.cs + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{F1AF9A3B-7856-46C9-992A-391E5455BF1F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX", "Source\SharpDX\SharpDX.csproj", "{D0BCD56A-41C4-4A4E-8590-26864CED07FF}" + ProjectSection(ProjectDependencies) = postProject + {31F85A16-CB01-4456-BE3C-76E9FF3A1343} = {31F85A16-CB01-4456-BE3C-76E9FF3A1343} + {4E2D9A17-2195-4A51-AAE3-924517440293} = {4E2D9A17-2195-4A51-AAE3-924517440293} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.D3DCompiler", "Source\SharpDX.D3DCompiler\SharpDX.D3DCompiler.csproj", "{361D3F81-A48A-47F2-80DF-CA4F9536CB4E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Direct2D1", "Source\SharpDX.Direct2D1\SharpDX.Direct2D1.csproj", "{C97878F4-1510-4BBA-8153-BD71DA7D50D8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Direct3D10", "Source\SharpDX.Direct3D10\SharpDX.Direct3D10.csproj", "{618AFA87-81A8-4B1C-8876-5457D49F2DEF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Direct3D11", "Source\SharpDX.Direct3D11\SharpDX.Direct3D11.csproj", "{736DFB52-1AFE-4EFF-9710-89046AB5B1F9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.DirectSound", "Source\SharpDX.DirectSound\SharpDX.DirectSound.csproj", "{E927F2D5-8E27-462A-8687-CB207EE01164}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.DXGI", "Source\SharpDX.DXGI\SharpDX.DXGI.csproj", "{3FC6DE77-B412-4101-9E64-6B9AA831179B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.XAudio2", "Source\SharpDX.XAudio2\SharpDX.XAudio2.csproj", "{4995127E-0B8E-45B8-80C4-6BAC1BBE3783}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Direct3D9", "Source\SharpDX.Direct3D9\SharpDX.Direct3D9.csproj", "{B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.DirectInput", "Source\SharpDX.DirectInput\SharpDX.DirectInput.csproj", "{112F146B-7C01-490B-B943-EA9341ACCAF2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SharpDX.WP8", "Source\SharpDX.WP8\SharpDX.WP8.vcxproj", "{C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpCli", "Source\Tools\SharpCli\SharpCli.csproj", "{4E2D9A17-2195-4A51-AAE3-924517440293}" + ProjectSection(ProjectDependencies) = postProject + {5E597A82-9DE9-4BA5-AD76-51202190E951} = {5E597A82-9DE9-4BA5-AD76-51202190E951} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpGen", "Source\Tools\SharpGen\SharpGen.csproj", "{31F85A16-CB01-4456-BE3C-76E9FF3A1343}" + ProjectSection(ProjectDependencies) = postProject + {5E597A82-9DE9-4BA5-AD76-51202190E951} = {5E597A82-9DE9-4BA5-AD76-51202190E951} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpPak", "Source\Tools\SharpPak\SharpPak.csproj", "{5E597A82-9DE9-4BA5-AD76-51202190E951}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Documentation", "Documentation\Documentation.csproj", "{9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{57C5C966-ADB2-43F2-BB54-99BCB56C9F10}" + ProjectSection(SolutionItems) = preProject + ChangeLog.txt = ChangeLog.txt + README.markdown = README.markdown + ReleaseNotes.html = ReleaseNotes.html + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{1B526C0E-EE4A-4E8F-BF8F-8C7397FB4918}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.XACT3", "Source\SharpDX.XACT3\SharpDX.XACT3.csproj", "{4939860C-5D5B-4D56-89C8-1980A9EBB392}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.RawInput", "Source\SharpDX.RawInput\SharpDX.RawInput.csproj", "{05D17A7B-F200-48C0-B8F9-B7211665A17F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.XInput", "Source\SharpDX.XInput\SharpDX.XInput.csproj", "{764D7CE5-F78B-432E-A849-E40BA44522D6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{E462D87D-C180-4114-B8C8-914E6735BF44}" + ProjectSection(SolutionItems) = preProject + Source\Install.ps1 = Source\Install.ps1 + Build\SharpDX.build = Build\SharpDX.build + Build\SharpDX.PostSettings.targets = Build\SharpDX.PostSettings.targets + Build\SharpDX.PreSettings.targets = Build\SharpDX.PreSettings.targets + Build\SharpDX.targets = Build\SharpDX.targets + Build\SharpDX.Toolkit.targets = Build\SharpDX.Toolkit.targets + Source\uninstall.ps1 = Source\uninstall.ps1 + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Tests", "Source\Tests\SharpDX.Tests\SharpDX.Tests.csproj", "{931FA266-E756-41CA-9736-8B29235DC999}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Animation", "Source\SharpDX.Animation\SharpDX.Animation.csproj", "{874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.MediaFoundation", "Source\SharpDX.MediaFoundation\SharpDX.MediaFoundation.csproj", "{CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Direct3D11.Effects", "Source\SharpDX.Direct3D11.Effects\SharpDX.Direct3D11.Effects.csproj", "{BBB50A46-3291-4C62-B884-D1AB64F71EA5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Toolkit", "Toolkit", "{529B140D-B91D-49EA-B173-9ADD6AB2A2A3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Toolkit.Graphics", "Source\Toolkit\SharpDX.Toolkit.Graphics\SharpDX.Toolkit.Graphics.csproj", "{53EF08A7-4224-434C-A62C-F29807C1C750}" + ProjectSection(ProjectDependencies) = postProject + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702} = {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702} + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8} = {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Toolkit.Graphics.Tests", "Source\Tests\SharpDX.Toolkit.Graphics.Tests\SharpDX.Toolkit.Graphics.Tests.csproj", "{4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Toolkit", "Source\Toolkit\SharpDX.Toolkit\SharpDX.Toolkit.csproj", "{9FF0707C-75BB-4984-A01F-B9EAAD293F6C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Toolkit.Compiler", "Source\Toolkit\SharpDX.Toolkit.Compiler\SharpDX.Toolkit.Compiler.csproj", "{8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tkfxc", "Source\Toolkit\tkfxc\tkfxc.csproj", "{BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpGitLog", "Source\Tools\SharpGitLog\SharpGitLog.csproj", "{15BA35B5-3E54-4715-8857-36F4F96F51FB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tkfont", "Source\Toolkit\tkfont\tkfont.csproj", "{7329B02D-C504-482A-A156-181D48CE493C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Toolkit.Game", "Source\Toolkit\SharpDX.Toolkit.Game\SharpDX.Toolkit.Game.csproj", "{B2516A23-1A99-4263-964A-B820FD07FA80}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Toolkit.Input", "Source\Toolkit\SharpDX.Toolkit.Input\SharpDX.Toolkit.Input.csproj", "{46452614-6B06-400F-A74C-1632C79B762C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Toolkit.CompilerTask", "Source\Toolkit\SharpDX.Toolkit.CompilerTask\SharpDX.Toolkit.CompilerTask.csproj", "{90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tkmodel", "Source\Toolkit\tkmodel\tkmodel.csproj", "{76FD0713-F217-4485-89B3-C6423DB46C58}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Toolkit.Yaml", "Source\Toolkit\SharpDX.Toolkit.Yaml\SharpDX.Toolkit.Yaml.csproj", "{ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Toolkit.Audio", "Source\Toolkit\SharpDX.Toolkit.Audio\SharpDX.Toolkit.Audio.csproj", "{1FA327C8-6C48-4FFC-9235-B98B7521B79D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.DirectComposition", "Source\SharpDX.DirectComposition\SharpDX.DirectComposition.csproj", "{FBE5DD99-00A0-4FED-A116-941A46A0C0D0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.DirectManipulation", "Source\SharpDX.DirectManipulation\SharpDX.DirectManipulation.csproj", "{F826CCCE-4B72-47F4-9493-DFCB51C106B7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDX.Mathematics", "Source\SharpDX.Mathematics\SharpDX.Mathematics.csproj", "{49E4485F-3A2A-4C35-A159-12ECCFC00396}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|DIRECTX11_2 = Debug|DIRECTX11_2 + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|Net20 = Debug|Net20 + Debug|Net40 = Debug|Net40 + Debug|Win8 = Debug|Win8 + Debug|WP81 = Debug|WP81 + Debug|WP8-ARM = Debug|WP8-ARM + Debug|WP8-x86 = Debug|WP8-x86 + Release|DIRECTX11_2 = Release|DIRECTX11_2 + Release|Mixed Platforms = Release|Mixed Platforms + Release|Net20 = Release|Net20 + Release|Net40 = Release|Net40 + Release|Win8 = Release|Win8 + Release|WP81 = Release|WP81 + Release|WP8-ARM = Release|WP8-ARM + Release|WP8-x86 = Release|WP8-x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|Net20.ActiveCfg = Debug|Net20 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|Net20.Build.0 = Debug|Net20 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|Net40.ActiveCfg = Debug|Net40 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|Net40.Build.0 = Debug|Net40 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|Win8.ActiveCfg = Debug|Win8 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|Win8.Build.0 = Debug|Win8 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|WP81.ActiveCfg = Debug|WP81 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|WP81.Build.0 = Debug|WP81 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|Net20.ActiveCfg = Release|Net20 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|Net20.Build.0 = Release|Net20 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|Net40.ActiveCfg = Release|Net40 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|Net40.Build.0 = Release|Net40 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|Win8.ActiveCfg = Release|Win8 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|Win8.Build.0 = Release|Win8 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|WP81.ActiveCfg = Release|WP81 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|WP81.Build.0 = Release|WP81 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|WP8-ARM.Build.0 = Release|WP8-ARM + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF}.Release|WP8-x86.Build.0 = Release|WP8-x86 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|Net20.ActiveCfg = Debug|Net20 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|Net20.Build.0 = Debug|Net20 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|Net40.ActiveCfg = Debug|Net40 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|Net40.Build.0 = Debug|Net40 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|Win8.ActiveCfg = Debug|Win8 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|Win8.Build.0 = Debug|Win8 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|WP81.ActiveCfg = Debug|WP81 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|WP81.Build.0 = Debug|WP81 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|Net20.ActiveCfg = Release|Net20 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|Net20.Build.0 = Release|Net20 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|Net40.ActiveCfg = Release|Net40 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|Net40.Build.0 = Release|Net40 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|Win8.ActiveCfg = Release|Win8 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|Win8.Build.0 = Release|Win8 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|WP81.ActiveCfg = Release|WP81 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|WP81.Build.0 = Release|WP81 + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|Net20.ActiveCfg = Debug|Net20 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|Net20.Build.0 = Debug|Net20 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|Net40.ActiveCfg = Debug|Net40 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|Net40.Build.0 = Debug|Net40 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|Win8.ActiveCfg = Debug|Win8 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|Win8.Build.0 = Debug|Win8 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|WP81.ActiveCfg = Debug|WP81 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|WP81.Build.0 = Debug|WP81 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|Net20.ActiveCfg = Release|Net20 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|Net20.Build.0 = Release|Net20 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|Net40.ActiveCfg = Release|Net40 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|Net40.Build.0 = Release|Net40 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|Win8.ActiveCfg = Release|Win8 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|Win8.Build.0 = Release|Win8 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|WP81.ActiveCfg = Release|WP81 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|WP81.Build.0 = Release|WP81 + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {C97878F4-1510-4BBA-8153-BD71DA7D50D8}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|Net20.ActiveCfg = Debug|Net20 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|Net20.Build.0 = Debug|Net20 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|Net40.ActiveCfg = Debug|Net40 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|Net40.Build.0 = Debug|Net40 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|Win8.ActiveCfg = Debug|Win8 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|WP81.ActiveCfg = Debug|WP81 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|Net20.ActiveCfg = Release|Net20 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|Net20.Build.0 = Release|Net20 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|Net40.ActiveCfg = Release|Net40 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|Net40.Build.0 = Release|Net40 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|Win8.ActiveCfg = Release|Win8 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|WP81.ActiveCfg = Release|WP81 + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {618AFA87-81A8-4B1C-8876-5457D49F2DEF}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|Net20.ActiveCfg = Debug|Net20 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|Net20.Build.0 = Debug|Net20 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|Net40.ActiveCfg = Debug|Net40 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|Net40.Build.0 = Debug|Net40 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|Win8.ActiveCfg = Debug|Win8 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|Win8.Build.0 = Debug|Win8 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|WP81.ActiveCfg = Debug|WP81 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|WP81.Build.0 = Debug|WP81 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|Net20.ActiveCfg = Release|Net20 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|Net20.Build.0 = Release|Net20 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|Net40.ActiveCfg = Release|Net40 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|Net40.Build.0 = Release|Net40 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|Win8.ActiveCfg = Release|Win8 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|Win8.Build.0 = Release|Win8 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|WP81.ActiveCfg = Release|WP81 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|WP81.Build.0 = Release|WP81 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|WP8-ARM.Build.0 = Release|WP8-ARM + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9}.Release|WP8-x86.Build.0 = Release|WP8-x86 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|Net20.ActiveCfg = Debug|Net20 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|Net20.Build.0 = Debug|Net20 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|Net40.ActiveCfg = Debug|Net40 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|Net40.Build.0 = Debug|Net40 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|Win8.ActiveCfg = Debug|Win8 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|WP81.ActiveCfg = Debug|WP81 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {E927F2D5-8E27-462A-8687-CB207EE01164}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|Net20.ActiveCfg = Release|Net20 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|Net20.Build.0 = Release|Net20 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|Net40.ActiveCfg = Release|Net40 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|Net40.Build.0 = Release|Net40 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|Win8.ActiveCfg = Release|Win8 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|WP81.ActiveCfg = Release|WP81 + {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {E927F2D5-8E27-462A-8687-CB207EE01164}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|Net20.ActiveCfg = Debug|Net20 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|Net20.Build.0 = Debug|Net20 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|Net40.ActiveCfg = Debug|Net40 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|Net40.Build.0 = Debug|Net40 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|Win8.ActiveCfg = Debug|Win8 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|Win8.Build.0 = Debug|Win8 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|WP81.ActiveCfg = Debug|WP81 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|WP81.Build.0 = Debug|WP81 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|Net20.ActiveCfg = Release|Net20 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|Net20.Build.0 = Release|Net20 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|Net40.ActiveCfg = Release|Net40 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|Net40.Build.0 = Release|Net40 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|Win8.ActiveCfg = Release|Win8 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|Win8.Build.0 = Release|Win8 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|WP81.ActiveCfg = Release|WP81 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|WP81.Build.0 = Release|WP81 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|WP8-ARM.Build.0 = Release|WP8-ARM + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {3FC6DE77-B412-4101-9E64-6B9AA831179B}.Release|WP8-x86.Build.0 = Release|WP8-x86 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|Net20.ActiveCfg = Debug|Net20 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|Net20.Build.0 = Debug|Net20 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|Net40.ActiveCfg = Debug|Net40 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|Net40.Build.0 = Debug|Net40 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|Win8.ActiveCfg = Debug|Win8 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|Win8.Build.0 = Debug|Win8 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|WP81.ActiveCfg = Debug|WP81 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|WP81.Build.0 = Debug|WP81 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|Net20.ActiveCfg = Release|Net20 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|Net20.Build.0 = Release|Net20 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|Net40.ActiveCfg = Release|Net40 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|Net40.Build.0 = Release|Net40 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|Win8.ActiveCfg = Release|Win8 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|Win8.Build.0 = Release|Win8 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|WP81.ActiveCfg = Release|WP81 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|WP81.Build.0 = Release|WP81 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|WP8-ARM.Build.0 = Release|WP8-ARM + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783}.Release|WP8-x86.Build.0 = Release|WP8-x86 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|Net20.ActiveCfg = Debug|Net20 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|Net20.Build.0 = Debug|Net20 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|Net40.ActiveCfg = Debug|Net40 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|Net40.Build.0 = Debug|Net40 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|Win8.ActiveCfg = Debug|Win8 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|WP81.ActiveCfg = Debug|WP81 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|Net20.ActiveCfg = Release|Net20 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|Net20.Build.0 = Release|Net20 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|Net40.ActiveCfg = Release|Net40 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|Net40.Build.0 = Release|Net40 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|Win8.ActiveCfg = Release|Win8 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|WP81.ActiveCfg = Release|WP81 + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|Net20.ActiveCfg = Debug|Net20 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|Net20.Build.0 = Debug|Net20 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|Net40.ActiveCfg = Debug|Net40 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|Net40.Build.0 = Debug|Net40 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|Win8.ActiveCfg = Debug|Win8 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|WP81.ActiveCfg = Debug|WP81 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|Net20.ActiveCfg = Release|Net20 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|Net20.Build.0 = Release|Net20 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|Net40.ActiveCfg = Release|Net40 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|Net40.Build.0 = Release|Net40 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|Win8.ActiveCfg = Release|Win8 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|WP81.ActiveCfg = Release|WP81 + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {112F146B-7C01-490B-B943-EA9341ACCAF2}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|DIRECTX11_2.ActiveCfg = Debug|Win32 + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|Net20.ActiveCfg = Debug|Win32 + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|Net40.ActiveCfg = Debug|Win32 + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|Win8.ActiveCfg = Debug|Win32 + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|WP81.ActiveCfg = Debug|Win32 + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|WP8-ARM.ActiveCfg = Debug|ARM + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|WP8-ARM.Build.0 = Debug|ARM + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|WP8-x86.ActiveCfg = Debug|Win32 + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Debug|WP8-x86.Build.0 = Debug|Win32 + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|DIRECTX11_2.ActiveCfg = Release|Win32 + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|Mixed Platforms.Build.0 = Release|Win32 + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|Net20.ActiveCfg = Release|Win32 + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|Net40.ActiveCfg = Release|Win32 + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|Win8.ActiveCfg = Release|Win32 + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|WP81.ActiveCfg = Release|Win32 + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|WP8-ARM.ActiveCfg = Release|ARM + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|WP8-ARM.Build.0 = Release|ARM + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|WP8-x86.ActiveCfg = Release|Win32 + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4}.Release|WP8-x86.Build.0 = Release|Win32 + {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|DIRECTX11_2.ActiveCfg = Debug|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|DIRECTX11_2.Build.0 = Debug|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|Net20.ActiveCfg = Debug|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|Net20.Build.0 = Debug|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|Net40.ActiveCfg = Debug|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|Net40.Build.0 = Debug|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|Win8.ActiveCfg = Debug|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|WP81.ActiveCfg = Debug|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|WP81.Build.0 = Debug|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|WP8-ARM.ActiveCfg = Debug|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|WP8-ARM.Build.0 = Debug|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|WP8-x86.ActiveCfg = Debug|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Debug|WP8-x86.Build.0 = Debug|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|DIRECTX11_2.ActiveCfg = Release|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|DIRECTX11_2.Build.0 = Release|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|Net20.ActiveCfg = Release|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|Net20.Build.0 = Release|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|Net40.ActiveCfg = Release|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|Net40.Build.0 = Release|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|Win8.ActiveCfg = Release|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|Win8.Build.0 = Release|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|WP81.ActiveCfg = Release|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|WP81.Build.0 = Release|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|WP8-ARM.ActiveCfg = Release|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|WP8-ARM.Build.0 = Release|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|WP8-x86.ActiveCfg = Release|Any CPU + {4E2D9A17-2195-4A51-AAE3-924517440293}.Release|WP8-x86.Build.0 = Release|Any CPU + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|Net20.ActiveCfg = Debug|Net20 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|Net20.Build.0 = Debug|Net20 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|Net40.ActiveCfg = Debug|Net40 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|Net40.Build.0 = Debug|Net40 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|Win8.ActiveCfg = Debug|Win8 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|Win8.Build.0 = Debug|Win8 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|WP81.ActiveCfg = Debug|WP81 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|WP81.Build.0 = Debug|WP81 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|Net20.ActiveCfg = Release|Net20 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|Net20.Build.0 = Release|Net20 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|Net40.ActiveCfg = Release|Net40 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|Net40.Build.0 = Release|Net40 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|Win8.ActiveCfg = Release|Win8 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|Win8.Build.0 = Release|Win8 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|WP81.ActiveCfg = Release|WP81 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|WP81.Build.0 = Release|WP81 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|WP8-ARM.Build.0 = Release|WP8-ARM + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {31F85A16-CB01-4456-BE3C-76E9FF3A1343}.Release|WP8-x86.Build.0 = Release|WP8-x86 + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|DIRECTX11_2.ActiveCfg = Debug|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|DIRECTX11_2.Build.0 = Debug|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|Net20.ActiveCfg = Debug|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|Net20.Build.0 = Debug|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|Net40.ActiveCfg = Debug|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|Net40.Build.0 = Debug|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|Win8.ActiveCfg = Debug|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|WP81.ActiveCfg = Debug|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|WP81.Build.0 = Debug|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|WP8-ARM.ActiveCfg = Debug|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Debug|WP8-x86.ActiveCfg = Debug|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|DIRECTX11_2.ActiveCfg = Release|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|DIRECTX11_2.Build.0 = Release|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|Net20.ActiveCfg = Release|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|Net20.Build.0 = Release|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|Net40.ActiveCfg = Release|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|Net40.Build.0 = Release|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|Win8.ActiveCfg = Release|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|Win8.Build.0 = Release|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|WP81.ActiveCfg = Release|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|WP81.Build.0 = Release|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|WP8-ARM.ActiveCfg = Release|Any CPU + {5E597A82-9DE9-4BA5-AD76-51202190E951}.Release|WP8-x86.ActiveCfg = Release|Any CPU + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Debug|DIRECTX11_2.ActiveCfg = Debug|Any CPU + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Debug|Net20.ActiveCfg = Debug|Any CPU + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Debug|Net40.ActiveCfg = Debug|Any CPU + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Debug|Win8.ActiveCfg = Debug|Any CPU + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Debug|WP81.ActiveCfg = Debug|Any CPU + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Debug|WP8-ARM.ActiveCfg = Debug|Any CPU + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Debug|WP8-x86.ActiveCfg = Debug|Any CPU + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Release|DIRECTX11_2.ActiveCfg = Release|Any CPU + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Release|Net20.ActiveCfg = Release|Any CPU + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Release|Net40.ActiveCfg = Release|Any CPU + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Release|Win8.ActiveCfg = Release|Any CPU + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Release|WP81.ActiveCfg = Release|Any CPU + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Release|WP8-ARM.ActiveCfg = Release|Any CPU + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB}.Release|WP8-x86.ActiveCfg = Release|Any CPU + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|Net20.ActiveCfg = Debug|Net20 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|Net20.Build.0 = Debug|Net20 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|Net40.ActiveCfg = Debug|Net40 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|Net40.Build.0 = Debug|Net40 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|Win8.ActiveCfg = Debug|Win8 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|WP81.ActiveCfg = Debug|WP81 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|Net20.ActiveCfg = Release|Net20 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|Net20.Build.0 = Release|Net20 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|Net40.ActiveCfg = Release|Net40 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|Net40.Build.0 = Release|Net40 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|Win8.ActiveCfg = Release|Win8 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|WP81.ActiveCfg = Release|WP81 + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {4939860C-5D5B-4D56-89C8-1980A9EBB392}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|Net20.ActiveCfg = Debug|Net20 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|Net20.Build.0 = Debug|Net20 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|Net40.ActiveCfg = Debug|Net40 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|Net40.Build.0 = Debug|Net40 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|Win8.ActiveCfg = Debug|Win8 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|WP81.ActiveCfg = Debug|WP81 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|Net20.ActiveCfg = Release|Net20 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|Net20.Build.0 = Release|Net20 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|Net40.ActiveCfg = Release|Net40 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|Net40.Build.0 = Release|Net40 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|Win8.ActiveCfg = Release|Win8 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|WP81.ActiveCfg = Release|WP81 + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {05D17A7B-F200-48C0-B8F9-B7211665A17F}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|Net20.ActiveCfg = Debug|Net20 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|Net20.Build.0 = Debug|Net20 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|Net40.ActiveCfg = Debug|Net40 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|Net40.Build.0 = Debug|Net40 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|Win8.ActiveCfg = Debug|Win8 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|Win8.Build.0 = Debug|Win8 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|WP81.ActiveCfg = Debug|WP81 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|Net20.ActiveCfg = Release|Net20 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|Net20.Build.0 = Release|Net20 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|Net40.ActiveCfg = Release|Net40 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|Net40.Build.0 = Release|Net40 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|Win8.ActiveCfg = Release|Win8 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|Win8.Build.0 = Release|Win8 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|WP81.ActiveCfg = Release|WP81 + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {764D7CE5-F78B-432E-A849-E40BA44522D6}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {931FA266-E756-41CA-9736-8B29235DC999}.Debug|DIRECTX11_2.ActiveCfg = Debug|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Debug|DIRECTX11_2.Build.0 = Debug|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Debug|Net20.ActiveCfg = Debug|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Debug|Net20.Build.0 = Debug|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Debug|Net40.ActiveCfg = Debug|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Debug|Net40.Build.0 = Debug|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Debug|Win8.ActiveCfg = Debug|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Debug|WP81.ActiveCfg = Debug|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Debug|WP8-ARM.ActiveCfg = Debug|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Debug|WP8-x86.ActiveCfg = Debug|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Release|DIRECTX11_2.ActiveCfg = Release|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Release|Net20.ActiveCfg = Release|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Release|Net40.ActiveCfg = Release|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Release|Win8.ActiveCfg = Release|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Release|WP81.ActiveCfg = Release|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Release|WP8-ARM.ActiveCfg = Release|Any CPU + {931FA266-E756-41CA-9736-8B29235DC999}.Release|WP8-x86.ActiveCfg = Release|Any CPU + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Debug|Net20.ActiveCfg = Debug|Net20 + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Debug|Net20.Build.0 = Debug|Net20 + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Debug|Net40.ActiveCfg = Debug|Net40 + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Debug|Win8.ActiveCfg = Debug|Win8 + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Debug|WP81.ActiveCfg = Debug|WP81 + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Release|Net20.ActiveCfg = Release|Net20 + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Release|Net40.ActiveCfg = Release|Net40 + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Release|Win8.ActiveCfg = Release|Win8 + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Release|WP81.ActiveCfg = Release|WP81 + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|Net20.ActiveCfg = Debug|Net20 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|Net20.Build.0 = Debug|Net20 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|Net40.ActiveCfg = Debug|Net40 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|Net40.Build.0 = Debug|Net40 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|Win8.ActiveCfg = Debug|Win8 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|Win8.Build.0 = Debug|Win8 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|WP81.ActiveCfg = Debug|WP81 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|WP81.Build.0 = Debug|WP81 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|Net20.ActiveCfg = Release|Net20 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|Net20.Build.0 = Release|Net20 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|Net40.ActiveCfg = Release|Net40 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|Net40.Build.0 = Release|Net40 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|Win8.ActiveCfg = Release|Win8 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|Win8.Build.0 = Release|Win8 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|WP81.ActiveCfg = Release|WP81 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|WP81.Build.0 = Release|WP81 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|WP8-ARM.Build.0 = Release|WP8-ARM + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9}.Release|WP8-x86.Build.0 = Release|WP8-x86 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|Net20.ActiveCfg = Debug|Net20 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|Net20.Build.0 = Debug|Net20 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|Net40.ActiveCfg = Debug|Net40 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|Net40.Build.0 = Debug|Net40 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|Win8.ActiveCfg = Debug|Win8 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|WP81.ActiveCfg = Debug|WP81 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|Net20.ActiveCfg = Release|Net20 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|Net20.Build.0 = Release|Net20 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|Net40.ActiveCfg = Release|Net40 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|Net40.Build.0 = Release|Net40 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|Win8.ActiveCfg = Release|Win8 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|WP81.ActiveCfg = Release|WP81 + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {BBB50A46-3291-4C62-B884-D1AB64F71EA5}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|Net20.ActiveCfg = Debug|Net20 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|Net20.Build.0 = Debug|Net20 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|Net40.ActiveCfg = Debug|Net40 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|Net40.Build.0 = Debug|Net40 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|Win8.ActiveCfg = Debug|Win8 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|Win8.Build.0 = Debug|Win8 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|WP81.ActiveCfg = Debug|WP81 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|WP81.Build.0 = Debug|WP81 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM + {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|Net20.ActiveCfg = Release|Net20 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|Net20.Build.0 = Release|Net20 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|Net40.ActiveCfg = Release|Net40 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|Net40.Build.0 = Release|Net40 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|Win8.ActiveCfg = Release|Win8 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|Win8.Build.0 = Release|Win8 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|WP81.ActiveCfg = Release|WP81 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|WP81.Build.0 = Release|WP81 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|WP8-ARM.Build.0 = Release|WP8-ARM + {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {53EF08A7-4224-434C-A62C-F29807C1C750}.Release|WP8-x86.Build.0 = Release|WP8-x86 + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|DIRECTX11_2.ActiveCfg = Debug|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|DIRECTX11_2.Build.0 = Debug|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|Net20.ActiveCfg = Debug|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|Net20.Build.0 = Debug|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|Net40.ActiveCfg = Debug|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|Net40.Build.0 = Debug|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|Win8.ActiveCfg = Debug|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|WP81.ActiveCfg = Debug|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|WP8-ARM.ActiveCfg = Debug|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Debug|WP8-x86.ActiveCfg = Debug|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|DIRECTX11_2.ActiveCfg = Release|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|Net20.ActiveCfg = Release|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|Net20.Build.0 = Release|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|Net40.ActiveCfg = Release|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|Net40.Build.0 = Release|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|Win8.ActiveCfg = Release|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|WP81.ActiveCfg = Release|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|WP8-ARM.ActiveCfg = Release|Any CPU + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9}.Release|WP8-x86.ActiveCfg = Release|Any CPU + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|Net20.ActiveCfg = Debug|Net20 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|Net20.Build.0 = Debug|Net20 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|Net40.ActiveCfg = Debug|Net40 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|Net40.Build.0 = Debug|Net40 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|Win8.ActiveCfg = Debug|Win8 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|Win8.Build.0 = Debug|Win8 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|WP81.ActiveCfg = Debug|WP81 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|WP81.Build.0 = Debug|WP81 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|Net20.ActiveCfg = Release|Net20 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|Net20.Build.0 = Release|Net20 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|Net40.ActiveCfg = Release|Net40 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|Net40.Build.0 = Release|Net40 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|Win8.ActiveCfg = Release|Win8 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|Win8.Build.0 = Release|Win8 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|WP81.ActiveCfg = Release|WP81 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|WP81.Build.0 = Release|WP81 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|WP8-ARM.Build.0 = Release|WP8-ARM + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C}.Release|WP8-x86.Build.0 = Release|WP8-x86 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|Net20.ActiveCfg = Debug|Net20 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|Net20.Build.0 = Debug|Net20 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|Net40.ActiveCfg = Debug|Net40 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|Net40.Build.0 = Debug|Net40 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|Win8.ActiveCfg = Debug|Win8 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|WP81.ActiveCfg = Debug|WP81 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|Net20.ActiveCfg = Release|Net20 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|Net20.Build.0 = Release|Net20 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|Net40.ActiveCfg = Release|Net40 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|Net40.Build.0 = Release|Net40 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|Win8.ActiveCfg = Release|Win8 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|WP81.ActiveCfg = Release|WP81 + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|Net20.ActiveCfg = Debug|Net20 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|Net20.Build.0 = Debug|Net20 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|Net40.ActiveCfg = Debug|Net40 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|Net40.Build.0 = Debug|Net40 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|Win8.ActiveCfg = Debug|Win8 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|WP81.ActiveCfg = Debug|WP81 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|Net20.ActiveCfg = Release|Net20 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|Net20.Build.0 = Release|Net20 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|Net40.ActiveCfg = Release|Net40 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|Net40.Build.0 = Release|Net40 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|Win8.ActiveCfg = Release|Win8 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|WP81.ActiveCfg = Release|WP81 + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|DIRECTX11_2.ActiveCfg = Debug|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|DIRECTX11_2.Build.0 = Debug|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|Net20.ActiveCfg = Debug|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|Net20.Build.0 = Debug|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|Net40.ActiveCfg = Debug|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|Net40.Build.0 = Debug|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|Win8.ActiveCfg = Debug|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|Win8.Build.0 = Debug|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|WP81.ActiveCfg = Debug|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|WP81.Build.0 = Debug|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|WP8-ARM.ActiveCfg = Debug|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Debug|WP8-x86.ActiveCfg = Debug|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|DIRECTX11_2.ActiveCfg = Release|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|DIRECTX11_2.Build.0 = Release|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|Net20.ActiveCfg = Release|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|Net20.Build.0 = Release|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|Net40.ActiveCfg = Release|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|Net40.Build.0 = Release|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|Win8.ActiveCfg = Release|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|Win8.Build.0 = Release|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|WP81.ActiveCfg = Release|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|WP81.Build.0 = Release|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|WP8-ARM.ActiveCfg = Release|Any CPU + {15BA35B5-3E54-4715-8857-36F4F96F51FB}.Release|WP8-x86.ActiveCfg = Release|Any CPU + {7329B02D-C504-482A-A156-181D48CE493C}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {7329B02D-C504-482A-A156-181D48CE493C}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {7329B02D-C504-482A-A156-181D48CE493C}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {7329B02D-C504-482A-A156-181D48CE493C}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {7329B02D-C504-482A-A156-181D48CE493C}.Debug|Net20.ActiveCfg = Debug|Net20 + {7329B02D-C504-482A-A156-181D48CE493C}.Debug|Net20.Build.0 = Debug|Net20 + {7329B02D-C504-482A-A156-181D48CE493C}.Debug|Net40.ActiveCfg = Debug|Net40 + {7329B02D-C504-482A-A156-181D48CE493C}.Debug|Net40.Build.0 = Debug|Net40 + {7329B02D-C504-482A-A156-181D48CE493C}.Debug|Win8.ActiveCfg = Debug|Win8 + {7329B02D-C504-482A-A156-181D48CE493C}.Debug|WP81.ActiveCfg = Debug|WP81 + {7329B02D-C504-482A-A156-181D48CE493C}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {7329B02D-C504-482A-A156-181D48CE493C}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {7329B02D-C504-482A-A156-181D48CE493C}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {7329B02D-C504-482A-A156-181D48CE493C}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {7329B02D-C504-482A-A156-181D48CE493C}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {7329B02D-C504-482A-A156-181D48CE493C}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {7329B02D-C504-482A-A156-181D48CE493C}.Release|Net20.ActiveCfg = Release|Net20 + {7329B02D-C504-482A-A156-181D48CE493C}.Release|Net20.Build.0 = Release|Net20 + {7329B02D-C504-482A-A156-181D48CE493C}.Release|Net40.ActiveCfg = Release|Net40 + {7329B02D-C504-482A-A156-181D48CE493C}.Release|Net40.Build.0 = Release|Net40 + {7329B02D-C504-482A-A156-181D48CE493C}.Release|Win8.ActiveCfg = Release|Win8 + {7329B02D-C504-482A-A156-181D48CE493C}.Release|WP81.ActiveCfg = Release|WP81 + {7329B02D-C504-482A-A156-181D48CE493C}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {7329B02D-C504-482A-A156-181D48CE493C}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|Net20.ActiveCfg = Debug|Net20 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|Net20.Build.0 = Debug|Net20 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|Net40.ActiveCfg = Debug|Net40 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|Net40.Build.0 = Debug|Net40 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|Win8.ActiveCfg = Debug|Win8 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|Win8.Build.0 = Debug|Win8 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|WP81.ActiveCfg = Debug|WP81 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|WP81.Build.0 = Debug|WP81 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM + {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|Net20.ActiveCfg = Release|Net20 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|Net20.Build.0 = Release|Net20 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|Net40.ActiveCfg = Release|Net40 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|Net40.Build.0 = Release|Net40 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|Win8.ActiveCfg = Release|Win8 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|Win8.Build.0 = Release|Win8 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|WP81.ActiveCfg = Release|WP81 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|WP81.Build.0 = Release|WP81 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|WP8-ARM.Build.0 = Release|WP8-ARM + {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {B2516A23-1A99-4263-964A-B820FD07FA80}.Release|WP8-x86.Build.0 = Release|WP8-x86 + {46452614-6B06-400F-A74C-1632C79B762C}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {46452614-6B06-400F-A74C-1632C79B762C}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {46452614-6B06-400F-A74C-1632C79B762C}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {46452614-6B06-400F-A74C-1632C79B762C}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {46452614-6B06-400F-A74C-1632C79B762C}.Debug|Net20.ActiveCfg = Debug|Net20 + {46452614-6B06-400F-A74C-1632C79B762C}.Debug|Net20.Build.0 = Debug|Net20 + {46452614-6B06-400F-A74C-1632C79B762C}.Debug|Net40.ActiveCfg = Debug|Net40 + {46452614-6B06-400F-A74C-1632C79B762C}.Debug|Net40.Build.0 = Debug|Net40 + {46452614-6B06-400F-A74C-1632C79B762C}.Debug|Win8.ActiveCfg = Debug|Win8 + {46452614-6B06-400F-A74C-1632C79B762C}.Debug|Win8.Build.0 = Debug|Win8 + {46452614-6B06-400F-A74C-1632C79B762C}.Debug|WP81.ActiveCfg = Debug|WP81 + {46452614-6B06-400F-A74C-1632C79B762C}.Debug|WP81.Build.0 = Debug|WP81 + {46452614-6B06-400F-A74C-1632C79B762C}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {46452614-6B06-400F-A74C-1632C79B762C}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM + {46452614-6B06-400F-A74C-1632C79B762C}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {46452614-6B06-400F-A74C-1632C79B762C}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 + {46452614-6B06-400F-A74C-1632C79B762C}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {46452614-6B06-400F-A74C-1632C79B762C}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {46452614-6B06-400F-A74C-1632C79B762C}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {46452614-6B06-400F-A74C-1632C79B762C}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {46452614-6B06-400F-A74C-1632C79B762C}.Release|Net20.ActiveCfg = Release|Net20 + {46452614-6B06-400F-A74C-1632C79B762C}.Release|Net20.Build.0 = Release|Net20 + {46452614-6B06-400F-A74C-1632C79B762C}.Release|Net40.ActiveCfg = Release|Net40 + {46452614-6B06-400F-A74C-1632C79B762C}.Release|Net40.Build.0 = Release|Net40 + {46452614-6B06-400F-A74C-1632C79B762C}.Release|Win8.ActiveCfg = Release|Win8 + {46452614-6B06-400F-A74C-1632C79B762C}.Release|Win8.Build.0 = Release|Win8 + {46452614-6B06-400F-A74C-1632C79B762C}.Release|WP81.ActiveCfg = Release|WP81 + {46452614-6B06-400F-A74C-1632C79B762C}.Release|WP81.Build.0 = Release|WP81 + {46452614-6B06-400F-A74C-1632C79B762C}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {46452614-6B06-400F-A74C-1632C79B762C}.Release|WP8-ARM.Build.0 = Release|WP8-ARM + {46452614-6B06-400F-A74C-1632C79B762C}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {46452614-6B06-400F-A74C-1632C79B762C}.Release|WP8-x86.Build.0 = Release|WP8-x86 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|Net20.ActiveCfg = Debug|Net20 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|Net40.ActiveCfg = Debug|Net40 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|Net40.Build.0 = Debug|Net40 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|Win8.ActiveCfg = Debug|Win8 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|WP81.ActiveCfg = Debug|WP81 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|Net20.ActiveCfg = Release|Net20 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|Net40.ActiveCfg = Release|Net40 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|Net40.Build.0 = Release|Net40 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|Win8.ActiveCfg = Release|Win8 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|WP81.ActiveCfg = Release|WP81 + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|Net20.ActiveCfg = Debug|Net20 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|Net20.Build.0 = Debug|Net20 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|Net40.ActiveCfg = Debug|Net40 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|Net40.Build.0 = Debug|Net40 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|Win8.ActiveCfg = Debug|Win8 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|WP81.ActiveCfg = Debug|WP81 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {76FD0713-F217-4485-89B3-C6423DB46C58}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|Net20.ActiveCfg = Release|Net20 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|Net20.Build.0 = Release|Net20 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|Net40.ActiveCfg = Release|Net40 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|Net40.Build.0 = Release|Net40 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|Win8.ActiveCfg = Release|Win8 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|WP81.ActiveCfg = Release|WP81 + {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {76FD0713-F217-4485-89B3-C6423DB46C58}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|Net20.ActiveCfg = Debug|Net20 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|Net20.Build.0 = Debug|Net20 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|Net40.ActiveCfg = Debug|Net40 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|Net40.Build.0 = Debug|Net40 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|Win8.ActiveCfg = Debug|Win8 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|Win8.Build.0 = Debug|Win8 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|WP81.ActiveCfg = Debug|WP81 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|WP81.Build.0 = Debug|WP81 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|Net20.ActiveCfg = Release|Net20 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|Net20.Build.0 = Release|Net20 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|Net40.ActiveCfg = Release|Net40 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|Net40.Build.0 = Release|Net40 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|Win8.ActiveCfg = Release|Win8 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|Win8.Build.0 = Release|Win8 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|WP81.ActiveCfg = Release|WP81 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|WP81.Build.0 = Release|WP81 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|WP8-ARM.Build.0 = Release|WP8-ARM + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F}.Release|WP8-x86.Build.0 = Release|WP8-x86 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|Net20.ActiveCfg = Debug|Net20 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|Net20.Build.0 = Debug|Net20 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|Net40.ActiveCfg = Debug|Net40 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|Net40.Build.0 = Debug|Net40 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|Win8.ActiveCfg = Debug|Win8 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|Win8.Build.0 = Debug|Win8 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|WP81.ActiveCfg = Debug|WP81 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|WP81.Build.0 = Debug|WP81 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|Net20.ActiveCfg = Release|Net20 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|Net20.Build.0 = Release|Net20 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|Net40.ActiveCfg = Release|Net40 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|Net40.Build.0 = Release|Net40 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|Win8.ActiveCfg = Release|Win8 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|Win8.Build.0 = Release|Win8 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|WP81.ActiveCfg = Release|WP81 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|WP81.Build.0 = Release|WP81 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|WP8-ARM.Build.0 = Release|WP8-ARM + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {1FA327C8-6C48-4FFC-9235-B98B7521B79D}.Release|WP8-x86.Build.0 = Release|WP8-x86 + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Debug|Net20.ActiveCfg = Debug|Net20 + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Debug|Net40.ActiveCfg = Debug|Net40 + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Debug|Win8.ActiveCfg = Debug|Win8 + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Debug|WP81.ActiveCfg = Debug|WP81 + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Release|Net20.ActiveCfg = Release|Net20 + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Release|Net40.ActiveCfg = Release|Net40 + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Release|Win8.ActiveCfg = Release|Win8 + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Release|WP81.ActiveCfg = Release|WP81 + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Debug|Mixed Platforms.ActiveCfg = Debug|WP8-x86 + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Debug|Mixed Platforms.Build.0 = Debug|WP8-x86 + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Debug|Net20.ActiveCfg = Debug|Net20 + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Debug|Net40.ActiveCfg = Debug|Net40 + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Debug|Win8.ActiveCfg = Debug|Win8 + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Debug|WP81.ActiveCfg = Debug|WP81 + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Release|Mixed Platforms.ActiveCfg = Release|WP8-x86 + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Release|Mixed Platforms.Build.0 = Release|WP8-x86 + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Release|Net20.ActiveCfg = Release|Net20 + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Release|Net40.ActiveCfg = Release|Net40 + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Release|Win8.ActiveCfg = Release|Win8 + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Release|WP81.ActiveCfg = Release|WP81 + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {F826CCCE-4B72-47F4-9493-DFCB51C106B7}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Debug|DIRECTX11_2.ActiveCfg = Debug|DIRECTX11_2 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Debug|DIRECTX11_2.Build.0 = Debug|DIRECTX11_2 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Debug|Mixed Platforms.ActiveCfg = Debug|Win8 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Debug|Mixed Platforms.Build.0 = Debug|Win8 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Debug|Net20.ActiveCfg = Debug|Net20 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Debug|Net20.Build.0 = Debug|Net20 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Debug|Net40.ActiveCfg = Debug|Net40 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Debug|Net40.Build.0 = Debug|Net40 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Debug|Win8.ActiveCfg = Debug|Win8 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Debug|Win8.Build.0 = Debug|Win8 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Debug|WP81.ActiveCfg = Debug|WP81 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Debug|WP81.Build.0 = Debug|WP81 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Debug|WP8-ARM.ActiveCfg = Debug|WP8-ARM + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Debug|WP8-ARM.Build.0 = Debug|WP8-ARM + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Debug|WP8-x86.ActiveCfg = Debug|WP8-x86 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Debug|WP8-x86.Build.0 = Debug|WP8-x86 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Release|DIRECTX11_2.ActiveCfg = Release|DIRECTX11_2 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Release|DIRECTX11_2.Build.0 = Release|DIRECTX11_2 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Release|Mixed Platforms.ActiveCfg = Release|Win8 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Release|Mixed Platforms.Build.0 = Release|Win8 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Release|Net20.ActiveCfg = Release|Net20 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Release|Net20.Build.0 = Release|Net20 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Release|Net40.ActiveCfg = Release|Net40 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Release|Net40.Build.0 = Release|Net40 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Release|Win8.ActiveCfg = Release|Win8 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Release|Win8.Build.0 = Release|Win8 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Release|WP81.ActiveCfg = Release|WP81 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Release|WP81.Build.0 = Release|WP81 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Release|WP8-ARM.ActiveCfg = Release|WP8-ARM + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Release|WP8-ARM.Build.0 = Release|WP8-ARM + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Release|WP8-x86.ActiveCfg = Release|WP8-x86 + {49E4485F-3A2A-4C35-A159-12ECCFC00396}.Release|WP8-x86.Build.0 = Release|WP8-x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {D0BCD56A-41C4-4A4E-8590-26864CED07FF} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {361D3F81-A48A-47F2-80DF-CA4F9536CB4E} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {C97878F4-1510-4BBA-8153-BD71DA7D50D8} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {618AFA87-81A8-4B1C-8876-5457D49F2DEF} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {736DFB52-1AFE-4EFF-9710-89046AB5B1F9} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {E927F2D5-8E27-462A-8687-CB207EE01164} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {3FC6DE77-B412-4101-9E64-6B9AA831179B} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {4995127E-0B8E-45B8-80C4-6BAC1BBE3783} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {B4D984DF-85B8-4BBF-8C3B-5CEF905F40D9} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {112F146B-7C01-490B-B943-EA9341ACCAF2} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {C6AE9847-3089-4FE4-91DF-B1A3EE115CF4} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {4E2D9A17-2195-4A51-AAE3-924517440293} = {F1AF9A3B-7856-46C9-992A-391E5455BF1F} + {31F85A16-CB01-4456-BE3C-76E9FF3A1343} = {F1AF9A3B-7856-46C9-992A-391E5455BF1F} + {5E597A82-9DE9-4BA5-AD76-51202190E951} = {F1AF9A3B-7856-46C9-992A-391E5455BF1F} + {9AA405CA-B7FD-44D0-9EBC-21F5D0F44DEB} = {57C5C966-ADB2-43F2-BB54-99BCB56C9F10} + {4939860C-5D5B-4D56-89C8-1980A9EBB392} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {05D17A7B-F200-48C0-B8F9-B7211665A17F} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {764D7CE5-F78B-432E-A849-E40BA44522D6} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {931FA266-E756-41CA-9736-8B29235DC999} = {1B526C0E-EE4A-4E8F-BF8F-8C7397FB4918} + {874DEC63-9AB9-4A09-B1EA-E8FB1F1B68A1} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {CA21A201-078B-4EBE-A2AB-C3B1FFEC99F9} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {BBB50A46-3291-4C62-B884-D1AB64F71EA5} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {53EF08A7-4224-434C-A62C-F29807C1C750} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} + {4E0E6A4D-930D-4660-8DE0-E30FF1F9F4A9} = {1B526C0E-EE4A-4E8F-BF8F-8C7397FB4918} + {9FF0707C-75BB-4984-A01F-B9EAAD293F6C} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} + {8BFFF9D1-84EC-4FBA-9BEB-710ECF1857A8} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} + {BCE106B4-0C81-4705-8A9C-C4C4F5EAB702} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} + {15BA35B5-3E54-4715-8857-36F4F96F51FB} = {F1AF9A3B-7856-46C9-992A-391E5455BF1F} + {7329B02D-C504-482A-A156-181D48CE493C} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} + {B2516A23-1A99-4263-964A-B820FD07FA80} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} + {46452614-6B06-400F-A74C-1632C79B762C} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} + {90F4C7BC-7A08-4C0F-A5D7-ED9D1D3900D4} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} + {76FD0713-F217-4485-89B3-C6423DB46C58} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} + {ED9F81D3-C2F1-47CA-A25C-8F2CEFE70D0F} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} + {1FA327C8-6C48-4FFC-9235-B98B7521B79D} = {529B140D-B91D-49EA-B173-9ADD6AB2A2A3} + {FBE5DD99-00A0-4FED-A116-941A46A0C0D0} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {F826CCCE-4B72-47F4-9493-DFCB51C106B7} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + {49E4485F-3A2A-4C35-A159-12ECCFC00396} = {CC8DB471-0644-430D-9D4B-808A2475BEC0} + EndGlobalSection +EndGlobal diff --git a/Source/Mapping.xml b/Source/Mapping.xml index 416a41814..f3b731e9f 100644 --- a/Source/Mapping.xml +++ b/Source/Mapping.xml @@ -1,193 +1,193 @@ - - - - - - - - $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc11\overrides\wp8--> - $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc11\overrides - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\11.0\Setup\VC\ProductDir;Include - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows Phone\v8.0\InstallationFolder;Include - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows Phone\v8.0\InstallationFolder;Include\abi - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows Phone\v8.0\InstallationFolder;Include\mincore - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows Phone\v8.0\InstallationFolder;Include\minwin - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows Phone\v8.0\InstallationFolder;Include\wrl - - - - - - $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc12\overrides - $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc12\overrides\wp81 - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\12.0\Setup\VC\ProductDir;include - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhoneApp\v8.1\InstallationFolder;Include - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhoneApp\v8.1\InstallationFolder;Include\abi - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhoneApp\v8.1\InstallationFolder;Include\mincore - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhoneApp\v8.1\InstallationFolder;Include\minwin - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhoneApp\v8.1\InstallationFolder;Include\wrl - - - - - - $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc11\overrides\shared - $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc11\overrides\um - $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc11\overrides - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\11.0\Setup\VC\ProductDir;Include - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots\KitsRoot;Include\shared - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots\KitsRoot;Include\um - - - - $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc12\overrides\shared - $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc12\overrides\um - $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc12\overrides - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\12.0\Setup\VC\ProductDir;Include - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots\KitsRoot81;Include\shared - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots\KitsRoot81;Include\um - - - - - - - - - $(DXSDK_DIR)\include - - - - $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc10\Include - $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc10\PlatformSDK - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VC\ProductDir;Include - - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1\InstallationFolder;Include - - - =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0a\InstallationFolder;Include - - - - error: pasting .*a valid preprocessing token - - - - - - // For Win8 we need to force to use include headers for MetroApp only - #define WINAPI_FAMILY WINAPI_PARTITION_APP - - - - - // For Win8 we need to force to use include headers for MetroApp only - #define WINAPI_FAMILY WINAPI_FAMILY_PC_APP - - - - - - - // For WP8 we need to force to use include headers for WPPhone App only - #define WINAPI_FAMILY WINAPI_FAMILY_PHONE_APP - - - - - - // For WP8.1 we need to force to use include headers for MetroApp only - #define WINAPI_FAMILY WINAPI_FAMILY_PHONE_APP - - - - - - // Use unicode - #define UNICODE - // for SAL annotations - #define _PREFAST_ - // To force GUID to be declared - #define INITGUID - // Wrap all declspec with gccxml - #define __declspec(x) __attribute__((gccxml(#x))) - // For XAudio2 patch - #define __unaligned __attribute((__unaligned)) - - - - - enum __SAL_YesNo {}; - - - - - - SharpDX\Mapping.xml - SharpDX.DXGI\Mapping.xml - - SharpDX.D3DCompiler\Mapping.xml - - - Mapping.Direct3D1x.xml - - - - SharpDX.Direct3D10\Mapping.xml - - - - SharpDX.Direct3D11\Mapping.xml - - - SharpDX.XAudio2\Mapping.xml - SharpDX.MediaFoundation\Mapping.xml - - - - SharpDX.Direct3D11.Effects\Mapping.xml - - SharpDX.Animation\Mapping.xml - SharpDX.DirectComposition\Mapping.xml - SharpDX.DirectManipulation\Mapping.xml - - - - - SharpDX.Direct2D1\Mapping.xml - - SharpDX.DirectInput\Mapping.xml - SharpDX.Direct3D9\Mapping.xml - SharpDX.DirectSound\Mapping.xml - SharpDX.XACT3\Mapping.xml - - SharpDX.XAudio2\Mapping.xml - - SharpDX.XInput\Mapping.xml - SharpDX.RawInput\Mapping.xml - - SharpDX.MediaFoundation\Mapping.xml - + + + + + + + + $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc11\overrides\wp8--> + $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc11\overrides + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\11.0\Setup\VC\ProductDir;Include + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows Phone\v8.0\InstallationFolder;Include + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows Phone\v8.0\InstallationFolder;Include\abi + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows Phone\v8.0\InstallationFolder;Include\mincore + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows Phone\v8.0\InstallationFolder;Include\minwin + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows Phone\v8.0\InstallationFolder;Include\wrl + + + + + + $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc12\overrides + $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc12\overrides\wp81 + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\12.0\Setup\VC\ProductDir;include + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhoneApp\v8.1\InstallationFolder;Include + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhoneApp\v8.1\InstallationFolder;Include\abi + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhoneApp\v8.1\InstallationFolder;Include\mincore + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhoneApp\v8.1\InstallationFolder;Include\minwin + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\WindowsPhoneApp\v8.1\InstallationFolder;Include\wrl + + + + + + $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc11\overrides\shared + $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc11\overrides\um + $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc11\overrides + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\11.0\Setup\VC\ProductDir;Include + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots\KitsRoot;Include\shared + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots\KitsRoot;Include\um + + + + $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc12\overrides\shared + $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc12\overrides\um + $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc12\overrides + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\12.0\Setup\VC\ProductDir;Include + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots\KitsRoot81;Include\shared + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots\KitsRoot81;Include\um + + + + + + + + + $(DXSDK_DIR)\include + + + + $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc10\Include + $(THIS_CONFIG_PATH)\..\External\gccxml\share\gccxml-0.9\vc10\PlatformSDK + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VC\ProductDir;Include + + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1\InstallationFolder;Include + + + =HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0a\InstallationFolder;Include + + + + error: pasting .*a valid preprocessing token + + + + + + // For Win8 we need to force to use include headers for MetroApp only + #define WINAPI_FAMILY WINAPI_PARTITION_APP + + + + + // For Win8 we need to force to use include headers for MetroApp only + #define WINAPI_FAMILY WINAPI_FAMILY_PC_APP + + + + + + + // For WP8 we need to force to use include headers for WPPhone App only + #define WINAPI_FAMILY WINAPI_FAMILY_PHONE_APP + + + + + + // For WP8.1 we need to force to use include headers for MetroApp only + #define WINAPI_FAMILY WINAPI_FAMILY_PHONE_APP + + + + + + // Use unicode + #define UNICODE + // for SAL annotations + #define _PREFAST_ + // To force GUID to be declared + #define INITGUID + // Wrap all declspec with gccxml + #define __declspec(x) __attribute__((gccxml(#x))) + // For XAudio2 patch + #define __unaligned __attribute((__unaligned)) + + + + + enum __SAL_YesNo {}; + + + + + + SharpDX\Mapping.xml + SharpDX.DXGI\Mapping.xml + + SharpDX.D3DCompiler\Mapping.xml + + + Mapping.Direct3D1x.xml + + + + SharpDX.Direct3D10\Mapping.xml + + + + SharpDX.Direct3D11\Mapping.xml + + + SharpDX.XAudio2\Mapping.xml + SharpDX.MediaFoundation\Mapping.xml + + + + SharpDX.Direct3D11.Effects\Mapping.xml + + SharpDX.Animation\Mapping.xml + SharpDX.DirectComposition\Mapping.xml + SharpDX.DirectManipulation\Mapping.xml + + + + + SharpDX.Direct2D1\Mapping.xml + + SharpDX.DirectInput\Mapping.xml + SharpDX.Direct3D9\Mapping.xml + SharpDX.DirectSound\Mapping.xml + SharpDX.XACT3\Mapping.xml + + SharpDX.XAudio2\Mapping.xml + + SharpDX.XInput\Mapping.xml + SharpDX.RawInput\Mapping.xml + + SharpDX.MediaFoundation\Mapping.xml + \ No newline at end of file diff --git a/Source/SharpDX.Direct3D11/StreamOutputElement.cs b/Source/SharpDX.Direct3D11/StreamOutputElement.cs index 5e2e02c5d..a12f164e0 100644 --- a/Source/SharpDX.Direct3D11/StreamOutputElement.cs +++ b/Source/SharpDX.Direct3D11/StreamOutputElement.cs @@ -19,11 +19,9 @@ // THE SOFTWARE. using System; -using SharpDX.Serialization; - namespace SharpDX.Direct3D11 { - public partial struct StreamOutputElement : IDataSerializable + public partial struct StreamOutputElement { /// /// Initializes a new instance of the struct. @@ -43,15 +41,5 @@ public StreamOutputElement(int streamIndex, string semanticName, int semanticInd ComponentCount = componentCount; OutputSlot = outputSlot; } - - void IDataSerializable.Serialize(BinarySerializer serializer) - { - serializer.Serialize(ref Stream); - serializer.Serialize(ref SemanticName); - serializer.Serialize(ref SemanticIndex); - serializer.Serialize(ref StartComponent); - serializer.Serialize(ref ComponentCount); - serializer.Serialize(ref OutputSlot); - } } } \ No newline at end of file diff --git a/Source/SharpDX/Angle.cs b/Source/SharpDX.Mathematics/Angle.cs similarity index 95% rename from Source/SharpDX/Angle.cs rename to Source/SharpDX.Mathematics/Angle.cs index dbaef8d56..bf2b89805 100644 --- a/Source/SharpDX/Angle.cs +++ b/Source/SharpDX.Mathematics/Angle.cs @@ -1,803 +1,785 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ----------------------------------------------------------------------------- -// Original code from SlimMath project. http://code.google.com/p/slimmath/ -// Greetings to SlimDX Group. Original code published with the following license: -// ----------------------------------------------------------------------------- -/* -* Copyright (c) 2007-2011 SlimDX Group -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text; -using System.Globalization; -using SharpDX.Serialization; - - -namespace SharpDX -{ - /// - /// Represents a unit independent angle using a single-precision floating-point - /// internal representation. - /// - [StructLayout(LayoutKind.Explicit)] - public struct AngleSingle : IComparable, IComparable, IEquatable, IFormattable, IDataSerializable - { - /// - /// A value that specifies the size of a single degree. - /// - public const float Degree = 0.002777777777777778f; - - /// - /// A value that specifies the size of a single minute. - /// - public const float Minute = 0.000046296296296296f; - - /// - /// A value that specifies the size of a single second. - /// - public const float Second = 0.000000771604938272f; - - /// - /// A value that specifies the size of a single radian. - /// - public const float Radian = 0.159154943091895336f; - - /// - /// A value that specifies the size of a single milliradian. - /// - public const float Milliradian = 0.0001591549431f; - - /// - /// A value that specifies the size of a single gradian. - /// - public const float Gradian = 0.0025f; - - /// - /// The internal representation of the angle. - /// - [FieldOffset(0)] - float radians; - - [FieldOffset(0)] - private int radiansInt; - - /// - /// Initializes a new instance of the SharpDX.AngleSingle structure with the - /// given unit dependant angle and unit type. - /// - /// A unit dependant measure of the angle. - /// The type of unit the angle argument is. - public AngleSingle(float angle, AngleType type) - { - radiansInt = 0; - switch (type) - { - case AngleType.Revolution: - radians = MathUtil.RevolutionsToRadians(angle); - break; - - case AngleType.Degree: - radians = MathUtil.DegreesToRadians(angle); - break; - - case AngleType.Radian: - radians = angle; - break; - - case AngleType.Gradian: - radians = MathUtil.GradiansToRadians(angle); - break; - - default: - radians = 0.0f; - break; - } - } - - /// - /// Initializes a new instance of the SharpDX.AngleSingle structure using the - /// arc length formula (θ = s/r). - /// - /// The measure of the arc. - /// The radius of the circle. - public AngleSingle(float arcLength, float radius) - { - radiansInt = 0; - radians = arcLength / radius; - } - - /// - /// Wraps this SharpDX.AngleSingle to be in the range [π, -π]. - /// - public void Wrap() - { - float newangle = (float)Math.IEEERemainder(radians, MathUtil.TwoPi); - - if (newangle <= -MathUtil.Pi) - newangle += MathUtil.TwoPi; - else if (newangle > MathUtil.Pi) - newangle -= MathUtil.TwoPi; - - radians = newangle; - } - - /// - /// Wraps this SharpDX.AngleSingle to be in the range [0, 2π). - /// - public void WrapPositive() - { - float newangle = radians % MathUtil.TwoPi; - - if (newangle < 0.0) - newangle += MathUtil.TwoPi; - - radians = newangle; - } - - /// - /// Gets or sets the total number of revolutions this SharpDX.AngleSingle represents. - /// - public float Revolutions - { - get { return MathUtil.RadiansToRevolutions(radians); } - set { radians = MathUtil.RevolutionsToRadians(value); } - } - - /// - /// Gets or sets the total number of degrees this SharpDX.AngleSingle represents. - /// - public float Degrees - { - get { return MathUtil.RadiansToDegrees(radians); } - set { radians = MathUtil.DegreesToRadians(value); } - } - - /// - /// Gets or sets the minutes component of the degrees this SharpDX.AngleSingle represents. - /// When setting the minutes, if the value is in the range (-60, 60) the whole degrees are - /// not changed; otherwise, the whole degrees may be changed. Fractional values may set - /// the seconds component. - /// - public float Minutes - { - get - { - float degrees = MathUtil.RadiansToDegrees(radians); - - if (degrees < 0) - { - float degreesfloor = (float)Math.Ceiling(degrees); - return (degrees - degreesfloor) * 60.0f; - } - else - { - float degreesfloor = (float)Math.Floor(degrees); - return (degrees - degreesfloor) * 60.0f; - } - } - set - { - float degrees = MathUtil.RadiansToDegrees(radians); - float degreesfloor = (float)Math.Floor(degrees); - - degreesfloor += value / 60.0f; - radians = MathUtil.DegreesToRadians(degreesfloor); - } - } - - /// - /// Gets or sets the seconds of the degrees this SharpDX.AngleSingle represents. - /// When setting the seconds, if the value is in the range (-60, 60) the whole minutes - /// or whole degrees are not changed; otherwise, the whole minutes or whole degrees - /// may be changed. - /// - public float Seconds - { - get - { - float degrees = MathUtil.RadiansToDegrees(radians); - - if (degrees < 0) - { - float degreesfloor = (float)Math.Ceiling(degrees); - - float minutes = (degrees - degreesfloor) * 60.0f; - float minutesfloor = (float)Math.Ceiling(minutes); - - return (minutes - minutesfloor) * 60.0f; - } - else - { - float degreesfloor = (float)Math.Floor(degrees); - - float minutes = (degrees - degreesfloor) * 60.0f; - float minutesfloor = (float)Math.Floor(minutes); - - return (minutes - minutesfloor) * 60.0f; - } - } - set - { - float degrees = MathUtil.RadiansToDegrees(radians); - float degreesfloor = (float)Math.Floor(degrees); - - float minutes = (degrees - degreesfloor) * 60.0f; - float minutesfloor = (float)Math.Floor(minutes); - - minutesfloor += value / 60.0f; - degreesfloor += minutesfloor / 60.0f; - radians = MathUtil.DegreesToRadians(degreesfloor); - } - } - - /// - /// Gets or sets the total number of radians this SharpDX.AngleSingle represents. - /// - public float Radians - { - get { return radians; } - set { radians = value; } - } - - /// - /// Gets or sets the total number of milliradians this SharpDX.AngleSingle represents. - /// One milliradian is equal to 1/(2000π). - /// - public float Milliradians - { - get { return radians / (Milliradian * MathUtil.TwoPi); } - set { radians = value * (Milliradian * MathUtil.TwoPi); } - } - - /// - /// Gets or sets the total number of gradians this SharpDX.AngleSingle represents. - /// - public float Gradians - { - get { return MathUtil.RadiansToGradians(radians); } - set { radians = MathUtil.RadiansToGradians(value); } - } - - /// - /// Gets a System.Boolean that determines whether this SharpDX.Angle - /// is a right angle (i.e. 90° or π/2). - /// - public bool IsRight - { - get { return radians == MathUtil.PiOverTwo; } - } - - /// - /// Gets a System.Boolean that determines whether this SharpDX.Angle - /// is a straight angle (i.e. 180° or π). - /// - public bool IsStraight - { - get { return radians == MathUtil.Pi; } - } - - /// - /// Gets a System.Boolean that determines whether this SharpDX.Angle - /// is a full rotation angle (i.e. 360° or 2π). - /// - public bool IsFullRotation - { - get { return radians == MathUtil.TwoPi; } - } - - /// - /// Gets a System.Boolean that determines whether this SharpDX.Angle - /// is an oblique angle (i.e. is not 90° or a multiple of 90°). - /// - public bool IsOblique - { - get { return WrapPositive(this).radians != MathUtil.PiOverTwo; } - } - - /// - /// Gets a System.Boolean that determines whether this SharpDX.Angle - /// is an acute angle (i.e. less than 90° but greater than 0°). - /// - public bool IsAcute - { - get { return radians > 0.0 && radians < MathUtil.PiOverTwo; } - } - - /// - /// Gets a System.Boolean that determines whether this SharpDX.Angle - /// is an obtuse angle (i.e. greater than 90° but less than 180°). - /// - public bool IsObtuse - { - get { return radians > MathUtil.PiOverTwo && radians < MathUtil.Pi; } - } - - /// - /// Gets a System.Boolean that determines whether this SharpDX.Angle - /// is a reflex angle (i.e. greater than 180° but less than 360°). - /// - public bool IsReflex - { - get { return radians > MathUtil.Pi && radians < MathUtil.TwoPi; } - } - - /// - /// Gets a SharpDX.AngleSingle instance that complements this angle (i.e. the two angles add to 90°). - /// - public AngleSingle Complement - { - get { return new AngleSingle(MathUtil.PiOverTwo - radians, AngleType.Radian); } - } - - /// - /// Gets a SharpDX.AngleSingle instance that supplements this angle (i.e. the two angles add to 180°). - /// - public AngleSingle Supplement - { - get { return new AngleSingle(MathUtil.Pi - radians, AngleType.Radian); } - } - - /// - /// Wraps the SharpDX.AngleSingle given in the value argument to be in the range [π, -π]. - /// - /// A SharpDX.AngleSingle to wrap. - /// The SharpDX.AngleSingle that is wrapped. - public static AngleSingle Wrap(AngleSingle value) - { - value.Wrap(); - return value; - } - - /// - /// Wraps the SharpDX.AngleSingle given in the value argument to be in the range [0, 2π). - /// - /// A SharpDX.AngleSingle to wrap. - /// The SharpDX.AngleSingle that is wrapped. - public static AngleSingle WrapPositive(AngleSingle value) - { - value.WrapPositive(); - return value; - } - - /// - /// Compares two SharpDX.AngleSingle instances and returns the smaller angle. - /// - /// The first SharpDX.AngleSingle instance to compare. - /// The second SharpDX.AngleSingle instance to compare. - /// The smaller of the two given SharpDX.AngleSingle instances. - public static AngleSingle Min(AngleSingle left, AngleSingle right) - { - if (left.radians < right.radians) - return left; - - return right; - } - - /// - /// Compares two SharpDX.AngleSingle instances and returns the greater angle. - /// - /// The first SharpDX.AngleSingle instance to compare. - /// The second SharpDX.AngleSingle instance to compare. - /// The greater of the two given SharpDX.AngleSingle instances. - public static AngleSingle Max(AngleSingle left, AngleSingle right) - { - if (left.radians > right.radians) - return left; - - return right; - } - - /// - /// Adds two SharpDX.AngleSingle objects and returns the result. - /// - /// The first object to add. - /// The second object to add. - /// The value of the two objects added together. - public static AngleSingle Add(AngleSingle left, AngleSingle right) - { - return new AngleSingle(left.radians + right.radians, AngleType.Radian); - } - - /// - /// Subtracts two SharpDX.AngleSingle objects and returns the result. - /// - /// The first object to subtract. - /// The second object to subtract. - /// The value of the two objects subtracted. - public static AngleSingle Subtract(AngleSingle left, AngleSingle right) - { - return new AngleSingle(left.radians - right.radians, AngleType.Radian); - } - - /// - /// Multiplies two SharpDX.AngleSingle objects and returns the result. - /// - /// The first object to multiply. - /// The second object to multiply. - /// The value of the two objects multiplied together. - public static AngleSingle Multiply(AngleSingle left, AngleSingle right) - { - return new AngleSingle(left.radians * right.radians, AngleType.Radian); - } - - /// - /// Divides two SharpDX.AngleSingle objects and returns the result. - /// - /// The numerator object. - /// The denominator object. - /// The value of the two objects divided. - public static AngleSingle Divide(AngleSingle left, AngleSingle right) - { - return new AngleSingle(left.radians / right.radians, AngleType.Radian); - } - - /// - /// Gets a new SharpDX.AngleSingle instance that represents the zero angle (i.e. 0°). - /// - public static AngleSingle ZeroAngle - { - get { return new AngleSingle(0.0f, AngleType.Radian); } - } - - /// - /// Gets a new SharpDX.AngleSingle instance that represents the right angle (i.e. 90° or π/2). - /// - public static AngleSingle RightAngle - { - get { return new AngleSingle(MathUtil.PiOverTwo, AngleType.Radian); } - } - - /// - /// Gets a new SharpDX.AngleSingle instance that represents the straight angle (i.e. 180° or π). - /// - public static AngleSingle StraightAngle - { - get { return new AngleSingle(MathUtil.Pi, AngleType.Radian); } - } - - /// - /// Gets a new SharpDX.AngleSingle instance that represents the full rotation angle (i.e. 360° or 2π). - /// - public static AngleSingle FullRotationAngle - { - get { return new AngleSingle(MathUtil.TwoPi, AngleType.Radian); } - } - - /// - /// Returns a System.Boolean that indicates whether the values of two SharpDX.Angle - /// objects are equal. - /// - /// The first object to compare. - /// The second object to compare. - /// True if the left and right parameters have the same value; otherwise, false. - public static bool operator ==(AngleSingle left, AngleSingle right) - { - return left.radians == right.radians; - } - - /// - /// Returns a System.Boolean that indicates whether the values of two SharpDX.Angle - /// objects are not equal. - /// - /// The first object to compare. - /// The second object to compare. - /// True if the left and right parameters do not have the same value; otherwise, false. - public static bool operator !=(AngleSingle left, AngleSingle right) - { - return left.radians != right.radians; - } - - /// - /// Returns a System.Boolean that indicates whether a SharpDX.Angle - /// object is less than another SharpDX.AngleSingle object. - /// - /// The first object to compare. - /// The second object to compare. - /// True if left is less than right; otherwise, false. - public static bool operator <(AngleSingle left, AngleSingle right) - { - return left.radians < right.radians; - } - - /// - /// Returns a System.Boolean that indicates whether a SharpDX.Angle - /// object is greater than another SharpDX.AngleSingle object. - /// - /// The first object to compare. - /// The second object to compare. - /// True if left is greater than right; otherwise, false. - public static bool operator >(AngleSingle left, AngleSingle right) - { - return left.radians > right.radians; - } - - /// - /// Returns a System.Boolean that indicates whether a SharpDX.Angle - /// object is less than or equal to another SharpDX.AngleSingle object. - /// - /// The first object to compare. - /// The second object to compare. - /// True if left is less than or equal to right; otherwise, false. - public static bool operator <=(AngleSingle left, AngleSingle right) - { - return left.radians <= right.radians; - } - - /// - /// Returns a System.Boolean that indicates whether a SharpDX.Angle - /// object is greater than or equal to another SharpDX.AngleSingle object. - /// - /// The first object to compare. - /// The second object to compare. - /// True if left is greater than or equal to right; otherwise, false. - public static bool operator >=(AngleSingle left, AngleSingle right) - { - return left.radians >= right.radians; - } - - /// - /// Returns the value of the SharpDX.AngleSingle operand. (The sign of - /// the operand is unchanged.) - /// - /// A SharpDX.AngleSingle object. - /// The value of the value parameter. - public static AngleSingle operator +(AngleSingle value) - { - return value; - } - - /// - /// Returns the the negated value of the SharpDX.AngleSingle operand. - /// - /// A SharpDX.AngleSingle object. - /// The negated value of the value parameter. - public static AngleSingle operator -(AngleSingle value) - { - return new AngleSingle(-value.radians, AngleType.Radian); - } - - /// - /// Adds two SharpDX.AngleSingle objects and returns the result. - /// - /// The first object to add. - /// The second object to add. - /// The value of the two objects added together. - public static AngleSingle operator +(AngleSingle left, AngleSingle right) - { - return new AngleSingle(left.radians + right.radians, AngleType.Radian); - } - - /// - /// Subtracts two SharpDX.AngleSingle objects and returns the result. - /// - /// The first object to subtract - /// The second object to subtract. - /// The value of the two objects subtracted. - public static AngleSingle operator -(AngleSingle left, AngleSingle right) - { - return new AngleSingle(left.radians - right.radians, AngleType.Radian); - } - - /// - /// Multiplies two SharpDX.AngleSingle objects and returns the result. - /// - /// The first object to multiply. - /// The second object to multiply. - /// The value of the two objects multiplied together. - public static AngleSingle operator *(AngleSingle left, AngleSingle right) - { - return new AngleSingle(left.radians * right.radians, AngleType.Radian); - } - - /// - /// Divides two SharpDX.AngleSingle objects and returns the result. - /// - /// The numerator object. - /// The denominator object. - /// The value of the two objects divided. - public static AngleSingle operator /(AngleSingle left, AngleSingle right) - { - return new AngleSingle(left.radians / right.radians, AngleType.Radian); - } - - /// - /// Compares this instance to a specified object and returns an integer that - /// indicates whether the value of this instance is less than, equal to, or greater - /// than the value of the specified object. - /// - /// The object to compare. - /// - /// A signed integer that indicates the relationship of the current instance - /// to the obj parameter. If the value is less than zero, the current instance - /// is less than the other. If the value is zero, the current instance is equal - /// to the other. If the value is greater than zero, the current instance is - /// greater than the other. - /// - public int CompareTo(object other) - { - if (other == null) - return 1; - - if (!(other is AngleSingle)) - throw new ArgumentException("Argument must be of type Angle.", "other"); - - float radians = ((AngleSingle)other).radians; - - if (this.radians > radians) - return 1; - - if (this.radians < radians) - return -1; - - return 0; - } - - /// - /// Compares this instance to a second SharpDX.AngleSingle and returns - /// an integer that indicates whether the value of this instance is less than, - /// equal to, or greater than the value of the specified object. - /// - /// The object to compare. - /// - /// A signed integer that indicates the relationship of the current instance - /// to the obj parameter. If the value is less than zero, the current instance - /// is less than the other. If the value is zero, the current instance is equal - /// to the other. If the value is greater than zero, the current instance is - /// greater than the other. - /// - public int CompareTo(AngleSingle other) - { - if (this.radians > other.radians) - return 1; - - if (this.radians < other.radians) - return -1; - - return 0; - } - - /// - /// Returns a value that indicates whether the current instance and a specified - /// SharpDX.AngleSingle object have the same value. - /// - /// The object to compare. - /// - /// Returns true if this SharpDX.AngleSingle object and another have the same value; - /// otherwise, false. - /// - public bool Equals(AngleSingle other) - { - return this == other; - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return string.Format(CultureInfo.CurrentCulture, MathUtil.RadiansToDegrees(radians).ToString("0.##°")); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// - /// A that represents this instance. - /// - public string ToString(string format) - { - if (format == null) - return ToString(); - - return string.Format(CultureInfo.CurrentCulture, "{0}°", MathUtil.RadiansToDegrees(radians).ToString(format, CultureInfo.CurrentCulture)); - } - - /// - /// Returns a that represents this instance. - /// - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(IFormatProvider formatProvider) - { - return string.Format(formatProvider, MathUtil.RadiansToDegrees(radians).ToString("0.##°")); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - if (format == null) - return ToString(formatProvider); - - return string.Format(formatProvider, "{0}°", MathUtil.RadiansToDegrees(radians).ToString(format, CultureInfo.CurrentCulture)); - } - - /// - /// Returns a hash code for this SharpDX.AngleSingle instance. - /// - /// A 32-bit signed integer hash code. - public override int GetHashCode() - { - return radiansInt; - } - - /// - /// Returns a value that indicates whether the current instance and a specified - /// object have the same value. - /// - /// The object to compare. - /// - /// Returns true if the obj parameter is a SharpDX.AngleSingle object or a type - /// capable of implicit conversion to a SharpDX.AngleSingle value, and - /// its value is equal to the value of the current SharpDX.Angle - /// object; otherwise, false. - /// - public override bool Equals(object obj) - { - return (obj is AngleSingle) && (this == (AngleSingle)obj); - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(radiansInt); - } - else - { - radiansInt = serializer.Reader.ReadInt32(); - } - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from SlimMath project. http://code.google.com/p/slimmath/ +// Greetings to SlimDX Group. Original code published with the following license: +// ----------------------------------------------------------------------------- +/* +* Copyright (c) 2007-2011 SlimDX Group +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +using System; +using System.Runtime.InteropServices; +using System.Globalization; + +namespace SharpDX +{ + /// + /// Represents a unit independent angle using a single-precision floating-point + /// internal representation. + /// + [StructLayout(LayoutKind.Explicit)] + public struct AngleSingle : IComparable, IComparable, IEquatable, IFormattable + { + /// + /// A value that specifies the size of a single degree. + /// + public const float Degree = 0.002777777777777778f; + + /// + /// A value that specifies the size of a single minute. + /// + public const float Minute = 0.000046296296296296f; + + /// + /// A value that specifies the size of a single second. + /// + public const float Second = 0.000000771604938272f; + + /// + /// A value that specifies the size of a single radian. + /// + public const float Radian = 0.159154943091895336f; + + /// + /// A value that specifies the size of a single milliradian. + /// + public const float Milliradian = 0.0001591549431f; + + /// + /// A value that specifies the size of a single gradian. + /// + public const float Gradian = 0.0025f; + + /// + /// The internal representation of the angle. + /// + [FieldOffset(0)] + float radians; + + [FieldOffset(0)] + private int radiansInt; + + /// + /// Initializes a new instance of the SharpDX.AngleSingle structure with the + /// given unit dependant angle and unit type. + /// + /// A unit dependant measure of the angle. + /// The type of unit the angle argument is. + public AngleSingle(float angle, AngleType type) + { + radiansInt = 0; + switch (type) + { + case AngleType.Revolution: + radians = MathUtil.RevolutionsToRadians(angle); + break; + + case AngleType.Degree: + radians = MathUtil.DegreesToRadians(angle); + break; + + case AngleType.Radian: + radians = angle; + break; + + case AngleType.Gradian: + radians = MathUtil.GradiansToRadians(angle); + break; + + default: + radians = 0.0f; + break; + } + } + + /// + /// Initializes a new instance of the SharpDX.AngleSingle structure using the + /// arc length formula (θ = s/r). + /// + /// The measure of the arc. + /// The radius of the circle. + public AngleSingle(float arcLength, float radius) + { + radiansInt = 0; + radians = arcLength / radius; + } + + /// + /// Wraps this SharpDX.AngleSingle to be in the range [π, -π]. + /// + public void Wrap() + { + float newangle = (float)Math.IEEERemainder(radians, MathUtil.TwoPi); + + if (newangle <= -MathUtil.Pi) + newangle += MathUtil.TwoPi; + else if (newangle > MathUtil.Pi) + newangle -= MathUtil.TwoPi; + + radians = newangle; + } + + /// + /// Wraps this SharpDX.AngleSingle to be in the range [0, 2π). + /// + public void WrapPositive() + { + float newangle = radians % MathUtil.TwoPi; + + if (newangle < 0.0) + newangle += MathUtil.TwoPi; + + radians = newangle; + } + + /// + /// Gets or sets the total number of revolutions this SharpDX.AngleSingle represents. + /// + public float Revolutions + { + get { return MathUtil.RadiansToRevolutions(radians); } + set { radians = MathUtil.RevolutionsToRadians(value); } + } + + /// + /// Gets or sets the total number of degrees this SharpDX.AngleSingle represents. + /// + public float Degrees + { + get { return MathUtil.RadiansToDegrees(radians); } + set { radians = MathUtil.DegreesToRadians(value); } + } + + /// + /// Gets or sets the minutes component of the degrees this SharpDX.AngleSingle represents. + /// When setting the minutes, if the value is in the range (-60, 60) the whole degrees are + /// not changed; otherwise, the whole degrees may be changed. Fractional values may set + /// the seconds component. + /// + public float Minutes + { + get + { + float degrees = MathUtil.RadiansToDegrees(radians); + + if (degrees < 0) + { + float degreesfloor = (float)Math.Ceiling(degrees); + return (degrees - degreesfloor) * 60.0f; + } + else + { + float degreesfloor = (float)Math.Floor(degrees); + return (degrees - degreesfloor) * 60.0f; + } + } + set + { + float degrees = MathUtil.RadiansToDegrees(radians); + float degreesfloor = (float)Math.Floor(degrees); + + degreesfloor += value / 60.0f; + radians = MathUtil.DegreesToRadians(degreesfloor); + } + } + + /// + /// Gets or sets the seconds of the degrees this SharpDX.AngleSingle represents. + /// When setting the seconds, if the value is in the range (-60, 60) the whole minutes + /// or whole degrees are not changed; otherwise, the whole minutes or whole degrees + /// may be changed. + /// + public float Seconds + { + get + { + float degrees = MathUtil.RadiansToDegrees(radians); + + if (degrees < 0) + { + float degreesfloor = (float)Math.Ceiling(degrees); + + float minutes = (degrees - degreesfloor) * 60.0f; + float minutesfloor = (float)Math.Ceiling(minutes); + + return (minutes - minutesfloor) * 60.0f; + } + else + { + float degreesfloor = (float)Math.Floor(degrees); + + float minutes = (degrees - degreesfloor) * 60.0f; + float minutesfloor = (float)Math.Floor(minutes); + + return (minutes - minutesfloor) * 60.0f; + } + } + set + { + float degrees = MathUtil.RadiansToDegrees(radians); + float degreesfloor = (float)Math.Floor(degrees); + + float minutes = (degrees - degreesfloor) * 60.0f; + float minutesfloor = (float)Math.Floor(minutes); + + minutesfloor += value / 60.0f; + degreesfloor += minutesfloor / 60.0f; + radians = MathUtil.DegreesToRadians(degreesfloor); + } + } + + /// + /// Gets or sets the total number of radians this SharpDX.AngleSingle represents. + /// + public float Radians + { + get { return radians; } + set { radians = value; } + } + + /// + /// Gets or sets the total number of milliradians this SharpDX.AngleSingle represents. + /// One milliradian is equal to 1/(2000π). + /// + public float Milliradians + { + get { return radians / (Milliradian * MathUtil.TwoPi); } + set { radians = value * (Milliradian * MathUtil.TwoPi); } + } + + /// + /// Gets or sets the total number of gradians this SharpDX.AngleSingle represents. + /// + public float Gradians + { + get { return MathUtil.RadiansToGradians(radians); } + set { radians = MathUtil.RadiansToGradians(value); } + } + + /// + /// Gets a System.Boolean that determines whether this SharpDX.Angle + /// is a right angle (i.e. 90° or π/2). + /// + public bool IsRight + { + get { return radians == MathUtil.PiOverTwo; } + } + + /// + /// Gets a System.Boolean that determines whether this SharpDX.Angle + /// is a straight angle (i.e. 180° or π). + /// + public bool IsStraight + { + get { return radians == MathUtil.Pi; } + } + + /// + /// Gets a System.Boolean that determines whether this SharpDX.Angle + /// is a full rotation angle (i.e. 360° or 2π). + /// + public bool IsFullRotation + { + get { return radians == MathUtil.TwoPi; } + } + + /// + /// Gets a System.Boolean that determines whether this SharpDX.Angle + /// is an oblique angle (i.e. is not 90° or a multiple of 90°). + /// + public bool IsOblique + { + get { return WrapPositive(this).radians != MathUtil.PiOverTwo; } + } + + /// + /// Gets a System.Boolean that determines whether this SharpDX.Angle + /// is an acute angle (i.e. less than 90° but greater than 0°). + /// + public bool IsAcute + { + get { return radians > 0.0 && radians < MathUtil.PiOverTwo; } + } + + /// + /// Gets a System.Boolean that determines whether this SharpDX.Angle + /// is an obtuse angle (i.e. greater than 90° but less than 180°). + /// + public bool IsObtuse + { + get { return radians > MathUtil.PiOverTwo && radians < MathUtil.Pi; } + } + + /// + /// Gets a System.Boolean that determines whether this SharpDX.Angle + /// is a reflex angle (i.e. greater than 180° but less than 360°). + /// + public bool IsReflex + { + get { return radians > MathUtil.Pi && radians < MathUtil.TwoPi; } + } + + /// + /// Gets a SharpDX.AngleSingle instance that complements this angle (i.e. the two angles add to 90°). + /// + public AngleSingle Complement + { + get { return new AngleSingle(MathUtil.PiOverTwo - radians, AngleType.Radian); } + } + + /// + /// Gets a SharpDX.AngleSingle instance that supplements this angle (i.e. the two angles add to 180°). + /// + public AngleSingle Supplement + { + get { return new AngleSingle(MathUtil.Pi - radians, AngleType.Radian); } + } + + /// + /// Wraps the SharpDX.AngleSingle given in the value argument to be in the range [π, -π]. + /// + /// A SharpDX.AngleSingle to wrap. + /// The SharpDX.AngleSingle that is wrapped. + public static AngleSingle Wrap(AngleSingle value) + { + value.Wrap(); + return value; + } + + /// + /// Wraps the SharpDX.AngleSingle given in the value argument to be in the range [0, 2π). + /// + /// A SharpDX.AngleSingle to wrap. + /// The SharpDX.AngleSingle that is wrapped. + public static AngleSingle WrapPositive(AngleSingle value) + { + value.WrapPositive(); + return value; + } + + /// + /// Compares two SharpDX.AngleSingle instances and returns the smaller angle. + /// + /// The first SharpDX.AngleSingle instance to compare. + /// The second SharpDX.AngleSingle instance to compare. + /// The smaller of the two given SharpDX.AngleSingle instances. + public static AngleSingle Min(AngleSingle left, AngleSingle right) + { + if (left.radians < right.radians) + return left; + + return right; + } + + /// + /// Compares two SharpDX.AngleSingle instances and returns the greater angle. + /// + /// The first SharpDX.AngleSingle instance to compare. + /// The second SharpDX.AngleSingle instance to compare. + /// The greater of the two given SharpDX.AngleSingle instances. + public static AngleSingle Max(AngleSingle left, AngleSingle right) + { + if (left.radians > right.radians) + return left; + + return right; + } + + /// + /// Adds two SharpDX.AngleSingle objects and returns the result. + /// + /// The first object to add. + /// The second object to add. + /// The value of the two objects added together. + public static AngleSingle Add(AngleSingle left, AngleSingle right) + { + return new AngleSingle(left.radians + right.radians, AngleType.Radian); + } + + /// + /// Subtracts two SharpDX.AngleSingle objects and returns the result. + /// + /// The first object to subtract. + /// The second object to subtract. + /// The value of the two objects subtracted. + public static AngleSingle Subtract(AngleSingle left, AngleSingle right) + { + return new AngleSingle(left.radians - right.radians, AngleType.Radian); + } + + /// + /// Multiplies two SharpDX.AngleSingle objects and returns the result. + /// + /// The first object to multiply. + /// The second object to multiply. + /// The value of the two objects multiplied together. + public static AngleSingle Multiply(AngleSingle left, AngleSingle right) + { + return new AngleSingle(left.radians * right.radians, AngleType.Radian); + } + + /// + /// Divides two SharpDX.AngleSingle objects and returns the result. + /// + /// The numerator object. + /// The denominator object. + /// The value of the two objects divided. + public static AngleSingle Divide(AngleSingle left, AngleSingle right) + { + return new AngleSingle(left.radians / right.radians, AngleType.Radian); + } + + /// + /// Gets a new SharpDX.AngleSingle instance that represents the zero angle (i.e. 0°). + /// + public static AngleSingle ZeroAngle + { + get { return new AngleSingle(0.0f, AngleType.Radian); } + } + + /// + /// Gets a new SharpDX.AngleSingle instance that represents the right angle (i.e. 90° or π/2). + /// + public static AngleSingle RightAngle + { + get { return new AngleSingle(MathUtil.PiOverTwo, AngleType.Radian); } + } + + /// + /// Gets a new SharpDX.AngleSingle instance that represents the straight angle (i.e. 180° or π). + /// + public static AngleSingle StraightAngle + { + get { return new AngleSingle(MathUtil.Pi, AngleType.Radian); } + } + + /// + /// Gets a new SharpDX.AngleSingle instance that represents the full rotation angle (i.e. 360° or 2π). + /// + public static AngleSingle FullRotationAngle + { + get { return new AngleSingle(MathUtil.TwoPi, AngleType.Radian); } + } + + /// + /// Returns a System.Boolean that indicates whether the values of two SharpDX.Angle + /// objects are equal. + /// + /// The first object to compare. + /// The second object to compare. + /// True if the left and right parameters have the same value; otherwise, false. + public static bool operator ==(AngleSingle left, AngleSingle right) + { + return left.radians == right.radians; + } + + /// + /// Returns a System.Boolean that indicates whether the values of two SharpDX.Angle + /// objects are not equal. + /// + /// The first object to compare. + /// The second object to compare. + /// True if the left and right parameters do not have the same value; otherwise, false. + public static bool operator !=(AngleSingle left, AngleSingle right) + { + return left.radians != right.radians; + } + + /// + /// Returns a System.Boolean that indicates whether a SharpDX.Angle + /// object is less than another SharpDX.AngleSingle object. + /// + /// The first object to compare. + /// The second object to compare. + /// True if left is less than right; otherwise, false. + public static bool operator <(AngleSingle left, AngleSingle right) + { + return left.radians < right.radians; + } + + /// + /// Returns a System.Boolean that indicates whether a SharpDX.Angle + /// object is greater than another SharpDX.AngleSingle object. + /// + /// The first object to compare. + /// The second object to compare. + /// True if left is greater than right; otherwise, false. + public static bool operator >(AngleSingle left, AngleSingle right) + { + return left.radians > right.radians; + } + + /// + /// Returns a System.Boolean that indicates whether a SharpDX.Angle + /// object is less than or equal to another SharpDX.AngleSingle object. + /// + /// The first object to compare. + /// The second object to compare. + /// True if left is less than or equal to right; otherwise, false. + public static bool operator <=(AngleSingle left, AngleSingle right) + { + return left.radians <= right.radians; + } + + /// + /// Returns a System.Boolean that indicates whether a SharpDX.Angle + /// object is greater than or equal to another SharpDX.AngleSingle object. + /// + /// The first object to compare. + /// The second object to compare. + /// True if left is greater than or equal to right; otherwise, false. + public static bool operator >=(AngleSingle left, AngleSingle right) + { + return left.radians >= right.radians; + } + + /// + /// Returns the value of the SharpDX.AngleSingle operand. (The sign of + /// the operand is unchanged.) + /// + /// A SharpDX.AngleSingle object. + /// The value of the value parameter. + public static AngleSingle operator +(AngleSingle value) + { + return value; + } + + /// + /// Returns the the negated value of the SharpDX.AngleSingle operand. + /// + /// A SharpDX.AngleSingle object. + /// The negated value of the value parameter. + public static AngleSingle operator -(AngleSingle value) + { + return new AngleSingle(-value.radians, AngleType.Radian); + } + + /// + /// Adds two SharpDX.AngleSingle objects and returns the result. + /// + /// The first object to add. + /// The second object to add. + /// The value of the two objects added together. + public static AngleSingle operator +(AngleSingle left, AngleSingle right) + { + return new AngleSingle(left.radians + right.radians, AngleType.Radian); + } + + /// + /// Subtracts two SharpDX.AngleSingle objects and returns the result. + /// + /// The first object to subtract + /// The second object to subtract. + /// The value of the two objects subtracted. + public static AngleSingle operator -(AngleSingle left, AngleSingle right) + { + return new AngleSingle(left.radians - right.radians, AngleType.Radian); + } + + /// + /// Multiplies two SharpDX.AngleSingle objects and returns the result. + /// + /// The first object to multiply. + /// The second object to multiply. + /// The value of the two objects multiplied together. + public static AngleSingle operator *(AngleSingle left, AngleSingle right) + { + return new AngleSingle(left.radians * right.radians, AngleType.Radian); + } + + /// + /// Divides two SharpDX.AngleSingle objects and returns the result. + /// + /// The numerator object. + /// The denominator object. + /// The value of the two objects divided. + public static AngleSingle operator /(AngleSingle left, AngleSingle right) + { + return new AngleSingle(left.radians / right.radians, AngleType.Radian); + } + + /// + /// Compares this instance to a specified object and returns an integer that + /// indicates whether the value of this instance is less than, equal to, or greater + /// than the value of the specified object. + /// + /// The object to compare. + /// + /// A signed integer that indicates the relationship of the current instance + /// to the obj parameter. If the value is less than zero, the current instance + /// is less than the other. If the value is zero, the current instance is equal + /// to the other. If the value is greater than zero, the current instance is + /// greater than the other. + /// + public int CompareTo(object other) + { + if (other == null) + return 1; + + if (!(other is AngleSingle)) + throw new ArgumentException("Argument must be of type Angle.", "other"); + + float radians = ((AngleSingle)other).radians; + + if (this.radians > radians) + return 1; + + if (this.radians < radians) + return -1; + + return 0; + } + + /// + /// Compares this instance to a second SharpDX.AngleSingle and returns + /// an integer that indicates whether the value of this instance is less than, + /// equal to, or greater than the value of the specified object. + /// + /// The object to compare. + /// + /// A signed integer that indicates the relationship of the current instance + /// to the obj parameter. If the value is less than zero, the current instance + /// is less than the other. If the value is zero, the current instance is equal + /// to the other. If the value is greater than zero, the current instance is + /// greater than the other. + /// + public int CompareTo(AngleSingle other) + { + if (this.radians > other.radians) + return 1; + + if (this.radians < other.radians) + return -1; + + return 0; + } + + /// + /// Returns a value that indicates whether the current instance and a specified + /// SharpDX.AngleSingle object have the same value. + /// + /// The object to compare. + /// + /// Returns true if this SharpDX.AngleSingle object and another have the same value; + /// otherwise, false. + /// + public bool Equals(AngleSingle other) + { + return this == other; + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return string.Format(CultureInfo.CurrentCulture, MathUtil.RadiansToDegrees(radians).ToString("0.##°")); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// + /// A that represents this instance. + /// + public string ToString(string format) + { + if (format == null) + return ToString(); + + return string.Format(CultureInfo.CurrentCulture, "{0}°", MathUtil.RadiansToDegrees(radians).ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format(formatProvider, MathUtil.RadiansToDegrees(radians).ToString("0.##°")); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(string format, IFormatProvider formatProvider) + { + if (format == null) + return ToString(formatProvider); + + return string.Format(formatProvider, "{0}°", MathUtil.RadiansToDegrees(radians).ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a hash code for this SharpDX.AngleSingle instance. + /// + /// A 32-bit signed integer hash code. + public override int GetHashCode() + { + return radiansInt; + } + + /// + /// Returns a value that indicates whether the current instance and a specified + /// object have the same value. + /// + /// The object to compare. + /// + /// Returns true if the obj parameter is a SharpDX.AngleSingle object or a type + /// capable of implicit conversion to a SharpDX.AngleSingle value, and + /// its value is equal to the value of the current SharpDX.Angle + /// object; otherwise, false. + /// + public override bool Equals(object obj) + { + return (obj is AngleSingle) && (this == (AngleSingle)obj); + } + } +} diff --git a/Source/SharpDX.Mathematics/AssemblyDoc.cs b/Source/SharpDX.Mathematics/AssemblyDoc.cs new file mode 100644 index 000000000..8e0345eff --- /dev/null +++ b/Source/SharpDX.Mathematics/AssemblyDoc.cs @@ -0,0 +1,29 @@ +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +namespace SharpDX.Mathematics +{ + /// + /// The assembly is a managed Math API. + /// + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + class AssemblyDoc + { + } +} \ No newline at end of file diff --git a/Source/SharpDX/BoundingBox.cs b/Source/SharpDX.Mathematics/BoundingBox.cs similarity index 96% rename from Source/SharpDX/BoundingBox.cs rename to Source/SharpDX.Mathematics/BoundingBox.cs index 699c6c27c..43177f486 100644 --- a/Source/SharpDX/BoundingBox.cs +++ b/Source/SharpDX.Mathematics/BoundingBox.cs @@ -1,505 +1,496 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ----------------------------------------------------------------------------- -// Original code from SlimMath project. http://code.google.com/p/slimmath/ -// Greetings to SlimDX Group. Original code published with the following license: -// ----------------------------------------------------------------------------- -/* -* Copyright (c) 2007-2011 SlimDX Group -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using System.ComponentModel; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Represents an axis-aligned bounding box in three dimensional space. - /// - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct BoundingBox : IEquatable, IFormattable, IDataSerializable - { - /// - /// The minimum point of the box. - /// - public Vector3 Minimum; - - /// - /// The maximum point of the box. - /// - public Vector3 Maximum; - - /// - /// Initializes a new instance of the struct. - /// - /// The minimum vertex of the bounding box. - /// The maximum vertex of the bounding box. - public BoundingBox(Vector3 minimum, Vector3 maximum) - { - this.Minimum = minimum; - this.Maximum = maximum; - } - - /// - /// Retrieves the eight corners of the bounding box. - /// - /// An array of points representing the eight corners of the bounding box. - public Vector3[] GetCorners() - { - Vector3[] results = new Vector3[8]; - GetCorners(results); - return results; - } - - /// - /// Retrieves the eight corners of the bounding box. - /// - /// An array of points representing the eight corners of the bounding box. - public void GetCorners(Vector3[] corners) - { - corners[0] = new Vector3(Minimum.X, Maximum.Y, Maximum.Z); - corners[1] = new Vector3(Maximum.X, Maximum.Y, Maximum.Z); - corners[2] = new Vector3(Maximum.X, Minimum.Y, Maximum.Z); - corners[3] = new Vector3(Minimum.X, Minimum.Y, Maximum.Z); - corners[4] = new Vector3(Minimum.X, Maximum.Y, Minimum.Z); - corners[5] = new Vector3(Maximum.X, Maximum.Y, Minimum.Z); - corners[6] = new Vector3(Maximum.X, Minimum.Y, Minimum.Z); - corners[7] = new Vector3(Minimum.X, Minimum.Y, Minimum.Z); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The ray to test. - /// Whether the two objects intersected. - public bool Intersects(ref Ray ray) - { - float distance; - return Collision.RayIntersectsBox(ref ray, ref this, out distance); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The ray to test. - /// When the method completes, contains the distance of the intersection, - /// or 0 if there was no intersection. - /// Whether the two objects intersected. - public bool Intersects(ref Ray ray, out float distance) - { - return Collision.RayIntersectsBox(ref ray, ref this, out distance); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The ray to test. - /// When the method completes, contains the point of intersection, - /// or if there was no intersection. - /// Whether the two objects intersected. - public bool Intersects(ref Ray ray, out Vector3 point) - { - return Collision.RayIntersectsBox(ref ray, ref this, out point); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The plane to test. - /// Whether the two objects intersected. - public PlaneIntersectionType Intersects(ref Plane plane) - { - return Collision.PlaneIntersectsBox(ref plane, ref this); - } - - /* This implementation is wrong - /// - /// Determines if there is an intersection between the current object and a triangle. - /// - /// The first vertex of the triangle to test. - /// The second vertex of the triangle to test. - /// The third vertex of the triangle to test. - /// Whether the two objects intersected. - public bool Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) - { - return Collision.BoxIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3); - } - */ - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The box to test. - /// Whether the two objects intersected. - public bool Intersects(ref BoundingBox box) - { - return Collision.BoxIntersectsBox(ref this, ref box); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The box to test. - /// Whether the two objects intersected. - public bool Intersects(BoundingBox box) - { - return Intersects(ref box); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The sphere to test. - /// Whether the two objects intersected. - public bool Intersects(ref BoundingSphere sphere) - { - return Collision.BoxIntersectsSphere(ref this, ref sphere); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The sphere to test. - /// Whether the two objects intersected. - public bool Intersects(BoundingSphere sphere) - { - return Intersects(ref sphere); - } - - /// - /// Determines whether the current objects contains a point. - /// - /// The point to test. - /// The type of containment the two objects have. - public ContainmentType Contains(ref Vector3 point) - { - return Collision.BoxContainsPoint(ref this, ref point); - } - - /// - /// Determines whether the current objects contains a point. - /// - /// The point to test. - /// The type of containment the two objects have. - public ContainmentType Contains(Vector3 point) - { - return Contains(ref point); - } - - /* This implementation is wrong - /// - /// Determines whether the current objects contains a triangle. - /// - /// The first vertex of the triangle to test. - /// The second vertex of the triangle to test. - /// The third vertex of the triangle to test. - /// The type of containment the two objects have. - public ContainmentType Contains(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) - { - return Collision.BoxContainsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3); - } - */ - - /// - /// Determines whether the current objects contains a . - /// - /// The box to test. - /// The type of containment the two objects have. - public ContainmentType Contains(ref BoundingBox box) - { - return Collision.BoxContainsBox(ref this, ref box); - } - - /// - /// Determines whether the current objects contains a . - /// - /// The box to test. - /// The type of containment the two objects have. - public ContainmentType Contains(BoundingBox box) - { - return Contains(ref box); - } - - /// - /// Determines whether the current objects contains a . - /// - /// The sphere to test. - /// The type of containment the two objects have. - public ContainmentType Contains(ref BoundingSphere sphere) - { - return Collision.BoxContainsSphere(ref this, ref sphere); - } - - /// - /// Determines whether the current objects contains a . - /// - /// The sphere to test. - /// The type of containment the two objects have. - public ContainmentType Contains(BoundingSphere sphere) - { - return Contains(ref sphere); - } - - /// - /// Constructs a that fully contains the given points. - /// - /// The points that will be contained by the box. - /// When the method completes, contains the newly constructed bounding box. - /// Thrown when is null. - public static void FromPoints(Vector3[] points, out BoundingBox result) - { - if (points == null) - throw new ArgumentNullException("points"); - - Vector3 min = new Vector3(float.MaxValue); - Vector3 max = new Vector3(float.MinValue); - - for (int i = 0; i < points.Length; ++i) - { - Vector3.Min(ref min, ref points[i], out min); - Vector3.Max(ref max, ref points[i], out max); - } - - result = new BoundingBox(min, max); - } - - /// - /// Constructs a that fully contains the given points. - /// - /// The points that will be contained by the box. - /// The newly constructed bounding box. - /// Thrown when is null. - public static BoundingBox FromPoints(Vector3[] points) - { - if (points == null) - throw new ArgumentNullException("points"); - - Vector3 min = new Vector3(float.MaxValue); - Vector3 max = new Vector3(float.MinValue); - - for (int i = 0; i < points.Length; ++i) - { - Vector3.Min(ref min, ref points[i], out min); - Vector3.Max(ref max, ref points[i], out max); - } - - return new BoundingBox(min, max); - } - - /// - /// Constructs a from a given sphere. - /// - /// The sphere that will designate the extents of the box. - /// When the method completes, contains the newly constructed bounding box. - public static void FromSphere(ref BoundingSphere sphere, out BoundingBox result) - { - result.Minimum = new Vector3(sphere.Center.X - sphere.Radius, sphere.Center.Y - sphere.Radius, sphere.Center.Z - sphere.Radius); - result.Maximum = new Vector3(sphere.Center.X + sphere.Radius, sphere.Center.Y + sphere.Radius, sphere.Center.Z + sphere.Radius); - } - - /// - /// Constructs a from a given sphere. - /// - /// The sphere that will designate the extents of the box. - /// The newly constructed bounding box. - public static BoundingBox FromSphere(BoundingSphere sphere) - { - BoundingBox box; - box.Minimum = new Vector3(sphere.Center.X - sphere.Radius, sphere.Center.Y - sphere.Radius, sphere.Center.Z - sphere.Radius); - box.Maximum = new Vector3(sphere.Center.X + sphere.Radius, sphere.Center.Y + sphere.Radius, sphere.Center.Z + sphere.Radius); - return box; - } - - /// - /// Constructs a that is as large as the total combined area of the two specified boxes. - /// - /// The first box to merge. - /// The second box to merge. - /// When the method completes, contains the newly constructed bounding box. - public static void Merge(ref BoundingBox value1, ref BoundingBox value2, out BoundingBox result) - { - Vector3.Min(ref value1.Minimum, ref value2.Minimum, out result.Minimum); - Vector3.Max(ref value1.Maximum, ref value2.Maximum, out result.Maximum); - } - - /// - /// Constructs a that is as large as the total combined area of the two specified boxes. - /// - /// The first box to merge. - /// The second box to merge. - /// The newly constructed bounding box. - public static BoundingBox Merge(BoundingBox value1, BoundingBox value2) - { - BoundingBox box; - Vector3.Min(ref value1.Minimum, ref value2.Minimum, out box.Minimum); - Vector3.Max(ref value1.Maximum, ref value2.Maximum, out box.Maximum); - return box; - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has the same value as ; otherwise, false. - public static bool operator ==(BoundingBox left, BoundingBox right) - { - return left.Equals(right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has a different value than ; otherwise, false. - public static bool operator !=(BoundingBox left, BoundingBox right) - { - return !left.Equals(right); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return string.Format(CultureInfo.CurrentCulture, "Minimum:{0} Maximum:{1}", Minimum.ToString(), Maximum.ToString()); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// - /// A that represents this instance. - /// - public string ToString(string format) - { - if (format == null) - return ToString(); - - return string.Format(CultureInfo.CurrentCulture, "Minimum:{0} Maximum:{1}", Minimum.ToString(format, CultureInfo.CurrentCulture), - Maximum.ToString(format, CultureInfo.CurrentCulture)); - } - - /// - /// Returns a that represents this instance. - /// - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(IFormatProvider formatProvider) - { - return string.Format(formatProvider, "Minimum:{0} Maximum:{1}", Minimum.ToString(), Maximum.ToString()); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - if (format == null) - return ToString(formatProvider); - - return string.Format(formatProvider, "Minimum:{0} Maximum:{1}", Minimum.ToString(format, formatProvider), - Maximum.ToString(format, formatProvider)); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - return (Minimum.GetHashCode() * 397) ^ Maximum.GetHashCode(); - } - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(BoundingBox value) - { - return Minimum == value.Minimum && Maximum == value.Maximum; - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object value) - { - if (value == null) - return false; - - if (!ReferenceEquals(value.GetType(), typeof(BoundingBox))) - return false; - - return Equals((BoundingBox)value); - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - serializer.Serialize(ref Minimum); - serializer.Serialize(ref Maximum); - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from SlimMath project. http://code.google.com/p/slimmath/ +// Greetings to SlimDX Group. Original code published with the following license: +// ----------------------------------------------------------------------------- +/* +* Copyright (c) 2007-2011 SlimDX Group +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Represents an axis-aligned bounding box in three dimensional space. + /// + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct BoundingBox : IEquatable, IFormattable + { + /// + /// The minimum point of the box. + /// + public Vector3 Minimum; + + /// + /// The maximum point of the box. + /// + public Vector3 Maximum; + + /// + /// Initializes a new instance of the struct. + /// + /// The minimum vertex of the bounding box. + /// The maximum vertex of the bounding box. + public BoundingBox(Vector3 minimum, Vector3 maximum) + { + this.Minimum = minimum; + this.Maximum = maximum; + } + + /// + /// Retrieves the eight corners of the bounding box. + /// + /// An array of points representing the eight corners of the bounding box. + public Vector3[] GetCorners() + { + Vector3[] results = new Vector3[8]; + GetCorners(results); + return results; + } + + /// + /// Retrieves the eight corners of the bounding box. + /// + /// An array of points representing the eight corners of the bounding box. + public void GetCorners(Vector3[] corners) + { + corners[0] = new Vector3(Minimum.X, Maximum.Y, Maximum.Z); + corners[1] = new Vector3(Maximum.X, Maximum.Y, Maximum.Z); + corners[2] = new Vector3(Maximum.X, Minimum.Y, Maximum.Z); + corners[3] = new Vector3(Minimum.X, Minimum.Y, Maximum.Z); + corners[4] = new Vector3(Minimum.X, Maximum.Y, Minimum.Z); + corners[5] = new Vector3(Maximum.X, Maximum.Y, Minimum.Z); + corners[6] = new Vector3(Maximum.X, Minimum.Y, Minimum.Z); + corners[7] = new Vector3(Minimum.X, Minimum.Y, Minimum.Z); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The ray to test. + /// Whether the two objects intersected. + public bool Intersects(ref Ray ray) + { + float distance; + return Collision.RayIntersectsBox(ref ray, ref this, out distance); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The ray to test. + /// When the method completes, contains the distance of the intersection, + /// or 0 if there was no intersection. + /// Whether the two objects intersected. + public bool Intersects(ref Ray ray, out float distance) + { + return Collision.RayIntersectsBox(ref ray, ref this, out distance); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The ray to test. + /// When the method completes, contains the point of intersection, + /// or if there was no intersection. + /// Whether the two objects intersected. + public bool Intersects(ref Ray ray, out Vector3 point) + { + return Collision.RayIntersectsBox(ref ray, ref this, out point); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The plane to test. + /// Whether the two objects intersected. + public PlaneIntersectionType Intersects(ref Plane plane) + { + return Collision.PlaneIntersectsBox(ref plane, ref this); + } + + /* This implementation is wrong + /// + /// Determines if there is an intersection between the current object and a triangle. + /// + /// The first vertex of the triangle to test. + /// The second vertex of the triangle to test. + /// The third vertex of the triangle to test. + /// Whether the two objects intersected. + public bool Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) + { + return Collision.BoxIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3); + } + */ + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The box to test. + /// Whether the two objects intersected. + public bool Intersects(ref BoundingBox box) + { + return Collision.BoxIntersectsBox(ref this, ref box); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The box to test. + /// Whether the two objects intersected. + public bool Intersects(BoundingBox box) + { + return Intersects(ref box); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The sphere to test. + /// Whether the two objects intersected. + public bool Intersects(ref BoundingSphere sphere) + { + return Collision.BoxIntersectsSphere(ref this, ref sphere); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The sphere to test. + /// Whether the two objects intersected. + public bool Intersects(BoundingSphere sphere) + { + return Intersects(ref sphere); + } + + /// + /// Determines whether the current objects contains a point. + /// + /// The point to test. + /// The type of containment the two objects have. + public ContainmentType Contains(ref Vector3 point) + { + return Collision.BoxContainsPoint(ref this, ref point); + } + + /// + /// Determines whether the current objects contains a point. + /// + /// The point to test. + /// The type of containment the two objects have. + public ContainmentType Contains(Vector3 point) + { + return Contains(ref point); + } + + /* This implementation is wrong + /// + /// Determines whether the current objects contains a triangle. + /// + /// The first vertex of the triangle to test. + /// The second vertex of the triangle to test. + /// The third vertex of the triangle to test. + /// The type of containment the two objects have. + public ContainmentType Contains(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) + { + return Collision.BoxContainsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3); + } + */ + + /// + /// Determines whether the current objects contains a . + /// + /// The box to test. + /// The type of containment the two objects have. + public ContainmentType Contains(ref BoundingBox box) + { + return Collision.BoxContainsBox(ref this, ref box); + } + + /// + /// Determines whether the current objects contains a . + /// + /// The box to test. + /// The type of containment the two objects have. + public ContainmentType Contains(BoundingBox box) + { + return Contains(ref box); + } + + /// + /// Determines whether the current objects contains a . + /// + /// The sphere to test. + /// The type of containment the two objects have. + public ContainmentType Contains(ref BoundingSphere sphere) + { + return Collision.BoxContainsSphere(ref this, ref sphere); + } + + /// + /// Determines whether the current objects contains a . + /// + /// The sphere to test. + /// The type of containment the two objects have. + public ContainmentType Contains(BoundingSphere sphere) + { + return Contains(ref sphere); + } + + /// + /// Constructs a that fully contains the given points. + /// + /// The points that will be contained by the box. + /// When the method completes, contains the newly constructed bounding box. + /// Thrown when is null. + public static void FromPoints(Vector3[] points, out BoundingBox result) + { + if (points == null) + throw new ArgumentNullException("points"); + + Vector3 min = new Vector3(float.MaxValue); + Vector3 max = new Vector3(float.MinValue); + + for (int i = 0; i < points.Length; ++i) + { + Vector3.Min(ref min, ref points[i], out min); + Vector3.Max(ref max, ref points[i], out max); + } + + result = new BoundingBox(min, max); + } + + /// + /// Constructs a that fully contains the given points. + /// + /// The points that will be contained by the box. + /// The newly constructed bounding box. + /// Thrown when is null. + public static BoundingBox FromPoints(Vector3[] points) + { + if (points == null) + throw new ArgumentNullException("points"); + + Vector3 min = new Vector3(float.MaxValue); + Vector3 max = new Vector3(float.MinValue); + + for (int i = 0; i < points.Length; ++i) + { + Vector3.Min(ref min, ref points[i], out min); + Vector3.Max(ref max, ref points[i], out max); + } + + return new BoundingBox(min, max); + } + + /// + /// Constructs a from a given sphere. + /// + /// The sphere that will designate the extents of the box. + /// When the method completes, contains the newly constructed bounding box. + public static void FromSphere(ref BoundingSphere sphere, out BoundingBox result) + { + result.Minimum = new Vector3(sphere.Center.X - sphere.Radius, sphere.Center.Y - sphere.Radius, sphere.Center.Z - sphere.Radius); + result.Maximum = new Vector3(sphere.Center.X + sphere.Radius, sphere.Center.Y + sphere.Radius, sphere.Center.Z + sphere.Radius); + } + + /// + /// Constructs a from a given sphere. + /// + /// The sphere that will designate the extents of the box. + /// The newly constructed bounding box. + public static BoundingBox FromSphere(BoundingSphere sphere) + { + BoundingBox box; + box.Minimum = new Vector3(sphere.Center.X - sphere.Radius, sphere.Center.Y - sphere.Radius, sphere.Center.Z - sphere.Radius); + box.Maximum = new Vector3(sphere.Center.X + sphere.Radius, sphere.Center.Y + sphere.Radius, sphere.Center.Z + sphere.Radius); + return box; + } + + /// + /// Constructs a that is as large as the total combined area of the two specified boxes. + /// + /// The first box to merge. + /// The second box to merge. + /// When the method completes, contains the newly constructed bounding box. + public static void Merge(ref BoundingBox value1, ref BoundingBox value2, out BoundingBox result) + { + Vector3.Min(ref value1.Minimum, ref value2.Minimum, out result.Minimum); + Vector3.Max(ref value1.Maximum, ref value2.Maximum, out result.Maximum); + } + + /// + /// Constructs a that is as large as the total combined area of the two specified boxes. + /// + /// The first box to merge. + /// The second box to merge. + /// The newly constructed bounding box. + public static BoundingBox Merge(BoundingBox value1, BoundingBox value2) + { + BoundingBox box; + Vector3.Min(ref value1.Minimum, ref value2.Minimum, out box.Minimum); + Vector3.Max(ref value1.Maximum, ref value2.Maximum, out box.Maximum); + return box; + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has the same value as ; otherwise, false. + public static bool operator ==(BoundingBox left, BoundingBox right) + { + return left.Equals(right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has a different value than ; otherwise, false. + public static bool operator !=(BoundingBox left, BoundingBox right) + { + return !left.Equals(right); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return string.Format(CultureInfo.CurrentCulture, "Minimum:{0} Maximum:{1}", Minimum.ToString(), Maximum.ToString()); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// + /// A that represents this instance. + /// + public string ToString(string format) + { + if (format == null) + return ToString(); + + return string.Format(CultureInfo.CurrentCulture, "Minimum:{0} Maximum:{1}", Minimum.ToString(format, CultureInfo.CurrentCulture), + Maximum.ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format(formatProvider, "Minimum:{0} Maximum:{1}", Minimum.ToString(), Maximum.ToString()); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(string format, IFormatProvider formatProvider) + { + if (format == null) + return ToString(formatProvider); + + return string.Format(formatProvider, "Minimum:{0} Maximum:{1}", Minimum.ToString(format, formatProvider), + Maximum.ToString(format, formatProvider)); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + unchecked + { + return (Minimum.GetHashCode() * 397) ^ Maximum.GetHashCode(); + } + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(BoundingBox value) + { + return Minimum == value.Minimum && Maximum == value.Maximum; + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object value) + { + if (value == null) + return false; + + if (!ReferenceEquals(value.GetType(), typeof(BoundingBox))) + return false; + + return Equals((BoundingBox)value); + } + } +} diff --git a/Source/SharpDX/BoundingFrustum.cs b/Source/SharpDX.Mathematics/BoundingFrustum.cs similarity index 96% rename from Source/SharpDX/BoundingFrustum.cs rename to Source/SharpDX.Mathematics/BoundingFrustum.cs index 5fdccfcb3..37be4a997 100644 --- a/Source/SharpDX/BoundingFrustum.cs +++ b/Source/SharpDX.Mathematics/BoundingFrustum.cs @@ -1,883 +1,870 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Defines a frustum which can be used in frustum culling, zoom to Extents (zoom to fit) operations, - /// (matrix, frustum, camera) interchange, and many kind of intersection testing. - /// - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct BoundingFrustum : IEquatable, IDataSerializable - { - private Matrix pMatrix; - private Plane pNear; - private Plane pFar; - private Plane pLeft; - private Plane pRight; - private Plane pTop; - private Plane pBottom; - - /// - /// Gets or sets the Matrix that describes this bounding frustum. - /// - public Matrix Matrix - { - get - { - return pMatrix; - } - set - { - pMatrix = value; - GetPlanesFromMatrix(ref pMatrix, out pNear, out pFar, out pLeft, out pRight, out pTop, out pBottom); - } - } - /// - /// Gets the near plane of the BoundingFrustum. - /// - public Plane Near - { - get - { - return pNear; - } - } - /// - /// Gets the far plane of the BoundingFrustum. - /// - public Plane Far - { - get - { - return pFar; - } - } - /// - /// Gets the left plane of the BoundingFrustum. - /// - public Plane Left - { - get - { - return pLeft; - } - } - /// - /// Gets the right plane of the BoundingFrustum. - /// - public Plane Right - { - get - { - return pRight; - } - } - /// - /// Gets the top plane of the BoundingFrustum. - /// - public Plane Top - { - get - { - return pTop; - } - } - /// - /// Gets the bottom plane of the BoundingFrustum. - /// - public Plane Bottom - { - get - { - return pBottom; - } - } - - /// - /// Creates a new instance of BoundingFrustum. - /// - /// Combined matrix that usually takes view × projection matrix. - public BoundingFrustum(Matrix matrix) - { - pMatrix = matrix; - GetPlanesFromMatrix(ref pMatrix, out pNear, out pFar, out pLeft, out pRight, out pTop, out pBottom); - } - - public override int GetHashCode() - { - return pMatrix.GetHashCode(); - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(BoundingFrustum other) - { - return this.pMatrix == other.pMatrix; - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object obj) - { - if (obj != null && obj is BoundingFrustum) - return Equals((BoundingFrustum)obj); - return false; - } - - /// - /// Implements the operator ==. - /// - /// The left. - /// The right. - /// - /// The result of the operator. - /// - public static bool operator ==(BoundingFrustum left, BoundingFrustum right) - { - return left.Equals(right); - } - - /// - /// Implements the operator !=. - /// - /// The left. - /// The right. - /// - /// The result of the operator. - /// - public static bool operator !=(BoundingFrustum left, BoundingFrustum right) - { - return !left.Equals(right); - } - - /// - /// Returns one of the 6 planes related to this frustum. - /// - /// Plane index where 0 fro Left, 1 for Right, 2 for Top, 3 for Bottom, 4 for Near, 5 for Far - /// - public Plane GetPlane(int index) - { - switch (index) - { - case 0: return pLeft; - case 1: return pRight; - case 2: return pTop; - case 3: return pBottom; - case 4: return pNear; - case 5: return pFar; - default: - return new Plane(); - } - } - - private static void GetPlanesFromMatrix(ref Matrix matrix, out Plane near, out Plane far, out Plane left, out Plane right, out Plane top, out Plane bottom) - { - //http://www.chadvernon.com/blog/resources/directx9/frustum-culling/ - - // Left plane - left.Normal.X = matrix.M14 + matrix.M11; - left.Normal.Y = matrix.M24 + matrix.M21; - left.Normal.Z = matrix.M34 + matrix.M31; - left.D = matrix.M44 + matrix.M41; - left.Normalize(); - - // Right plane - right.Normal.X = matrix.M14 - matrix.M11; - right.Normal.Y = matrix.M24 - matrix.M21; - right.Normal.Z = matrix.M34 - matrix.M31; - right.D = matrix.M44 - matrix.M41; - right.Normalize(); - - // Top plane - top.Normal.X = matrix.M14 - matrix.M12; - top.Normal.Y = matrix.M24 - matrix.M22; - top.Normal.Z = matrix.M34 - matrix.M32; - top.D = matrix.M44 - matrix.M42; - top.Normalize(); - - // Bottom plane - bottom.Normal.X = matrix.M14 + matrix.M12; - bottom.Normal.Y = matrix.M24 + matrix.M22; - bottom.Normal.Z = matrix.M34 + matrix.M32; - bottom.D = matrix.M44 + matrix.M42; - bottom.Normalize(); - - // Near plane - near.Normal.X = matrix.M13; - near.Normal.Y = matrix.M23; - near.Normal.Z = matrix.M33; - near.D = matrix.M43; - near.Normalize(); - - // Far plane - far.Normal.X = matrix.M14 - matrix.M13; - far.Normal.Y = matrix.M24 - matrix.M23; - far.Normal.Z = matrix.M34 - matrix.M33; - far.D = matrix.M44 - matrix.M43; - far.Normalize(); - } - - private static Vector3 Get3PlanesInterPoint(ref Plane p1, ref Plane p2, ref Plane p3) - { - //P = -d1 * N2xN3 / N1.N2xN3 - d2 * N3xN1 / N2.N3xN1 - d3 * N1xN2 / N3.N1xN2 - Vector3 v = - -p1.D * Vector3.Cross(p2.Normal, p3.Normal) / Vector3.Dot(p1.Normal, Vector3.Cross(p2.Normal, p3.Normal)) - - p2.D * Vector3.Cross(p3.Normal, p1.Normal) / Vector3.Dot(p2.Normal, Vector3.Cross(p3.Normal, p1.Normal)) - - p3.D * Vector3.Cross(p1.Normal, p2.Normal) / Vector3.Dot(p3.Normal, Vector3.Cross(p1.Normal, p2.Normal)); - - return v; - } - - /// - /// Creates a new frustum relaying on perspective camera parameters - /// - /// The camera pos. - /// The look dir. - /// Up dir. - /// The fov. - /// The znear. - /// The zfar. - /// The aspect. - /// The bounding frustum calculated from perspective camera - public static BoundingFrustum FromCamera(Vector3 cameraPos, Vector3 lookDir, Vector3 upDir, float fov, float znear, float zfar, float aspect) - { - //http://knol.google.com/k/view-frustum - - lookDir = Vector3.Normalize(lookDir); - upDir = Vector3.Normalize(upDir); - - Vector3 nearCenter = cameraPos + lookDir * znear; - Vector3 farCenter = cameraPos + lookDir * zfar; - float nearHalfHeight = (float)(znear * Math.Tan(fov / 2f)); - float farHalfHeight = (float)(zfar * Math.Tan(fov / 2f)); - float nearHalfWidth = nearHalfHeight * aspect; - float farHalfWidth = farHalfHeight * aspect; - - Vector3 rightDir = Vector3.Normalize(Vector3.Cross(upDir, lookDir)); - Vector3 Near1 = nearCenter - nearHalfHeight * upDir + nearHalfWidth * rightDir; - Vector3 Near2 = nearCenter + nearHalfHeight * upDir + nearHalfWidth * rightDir; - Vector3 Near3 = nearCenter + nearHalfHeight * upDir - nearHalfWidth * rightDir; - Vector3 Near4 = nearCenter - nearHalfHeight * upDir - nearHalfWidth * rightDir; - Vector3 Far1 = farCenter - farHalfHeight * upDir + farHalfWidth * rightDir; - Vector3 Far2 = farCenter + farHalfHeight * upDir + farHalfWidth * rightDir; - Vector3 Far3 = farCenter + farHalfHeight * upDir - farHalfWidth * rightDir; - Vector3 Far4 = farCenter - farHalfHeight * upDir - farHalfWidth * rightDir; - - var result = new BoundingFrustum(); - result.pNear = new Plane(Near1, Near2, Near3); - result.pFar = new Plane(Far3, Far2, Far1); - result.pLeft = new Plane(Near4, Near3, Far3); - result.pRight = new Plane(Far1, Far2, Near2); - result.pTop = new Plane(Near2, Far2, Far3); - result.pBottom = new Plane(Far4, Far1, Near1); - - result.pNear.Normalize(); - result.pFar.Normalize(); - result.pLeft.Normalize(); - result.pRight.Normalize(); - result.pTop.Normalize(); - result.pBottom.Normalize(); - - result.pMatrix = Matrix.LookAtLH(cameraPos, cameraPos + lookDir * 10, upDir) * Matrix.PerspectiveFovLH(fov, aspect, znear, zfar); - - return result; - } - /// - /// Creates a new frustum relaying on perspective camera parameters - /// - /// The camera params. - /// The bounding frustum from camera params - public static BoundingFrustum FromCamera(FrustumCameraParams cameraParams) - { - return FromCamera(cameraParams.Position, cameraParams.LookAtDir, cameraParams.UpDir, cameraParams.FOV, cameraParams.ZNear, cameraParams.ZFar, cameraParams.AspectRatio); - } - - /// - /// Returns the 8 corners of the frustum, element0 is Near1 (near right down corner) - /// , element1 is Near2 (near right top corner) - /// , element2 is Near3 (near Left top corner) - /// , element3 is Near4 (near Left down corner) - /// , element4 is Far1 (far right down corner) - /// , element5 is Far2 (far right top corner) - /// , element6 is Far3 (far left top corner) - /// , element7 is Far4 (far left down corner) - /// - /// The 8 corners of the frustum - public Vector3[] GetCorners() - { - var corners = new Vector3[8]; - GetCorners(corners); - return corners; - } - - /// - /// Returns the 8 corners of the frustum, element0 is Near1 (near right down corner) - /// , element1 is Near2 (near right top corner) - /// , element2 is Near3 (near Left top corner) - /// , element3 is Near4 (near Left down corner) - /// , element4 is Far1 (far right down corner) - /// , element5 is Far2 (far right top corner) - /// , element6 is Far3 (far left top corner) - /// , element7 is Far4 (far left down corner) - /// - /// The 8 corners of the frustum - public void GetCorners(Vector3[] corners) - { - corners[0] = Get3PlanesInterPoint(ref pNear, ref pBottom, ref pRight); //Near1 - corners[1] = Get3PlanesInterPoint(ref pNear, ref pTop, ref pRight); //Near2 - corners[2] = Get3PlanesInterPoint(ref pNear, ref pTop, ref pLeft); //Near3 - corners[3] = Get3PlanesInterPoint(ref pNear, ref pBottom, ref pLeft); //Near3 - corners[4] = Get3PlanesInterPoint(ref pFar, ref pBottom, ref pRight); //Far1 - corners[5] = Get3PlanesInterPoint(ref pFar, ref pTop, ref pRight); //Far2 - corners[6] = Get3PlanesInterPoint(ref pFar, ref pTop, ref pLeft); //Far3 - corners[7] = Get3PlanesInterPoint(ref pFar, ref pBottom, ref pLeft); //Far3 - } - - /// - /// Extracts perspective camera parameters from the frustum, doesn't work with orthographic frustums. - /// - /// Perspective camera parameters from the frustum - public FrustumCameraParams GetCameraParams() - { - var corners = GetCorners(); - var cameraParam = new FrustumCameraParams(); - cameraParam.Position = Get3PlanesInterPoint(ref pRight, ref pTop, ref pLeft); - cameraParam.LookAtDir = pNear.Normal; - cameraParam.UpDir = Vector3.Normalize(Vector3.Cross(pRight.Normal, pNear.Normal)); - cameraParam.FOV = (float)((Math.PI / 2.0 - Math.Acos(Vector3.Dot(pNear.Normal, pTop.Normal))) * 2); - cameraParam.AspectRatio = (corners[6] - corners[5]).Length() / (corners[4] - corners[5]).Length(); - cameraParam.ZNear = (cameraParam.Position + (pNear.Normal * pNear.D)).Length(); - cameraParam.ZFar = (cameraParam.Position + (pFar.Normal * pFar.D)).Length(); - return cameraParam; - } - - /// - /// Checks whether a point lay inside, intersects or lay outside the frustum. - /// - /// The point. - /// Type of the containment - public ContainmentType Contains(ref Vector3 point) - { - var result = PlaneIntersectionType.Front; - var planeResult = PlaneIntersectionType.Front; - for (int i = 0; i < 6; i++) - { - switch (i) - { - case 0: planeResult = pNear.Intersects(ref point); break; - case 1: planeResult = pFar.Intersects(ref point); break; - case 2: planeResult = pLeft.Intersects(ref point); break; - case 3: planeResult = pRight.Intersects(ref point); break; - case 4: planeResult = pTop.Intersects(ref point); break; - case 5: planeResult = pBottom.Intersects(ref point); break; - } - switch (planeResult) - { - case PlaneIntersectionType.Back: - return ContainmentType.Disjoint; - case PlaneIntersectionType.Intersecting: - result = PlaneIntersectionType.Intersecting; - break; - } - } - switch (result) - { - case PlaneIntersectionType.Intersecting: return ContainmentType.Intersects; - default: return ContainmentType.Contains; - } - } - - /// - /// Checks whether a point lay inside, intersects or lay outside the frustum. - /// - /// The point. - /// Type of the containment - public ContainmentType Contains(Vector3 point) - { - return Contains(ref point); - } - - /// - /// Checks whether a group of points lay totally inside the frustum (Contains), or lay partially inside the frustum (Intersects), or lay outside the frustum (Disjoint). - /// - /// The points. - /// Type of the containment - public ContainmentType Contains(Vector3[] points) - { - throw new NotImplementedException(); - /* TODO: (PMin) This method is wrong, does not calculate case where only plane from points is intersected - var containsAny = false; - var containsAll = true; - for (int i = 0; i < points.Length; i++) - { - switch (Contains(ref points[i])) - { - case ContainmentType.Contains: - case ContainmentType.Intersects: - containsAny = true; - break; - case ContainmentType.Disjoint: - containsAll = false; - break; - } - } - if (containsAny) - { - if (containsAll) - return ContainmentType.Contains; - else - return ContainmentType.Intersects; - } - else - return ContainmentType.Disjoint; */ - } - /// - /// Checks whether a group of points lay totally inside the frustum (Contains), or lay partially inside the frustum (Intersects), or lay outside the frustum (Disjoint). - /// - /// The points. - /// Type of the containment. - public void Contains(Vector3[] points, out ContainmentType result) - { - result = Contains(points); - } - - private void GetBoxToPlanePVertexNVertex(ref BoundingBox box, ref Vector3 planeNormal, out Vector3 p, out Vector3 n) - { - p = box.Minimum; - if (planeNormal.X >= 0) - p.X = box.Maximum.X; - if (planeNormal.Y >= 0) - p.Y = box.Maximum.Y; - if (planeNormal.Z >= 0) - p.Z = box.Maximum.Z; - - n = box.Maximum; - if (planeNormal.X >= 0) - n.X = box.Minimum.X; - if (planeNormal.Y >= 0) - n.Y = box.Minimum.Y; - if (planeNormal.Z >= 0) - n.Z = box.Minimum.Z; - } - - /// - /// Determines the intersection relationship between the frustum and a bounding box. - /// - /// The box. - /// Type of the containment - public ContainmentType Contains(ref BoundingBox box) - { - Vector3 p, n; - Plane plane; - var result = ContainmentType.Contains; - for (int i = 0; i < 6; i++) - { - plane = GetPlane(i); - GetBoxToPlanePVertexNVertex(ref box, ref plane.Normal, out p, out n); - if (Collision.PlaneIntersectsPoint(ref plane, ref p) == PlaneIntersectionType.Back) - return ContainmentType.Disjoint; - - if (Collision.PlaneIntersectsPoint(ref plane, ref n) == PlaneIntersectionType.Back) - result = ContainmentType.Intersects; - } - return result; - } - - /// - /// Determines the intersection relationship between the frustum and a bounding box. - /// - /// The box. - /// Type of the containment - public ContainmentType Contains(BoundingBox box) - { - return Contains(ref box); - } - - /// - /// Determines the intersection relationship between the frustum and a bounding box. - /// - /// The box. - /// Type of the containment. - public void Contains(ref BoundingBox box, out ContainmentType result) - { - result = Contains(ref box); - } - /// - /// Determines the intersection relationship between the frustum and a bounding sphere. - /// - /// The sphere. - /// Type of the containment - public ContainmentType Contains(ref BoundingSphere sphere) - { - var result = PlaneIntersectionType.Front; - var planeResult = PlaneIntersectionType.Front; - for (int i = 0; i < 6; i++) - { - switch (i) - { - case 0: planeResult = pNear.Intersects(ref sphere); break; - case 1: planeResult = pFar.Intersects(ref sphere); break; - case 2: planeResult = pLeft.Intersects(ref sphere); break; - case 3: planeResult = pRight.Intersects(ref sphere); break; - case 4: planeResult = pTop.Intersects(ref sphere); break; - case 5: planeResult = pBottom.Intersects(ref sphere); break; - } - switch (planeResult) - { - case PlaneIntersectionType.Back: - return ContainmentType.Disjoint; - case PlaneIntersectionType.Intersecting: - result = PlaneIntersectionType.Intersecting; - break; - } - } - switch (result) - { - case PlaneIntersectionType.Intersecting: return ContainmentType.Intersects; - default: return ContainmentType.Contains; - } - } - - /// - /// Determines the intersection relationship between the frustum and a bounding sphere. - /// - /// The sphere. - /// Type of the containment - public ContainmentType Contains(BoundingSphere sphere) - { - return Contains(ref sphere); - } - - /// - /// Determines the intersection relationship between the frustum and a bounding sphere. - /// - /// The sphere. - /// Type of the containment. - public void Contains(ref BoundingSphere sphere, out ContainmentType result) - { - result = Contains(ref sphere); - } - /// - /// Determines the intersection relationship between the frustum and another bounding frustum. - /// - /// The frustum. - /// Type of the containment - public bool Contains(ref BoundingFrustum frustum) - { - return Contains(frustum.GetCorners()) != ContainmentType.Disjoint; - } - - /// - /// Determines the intersection relationship between the frustum and another bounding frustum. - /// - /// The frustum. - /// Type of the containment - public bool Contains(BoundingFrustum frustum) - { - return Contains(ref frustum); - } - - /// - /// Determines the intersection relationship between the frustum and another bounding frustum. - /// - /// The frustum. - /// Type of the containment. - public void Contains(ref BoundingFrustum frustum, out bool result) - { - result = Contains(frustum.GetCorners()) != ContainmentType.Disjoint; - } - - /// - /// Checks whether the current BoundingFrustum intersects a BoundingSphere. - /// - /// The sphere. - /// Type of the containment - public bool Intersects(ref BoundingSphere sphere) - { - return Contains(ref sphere) != ContainmentType.Disjoint; - } - /// - /// Checks whether the current BoundingFrustum intersects a BoundingSphere. - /// - /// The sphere. - /// Set to true if the current BoundingFrustum intersects a BoundingSphere. - public void Intersects(ref BoundingSphere sphere, out bool result) - { - result = Contains(ref sphere) != ContainmentType.Disjoint; - } - /// - /// Checks whether the current BoundingFrustum intersects a BoundingBox. - /// - /// The box. - /// true if the current BoundingFrustum intersects a BoundingSphere. - public bool Intersects(ref BoundingBox box) - { - return Contains(ref box) != ContainmentType.Disjoint; - } - /// - /// Checks whether the current BoundingFrustum intersects a BoundingBox. - /// - /// The box. - /// true if the current BoundingFrustum intersects a BoundingSphere. - public void Intersects(ref BoundingBox box, out bool result) - { - result = Contains(ref box) != ContainmentType.Disjoint; - } - - private PlaneIntersectionType PlaneIntersectsPoints(ref Plane plane, Vector3[] points) - { - var result = Collision.PlaneIntersectsPoint(ref plane, ref points[0]); - for (int i = 1; i < points.Length; i++) - if (Collision.PlaneIntersectsPoint(ref plane, ref points[i]) != result) - return PlaneIntersectionType.Intersecting; - return result; - } - - /// - /// Checks whether the current BoundingFrustum intersects the specified Plane. - /// - /// The plane. - /// Plane intersection type. - public PlaneIntersectionType Intersects(ref Plane plane) - { - return PlaneIntersectsPoints(ref plane, GetCorners()); - } - /// - /// Checks whether the current BoundingFrustum intersects the specified Plane. - /// - /// The plane. - /// Plane intersection type. - public void Intersects(ref Plane plane, out PlaneIntersectionType result) - { - result = PlaneIntersectsPoints(ref plane, GetCorners()); - } - - /// - /// Get the width of the frustum at specified depth. - /// - /// the depth at which to calculate frustum width. - /// With of the frustum at the specified depth - public float GetWidthAtDepth(float depth) - { - float hAngle = (float)((Math.PI / 2.0 - Math.Acos(Vector3.Dot(pNear.Normal, pLeft.Normal)))); - return (float)(Math.Tan(hAngle) * depth * 2); - } - - /// - /// Get the height of the frustum at specified depth. - /// - /// the depth at which to calculate frustum height. - /// Height of the frustum at the specified depth - public float GetHeightAtDepth(float depth) - { - float vAngle = (float)((Math.PI / 2.0 - Math.Acos(Vector3.Dot(pNear.Normal, pTop.Normal)))); - return (float)(Math.Tan(vAngle) * depth * 2); - } - - private BoundingFrustum GetInsideOutClone() - { - var frustum = this; - frustum.pNear.Normal = -frustum.pNear.Normal; - frustum.pFar.Normal = -frustum.pFar.Normal; - frustum.pLeft.Normal = -frustum.pLeft.Normal; - frustum.pRight.Normal = -frustum.pRight.Normal; - frustum.pTop.Normal = -frustum.pTop.Normal; - frustum.pBottom.Normal = -frustum.pBottom.Normal; - return frustum; - } - - /// - /// Checks whether the current BoundingFrustum intersects the specified Ray. - /// - /// The ray. - /// true if the current BoundingFrustum intersects the specified Ray. - public bool Intersects(ref Ray ray) - { - float? inDist, outDist; - return Intersects(ref ray, out inDist, out outDist); - } - /// - /// Checks whether the current BoundingFrustum intersects the specified Ray. - /// - /// The Ray to check for intersection with. - /// The distance at which the ray enters the frustum if there is an intersection and the ray starts outside the frustum. - /// The distance at which the ray exits the frustum if there is an intersection. - /// true if the current BoundingFrustum intersects the specified Ray. - public bool Intersects(ref Ray ray, out float? inDistance, out float? outDistance) - { - if (Contains(ray.Position) != ContainmentType.Disjoint) - { - float nearstPlaneDistance = float.MaxValue; - for (int i = 0; i < 6; i++) - { - var plane = GetPlane(i); - float distance; - if (Collision.RayIntersectsPlane(ref ray, ref plane, out distance) && distance < nearstPlaneDistance) - { - nearstPlaneDistance = distance; - } - } - - inDistance = nearstPlaneDistance; - outDistance = null; - return true; - } - else - { - //We will find the two points at which the ray enters and exists the frustum - //These two points make a line which center inside the frustum if the ray intersects it - //Or outside the frustum if the ray intersects frustum planes outside it. - float minDist = float.MaxValue; - float maxDist = float.MinValue; - for (int i = 0; i < 6; i++) - { - var plane = GetPlane(i); - float distance; - if (Collision.RayIntersectsPlane(ref ray, ref plane, out distance)) - { - minDist = Math.Min(minDist, distance); - maxDist = Math.Max(maxDist, distance); - } - } - - Vector3 minPoint = ray.Position + ray.Direction * minDist; - Vector3 maxPoint = ray.Position + ray.Direction * maxDist; - Vector3 center = (minPoint + maxPoint) / 2f; - if (Contains(ref center) != ContainmentType.Disjoint) - { - inDistance = minDist; - outDistance = maxDist; - return true; - } - else - { - inDistance = null; - outDistance = null; - return false; - } - } - } - - /// - /// Get the distance which when added to camera position along the lookat direction will do the effect of zoom to extents (zoom to fit) operation, - /// so all the passed points will fit in the current view. - /// if the returned value is positive, the camera will move toward the lookat direction (ZoomIn). - /// if the returned value is negative, the camera will move in the reverse direction of the lookat direction (ZoomOut). - /// - /// The points. - /// The zoom to fit distance - public float GetZoomToExtentsShiftDistance(Vector3[] points) - { - float vAngle = (float)((Math.PI / 2.0 - Math.Acos(Vector3.Dot(pNear.Normal, pTop.Normal)))); - float vSin = (float)Math.Sin(vAngle); - float hAngle = (float)((Math.PI / 2.0 - Math.Acos(Vector3.Dot(pNear.Normal, pLeft.Normal)))); - float hSin = (float)Math.Sin(hAngle); - float horizontalToVerticalMapping = vSin / hSin; - - var ioFrustrum = GetInsideOutClone(); - - float maxPointDist = float.MinValue; - for (int i = 0; i < points.Length; i++) - { - float pointDist = Collision.DistancePlanePoint(ref ioFrustrum.pTop, ref points[i]); - pointDist = Math.Max(pointDist, Collision.DistancePlanePoint(ref ioFrustrum.pBottom, ref points[i])); - pointDist = Math.Max(pointDist, Collision.DistancePlanePoint(ref ioFrustrum.pLeft, ref points[i]) * horizontalToVerticalMapping); - pointDist = Math.Max(pointDist, Collision.DistancePlanePoint(ref ioFrustrum.pRight, ref points[i]) * horizontalToVerticalMapping); - - maxPointDist = Math.Max(maxPointDist, pointDist); - } - return -maxPointDist / vSin; - } - - /// - /// Get the distance which when added to camera position along the lookat direction will do the effect of zoom to extents (zoom to fit) operation, - /// so all the passed points will fit in the current view. - /// if the returned value is positive, the camera will move toward the lookat direction (ZoomIn). - /// if the returned value is negative, the camera will move in the reverse direction of the lookat direction (ZoomOut). - /// - /// The bounding box. - /// The zoom to fit distance - public float GetZoomToExtentsShiftDistance(ref BoundingBox boundingBox) - { - return GetZoomToExtentsShiftDistance(boundingBox.GetCorners()); - } - - /// - /// Get the vector shift which when added to camera position will do the effect of zoom to extents (zoom to fit) operation, - /// so all the passed points will fit in the current view. - /// - /// The points. - /// The zoom to fit vector - public Vector3 GetZoomToExtentsShiftVector(Vector3[] points) - { - return GetZoomToExtentsShiftDistance(points) * pNear.Normal; - } - /// - /// Get the vector shift which when added to camera position will do the effect of zoom to extents (zoom to fit) operation, - /// so all the passed points will fit in the current view. - /// - /// The bounding box. - /// The zoom to fit vector - public Vector3 GetZoomToExtentsShiftVector(ref BoundingBox boundingBox) - { - return GetZoomToExtentsShiftDistance(boundingBox.GetCorners()) * pNear.Normal; - } - - /// - /// Indicate whether the current BoundingFrustrum is Orthographic. - /// - /// - /// true if the current BoundingFrustrum is Orthographic; otherwise, false. - /// - public bool IsOrthographic - { - get - { - return (pLeft.Normal == -pRight.Normal) && (pTop.Normal == -pBottom.Normal); - } - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - serializer.Serialize(ref pMatrix); - serializer.Serialize(ref pNear); - serializer.Serialize(ref pFar); - serializer.Serialize(ref pLeft); - serializer.Serialize(ref pRight); - serializer.Serialize(ref pTop); - serializer.Serialize(ref pBottom); - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Defines a frustum which can be used in frustum culling, zoom to Extents (zoom to fit) operations, + /// (matrix, frustum, camera) interchange, and many kind of intersection testing. + /// + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct BoundingFrustum : IEquatable + { + private Matrix pMatrix; + private Plane pNear; + private Plane pFar; + private Plane pLeft; + private Plane pRight; + private Plane pTop; + private Plane pBottom; + + /// + /// Gets or sets the Matrix that describes this bounding frustum. + /// + public Matrix Matrix + { + get + { + return pMatrix; + } + set + { + pMatrix = value; + GetPlanesFromMatrix(ref pMatrix, out pNear, out pFar, out pLeft, out pRight, out pTop, out pBottom); + } + } + /// + /// Gets the near plane of the BoundingFrustum. + /// + public Plane Near + { + get + { + return pNear; + } + } + /// + /// Gets the far plane of the BoundingFrustum. + /// + public Plane Far + { + get + { + return pFar; + } + } + /// + /// Gets the left plane of the BoundingFrustum. + /// + public Plane Left + { + get + { + return pLeft; + } + } + /// + /// Gets the right plane of the BoundingFrustum. + /// + public Plane Right + { + get + { + return pRight; + } + } + /// + /// Gets the top plane of the BoundingFrustum. + /// + public Plane Top + { + get + { + return pTop; + } + } + /// + /// Gets the bottom plane of the BoundingFrustum. + /// + public Plane Bottom + { + get + { + return pBottom; + } + } + + /// + /// Creates a new instance of BoundingFrustum. + /// + /// Combined matrix that usually takes view × projection matrix. + public BoundingFrustum(Matrix matrix) + { + pMatrix = matrix; + GetPlanesFromMatrix(ref pMatrix, out pNear, out pFar, out pLeft, out pRight, out pTop, out pBottom); + } + + public override int GetHashCode() + { + return pMatrix.GetHashCode(); + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(BoundingFrustum other) + { + return this.pMatrix == other.pMatrix; + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object obj) + { + if (obj != null && obj is BoundingFrustum) + return Equals((BoundingFrustum)obj); + return false; + } + + /// + /// Implements the operator ==. + /// + /// The left. + /// The right. + /// + /// The result of the operator. + /// + public static bool operator ==(BoundingFrustum left, BoundingFrustum right) + { + return left.Equals(right); + } + + /// + /// Implements the operator !=. + /// + /// The left. + /// The right. + /// + /// The result of the operator. + /// + public static bool operator !=(BoundingFrustum left, BoundingFrustum right) + { + return !left.Equals(right); + } + + /// + /// Returns one of the 6 planes related to this frustum. + /// + /// Plane index where 0 fro Left, 1 for Right, 2 for Top, 3 for Bottom, 4 for Near, 5 for Far + /// + public Plane GetPlane(int index) + { + switch (index) + { + case 0: return pLeft; + case 1: return pRight; + case 2: return pTop; + case 3: return pBottom; + case 4: return pNear; + case 5: return pFar; + default: + return new Plane(); + } + } + + private static void GetPlanesFromMatrix(ref Matrix matrix, out Plane near, out Plane far, out Plane left, out Plane right, out Plane top, out Plane bottom) + { + //http://www.chadvernon.com/blog/resources/directx9/frustum-culling/ + + // Left plane + left.Normal.X = matrix.M14 + matrix.M11; + left.Normal.Y = matrix.M24 + matrix.M21; + left.Normal.Z = matrix.M34 + matrix.M31; + left.D = matrix.M44 + matrix.M41; + left.Normalize(); + + // Right plane + right.Normal.X = matrix.M14 - matrix.M11; + right.Normal.Y = matrix.M24 - matrix.M21; + right.Normal.Z = matrix.M34 - matrix.M31; + right.D = matrix.M44 - matrix.M41; + right.Normalize(); + + // Top plane + top.Normal.X = matrix.M14 - matrix.M12; + top.Normal.Y = matrix.M24 - matrix.M22; + top.Normal.Z = matrix.M34 - matrix.M32; + top.D = matrix.M44 - matrix.M42; + top.Normalize(); + + // Bottom plane + bottom.Normal.X = matrix.M14 + matrix.M12; + bottom.Normal.Y = matrix.M24 + matrix.M22; + bottom.Normal.Z = matrix.M34 + matrix.M32; + bottom.D = matrix.M44 + matrix.M42; + bottom.Normalize(); + + // Near plane + near.Normal.X = matrix.M13; + near.Normal.Y = matrix.M23; + near.Normal.Z = matrix.M33; + near.D = matrix.M43; + near.Normalize(); + + // Far plane + far.Normal.X = matrix.M14 - matrix.M13; + far.Normal.Y = matrix.M24 - matrix.M23; + far.Normal.Z = matrix.M34 - matrix.M33; + far.D = matrix.M44 - matrix.M43; + far.Normalize(); + } + + private static Vector3 Get3PlanesInterPoint(ref Plane p1, ref Plane p2, ref Plane p3) + { + //P = -d1 * N2xN3 / N1.N2xN3 - d2 * N3xN1 / N2.N3xN1 - d3 * N1xN2 / N3.N1xN2 + Vector3 v = + -p1.D * Vector3.Cross(p2.Normal, p3.Normal) / Vector3.Dot(p1.Normal, Vector3.Cross(p2.Normal, p3.Normal)) + - p2.D * Vector3.Cross(p3.Normal, p1.Normal) / Vector3.Dot(p2.Normal, Vector3.Cross(p3.Normal, p1.Normal)) + - p3.D * Vector3.Cross(p1.Normal, p2.Normal) / Vector3.Dot(p3.Normal, Vector3.Cross(p1.Normal, p2.Normal)); + + return v; + } + + /// + /// Creates a new frustum relaying on perspective camera parameters + /// + /// The camera pos. + /// The look dir. + /// Up dir. + /// The fov. + /// The znear. + /// The zfar. + /// The aspect. + /// The bounding frustum calculated from perspective camera + public static BoundingFrustum FromCamera(Vector3 cameraPos, Vector3 lookDir, Vector3 upDir, float fov, float znear, float zfar, float aspect) + { + //http://knol.google.com/k/view-frustum + + lookDir = Vector3.Normalize(lookDir); + upDir = Vector3.Normalize(upDir); + + Vector3 nearCenter = cameraPos + lookDir * znear; + Vector3 farCenter = cameraPos + lookDir * zfar; + float nearHalfHeight = (float)(znear * Math.Tan(fov / 2f)); + float farHalfHeight = (float)(zfar * Math.Tan(fov / 2f)); + float nearHalfWidth = nearHalfHeight * aspect; + float farHalfWidth = farHalfHeight * aspect; + + Vector3 rightDir = Vector3.Normalize(Vector3.Cross(upDir, lookDir)); + Vector3 Near1 = nearCenter - nearHalfHeight * upDir + nearHalfWidth * rightDir; + Vector3 Near2 = nearCenter + nearHalfHeight * upDir + nearHalfWidth * rightDir; + Vector3 Near3 = nearCenter + nearHalfHeight * upDir - nearHalfWidth * rightDir; + Vector3 Near4 = nearCenter - nearHalfHeight * upDir - nearHalfWidth * rightDir; + Vector3 Far1 = farCenter - farHalfHeight * upDir + farHalfWidth * rightDir; + Vector3 Far2 = farCenter + farHalfHeight * upDir + farHalfWidth * rightDir; + Vector3 Far3 = farCenter + farHalfHeight * upDir - farHalfWidth * rightDir; + Vector3 Far4 = farCenter - farHalfHeight * upDir - farHalfWidth * rightDir; + + var result = new BoundingFrustum(); + result.pNear = new Plane(Near1, Near2, Near3); + result.pFar = new Plane(Far3, Far2, Far1); + result.pLeft = new Plane(Near4, Near3, Far3); + result.pRight = new Plane(Far1, Far2, Near2); + result.pTop = new Plane(Near2, Far2, Far3); + result.pBottom = new Plane(Far4, Far1, Near1); + + result.pNear.Normalize(); + result.pFar.Normalize(); + result.pLeft.Normalize(); + result.pRight.Normalize(); + result.pTop.Normalize(); + result.pBottom.Normalize(); + + result.pMatrix = Matrix.LookAtLH(cameraPos, cameraPos + lookDir * 10, upDir) * Matrix.PerspectiveFovLH(fov, aspect, znear, zfar); + + return result; + } + /// + /// Creates a new frustum relaying on perspective camera parameters + /// + /// The camera params. + /// The bounding frustum from camera params + public static BoundingFrustum FromCamera(FrustumCameraParams cameraParams) + { + return FromCamera(cameraParams.Position, cameraParams.LookAtDir, cameraParams.UpDir, cameraParams.FOV, cameraParams.ZNear, cameraParams.ZFar, cameraParams.AspectRatio); + } + + /// + /// Returns the 8 corners of the frustum, element0 is Near1 (near right down corner) + /// , element1 is Near2 (near right top corner) + /// , element2 is Near3 (near Left top corner) + /// , element3 is Near4 (near Left down corner) + /// , element4 is Far1 (far right down corner) + /// , element5 is Far2 (far right top corner) + /// , element6 is Far3 (far left top corner) + /// , element7 is Far4 (far left down corner) + /// + /// The 8 corners of the frustum + public Vector3[] GetCorners() + { + var corners = new Vector3[8]; + GetCorners(corners); + return corners; + } + + /// + /// Returns the 8 corners of the frustum, element0 is Near1 (near right down corner) + /// , element1 is Near2 (near right top corner) + /// , element2 is Near3 (near Left top corner) + /// , element3 is Near4 (near Left down corner) + /// , element4 is Far1 (far right down corner) + /// , element5 is Far2 (far right top corner) + /// , element6 is Far3 (far left top corner) + /// , element7 is Far4 (far left down corner) + /// + /// The 8 corners of the frustum + public void GetCorners(Vector3[] corners) + { + corners[0] = Get3PlanesInterPoint(ref pNear, ref pBottom, ref pRight); //Near1 + corners[1] = Get3PlanesInterPoint(ref pNear, ref pTop, ref pRight); //Near2 + corners[2] = Get3PlanesInterPoint(ref pNear, ref pTop, ref pLeft); //Near3 + corners[3] = Get3PlanesInterPoint(ref pNear, ref pBottom, ref pLeft); //Near3 + corners[4] = Get3PlanesInterPoint(ref pFar, ref pBottom, ref pRight); //Far1 + corners[5] = Get3PlanesInterPoint(ref pFar, ref pTop, ref pRight); //Far2 + corners[6] = Get3PlanesInterPoint(ref pFar, ref pTop, ref pLeft); //Far3 + corners[7] = Get3PlanesInterPoint(ref pFar, ref pBottom, ref pLeft); //Far3 + } + + /// + /// Extracts perspective camera parameters from the frustum, doesn't work with orthographic frustums. + /// + /// Perspective camera parameters from the frustum + public FrustumCameraParams GetCameraParams() + { + var corners = GetCorners(); + var cameraParam = new FrustumCameraParams(); + cameraParam.Position = Get3PlanesInterPoint(ref pRight, ref pTop, ref pLeft); + cameraParam.LookAtDir = pNear.Normal; + cameraParam.UpDir = Vector3.Normalize(Vector3.Cross(pRight.Normal, pNear.Normal)); + cameraParam.FOV = (float)((Math.PI / 2.0 - Math.Acos(Vector3.Dot(pNear.Normal, pTop.Normal))) * 2); + cameraParam.AspectRatio = (corners[6] - corners[5]).Length() / (corners[4] - corners[5]).Length(); + cameraParam.ZNear = (cameraParam.Position + (pNear.Normal * pNear.D)).Length(); + cameraParam.ZFar = (cameraParam.Position + (pFar.Normal * pFar.D)).Length(); + return cameraParam; + } + + /// + /// Checks whether a point lay inside, intersects or lay outside the frustum. + /// + /// The point. + /// Type of the containment + public ContainmentType Contains(ref Vector3 point) + { + var result = PlaneIntersectionType.Front; + var planeResult = PlaneIntersectionType.Front; + for (int i = 0; i < 6; i++) + { + switch (i) + { + case 0: planeResult = pNear.Intersects(ref point); break; + case 1: planeResult = pFar.Intersects(ref point); break; + case 2: planeResult = pLeft.Intersects(ref point); break; + case 3: planeResult = pRight.Intersects(ref point); break; + case 4: planeResult = pTop.Intersects(ref point); break; + case 5: planeResult = pBottom.Intersects(ref point); break; + } + switch (planeResult) + { + case PlaneIntersectionType.Back: + return ContainmentType.Disjoint; + case PlaneIntersectionType.Intersecting: + result = PlaneIntersectionType.Intersecting; + break; + } + } + switch (result) + { + case PlaneIntersectionType.Intersecting: return ContainmentType.Intersects; + default: return ContainmentType.Contains; + } + } + + /// + /// Checks whether a point lay inside, intersects or lay outside the frustum. + /// + /// The point. + /// Type of the containment + public ContainmentType Contains(Vector3 point) + { + return Contains(ref point); + } + + /// + /// Checks whether a group of points lay totally inside the frustum (Contains), or lay partially inside the frustum (Intersects), or lay outside the frustum (Disjoint). + /// + /// The points. + /// Type of the containment + public ContainmentType Contains(Vector3[] points) + { + throw new NotImplementedException(); + /* TODO: (PMin) This method is wrong, does not calculate case where only plane from points is intersected + var containsAny = false; + var containsAll = true; + for (int i = 0; i < points.Length; i++) + { + switch (Contains(ref points[i])) + { + case ContainmentType.Contains: + case ContainmentType.Intersects: + containsAny = true; + break; + case ContainmentType.Disjoint: + containsAll = false; + break; + } + } + if (containsAny) + { + if (containsAll) + return ContainmentType.Contains; + else + return ContainmentType.Intersects; + } + else + return ContainmentType.Disjoint; */ + } + /// + /// Checks whether a group of points lay totally inside the frustum (Contains), or lay partially inside the frustum (Intersects), or lay outside the frustum (Disjoint). + /// + /// The points. + /// Type of the containment. + public void Contains(Vector3[] points, out ContainmentType result) + { + result = Contains(points); + } + + private void GetBoxToPlanePVertexNVertex(ref BoundingBox box, ref Vector3 planeNormal, out Vector3 p, out Vector3 n) + { + p = box.Minimum; + if (planeNormal.X >= 0) + p.X = box.Maximum.X; + if (planeNormal.Y >= 0) + p.Y = box.Maximum.Y; + if (planeNormal.Z >= 0) + p.Z = box.Maximum.Z; + + n = box.Maximum; + if (planeNormal.X >= 0) + n.X = box.Minimum.X; + if (planeNormal.Y >= 0) + n.Y = box.Minimum.Y; + if (planeNormal.Z >= 0) + n.Z = box.Minimum.Z; + } + + /// + /// Determines the intersection relationship between the frustum and a bounding box. + /// + /// The box. + /// Type of the containment + public ContainmentType Contains(ref BoundingBox box) + { + Vector3 p, n; + Plane plane; + var result = ContainmentType.Contains; + for (int i = 0; i < 6; i++) + { + plane = GetPlane(i); + GetBoxToPlanePVertexNVertex(ref box, ref plane.Normal, out p, out n); + if (Collision.PlaneIntersectsPoint(ref plane, ref p) == PlaneIntersectionType.Back) + return ContainmentType.Disjoint; + + if (Collision.PlaneIntersectsPoint(ref plane, ref n) == PlaneIntersectionType.Back) + result = ContainmentType.Intersects; + } + return result; + } + + /// + /// Determines the intersection relationship between the frustum and a bounding box. + /// + /// The box. + /// Type of the containment + public ContainmentType Contains(BoundingBox box) + { + return Contains(ref box); + } + + /// + /// Determines the intersection relationship between the frustum and a bounding box. + /// + /// The box. + /// Type of the containment. + public void Contains(ref BoundingBox box, out ContainmentType result) + { + result = Contains(ref box); + } + /// + /// Determines the intersection relationship between the frustum and a bounding sphere. + /// + /// The sphere. + /// Type of the containment + public ContainmentType Contains(ref BoundingSphere sphere) + { + var result = PlaneIntersectionType.Front; + var planeResult = PlaneIntersectionType.Front; + for (int i = 0; i < 6; i++) + { + switch (i) + { + case 0: planeResult = pNear.Intersects(ref sphere); break; + case 1: planeResult = pFar.Intersects(ref sphere); break; + case 2: planeResult = pLeft.Intersects(ref sphere); break; + case 3: planeResult = pRight.Intersects(ref sphere); break; + case 4: planeResult = pTop.Intersects(ref sphere); break; + case 5: planeResult = pBottom.Intersects(ref sphere); break; + } + switch (planeResult) + { + case PlaneIntersectionType.Back: + return ContainmentType.Disjoint; + case PlaneIntersectionType.Intersecting: + result = PlaneIntersectionType.Intersecting; + break; + } + } + switch (result) + { + case PlaneIntersectionType.Intersecting: return ContainmentType.Intersects; + default: return ContainmentType.Contains; + } + } + + /// + /// Determines the intersection relationship between the frustum and a bounding sphere. + /// + /// The sphere. + /// Type of the containment + public ContainmentType Contains(BoundingSphere sphere) + { + return Contains(ref sphere); + } + + /// + /// Determines the intersection relationship between the frustum and a bounding sphere. + /// + /// The sphere. + /// Type of the containment. + public void Contains(ref BoundingSphere sphere, out ContainmentType result) + { + result = Contains(ref sphere); + } + /// + /// Determines the intersection relationship between the frustum and another bounding frustum. + /// + /// The frustum. + /// Type of the containment + public bool Contains(ref BoundingFrustum frustum) + { + return Contains(frustum.GetCorners()) != ContainmentType.Disjoint; + } + + /// + /// Determines the intersection relationship between the frustum and another bounding frustum. + /// + /// The frustum. + /// Type of the containment + public bool Contains(BoundingFrustum frustum) + { + return Contains(ref frustum); + } + + /// + /// Determines the intersection relationship between the frustum and another bounding frustum. + /// + /// The frustum. + /// Type of the containment. + public void Contains(ref BoundingFrustum frustum, out bool result) + { + result = Contains(frustum.GetCorners()) != ContainmentType.Disjoint; + } + + /// + /// Checks whether the current BoundingFrustum intersects a BoundingSphere. + /// + /// The sphere. + /// Type of the containment + public bool Intersects(ref BoundingSphere sphere) + { + return Contains(ref sphere) != ContainmentType.Disjoint; + } + /// + /// Checks whether the current BoundingFrustum intersects a BoundingSphere. + /// + /// The sphere. + /// Set to true if the current BoundingFrustum intersects a BoundingSphere. + public void Intersects(ref BoundingSphere sphere, out bool result) + { + result = Contains(ref sphere) != ContainmentType.Disjoint; + } + /// + /// Checks whether the current BoundingFrustum intersects a BoundingBox. + /// + /// The box. + /// true if the current BoundingFrustum intersects a BoundingSphere. + public bool Intersects(ref BoundingBox box) + { + return Contains(ref box) != ContainmentType.Disjoint; + } + /// + /// Checks whether the current BoundingFrustum intersects a BoundingBox. + /// + /// The box. + /// true if the current BoundingFrustum intersects a BoundingSphere. + public void Intersects(ref BoundingBox box, out bool result) + { + result = Contains(ref box) != ContainmentType.Disjoint; + } + + private PlaneIntersectionType PlaneIntersectsPoints(ref Plane plane, Vector3[] points) + { + var result = Collision.PlaneIntersectsPoint(ref plane, ref points[0]); + for (int i = 1; i < points.Length; i++) + if (Collision.PlaneIntersectsPoint(ref plane, ref points[i]) != result) + return PlaneIntersectionType.Intersecting; + return result; + } + + /// + /// Checks whether the current BoundingFrustum intersects the specified Plane. + /// + /// The plane. + /// Plane intersection type. + public PlaneIntersectionType Intersects(ref Plane plane) + { + return PlaneIntersectsPoints(ref plane, GetCorners()); + } + /// + /// Checks whether the current BoundingFrustum intersects the specified Plane. + /// + /// The plane. + /// Plane intersection type. + public void Intersects(ref Plane plane, out PlaneIntersectionType result) + { + result = PlaneIntersectsPoints(ref plane, GetCorners()); + } + + /// + /// Get the width of the frustum at specified depth. + /// + /// the depth at which to calculate frustum width. + /// With of the frustum at the specified depth + public float GetWidthAtDepth(float depth) + { + float hAngle = (float)((Math.PI / 2.0 - Math.Acos(Vector3.Dot(pNear.Normal, pLeft.Normal)))); + return (float)(Math.Tan(hAngle) * depth * 2); + } + + /// + /// Get the height of the frustum at specified depth. + /// + /// the depth at which to calculate frustum height. + /// Height of the frustum at the specified depth + public float GetHeightAtDepth(float depth) + { + float vAngle = (float)((Math.PI / 2.0 - Math.Acos(Vector3.Dot(pNear.Normal, pTop.Normal)))); + return (float)(Math.Tan(vAngle) * depth * 2); + } + + private BoundingFrustum GetInsideOutClone() + { + var frustum = this; + frustum.pNear.Normal = -frustum.pNear.Normal; + frustum.pFar.Normal = -frustum.pFar.Normal; + frustum.pLeft.Normal = -frustum.pLeft.Normal; + frustum.pRight.Normal = -frustum.pRight.Normal; + frustum.pTop.Normal = -frustum.pTop.Normal; + frustum.pBottom.Normal = -frustum.pBottom.Normal; + return frustum; + } + + /// + /// Checks whether the current BoundingFrustum intersects the specified Ray. + /// + /// The ray. + /// true if the current BoundingFrustum intersects the specified Ray. + public bool Intersects(ref Ray ray) + { + float? inDist, outDist; + return Intersects(ref ray, out inDist, out outDist); + } + /// + /// Checks whether the current BoundingFrustum intersects the specified Ray. + /// + /// The Ray to check for intersection with. + /// The distance at which the ray enters the frustum if there is an intersection and the ray starts outside the frustum. + /// The distance at which the ray exits the frustum if there is an intersection. + /// true if the current BoundingFrustum intersects the specified Ray. + public bool Intersects(ref Ray ray, out float? inDistance, out float? outDistance) + { + if (Contains(ray.Position) != ContainmentType.Disjoint) + { + float nearstPlaneDistance = float.MaxValue; + for (int i = 0; i < 6; i++) + { + var plane = GetPlane(i); + float distance; + if (Collision.RayIntersectsPlane(ref ray, ref plane, out distance) && distance < nearstPlaneDistance) + { + nearstPlaneDistance = distance; + } + } + + inDistance = nearstPlaneDistance; + outDistance = null; + return true; + } + else + { + //We will find the two points at which the ray enters and exists the frustum + //These two points make a line which center inside the frustum if the ray intersects it + //Or outside the frustum if the ray intersects frustum planes outside it. + float minDist = float.MaxValue; + float maxDist = float.MinValue; + for (int i = 0; i < 6; i++) + { + var plane = GetPlane(i); + float distance; + if (Collision.RayIntersectsPlane(ref ray, ref plane, out distance)) + { + minDist = Math.Min(minDist, distance); + maxDist = Math.Max(maxDist, distance); + } + } + + Vector3 minPoint = ray.Position + ray.Direction * minDist; + Vector3 maxPoint = ray.Position + ray.Direction * maxDist; + Vector3 center = (minPoint + maxPoint) / 2f; + if (Contains(ref center) != ContainmentType.Disjoint) + { + inDistance = minDist; + outDistance = maxDist; + return true; + } + else + { + inDistance = null; + outDistance = null; + return false; + } + } + } + + /// + /// Get the distance which when added to camera position along the lookat direction will do the effect of zoom to extents (zoom to fit) operation, + /// so all the passed points will fit in the current view. + /// if the returned value is positive, the camera will move toward the lookat direction (ZoomIn). + /// if the returned value is negative, the camera will move in the reverse direction of the lookat direction (ZoomOut). + /// + /// The points. + /// The zoom to fit distance + public float GetZoomToExtentsShiftDistance(Vector3[] points) + { + float vAngle = (float)((Math.PI / 2.0 - Math.Acos(Vector3.Dot(pNear.Normal, pTop.Normal)))); + float vSin = (float)Math.Sin(vAngle); + float hAngle = (float)((Math.PI / 2.0 - Math.Acos(Vector3.Dot(pNear.Normal, pLeft.Normal)))); + float hSin = (float)Math.Sin(hAngle); + float horizontalToVerticalMapping = vSin / hSin; + + var ioFrustrum = GetInsideOutClone(); + + float maxPointDist = float.MinValue; + for (int i = 0; i < points.Length; i++) + { + float pointDist = Collision.DistancePlanePoint(ref ioFrustrum.pTop, ref points[i]); + pointDist = Math.Max(pointDist, Collision.DistancePlanePoint(ref ioFrustrum.pBottom, ref points[i])); + pointDist = Math.Max(pointDist, Collision.DistancePlanePoint(ref ioFrustrum.pLeft, ref points[i]) * horizontalToVerticalMapping); + pointDist = Math.Max(pointDist, Collision.DistancePlanePoint(ref ioFrustrum.pRight, ref points[i]) * horizontalToVerticalMapping); + + maxPointDist = Math.Max(maxPointDist, pointDist); + } + return -maxPointDist / vSin; + } + + /// + /// Get the distance which when added to camera position along the lookat direction will do the effect of zoom to extents (zoom to fit) operation, + /// so all the passed points will fit in the current view. + /// if the returned value is positive, the camera will move toward the lookat direction (ZoomIn). + /// if the returned value is negative, the camera will move in the reverse direction of the lookat direction (ZoomOut). + /// + /// The bounding box. + /// The zoom to fit distance + public float GetZoomToExtentsShiftDistance(ref BoundingBox boundingBox) + { + return GetZoomToExtentsShiftDistance(boundingBox.GetCorners()); + } + + /// + /// Get the vector shift which when added to camera position will do the effect of zoom to extents (zoom to fit) operation, + /// so all the passed points will fit in the current view. + /// + /// The points. + /// The zoom to fit vector + public Vector3 GetZoomToExtentsShiftVector(Vector3[] points) + { + return GetZoomToExtentsShiftDistance(points) * pNear.Normal; + } + /// + /// Get the vector shift which when added to camera position will do the effect of zoom to extents (zoom to fit) operation, + /// so all the passed points will fit in the current view. + /// + /// The bounding box. + /// The zoom to fit vector + public Vector3 GetZoomToExtentsShiftVector(ref BoundingBox boundingBox) + { + return GetZoomToExtentsShiftDistance(boundingBox.GetCorners()) * pNear.Normal; + } + + /// + /// Indicate whether the current BoundingFrustrum is Orthographic. + /// + /// + /// true if the current BoundingFrustrum is Orthographic; otherwise, false. + /// + public bool IsOrthographic + { + get + { + return (pLeft.Normal == -pRight.Normal) && (pTop.Normal == -pBottom.Normal); + } + } + } +} diff --git a/Source/SharpDX/BoundingSphere.cs b/Source/SharpDX.Mathematics/BoundingSphere.cs similarity index 96% rename from Source/SharpDX/BoundingSphere.cs rename to Source/SharpDX.Mathematics/BoundingSphere.cs index a5df57f5c..753083a57 100644 --- a/Source/SharpDX/BoundingSphere.cs +++ b/Source/SharpDX.Mathematics/BoundingSphere.cs @@ -1,519 +1,510 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ----------------------------------------------------------------------------- -// Original code from SlimMath project. http://code.google.com/p/slimmath/ -// Greetings to SlimDX Group. Original code published with the following license: -// ----------------------------------------------------------------------------- -/* -* Copyright (c) 2007-2011 SlimDX Group -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using System.ComponentModel; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Represents a bounding sphere in three dimensional space. - /// - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct BoundingSphere : IEquatable, IFormattable, IDataSerializable - { - /// - /// The center of the sphere in three dimensional space. - /// - public Vector3 Center; - - /// - /// The radius of the sphere. - /// - public float Radius; - - /// - /// Initializes a new instance of the struct. - /// - /// The center of the sphere in three dimensional space. - /// The radius of the sphere. - public BoundingSphere(Vector3 center, float radius) - { - this.Center = center; - this.Radius = radius; - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The ray to test. - /// Whether the two objects intersected. - public bool Intersects(ref Ray ray) - { - float distance; - return Collision.RayIntersectsSphere(ref ray, ref this, out distance); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The ray to test. - /// When the method completes, contains the distance of the intersection, - /// or 0 if there was no intersection. - /// Whether the two objects intersected. - public bool Intersects(ref Ray ray, out float distance) - { - return Collision.RayIntersectsSphere(ref ray, ref this, out distance); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The ray to test. - /// When the method completes, contains the point of intersection, - /// or if there was no intersection. - /// Whether the two objects intersected. - public bool Intersects(ref Ray ray, out Vector3 point) - { - return Collision.RayIntersectsSphere(ref ray, ref this, out point); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The plane to test. - /// Whether the two objects intersected. - public PlaneIntersectionType Intersects(ref Plane plane) - { - return Collision.PlaneIntersectsSphere(ref plane, ref this); - } - - /// - /// Determines if there is an intersection between the current object and a triangle. - /// - /// The first vertex of the triangle to test. - /// The second vertex of the triangle to test. - /// The third vertex of the triangle to test. - /// Whether the two objects intersected. - public bool Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) - { - return Collision.SphereIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The box to test. - /// Whether the two objects intersected. - public bool Intersects(ref BoundingBox box) - { - return Collision.BoxIntersectsSphere(ref box, ref this); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The box to test. - /// Whether the two objects intersected. - public bool Intersects(BoundingBox box) - { - return Intersects(ref box); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The sphere to test. - /// Whether the two objects intersected. - public bool Intersects(ref BoundingSphere sphere) - { - return Collision.SphereIntersectsSphere(ref this, ref sphere); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The sphere to test. - /// Whether the two objects intersected. - public bool Intersects(BoundingSphere sphere) - { - return Intersects(ref sphere); - } - - /// - /// Determines whether the current objects contains a point. - /// - /// The point to test. - /// The type of containment the two objects have. - public ContainmentType Contains(ref Vector3 point) - { - return Collision.SphereContainsPoint(ref this, ref point); - } - - /// - /// Determines whether the current objects contains a triangle. - /// - /// The first vertex of the triangle to test. - /// The second vertex of the triangle to test. - /// The third vertex of the triangle to test. - /// The type of containment the two objects have. - public ContainmentType Contains(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) - { - return Collision.SphereContainsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3); - } - - /// - /// Determines whether the current objects contains a . - /// - /// The box to test. - /// The type of containment the two objects have. - public ContainmentType Contains(ref BoundingBox box) - { - return Collision.SphereContainsBox(ref this, ref box); - } - - /// - /// Determines whether the current objects contains a . - /// - /// The sphere to test. - /// The type of containment the two objects have. - public ContainmentType Contains(ref BoundingSphere sphere) - { - return Collision.SphereContainsSphere(ref this, ref sphere); - } - - /// - /// Constructs a that fully contains the given points. - /// - /// The points that will be contained by the sphere. - /// The start index from points array to start compute the bounding sphere. - /// The count of points to process to compute the bounding sphere. - /// When the method completes, contains the newly constructed bounding sphere. - /// points - /// - /// start - /// or - /// count - /// - public static void FromPoints(Vector3[] points, int start, int count, out BoundingSphere result) - { - if (points == null) - { - throw new ArgumentNullException("points"); - } - - // Check that start is in the correct range - if (start < 0 || start >= points.Length) - { - throw new ArgumentOutOfRangeException("start", start, string.Format("Must be in the range [0, {0}]", points.Length - 1)); - } - - // Check that count is in the correct range - if (count < 0 || (start + count) > points.Length) - { - throw new ArgumentOutOfRangeException("count", count, string.Format("Must be in the range <= {0}", points.Length)); - } - - var upperEnd = start + count; - - //Find the center of all points. - Vector3 center = Vector3.Zero; - for (int i = start; i < upperEnd; ++i) - { - Vector3.Add(ref points[i], ref center, out center); - } - - //This is the center of our sphere. - center /= (float)count; - - //Find the radius of the sphere - float radius = 0f; - for (int i = start; i < upperEnd; ++i) - { - //We are doing a relative distance comparison to find the maximum distance - //from the center of our sphere. - float distance; - Vector3.DistanceSquared(ref center, ref points[i], out distance); - - if (distance > radius) - radius = distance; - } - - //Find the real distance from the DistanceSquared. - radius = (float)Math.Sqrt(radius); - - //Construct the sphere. - result.Center = center; - result.Radius = radius; - } - - /// - /// Constructs a that fully contains the given points. - /// - /// The points that will be contained by the sphere. - /// When the method completes, contains the newly constructed bounding sphere. - public static void FromPoints(Vector3[] points, out BoundingSphere result) - { - if (points == null) - { - throw new ArgumentNullException("points"); - } - - FromPoints(points, 0, points.Length, out result); - } - - /// - /// Constructs a that fully contains the given points. - /// - /// The points that will be contained by the sphere. - /// The newly constructed bounding sphere. - public static BoundingSphere FromPoints(Vector3[] points) - { - BoundingSphere result; - FromPoints(points, out result); - return result; - } - - /// - /// Constructs a from a given box. - /// - /// The box that will designate the extents of the sphere. - /// When the method completes, the newly constructed bounding sphere. - public static void FromBox(ref BoundingBox box, out BoundingSphere result) - { - Vector3.Lerp(ref box.Minimum, ref box.Maximum, 0.5f, out result.Center); - - float x = box.Minimum.X - box.Maximum.X; - float y = box.Minimum.Y - box.Maximum.Y; - float z = box.Minimum.Z - box.Maximum.Z; - - float distance = (float)(Math.Sqrt((x * x) + (y * y) + (z * z))); - result.Radius = distance * 0.5f; - } - - /// - /// Constructs a from a given box. - /// - /// The box that will designate the extents of the sphere. - /// The newly constructed bounding sphere. - public static BoundingSphere FromBox(BoundingBox box) - { - BoundingSphere result; - FromBox(ref box, out result); - return result; - } - - /// - /// Constructs a that is the as large as the total combined area of the two specified spheres. - /// - /// The first sphere to merge. - /// The second sphere to merge. - /// When the method completes, contains the newly constructed bounding sphere. - public static void Merge(ref BoundingSphere value1, ref BoundingSphere value2, out BoundingSphere result) - { - Vector3 difference = value2.Center - value1.Center; - - float length = difference.Length(); - float radius = value1.Radius; - float radius2 = value2.Radius; - - if (radius + radius2 >= length) - { - if (radius - radius2 >= length) - { - result = value1; - return; - } - - if (radius2 - radius >= length) - { - result = value2; - return; - } - } - - Vector3 vector = difference * (1.0f / length); - float min = Math.Min(-radius, length - radius2); - float max = (Math.Max(radius, length + radius2) - min) * 0.5f; - - result.Center = value1.Center + vector * (max + min); - result.Radius = max; - } - - /// - /// Constructs a that is the as large as the total combined area of the two specified spheres. - /// - /// The first sphere to merge. - /// The second sphere to merge. - /// The newly constructed bounding sphere. - public static BoundingSphere Merge(BoundingSphere value1, BoundingSphere value2) - { - BoundingSphere result; - Merge(ref value1, ref value2, out result); - return result; - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has the same value as ; otherwise, false. - public static bool operator ==(BoundingSphere left, BoundingSphere right) - { - return left.Equals(right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has a different value than ; otherwise, false. - public static bool operator !=(BoundingSphere left, BoundingSphere right) - { - return !left.Equals(right); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return string.Format(CultureInfo.CurrentCulture, "Center:{0} Radius:{1}", Center.ToString(), Radius.ToString()); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// - /// A that represents this instance. - /// - public string ToString(string format) - { - if (format == null) - return ToString(); - - return string.Format(CultureInfo.CurrentCulture, "Center:{0} Radius:{1}", Center.ToString(format, CultureInfo.CurrentCulture), - Radius.ToString(format, CultureInfo.CurrentCulture)); - } - - /// - /// Returns a that represents this instance. - /// - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(IFormatProvider formatProvider) - { - return string.Format(formatProvider, "Center:{0} Radius:{1}", Center.ToString(), Radius.ToString()); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - if (format == null) - return ToString(formatProvider); - - return string.Format(formatProvider, "Center:{0} Radius:{1}", Center.ToString(format, formatProvider), - Radius.ToString(format, formatProvider)); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - return (Center.GetHashCode() * 397) ^ Radius.GetHashCode(); - } - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(BoundingSphere value) - { - return Center == value.Center && Radius == value.Radius; - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object value) - { - if (value == null) - return false; - - if (!ReferenceEquals(value.GetType(), typeof(BoundingSphere))) - return false; - - return Equals((BoundingSphere)value); - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - serializer.Serialize(ref Center); - serializer.Serialize(ref Radius); - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from SlimMath project. http://code.google.com/p/slimmath/ +// Greetings to SlimDX Group. Original code published with the following license: +// ----------------------------------------------------------------------------- +/* +* Copyright (c) 2007-2011 SlimDX Group +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Represents a bounding sphere in three dimensional space. + /// + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct BoundingSphere : IEquatable, IFormattable + { + /// + /// The center of the sphere in three dimensional space. + /// + public Vector3 Center; + + /// + /// The radius of the sphere. + /// + public float Radius; + + /// + /// Initializes a new instance of the struct. + /// + /// The center of the sphere in three dimensional space. + /// The radius of the sphere. + public BoundingSphere(Vector3 center, float radius) + { + this.Center = center; + this.Radius = radius; + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The ray to test. + /// Whether the two objects intersected. + public bool Intersects(ref Ray ray) + { + float distance; + return Collision.RayIntersectsSphere(ref ray, ref this, out distance); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The ray to test. + /// When the method completes, contains the distance of the intersection, + /// or 0 if there was no intersection. + /// Whether the two objects intersected. + public bool Intersects(ref Ray ray, out float distance) + { + return Collision.RayIntersectsSphere(ref ray, ref this, out distance); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The ray to test. + /// When the method completes, contains the point of intersection, + /// or if there was no intersection. + /// Whether the two objects intersected. + public bool Intersects(ref Ray ray, out Vector3 point) + { + return Collision.RayIntersectsSphere(ref ray, ref this, out point); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The plane to test. + /// Whether the two objects intersected. + public PlaneIntersectionType Intersects(ref Plane plane) + { + return Collision.PlaneIntersectsSphere(ref plane, ref this); + } + + /// + /// Determines if there is an intersection between the current object and a triangle. + /// + /// The first vertex of the triangle to test. + /// The second vertex of the triangle to test. + /// The third vertex of the triangle to test. + /// Whether the two objects intersected. + public bool Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) + { + return Collision.SphereIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The box to test. + /// Whether the two objects intersected. + public bool Intersects(ref BoundingBox box) + { + return Collision.BoxIntersectsSphere(ref box, ref this); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The box to test. + /// Whether the two objects intersected. + public bool Intersects(BoundingBox box) + { + return Intersects(ref box); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The sphere to test. + /// Whether the two objects intersected. + public bool Intersects(ref BoundingSphere sphere) + { + return Collision.SphereIntersectsSphere(ref this, ref sphere); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The sphere to test. + /// Whether the two objects intersected. + public bool Intersects(BoundingSphere sphere) + { + return Intersects(ref sphere); + } + + /// + /// Determines whether the current objects contains a point. + /// + /// The point to test. + /// The type of containment the two objects have. + public ContainmentType Contains(ref Vector3 point) + { + return Collision.SphereContainsPoint(ref this, ref point); + } + + /// + /// Determines whether the current objects contains a triangle. + /// + /// The first vertex of the triangle to test. + /// The second vertex of the triangle to test. + /// The third vertex of the triangle to test. + /// The type of containment the two objects have. + public ContainmentType Contains(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) + { + return Collision.SphereContainsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3); + } + + /// + /// Determines whether the current objects contains a . + /// + /// The box to test. + /// The type of containment the two objects have. + public ContainmentType Contains(ref BoundingBox box) + { + return Collision.SphereContainsBox(ref this, ref box); + } + + /// + /// Determines whether the current objects contains a . + /// + /// The sphere to test. + /// The type of containment the two objects have. + public ContainmentType Contains(ref BoundingSphere sphere) + { + return Collision.SphereContainsSphere(ref this, ref sphere); + } + + /// + /// Constructs a that fully contains the given points. + /// + /// The points that will be contained by the sphere. + /// The start index from points array to start compute the bounding sphere. + /// The count of points to process to compute the bounding sphere. + /// When the method completes, contains the newly constructed bounding sphere. + /// points + /// + /// start + /// or + /// count + /// + public static void FromPoints(Vector3[] points, int start, int count, out BoundingSphere result) + { + if (points == null) + { + throw new ArgumentNullException("points"); + } + + // Check that start is in the correct range + if (start < 0 || start >= points.Length) + { + throw new ArgumentOutOfRangeException("start", start, string.Format("Must be in the range [0, {0}]", points.Length - 1)); + } + + // Check that count is in the correct range + if (count < 0 || (start + count) > points.Length) + { + throw new ArgumentOutOfRangeException("count", count, string.Format("Must be in the range <= {0}", points.Length)); + } + + var upperEnd = start + count; + + //Find the center of all points. + Vector3 center = Vector3.Zero; + for (int i = start; i < upperEnd; ++i) + { + Vector3.Add(ref points[i], ref center, out center); + } + + //This is the center of our sphere. + center /= (float)count; + + //Find the radius of the sphere + float radius = 0f; + for (int i = start; i < upperEnd; ++i) + { + //We are doing a relative distance comparison to find the maximum distance + //from the center of our sphere. + float distance; + Vector3.DistanceSquared(ref center, ref points[i], out distance); + + if (distance > radius) + radius = distance; + } + + //Find the real distance from the DistanceSquared. + radius = (float)Math.Sqrt(radius); + + //Construct the sphere. + result.Center = center; + result.Radius = radius; + } + + /// + /// Constructs a that fully contains the given points. + /// + /// The points that will be contained by the sphere. + /// When the method completes, contains the newly constructed bounding sphere. + public static void FromPoints(Vector3[] points, out BoundingSphere result) + { + if (points == null) + { + throw new ArgumentNullException("points"); + } + + FromPoints(points, 0, points.Length, out result); + } + + /// + /// Constructs a that fully contains the given points. + /// + /// The points that will be contained by the sphere. + /// The newly constructed bounding sphere. + public static BoundingSphere FromPoints(Vector3[] points) + { + BoundingSphere result; + FromPoints(points, out result); + return result; + } + + /// + /// Constructs a from a given box. + /// + /// The box that will designate the extents of the sphere. + /// When the method completes, the newly constructed bounding sphere. + public static void FromBox(ref BoundingBox box, out BoundingSphere result) + { + Vector3.Lerp(ref box.Minimum, ref box.Maximum, 0.5f, out result.Center); + + float x = box.Minimum.X - box.Maximum.X; + float y = box.Minimum.Y - box.Maximum.Y; + float z = box.Minimum.Z - box.Maximum.Z; + + float distance = (float)(Math.Sqrt((x * x) + (y * y) + (z * z))); + result.Radius = distance * 0.5f; + } + + /// + /// Constructs a from a given box. + /// + /// The box that will designate the extents of the sphere. + /// The newly constructed bounding sphere. + public static BoundingSphere FromBox(BoundingBox box) + { + BoundingSphere result; + FromBox(ref box, out result); + return result; + } + + /// + /// Constructs a that is the as large as the total combined area of the two specified spheres. + /// + /// The first sphere to merge. + /// The second sphere to merge. + /// When the method completes, contains the newly constructed bounding sphere. + public static void Merge(ref BoundingSphere value1, ref BoundingSphere value2, out BoundingSphere result) + { + Vector3 difference = value2.Center - value1.Center; + + float length = difference.Length(); + float radius = value1.Radius; + float radius2 = value2.Radius; + + if (radius + radius2 >= length) + { + if (radius - radius2 >= length) + { + result = value1; + return; + } + + if (radius2 - radius >= length) + { + result = value2; + return; + } + } + + Vector3 vector = difference * (1.0f / length); + float min = Math.Min(-radius, length - radius2); + float max = (Math.Max(radius, length + radius2) - min) * 0.5f; + + result.Center = value1.Center + vector * (max + min); + result.Radius = max; + } + + /// + /// Constructs a that is the as large as the total combined area of the two specified spheres. + /// + /// The first sphere to merge. + /// The second sphere to merge. + /// The newly constructed bounding sphere. + public static BoundingSphere Merge(BoundingSphere value1, BoundingSphere value2) + { + BoundingSphere result; + Merge(ref value1, ref value2, out result); + return result; + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has the same value as ; otherwise, false. + public static bool operator ==(BoundingSphere left, BoundingSphere right) + { + return left.Equals(right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has a different value than ; otherwise, false. + public static bool operator !=(BoundingSphere left, BoundingSphere right) + { + return !left.Equals(right); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return string.Format(CultureInfo.CurrentCulture, "Center:{0} Radius:{1}", Center.ToString(), Radius.ToString()); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// + /// A that represents this instance. + /// + public string ToString(string format) + { + if (format == null) + return ToString(); + + return string.Format(CultureInfo.CurrentCulture, "Center:{0} Radius:{1}", Center.ToString(format, CultureInfo.CurrentCulture), + Radius.ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format(formatProvider, "Center:{0} Radius:{1}", Center.ToString(), Radius.ToString()); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(string format, IFormatProvider formatProvider) + { + if (format == null) + return ToString(formatProvider); + + return string.Format(formatProvider, "Center:{0} Radius:{1}", Center.ToString(format, formatProvider), + Radius.ToString(format, formatProvider)); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + unchecked + { + return (Center.GetHashCode() * 397) ^ Radius.GetHashCode(); + } + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(BoundingSphere value) + { + return Center == value.Center && Radius == value.Radius; + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object value) + { + if (value == null) + return false; + + if (!ReferenceEquals(value.GetType(), typeof(BoundingSphere))) + return false; + + return Equals((BoundingSphere)value); + } + } +} diff --git a/Source/SharpDX/Collision.cs b/Source/SharpDX.Mathematics/Collision.cs similarity index 97% rename from Source/SharpDX/Collision.cs rename to Source/SharpDX.Mathematics/Collision.cs index e8d05e59c..6fdaf43b3 100644 --- a/Source/SharpDX/Collision.cs +++ b/Source/SharpDX.Mathematics/Collision.cs @@ -1,1386 +1,1386 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ----------------------------------------------------------------------------- -// Original code from SlimMath project. http://code.google.com/p/slimmath/ -// Greetings to SlimDX Group. Original code published with the following license: -// ----------------------------------------------------------------------------- -/* -* Copyright (c) 2007-2011 SlimDX Group -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using System.ComponentModel; - -namespace SharpDX -{ - /* - * This class is organized so that the least complex objects come first so that the least - * complex objects will have the most methods in most cases. Note that not all shapes exist - * at this time and not all shapes have a corresponding struct. Only the objects that have - * a corresponding struct should come first in naming and in parameter order. The order of - * complexity is as follows: - * - * 1. Point - * 2. Ray - * 3. Segment - * 4. Plane - * 5. Triangle - * 6. Polygon - * 7. Box - * 8. Sphere - * 9. Ellipsoid - * 10. Cylinder - * 11. Cone - * 12. Capsule - * 13. Torus - * 14. Polyhedron - * 15. Frustum - */ - - /// - /// Contains static methods to help in determining intersections, containment, etc. - /// - public static class Collision - { - /// - /// Determines the closest point between a point and a triangle. - /// - /// The point to test. - /// The first vertex to test. - /// The second vertex to test. - /// The third vertex to test. - /// When the method completes, contains the closest point between the two objects. - public static void ClosestPointPointTriangle(ref Vector3 point, ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3, out Vector3 result) - { - //Source: Real-Time Collision Detection by Christer Ericson - //Reference: Page 136 - - //Check if P in vertex region outside A - Vector3 ab = vertex2 - vertex1; - Vector3 ac = vertex3 - vertex1; - Vector3 ap = point - vertex1; - - float d1 = Vector3.Dot(ab, ap); - float d2 = Vector3.Dot(ac, ap); - if (d1 <= 0.0f && d2 <= 0.0f) - result = vertex1; //Barycentric coordinates (1,0,0) - - //Check if P in vertex region outside B - Vector3 bp = point - vertex2; - float d3 = Vector3.Dot(ab, bp); - float d4 = Vector3.Dot(ac, bp); - if (d3 >= 0.0f && d4 <= d3) - result = vertex2; // Barycentric coordinates (0,1,0) - - //Check if P in edge region of AB, if so return projection of P onto AB - float vc = d1 * d4 - d3 * d2; - if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) - { - float v = d1 / (d1 - d3); - result = vertex1 + v * ab; //Barycentric coordinates (1-v,v,0) - } - - //Check if P in vertex region outside C - Vector3 cp = point - vertex3; - float d5 = Vector3.Dot(ab, cp); - float d6 = Vector3.Dot(ac, cp); - if (d6 >= 0.0f && d5 <= d6) - result = vertex3; //Barycentric coordinates (0,0,1) - - //Check if P in edge region of AC, if so return projection of P onto AC - float vb = d5 * d2 - d1 * d6; - if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) - { - float w = d2 / (d2 - d6); - result = vertex1 + w * ac; //Barycentric coordinates (1-w,0,w) - } - - //Check if P in edge region of BC, if so return projection of P onto BC - float va = d3 * d6 - d5 * d4; - if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) - { - float w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); - result = vertex2 + w * (vertex3 - vertex2); //Barycentric coordinates (0,1-w,w) - } - - //P inside face region. Compute Q through its Barycentric coordinates (u,v,w) - float denom = 1.0f / (va + vb + vc); - float v2 = vb * denom; - float w2 = vc * denom; - result = vertex1 + ab * v2 + ac * w2; //= u*vertex1 + v*vertex2 + w*vertex3, u = va * denom = 1.0f - v - w - } - - /// - /// Determines the closest point between a and a point. - /// - /// The plane to test. - /// The point to test. - /// When the method completes, contains the closest point between the two objects. - public static void ClosestPointPlanePoint(ref Plane plane, ref Vector3 point, out Vector3 result) - { - //Source: Real-Time Collision Detection by Christer Ericson - //Reference: Page 126 - - float dot; - Vector3.Dot(ref plane.Normal, ref point, out dot); - float t = dot - plane.D; - - result = point - (t * plane.Normal); - } - - /// - /// Determines the closest point between a and a point. - /// - /// The box to test. - /// The point to test. - /// When the method completes, contains the closest point between the two objects. - public static void ClosestPointBoxPoint(ref BoundingBox box, ref Vector3 point, out Vector3 result) - { - //Source: Real-Time Collision Detection by Christer Ericson - //Reference: Page 130 - - Vector3 temp; - Vector3.Max(ref point, ref box.Minimum, out temp); - Vector3.Min(ref temp, ref box.Maximum, out result); - } - - /// - /// Determines the closest point between a and a point. - /// - /// - /// The point to test. - /// When the method completes, contains the closest point between the two objects; - /// or, if the point is directly in the center of the sphere, contains . - public static void ClosestPointSpherePoint(ref BoundingSphere sphere, ref Vector3 point, out Vector3 result) - { - //Source: Jorgy343 - //Reference: None - - //Get the unit direction from the sphere's center to the point. - Vector3.Subtract(ref point, ref sphere.Center, out result); - result.Normalize(); - - //Multiply the unit direction by the sphere's radius to get a vector - //the length of the sphere. - result *= sphere.Radius; - - //Add the sphere's center to the direction to get a point on the sphere. - result += sphere.Center; - } - - /// - /// Determines the closest point between a and a . - /// - /// The first sphere to test. - /// The second sphere to test. - /// When the method completes, contains the closest point between the two objects; - /// or, if the point is directly in the center of the sphere, contains . - /// - /// If the two spheres are overlapping, but not directly on top of each other, the closest point - /// is the 'closest' point of intersection. This can also be considered is the deepest point of - /// intersection. - /// - public static void ClosestPointSphereSphere(ref BoundingSphere sphere1, ref BoundingSphere sphere2, out Vector3 result) - { - //Source: Jorgy343 - //Reference: None - - //Get the unit direction from the first sphere's center to the second sphere's center. - Vector3.Subtract(ref sphere2.Center, ref sphere1.Center, out result); - result.Normalize(); - - //Multiply the unit direction by the first sphere's radius to get a vector - //the length of the first sphere. - result *= sphere1.Radius; - - //Add the first sphere's center to the direction to get a point on the first sphere. - result += sphere1.Center; - } - - /// - /// Determines the distance between a and a point. - /// - /// The plane to test. - /// The point to test. - /// The distance between the two objects. - public static float DistancePlanePoint(ref Plane plane, ref Vector3 point) - { - //Source: Real-Time Collision Detection by Christer Ericson - //Reference: Page 127 - - float dot; - Vector3.Dot(ref plane.Normal, ref point, out dot); - return dot - plane.D; - } - - /// - /// Determines the distance between a and a point. - /// - /// The box to test. - /// The point to test. - /// The distance between the two objects. - public static float DistanceBoxPoint(ref BoundingBox box, ref Vector3 point) - { - //Source: Real-Time Collision Detection by Christer Ericson - //Reference: Page 131 - - float distance = 0f; - - if (point.X < box.Minimum.X) - distance += (box.Minimum.X - point.X) * (box.Minimum.X - point.X); - if (point.X > box.Maximum.X) - distance += (point.X - box.Maximum.X) * (point.X - box.Maximum.X); - - if (point.Y < box.Minimum.Y) - distance += (box.Minimum.Y - point.Y) * (box.Minimum.Y - point.Y); - if (point.Y > box.Maximum.Y) - distance += (point.Y - box.Maximum.Y) * (point.Y - box.Maximum.Y); - - if (point.Z < box.Minimum.Z) - distance += (box.Minimum.Z - point.Z) * (box.Minimum.Z - point.Z); - if (point.Z > box.Maximum.Z) - distance += (point.Z - box.Maximum.Z) * (point.Z - box.Maximum.Z); - - return (float)Math.Sqrt(distance); - } - - /// - /// Determines the distance between a and a . - /// - /// The first box to test. - /// The second box to test. - /// The distance between the two objects. - public static float DistanceBoxBox(ref BoundingBox box1, ref BoundingBox box2) - { - //Source: - //Reference: - - float distance = 0f; - - //Distance for X. - if (box1.Minimum.X > box2.Maximum.X) - { - float delta = box2.Maximum.X - box1.Minimum.X; - distance += delta * delta; - } - else if (box2.Minimum.X > box1.Maximum.X) - { - float delta = box1.Maximum.X - box2.Minimum.X; - distance += delta * delta; - } - - //Distance for Y. - if (box1.Minimum.Y > box2.Maximum.Y) - { - float delta = box2.Maximum.Y - box1.Minimum.Y; - distance += delta * delta; - } - else if (box2.Minimum.Y > box1.Maximum.Y) - { - float delta = box1.Maximum.Y - box2.Minimum.Y; - distance += delta * delta; - } - - //Distance for Z. - if (box1.Minimum.Z > box2.Maximum.Z) - { - float delta = box2.Maximum.Z - box1.Minimum.Z; - distance += delta * delta; - } - else if (box2.Minimum.Z > box1.Maximum.Z) - { - float delta = box1.Maximum.Z - box2.Minimum.Z; - distance += delta * delta; - } - - return (float)Math.Sqrt(distance); - } - - /// - /// Determines the distance between a and a point. - /// - /// The sphere to test. - /// The point to test. - /// The distance between the two objects. - public static float DistanceSpherePoint(ref BoundingSphere sphere, ref Vector3 point) - { - //Source: Jorgy343 - //Reference: None - - float distance; - Vector3.Distance(ref sphere.Center, ref point, out distance); - distance -= sphere.Radius; - - return Math.Max(distance, 0f); - } - - /// - /// Determines the distance between a and a . - /// - /// The first sphere to test. - /// The second sphere to test. - /// The distance between the two objects. - public static float DistanceSphereSphere(ref BoundingSphere sphere1, ref BoundingSphere sphere2) - { - //Source: Jorgy343 - //Reference: None - - float distance; - Vector3.Distance(ref sphere1.Center, ref sphere2.Center, out distance); - distance -= sphere1.Radius + sphere2.Radius; - - return Math.Max(distance, 0f); - } - - /// - /// Determines whether there is an intersection between a and a point. - /// - /// The ray to test. - /// The point to test. - /// Whether the two objects intersect. - public static bool RayIntersectsPoint(ref Ray ray, ref Vector3 point) - { - //Source: RayIntersectsSphere - //Reference: None - - Vector3 m; - Vector3.Subtract(ref ray.Position, ref point, out m); - - //Same thing as RayIntersectsSphere except that the radius of the sphere (point) - //is the epsilon for zero. - float b = Vector3.Dot(m, ray.Direction); - float c = Vector3.Dot(m, m) - MathUtil.ZeroTolerance; - - if (c > 0f && b > 0f) - return false; - - float discriminant = b * b - c; - - if (discriminant < 0f) - return false; - - return true; - } - - /// - /// Determines whether there is an intersection between a and a . - /// - /// The first ray to test. - /// The second ray to test. - /// When the method completes, contains the point of intersection, - /// or if there was no intersection. - /// Whether the two objects intersect. - /// - /// This method performs a ray vs ray intersection test based on the following formula - /// from Goldman. - /// s = det([o_2 - o_1, d_2, d_1 x d_2]) / ||d_1 x d_2||^2 - /// t = det([o_2 - o_1, d_1, d_1 x d_2]) / ||d_1 x d_2||^2 - /// Where o_1 is the position of the first ray, o_2 is the position of the second ray, - /// d_1 is the normalized direction of the first ray, d_2 is the normalized direction - /// of the second ray, det denotes the determinant of a matrix, x denotes the cross - /// product, [ ] denotes a matrix, and || || denotes the length or magnitude of a vector. - /// - public static bool RayIntersectsRay(ref Ray ray1, ref Ray ray2, out Vector3 point) - { - //Source: Real-Time Rendering, Third Edition - //Reference: Page 780 - - Vector3 cross; - - Vector3.Cross(ref ray1.Direction, ref ray2.Direction, out cross); - float denominator = cross.Length(); - - //Lines are parallel. - if (MathUtil.IsZero(denominator)) - { - //Lines are parallel and on top of each other. - if (MathUtil.NearEqual(ray2.Position.X, ray1.Position.X) && - MathUtil.NearEqual(ray2.Position.Y, ray1.Position.Y) && - MathUtil.NearEqual(ray2.Position.Z, ray1.Position.Z)) - { - point = Vector3.Zero; - return true; - } - } - - denominator = denominator * denominator; - - //3x3 matrix for the first ray. - float m11 = ray2.Position.X - ray1.Position.X; - float m12 = ray2.Position.Y - ray1.Position.Y; - float m13 = ray2.Position.Z - ray1.Position.Z; - float m21 = ray2.Direction.X; - float m22 = ray2.Direction.Y; - float m23 = ray2.Direction.Z; - float m31 = cross.X; - float m32 = cross.Y; - float m33 = cross.Z; - - //Determinant of first matrix. - float dets = - m11 * m22 * m33 + - m12 * m23 * m31 + - m13 * m21 * m32 - - m11 * m23 * m32 - - m12 * m21 * m33 - - m13 * m22 * m31; - - //3x3 matrix for the second ray. - m21 = ray1.Direction.X; - m22 = ray1.Direction.Y; - m23 = ray1.Direction.Z; - - //Determinant of the second matrix. - float dett = - m11 * m22 * m33 + - m12 * m23 * m31 + - m13 * m21 * m32 - - m11 * m23 * m32 - - m12 * m21 * m33 - - m13 * m22 * m31; - - //t values of the point of intersection. - float s = dets / denominator; - float t = dett / denominator; - - //The points of intersection. - Vector3 point1 = ray1.Position + (s * ray1.Direction); - Vector3 point2 = ray2.Position + (t * ray2.Direction); - - //If the points are not equal, no intersection has occurred. - if (!MathUtil.NearEqual(point2.X, point1.X) || - !MathUtil.NearEqual(point2.Y, point1.Y) || - !MathUtil.NearEqual(point2.Z, point1.Z)) - { - point = Vector3.Zero; - return false; - } - - point = point1; - return true; - } - - /// - /// Determines whether there is an intersection between a and a . - /// - /// The ray to test. - /// The plane to test. - /// When the method completes, contains the distance of the intersection, - /// or 0 if there was no intersection. - /// Whether the two objects intersect. - public static bool RayIntersectsPlane(ref Ray ray, ref Plane plane, out float distance) - { - //Source: Real-Time Collision Detection by Christer Ericson - //Reference: Page 175 - - float direction; - Vector3.Dot(ref plane.Normal, ref ray.Direction, out direction); - - if (MathUtil.IsZero(direction)) - { - distance = 0f; - return false; - } - - float position; - Vector3.Dot(ref plane.Normal, ref ray.Position, out position); - distance = (-plane.D - position) / direction; - - if (distance < 0f) - { - if (MathUtil.IsZero(distance)) - { - distance = 0; - return false; - } - - distance = 0f; - } - - return true; - } - - /// - /// Determines whether there is an intersection between a and a . - /// - /// The ray to test. - /// The plane to test - /// When the method completes, contains the point of intersection, - /// or if there was no intersection. - /// Whether the two objects intersected. - public static bool RayIntersectsPlane(ref Ray ray, ref Plane plane, out Vector3 point) - { - //Source: Real-Time Collision Detection by Christer Ericson - //Reference: Page 175 - - float distance; - if (!RayIntersectsPlane(ref ray, ref plane, out distance)) - { - point = Vector3.Zero; - return false; - } - - point = ray.Position + (ray.Direction * distance); - return true; - } - - /// - /// Determines whether there is an intersection between a and a triangle. - /// - /// The ray to test. - /// The first vertex of the triangle to test. - /// The second vertex of the triangle to test. - /// The third vertex of the triangle to test. - /// When the method completes, contains the distance of the intersection, - /// or 0 if there was no intersection. - /// Whether the two objects intersected. - /// - /// This method tests if the ray intersects either the front or back of the triangle. - /// If the ray is parallel to the triangle's plane, no intersection is assumed to have - /// happened. If the intersection of the ray and the triangle is behind the origin of - /// the ray, no intersection is assumed to have happened. In both cases of assumptions, - /// this method returns false. - /// - public static bool RayIntersectsTriangle(ref Ray ray, ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3, out float distance) - { - //Source: Fast Minimum Storage Ray / Triangle Intersection - //Reference: http://www.cs.virginia.edu/~gfx/Courses/2003/ImageSynthesis/papers/Acceleration/Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf - - //Compute vectors along two edges of the triangle. - Vector3 edge1, edge2; - - //Edge 1 - edge1.X = vertex2.X - vertex1.X; - edge1.Y = vertex2.Y - vertex1.Y; - edge1.Z = vertex2.Z - vertex1.Z; - - //Edge2 - edge2.X = vertex3.X - vertex1.X; - edge2.Y = vertex3.Y - vertex1.Y; - edge2.Z = vertex3.Z - vertex1.Z; - - //Cross product of ray direction and edge2 - first part of determinant. - Vector3 directioncrossedge2; - directioncrossedge2.X = (ray.Direction.Y * edge2.Z) - (ray.Direction.Z * edge2.Y); - directioncrossedge2.Y = (ray.Direction.Z * edge2.X) - (ray.Direction.X * edge2.Z); - directioncrossedge2.Z = (ray.Direction.X * edge2.Y) - (ray.Direction.Y * edge2.X); - - //Compute the determinant. - float determinant; - //Dot product of edge1 and the first part of determinant. - determinant = (edge1.X * directioncrossedge2.X) + (edge1.Y * directioncrossedge2.Y) + (edge1.Z * directioncrossedge2.Z); - - //If the ray is parallel to the triangle plane, there is no collision. - //This also means that we are not culling, the ray may hit both the - //back and the front of the triangle. - if (MathUtil.IsZero(determinant)) - { - distance = 0f; - return false; - } - - float inversedeterminant = 1.0f / determinant; - - //Calculate the U parameter of the intersection point. - Vector3 distanceVector; - distanceVector.X = ray.Position.X - vertex1.X; - distanceVector.Y = ray.Position.Y - vertex1.Y; - distanceVector.Z = ray.Position.Z - vertex1.Z; - - float triangleU; - triangleU = (distanceVector.X * directioncrossedge2.X) + (distanceVector.Y * directioncrossedge2.Y) + (distanceVector.Z * directioncrossedge2.Z); - triangleU *= inversedeterminant; - - //Make sure it is inside the triangle. - if (triangleU < 0f || triangleU > 1f) - { - distance = 0f; - return false; - } - - //Calculate the V parameter of the intersection point. - Vector3 distancecrossedge1; - distancecrossedge1.X = (distanceVector.Y * edge1.Z) - (distanceVector.Z * edge1.Y); - distancecrossedge1.Y = (distanceVector.Z * edge1.X) - (distanceVector.X * edge1.Z); - distancecrossedge1.Z = (distanceVector.X * edge1.Y) - (distanceVector.Y * edge1.X); - - float triangleV; - triangleV = ((ray.Direction.X * distancecrossedge1.X) + (ray.Direction.Y * distancecrossedge1.Y)) + (ray.Direction.Z * distancecrossedge1.Z); - triangleV *= inversedeterminant; - - //Make sure it is inside the triangle. - if (triangleV < 0f || triangleU + triangleV > 1f) - { - distance = 0f; - return false; - } - - //Compute the distance along the ray to the triangle. - float raydistance; - raydistance = (edge2.X * distancecrossedge1.X) + (edge2.Y * distancecrossedge1.Y) + (edge2.Z * distancecrossedge1.Z); - raydistance *= inversedeterminant; - - //Is the triangle behind the ray origin? - if (raydistance < 0f) - { - distance = 0f; - return false; - } - - distance = raydistance; - return true; - } - - /// - /// Determines whether there is an intersection between a and a triangle. - /// - /// The ray to test. - /// The first vertex of the triangle to test. - /// The second vertex of the triangle to test. - /// The third vertex of the triangle to test. - /// When the method completes, contains the point of intersection, - /// or if there was no intersection. - /// Whether the two objects intersected. - public static bool RayIntersectsTriangle(ref Ray ray, ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3, out Vector3 point) - { - float distance; - if (!RayIntersectsTriangle(ref ray, ref vertex1, ref vertex2, ref vertex3, out distance)) - { - point = Vector3.Zero; - return false; - } - - point = ray.Position + (ray.Direction * distance); - return true; - } - - /// - /// Determines whether there is an intersection between a and a . - /// - /// The ray to test. - /// The box to test. - /// When the method completes, contains the distance of the intersection, - /// or 0 if there was no intersection. - /// Whether the two objects intersected. - public static bool RayIntersectsBox(ref Ray ray, ref BoundingBox box, out float distance) - { - //Source: Real-Time Collision Detection by Christer Ericson - //Reference: Page 179 - - distance = 0f; - float tmax = float.MaxValue; - - if (MathUtil.IsZero(ray.Direction.X)) - { - if (ray.Position.X < box.Minimum.X || ray.Position.X > box.Maximum.X) - { - distance = 0f; - return false; - } - } - else - { - float inverse = 1.0f / ray.Direction.X; - float t1 = (box.Minimum.X - ray.Position.X) * inverse; - float t2 = (box.Maximum.X - ray.Position.X) * inverse; - - if (t1 > t2) - { - float temp = t1; - t1 = t2; - t2 = temp; - } - - distance = Math.Max(t1, distance); - tmax = Math.Min(t2, tmax); - - if (distance > tmax) - { - distance = 0f; - return false; - } - } - - if (MathUtil.IsZero(ray.Direction.Y)) - { - if (ray.Position.Y < box.Minimum.Y || ray.Position.Y > box.Maximum.Y) - { - distance = 0f; - return false; - } - } - else - { - float inverse = 1.0f / ray.Direction.Y; - float t1 = (box.Minimum.Y - ray.Position.Y) * inverse; - float t2 = (box.Maximum.Y - ray.Position.Y) * inverse; - - if (t1 > t2) - { - float temp = t1; - t1 = t2; - t2 = temp; - } - - distance = Math.Max(t1, distance); - tmax = Math.Min(t2, tmax); - - if (distance > tmax) - { - distance = 0f; - return false; - } - } - - if (MathUtil.IsZero(ray.Direction.Z)) - { - if (ray.Position.Z < box.Minimum.Z || ray.Position.Z > box.Maximum.Z) - { - distance = 0f; - return false; - } - } - else - { - float inverse = 1.0f / ray.Direction.Z; - float t1 = (box.Minimum.Z - ray.Position.Z) * inverse; - float t2 = (box.Maximum.Z - ray.Position.Z) * inverse; - - if (t1 > t2) - { - float temp = t1; - t1 = t2; - t2 = temp; - } - - distance = Math.Max(t1, distance); - tmax = Math.Min(t2, tmax); - - if (distance > tmax) - { - distance = 0f; - return false; - } - } - - return true; - } - - /// - /// Determines whether there is an intersection between a and a . - /// - /// The ray to test. - /// The box to test. - /// When the method completes, contains the point of intersection, - /// or if there was no intersection. - /// Whether the two objects intersected. - public static bool RayIntersectsBox(ref Ray ray, ref BoundingBox box, out Vector3 point) - { - float distance; - if (!RayIntersectsBox(ref ray, ref box, out distance)) - { - point = Vector3.Zero; - return false; - } - - point = ray.Position + (ray.Direction * distance); - return true; - } - - /// - /// Determines whether there is an intersection between a and a . - /// - /// The ray to test. - /// The sphere to test. - /// When the method completes, contains the distance of the intersection, - /// or 0 if there was no intersection. - /// Whether the two objects intersected. - public static bool RayIntersectsSphere(ref Ray ray, ref BoundingSphere sphere, out float distance) - { - //Source: Real-Time Collision Detection by Christer Ericson - //Reference: Page 177 - - Vector3 m; - Vector3.Subtract(ref ray.Position, ref sphere.Center, out m); - - float b = Vector3.Dot(m, ray.Direction); - float c = Vector3.Dot(m, m) - (sphere.Radius * sphere.Radius); - - if (c > 0f && b > 0f) - { - distance = 0f; - return false; - } - - float discriminant = b * b - c; - - if (discriminant < 0f) - { - distance = 0f; - return false; - } - - distance = -b - (float)Math.Sqrt(discriminant); - - if (distance < 0f) - distance = 0f; - - return true; - } - - /// - /// Determines whether there is an intersection between a and a . - /// - /// The ray to test. - /// The sphere to test. - /// When the method completes, contains the point of intersection, - /// or if there was no intersection. - /// Whether the two objects intersected. - public static bool RayIntersectsSphere(ref Ray ray, ref BoundingSphere sphere, out Vector3 point) - { - float distance; - if (!RayIntersectsSphere(ref ray, ref sphere, out distance)) - { - point = Vector3.Zero; - return false; - } - - point = ray.Position + (ray.Direction * distance); - return true; - } - - /// - /// Determines whether there is an intersection between a and a point. - /// - /// The plane to test. - /// The point to test. - /// Whether the two objects intersected. - public static PlaneIntersectionType PlaneIntersectsPoint(ref Plane plane, ref Vector3 point) - { - float distance; - Vector3.Dot(ref plane.Normal, ref point, out distance); - distance += plane.D; - - if (distance > 0f) - return PlaneIntersectionType.Front; - - if (distance < 0f) - return PlaneIntersectionType.Back; - - return PlaneIntersectionType.Intersecting; - } - - /// - /// Determines whether there is an intersection between a and a . - /// - /// The first plane to test. - /// The second plane to test. - /// Whether the two objects intersected. - public static bool PlaneIntersectsPlane(ref Plane plane1, ref Plane plane2) - { - Vector3 direction; - Vector3.Cross(ref plane1.Normal, ref plane2.Normal, out direction); - - //If direction is the zero vector, the planes are parallel and possibly - //coincident. It is not an intersection. The dot product will tell us. - float denominator; - Vector3.Dot(ref direction, ref direction, out denominator); - - if (MathUtil.IsZero(denominator)) - return false; - - return true; - } - - /// - /// Determines whether there is an intersection between a and a . - /// - /// The first plane to test. - /// The second plane to test. - /// When the method completes, contains the line of intersection - /// as a , or a zero ray if there was no intersection. - /// Whether the two objects intersected. - /// - /// Although a ray is set to have an origin, the ray returned by this method is really - /// a line in three dimensions which has no real origin. The ray is considered valid when - /// both the positive direction is used and when the negative direction is used. - /// - public static bool PlaneIntersectsPlane(ref Plane plane1, ref Plane plane2, out Ray line) - { - //Source: Real-Time Collision Detection by Christer Ericson - //Reference: Page 207 - - Vector3 direction; - Vector3.Cross(ref plane1.Normal, ref plane2.Normal, out direction); - - //If direction is the zero vector, the planes are parallel and possibly - //coincident. It is not an intersection. The dot product will tell us. - float denominator; - Vector3.Dot(ref direction, ref direction, out denominator); - - //We assume the planes are normalized, therefore the denominator - //only serves as a parallel and coincident check. Otherwise we need - //to divide the point by the denominator. - if (MathUtil.IsZero(denominator)) - { - line = new Ray(); - return false; - } - - Vector3 point; - Vector3 temp = plane1.D * plane2.Normal - plane2.D * plane1.Normal; - Vector3.Cross(ref temp, ref direction, out point); - - line.Position = point; - line.Direction = direction; - line.Direction.Normalize(); - - return true; - } - - /// - /// Determines whether there is an intersection between a and a triangle. - /// - /// The plane to test. - /// The first vertex of the triangle to test. - /// The second vertex of the triangle to test. - /// The third vertex of the triangle to test. - /// Whether the two objects intersected. - public static PlaneIntersectionType PlaneIntersectsTriangle(ref Plane plane, ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) - { - //Source: Real-Time Collision Detection by Christer Ericson - //Reference: Page 207 - - PlaneIntersectionType test1 = PlaneIntersectsPoint(ref plane, ref vertex1); - PlaneIntersectionType test2 = PlaneIntersectsPoint(ref plane, ref vertex2); - PlaneIntersectionType test3 = PlaneIntersectsPoint(ref plane, ref vertex3); - - if (test1 == PlaneIntersectionType.Front && test2 == PlaneIntersectionType.Front && test3 == PlaneIntersectionType.Front) - return PlaneIntersectionType.Front; - - if (test1 == PlaneIntersectionType.Back && test2 == PlaneIntersectionType.Back && test3 == PlaneIntersectionType.Back) - return PlaneIntersectionType.Back; - - return PlaneIntersectionType.Intersecting; - } - - /// - /// Determines whether there is an intersection between a and a . - /// - /// The plane to test. - /// The box to test. - /// Whether the two objects intersected. - public static PlaneIntersectionType PlaneIntersectsBox(ref Plane plane, ref BoundingBox box) - { - //Source: Real-Time Collision Detection by Christer Ericson - //Reference: Page 161 - - Vector3 min; - Vector3 max; - - max.X = (plane.Normal.X >= 0.0f) ? box.Minimum.X : box.Maximum.X; - max.Y = (plane.Normal.Y >= 0.0f) ? box.Minimum.Y : box.Maximum.Y; - max.Z = (plane.Normal.Z >= 0.0f) ? box.Minimum.Z : box.Maximum.Z; - min.X = (plane.Normal.X >= 0.0f) ? box.Maximum.X : box.Minimum.X; - min.Y = (plane.Normal.Y >= 0.0f) ? box.Maximum.Y : box.Minimum.Y; - min.Z = (plane.Normal.Z >= 0.0f) ? box.Maximum.Z : box.Minimum.Z; - - float distance; - Vector3.Dot(ref plane.Normal, ref max, out distance); - - if (distance + plane.D > 0.0f) - return PlaneIntersectionType.Front; - - distance = Vector3.Dot(plane.Normal, min); - - if (distance + plane.D < 0.0f) - return PlaneIntersectionType.Back; - - return PlaneIntersectionType.Intersecting; - } - - /// - /// Determines whether there is an intersection between a and a . - /// - /// The plane to test. - /// The sphere to test. - /// Whether the two objects intersected. - public static PlaneIntersectionType PlaneIntersectsSphere(ref Plane plane, ref BoundingSphere sphere) - { - //Source: Real-Time Collision Detection by Christer Ericson - //Reference: Page 160 - - float distance; - Vector3.Dot(ref plane.Normal, ref sphere.Center, out distance); - distance += plane.D; - - if (distance > sphere.Radius) - return PlaneIntersectionType.Front; - - if (distance < -sphere.Radius) - return PlaneIntersectionType.Back; - - return PlaneIntersectionType.Intersecting; - } - - /* This implementation is wrong - /// - /// Determines whether there is an intersection between a and a triangle. - /// - /// The box to test. - /// The first vertex of the triangle to test. - /// The second vertex of the triangle to test. - /// The third vertex of the triangle to test. - /// Whether the two objects intersected. - public static bool BoxIntersectsTriangle(ref BoundingBox box, ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) - { - if (BoxContainsPoint(ref box, ref vertex1) == ContainmentType.Contains) - return true; - - if (BoxContainsPoint(ref box, ref vertex2) == ContainmentType.Contains) - return true; - - if (BoxContainsPoint(ref box, ref vertex3) == ContainmentType.Contains) - return true; - - return false; - } - */ - - /// - /// Determines whether there is an intersection between a and a . - /// - /// The first box to test. - /// The second box to test. - /// Whether the two objects intersected. - public static bool BoxIntersectsBox(ref BoundingBox box1, ref BoundingBox box2) - { - if (box1.Minimum.X > box2.Maximum.X || box2.Minimum.X > box1.Maximum.X) - return false; - - if (box1.Minimum.Y > box2.Maximum.Y || box2.Minimum.Y > box1.Maximum.Y) - return false; - - if (box1.Minimum.Z > box2.Maximum.Z || box2.Minimum.Z > box1.Maximum.Z) - return false; - - return true; - } - - /// - /// Determines whether there is an intersection between a and a . - /// - /// The box to test. - /// The sphere to test. - /// Whether the two objects intersected. - public static bool BoxIntersectsSphere(ref BoundingBox box, ref BoundingSphere sphere) - { - //Source: Real-Time Collision Detection by Christer Ericson - //Reference: Page 166 - - Vector3 vector; - Vector3.Clamp(ref sphere.Center, ref box.Minimum, ref box.Maximum, out vector); - float distance = Vector3.DistanceSquared(sphere.Center, vector); - - return distance <= sphere.Radius * sphere.Radius; - } - - /// - /// Determines whether there is an intersection between a and a triangle. - /// - /// The sphere to test. - /// The first vertex of the triangle to test. - /// The second vertex of the triangle to test. - /// The third vertex of the triangle to test. - /// Whether the two objects intersected. - public static bool SphereIntersectsTriangle(ref BoundingSphere sphere, ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) - { - //Source: Real-Time Collision Detection by Christer Ericson - //Reference: Page 167 - - Vector3 point; - ClosestPointPointTriangle(ref sphere.Center, ref vertex1, ref vertex2, ref vertex3, out point); - Vector3 v = point - sphere.Center; - - float dot; - Vector3.Dot(ref v, ref v, out dot); - - return dot <= sphere.Radius * sphere.Radius; - } - - /// - /// Determines whether there is an intersection between a and a . - /// - /// First sphere to test. - /// Second sphere to test. - /// Whether the two objects intersected. - public static bool SphereIntersectsSphere(ref BoundingSphere sphere1, ref BoundingSphere sphere2) - { - float radiisum = sphere1.Radius + sphere2.Radius; - return Vector3.DistanceSquared(sphere1.Center, sphere2.Center) <= radiisum * radiisum; - } - - /// - /// Determines whether a contains a point. - /// - /// The box to test. - /// The point to test. - /// The type of containment the two objects have. - public static ContainmentType BoxContainsPoint(ref BoundingBox box, ref Vector3 point) - { - if (box.Minimum.X <= point.X && box.Maximum.X >= point.X && - box.Minimum.Y <= point.Y && box.Maximum.Y >= point.Y && - box.Minimum.Z <= point.Z && box.Maximum.Z >= point.Z) - { - return ContainmentType.Contains; - } - - return ContainmentType.Disjoint; - } - - /* This implementation is wrong - /// - /// Determines whether a contains a triangle. - /// - /// The box to test. - /// The first vertex of the triangle to test. - /// The second vertex of the triangle to test. - /// The third vertex of the triangle to test. - /// The type of containment the two objects have. - public static ContainmentType BoxContainsTriangle(ref BoundingBox box, ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) - { - ContainmentType test1 = BoxContainsPoint(ref box, ref vertex1); - ContainmentType test2 = BoxContainsPoint(ref box, ref vertex2); - ContainmentType test3 = BoxContainsPoint(ref box, ref vertex3); - - if (test1 == ContainmentType.Contains && test2 == ContainmentType.Contains && test3 == ContainmentType.Contains) - return ContainmentType.Contains; - - if (test1 == ContainmentType.Contains || test2 == ContainmentType.Contains || test3 == ContainmentType.Contains) - return ContainmentType.Intersects; - - return ContainmentType.Disjoint; - } - */ - - /// - /// Determines whether a contains a . - /// - /// The first box to test. - /// The second box to test. - /// The type of containment the two objects have. - public static ContainmentType BoxContainsBox(ref BoundingBox box1, ref BoundingBox box2) - { - if (box1.Maximum.X < box2.Minimum.X || box1.Minimum.X > box2.Maximum.X) - return ContainmentType.Disjoint; - - if (box1.Maximum.Y < box2.Minimum.Y || box1.Minimum.Y > box2.Maximum.Y) - return ContainmentType.Disjoint; - - if (box1.Maximum.Z < box2.Minimum.Z || box1.Minimum.Z > box2.Maximum.Z) - return ContainmentType.Disjoint; - - if (box1.Minimum.X <= box2.Minimum.X && (box2.Maximum.X <= box1.Maximum.X && - box1.Minimum.Y <= box2.Minimum.Y && box2.Maximum.Y <= box1.Maximum.Y) && - box1.Minimum.Z <= box2.Minimum.Z && box2.Maximum.Z <= box1.Maximum.Z) - { - return ContainmentType.Contains; - } - - return ContainmentType.Intersects; - } - - /// - /// Determines whether a contains a . - /// - /// The box to test. - /// The sphere to test. - /// The type of containment the two objects have. - public static ContainmentType BoxContainsSphere(ref BoundingBox box, ref BoundingSphere sphere) - { - Vector3 vector; - Vector3.Clamp(ref sphere.Center, ref box.Minimum, ref box.Maximum, out vector); - float distance = Vector3.DistanceSquared(sphere.Center, vector); - - if (distance > sphere.Radius * sphere.Radius) - return ContainmentType.Disjoint; - - if ((((box.Minimum.X + sphere.Radius <= sphere.Center.X) && (sphere.Center.X <= box.Maximum.X - sphere.Radius)) && ((box.Maximum.X - box.Minimum.X > sphere.Radius) && - (box.Minimum.Y + sphere.Radius <= sphere.Center.Y))) && (((sphere.Center.Y <= box.Maximum.Y - sphere.Radius) && (box.Maximum.Y - box.Minimum.Y > sphere.Radius)) && - (((box.Minimum.Z + sphere.Radius <= sphere.Center.Z) && (sphere.Center.Z <= box.Maximum.Z - sphere.Radius)) && (box.Maximum.X - box.Minimum.X > sphere.Radius)))) - { - return ContainmentType.Contains; - } - - return ContainmentType.Intersects; - } - - /// - /// Determines whether a contains a point. - /// - /// The sphere to test. - /// The point to test. - /// The type of containment the two objects have. - public static ContainmentType SphereContainsPoint(ref BoundingSphere sphere, ref Vector3 point) - { - if (Vector3.DistanceSquared(point, sphere.Center) <= sphere.Radius * sphere.Radius) - return ContainmentType.Contains; - - return ContainmentType.Disjoint; - } - - /// - /// Determines whether a contains a triangle. - /// - /// The sphere to test. - /// The first vertex of the triangle to test. - /// The second vertex of the triangle to test. - /// The third vertex of the triangle to test. - /// The type of containment the two objects have. - public static ContainmentType SphereContainsTriangle(ref BoundingSphere sphere, ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) - { - //Source: Jorgy343 - //Reference: None - - ContainmentType test1 = SphereContainsPoint(ref sphere, ref vertex1); - ContainmentType test2 = SphereContainsPoint(ref sphere, ref vertex2); - ContainmentType test3 = SphereContainsPoint(ref sphere, ref vertex3); - - if (test1 == ContainmentType.Contains && test2 == ContainmentType.Contains && test3 == ContainmentType.Contains) - return ContainmentType.Contains; - - if (SphereIntersectsTriangle(ref sphere, ref vertex1, ref vertex2, ref vertex3)) - return ContainmentType.Intersects; - - return ContainmentType.Disjoint; - } - - /// - /// Determines whether a contains a . - /// - /// The sphere to test. - /// The box to test. - /// The type of containment the two objects have. - public static ContainmentType SphereContainsBox(ref BoundingSphere sphere, ref BoundingBox box) - { - Vector3 vector; - - if (!BoxIntersectsSphere(ref box, ref sphere)) - return ContainmentType.Disjoint; - - float radiussquared = sphere.Radius * sphere.Radius; - vector.X = sphere.Center.X - box.Minimum.X; - vector.Y = sphere.Center.Y - box.Maximum.Y; - vector.Z = sphere.Center.Z - box.Maximum.Z; - - if (vector.LengthSquared() > radiussquared) - return ContainmentType.Intersects; - - vector.X = sphere.Center.X - box.Maximum.X; - vector.Y = sphere.Center.Y - box.Maximum.Y; - vector.Z = sphere.Center.Z - box.Maximum.Z; - - if (vector.LengthSquared() > radiussquared) - return ContainmentType.Intersects; - - vector.X = sphere.Center.X - box.Maximum.X; - vector.Y = sphere.Center.Y - box.Minimum.Y; - vector.Z = sphere.Center.Z - box.Maximum.Z; - - if (vector.LengthSquared() > radiussquared) - return ContainmentType.Intersects; - - vector.X = sphere.Center.X - box.Minimum.X; - vector.Y = sphere.Center.Y - box.Minimum.Y; - vector.Z = sphere.Center.Z - box.Maximum.Z; - - if (vector.LengthSquared() > radiussquared) - return ContainmentType.Intersects; - - vector.X = sphere.Center.X - box.Minimum.X; - vector.Y = sphere.Center.Y - box.Maximum.Y; - vector.Z = sphere.Center.Z - box.Minimum.Z; - - if (vector.LengthSquared() > radiussquared) - return ContainmentType.Intersects; - - vector.X = sphere.Center.X - box.Maximum.X; - vector.Y = sphere.Center.Y - box.Maximum.Y; - vector.Z = sphere.Center.Z - box.Minimum.Z; - - if (vector.LengthSquared() > radiussquared) - return ContainmentType.Intersects; - - vector.X = sphere.Center.X - box.Maximum.X; - vector.Y = sphere.Center.Y - box.Minimum.Y; - vector.Z = sphere.Center.Z - box.Minimum.Z; - - if (vector.LengthSquared() > radiussquared) - return ContainmentType.Intersects; - - vector.X = sphere.Center.X - box.Minimum.X; - vector.Y = sphere.Center.Y - box.Minimum.Y; - vector.Z = sphere.Center.Z - box.Minimum.Z; - - if (vector.LengthSquared() > radiussquared) - return ContainmentType.Intersects; - - return ContainmentType.Contains; - } - - /// - /// Determines whether a contains a . - /// - /// The first sphere to test. - /// The second sphere to test. - /// The type of containment the two objects have. - public static ContainmentType SphereContainsSphere(ref BoundingSphere sphere1, ref BoundingSphere sphere2) - { - float distance = Vector3.Distance(sphere1.Center, sphere2.Center); - - if (sphere1.Radius + sphere2.Radius < distance) - return ContainmentType.Disjoint; - - if (sphere1.Radius - sphere2.Radius < distance) - return ContainmentType.Intersects; - - return ContainmentType.Contains; - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from SlimMath project. http://code.google.com/p/slimmath/ +// Greetings to SlimDX Group. Original code published with the following license: +// ----------------------------------------------------------------------------- +/* +* Copyright (c) 2007-2011 SlimDX Group +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +using System; +using System.Globalization; +using System.Runtime.InteropServices; +using System.ComponentModel; + +namespace SharpDX +{ + /* + * This class is organized so that the least complex objects come first so that the least + * complex objects will have the most methods in most cases. Note that not all shapes exist + * at this time and not all shapes have a corresponding struct. Only the objects that have + * a corresponding struct should come first in naming and in parameter order. The order of + * complexity is as follows: + * + * 1. Point + * 2. Ray + * 3. Segment + * 4. Plane + * 5. Triangle + * 6. Polygon + * 7. Box + * 8. Sphere + * 9. Ellipsoid + * 10. Cylinder + * 11. Cone + * 12. Capsule + * 13. Torus + * 14. Polyhedron + * 15. Frustum + */ + + /// + /// Contains static methods to help in determining intersections, containment, etc. + /// + public static class Collision + { + /// + /// Determines the closest point between a point and a triangle. + /// + /// The point to test. + /// The first vertex to test. + /// The second vertex to test. + /// The third vertex to test. + /// When the method completes, contains the closest point between the two objects. + public static void ClosestPointPointTriangle(ref Vector3 point, ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3, out Vector3 result) + { + //Source: Real-Time Collision Detection by Christer Ericson + //Reference: Page 136 + + //Check if P in vertex region outside A + Vector3 ab = vertex2 - vertex1; + Vector3 ac = vertex3 - vertex1; + Vector3 ap = point - vertex1; + + float d1 = Vector3.Dot(ab, ap); + float d2 = Vector3.Dot(ac, ap); + if (d1 <= 0.0f && d2 <= 0.0f) + result = vertex1; //Barycentric coordinates (1,0,0) + + //Check if P in vertex region outside B + Vector3 bp = point - vertex2; + float d3 = Vector3.Dot(ab, bp); + float d4 = Vector3.Dot(ac, bp); + if (d3 >= 0.0f && d4 <= d3) + result = vertex2; // Barycentric coordinates (0,1,0) + + //Check if P in edge region of AB, if so return projection of P onto AB + float vc = d1 * d4 - d3 * d2; + if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) + { + float v = d1 / (d1 - d3); + result = vertex1 + v * ab; //Barycentric coordinates (1-v,v,0) + } + + //Check if P in vertex region outside C + Vector3 cp = point - vertex3; + float d5 = Vector3.Dot(ab, cp); + float d6 = Vector3.Dot(ac, cp); + if (d6 >= 0.0f && d5 <= d6) + result = vertex3; //Barycentric coordinates (0,0,1) + + //Check if P in edge region of AC, if so return projection of P onto AC + float vb = d5 * d2 - d1 * d6; + if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) + { + float w = d2 / (d2 - d6); + result = vertex1 + w * ac; //Barycentric coordinates (1-w,0,w) + } + + //Check if P in edge region of BC, if so return projection of P onto BC + float va = d3 * d6 - d5 * d4; + if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) + { + float w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); + result = vertex2 + w * (vertex3 - vertex2); //Barycentric coordinates (0,1-w,w) + } + + //P inside face region. Compute Q through its Barycentric coordinates (u,v,w) + float denom = 1.0f / (va + vb + vc); + float v2 = vb * denom; + float w2 = vc * denom; + result = vertex1 + ab * v2 + ac * w2; //= u*vertex1 + v*vertex2 + w*vertex3, u = va * denom = 1.0f - v - w + } + + /// + /// Determines the closest point between a and a point. + /// + /// The plane to test. + /// The point to test. + /// When the method completes, contains the closest point between the two objects. + public static void ClosestPointPlanePoint(ref Plane plane, ref Vector3 point, out Vector3 result) + { + //Source: Real-Time Collision Detection by Christer Ericson + //Reference: Page 126 + + float dot; + Vector3.Dot(ref plane.Normal, ref point, out dot); + float t = dot - plane.D; + + result = point - (t * plane.Normal); + } + + /// + /// Determines the closest point between a and a point. + /// + /// The box to test. + /// The point to test. + /// When the method completes, contains the closest point between the two objects. + public static void ClosestPointBoxPoint(ref BoundingBox box, ref Vector3 point, out Vector3 result) + { + //Source: Real-Time Collision Detection by Christer Ericson + //Reference: Page 130 + + Vector3 temp; + Vector3.Max(ref point, ref box.Minimum, out temp); + Vector3.Min(ref temp, ref box.Maximum, out result); + } + + /// + /// Determines the closest point between a and a point. + /// + /// + /// The point to test. + /// When the method completes, contains the closest point between the two objects; + /// or, if the point is directly in the center of the sphere, contains . + public static void ClosestPointSpherePoint(ref BoundingSphere sphere, ref Vector3 point, out Vector3 result) + { + //Source: Jorgy343 + //Reference: None + + //Get the unit direction from the sphere's center to the point. + Vector3.Subtract(ref point, ref sphere.Center, out result); + result.Normalize(); + + //Multiply the unit direction by the sphere's radius to get a vector + //the length of the sphere. + result *= sphere.Radius; + + //Add the sphere's center to the direction to get a point on the sphere. + result += sphere.Center; + } + + /// + /// Determines the closest point between a and a . + /// + /// The first sphere to test. + /// The second sphere to test. + /// When the method completes, contains the closest point between the two objects; + /// or, if the point is directly in the center of the sphere, contains . + /// + /// If the two spheres are overlapping, but not directly on top of each other, the closest point + /// is the 'closest' point of intersection. This can also be considered is the deepest point of + /// intersection. + /// + public static void ClosestPointSphereSphere(ref BoundingSphere sphere1, ref BoundingSphere sphere2, out Vector3 result) + { + //Source: Jorgy343 + //Reference: None + + //Get the unit direction from the first sphere's center to the second sphere's center. + Vector3.Subtract(ref sphere2.Center, ref sphere1.Center, out result); + result.Normalize(); + + //Multiply the unit direction by the first sphere's radius to get a vector + //the length of the first sphere. + result *= sphere1.Radius; + + //Add the first sphere's center to the direction to get a point on the first sphere. + result += sphere1.Center; + } + + /// + /// Determines the distance between a and a point. + /// + /// The plane to test. + /// The point to test. + /// The distance between the two objects. + public static float DistancePlanePoint(ref Plane plane, ref Vector3 point) + { + //Source: Real-Time Collision Detection by Christer Ericson + //Reference: Page 127 + + float dot; + Vector3.Dot(ref plane.Normal, ref point, out dot); + return dot - plane.D; + } + + /// + /// Determines the distance between a and a point. + /// + /// The box to test. + /// The point to test. + /// The distance between the two objects. + public static float DistanceBoxPoint(ref BoundingBox box, ref Vector3 point) + { + //Source: Real-Time Collision Detection by Christer Ericson + //Reference: Page 131 + + float distance = 0f; + + if (point.X < box.Minimum.X) + distance += (box.Minimum.X - point.X) * (box.Minimum.X - point.X); + if (point.X > box.Maximum.X) + distance += (point.X - box.Maximum.X) * (point.X - box.Maximum.X); + + if (point.Y < box.Minimum.Y) + distance += (box.Minimum.Y - point.Y) * (box.Minimum.Y - point.Y); + if (point.Y > box.Maximum.Y) + distance += (point.Y - box.Maximum.Y) * (point.Y - box.Maximum.Y); + + if (point.Z < box.Minimum.Z) + distance += (box.Minimum.Z - point.Z) * (box.Minimum.Z - point.Z); + if (point.Z > box.Maximum.Z) + distance += (point.Z - box.Maximum.Z) * (point.Z - box.Maximum.Z); + + return (float)Math.Sqrt(distance); + } + + /// + /// Determines the distance between a and a . + /// + /// The first box to test. + /// The second box to test. + /// The distance between the two objects. + public static float DistanceBoxBox(ref BoundingBox box1, ref BoundingBox box2) + { + //Source: + //Reference: + + float distance = 0f; + + //Distance for X. + if (box1.Minimum.X > box2.Maximum.X) + { + float delta = box2.Maximum.X - box1.Minimum.X; + distance += delta * delta; + } + else if (box2.Minimum.X > box1.Maximum.X) + { + float delta = box1.Maximum.X - box2.Minimum.X; + distance += delta * delta; + } + + //Distance for Y. + if (box1.Minimum.Y > box2.Maximum.Y) + { + float delta = box2.Maximum.Y - box1.Minimum.Y; + distance += delta * delta; + } + else if (box2.Minimum.Y > box1.Maximum.Y) + { + float delta = box1.Maximum.Y - box2.Minimum.Y; + distance += delta * delta; + } + + //Distance for Z. + if (box1.Minimum.Z > box2.Maximum.Z) + { + float delta = box2.Maximum.Z - box1.Minimum.Z; + distance += delta * delta; + } + else if (box2.Minimum.Z > box1.Maximum.Z) + { + float delta = box1.Maximum.Z - box2.Minimum.Z; + distance += delta * delta; + } + + return (float)Math.Sqrt(distance); + } + + /// + /// Determines the distance between a and a point. + /// + /// The sphere to test. + /// The point to test. + /// The distance between the two objects. + public static float DistanceSpherePoint(ref BoundingSphere sphere, ref Vector3 point) + { + //Source: Jorgy343 + //Reference: None + + float distance; + Vector3.Distance(ref sphere.Center, ref point, out distance); + distance -= sphere.Radius; + + return Math.Max(distance, 0f); + } + + /// + /// Determines the distance between a and a . + /// + /// The first sphere to test. + /// The second sphere to test. + /// The distance between the two objects. + public static float DistanceSphereSphere(ref BoundingSphere sphere1, ref BoundingSphere sphere2) + { + //Source: Jorgy343 + //Reference: None + + float distance; + Vector3.Distance(ref sphere1.Center, ref sphere2.Center, out distance); + distance -= sphere1.Radius + sphere2.Radius; + + return Math.Max(distance, 0f); + } + + /// + /// Determines whether there is an intersection between a and a point. + /// + /// The ray to test. + /// The point to test. + /// Whether the two objects intersect. + public static bool RayIntersectsPoint(ref Ray ray, ref Vector3 point) + { + //Source: RayIntersectsSphere + //Reference: None + + Vector3 m; + Vector3.Subtract(ref ray.Position, ref point, out m); + + //Same thing as RayIntersectsSphere except that the radius of the sphere (point) + //is the epsilon for zero. + float b = Vector3.Dot(m, ray.Direction); + float c = Vector3.Dot(m, m) - MathUtil.ZeroTolerance; + + if (c > 0f && b > 0f) + return false; + + float discriminant = b * b - c; + + if (discriminant < 0f) + return false; + + return true; + } + + /// + /// Determines whether there is an intersection between a and a . + /// + /// The first ray to test. + /// The second ray to test. + /// When the method completes, contains the point of intersection, + /// or if there was no intersection. + /// Whether the two objects intersect. + /// + /// This method performs a ray vs ray intersection test based on the following formula + /// from Goldman. + /// s = det([o_2 - o_1, d_2, d_1 x d_2]) / ||d_1 x d_2||^2 + /// t = det([o_2 - o_1, d_1, d_1 x d_2]) / ||d_1 x d_2||^2 + /// Where o_1 is the position of the first ray, o_2 is the position of the second ray, + /// d_1 is the normalized direction of the first ray, d_2 is the normalized direction + /// of the second ray, det denotes the determinant of a matrix, x denotes the cross + /// product, [ ] denotes a matrix, and || || denotes the length or magnitude of a vector. + /// + public static bool RayIntersectsRay(ref Ray ray1, ref Ray ray2, out Vector3 point) + { + //Source: Real-Time Rendering, Third Edition + //Reference: Page 780 + + Vector3 cross; + + Vector3.Cross(ref ray1.Direction, ref ray2.Direction, out cross); + float denominator = cross.Length(); + + //Lines are parallel. + if (MathUtil.IsZero(denominator)) + { + //Lines are parallel and on top of each other. + if (MathUtil.NearEqual(ray2.Position.X, ray1.Position.X) && + MathUtil.NearEqual(ray2.Position.Y, ray1.Position.Y) && + MathUtil.NearEqual(ray2.Position.Z, ray1.Position.Z)) + { + point = Vector3.Zero; + return true; + } + } + + denominator = denominator * denominator; + + //3x3 matrix for the first ray. + float m11 = ray2.Position.X - ray1.Position.X; + float m12 = ray2.Position.Y - ray1.Position.Y; + float m13 = ray2.Position.Z - ray1.Position.Z; + float m21 = ray2.Direction.X; + float m22 = ray2.Direction.Y; + float m23 = ray2.Direction.Z; + float m31 = cross.X; + float m32 = cross.Y; + float m33 = cross.Z; + + //Determinant of first matrix. + float dets = + m11 * m22 * m33 + + m12 * m23 * m31 + + m13 * m21 * m32 - + m11 * m23 * m32 - + m12 * m21 * m33 - + m13 * m22 * m31; + + //3x3 matrix for the second ray. + m21 = ray1.Direction.X; + m22 = ray1.Direction.Y; + m23 = ray1.Direction.Z; + + //Determinant of the second matrix. + float dett = + m11 * m22 * m33 + + m12 * m23 * m31 + + m13 * m21 * m32 - + m11 * m23 * m32 - + m12 * m21 * m33 - + m13 * m22 * m31; + + //t values of the point of intersection. + float s = dets / denominator; + float t = dett / denominator; + + //The points of intersection. + Vector3 point1 = ray1.Position + (s * ray1.Direction); + Vector3 point2 = ray2.Position + (t * ray2.Direction); + + //If the points are not equal, no intersection has occurred. + if (!MathUtil.NearEqual(point2.X, point1.X) || + !MathUtil.NearEqual(point2.Y, point1.Y) || + !MathUtil.NearEqual(point2.Z, point1.Z)) + { + point = Vector3.Zero; + return false; + } + + point = point1; + return true; + } + + /// + /// Determines whether there is an intersection between a and a . + /// + /// The ray to test. + /// The plane to test. + /// When the method completes, contains the distance of the intersection, + /// or 0 if there was no intersection. + /// Whether the two objects intersect. + public static bool RayIntersectsPlane(ref Ray ray, ref Plane plane, out float distance) + { + //Source: Real-Time Collision Detection by Christer Ericson + //Reference: Page 175 + + float direction; + Vector3.Dot(ref plane.Normal, ref ray.Direction, out direction); + + if (MathUtil.IsZero(direction)) + { + distance = 0f; + return false; + } + + float position; + Vector3.Dot(ref plane.Normal, ref ray.Position, out position); + distance = (-plane.D - position) / direction; + + if (distance < 0f) + { + if (MathUtil.IsZero(distance)) + { + distance = 0; + return false; + } + + distance = 0f; + } + + return true; + } + + /// + /// Determines whether there is an intersection between a and a . + /// + /// The ray to test. + /// The plane to test + /// When the method completes, contains the point of intersection, + /// or if there was no intersection. + /// Whether the two objects intersected. + public static bool RayIntersectsPlane(ref Ray ray, ref Plane plane, out Vector3 point) + { + //Source: Real-Time Collision Detection by Christer Ericson + //Reference: Page 175 + + float distance; + if (!RayIntersectsPlane(ref ray, ref plane, out distance)) + { + point = Vector3.Zero; + return false; + } + + point = ray.Position + (ray.Direction * distance); + return true; + } + + /// + /// Determines whether there is an intersection between a and a triangle. + /// + /// The ray to test. + /// The first vertex of the triangle to test. + /// The second vertex of the triangle to test. + /// The third vertex of the triangle to test. + /// When the method completes, contains the distance of the intersection, + /// or 0 if there was no intersection. + /// Whether the two objects intersected. + /// + /// This method tests if the ray intersects either the front or back of the triangle. + /// If the ray is parallel to the triangle's plane, no intersection is assumed to have + /// happened. If the intersection of the ray and the triangle is behind the origin of + /// the ray, no intersection is assumed to have happened. In both cases of assumptions, + /// this method returns false. + /// + public static bool RayIntersectsTriangle(ref Ray ray, ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3, out float distance) + { + //Source: Fast Minimum Storage Ray / Triangle Intersection + //Reference: http://www.cs.virginia.edu/~gfx/Courses/2003/ImageSynthesis/papers/Acceleration/Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf + + //Compute vectors along two edges of the triangle. + Vector3 edge1, edge2; + + //Edge 1 + edge1.X = vertex2.X - vertex1.X; + edge1.Y = vertex2.Y - vertex1.Y; + edge1.Z = vertex2.Z - vertex1.Z; + + //Edge2 + edge2.X = vertex3.X - vertex1.X; + edge2.Y = vertex3.Y - vertex1.Y; + edge2.Z = vertex3.Z - vertex1.Z; + + //Cross product of ray direction and edge2 - first part of determinant. + Vector3 directioncrossedge2; + directioncrossedge2.X = (ray.Direction.Y * edge2.Z) - (ray.Direction.Z * edge2.Y); + directioncrossedge2.Y = (ray.Direction.Z * edge2.X) - (ray.Direction.X * edge2.Z); + directioncrossedge2.Z = (ray.Direction.X * edge2.Y) - (ray.Direction.Y * edge2.X); + + //Compute the determinant. + float determinant; + //Dot product of edge1 and the first part of determinant. + determinant = (edge1.X * directioncrossedge2.X) + (edge1.Y * directioncrossedge2.Y) + (edge1.Z * directioncrossedge2.Z); + + //If the ray is parallel to the triangle plane, there is no collision. + //This also means that we are not culling, the ray may hit both the + //back and the front of the triangle. + if (MathUtil.IsZero(determinant)) + { + distance = 0f; + return false; + } + + float inversedeterminant = 1.0f / determinant; + + //Calculate the U parameter of the intersection point. + Vector3 distanceVector; + distanceVector.X = ray.Position.X - vertex1.X; + distanceVector.Y = ray.Position.Y - vertex1.Y; + distanceVector.Z = ray.Position.Z - vertex1.Z; + + float triangleU; + triangleU = (distanceVector.X * directioncrossedge2.X) + (distanceVector.Y * directioncrossedge2.Y) + (distanceVector.Z * directioncrossedge2.Z); + triangleU *= inversedeterminant; + + //Make sure it is inside the triangle. + if (triangleU < 0f || triangleU > 1f) + { + distance = 0f; + return false; + } + + //Calculate the V parameter of the intersection point. + Vector3 distancecrossedge1; + distancecrossedge1.X = (distanceVector.Y * edge1.Z) - (distanceVector.Z * edge1.Y); + distancecrossedge1.Y = (distanceVector.Z * edge1.X) - (distanceVector.X * edge1.Z); + distancecrossedge1.Z = (distanceVector.X * edge1.Y) - (distanceVector.Y * edge1.X); + + float triangleV; + triangleV = ((ray.Direction.X * distancecrossedge1.X) + (ray.Direction.Y * distancecrossedge1.Y)) + (ray.Direction.Z * distancecrossedge1.Z); + triangleV *= inversedeterminant; + + //Make sure it is inside the triangle. + if (triangleV < 0f || triangleU + triangleV > 1f) + { + distance = 0f; + return false; + } + + //Compute the distance along the ray to the triangle. + float raydistance; + raydistance = (edge2.X * distancecrossedge1.X) + (edge2.Y * distancecrossedge1.Y) + (edge2.Z * distancecrossedge1.Z); + raydistance *= inversedeterminant; + + //Is the triangle behind the ray origin? + if (raydistance < 0f) + { + distance = 0f; + return false; + } + + distance = raydistance; + return true; + } + + /// + /// Determines whether there is an intersection between a and a triangle. + /// + /// The ray to test. + /// The first vertex of the triangle to test. + /// The second vertex of the triangle to test. + /// The third vertex of the triangle to test. + /// When the method completes, contains the point of intersection, + /// or if there was no intersection. + /// Whether the two objects intersected. + public static bool RayIntersectsTriangle(ref Ray ray, ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3, out Vector3 point) + { + float distance; + if (!RayIntersectsTriangle(ref ray, ref vertex1, ref vertex2, ref vertex3, out distance)) + { + point = Vector3.Zero; + return false; + } + + point = ray.Position + (ray.Direction * distance); + return true; + } + + /// + /// Determines whether there is an intersection between a and a . + /// + /// The ray to test. + /// The box to test. + /// When the method completes, contains the distance of the intersection, + /// or 0 if there was no intersection. + /// Whether the two objects intersected. + public static bool RayIntersectsBox(ref Ray ray, ref BoundingBox box, out float distance) + { + //Source: Real-Time Collision Detection by Christer Ericson + //Reference: Page 179 + + distance = 0f; + float tmax = float.MaxValue; + + if (MathUtil.IsZero(ray.Direction.X)) + { + if (ray.Position.X < box.Minimum.X || ray.Position.X > box.Maximum.X) + { + distance = 0f; + return false; + } + } + else + { + float inverse = 1.0f / ray.Direction.X; + float t1 = (box.Minimum.X - ray.Position.X) * inverse; + float t2 = (box.Maximum.X - ray.Position.X) * inverse; + + if (t1 > t2) + { + float temp = t1; + t1 = t2; + t2 = temp; + } + + distance = Math.Max(t1, distance); + tmax = Math.Min(t2, tmax); + + if (distance > tmax) + { + distance = 0f; + return false; + } + } + + if (MathUtil.IsZero(ray.Direction.Y)) + { + if (ray.Position.Y < box.Minimum.Y || ray.Position.Y > box.Maximum.Y) + { + distance = 0f; + return false; + } + } + else + { + float inverse = 1.0f / ray.Direction.Y; + float t1 = (box.Minimum.Y - ray.Position.Y) * inverse; + float t2 = (box.Maximum.Y - ray.Position.Y) * inverse; + + if (t1 > t2) + { + float temp = t1; + t1 = t2; + t2 = temp; + } + + distance = Math.Max(t1, distance); + tmax = Math.Min(t2, tmax); + + if (distance > tmax) + { + distance = 0f; + return false; + } + } + + if (MathUtil.IsZero(ray.Direction.Z)) + { + if (ray.Position.Z < box.Minimum.Z || ray.Position.Z > box.Maximum.Z) + { + distance = 0f; + return false; + } + } + else + { + float inverse = 1.0f / ray.Direction.Z; + float t1 = (box.Minimum.Z - ray.Position.Z) * inverse; + float t2 = (box.Maximum.Z - ray.Position.Z) * inverse; + + if (t1 > t2) + { + float temp = t1; + t1 = t2; + t2 = temp; + } + + distance = Math.Max(t1, distance); + tmax = Math.Min(t2, tmax); + + if (distance > tmax) + { + distance = 0f; + return false; + } + } + + return true; + } + + /// + /// Determines whether there is an intersection between a and a . + /// + /// The ray to test. + /// The box to test. + /// When the method completes, contains the point of intersection, + /// or if there was no intersection. + /// Whether the two objects intersected. + public static bool RayIntersectsBox(ref Ray ray, ref BoundingBox box, out Vector3 point) + { + float distance; + if (!RayIntersectsBox(ref ray, ref box, out distance)) + { + point = Vector3.Zero; + return false; + } + + point = ray.Position + (ray.Direction * distance); + return true; + } + + /// + /// Determines whether there is an intersection between a and a . + /// + /// The ray to test. + /// The sphere to test. + /// When the method completes, contains the distance of the intersection, + /// or 0 if there was no intersection. + /// Whether the two objects intersected. + public static bool RayIntersectsSphere(ref Ray ray, ref BoundingSphere sphere, out float distance) + { + //Source: Real-Time Collision Detection by Christer Ericson + //Reference: Page 177 + + Vector3 m; + Vector3.Subtract(ref ray.Position, ref sphere.Center, out m); + + float b = Vector3.Dot(m, ray.Direction); + float c = Vector3.Dot(m, m) - (sphere.Radius * sphere.Radius); + + if (c > 0f && b > 0f) + { + distance = 0f; + return false; + } + + float discriminant = b * b - c; + + if (discriminant < 0f) + { + distance = 0f; + return false; + } + + distance = -b - (float)Math.Sqrt(discriminant); + + if (distance < 0f) + distance = 0f; + + return true; + } + + /// + /// Determines whether there is an intersection between a and a . + /// + /// The ray to test. + /// The sphere to test. + /// When the method completes, contains the point of intersection, + /// or if there was no intersection. + /// Whether the two objects intersected. + public static bool RayIntersectsSphere(ref Ray ray, ref BoundingSphere sphere, out Vector3 point) + { + float distance; + if (!RayIntersectsSphere(ref ray, ref sphere, out distance)) + { + point = Vector3.Zero; + return false; + } + + point = ray.Position + (ray.Direction * distance); + return true; + } + + /// + /// Determines whether there is an intersection between a and a point. + /// + /// The plane to test. + /// The point to test. + /// Whether the two objects intersected. + public static PlaneIntersectionType PlaneIntersectsPoint(ref Plane plane, ref Vector3 point) + { + float distance; + Vector3.Dot(ref plane.Normal, ref point, out distance); + distance += plane.D; + + if (distance > 0f) + return PlaneIntersectionType.Front; + + if (distance < 0f) + return PlaneIntersectionType.Back; + + return PlaneIntersectionType.Intersecting; + } + + /// + /// Determines whether there is an intersection between a and a . + /// + /// The first plane to test. + /// The second plane to test. + /// Whether the two objects intersected. + public static bool PlaneIntersectsPlane(ref Plane plane1, ref Plane plane2) + { + Vector3 direction; + Vector3.Cross(ref plane1.Normal, ref plane2.Normal, out direction); + + //If direction is the zero vector, the planes are parallel and possibly + //coincident. It is not an intersection. The dot product will tell us. + float denominator; + Vector3.Dot(ref direction, ref direction, out denominator); + + if (MathUtil.IsZero(denominator)) + return false; + + return true; + } + + /// + /// Determines whether there is an intersection between a and a . + /// + /// The first plane to test. + /// The second plane to test. + /// When the method completes, contains the line of intersection + /// as a , or a zero ray if there was no intersection. + /// Whether the two objects intersected. + /// + /// Although a ray is set to have an origin, the ray returned by this method is really + /// a line in three dimensions which has no real origin. The ray is considered valid when + /// both the positive direction is used and when the negative direction is used. + /// + public static bool PlaneIntersectsPlane(ref Plane plane1, ref Plane plane2, out Ray line) + { + //Source: Real-Time Collision Detection by Christer Ericson + //Reference: Page 207 + + Vector3 direction; + Vector3.Cross(ref plane1.Normal, ref plane2.Normal, out direction); + + //If direction is the zero vector, the planes are parallel and possibly + //coincident. It is not an intersection. The dot product will tell us. + float denominator; + Vector3.Dot(ref direction, ref direction, out denominator); + + //We assume the planes are normalized, therefore the denominator + //only serves as a parallel and coincident check. Otherwise we need + //to divide the point by the denominator. + if (MathUtil.IsZero(denominator)) + { + line = new Ray(); + return false; + } + + Vector3 point; + Vector3 temp = plane1.D * plane2.Normal - plane2.D * plane1.Normal; + Vector3.Cross(ref temp, ref direction, out point); + + line.Position = point; + line.Direction = direction; + line.Direction.Normalize(); + + return true; + } + + /// + /// Determines whether there is an intersection between a and a triangle. + /// + /// The plane to test. + /// The first vertex of the triangle to test. + /// The second vertex of the triangle to test. + /// The third vertex of the triangle to test. + /// Whether the two objects intersected. + public static PlaneIntersectionType PlaneIntersectsTriangle(ref Plane plane, ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) + { + //Source: Real-Time Collision Detection by Christer Ericson + //Reference: Page 207 + + PlaneIntersectionType test1 = PlaneIntersectsPoint(ref plane, ref vertex1); + PlaneIntersectionType test2 = PlaneIntersectsPoint(ref plane, ref vertex2); + PlaneIntersectionType test3 = PlaneIntersectsPoint(ref plane, ref vertex3); + + if (test1 == PlaneIntersectionType.Front && test2 == PlaneIntersectionType.Front && test3 == PlaneIntersectionType.Front) + return PlaneIntersectionType.Front; + + if (test1 == PlaneIntersectionType.Back && test2 == PlaneIntersectionType.Back && test3 == PlaneIntersectionType.Back) + return PlaneIntersectionType.Back; + + return PlaneIntersectionType.Intersecting; + } + + /// + /// Determines whether there is an intersection between a and a . + /// + /// The plane to test. + /// The box to test. + /// Whether the two objects intersected. + public static PlaneIntersectionType PlaneIntersectsBox(ref Plane plane, ref BoundingBox box) + { + //Source: Real-Time Collision Detection by Christer Ericson + //Reference: Page 161 + + Vector3 min; + Vector3 max; + + max.X = (plane.Normal.X >= 0.0f) ? box.Minimum.X : box.Maximum.X; + max.Y = (plane.Normal.Y >= 0.0f) ? box.Minimum.Y : box.Maximum.Y; + max.Z = (plane.Normal.Z >= 0.0f) ? box.Minimum.Z : box.Maximum.Z; + min.X = (plane.Normal.X >= 0.0f) ? box.Maximum.X : box.Minimum.X; + min.Y = (plane.Normal.Y >= 0.0f) ? box.Maximum.Y : box.Minimum.Y; + min.Z = (plane.Normal.Z >= 0.0f) ? box.Maximum.Z : box.Minimum.Z; + + float distance; + Vector3.Dot(ref plane.Normal, ref max, out distance); + + if (distance + plane.D > 0.0f) + return PlaneIntersectionType.Front; + + distance = Vector3.Dot(plane.Normal, min); + + if (distance + plane.D < 0.0f) + return PlaneIntersectionType.Back; + + return PlaneIntersectionType.Intersecting; + } + + /// + /// Determines whether there is an intersection between a and a . + /// + /// The plane to test. + /// The sphere to test. + /// Whether the two objects intersected. + public static PlaneIntersectionType PlaneIntersectsSphere(ref Plane plane, ref BoundingSphere sphere) + { + //Source: Real-Time Collision Detection by Christer Ericson + //Reference: Page 160 + + float distance; + Vector3.Dot(ref plane.Normal, ref sphere.Center, out distance); + distance += plane.D; + + if (distance > sphere.Radius) + return PlaneIntersectionType.Front; + + if (distance < -sphere.Radius) + return PlaneIntersectionType.Back; + + return PlaneIntersectionType.Intersecting; + } + + /* This implementation is wrong + /// + /// Determines whether there is an intersection between a and a triangle. + /// + /// The box to test. + /// The first vertex of the triangle to test. + /// The second vertex of the triangle to test. + /// The third vertex of the triangle to test. + /// Whether the two objects intersected. + public static bool BoxIntersectsTriangle(ref BoundingBox box, ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) + { + if (BoxContainsPoint(ref box, ref vertex1) == ContainmentType.Contains) + return true; + + if (BoxContainsPoint(ref box, ref vertex2) == ContainmentType.Contains) + return true; + + if (BoxContainsPoint(ref box, ref vertex3) == ContainmentType.Contains) + return true; + + return false; + } + */ + + /// + /// Determines whether there is an intersection between a and a . + /// + /// The first box to test. + /// The second box to test. + /// Whether the two objects intersected. + public static bool BoxIntersectsBox(ref BoundingBox box1, ref BoundingBox box2) + { + if (box1.Minimum.X > box2.Maximum.X || box2.Minimum.X > box1.Maximum.X) + return false; + + if (box1.Minimum.Y > box2.Maximum.Y || box2.Minimum.Y > box1.Maximum.Y) + return false; + + if (box1.Minimum.Z > box2.Maximum.Z || box2.Minimum.Z > box1.Maximum.Z) + return false; + + return true; + } + + /// + /// Determines whether there is an intersection between a and a . + /// + /// The box to test. + /// The sphere to test. + /// Whether the two objects intersected. + public static bool BoxIntersectsSphere(ref BoundingBox box, ref BoundingSphere sphere) + { + //Source: Real-Time Collision Detection by Christer Ericson + //Reference: Page 166 + + Vector3 vector; + Vector3.Clamp(ref sphere.Center, ref box.Minimum, ref box.Maximum, out vector); + float distance = Vector3.DistanceSquared(sphere.Center, vector); + + return distance <= sphere.Radius * sphere.Radius; + } + + /// + /// Determines whether there is an intersection between a and a triangle. + /// + /// The sphere to test. + /// The first vertex of the triangle to test. + /// The second vertex of the triangle to test. + /// The third vertex of the triangle to test. + /// Whether the two objects intersected. + public static bool SphereIntersectsTriangle(ref BoundingSphere sphere, ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) + { + //Source: Real-Time Collision Detection by Christer Ericson + //Reference: Page 167 + + Vector3 point; + ClosestPointPointTriangle(ref sphere.Center, ref vertex1, ref vertex2, ref vertex3, out point); + Vector3 v = point - sphere.Center; + + float dot; + Vector3.Dot(ref v, ref v, out dot); + + return dot <= sphere.Radius * sphere.Radius; + } + + /// + /// Determines whether there is an intersection between a and a . + /// + /// First sphere to test. + /// Second sphere to test. + /// Whether the two objects intersected. + public static bool SphereIntersectsSphere(ref BoundingSphere sphere1, ref BoundingSphere sphere2) + { + float radiisum = sphere1.Radius + sphere2.Radius; + return Vector3.DistanceSquared(sphere1.Center, sphere2.Center) <= radiisum * radiisum; + } + + /// + /// Determines whether a contains a point. + /// + /// The box to test. + /// The point to test. + /// The type of containment the two objects have. + public static ContainmentType BoxContainsPoint(ref BoundingBox box, ref Vector3 point) + { + if (box.Minimum.X <= point.X && box.Maximum.X >= point.X && + box.Minimum.Y <= point.Y && box.Maximum.Y >= point.Y && + box.Minimum.Z <= point.Z && box.Maximum.Z >= point.Z) + { + return ContainmentType.Contains; + } + + return ContainmentType.Disjoint; + } + + /* This implementation is wrong + /// + /// Determines whether a contains a triangle. + /// + /// The box to test. + /// The first vertex of the triangle to test. + /// The second vertex of the triangle to test. + /// The third vertex of the triangle to test. + /// The type of containment the two objects have. + public static ContainmentType BoxContainsTriangle(ref BoundingBox box, ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) + { + ContainmentType test1 = BoxContainsPoint(ref box, ref vertex1); + ContainmentType test2 = BoxContainsPoint(ref box, ref vertex2); + ContainmentType test3 = BoxContainsPoint(ref box, ref vertex3); + + if (test1 == ContainmentType.Contains && test2 == ContainmentType.Contains && test3 == ContainmentType.Contains) + return ContainmentType.Contains; + + if (test1 == ContainmentType.Contains || test2 == ContainmentType.Contains || test3 == ContainmentType.Contains) + return ContainmentType.Intersects; + + return ContainmentType.Disjoint; + } + */ + + /// + /// Determines whether a contains a . + /// + /// The first box to test. + /// The second box to test. + /// The type of containment the two objects have. + public static ContainmentType BoxContainsBox(ref BoundingBox box1, ref BoundingBox box2) + { + if (box1.Maximum.X < box2.Minimum.X || box1.Minimum.X > box2.Maximum.X) + return ContainmentType.Disjoint; + + if (box1.Maximum.Y < box2.Minimum.Y || box1.Minimum.Y > box2.Maximum.Y) + return ContainmentType.Disjoint; + + if (box1.Maximum.Z < box2.Minimum.Z || box1.Minimum.Z > box2.Maximum.Z) + return ContainmentType.Disjoint; + + if (box1.Minimum.X <= box2.Minimum.X && (box2.Maximum.X <= box1.Maximum.X && + box1.Minimum.Y <= box2.Minimum.Y && box2.Maximum.Y <= box1.Maximum.Y) && + box1.Minimum.Z <= box2.Minimum.Z && box2.Maximum.Z <= box1.Maximum.Z) + { + return ContainmentType.Contains; + } + + return ContainmentType.Intersects; + } + + /// + /// Determines whether a contains a . + /// + /// The box to test. + /// The sphere to test. + /// The type of containment the two objects have. + public static ContainmentType BoxContainsSphere(ref BoundingBox box, ref BoundingSphere sphere) + { + Vector3 vector; + Vector3.Clamp(ref sphere.Center, ref box.Minimum, ref box.Maximum, out vector); + float distance = Vector3.DistanceSquared(sphere.Center, vector); + + if (distance > sphere.Radius * sphere.Radius) + return ContainmentType.Disjoint; + + if ((((box.Minimum.X + sphere.Radius <= sphere.Center.X) && (sphere.Center.X <= box.Maximum.X - sphere.Radius)) && ((box.Maximum.X - box.Minimum.X > sphere.Radius) && + (box.Minimum.Y + sphere.Radius <= sphere.Center.Y))) && (((sphere.Center.Y <= box.Maximum.Y - sphere.Radius) && (box.Maximum.Y - box.Minimum.Y > sphere.Radius)) && + (((box.Minimum.Z + sphere.Radius <= sphere.Center.Z) && (sphere.Center.Z <= box.Maximum.Z - sphere.Radius)) && (box.Maximum.X - box.Minimum.X > sphere.Radius)))) + { + return ContainmentType.Contains; + } + + return ContainmentType.Intersects; + } + + /// + /// Determines whether a contains a point. + /// + /// The sphere to test. + /// The point to test. + /// The type of containment the two objects have. + public static ContainmentType SphereContainsPoint(ref BoundingSphere sphere, ref Vector3 point) + { + if (Vector3.DistanceSquared(point, sphere.Center) <= sphere.Radius * sphere.Radius) + return ContainmentType.Contains; + + return ContainmentType.Disjoint; + } + + /// + /// Determines whether a contains a triangle. + /// + /// The sphere to test. + /// The first vertex of the triangle to test. + /// The second vertex of the triangle to test. + /// The third vertex of the triangle to test. + /// The type of containment the two objects have. + public static ContainmentType SphereContainsTriangle(ref BoundingSphere sphere, ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) + { + //Source: Jorgy343 + //Reference: None + + ContainmentType test1 = SphereContainsPoint(ref sphere, ref vertex1); + ContainmentType test2 = SphereContainsPoint(ref sphere, ref vertex2); + ContainmentType test3 = SphereContainsPoint(ref sphere, ref vertex3); + + if (test1 == ContainmentType.Contains && test2 == ContainmentType.Contains && test3 == ContainmentType.Contains) + return ContainmentType.Contains; + + if (SphereIntersectsTriangle(ref sphere, ref vertex1, ref vertex2, ref vertex3)) + return ContainmentType.Intersects; + + return ContainmentType.Disjoint; + } + + /// + /// Determines whether a contains a . + /// + /// The sphere to test. + /// The box to test. + /// The type of containment the two objects have. + public static ContainmentType SphereContainsBox(ref BoundingSphere sphere, ref BoundingBox box) + { + Vector3 vector; + + if (!BoxIntersectsSphere(ref box, ref sphere)) + return ContainmentType.Disjoint; + + float radiussquared = sphere.Radius * sphere.Radius; + vector.X = sphere.Center.X - box.Minimum.X; + vector.Y = sphere.Center.Y - box.Maximum.Y; + vector.Z = sphere.Center.Z - box.Maximum.Z; + + if (vector.LengthSquared() > radiussquared) + return ContainmentType.Intersects; + + vector.X = sphere.Center.X - box.Maximum.X; + vector.Y = sphere.Center.Y - box.Maximum.Y; + vector.Z = sphere.Center.Z - box.Maximum.Z; + + if (vector.LengthSquared() > radiussquared) + return ContainmentType.Intersects; + + vector.X = sphere.Center.X - box.Maximum.X; + vector.Y = sphere.Center.Y - box.Minimum.Y; + vector.Z = sphere.Center.Z - box.Maximum.Z; + + if (vector.LengthSquared() > radiussquared) + return ContainmentType.Intersects; + + vector.X = sphere.Center.X - box.Minimum.X; + vector.Y = sphere.Center.Y - box.Minimum.Y; + vector.Z = sphere.Center.Z - box.Maximum.Z; + + if (vector.LengthSquared() > radiussquared) + return ContainmentType.Intersects; + + vector.X = sphere.Center.X - box.Minimum.X; + vector.Y = sphere.Center.Y - box.Maximum.Y; + vector.Z = sphere.Center.Z - box.Minimum.Z; + + if (vector.LengthSquared() > radiussquared) + return ContainmentType.Intersects; + + vector.X = sphere.Center.X - box.Maximum.X; + vector.Y = sphere.Center.Y - box.Maximum.Y; + vector.Z = sphere.Center.Z - box.Minimum.Z; + + if (vector.LengthSquared() > radiussquared) + return ContainmentType.Intersects; + + vector.X = sphere.Center.X - box.Maximum.X; + vector.Y = sphere.Center.Y - box.Minimum.Y; + vector.Z = sphere.Center.Z - box.Minimum.Z; + + if (vector.LengthSquared() > radiussquared) + return ContainmentType.Intersects; + + vector.X = sphere.Center.X - box.Minimum.X; + vector.Y = sphere.Center.Y - box.Minimum.Y; + vector.Z = sphere.Center.Z - box.Minimum.Z; + + if (vector.LengthSquared() > radiussquared) + return ContainmentType.Intersects; + + return ContainmentType.Contains; + } + + /// + /// Determines whether a contains a . + /// + /// The first sphere to test. + /// The second sphere to test. + /// The type of containment the two objects have. + public static ContainmentType SphereContainsSphere(ref BoundingSphere sphere1, ref BoundingSphere sphere2) + { + float distance = Vector3.Distance(sphere1.Center, sphere2.Center); + + if (sphere1.Radius + sphere2.Radius < distance) + return ContainmentType.Disjoint; + + if (sphere1.Radius - sphere2.Radius < distance) + return ContainmentType.Intersects; + + return ContainmentType.Contains; + } + } +} diff --git a/Source/SharpDX/Enums.cs b/Source/SharpDX.Mathematics/Enums.cs similarity index 97% rename from Source/SharpDX/Enums.cs rename to Source/SharpDX.Mathematics/Enums.cs index ad726189c..61dbdfec4 100644 --- a/Source/SharpDX/Enums.cs +++ b/Source/SharpDX.Mathematics/Enums.cs @@ -1,124 +1,124 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ----------------------------------------------------------------------------- -// Original code from SlimMath project. http://code.google.com/p/slimmath/ -// Greetings to SlimDX Group. Original code published with the following license: -// ----------------------------------------------------------------------------- -/* -* Copyright (c) 2007-2011 SlimDX Group -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ -using System; -using System.Collections.Generic; -using System.Text; - -namespace SharpDX -{ - /* - * The enumerations defined in this file are in alphabetical order. When - * adding new enumerations or renaming existing ones, please make sure - * the ordering is maintained. - */ - - /// - /// Describes the type of angle. - /// - public enum AngleType - { - /// - /// Specifies an angle measurement in revolutions. - /// - Revolution, - - /// - /// Specifies an angle measurement in degrees. - /// - Degree, - - /// - /// Specifies an angle measurement in radians. - /// - Radian, - - /// - /// Specifies an angle measurement in gradians. - /// - Gradian - } - - /// - /// Describes how one bounding volume contains another. - /// - public enum ContainmentType - { - /// - /// The two bounding volumes don't intersect at all. - /// - Disjoint, - - /// - /// One bounding volume completely contains another. - /// - Contains, - - /// - /// The two bounding volumes overlap. - /// - Intersects - }; - - /// - /// Describes the result of an intersection with a plane in three dimensions. - /// - public enum PlaneIntersectionType - { - /// - /// The object is behind the plane. - /// - Back, - - /// - /// The object is in front of the plane. - /// - Front, - - /// - /// The object is intersecting the plane. - /// - Intersecting - }; -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from SlimMath project. http://code.google.com/p/slimmath/ +// Greetings to SlimDX Group. Original code published with the following license: +// ----------------------------------------------------------------------------- +/* +* Copyright (c) 2007-2011 SlimDX Group +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SharpDX +{ + /* + * The enumerations defined in this file are in alphabetical order. When + * adding new enumerations or renaming existing ones, please make sure + * the ordering is maintained. + */ + + /// + /// Describes the type of angle. + /// + public enum AngleType + { + /// + /// Specifies an angle measurement in revolutions. + /// + Revolution, + + /// + /// Specifies an angle measurement in degrees. + /// + Degree, + + /// + /// Specifies an angle measurement in radians. + /// + Radian, + + /// + /// Specifies an angle measurement in gradians. + /// + Gradian + } + + /// + /// Describes how one bounding volume contains another. + /// + public enum ContainmentType + { + /// + /// The two bounding volumes don't intersect at all. + /// + Disjoint, + + /// + /// One bounding volume completely contains another. + /// + Contains, + + /// + /// The two bounding volumes overlap. + /// + Intersects + }; + + /// + /// Describes the result of an intersection with a plane in three dimensions. + /// + public enum PlaneIntersectionType + { + /// + /// The object is behind the plane. + /// + Back, + + /// + /// The object is in front of the plane. + /// + Front, + + /// + /// The object is intersecting the plane. + /// + Intersecting + }; +} diff --git a/Source/SharpDX/FrustumCameraParams.cs b/Source/SharpDX.Mathematics/FrustumCameraParams.cs similarity index 100% rename from Source/SharpDX/FrustumCameraParams.cs rename to Source/SharpDX.Mathematics/FrustumCameraParams.cs diff --git a/Source/SharpDX.Mathematics/NamespaceDoc.cs b/Source/SharpDX.Mathematics/NamespaceDoc.cs new file mode 100644 index 000000000..82201775c --- /dev/null +++ b/Source/SharpDX.Mathematics/NamespaceDoc.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +namespace SharpDX.Mathematics +{ + /// + /// The namespace provides managed Direct3D Compiler API. + /// + /// dd607340 + /// Math + /// Math + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + class NamespaceDoc + { + } +} \ No newline at end of file diff --git a/Source/SharpDX/OrientedBoundingBox.cs b/Source/SharpDX.Mathematics/OrientedBoundingBox.cs similarity index 97% rename from Source/SharpDX/OrientedBoundingBox.cs rename to Source/SharpDX.Mathematics/OrientedBoundingBox.cs index 2c1170bb0..7605c0110 100644 --- a/Source/SharpDX/OrientedBoundingBox.cs +++ b/Source/SharpDX.Mathematics/OrientedBoundingBox.cs @@ -1,896 +1,888 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// OrientedBoundingBox (OBB) is a rectangular block, much like an AABB (BoundingBox) but with an arbitrary orientation. - /// - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct OrientedBoundingBox : IEquatable, IFormattable, IDataSerializable - { - /// - /// Half lengths of the box along each axis. - /// - public Vector3 Extents; - - /// - /// The matrix which aligns and scales the box, and its translation vector represents the center of the box. - /// - public Matrix Transformation; - - /// - /// Creates an from a BoundingBox. - /// - /// The BoundingBox to create from. - /// - /// Initially, the OBB is axis-aligned box, but it can be rotated and transformed later. - /// - public OrientedBoundingBox(BoundingBox bb) - { - var Center = bb.Minimum + (bb.Maximum - bb.Minimum) / 2f; - Extents = bb.Maximum - Center; - Transformation = Matrix.Translation(Center); - } - - /// - /// Creates an which contained between two minimum and maximum points. - /// - /// The minimum vertex of the bounding box. - /// The maximum vertex of the bounding box. - /// - /// Initially, the OrientedBoundingBox is axis-aligned box, but it can be rotated and transformed later. - /// - public OrientedBoundingBox(Vector3 minimum, Vector3 maximum) - { - var Center = minimum + (maximum - minimum) / 2f; - Extents = maximum - Center; - Transformation = Matrix.Translation(Center); - } - - /// - /// Creates an that fully contains the given points. - /// - /// The points that will be contained by the box. - /// - /// This method is not for computing the best tight-fitting OrientedBoundingBox. - /// And initially, the OrientedBoundingBox is axis-aligned box, but it can be rotated and transformed later. - /// - public OrientedBoundingBox(Vector3[] points) - { - if (points == null || points.Length == 0) - throw new ArgumentNullException("points"); - - Vector3 minimum = new Vector3(float.MaxValue); - Vector3 maximum = new Vector3(float.MinValue); - - for (int i = 0; i < points.Length; ++i) - { - Vector3.Min(ref minimum, ref points[i], out minimum); - Vector3.Max(ref maximum, ref points[i], out maximum); - } - - var Center = minimum + (maximum - minimum) / 2f; - Extents = maximum - Center; - Transformation = Matrix.Translation(Center); - } - - /// - /// Retrieves the eight corners of the bounding box. - /// - /// An array of points representing the eight corners of the bounding box. - public Vector3[] GetCorners() - { - var xv = new Vector3(Extents.X, 0, 0); - var yv = new Vector3(0, Extents.Y, 0); - var zv = new Vector3(0, 0, Extents.Z); - Vector3.TransformNormal(ref xv, ref Transformation, out xv); - Vector3.TransformNormal(ref yv, ref Transformation, out yv); - Vector3.TransformNormal(ref zv, ref Transformation, out zv); - - var center = Transformation.TranslationVector; - - var corners = new Vector3[8]; - corners[0] = center + xv + yv + zv; - corners[1] = center + xv + yv - zv; - corners[2] = center - xv + yv - zv; - corners[3] = center - xv + yv + zv; - corners[4] = center + xv - yv + zv; - corners[5] = center + xv - yv - zv; - corners[6] = center - xv - yv - zv; - corners[7] = center - xv - yv + zv; - - return corners; - } - - /// - /// Transforms this box using a transformation matrix. - /// - /// The transformation matrix. - /// - /// While any kind of transformation can be applied, it is recommended to apply scaling using scale method instead, which - /// scales the Extents and keeps the Transformation matrix for rotation only, and that preserves collision detection accuracy. - /// - public void Transform(ref Matrix mat) - { - Transformation *= mat; - } - - /// - /// Transforms this box using a transformation matrix. - /// - /// The transformation matrix. - /// - /// While any kind of transformation can be applied, it is recommended to apply scaling using scale method instead, which - /// scales the Extents and keeps the Transformation matrix for rotation only, and that preserves collision detection accuracy. - /// - public void Transform(Matrix mat) - { - Transformation *= mat; - } - - /// - /// Scales the by scaling its Extents without affecting the Transformation matrix, - /// By keeping Transformation matrix scaling-free, the collision detection methods will be more accurate. - /// - /// - public void Scale(ref Vector3 scaling) - { - Extents *= scaling; - } - - /// - /// Scales the by scaling its Extents without affecting the Transformation matrix, - /// By keeping Transformation matrix scaling-free, the collision detection methods will be more accurate. - /// - /// - public void Scale(Vector3 scaling) - { - Extents *= scaling; - } - - /// - /// Scales the by scaling its Extents without affecting the Transformation matrix, - /// By keeping Transformation matrix scaling-free, the collision detection methods will be more accurate. - /// - /// - public void Scale(float scaling) - { - Extents *= scaling; - } - - /// - /// Translates the to a new position using a translation vector; - /// - /// the translation vector. - public void Translate(ref Vector3 translation) - { - Transformation.TranslationVector += translation; - } - - /// - /// Translates the to a new position using a translation vector; - /// - /// the translation vector. - public void Translate(Vector3 translation) - { - Transformation.TranslationVector += translation; - } - - /// - /// The size of the if no scaling is applied to the transformation matrix. - /// - /// - /// The property will return the actual size even if the scaling is applied using Scale method, - /// but if the scaling is applied to transformation matrix, use GetSize Function instead. - /// - public Vector3 Size - { - get - { - return Extents * 2; - } - } - - /// - /// Returns the size of the taking into consideration the scaling applied to the transformation matrix. - /// - /// The size of the consideration - /// - /// This method is computationally expensive, so if no scale is applied to the transformation matrix - /// use property instead. - /// - public Vector3 GetSize() - { - var xv = new Vector3(Extents.X * 2, 0, 0); - var yv = new Vector3(0, Extents.Y * 2, 0); - var zv = new Vector3(0, 0, Extents.Z * 2); - Vector3.TransformNormal(ref xv, ref Transformation, out xv); - Vector3.TransformNormal(ref yv, ref Transformation, out yv); - Vector3.TransformNormal(ref zv, ref Transformation, out zv); - - return new Vector3(xv.Length(), yv.Length(), zv.Length()); - } - - /// - /// Returns the square size of the taking into consideration the scaling applied to the transformation matrix. - /// - /// The size of the consideration - public Vector3 GetSizeSquared() - { - var xv = new Vector3(Extents.X * 2, 0, 0); - var yv = new Vector3(0, Extents.Y * 2, 0); - var zv = new Vector3(0, 0, Extents.Z * 2); - Vector3.TransformNormal(ref xv, ref Transformation, out xv); - Vector3.TransformNormal(ref yv, ref Transformation, out yv); - Vector3.TransformNormal(ref zv, ref Transformation, out zv); - - return new Vector3(xv.LengthSquared(), yv.LengthSquared(), zv.LengthSquared()); - } - - /// - /// Returns the center of the . - /// - public Vector3 Center - { - get - { - return Transformation.TranslationVector; - } - } - - /// - /// Determines whether a contains a point. - /// - /// The point to test. - /// The type of containment the two objects have. - public ContainmentType Contains(ref Vector3 point) - { - // Transform the point into the obb coordinates - Matrix invTrans; - Matrix.Invert(ref Transformation, out invTrans); - - Vector3 locPoint; - Vector3.TransformCoordinate(ref point, ref invTrans, out locPoint); - - locPoint.X = Math.Abs(locPoint.X); - locPoint.Y = Math.Abs(locPoint.Y); - locPoint.Z = Math.Abs(locPoint.Z); - - //Simple axes-aligned BB check - if (MathUtil.NearEqual(locPoint.X, Extents.X) && MathUtil.NearEqual(locPoint.Y, Extents.Y) && MathUtil.NearEqual(locPoint.Z, Extents.Z)) - return ContainmentType.Intersects; - if (locPoint.X < Extents.X && locPoint.Y < Extents.Y && locPoint.Z < Extents.Z) - return ContainmentType.Contains; - else - return ContainmentType.Disjoint; - } - - /// - /// Determines whether a contains a point. - /// - /// The point to test. - /// The type of containment the two objects have. - public ContainmentType Contains(Vector3 point) - { - return Contains(ref point); - } - - /// - /// Determines whether a contains an array of points>. - /// - /// The points array to test. - /// The type of containment. - public ContainmentType Contains(Vector3[] points) - { - Matrix invTrans; - Matrix.Invert(ref Transformation, out invTrans); - - var containsAll = true; - var containsAny = false; - - for (int i = 0; i < points.Length; i++) - { - Vector3 locPoint; - Vector3.TransformCoordinate(ref points[i], ref invTrans, out locPoint); - - locPoint.X = Math.Abs(locPoint.X); - locPoint.Y = Math.Abs(locPoint.Y); - locPoint.Z = Math.Abs(locPoint.Z); - - //Simple axes-aligned BB check - if (MathUtil.NearEqual(locPoint.X, Extents.X) && - MathUtil.NearEqual(locPoint.Y, Extents.Y) && - MathUtil.NearEqual(locPoint.Z, Extents.Z)) - containsAny = true; - if (locPoint.X < Extents.X && locPoint.Y < Extents.Y && locPoint.Z < Extents.Z) - containsAny = true; - else - containsAll = false; - } - - if (containsAll) - return ContainmentType.Contains; - else if (containsAny) - return ContainmentType.Intersects; - else - return ContainmentType.Disjoint; - } - - /// - /// Determines whether a contains a . - /// - /// The sphere to test. - /// Optimize the check operation by assuming that has no scaling applied - /// The type of containment the two objects have. - /// - /// This method is not designed for which has a non-uniform scaling applied to its transformation matrix. - /// But any type of scaling applied using Scale method will keep this method accurate. - /// - public ContainmentType Contains(BoundingSphere sphere, bool IgnoreScale = false) - { - Matrix invTrans; - Matrix.Invert(ref Transformation, out invTrans); - - // Transform sphere center into the obb coordinates - Vector3 locCenter; - Vector3.TransformCoordinate(ref sphere.Center, ref invTrans, out locCenter); - - float locRadius; - if (IgnoreScale) - locRadius = sphere.Radius; - else - { - // Transform sphere radius into the obb coordinates - Vector3 vRadius = Vector3.UnitX * sphere.Radius; - Vector3.TransformNormal(ref vRadius, ref invTrans, out vRadius); - locRadius = vRadius.Length(); - } - - //Perform regular BoundingBox to BoundingSphere containment check - Vector3 minusExtens = -Extents; - Vector3 vector; - Vector3.Clamp(ref locCenter, ref minusExtens, ref Extents, out vector); - float distance = Vector3.DistanceSquared(locCenter, vector); - - if (distance > locRadius * locRadius) - return ContainmentType.Disjoint; - - if ((((minusExtens.X + locRadius <= locCenter.X) && (locCenter.X <= Extents.X - locRadius)) && ((Extents.X - minusExtens.X > locRadius) && - (minusExtens.Y + locRadius <= locCenter.Y))) && (((locCenter.Y <= Extents.Y - locRadius) && (Extents.Y - minusExtens.Y > locRadius)) && - (((minusExtens.Z + locRadius <= locCenter.Z) && (locCenter.Z <= Extents.Z - locRadius)) && (Extents.X - minusExtens.X > locRadius)))) - { - return ContainmentType.Contains; - } - - return ContainmentType.Intersects; - } - - private static Vector3[] GetRows(ref Matrix mat) - { - return new Vector3[] { - new Vector3(mat.M11,mat.M12,mat.M13), - new Vector3(mat.M21,mat.M22,mat.M23), - new Vector3(mat.M31,mat.M32,mat.M33) - }; - } - - /// - /// Check the intersection between two - /// - /// The OrientedBoundingBoxs to test. - /// The type of containment the two objects have. - /// - /// For accuracy, The transformation matrix for both must not have any scaling applied to it. - /// Anyway, scaling using Scale method will keep this method accurate. - /// - public ContainmentType Contains(ref OrientedBoundingBox obb) - { - var cornersCheck = Contains(obb.GetCorners()); - if (cornersCheck != ContainmentType.Disjoint) - return cornersCheck; - - //http://www.3dkingdoms.com/weekly/bbox.cpp - var SizeA = Extents; - var SizeB = obb.Extents; - var RotA = GetRows(ref Transformation); - var RotB = GetRows(ref obb.Transformation); - - var R = new Matrix(); // Rotation from B to A - var AR = new Matrix(); // absolute values of R matrix, to use with box extents - - float ExtentA, ExtentB, Separation; - int i, k; - - // Calculate B to A rotation matrix - for (i = 0; i < 3; i++) - for (k = 0; k < 3; k++) - { - R[i, k] = Vector3.Dot(RotA[i], RotB[k]); - AR[i, k] = Math.Abs(R[i, k]); - } - - - // Vector separating the centers of Box B and of Box A - var vSepWS = obb.Center - Center; - // Rotated into Box A's coordinates - var vSepA = new Vector3(Vector3.Dot(vSepWS, RotA[0]), Vector3.Dot(vSepWS, RotA[1]), Vector3.Dot(vSepWS, RotA[2])); - - // Test if any of A's basis vectors separate the box - for (i = 0; i < 3; i++) - { - ExtentA = SizeA[i]; - ExtentB = Vector3.Dot(SizeB, new Vector3(AR[i, 0], AR[i, 1], AR[i, 2])); - Separation = Math.Abs(vSepA[i]); - - if (Separation > ExtentA + ExtentB) - return ContainmentType.Disjoint; - } - - // Test if any of B's basis vectors separate the box - for (k = 0; k < 3; k++) - { - ExtentA = Vector3.Dot(SizeA, new Vector3(AR[0, k], AR[1, k], AR[2, k])); - ExtentB = SizeB[k]; - Separation = Math.Abs(Vector3.Dot(vSepA, new Vector3(R[0, k], R[1, k], R[2, k]))); - - if (Separation > ExtentA + ExtentB) - return ContainmentType.Disjoint; - } - - // Now test Cross Products of each basis vector combination ( A[i], B[k] ) - for (i = 0; i < 3; i++) - for (k = 0; k < 3; k++) - { - int i1 = (i + 1) % 3, i2 = (i + 2) % 3; - int k1 = (k + 1) % 3, k2 = (k + 2) % 3; - ExtentA = SizeA[i1] * AR[i2, k] + SizeA[i2] * AR[i1, k]; - ExtentB = SizeB[k1] * AR[i, k2] + SizeB[k2] * AR[i, k1]; - Separation = Math.Abs(vSepA[i2] * R[i1, k] - vSepA[i1] * R[i2, k]); - if (Separation > ExtentA + ExtentB) - return ContainmentType.Disjoint; - } - - // No separating axis found, the boxes overlap - return ContainmentType.Intersects; - } - - /// - /// Check the intersection between an and a line defined by two points - /// - /// The first point in the line. - /// The second point in the line. - /// The type of containment the two objects have. - /// - /// For accuracy, The transformation matrix for the must not have any scaling applied to it. - /// Anyway, scaling using Scale method will keep this method accurate. - /// - public ContainmentType ContainsLine(ref Vector3 L1, ref Vector3 L2) - { - var cornersCheck = Contains(new Vector3[] { L1, L2 }); - if (cornersCheck != ContainmentType.Disjoint) - return cornersCheck; - - //http://www.3dkingdoms.com/weekly/bbox.cpp - // Put line in box space - Matrix invTrans; - Matrix.Invert(ref Transformation, out invTrans); - - Vector3 LB1; - Vector3.TransformCoordinate(ref L1, ref invTrans, out LB1); - Vector3 LB2; - Vector3.TransformCoordinate(ref L1, ref invTrans, out LB2); - - // Get line midpoint and extent - var LMid = (LB1 + LB2) * 0.5f; - var L = (LB1 - LMid); - var LExt = new Vector3(Math.Abs(L.X), Math.Abs(L.Y), Math.Abs(L.Z)); - - // Use Separating Axis Test - // Separation vector from box center to line center is LMid, since the line is in box space - if (Math.Abs(LMid.X) > Extents.X + LExt.X) return ContainmentType.Disjoint; - if (Math.Abs(LMid.Y) > Extents.Y + LExt.Y) return ContainmentType.Disjoint; - if (Math.Abs(LMid.Z) > Extents.Z + LExt.Z) return ContainmentType.Disjoint; - // Cross products of line and each axis - if (Math.Abs(LMid.Y * L.Z - LMid.Z * L.Y) > (Extents.Y * LExt.Z + Extents.Z * LExt.Y)) return ContainmentType.Disjoint; - if (Math.Abs(LMid.X * L.Z - LMid.Z * L.X) > (Extents.X * LExt.Z + Extents.Z * LExt.X)) return ContainmentType.Disjoint; - if (Math.Abs(LMid.X * L.Y - LMid.Y * L.X) > (Extents.X * LExt.Y + Extents.Y * LExt.X)) return ContainmentType.Disjoint; - // No separating axis, the line intersects - return ContainmentType.Intersects; - } - - /// - /// Check the intersection between an and - /// - /// The BoundingBox to test. - /// The type of containment the two objects have. - /// - /// For accuracy, The transformation matrix for the must not have any scaling applied to it. - /// Anyway, scaling using Scale method will keep this method accurate. - /// - public ContainmentType Contains(ref BoundingBox box) - { - var cornersCheck = Contains(box.GetCorners()); - if (cornersCheck != ContainmentType.Disjoint) - return cornersCheck; - - var boxCenter = box.Minimum + (box.Maximum - box.Minimum) / 2f; - var boxExtents = box.Maximum - boxCenter; - - var SizeA = Extents; - var SizeB = boxExtents; - var RotA = GetRows(ref Transformation); - - float ExtentA, ExtentB, Separation; - int i, k; - - Matrix R; // Rotation from B to A - Matrix.Invert(ref Transformation, out R); - var AR = new Matrix(); // absolute values of R matrix, to use with box extents - - for (i = 0; i < 3; i++) - for (k = 0; k < 3; k++) - { - AR[i, k] = Math.Abs(R[i, k]); - } - - - // Vector separating the centers of Box B and of Box A - var vSepWS = boxCenter - Center; - // Rotated into Box A's coordinates - var vSepA = new Vector3(Vector3.Dot(vSepWS, RotA[0]), Vector3.Dot(vSepWS, RotA[1]), Vector3.Dot(vSepWS, RotA[2])); - - // Test if any of A's basis vectors separate the box - for (i = 0; i < 3; i++) - { - ExtentA = SizeA[i]; - ExtentB = Vector3.Dot(SizeB, new Vector3(AR[i, 0], AR[i, 1], AR[i, 2])); - Separation = Math.Abs(vSepA[i]); - - if (Separation > ExtentA + ExtentB) - return ContainmentType.Disjoint; - } - - // Test if any of B's basis vectors separate the box - for (k = 0; k < 3; k++) - { - ExtentA = Vector3.Dot(SizeA, new Vector3(AR[0, k], AR[1, k], AR[2, k])); - ExtentB = SizeB[k]; - Separation = Math.Abs(Vector3.Dot(vSepA, new Vector3(R[0, k], R[1, k], R[2, k]))); - - if (Separation > ExtentA + ExtentB) - return ContainmentType.Disjoint; - } - - // Now test Cross Products of each basis vector combination ( A[i], B[k] ) - for (i = 0; i < 3; i++) - for (k = 0; k < 3; k++) - { - int i1 = (i + 1) % 3, i2 = (i + 2) % 3; - int k1 = (k + 1) % 3, k2 = (k + 2) % 3; - ExtentA = SizeA[i1] * AR[i2, k] + SizeA[i2] * AR[i1, k]; - ExtentB = SizeB[k1] * AR[i, k2] + SizeB[k2] * AR[i, k1]; - Separation = Math.Abs(vSepA[i2] * R[i1, k] - vSepA[i1] * R[i2, k]); - if (Separation > ExtentA + ExtentB) - return ContainmentType.Disjoint; - } - - // No separating axis found, the boxes overlap - return ContainmentType.Intersects; - } - - /// - /// Determines whether there is an intersection between a and a . - /// - /// The ray to test. - /// When the method completes, contains the point of intersection, - /// or if there was no intersection. - /// Whether the two objects intersected. - public bool Intersects(ref Ray ray, out Vector3 point) - { - // Put ray in box space - Matrix invTrans; - Matrix.Invert(ref Transformation, out invTrans); - - Ray bRay; - Vector3.TransformNormal(ref ray.Direction, ref invTrans, out bRay.Direction); - Vector3.TransformCoordinate(ref ray.Position, ref invTrans, out bRay.Position); - - //Perform a regular ray to BoundingBox check - var bb = new BoundingBox(-Extents, Extents); - var intersects = Collision.RayIntersectsBox(ref bRay, ref bb, out point); - - //Put the result intersection back to world - if (intersects) - Vector3.TransformCoordinate(ref point, ref Transformation, out point); - - return intersects; - } - - /// - /// Determines whether there is an intersection between a and a . - /// - /// The ray to test. - /// Whether the two objects intersected. - public bool Intersects(ref Ray ray) - { - Vector3 point; - return Intersects(ref ray, out point); - } - - private Vector3[] GetLocalCorners() - { - var xv = new Vector3(Extents.X, 0, 0); - var yv = new Vector3(0, Extents.Y, 0); - var zv = new Vector3(0, 0, Extents.Z); - - var corners = new Vector3[8]; - corners[0] = +xv + yv + zv; - corners[1] = +xv + yv - zv; - corners[2] = -xv + yv - zv; - corners[3] = -xv + yv + zv; - corners[4] = +xv - yv + zv; - corners[5] = +xv - yv - zv; - corners[6] = -xv - yv - zv; - corners[7] = -xv - yv + zv; - - return corners; - } - - /// - /// Get the axis-aligned which contains all corners. - /// - /// The axis-aligned BoundingBox of this OrientedBoundingBox. - public BoundingBox GetBoundingBox() - { - return BoundingBox.FromPoints(GetCorners()); - } - - /// - /// Calculates the matrix required to transfer any point from one local coordinates to another. - /// - /// The source OrientedBoundingBox. - /// The target OrientedBoundingBox. - /// - /// If true, the method will use a fast algorithm which is inapplicable if a scale is applied to the transformation matrix of the OrientedBoundingBox. - /// - /// - public static Matrix GetBoxToBoxMatrix(ref OrientedBoundingBox A, ref OrientedBoundingBox B, bool NoMatrixScaleApplied = false) - { - Matrix AtoB_Matrix; - - // Calculate B to A transformation matrix - if (NoMatrixScaleApplied) - { - var RotA = GetRows(ref A.Transformation); - var RotB = GetRows(ref B.Transformation); - AtoB_Matrix = new Matrix(); - int i, k; - for (i = 0; i < 3; i++) - for (k = 0; k < 3; k++) - AtoB_Matrix[i, k] = Vector3.Dot(RotB[i], RotA[k]); - var v = B.Center - A.Center; - AtoB_Matrix.M41 = Vector3.Dot(v, RotA[0]); - AtoB_Matrix.M42 = Vector3.Dot(v, RotA[1]); - AtoB_Matrix.M43 = Vector3.Dot(v, RotA[2]); - AtoB_Matrix.M44 = 1; - } - else - { - Matrix AInvMat; - Matrix.Invert(ref A.Transformation, out AInvMat); - AtoB_Matrix = B.Transformation * AInvMat; - } - - return AtoB_Matrix; - } - - /// - /// Merge an OrientedBoundingBox B into another OrientedBoundingBox A, by expanding A to contain B and keeping A orientation. - /// - /// The to merge into it. - /// The to be merged - /// - /// If true, the method will use a fast algorithm which is inapplicable if a scale is applied to the transformation matrix of the OrientedBoundingBox. - /// - /// - /// Unlike merging axis aligned boxes, The operation is not interchangeable, because it keeps A orientation and merge B into it. - /// - public static void Merge(ref OrientedBoundingBox A, ref OrientedBoundingBox B, bool NoMatrixScaleApplied = false) - { - Matrix AtoB_Matrix = GetBoxToBoxMatrix(ref A, ref B, NoMatrixScaleApplied); - - //Get B corners in A Space - var bCorners = B.GetLocalCorners(); - Vector3.TransformCoordinate(bCorners, ref AtoB_Matrix, bCorners); - - //Get A local Bounding Box - var A_LocalBB = new BoundingBox(-A.Extents, A.Extents); - - //Find B BoundingBox in A Space - var B_LocalBB = BoundingBox.FromPoints(bCorners); - - //Merger A and B local Bounding Boxes - BoundingBox mergedBB; - BoundingBox.Merge(ref B_LocalBB, ref A_LocalBB, out mergedBB); - - //Find the new Extents and Center, Transform Center back to world - var newCenter = mergedBB.Minimum + (mergedBB.Maximum - mergedBB.Minimum) / 2f; - A.Extents = mergedBB.Maximum - newCenter; - Vector3.TransformCoordinate(ref newCenter, ref A.Transformation, out newCenter); - A.Transformation.TranslationVector = newCenter; - } - - /// - /// Merge this OrientedBoundingBox into another OrientedBoundingBox, keeping the other OrientedBoundingBox orientation. - /// - /// The other to merge into. - /// - /// If true, the method will use a fast algorithm which is inapplicable if a scale is applied to the transformation matrix of the OrientedBoundingBox. - /// - public void MergeInto(ref OrientedBoundingBox OBB, bool NoMatrixScaleApplied = false) - { - Merge(ref OBB, ref this, NoMatrixScaleApplied); - } - - /// - /// Merge another OrientedBoundingBox into this OrientedBoundingBox. - /// - /// The other to merge into this OrientedBoundingBox. - /// - /// If true, the method will use a fast algorithm which is inapplicable if a scale is applied to the transformation matrix of the OrientedBoundingBox. - /// - public void Add(ref OrientedBoundingBox OBB, bool NoMatrixScaleApplied = false) - { - Merge(ref this, ref OBB, NoMatrixScaleApplied); - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(OrientedBoundingBox value) - { - return Extents == value.Extents && Transformation == value.Transformation; - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object value) - { - if (value == null) - return false; - - if (!ReferenceEquals(value.GetType(), typeof(OrientedBoundingBox))) - return false; - - return Equals((OrientedBoundingBox)value); - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has the same value as ; otherwise, false. - public static bool operator ==(OrientedBoundingBox left, OrientedBoundingBox right) - { - return left.Equals(right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has a different value than ; otherwise, false. - public static bool operator !=(OrientedBoundingBox left, OrientedBoundingBox right) - { - return !left.Equals(right); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - return Extents.GetHashCode() + Transformation.GetHashCode(); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return String.Format(CultureInfo.CurrentCulture, "Center: {0}, Extents: {1}", Center, Extents); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// - /// A that represents this instance. - /// - public string ToString(string format) - { - if (format == null) - return ToString(); - - return string.Format(CultureInfo.CurrentCulture, "Center: {0}, Extents: {1}", Center.ToString(format, CultureInfo.CurrentCulture), - Extents.ToString(format, CultureInfo.CurrentCulture)); - } - - /// - /// Returns a that represents this instance. - /// - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(IFormatProvider formatProvider) - { - return string.Format(formatProvider, "Center: {0}, Extents: {1}", Center.ToString(), Extents.ToString()); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - if (format == null) - return ToString(formatProvider); - - return string.Format(formatProvider, "Center: {0}, Extents: {1}", Center.ToString(format, formatProvider), - Extents.ToString(format, formatProvider)); - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - serializer.Serialize(ref Extents); - serializer.Serialize(ref Transformation); - } - } -} - +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// OrientedBoundingBox (OBB) is a rectangular block, much like an AABB (BoundingBox) but with an arbitrary orientation. + /// + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct OrientedBoundingBox : IEquatable, IFormattable + { + /// + /// Half lengths of the box along each axis. + /// + public Vector3 Extents; + + /// + /// The matrix which aligns and scales the box, and its translation vector represents the center of the box. + /// + public Matrix Transformation; + + /// + /// Creates an from a BoundingBox. + /// + /// The BoundingBox to create from. + /// + /// Initially, the OBB is axis-aligned box, but it can be rotated and transformed later. + /// + public OrientedBoundingBox(BoundingBox bb) + { + var Center = bb.Minimum + (bb.Maximum - bb.Minimum) / 2f; + Extents = bb.Maximum - Center; + Transformation = Matrix.Translation(Center); + } + + /// + /// Creates an which contained between two minimum and maximum points. + /// + /// The minimum vertex of the bounding box. + /// The maximum vertex of the bounding box. + /// + /// Initially, the OrientedBoundingBox is axis-aligned box, but it can be rotated and transformed later. + /// + public OrientedBoundingBox(Vector3 minimum, Vector3 maximum) + { + var Center = minimum + (maximum - minimum) / 2f; + Extents = maximum - Center; + Transformation = Matrix.Translation(Center); + } + + /// + /// Creates an that fully contains the given points. + /// + /// The points that will be contained by the box. + /// + /// This method is not for computing the best tight-fitting OrientedBoundingBox. + /// And initially, the OrientedBoundingBox is axis-aligned box, but it can be rotated and transformed later. + /// + public OrientedBoundingBox(Vector3[] points) + { + if (points == null || points.Length == 0) + throw new ArgumentNullException("points"); + + Vector3 minimum = new Vector3(float.MaxValue); + Vector3 maximum = new Vector3(float.MinValue); + + for (int i = 0; i < points.Length; ++i) + { + Vector3.Min(ref minimum, ref points[i], out minimum); + Vector3.Max(ref maximum, ref points[i], out maximum); + } + + var Center = minimum + (maximum - minimum) / 2f; + Extents = maximum - Center; + Transformation = Matrix.Translation(Center); + } + + /// + /// Retrieves the eight corners of the bounding box. + /// + /// An array of points representing the eight corners of the bounding box. + public Vector3[] GetCorners() + { + var xv = new Vector3(Extents.X, 0, 0); + var yv = new Vector3(0, Extents.Y, 0); + var zv = new Vector3(0, 0, Extents.Z); + Vector3.TransformNormal(ref xv, ref Transformation, out xv); + Vector3.TransformNormal(ref yv, ref Transformation, out yv); + Vector3.TransformNormal(ref zv, ref Transformation, out zv); + + var center = Transformation.TranslationVector; + + var corners = new Vector3[8]; + corners[0] = center + xv + yv + zv; + corners[1] = center + xv + yv - zv; + corners[2] = center - xv + yv - zv; + corners[3] = center - xv + yv + zv; + corners[4] = center + xv - yv + zv; + corners[5] = center + xv - yv - zv; + corners[6] = center - xv - yv - zv; + corners[7] = center - xv - yv + zv; + + return corners; + } + + /// + /// Transforms this box using a transformation matrix. + /// + /// The transformation matrix. + /// + /// While any kind of transformation can be applied, it is recommended to apply scaling using scale method instead, which + /// scales the Extents and keeps the Transformation matrix for rotation only, and that preserves collision detection accuracy. + /// + public void Transform(ref Matrix mat) + { + Transformation *= mat; + } + + /// + /// Transforms this box using a transformation matrix. + /// + /// The transformation matrix. + /// + /// While any kind of transformation can be applied, it is recommended to apply scaling using scale method instead, which + /// scales the Extents and keeps the Transformation matrix for rotation only, and that preserves collision detection accuracy. + /// + public void Transform(Matrix mat) + { + Transformation *= mat; + } + + /// + /// Scales the by scaling its Extents without affecting the Transformation matrix, + /// By keeping Transformation matrix scaling-free, the collision detection methods will be more accurate. + /// + /// + public void Scale(ref Vector3 scaling) + { + Extents *= scaling; + } + + /// + /// Scales the by scaling its Extents without affecting the Transformation matrix, + /// By keeping Transformation matrix scaling-free, the collision detection methods will be more accurate. + /// + /// + public void Scale(Vector3 scaling) + { + Extents *= scaling; + } + + /// + /// Scales the by scaling its Extents without affecting the Transformation matrix, + /// By keeping Transformation matrix scaling-free, the collision detection methods will be more accurate. + /// + /// + public void Scale(float scaling) + { + Extents *= scaling; + } + + /// + /// Translates the to a new position using a translation vector; + /// + /// the translation vector. + public void Translate(ref Vector3 translation) + { + Transformation.TranslationVector += translation; + } + + /// + /// Translates the to a new position using a translation vector; + /// + /// the translation vector. + public void Translate(Vector3 translation) + { + Transformation.TranslationVector += translation; + } + + /// + /// The size of the if no scaling is applied to the transformation matrix. + /// + /// + /// The property will return the actual size even if the scaling is applied using Scale method, + /// but if the scaling is applied to transformation matrix, use GetSize Function instead. + /// + public Vector3 Size + { + get + { + return Extents * 2; + } + } + + /// + /// Returns the size of the taking into consideration the scaling applied to the transformation matrix. + /// + /// The size of the consideration + /// + /// This method is computationally expensive, so if no scale is applied to the transformation matrix + /// use property instead. + /// + public Vector3 GetSize() + { + var xv = new Vector3(Extents.X * 2, 0, 0); + var yv = new Vector3(0, Extents.Y * 2, 0); + var zv = new Vector3(0, 0, Extents.Z * 2); + Vector3.TransformNormal(ref xv, ref Transformation, out xv); + Vector3.TransformNormal(ref yv, ref Transformation, out yv); + Vector3.TransformNormal(ref zv, ref Transformation, out zv); + + return new Vector3(xv.Length(), yv.Length(), zv.Length()); + } + + /// + /// Returns the square size of the taking into consideration the scaling applied to the transformation matrix. + /// + /// The size of the consideration + public Vector3 GetSizeSquared() + { + var xv = new Vector3(Extents.X * 2, 0, 0); + var yv = new Vector3(0, Extents.Y * 2, 0); + var zv = new Vector3(0, 0, Extents.Z * 2); + Vector3.TransformNormal(ref xv, ref Transformation, out xv); + Vector3.TransformNormal(ref yv, ref Transformation, out yv); + Vector3.TransformNormal(ref zv, ref Transformation, out zv); + + return new Vector3(xv.LengthSquared(), yv.LengthSquared(), zv.LengthSquared()); + } + + /// + /// Returns the center of the . + /// + public Vector3 Center + { + get + { + return Transformation.TranslationVector; + } + } + + /// + /// Determines whether a contains a point. + /// + /// The point to test. + /// The type of containment the two objects have. + public ContainmentType Contains(ref Vector3 point) + { + // Transform the point into the obb coordinates + Matrix invTrans; + Matrix.Invert(ref Transformation, out invTrans); + + Vector3 locPoint; + Vector3.TransformCoordinate(ref point, ref invTrans, out locPoint); + + locPoint.X = Math.Abs(locPoint.X); + locPoint.Y = Math.Abs(locPoint.Y); + locPoint.Z = Math.Abs(locPoint.Z); + + //Simple axes-aligned BB check + if (MathUtil.NearEqual(locPoint.X, Extents.X) && MathUtil.NearEqual(locPoint.Y, Extents.Y) && MathUtil.NearEqual(locPoint.Z, Extents.Z)) + return ContainmentType.Intersects; + if (locPoint.X < Extents.X && locPoint.Y < Extents.Y && locPoint.Z < Extents.Z) + return ContainmentType.Contains; + else + return ContainmentType.Disjoint; + } + + /// + /// Determines whether a contains a point. + /// + /// The point to test. + /// The type of containment the two objects have. + public ContainmentType Contains(Vector3 point) + { + return Contains(ref point); + } + + /// + /// Determines whether a contains an array of points>. + /// + /// The points array to test. + /// The type of containment. + public ContainmentType Contains(Vector3[] points) + { + Matrix invTrans; + Matrix.Invert(ref Transformation, out invTrans); + + var containsAll = true; + var containsAny = false; + + for (int i = 0; i < points.Length; i++) + { + Vector3 locPoint; + Vector3.TransformCoordinate(ref points[i], ref invTrans, out locPoint); + + locPoint.X = Math.Abs(locPoint.X); + locPoint.Y = Math.Abs(locPoint.Y); + locPoint.Z = Math.Abs(locPoint.Z); + + //Simple axes-aligned BB check + if (MathUtil.NearEqual(locPoint.X, Extents.X) && + MathUtil.NearEqual(locPoint.Y, Extents.Y) && + MathUtil.NearEqual(locPoint.Z, Extents.Z)) + containsAny = true; + if (locPoint.X < Extents.X && locPoint.Y < Extents.Y && locPoint.Z < Extents.Z) + containsAny = true; + else + containsAll = false; + } + + if (containsAll) + return ContainmentType.Contains; + else if (containsAny) + return ContainmentType.Intersects; + else + return ContainmentType.Disjoint; + } + + /// + /// Determines whether a contains a . + /// + /// The sphere to test. + /// Optimize the check operation by assuming that has no scaling applied + /// The type of containment the two objects have. + /// + /// This method is not designed for which has a non-uniform scaling applied to its transformation matrix. + /// But any type of scaling applied using Scale method will keep this method accurate. + /// + public ContainmentType Contains(BoundingSphere sphere, bool IgnoreScale = false) + { + Matrix invTrans; + Matrix.Invert(ref Transformation, out invTrans); + + // Transform sphere center into the obb coordinates + Vector3 locCenter; + Vector3.TransformCoordinate(ref sphere.Center, ref invTrans, out locCenter); + + float locRadius; + if (IgnoreScale) + locRadius = sphere.Radius; + else + { + // Transform sphere radius into the obb coordinates + Vector3 vRadius = Vector3.UnitX * sphere.Radius; + Vector3.TransformNormal(ref vRadius, ref invTrans, out vRadius); + locRadius = vRadius.Length(); + } + + //Perform regular BoundingBox to BoundingSphere containment check + Vector3 minusExtens = -Extents; + Vector3 vector; + Vector3.Clamp(ref locCenter, ref minusExtens, ref Extents, out vector); + float distance = Vector3.DistanceSquared(locCenter, vector); + + if (distance > locRadius * locRadius) + return ContainmentType.Disjoint; + + if ((((minusExtens.X + locRadius <= locCenter.X) && (locCenter.X <= Extents.X - locRadius)) && ((Extents.X - minusExtens.X > locRadius) && + (minusExtens.Y + locRadius <= locCenter.Y))) && (((locCenter.Y <= Extents.Y - locRadius) && (Extents.Y - minusExtens.Y > locRadius)) && + (((minusExtens.Z + locRadius <= locCenter.Z) && (locCenter.Z <= Extents.Z - locRadius)) && (Extents.X - minusExtens.X > locRadius)))) + { + return ContainmentType.Contains; + } + + return ContainmentType.Intersects; + } + + private static Vector3[] GetRows(ref Matrix mat) + { + return new Vector3[] { + new Vector3(mat.M11,mat.M12,mat.M13), + new Vector3(mat.M21,mat.M22,mat.M23), + new Vector3(mat.M31,mat.M32,mat.M33) + }; + } + + /// + /// Check the intersection between two + /// + /// The OrientedBoundingBoxs to test. + /// The type of containment the two objects have. + /// + /// For accuracy, The transformation matrix for both must not have any scaling applied to it. + /// Anyway, scaling using Scale method will keep this method accurate. + /// + public ContainmentType Contains(ref OrientedBoundingBox obb) + { + var cornersCheck = Contains(obb.GetCorners()); + if (cornersCheck != ContainmentType.Disjoint) + return cornersCheck; + + //http://www.3dkingdoms.com/weekly/bbox.cpp + var SizeA = Extents; + var SizeB = obb.Extents; + var RotA = GetRows(ref Transformation); + var RotB = GetRows(ref obb.Transformation); + + var R = new Matrix(); // Rotation from B to A + var AR = new Matrix(); // absolute values of R matrix, to use with box extents + + float ExtentA, ExtentB, Separation; + int i, k; + + // Calculate B to A rotation matrix + for (i = 0; i < 3; i++) + for (k = 0; k < 3; k++) + { + R[i, k] = Vector3.Dot(RotA[i], RotB[k]); + AR[i, k] = Math.Abs(R[i, k]); + } + + + // Vector separating the centers of Box B and of Box A + var vSepWS = obb.Center - Center; + // Rotated into Box A's coordinates + var vSepA = new Vector3(Vector3.Dot(vSepWS, RotA[0]), Vector3.Dot(vSepWS, RotA[1]), Vector3.Dot(vSepWS, RotA[2])); + + // Test if any of A's basis vectors separate the box + for (i = 0; i < 3; i++) + { + ExtentA = SizeA[i]; + ExtentB = Vector3.Dot(SizeB, new Vector3(AR[i, 0], AR[i, 1], AR[i, 2])); + Separation = Math.Abs(vSepA[i]); + + if (Separation > ExtentA + ExtentB) + return ContainmentType.Disjoint; + } + + // Test if any of B's basis vectors separate the box + for (k = 0; k < 3; k++) + { + ExtentA = Vector3.Dot(SizeA, new Vector3(AR[0, k], AR[1, k], AR[2, k])); + ExtentB = SizeB[k]; + Separation = Math.Abs(Vector3.Dot(vSepA, new Vector3(R[0, k], R[1, k], R[2, k]))); + + if (Separation > ExtentA + ExtentB) + return ContainmentType.Disjoint; + } + + // Now test Cross Products of each basis vector combination ( A[i], B[k] ) + for (i = 0; i < 3; i++) + for (k = 0; k < 3; k++) + { + int i1 = (i + 1) % 3, i2 = (i + 2) % 3; + int k1 = (k + 1) % 3, k2 = (k + 2) % 3; + ExtentA = SizeA[i1] * AR[i2, k] + SizeA[i2] * AR[i1, k]; + ExtentB = SizeB[k1] * AR[i, k2] + SizeB[k2] * AR[i, k1]; + Separation = Math.Abs(vSepA[i2] * R[i1, k] - vSepA[i1] * R[i2, k]); + if (Separation > ExtentA + ExtentB) + return ContainmentType.Disjoint; + } + + // No separating axis found, the boxes overlap + return ContainmentType.Intersects; + } + + /// + /// Check the intersection between an and a line defined by two points + /// + /// The first point in the line. + /// The second point in the line. + /// The type of containment the two objects have. + /// + /// For accuracy, The transformation matrix for the must not have any scaling applied to it. + /// Anyway, scaling using Scale method will keep this method accurate. + /// + public ContainmentType ContainsLine(ref Vector3 L1, ref Vector3 L2) + { + var cornersCheck = Contains(new Vector3[] { L1, L2 }); + if (cornersCheck != ContainmentType.Disjoint) + return cornersCheck; + + //http://www.3dkingdoms.com/weekly/bbox.cpp + // Put line in box space + Matrix invTrans; + Matrix.Invert(ref Transformation, out invTrans); + + Vector3 LB1; + Vector3.TransformCoordinate(ref L1, ref invTrans, out LB1); + Vector3 LB2; + Vector3.TransformCoordinate(ref L1, ref invTrans, out LB2); + + // Get line midpoint and extent + var LMid = (LB1 + LB2) * 0.5f; + var L = (LB1 - LMid); + var LExt = new Vector3(Math.Abs(L.X), Math.Abs(L.Y), Math.Abs(L.Z)); + + // Use Separating Axis Test + // Separation vector from box center to line center is LMid, since the line is in box space + if (Math.Abs(LMid.X) > Extents.X + LExt.X) return ContainmentType.Disjoint; + if (Math.Abs(LMid.Y) > Extents.Y + LExt.Y) return ContainmentType.Disjoint; + if (Math.Abs(LMid.Z) > Extents.Z + LExt.Z) return ContainmentType.Disjoint; + // Cross products of line and each axis + if (Math.Abs(LMid.Y * L.Z - LMid.Z * L.Y) > (Extents.Y * LExt.Z + Extents.Z * LExt.Y)) return ContainmentType.Disjoint; + if (Math.Abs(LMid.X * L.Z - LMid.Z * L.X) > (Extents.X * LExt.Z + Extents.Z * LExt.X)) return ContainmentType.Disjoint; + if (Math.Abs(LMid.X * L.Y - LMid.Y * L.X) > (Extents.X * LExt.Y + Extents.Y * LExt.X)) return ContainmentType.Disjoint; + // No separating axis, the line intersects + return ContainmentType.Intersects; + } + + /// + /// Check the intersection between an and + /// + /// The BoundingBox to test. + /// The type of containment the two objects have. + /// + /// For accuracy, The transformation matrix for the must not have any scaling applied to it. + /// Anyway, scaling using Scale method will keep this method accurate. + /// + public ContainmentType Contains(ref BoundingBox box) + { + var cornersCheck = Contains(box.GetCorners()); + if (cornersCheck != ContainmentType.Disjoint) + return cornersCheck; + + var boxCenter = box.Minimum + (box.Maximum - box.Minimum) / 2f; + var boxExtents = box.Maximum - boxCenter; + + var SizeA = Extents; + var SizeB = boxExtents; + var RotA = GetRows(ref Transformation); + + float ExtentA, ExtentB, Separation; + int i, k; + + Matrix R; // Rotation from B to A + Matrix.Invert(ref Transformation, out R); + var AR = new Matrix(); // absolute values of R matrix, to use with box extents + + for (i = 0; i < 3; i++) + for (k = 0; k < 3; k++) + { + AR[i, k] = Math.Abs(R[i, k]); + } + + + // Vector separating the centers of Box B and of Box A + var vSepWS = boxCenter - Center; + // Rotated into Box A's coordinates + var vSepA = new Vector3(Vector3.Dot(vSepWS, RotA[0]), Vector3.Dot(vSepWS, RotA[1]), Vector3.Dot(vSepWS, RotA[2])); + + // Test if any of A's basis vectors separate the box + for (i = 0; i < 3; i++) + { + ExtentA = SizeA[i]; + ExtentB = Vector3.Dot(SizeB, new Vector3(AR[i, 0], AR[i, 1], AR[i, 2])); + Separation = Math.Abs(vSepA[i]); + + if (Separation > ExtentA + ExtentB) + return ContainmentType.Disjoint; + } + + // Test if any of B's basis vectors separate the box + for (k = 0; k < 3; k++) + { + ExtentA = Vector3.Dot(SizeA, new Vector3(AR[0, k], AR[1, k], AR[2, k])); + ExtentB = SizeB[k]; + Separation = Math.Abs(Vector3.Dot(vSepA, new Vector3(R[0, k], R[1, k], R[2, k]))); + + if (Separation > ExtentA + ExtentB) + return ContainmentType.Disjoint; + } + + // Now test Cross Products of each basis vector combination ( A[i], B[k] ) + for (i = 0; i < 3; i++) + for (k = 0; k < 3; k++) + { + int i1 = (i + 1) % 3, i2 = (i + 2) % 3; + int k1 = (k + 1) % 3, k2 = (k + 2) % 3; + ExtentA = SizeA[i1] * AR[i2, k] + SizeA[i2] * AR[i1, k]; + ExtentB = SizeB[k1] * AR[i, k2] + SizeB[k2] * AR[i, k1]; + Separation = Math.Abs(vSepA[i2] * R[i1, k] - vSepA[i1] * R[i2, k]); + if (Separation > ExtentA + ExtentB) + return ContainmentType.Disjoint; + } + + // No separating axis found, the boxes overlap + return ContainmentType.Intersects; + } + + /// + /// Determines whether there is an intersection between a and a . + /// + /// The ray to test. + /// When the method completes, contains the point of intersection, + /// or if there was no intersection. + /// Whether the two objects intersected. + public bool Intersects(ref Ray ray, out Vector3 point) + { + // Put ray in box space + Matrix invTrans; + Matrix.Invert(ref Transformation, out invTrans); + + Ray bRay; + Vector3.TransformNormal(ref ray.Direction, ref invTrans, out bRay.Direction); + Vector3.TransformCoordinate(ref ray.Position, ref invTrans, out bRay.Position); + + //Perform a regular ray to BoundingBox check + var bb = new BoundingBox(-Extents, Extents); + var intersects = Collision.RayIntersectsBox(ref bRay, ref bb, out point); + + //Put the result intersection back to world + if (intersects) + Vector3.TransformCoordinate(ref point, ref Transformation, out point); + + return intersects; + } + + /// + /// Determines whether there is an intersection between a and a . + /// + /// The ray to test. + /// Whether the two objects intersected. + public bool Intersects(ref Ray ray) + { + Vector3 point; + return Intersects(ref ray, out point); + } + + private Vector3[] GetLocalCorners() + { + var xv = new Vector3(Extents.X, 0, 0); + var yv = new Vector3(0, Extents.Y, 0); + var zv = new Vector3(0, 0, Extents.Z); + + var corners = new Vector3[8]; + corners[0] = +xv + yv + zv; + corners[1] = +xv + yv - zv; + corners[2] = -xv + yv - zv; + corners[3] = -xv + yv + zv; + corners[4] = +xv - yv + zv; + corners[5] = +xv - yv - zv; + corners[6] = -xv - yv - zv; + corners[7] = -xv - yv + zv; + + return corners; + } + + /// + /// Get the axis-aligned which contains all corners. + /// + /// The axis-aligned BoundingBox of this OrientedBoundingBox. + public BoundingBox GetBoundingBox() + { + return BoundingBox.FromPoints(GetCorners()); + } + + /// + /// Calculates the matrix required to transfer any point from one local coordinates to another. + /// + /// The source OrientedBoundingBox. + /// The target OrientedBoundingBox. + /// + /// If true, the method will use a fast algorithm which is inapplicable if a scale is applied to the transformation matrix of the OrientedBoundingBox. + /// + /// + public static Matrix GetBoxToBoxMatrix(ref OrientedBoundingBox A, ref OrientedBoundingBox B, bool NoMatrixScaleApplied = false) + { + Matrix AtoB_Matrix; + + // Calculate B to A transformation matrix + if (NoMatrixScaleApplied) + { + var RotA = GetRows(ref A.Transformation); + var RotB = GetRows(ref B.Transformation); + AtoB_Matrix = new Matrix(); + int i, k; + for (i = 0; i < 3; i++) + for (k = 0; k < 3; k++) + AtoB_Matrix[i, k] = Vector3.Dot(RotB[i], RotA[k]); + var v = B.Center - A.Center; + AtoB_Matrix.M41 = Vector3.Dot(v, RotA[0]); + AtoB_Matrix.M42 = Vector3.Dot(v, RotA[1]); + AtoB_Matrix.M43 = Vector3.Dot(v, RotA[2]); + AtoB_Matrix.M44 = 1; + } + else + { + Matrix AInvMat; + Matrix.Invert(ref A.Transformation, out AInvMat); + AtoB_Matrix = B.Transformation * AInvMat; + } + + return AtoB_Matrix; + } + + /// + /// Merge an OrientedBoundingBox B into another OrientedBoundingBox A, by expanding A to contain B and keeping A orientation. + /// + /// The to merge into it. + /// The to be merged + /// + /// If true, the method will use a fast algorithm which is inapplicable if a scale is applied to the transformation matrix of the OrientedBoundingBox. + /// + /// + /// Unlike merging axis aligned boxes, The operation is not interchangeable, because it keeps A orientation and merge B into it. + /// + public static void Merge(ref OrientedBoundingBox A, ref OrientedBoundingBox B, bool NoMatrixScaleApplied = false) + { + Matrix AtoB_Matrix = GetBoxToBoxMatrix(ref A, ref B, NoMatrixScaleApplied); + + //Get B corners in A Space + var bCorners = B.GetLocalCorners(); + Vector3.TransformCoordinate(bCorners, ref AtoB_Matrix, bCorners); + + //Get A local Bounding Box + var A_LocalBB = new BoundingBox(-A.Extents, A.Extents); + + //Find B BoundingBox in A Space + var B_LocalBB = BoundingBox.FromPoints(bCorners); + + //Merger A and B local Bounding Boxes + BoundingBox mergedBB; + BoundingBox.Merge(ref B_LocalBB, ref A_LocalBB, out mergedBB); + + //Find the new Extents and Center, Transform Center back to world + var newCenter = mergedBB.Minimum + (mergedBB.Maximum - mergedBB.Minimum) / 2f; + A.Extents = mergedBB.Maximum - newCenter; + Vector3.TransformCoordinate(ref newCenter, ref A.Transformation, out newCenter); + A.Transformation.TranslationVector = newCenter; + } + + /// + /// Merge this OrientedBoundingBox into another OrientedBoundingBox, keeping the other OrientedBoundingBox orientation. + /// + /// The other to merge into. + /// + /// If true, the method will use a fast algorithm which is inapplicable if a scale is applied to the transformation matrix of the OrientedBoundingBox. + /// + public void MergeInto(ref OrientedBoundingBox OBB, bool NoMatrixScaleApplied = false) + { + Merge(ref OBB, ref this, NoMatrixScaleApplied); + } + + /// + /// Merge another OrientedBoundingBox into this OrientedBoundingBox. + /// + /// The other to merge into this OrientedBoundingBox. + /// + /// If true, the method will use a fast algorithm which is inapplicable if a scale is applied to the transformation matrix of the OrientedBoundingBox. + /// + public void Add(ref OrientedBoundingBox OBB, bool NoMatrixScaleApplied = false) + { + Merge(ref this, ref OBB, NoMatrixScaleApplied); + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(OrientedBoundingBox value) + { + return Extents == value.Extents && Transformation == value.Transformation; + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object value) + { + if (value == null) + return false; + + if (!ReferenceEquals(value.GetType(), typeof(OrientedBoundingBox))) + return false; + + return Equals((OrientedBoundingBox)value); + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has the same value as ; otherwise, false. + public static bool operator ==(OrientedBoundingBox left, OrientedBoundingBox right) + { + return left.Equals(right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has a different value than ; otherwise, false. + public static bool operator !=(OrientedBoundingBox left, OrientedBoundingBox right) + { + return !left.Equals(right); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + return Extents.GetHashCode() + Transformation.GetHashCode(); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return String.Format(CultureInfo.CurrentCulture, "Center: {0}, Extents: {1}", Center, Extents); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// + /// A that represents this instance. + /// + public string ToString(string format) + { + if (format == null) + return ToString(); + + return string.Format(CultureInfo.CurrentCulture, "Center: {0}, Extents: {1}", Center.ToString(format, CultureInfo.CurrentCulture), + Extents.ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format(formatProvider, "Center: {0}, Extents: {1}", Center.ToString(), Extents.ToString()); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(string format, IFormatProvider formatProvider) + { + if (format == null) + return ToString(formatProvider); + + return string.Format(formatProvider, "Center: {0}, Extents: {1}", Center.ToString(format, formatProvider), + Extents.ToString(format, formatProvider)); + } + } +} + diff --git a/Source/SharpDX/Plane.cs b/Source/SharpDX.Mathematics/Plane.cs similarity index 82% rename from Source/SharpDX/Plane.cs rename to Source/SharpDX.Mathematics/Plane.cs index 6300e33ca..df2e4a6a0 100644 --- a/Source/SharpDX/Plane.cs +++ b/Source/SharpDX.Mathematics/Plane.cs @@ -1,747 +1,906 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ----------------------------------------------------------------------------- -// Original code from SlimMath project. http://code.google.com/p/slimmath/ -// Greetings to SlimDX Group. Original code published with the following license: -// ----------------------------------------------------------------------------- -/* -* Copyright (c) 2007-2011 SlimDX Group -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using System.ComponentModel; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Represents a plane in three dimensional space. - /// - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct Plane : IEquatable, IFormattable, IDataSerializable - { - /// - /// The normal vector of the plane. - /// - public Vector3 Normal; - - /// - /// The distance of the plane along its normal from the origin. - /// - public float D; - - /// - /// Initializes a new instance of the struct. - /// - /// The value that will be assigned to all components. - public Plane(float value) - { - Normal.X = Normal.Y = Normal.Z = D = value; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The X component of the normal. - /// The Y component of the normal. - /// The Z component of the normal. - /// The distance of the plane along its normal from the origin. - public Plane(float a, float b, float c, float d) - { - Normal.X = a; - Normal.Y = b; - Normal.Z = c; - D = d; - } - - /// - /// Initializes a new instance of the class. - /// - /// Any point that lies along the plane. - /// The normal vector to the plane. - public Plane(Vector3 point, Vector3 normal) - { - this.Normal = normal; - this.D = -Vector3.Dot(normal, point); - } - - /// - /// Initializes a new instance of the struct. - /// - /// The normal of the plane. - /// The distance of the plane along its normal from the origin - public Plane(Vector3 value, float d) - { - Normal = value; - D = d; - } - - /// - /// Initializes a new instance of the struct. - /// - /// First point of a triangle defining the plane. - /// Second point of a triangle defining the plane. - /// Third point of a triangle defining the plane. - public Plane(Vector3 point1, Vector3 point2, Vector3 point3) - { - float x1 = point2.X - point1.X; - float y1 = point2.Y - point1.Y; - float z1 = point2.Z - point1.Z; - float x2 = point3.X - point1.X; - float y2 = point3.Y - point1.Y; - float z2 = point3.Z - point1.Z; - float yz = (y1 * z2) - (z1 * y2); - float xz = (z1 * x2) - (x1 * z2); - float xy = (x1 * y2) - (y1 * x2); - float invPyth = 1.0f / (float)(Math.Sqrt((yz * yz) + (xz * xz) + (xy * xy))); - - Normal.X = yz * invPyth; - Normal.Y = xz * invPyth; - Normal.Z = xy * invPyth; - D = -((Normal.X * point1.X) + (Normal.Y * point1.Y) + (Normal.Z * point1.Z)); - } - - /// - /// Initializes a new instance of the struct. - /// - /// The values to assign to the A, B, C, and D components of the plane. This must be an array with four elements. - /// Thrown when is null. - /// Thrown when contains more or less than four elements. - public Plane(float[] values) - { - if (values == null) - throw new ArgumentNullException("values"); - if (values.Length != 4) - throw new ArgumentOutOfRangeException("values", "There must be four and only four input values for Plane."); - - Normal.X = values[0]; - Normal.Y = values[1]; - Normal.Z = values[2]; - D = values[3]; - } - - /// - /// Gets or sets the component at the specified index. - /// - /// The value of the A, B, C, or D component, depending on the index. - /// The index of the component to access. Use 0 for the A component, 1 for the B component, 2 for the C component, and 3 for the D component. - /// The value of the component at the specified index. - /// Thrown when the is out of the range [0, 3]. - public float this[int index] - { - get - { - switch (index) - { - case 0: return Normal.X; - case 1: return Normal.Y; - case 2: return Normal.Z; - case 3: return D; - } - - throw new ArgumentOutOfRangeException("index", "Indices for Plane run from 0 to 3, inclusive."); - } - - set - { - switch (index) - { - case 0: Normal.X = value; break; - case 1: Normal.Y = value; break; - case 2: Normal.Z = value; break; - case 3: D = value; break; - default: throw new ArgumentOutOfRangeException("index", "Indices for Plane run from 0 to 3, inclusive."); - } - } - } - - /// - /// Changes the coefficients of the normal vector of the plane to make it of unit length. - /// - public void Normalize() - { - float magnitude = 1.0f / (float)(Math.Sqrt((Normal.X * Normal.X) + (Normal.Y * Normal.Y) + (Normal.Z * Normal.Z))); - - Normal.X *= magnitude; - Normal.Y *= magnitude; - Normal.Z *= magnitude; - D *= magnitude; - } - - /// - /// Creates an array containing the elements of the plane. - /// - /// A four-element array containing the components of the plane. - public float[] ToArray() - { - return new float[] { Normal.X, Normal.Y, Normal.Z, D }; - } - - /// - /// Determines if there is an intersection between the current object and a point. - /// - /// The point to test. - /// Whether the two objects intersected. - public PlaneIntersectionType Intersects(ref Vector3 point) - { - return Collision.PlaneIntersectsPoint(ref this, ref point); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The ray to test. - /// Whether the two objects intersected. - public bool Intersects(ref Ray ray) - { - float distance; - return Collision.RayIntersectsPlane(ref ray, ref this, out distance); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The ray to test. - /// When the method completes, contains the distance of the intersection, - /// or 0 if there was no intersection. - /// Whether the two objects intersected. - public bool Intersects(ref Ray ray, out float distance) - { - return Collision.RayIntersectsPlane(ref ray, ref this, out distance); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The ray to test. - /// When the method completes, contains the point of intersection, - /// or if there was no intersection. - /// Whether the two objects intersected. - public bool Intersects(ref Ray ray, out Vector3 point) - { - return Collision.RayIntersectsPlane(ref ray, ref this, out point); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The plane to test. - /// Whether the two objects intersected. - public bool Intersects(ref Plane plane) - { - return Collision.PlaneIntersectsPlane(ref this, ref plane); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The plane to test. - /// When the method completes, contains the line of intersection - /// as a , or a zero ray if there was no intersection. - /// Whether the two objects intersected. - public bool Intersects(ref Plane plane, out Ray line) - { - return Collision.PlaneIntersectsPlane(ref this, ref plane, out line); - } - - /// - /// Determines if there is an intersection between the current object and a triangle. - /// - /// The first vertex of the triangle to test. - /// The second vertex of the triangle to test. - /// The third vertex of the triangle to test. - /// Whether the two objects intersected. - public PlaneIntersectionType Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) - { - return Collision.PlaneIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The box to test. - /// Whether the two objects intersected. - public PlaneIntersectionType Intersects(ref BoundingBox box) - { - return Collision.PlaneIntersectsBox(ref this, ref box); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The sphere to test. - /// Whether the two objects intersected. - public PlaneIntersectionType Intersects(ref BoundingSphere sphere) - { - return Collision.PlaneIntersectsSphere(ref this, ref sphere); - } - - /// - /// Scales the plane by the given scaling factor. - /// - /// The plane to scale. - /// The amount by which to scale the plane. - /// When the method completes, contains the scaled plane. - public static void Multiply(ref Plane value, float scale, out Plane result) - { - result.Normal.X = value.Normal.X * scale; - result.Normal.Y = value.Normal.Y * scale; - result.Normal.Z = value.Normal.Z * scale; - result.D = value.D * scale; - } - - /// - /// Scales the plane by the given scaling factor. - /// - /// The plane to scale. - /// The amount by which to scale the plane. - /// The scaled plane. - public static Plane Multiply(Plane value, float scale) - { - return new Plane(value.Normal.X * scale, value.Normal.Y * scale, value.Normal.Z * scale, value.D * scale); - } - - /// - /// Calculates the dot product of the specified vector and plane. - /// - /// The source plane. - /// The source vector. - /// When the method completes, contains the dot product of the specified plane and vector. - public static void Dot(ref Plane left, ref Vector4 right, out float result) - { - result = (left.Normal.X * right.X) + (left.Normal.Y * right.Y) + (left.Normal.Z * right.Z) + (left.D * right.W); - } - - /// - /// Calculates the dot product of the specified vector and plane. - /// - /// The source plane. - /// The source vector. - /// The dot product of the specified plane and vector. - public static float Dot(Plane left, Vector4 right) - { - return (left.Normal.X * right.X) + (left.Normal.Y * right.Y) + (left.Normal.Z * right.Z) + (left.D * right.W); - } - - /// - /// Calculates the dot product of a specified vector and the normal of the plane plus the distance value of the plane. - /// - /// The source plane. - /// The source vector. - /// When the method completes, contains the dot product of a specified vector and the normal of the Plane plus the distance value of the plane. - public static void DotCoordinate(ref Plane left, ref Vector3 right, out float result) - { - result = (left.Normal.X * right.X) + (left.Normal.Y * right.Y) + (left.Normal.Z * right.Z) + left.D; - } - - /// - /// Calculates the dot product of a specified vector and the normal of the plane plus the distance value of the plane. - /// - /// The source plane. - /// The source vector. - /// The dot product of a specified vector and the normal of the Plane plus the distance value of the plane. - public static float DotCoordinate(Plane left, Vector3 right) - { - return (left.Normal.X * right.X) + (left.Normal.Y * right.Y) + (left.Normal.Z * right.Z) + left.D; - } - - /// - /// Calculates the dot product of the specified vector and the normal of the plane. - /// - /// The source plane. - /// The source vector. - /// When the method completes, contains the dot product of the specified vector and the normal of the plane. - public static void DotNormal(ref Plane left, ref Vector3 right, out float result) - { - result = (left.Normal.X * right.X) + (left.Normal.Y * right.Y) + (left.Normal.Z * right.Z); - } - - /// - /// Calculates the dot product of the specified vector and the normal of the plane. - /// - /// The source plane. - /// The source vector. - /// The dot product of the specified vector and the normal of the plane. - public static float DotNormal(Plane left, Vector3 right) - { - return (left.Normal.X * right.X) + (left.Normal.Y * right.Y) + (left.Normal.Z * right.Z); - } - - /// - /// Changes the coefficients of the normal vector of the plane to make it of unit length. - /// - /// The source plane. - /// When the method completes, contains the normalized plane. - public static void Normalize(ref Plane plane, out Plane result) - { - float magnitude = 1.0f / (float)(Math.Sqrt((plane.Normal.X * plane.Normal.X) + (plane.Normal.Y * plane.Normal.Y) + (plane.Normal.Z * plane.Normal.Z))); - - result.Normal.X = plane.Normal.X * magnitude; - result.Normal.Y = plane.Normal.Y * magnitude; - result.Normal.Z = plane.Normal.Z * magnitude; - result.D = plane.D * magnitude; - } - - /// - /// Changes the coefficients of the normal vector of the plane to make it of unit length. - /// - /// The source plane. - /// The normalized plane. - public static Plane Normalize(Plane plane) - { - float magnitude = 1.0f / (float)(Math.Sqrt((plane.Normal.X * plane.Normal.X) + (plane.Normal.Y * plane.Normal.Y) + (plane.Normal.Z * plane.Normal.Z))); - return new Plane(plane.Normal.X * magnitude, plane.Normal.Y * magnitude, plane.Normal.Z * magnitude, plane.D * magnitude); - } - - /// - /// Transforms a normalized plane by a quaternion rotation. - /// - /// The normalized source plane. - /// The quaternion rotation. - /// When the method completes, contains the transformed plane. - public static void Transform(ref Plane plane, ref Quaternion rotation, out Plane result) - { - float x2 = rotation.X + rotation.X; - float y2 = rotation.Y + rotation.Y; - float z2 = rotation.Z + rotation.Z; - float wx = rotation.W * x2; - float wy = rotation.W * y2; - float wz = rotation.W * z2; - float xx = rotation.X * x2; - float xy = rotation.X * y2; - float xz = rotation.X * z2; - float yy = rotation.Y * y2; - float yz = rotation.Y * z2; - float zz = rotation.Z * z2; - - float x = plane.Normal.X; - float y = plane.Normal.Y; - float z = plane.Normal.Z; - - result.Normal.X = ((x * ((1.0f - yy) - zz)) + (y * (xy - wz))) + (z * (xz + wy)); - result.Normal.Y = ((x * (xy + wz)) + (y * ((1.0f - xx) - zz))) + (z * (yz - wx)); - result.Normal.Z = ((x * (xz - wy)) + (y * (yz + wx))) + (z * ((1.0f - xx) - yy)); - result.D = plane.D; - } - - /// - /// Transforms a normalized plane by a quaternion rotation. - /// - /// The normalized source plane. - /// The quaternion rotation. - /// The transformed plane. - public static Plane Transform(Plane plane, Quaternion rotation) - { - Plane result; - float x2 = rotation.X + rotation.X; - float y2 = rotation.Y + rotation.Y; - float z2 = rotation.Z + rotation.Z; - float wx = rotation.W * x2; - float wy = rotation.W * y2; - float wz = rotation.W * z2; - float xx = rotation.X * x2; - float xy = rotation.X * y2; - float xz = rotation.X * z2; - float yy = rotation.Y * y2; - float yz = rotation.Y * z2; - float zz = rotation.Z * z2; - - float x = plane.Normal.X; - float y = plane.Normal.Y; - float z = plane.Normal.Z; - - result.Normal.X = ((x * ((1.0f - yy) - zz)) + (y * (xy - wz))) + (z * (xz + wy)); - result.Normal.Y = ((x * (xy + wz)) + (y * ((1.0f - xx) - zz))) + (z * (yz - wx)); - result.Normal.Z = ((x * (xz - wy)) + (y * (yz + wx))) + (z * ((1.0f - xx) - yy)); - result.D = plane.D; - - return result; - } - - /// - /// Transforms an array of normalized planes by a quaternion rotation. - /// - /// The array of normalized planes to transform. - /// The quaternion rotation. - /// Thrown when is null. - public static void Transform(Plane[] planes, ref Quaternion rotation) - { - if (planes == null) - throw new ArgumentNullException("planes"); - - float x2 = rotation.X + rotation.X; - float y2 = rotation.Y + rotation.Y; - float z2 = rotation.Z + rotation.Z; - float wx = rotation.W * x2; - float wy = rotation.W * y2; - float wz = rotation.W * z2; - float xx = rotation.X * x2; - float xy = rotation.X * y2; - float xz = rotation.X * z2; - float yy = rotation.Y * y2; - float yz = rotation.Y * z2; - float zz = rotation.Z * z2; - - for (int i = 0; i < planes.Length; ++i) - { - float x = planes[i].Normal.X; - float y = planes[i].Normal.Y; - float z = planes[i].Normal.Z; - - /* - * Note: - * Factor common arithmetic out of loop. - */ - planes[i].Normal.X = ((x * ((1.0f - yy) - zz)) + (y * (xy - wz))) + (z * (xz + wy)); - planes[i].Normal.Y = ((x * (xy + wz)) + (y * ((1.0f - xx) - zz))) + (z * (yz - wx)); - planes[i].Normal.Z = ((x * (xz - wy)) + (y * (yz + wx))) + (z * ((1.0f - xx) - yy)); - } - } - - /// - /// Transforms a normalized plane by a matrix. - /// - /// The normalized source plane. - /// The transformation matrix. - /// When the method completes, contains the transformed plane. - public static void Transform(ref Plane plane, ref Matrix transformation, out Plane result) - { - float x = plane.Normal.X; - float y = plane.Normal.Y; - float z = plane.Normal.Z; - float d = plane.D; - - Matrix inverse; - Matrix.Invert(ref transformation, out inverse); - - result.Normal.X = (((x * inverse.M11) + (y * inverse.M12)) + (z * inverse.M13)) + (d * inverse.M14); - result.Normal.Y = (((x * inverse.M21) + (y * inverse.M22)) + (z * inverse.M23)) + (d * inverse.M24); - result.Normal.Z = (((x * inverse.M31) + (y * inverse.M32)) + (z * inverse.M33)) + (d * inverse.M34); - result.D = (((x * inverse.M41) + (y * inverse.M42)) + (z * inverse.M43)) + (d * inverse.M44); - } - - /// - /// Transforms a normalized plane by a matrix. - /// - /// The normalized source plane. - /// The transformation matrix. - /// When the method completes, contains the transformed plane. - public static Plane Transform(Plane plane, Matrix transformation) - { - Plane result; - float x = plane.Normal.X; - float y = plane.Normal.Y; - float z = plane.Normal.Z; - float d = plane.D; - - transformation.Invert(); - result.Normal.X = (((x * transformation.M11) + (y * transformation.M12)) + (z * transformation.M13)) + (d * transformation.M14); - result.Normal.Y = (((x * transformation.M21) + (y * transformation.M22)) + (z * transformation.M23)) + (d * transformation.M24); - result.Normal.Z = (((x * transformation.M31) + (y * transformation.M32)) + (z * transformation.M33)) + (d * transformation.M34); - result.D = (((x * transformation.M41) + (y * transformation.M42)) + (z * transformation.M43)) + (d * transformation.M44); - - return result; - } - - /// - /// Transforms an array of normalized planes by a matrix. - /// - /// The array of normalized planes to transform. - /// The transformation matrix. - /// Thrown when is null. - public static void Transform(Plane[] planes, ref Matrix transformation) - { - if (planes == null) - throw new ArgumentNullException("planes"); - - Matrix inverse; - Matrix.Invert(ref transformation, out inverse); - - for (int i = 0; i < planes.Length; ++i) - { - Transform(ref planes[i], ref transformation, out planes[i]); - } - } - - /// - /// Scales a plane by the given value. - /// - /// The amount by which to scale the plane. - /// The plane to scale. - /// The scaled plane. - public static Plane operator *(float scale, Plane plane) - { - return new Plane(plane.Normal.X * scale, plane.Normal.Y * scale, plane.Normal.Z * scale, plane.D * scale); - } - - /// - /// Scales a plane by the given value. - /// - /// The plane to scale. - /// The amount by which to scale the plane. - /// The scaled plane. - public static Plane operator *(Plane plane, float scale) - { - return new Plane(plane.Normal.X * scale, plane.Normal.Y * scale, plane.Normal.Z * scale, plane.D * scale); - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has the same value as ; otherwise, false. - public static bool operator ==(Plane left, Plane right) - { - return left.Equals(right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has a different value than ; otherwise, false. - public static bool operator !=(Plane left, Plane right) - { - return !left.Equals(right); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return string.Format(CultureInfo.CurrentCulture, "A:{0} B:{1} C:{2} D:{3}", Normal.X, Normal.Y, Normal.Z, D); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// - /// A that represents this instance. - /// - public string ToString(string format) - { - return string.Format(CultureInfo.CurrentCulture, "A:{0} B:{1} C:{2} D:{3}", Normal.X.ToString(format, CultureInfo.CurrentCulture), - Normal.Y.ToString(format, CultureInfo.CurrentCulture), Normal.Z.ToString(format, CultureInfo.CurrentCulture), D.ToString(format, CultureInfo.CurrentCulture)); - } - - /// - /// Returns a that represents this instance. - /// - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(IFormatProvider formatProvider) - { - return string.Format(formatProvider, "A:{0} B:{1} C:{2} D:{3}", Normal.X, Normal.Y, Normal.Z, D); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - return string.Format(formatProvider, "A:{0} B:{1} C:{2} D:{3}", Normal.X.ToString(format, formatProvider), - Normal.Y.ToString(format, formatProvider), Normal.Z.ToString(format, formatProvider), D.ToString(format, formatProvider)); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - return (Normal.GetHashCode() * 397) ^ D.GetHashCode(); - } - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(Plane value) - { - return Normal == value.Normal && D == value.D; - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object value) - { - if (value == null) - return false; - - if (!ReferenceEquals(value.GetType(), typeof(Plane))) - return false; - - return Equals((Plane)value); - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - serializer.Serialize(ref Normal); - serializer.Serialize(ref D); - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from SlimMath project. http://code.google.com/p/slimmath/ +// Greetings to SlimDX Group. Original code published with the following license: +// ----------------------------------------------------------------------------- +/* +* Copyright (c) 2007-2011 SlimDX Group +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Represents a plane in three dimensional space. + /// + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct Plane : IEquatable, IFormattable + { + /// + /// The normal vector of the plane. + /// + public Vector3 Normal; + + /// + /// The distance of the plane along its normal from the origin. + /// + public float D; + + /// + /// Initializes a new instance of the struct. + /// + /// The value that will be assigned to all components. + public Plane(float value) + { + Normal.X = Normal.Y = Normal.Z = D = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The X component of the normal. + /// The Y component of the normal. + /// The Z component of the normal. + /// The distance of the plane along its normal from the origin. + public Plane(float a, float b, float c, float d) + { + Normal.X = a; + Normal.Y = b; + Normal.Z = c; + D = d; + } + + /// + /// Initializes a new instance of the class. + /// + /// Any point that lies along the plane. + /// The normal vector to the plane. + public Plane(Vector3 point, Vector3 normal) + { + this.Normal = normal; + this.D = -Vector3.Dot(normal, point); + } + + /// + /// Initializes a new instance of the struct. + /// + /// The normal of the plane. + /// The distance of the plane along its normal from the origin + public Plane(Vector3 value, float d) + { + Normal = value; + D = d; + } + + /// + /// Initializes a new instance of the struct. + /// + /// First point of a triangle defining the plane. + /// Second point of a triangle defining the plane. + /// Third point of a triangle defining the plane. + public Plane(Vector3 point1, Vector3 point2, Vector3 point3) + { + float x1 = point2.X - point1.X; + float y1 = point2.Y - point1.Y; + float z1 = point2.Z - point1.Z; + float x2 = point3.X - point1.X; + float y2 = point3.Y - point1.Y; + float z2 = point3.Z - point1.Z; + float yz = (y1 * z2) - (z1 * y2); + float xz = (z1 * x2) - (x1 * z2); + float xy = (x1 * y2) - (y1 * x2); + float invPyth = 1.0f / (float)(Math.Sqrt((yz * yz) + (xz * xz) + (xy * xy))); + + Normal.X = yz * invPyth; + Normal.Y = xz * invPyth; + Normal.Z = xy * invPyth; + D = -((Normal.X * point1.X) + (Normal.Y * point1.Y) + (Normal.Z * point1.Z)); + } + + /// + /// Initializes a new instance of the struct. + /// + /// The values to assign to the A, B, C, and D components of the plane. This must be an array with four elements. + /// Thrown when is null. + /// Thrown when contains more or less than four elements. + public Plane(float[] values) + { + if (values == null) + throw new ArgumentNullException("values"); + if (values.Length != 4) + throw new ArgumentOutOfRangeException("values", "There must be four and only four input values for Plane."); + + Normal.X = values[0]; + Normal.Y = values[1]; + Normal.Z = values[2]; + D = values[3]; + } + + /// + /// Gets or sets the component at the specified index. + /// + /// The value of the A, B, C, or D component, depending on the index. + /// The index of the component to access. Use 0 for the A component, 1 for the B component, 2 for the C component, and 3 for the D component. + /// The value of the component at the specified index. + /// Thrown when the is out of the range [0, 3]. + public float this[int index] + { + get + { + switch (index) + { + case 0: return Normal.X; + case 1: return Normal.Y; + case 2: return Normal.Z; + case 3: return D; + } + + throw new ArgumentOutOfRangeException("index", "Indices for Plane run from 0 to 3, inclusive."); + } + + set + { + switch (index) + { + case 0: Normal.X = value; break; + case 1: Normal.Y = value; break; + case 2: Normal.Z = value; break; + case 3: D = value; break; + default: throw new ArgumentOutOfRangeException("index", "Indices for Plane run from 0 to 3, inclusive."); + } + } + } + + /// + /// Changes the coefficients of the normal vector of the plane to make it of unit length. + /// + public void Normalize() + { + float magnitude = 1.0f / (float)(Math.Sqrt((Normal.X * Normal.X) + (Normal.Y * Normal.Y) + (Normal.Z * Normal.Z))); + + Normal.X *= magnitude; + Normal.Y *= magnitude; + Normal.Z *= magnitude; + D *= magnitude; + } + + /// + /// Creates an array containing the elements of the plane. + /// + /// A four-element array containing the components of the plane. + public float[] ToArray() + { + return new float[] { Normal.X, Normal.Y, Normal.Z, D }; + } + + /// + /// Determines if there is an intersection between the current object and a point. + /// + /// The point to test. + /// Whether the two objects intersected. + public PlaneIntersectionType Intersects(ref Vector3 point) + { + return Collision.PlaneIntersectsPoint(ref this, ref point); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The ray to test. + /// Whether the two objects intersected. + public bool Intersects(ref Ray ray) + { + float distance; + return Collision.RayIntersectsPlane(ref ray, ref this, out distance); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The ray to test. + /// When the method completes, contains the distance of the intersection, + /// or 0 if there was no intersection. + /// Whether the two objects intersected. + public bool Intersects(ref Ray ray, out float distance) + { + return Collision.RayIntersectsPlane(ref ray, ref this, out distance); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The ray to test. + /// When the method completes, contains the point of intersection, + /// or if there was no intersection. + /// Whether the two objects intersected. + public bool Intersects(ref Ray ray, out Vector3 point) + { + return Collision.RayIntersectsPlane(ref ray, ref this, out point); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The plane to test. + /// Whether the two objects intersected. + public bool Intersects(ref Plane plane) + { + return Collision.PlaneIntersectsPlane(ref this, ref plane); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The plane to test. + /// When the method completes, contains the line of intersection + /// as a , or a zero ray if there was no intersection. + /// Whether the two objects intersected. + public bool Intersects(ref Plane plane, out Ray line) + { + return Collision.PlaneIntersectsPlane(ref this, ref plane, out line); + } + + /// + /// Determines if there is an intersection between the current object and a triangle. + /// + /// The first vertex of the triangle to test. + /// The second vertex of the triangle to test. + /// The third vertex of the triangle to test. + /// Whether the two objects intersected. + public PlaneIntersectionType Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) + { + return Collision.PlaneIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The box to test. + /// Whether the two objects intersected. + public PlaneIntersectionType Intersects(ref BoundingBox box) + { + return Collision.PlaneIntersectsBox(ref this, ref box); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The sphere to test. + /// Whether the two objects intersected. + public PlaneIntersectionType Intersects(ref BoundingSphere sphere) + { + return Collision.PlaneIntersectsSphere(ref this, ref sphere); + } + + /// + /// Builds a matrix that can be used to reflect vectors about a plane. + /// + /// The plane for which the reflection occurs. This parameter is assumed to be normalized. + /// When the method completes, contains the reflection matrix. + public void Reflection(out Matrix result) + { + float x = this.Normal.X; + float y = this.Normal.Y; + float z = this.Normal.Z; + float x2 = -2.0f * x; + float y2 = -2.0f * y; + float z2 = -2.0f * z; + + result.M11 = (x2 * x) + 1.0f; + result.M12 = y2 * x; + result.M13 = z2 * x; + result.M14 = 0.0f; + result.M21 = x2 * y; + result.M22 = (y2 * y) + 1.0f; + result.M23 = z2 * y; + result.M24 = 0.0f; + result.M31 = x2 * z; + result.M32 = y2 * z; + result.M33 = (z2 * z) + 1.0f; + result.M34 = 0.0f; + result.M41 = x2 * this.D; + result.M42 = y2 * this.D; + result.M43 = z2 * this.D; + result.M44 = 1.0f; + } + + /// + /// Builds a matrix that can be used to reflect vectors about a plane. + /// + /// The reflection matrix. + public Matrix Reflection() + { + Matrix result; + Reflection(out result); + return result; + } + + /// + /// Creates a matrix that flattens geometry into a shadow from this the plane onto which to project the geometry as a shadow. + /// This plane is assumed to be normalized + /// + /// The light direction. If the W component is 0, the light is directional light; if the + /// W component is 1, the light is a point light. + /// When the method completes, contains the shadow matrix. + public void Shadow(ref Vector4 light, out Matrix result) + { + float dot = (this.Normal.X * light.X) + (this.Normal.Y * light.Y) + (this.Normal.Z * light.Z) + (this.D * light.W); + float x = -this.Normal.X; + float y = -this.Normal.Y; + float z = -this.Normal.Z; + float d = -this.D; + + result.M11 = (x * light.X) + dot; + result.M21 = y * light.X; + result.M31 = z * light.X; + result.M41 = d * light.X; + result.M12 = x * light.Y; + result.M22 = (y * light.Y) + dot; + result.M32 = z * light.Y; + result.M42 = d * light.Y; + result.M13 = x * light.Z; + result.M23 = y * light.Z; + result.M33 = (z * light.Z) + dot; + result.M43 = d * light.Z; + result.M14 = x * light.W; + result.M24 = y * light.W; + result.M34 = z * light.W; + result.M44 = (d * light.W) + dot; + } + + /// + /// Creates a matrix that flattens geometry into a shadow from this the plane onto which to project the geometry as a shadow. + /// This plane is assumed to be normalized + /// + /// The light direction. If the W component is 0, the light is directional light; if the + /// W component is 1, the light is a point light. + /// The shadow matrix. + public Matrix Shadow(Vector4 light) + { + Matrix result; + Shadow(ref light, out result); + return result; + } + + /// + /// Builds a Matrix3x3 that can be used to reflect vectors about a plane for which the reflection occurs. + /// This plane is assumed to be normalized + /// + /// When the method completes, contains the reflection Matrix3x3. + public void Reflection(out Matrix3x3 result) + { + float x = this.Normal.X; + float y = this.Normal.Y; + float z = this.Normal.Z; + float x2 = -2.0f * x; + float y2 = -2.0f * y; + float z2 = -2.0f * z; + + result.M11 = (x2 * x) + 1.0f; + result.M12 = y2 * x; + result.M13 = z2 * x; + result.M21 = x2 * y; + result.M22 = (y2 * y) + 1.0f; + result.M23 = z2 * y; + result.M31 = x2 * z; + result.M32 = y2 * z; + result.M33 = (z2 * z) + 1.0f; + } + + /// + /// Builds a Matrix3x3 that can be used to reflect vectors about a plane for which the reflection occurs. + /// This plane is assumed to be normalized + /// + /// The reflection Matrix3x3. + public Matrix3x3 Reflection3x3() + { + Matrix3x3 result; + Reflection(out result); + return result; + } + + /// + /// Creates a Matrix3x3 that flattens geometry into a shadow. + /// + /// The light direction. If the W component is 0, the light is directional light; if the + /// W component is 1, the light is a point light. + /// The plane onto which to project the geometry as a shadow. This parameter is assumed to be normalized. + /// When the method completes, contains the shadow Matrix3x3. + public static void Shadow(ref Vector4 light, ref Plane plane, out Matrix3x3 result) + { + float dot = (plane.Normal.X * light.X) + (plane.Normal.Y * light.Y) + (plane.Normal.Z * light.Z) + (plane.D * light.W); + float x = -plane.Normal.X; + float y = -plane.Normal.Y; + float z = -plane.Normal.Z; + float d = -plane.D; + + result.M11 = (x * light.X) + dot; + result.M21 = y * light.X; + result.M31 = z * light.X; + result.M12 = x * light.Y; + result.M22 = (y * light.Y) + dot; + result.M32 = z * light.Y; + result.M13 = x * light.Z; + result.M23 = y * light.Z; + result.M33 = (z * light.Z) + dot; + } + + /// + /// Creates a Matrix3x3 that flattens geometry into a shadow. + /// + /// The light direction. If the W component is 0, the light is directional light; if the + /// W component is 1, the light is a point light. + /// The plane onto which to project the geometry as a shadow. This parameter is assumed to be normalized. + /// The shadow Matrix3x3. + public static Matrix3x3 Shadow(Vector4 light, Plane plane) + { + Matrix3x3 result; + Shadow(ref light, ref plane, out result); + return result; + } + + + /// + /// Scales the plane by the given scaling factor. + /// + /// The plane to scale. + /// The amount by which to scale the plane. + /// When the method completes, contains the scaled plane. + public static void Multiply(ref Plane value, float scale, out Plane result) + { + result.Normal.X = value.Normal.X * scale; + result.Normal.Y = value.Normal.Y * scale; + result.Normal.Z = value.Normal.Z * scale; + result.D = value.D * scale; + } + + /// + /// Scales the plane by the given scaling factor. + /// + /// The plane to scale. + /// The amount by which to scale the plane. + /// The scaled plane. + public static Plane Multiply(Plane value, float scale) + { + return new Plane(value.Normal.X * scale, value.Normal.Y * scale, value.Normal.Z * scale, value.D * scale); + } + + /// + /// Calculates the dot product of the specified vector and plane. + /// + /// The source plane. + /// The source vector. + /// When the method completes, contains the dot product of the specified plane and vector. + public static void Dot(ref Plane left, ref Vector4 right, out float result) + { + result = (left.Normal.X * right.X) + (left.Normal.Y * right.Y) + (left.Normal.Z * right.Z) + (left.D * right.W); + } + + /// + /// Calculates the dot product of the specified vector and plane. + /// + /// The source plane. + /// The source vector. + /// The dot product of the specified plane and vector. + public static float Dot(Plane left, Vector4 right) + { + return (left.Normal.X * right.X) + (left.Normal.Y * right.Y) + (left.Normal.Z * right.Z) + (left.D * right.W); + } + + /// + /// Calculates the dot product of a specified vector and the normal of the plane plus the distance value of the plane. + /// + /// The source plane. + /// The source vector. + /// When the method completes, contains the dot product of a specified vector and the normal of the Plane plus the distance value of the plane. + public static void DotCoordinate(ref Plane left, ref Vector3 right, out float result) + { + result = (left.Normal.X * right.X) + (left.Normal.Y * right.Y) + (left.Normal.Z * right.Z) + left.D; + } + + /// + /// Calculates the dot product of a specified vector and the normal of the plane plus the distance value of the plane. + /// + /// The source plane. + /// The source vector. + /// The dot product of a specified vector and the normal of the Plane plus the distance value of the plane. + public static float DotCoordinate(Plane left, Vector3 right) + { + return (left.Normal.X * right.X) + (left.Normal.Y * right.Y) + (left.Normal.Z * right.Z) + left.D; + } + + /// + /// Calculates the dot product of the specified vector and the normal of the plane. + /// + /// The source plane. + /// The source vector. + /// When the method completes, contains the dot product of the specified vector and the normal of the plane. + public static void DotNormal(ref Plane left, ref Vector3 right, out float result) + { + result = (left.Normal.X * right.X) + (left.Normal.Y * right.Y) + (left.Normal.Z * right.Z); + } + + /// + /// Calculates the dot product of the specified vector and the normal of the plane. + /// + /// The source plane. + /// The source vector. + /// The dot product of the specified vector and the normal of the plane. + public static float DotNormal(Plane left, Vector3 right) + { + return (left.Normal.X * right.X) + (left.Normal.Y * right.Y) + (left.Normal.Z * right.Z); + } + + /// + /// Changes the coefficients of the normal vector of the plane to make it of unit length. + /// + /// The source plane. + /// When the method completes, contains the normalized plane. + public static void Normalize(ref Plane plane, out Plane result) + { + float magnitude = 1.0f / (float)(Math.Sqrt((plane.Normal.X * plane.Normal.X) + (plane.Normal.Y * plane.Normal.Y) + (plane.Normal.Z * plane.Normal.Z))); + + result.Normal.X = plane.Normal.X * magnitude; + result.Normal.Y = plane.Normal.Y * magnitude; + result.Normal.Z = plane.Normal.Z * magnitude; + result.D = plane.D * magnitude; + } + + /// + /// Changes the coefficients of the normal vector of the plane to make it of unit length. + /// + /// The source plane. + /// The normalized plane. + public static Plane Normalize(Plane plane) + { + float magnitude = 1.0f / (float)(Math.Sqrt((plane.Normal.X * plane.Normal.X) + (plane.Normal.Y * plane.Normal.Y) + (plane.Normal.Z * plane.Normal.Z))); + return new Plane(plane.Normal.X * magnitude, plane.Normal.Y * magnitude, plane.Normal.Z * magnitude, plane.D * magnitude); + } + + /// + /// Transforms a normalized plane by a quaternion rotation. + /// + /// The normalized source plane. + /// The quaternion rotation. + /// When the method completes, contains the transformed plane. + public static void Transform(ref Plane plane, ref Quaternion rotation, out Plane result) + { + float x2 = rotation.X + rotation.X; + float y2 = rotation.Y + rotation.Y; + float z2 = rotation.Z + rotation.Z; + float wx = rotation.W * x2; + float wy = rotation.W * y2; + float wz = rotation.W * z2; + float xx = rotation.X * x2; + float xy = rotation.X * y2; + float xz = rotation.X * z2; + float yy = rotation.Y * y2; + float yz = rotation.Y * z2; + float zz = rotation.Z * z2; + + float x = plane.Normal.X; + float y = plane.Normal.Y; + float z = plane.Normal.Z; + + result.Normal.X = ((x * ((1.0f - yy) - zz)) + (y * (xy - wz))) + (z * (xz + wy)); + result.Normal.Y = ((x * (xy + wz)) + (y * ((1.0f - xx) - zz))) + (z * (yz - wx)); + result.Normal.Z = ((x * (xz - wy)) + (y * (yz + wx))) + (z * ((1.0f - xx) - yy)); + result.D = plane.D; + } + + /// + /// Transforms a normalized plane by a quaternion rotation. + /// + /// The normalized source plane. + /// The quaternion rotation. + /// The transformed plane. + public static Plane Transform(Plane plane, Quaternion rotation) + { + Plane result; + float x2 = rotation.X + rotation.X; + float y2 = rotation.Y + rotation.Y; + float z2 = rotation.Z + rotation.Z; + float wx = rotation.W * x2; + float wy = rotation.W * y2; + float wz = rotation.W * z2; + float xx = rotation.X * x2; + float xy = rotation.X * y2; + float xz = rotation.X * z2; + float yy = rotation.Y * y2; + float yz = rotation.Y * z2; + float zz = rotation.Z * z2; + + float x = plane.Normal.X; + float y = plane.Normal.Y; + float z = plane.Normal.Z; + + result.Normal.X = ((x * ((1.0f - yy) - zz)) + (y * (xy - wz))) + (z * (xz + wy)); + result.Normal.Y = ((x * (xy + wz)) + (y * ((1.0f - xx) - zz))) + (z * (yz - wx)); + result.Normal.Z = ((x * (xz - wy)) + (y * (yz + wx))) + (z * ((1.0f - xx) - yy)); + result.D = plane.D; + + return result; + } + + /// + /// Transforms an array of normalized planes by a quaternion rotation. + /// + /// The array of normalized planes to transform. + /// The quaternion rotation. + /// Thrown when is null. + public static void Transform(Plane[] planes, ref Quaternion rotation) + { + if (planes == null) + throw new ArgumentNullException("planes"); + + float x2 = rotation.X + rotation.X; + float y2 = rotation.Y + rotation.Y; + float z2 = rotation.Z + rotation.Z; + float wx = rotation.W * x2; + float wy = rotation.W * y2; + float wz = rotation.W * z2; + float xx = rotation.X * x2; + float xy = rotation.X * y2; + float xz = rotation.X * z2; + float yy = rotation.Y * y2; + float yz = rotation.Y * z2; + float zz = rotation.Z * z2; + + for (int i = 0; i < planes.Length; ++i) + { + float x = planes[i].Normal.X; + float y = planes[i].Normal.Y; + float z = planes[i].Normal.Z; + + /* + * Note: + * Factor common arithmetic out of loop. + */ + planes[i].Normal.X = ((x * ((1.0f - yy) - zz)) + (y * (xy - wz))) + (z * (xz + wy)); + planes[i].Normal.Y = ((x * (xy + wz)) + (y * ((1.0f - xx) - zz))) + (z * (yz - wx)); + planes[i].Normal.Z = ((x * (xz - wy)) + (y * (yz + wx))) + (z * ((1.0f - xx) - yy)); + } + } + + /// + /// Transforms a normalized plane by a matrix. + /// + /// The normalized source plane. + /// The transformation matrix. + /// When the method completes, contains the transformed plane. + public static void Transform(ref Plane plane, ref Matrix transformation, out Plane result) + { + float x = plane.Normal.X; + float y = plane.Normal.Y; + float z = plane.Normal.Z; + float d = plane.D; + + Matrix inverse; + Matrix.Invert(ref transformation, out inverse); + + result.Normal.X = (((x * inverse.M11) + (y * inverse.M12)) + (z * inverse.M13)) + (d * inverse.M14); + result.Normal.Y = (((x * inverse.M21) + (y * inverse.M22)) + (z * inverse.M23)) + (d * inverse.M24); + result.Normal.Z = (((x * inverse.M31) + (y * inverse.M32)) + (z * inverse.M33)) + (d * inverse.M34); + result.D = (((x * inverse.M41) + (y * inverse.M42)) + (z * inverse.M43)) + (d * inverse.M44); + } + + /// + /// Transforms a normalized plane by a matrix. + /// + /// The normalized source plane. + /// The transformation matrix. + /// When the method completes, contains the transformed plane. + public static Plane Transform(Plane plane, Matrix transformation) + { + Plane result; + float x = plane.Normal.X; + float y = plane.Normal.Y; + float z = plane.Normal.Z; + float d = plane.D; + + transformation.Invert(); + result.Normal.X = (((x * transformation.M11) + (y * transformation.M12)) + (z * transformation.M13)) + (d * transformation.M14); + result.Normal.Y = (((x * transformation.M21) + (y * transformation.M22)) + (z * transformation.M23)) + (d * transformation.M24); + result.Normal.Z = (((x * transformation.M31) + (y * transformation.M32)) + (z * transformation.M33)) + (d * transformation.M34); + result.D = (((x * transformation.M41) + (y * transformation.M42)) + (z * transformation.M43)) + (d * transformation.M44); + + return result; + } + + /// + /// Transforms an array of normalized planes by a matrix. + /// + /// The array of normalized planes to transform. + /// The transformation matrix. + /// Thrown when is null. + public static void Transform(Plane[] planes, ref Matrix transformation) + { + if (planes == null) + throw new ArgumentNullException("planes"); + + Matrix inverse; + Matrix.Invert(ref transformation, out inverse); + + for (int i = 0; i < planes.Length; ++i) + { + Transform(ref planes[i], ref transformation, out planes[i]); + } + } + + /// + /// Scales a plane by the given value. + /// + /// The amount by which to scale the plane. + /// The plane to scale. + /// The scaled plane. + public static Plane operator *(float scale, Plane plane) + { + return new Plane(plane.Normal.X * scale, plane.Normal.Y * scale, plane.Normal.Z * scale, plane.D * scale); + } + + /// + /// Scales a plane by the given value. + /// + /// The plane to scale. + /// The amount by which to scale the plane. + /// The scaled plane. + public static Plane operator *(Plane plane, float scale) + { + return new Plane(plane.Normal.X * scale, plane.Normal.Y * scale, plane.Normal.Z * scale, plane.D * scale); + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has the same value as ; otherwise, false. + public static bool operator ==(Plane left, Plane right) + { + return left.Equals(right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has a different value than ; otherwise, false. + public static bool operator !=(Plane left, Plane right) + { + return !left.Equals(right); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return string.Format(CultureInfo.CurrentCulture, "A:{0} B:{1} C:{2} D:{3}", Normal.X, Normal.Y, Normal.Z, D); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// + /// A that represents this instance. + /// + public string ToString(string format) + { + return string.Format(CultureInfo.CurrentCulture, "A:{0} B:{1} C:{2} D:{3}", Normal.X.ToString(format, CultureInfo.CurrentCulture), + Normal.Y.ToString(format, CultureInfo.CurrentCulture), Normal.Z.ToString(format, CultureInfo.CurrentCulture), D.ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format(formatProvider, "A:{0} B:{1} C:{2} D:{3}", Normal.X, Normal.Y, Normal.Z, D); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(string format, IFormatProvider formatProvider) + { + return string.Format(formatProvider, "A:{0} B:{1} C:{2} D:{3}", Normal.X.ToString(format, formatProvider), + Normal.Y.ToString(format, formatProvider), Normal.Z.ToString(format, formatProvider), D.ToString(format, formatProvider)); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + unchecked + { + return (Normal.GetHashCode() * 397) ^ D.GetHashCode(); + } + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(Plane value) + { + return Normal == value.Normal && D == value.D; + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object value) + { + if (value == null) + return false; + + if (!ReferenceEquals(value.GetType(), typeof(Plane))) + return false; + + return Equals((Plane)value); + } + } +} diff --git a/Source/SharpDX.Mathematics/Properties/AssemblyInfo.cs b/Source/SharpDX.Mathematics/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..820aca937 --- /dev/null +++ b/Source/SharpDX.Mathematics/Properties/AssemblyInfo.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyProduct("SharpDX.Mathematics")] +[assembly: AssemblyTitle("SharpDX.Mathematics")] +[assembly: AssemblyDescription("Assembly providing Mathematics managed API")] diff --git a/Source/SharpDX/RandomUtil.cs b/Source/SharpDX.Mathematics/RandomUtil.cs similarity index 100% rename from Source/SharpDX/RandomUtil.cs rename to Source/SharpDX.Mathematics/RandomUtil.cs diff --git a/Source/SharpDX/Ray.cs b/Source/SharpDX.Mathematics/Ray.cs similarity index 96% rename from Source/SharpDX/Ray.cs rename to Source/SharpDX.Mathematics/Ray.cs index a4ccfd7ce..2ef7d7bc5 100644 --- a/Source/SharpDX/Ray.cs +++ b/Source/SharpDX.Mathematics/Ray.cs @@ -1,426 +1,417 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ----------------------------------------------------------------------------- -// Original code from SlimMath project. http://code.google.com/p/slimmath/ -// Greetings to SlimDX Group. Original code published with the following license: -// ----------------------------------------------------------------------------- -/* -* Copyright (c) 2007-2011 SlimDX Group -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using System.ComponentModel; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Represents a three dimensional line based on a point in space and a direction. - /// - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct Ray : IEquatable, IFormattable, IDataSerializable - { - /// - /// The position in three dimensional space where the ray starts. - /// - public Vector3 Position; - - /// - /// The normalized direction in which the ray points. - /// - public Vector3 Direction; - - /// - /// Initializes a new instance of the struct. - /// - /// The position in three dimensional space of the origin of the ray. - /// The normalized direction of the ray. - public Ray(Vector3 position, Vector3 direction) - { - this.Position = position; - this.Direction = direction; - } - - /// - /// Determines if there is an intersection between the current object and a point. - /// - /// The point to test. - /// Whether the two objects intersected. - public bool Intersects(ref Vector3 point) - { - return Collision.RayIntersectsPoint(ref this, ref point); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The ray to test. - /// Whether the two objects intersected. - public bool Intersects(ref Ray ray) - { - Vector3 point; - return Collision.RayIntersectsRay(ref this, ref ray, out point); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The ray to test. - /// When the method completes, contains the point of intersection, - /// or if there was no intersection. - /// Whether the two objects intersected. - public bool Intersects(ref Ray ray, out Vector3 point) - { - return Collision.RayIntersectsRay(ref this, ref ray, out point); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The plane to test - /// Whether the two objects intersected. - public bool Intersects(ref Plane plane) - { - float distance; - return Collision.RayIntersectsPlane(ref this, ref plane, out distance); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The plane to test. - /// When the method completes, contains the distance of the intersection, - /// or 0 if there was no intersection. - /// Whether the two objects intersected. - public bool Intersects(ref Plane plane, out float distance) - { - return Collision.RayIntersectsPlane(ref this, ref plane, out distance); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The plane to test. - /// When the method completes, contains the point of intersection, - /// or if there was no intersection. - /// Whether the two objects intersected. - public bool Intersects(ref Plane plane, out Vector3 point) - { - return Collision.RayIntersectsPlane(ref this, ref plane, out point); - } - - /// - /// Determines if there is an intersection between the current object and a triangle. - /// - /// The first vertex of the triangle to test. - /// The second vertex of the triangle to test. - /// The third vertex of the triangle to test. - /// Whether the two objects intersected. - public bool Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) - { - float distance; - return Collision.RayIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3, out distance); - } - - /// - /// Determines if there is an intersection between the current object and a triangle. - /// - /// The first vertex of the triangle to test. - /// The second vertex of the triangle to test. - /// The third vertex of the triangle to test. - /// When the method completes, contains the distance of the intersection, - /// or 0 if there was no intersection. - /// Whether the two objects intersected. - public bool Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3, out float distance) - { - return Collision.RayIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3, out distance); - } - - /// - /// Determines if there is an intersection between the current object and a triangle. - /// - /// The first vertex of the triangle to test. - /// The second vertex of the triangle to test. - /// The third vertex of the triangle to test. - /// When the method completes, contains the point of intersection, - /// or if there was no intersection. - /// Whether the two objects intersected. - public bool Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3, out Vector3 point) - { - return Collision.RayIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3, out point); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The box to test. - /// Whether the two objects intersected. - public bool Intersects(ref BoundingBox box) - { - float distance; - return Collision.RayIntersectsBox(ref this, ref box, out distance); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The box to test. - /// Whether the two objects intersected. - public bool Intersects(BoundingBox box) - { - return Intersects(ref box); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The box to test. - /// When the method completes, contains the distance of the intersection, - /// or 0 if there was no intersection. - /// Whether the two objects intersected. - public bool Intersects(ref BoundingBox box, out float distance) - { - return Collision.RayIntersectsBox(ref this, ref box, out distance); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The box to test. - /// When the method completes, contains the point of intersection, - /// or if there was no intersection. - /// Whether the two objects intersected. - public bool Intersects(ref BoundingBox box, out Vector3 point) - { - return Collision.RayIntersectsBox(ref this, ref box, out point); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The sphere to test. - /// Whether the two objects intersected. - public bool Intersects(ref BoundingSphere sphere) - { - float distance; - return Collision.RayIntersectsSphere(ref this, ref sphere, out distance); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The sphere to test. - /// Whether the two objects intersected. - public bool Intersects(BoundingSphere sphere) - { - return Intersects(ref sphere); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The sphere to test. - /// When the method completes, contains the distance of the intersection, - /// or 0 if there was no intersection. - /// Whether the two objects intersected. - public bool Intersects(ref BoundingSphere sphere, out float distance) - { - return Collision.RayIntersectsSphere(ref this, ref sphere, out distance); - } - - /// - /// Determines if there is an intersection between the current object and a . - /// - /// The sphere to test. - /// When the method completes, contains the point of intersection, - /// or if there was no intersection. - /// Whether the two objects intersected. - public bool Intersects(ref BoundingSphere sphere, out Vector3 point) - { - return Collision.RayIntersectsSphere(ref this, ref sphere, out point); - } - - /// - /// Calculates a world space from 2d screen coordinates. - /// - /// X coordinate on 2d screen. - /// Y coordinate on 2d screen. - /// . - /// Transformation . - /// Resulting . - public static Ray GetPickRay(int x, int y, ViewportF viewport, Matrix worldViewProjection) - { - var nearPoint = new Vector3(x, y, 0); - var farPoint = new Vector3(x, y, 1); - - nearPoint = Vector3.Unproject(nearPoint, viewport.X, viewport.Y, viewport.Width, viewport.Height, viewport.MinDepth, - viewport.MaxDepth, worldViewProjection); - farPoint = Vector3.Unproject(farPoint, viewport.X, viewport.Y, viewport.Width, viewport.Height, viewport.MinDepth, - viewport.MaxDepth, worldViewProjection); - - Vector3 direction = farPoint - nearPoint; - direction.Normalize(); - - return new Ray(nearPoint, direction); - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has the same value as ; otherwise, false. - public static bool operator ==(Ray left, Ray right) - { - return left.Equals(right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has a different value than ; otherwise, false. - public static bool operator !=(Ray left, Ray right) - { - return !left.Equals(right); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return string.Format(CultureInfo.CurrentCulture, "Position:{0} Direction:{1}", Position.ToString(), Direction.ToString()); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// - /// A that represents this instance. - /// - public string ToString(string format) - { - return string.Format(CultureInfo.CurrentCulture, "Position:{0} Direction:{1}", Position.ToString(format, CultureInfo.CurrentCulture), - Direction.ToString(format, CultureInfo.CurrentCulture)); - } - - /// - /// Returns a that represents this instance. - /// - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(IFormatProvider formatProvider) - { - return string.Format(formatProvider, "Position:{0} Direction:{1}", Position.ToString(), Direction.ToString()); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - return string.Format(formatProvider, "Position:{0} Direction:{1}", Position.ToString(format, formatProvider), - Direction.ToString(format, formatProvider)); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - return (Position.GetHashCode() * 397) ^ Direction.GetHashCode(); - } - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(Ray value) - { - return Position == value.Position && Direction == value.Direction; - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object value) - { - if (value == null) - return false; - - if (!ReferenceEquals(value.GetType(), typeof(Ray))) - return false; - - return Equals((Ray)value); - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - serializer.Serialize(ref Position); - serializer.Serialize(ref Direction); - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from SlimMath project. http://code.google.com/p/slimmath/ +// Greetings to SlimDX Group. Original code published with the following license: +// ----------------------------------------------------------------------------- +/* +* Copyright (c) 2007-2011 SlimDX Group +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Represents a three dimensional line based on a point in space and a direction. + /// + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct Ray : IEquatable, IFormattable + { + /// + /// The position in three dimensional space where the ray starts. + /// + public Vector3 Position; + + /// + /// The normalized direction in which the ray points. + /// + public Vector3 Direction; + + /// + /// Initializes a new instance of the struct. + /// + /// The position in three dimensional space of the origin of the ray. + /// The normalized direction of the ray. + public Ray(Vector3 position, Vector3 direction) + { + this.Position = position; + this.Direction = direction; + } + + /// + /// Determines if there is an intersection between the current object and a point. + /// + /// The point to test. + /// Whether the two objects intersected. + public bool Intersects(ref Vector3 point) + { + return Collision.RayIntersectsPoint(ref this, ref point); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The ray to test. + /// Whether the two objects intersected. + public bool Intersects(ref Ray ray) + { + Vector3 point; + return Collision.RayIntersectsRay(ref this, ref ray, out point); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The ray to test. + /// When the method completes, contains the point of intersection, + /// or if there was no intersection. + /// Whether the two objects intersected. + public bool Intersects(ref Ray ray, out Vector3 point) + { + return Collision.RayIntersectsRay(ref this, ref ray, out point); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The plane to test + /// Whether the two objects intersected. + public bool Intersects(ref Plane plane) + { + float distance; + return Collision.RayIntersectsPlane(ref this, ref plane, out distance); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The plane to test. + /// When the method completes, contains the distance of the intersection, + /// or 0 if there was no intersection. + /// Whether the two objects intersected. + public bool Intersects(ref Plane plane, out float distance) + { + return Collision.RayIntersectsPlane(ref this, ref plane, out distance); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The plane to test. + /// When the method completes, contains the point of intersection, + /// or if there was no intersection. + /// Whether the two objects intersected. + public bool Intersects(ref Plane plane, out Vector3 point) + { + return Collision.RayIntersectsPlane(ref this, ref plane, out point); + } + + /// + /// Determines if there is an intersection between the current object and a triangle. + /// + /// The first vertex of the triangle to test. + /// The second vertex of the triangle to test. + /// The third vertex of the triangle to test. + /// Whether the two objects intersected. + public bool Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3) + { + float distance; + return Collision.RayIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3, out distance); + } + + /// + /// Determines if there is an intersection between the current object and a triangle. + /// + /// The first vertex of the triangle to test. + /// The second vertex of the triangle to test. + /// The third vertex of the triangle to test. + /// When the method completes, contains the distance of the intersection, + /// or 0 if there was no intersection. + /// Whether the two objects intersected. + public bool Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3, out float distance) + { + return Collision.RayIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3, out distance); + } + + /// + /// Determines if there is an intersection between the current object and a triangle. + /// + /// The first vertex of the triangle to test. + /// The second vertex of the triangle to test. + /// The third vertex of the triangle to test. + /// When the method completes, contains the point of intersection, + /// or if there was no intersection. + /// Whether the two objects intersected. + public bool Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3, out Vector3 point) + { + return Collision.RayIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3, out point); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The box to test. + /// Whether the two objects intersected. + public bool Intersects(ref BoundingBox box) + { + float distance; + return Collision.RayIntersectsBox(ref this, ref box, out distance); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The box to test. + /// Whether the two objects intersected. + public bool Intersects(BoundingBox box) + { + return Intersects(ref box); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The box to test. + /// When the method completes, contains the distance of the intersection, + /// or 0 if there was no intersection. + /// Whether the two objects intersected. + public bool Intersects(ref BoundingBox box, out float distance) + { + return Collision.RayIntersectsBox(ref this, ref box, out distance); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The box to test. + /// When the method completes, contains the point of intersection, + /// or if there was no intersection. + /// Whether the two objects intersected. + public bool Intersects(ref BoundingBox box, out Vector3 point) + { + return Collision.RayIntersectsBox(ref this, ref box, out point); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The sphere to test. + /// Whether the two objects intersected. + public bool Intersects(ref BoundingSphere sphere) + { + float distance; + return Collision.RayIntersectsSphere(ref this, ref sphere, out distance); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The sphere to test. + /// Whether the two objects intersected. + public bool Intersects(BoundingSphere sphere) + { + return Intersects(ref sphere); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The sphere to test. + /// When the method completes, contains the distance of the intersection, + /// or 0 if there was no intersection. + /// Whether the two objects intersected. + public bool Intersects(ref BoundingSphere sphere, out float distance) + { + return Collision.RayIntersectsSphere(ref this, ref sphere, out distance); + } + + /// + /// Determines if there is an intersection between the current object and a . + /// + /// The sphere to test. + /// When the method completes, contains the point of intersection, + /// or if there was no intersection. + /// Whether the two objects intersected. + public bool Intersects(ref BoundingSphere sphere, out Vector3 point) + { + return Collision.RayIntersectsSphere(ref this, ref sphere, out point); + } + + /// + /// Calculates a world space from 2d screen coordinates. + /// + /// X coordinate on 2d screen. + /// Y coordinate on 2d screen. + /// . + /// Transformation . + /// Resulting . + public static Ray GetPickRay(int x, int y, ViewportF viewport, Matrix worldViewProjection) + { + var nearPoint = new Vector3(x, y, 0); + var farPoint = new Vector3(x, y, 1); + + nearPoint = Vector3.Unproject(nearPoint, viewport.X, viewport.Y, viewport.Width, viewport.Height, viewport.MinDepth, + viewport.MaxDepth, worldViewProjection); + farPoint = Vector3.Unproject(farPoint, viewport.X, viewport.Y, viewport.Width, viewport.Height, viewport.MinDepth, + viewport.MaxDepth, worldViewProjection); + + Vector3 direction = farPoint - nearPoint; + direction.Normalize(); + + return new Ray(nearPoint, direction); + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has the same value as ; otherwise, false. + public static bool operator ==(Ray left, Ray right) + { + return left.Equals(right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has a different value than ; otherwise, false. + public static bool operator !=(Ray left, Ray right) + { + return !left.Equals(right); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return string.Format(CultureInfo.CurrentCulture, "Position:{0} Direction:{1}", Position.ToString(), Direction.ToString()); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// + /// A that represents this instance. + /// + public string ToString(string format) + { + return string.Format(CultureInfo.CurrentCulture, "Position:{0} Direction:{1}", Position.ToString(format, CultureInfo.CurrentCulture), + Direction.ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format(formatProvider, "Position:{0} Direction:{1}", Position.ToString(), Direction.ToString()); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(string format, IFormatProvider formatProvider) + { + return string.Format(formatProvider, "Position:{0} Direction:{1}", Position.ToString(format, formatProvider), + Direction.ToString(format, formatProvider)); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + unchecked + { + return (Position.GetHashCode() * 397) ^ Direction.GetHashCode(); + } + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(Ray value) + { + return Position == value.Position && Direction == value.Direction; + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object value) + { + if (value == null) + return false; + + if (!ReferenceEquals(value.GetType(), typeof(Ray))) + return false; + + return Equals((Ray)value); + } + } +} diff --git a/Source/SharpDX.Mathematics/SharpDX.Mathematics.csproj b/Source/SharpDX.Mathematics/SharpDX.Mathematics.csproj new file mode 100644 index 000000000..fb31bf737 --- /dev/null +++ b/Source/SharpDX.Mathematics/SharpDX.Mathematics.csproj @@ -0,0 +1,51 @@ + + + + + 8.0.30703 + 2.0 + {49E4485F-3A2A-4C35-A159-12ECCFC00396} + SharpDX.Mathematics + SharpDX.Mathematics + + + + + + + + Properties\SharedAssemblyInfo.cs + + + + + + + + + + + + + + + + + + + + + + {d0bcd56a-41c4-4a4e-8590-26864ced07ff} + SharpDX + + + + + \ No newline at end of file diff --git a/Source/SharpDX.Mathematics/SharpDX.Mathematics.nuspec b/Source/SharpDX.Mathematics/SharpDX.Mathematics.nuspec new file mode 100644 index 000000000..f5c902901 --- /dev/null +++ b/Source/SharpDX.Mathematics/SharpDX.Mathematics.nuspec @@ -0,0 +1,49 @@ + + + + + SharpDX.Mathematics + $version$ + SharpDX.Mathematics + Alexandre Mutel + Alexandre Mutel + http://sharpdx.org/License.txt + http://sharpdx.org + http://sharpdx.org/logo_100x100.png + false + Assembly providing DirectX - Mathematics managed API. + Copyright (c) 2010-2013 Alexandre Mutel + SharpDX DirectX Direct3D MDX 3D Mathematics HLSL fx Shaders + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/SharpDX.MediaFoundation/AudioDecoder.cs b/Source/SharpDX.MediaFoundation/AudioDecoder.cs index 3464779e2..782928bbb 100644 --- a/Source/SharpDX.MediaFoundation/AudioDecoder.cs +++ b/Source/SharpDX.MediaFoundation/AudioDecoder.cs @@ -36,7 +36,7 @@ namespace SharpDX.MediaFoundation /// /// This class was developed following the "Tutorial: Decoding Audio" /// - public class AudioDecoder : Component + public class AudioDecoder : DisposeBase { private SourceReader sourceReader; private SourceReader nextSourceReader; @@ -236,16 +236,12 @@ private void CleanupAndDispose() private void CheckIfDisposed() { - if (IsDisposing) - throw new InvalidOperationException("This instance is being disposed while enumerating the samples."); if (IsDisposed) throw new InvalidOperationException("This instance is disposed while enumerating the samples."); } protected override void Dispose(bool disposeManagedResources) { - base.Dispose(disposeManagedResources); - CleanupAndDispose(); if (nextSourceReader != null) diff --git a/Source/SharpDX/Collections/EqualityComparer.cs b/Source/SharpDX/Collections/EqualityComparer.cs index 2c9fa7b3c..9e99be295 100644 --- a/Source/SharpDX/Collections/EqualityComparer.cs +++ b/Source/SharpDX/Collections/EqualityComparer.cs @@ -26,7 +26,7 @@ namespace SharpDX.Collections /// /// Provides for default value types. /// - public static class EqualityComparer + internal static class EqualityComparer { /// /// A default for . diff --git a/Source/SharpDX/DataBuffer.cs b/Source/SharpDX/DataBuffer.cs index 5474c021a..0a8b7b158 100644 --- a/Source/SharpDX/DataBuffer.cs +++ b/Source/SharpDX/DataBuffer.cs @@ -1,750 +1,748 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Runtime.InteropServices; -using SharpDX.Direct3D; - -namespace SharpDX -{ - /// - /// Provides methods to perform fast read/write random access data on a buffer located in an unmanaged memory. - /// - /// - /// This class doesn't validate the position read/write from. It is the responsibility of the client of this class - /// to verify that access is done within the size of the buffer. - /// - public class DataBuffer : Component - { - private unsafe sbyte* _buffer; - private GCHandle _gCHandle; - private Blob _blob; - private readonly bool _ownsBuffer; - private readonly int _size; - - /// - /// Creates the specified user buffer. - /// - /// Type of the buffer. - /// The buffer to use as a DataBuffer. - /// Index inside the buffer in terms of element count (not size in bytes). - /// True to keep the managed buffer and pin it, false will allocate unmanaged memory and make a copy of it. Default is true. - /// An instance of a DataBuffer - public static DataBuffer Create(T[] userBuffer, int index = 0, bool pinBuffer = true) where T : struct - { - unsafe - { - if (userBuffer == null) - throw new ArgumentNullException("userBuffer"); - - if (index < 0 || index > userBuffer.Length) - throw new ArgumentException("Index is out of range [0, userBuffer.Length-1]", "index"); - - DataBuffer buffer; - - var sizeOfBuffer = Utilities.SizeOf(userBuffer); - - if (pinBuffer) - { - var handle = GCHandle.Alloc(userBuffer, GCHandleType.Pinned); - var indexOffset = index * Utilities.SizeOf(); - buffer = new DataBuffer(indexOffset + (byte*)handle.AddrOfPinnedObject(), sizeOfBuffer - indexOffset, handle); - } - else - { - buffer = new DataBuffer(Interop.Fixed(userBuffer), sizeOfBuffer, true); - } - - return buffer; - } - } - - /// - /// Initializes a new instance of the class, and allocates a new buffer to use as a backing store. - /// - /// The size of the buffer to be allocated, in bytes. - /// - /// is less than 1. - public DataBuffer(int sizeInBytes) - { - unsafe - { - System.Diagnostics.Debug.Assert(sizeInBytes > 0); - - _buffer = (sbyte*)Utilities.AllocateMemory(sizeInBytes); - _size = sizeInBytes; - _ownsBuffer = true; - } - } - - /// - /// Initializes a new instance of the class. - /// - /// The data pointer. - public DataBuffer(DataPointer dataPointer) - : this(dataPointer.Pointer, dataPointer.Size) - { - } - - - /// - /// Initializes a new instance of the class, using an unmanaged buffer as a backing store. - /// - /// A pointer to the buffer to be used as a backing store. - /// The size of the buffer provided, in bytes. - public unsafe DataBuffer(IntPtr userBuffer, int sizeInBytes) - : this((void*)userBuffer, sizeInBytes, false) - { - } - - - internal unsafe DataBuffer(void* buffer, int sizeInBytes, GCHandle handle) - { - System.Diagnostics.Debug.Assert(sizeInBytes > 0); - - _buffer = (sbyte*)buffer; - _size = sizeInBytes; - _gCHandle = handle; - _ownsBuffer = false; - } - - internal unsafe DataBuffer(void* buffer, int sizeInBytes, bool makeCopy) - { - System.Diagnostics.Debug.Assert(sizeInBytes > 0); - - if (makeCopy) - { - _buffer = (sbyte*)Utilities.AllocateMemory(sizeInBytes); - Utilities.CopyMemory((IntPtr)_buffer, (IntPtr)buffer, sizeInBytes); - } - else - { - _buffer = (sbyte*)buffer; - } - _size = sizeInBytes; - _ownsBuffer = makeCopy; - } - - internal unsafe DataBuffer(Blob buffer) - { - System.Diagnostics.Debug.Assert(buffer.GetBufferSize() > 0); - - _buffer = (sbyte*)buffer.GetBufferPointer(); - _size = buffer.GetBufferSize(); - _blob = buffer; - } - - - /// - /// Releases unmanaged and - optionally - managed resources - /// - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. - protected override void Dispose(bool disposing) - { - if (disposing) - { - if (_blob != null) - { - _blob.Dispose(); - _blob = null; - } - } - - if (_gCHandle.IsAllocated) - _gCHandle.Free(); - - unsafe - { - if (_ownsBuffer && _buffer != (sbyte*)0) - { - Utilities.FreeMemory((IntPtr)_buffer); - _buffer = (sbyte*)0; - } - } - - base.Dispose(disposing); - } - - /// - /// Clears the buffer. - /// - public unsafe void Clear(byte value = 0) - { - Utilities.ClearMemory((IntPtr)_buffer, value, Size); - } - - /// - /// Gets a single value from the current buffer at the specified position. - /// - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// The type of the value to be read from the buffer. - /// The value that was read. - public T Get(int positionInBytes) where T : struct - { - unsafe - { - T result = default(T); - Utilities.Read((IntPtr)(_buffer + positionInBytes), ref result); - return result; - } - } - - /// - /// Gets a single value from the current buffer at the specified position. - /// - /// The type of the value to be read from the buffer. - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// The value as out. - /// The value that was read. - public void Get(int positionInBytes, out T value) where T : struct - { - unsafe - { - Utilities.ReadOut((IntPtr)(_buffer + positionInBytes), out value); - } - } - - /// - /// Gets a float. - /// - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// a float from the buffer - public float GetFloat(int positionInBytes) - { - unsafe - { - return *((float*)(_buffer + positionInBytes)); - } - } - - /// - /// Gets a int. - /// - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// an int from the buffer - public int GetInt(int positionInBytes) - { - unsafe - { - return *((int*)(_buffer + positionInBytes)); - } - } - - /// - /// Gets a short. - /// - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// an short from the buffer - public short GetShort(int positionInBytes) - { - unsafe - { - return *((short*)(_buffer + positionInBytes)); - } - } - - /// - /// Gets a bool. - /// - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// an bool from the buffer - public bool GetBoolean(int positionInBytes) - { - unsafe - { - return *((int*) (_buffer + positionInBytes)) != 0; - } - } - - /// - /// Gets a Vector2. - /// - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// an Vector2 from the buffer - public Vector2 GetVector2(int positionInBytes) - { - unsafe - { - return *((Vector2*)(_buffer + positionInBytes)); - } - } - - /// - /// Gets a Vector3. - /// - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// an Vector3 from the buffer - public Vector3 GetVector3(int positionInBytes) - { - unsafe - { - return *((Vector3*)(_buffer + positionInBytes)); - } - } - - /// - /// Gets a Vector4. - /// - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// an Vector4 from the buffer - public Vector4 GetVector4(int positionInBytes) - { - unsafe - { - return *((Vector4*)(_buffer + positionInBytes)); - } - } - - /// - /// Gets a Color3. - /// - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// an Color3 from the buffer - public Color3 GetColor3(int positionInBytes) - { - unsafe - { - return *((Color3*)(_buffer + positionInBytes)); - } - } - - /// - /// Gets a Color4. - /// - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// an Color4 from the buffer - public Color4 GetColor4(int positionInBytes) - { - unsafe - { - return *((Color4*)(_buffer + positionInBytes)); - } - } - - /// - /// Gets a Half. - /// - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// an Half from the buffer - public Half GetHalf(int positionInBytes) - { - unsafe - { - return *((Half*)(_buffer + positionInBytes)); - } - } - - /// - /// Gets a Half2. - /// - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// an Half2 from the buffer - public Half2 GetHalf2(int positionInBytes) - { - unsafe - { - return *((Half2*)(_buffer + positionInBytes)); - } - } - - /// - /// Gets a Half3. - /// - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// an Half3 from the buffer - public Half3 GetHalf3(int positionInBytes) - { - unsafe - { - return *((Half3*)(_buffer + positionInBytes)); - } - } - - /// - /// Gets a Half4. - /// - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// an Half4 from the buffer - public Half4 GetHalf4(int positionInBytes) - { - unsafe - { - return *((Half4*)(_buffer + positionInBytes)); - } - } - - /// - /// Gets a Matrix. - /// - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// a Matrix from the buffer - public Matrix GetMatrix(int positionInBytes) - { - unsafe - { - return *((Matrix*)(_buffer + positionInBytes)); - } - } - - /// - /// Gets a Quaternion. - /// - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// a Quaternion from the buffer - public Quaternion GetQuaternion(int positionInBytes) - { - unsafe - { - return *((Quaternion*)(_buffer + positionInBytes)); - } - } - - /// - /// Gets an array of values from a position in the buffer. - /// - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// number of T instance to get from the positionInBytes - /// The type of the values to be read from the buffer. - /// An array of values that was read from the current buffer. - public T[] GetRange(int positionInBytes, int count) where T : struct - { - unsafe - { - var result = new T[count]; - Utilities.Read((IntPtr)(_buffer + positionInBytes), result, 0, count); - return result; - } - } - - /// - /// Gets a sequence of elements from a position in the buffer into a target buffer. - /// - /// Relative position in bytes from the beginning of the buffer to get the data from. - /// An array of values to be read from the buffer. - /// The zero-based byte offset in buffer at which to begin storing - /// the data read from the current buffer. - /// The number of values to be read from the current buffer. - public void GetRange(int positionInBytes, T[] buffer, int offset, int count) where T : struct - { - unsafe - { - Utilities.Read((IntPtr) (_buffer + positionInBytes), buffer, offset, count); - } - } - - /// - /// Sets a single value to the buffer at a specified position. - /// - /// The type of the value to be written to the buffer. - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// The value to write to the buffer. - public void Set(int positionInBytes, ref T value) where T : struct - { - unsafe - { - Interop.CopyInline(_buffer + positionInBytes, ref value); - } - } - - /// - /// Sets a single value to the buffer at a specified position. - /// - /// The type of the value to be written to the buffer. - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// The value to write to the buffer. - public void Set(int positionInBytes, T value) where T : struct - { - unsafe - { - Interop.CopyInline(_buffer + positionInBytes, ref value); - } - } - - /// - /// Sets the specified value. - /// - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// The value. - public void Set(int positionInBytes, float value) - { - unsafe - { - *((float*)(_buffer + positionInBytes)) = value; - } - } - - /// - /// Sets the specified value. - /// - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// The value. - public void Set(int positionInBytes, int value) - { - unsafe - { - *((int*)(_buffer + positionInBytes)) = value; - } - } - - /// - /// Sets the specified value. - /// - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// The value. - public void Set(int positionInBytes, short value) - { - unsafe - { - *((short*)(_buffer + positionInBytes)) = value; - } - } - - /// - /// Sets the specified value. - /// - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// The value. - public void Set(int positionInBytes, bool value) - { - unsafe - { - *((int*)(_buffer + positionInBytes)) = value?1:0; - } - } - - /// - /// Sets the specified value. - /// - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// The value. - public void Set(int positionInBytes, Vector2 value) - { - unsafe - { - *((Vector2*)(_buffer + positionInBytes)) = value; - } - } - - /// - /// Sets the specified value. - /// - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// The value. - public void Set(int positionInBytes, Vector3 value) - { - unsafe - { - *((Vector3*)(_buffer + positionInBytes)) = value; - } - } - - /// - /// Sets the specified value. - /// - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// The value. - public void Set(int positionInBytes, Vector4 value) - { - unsafe - { - *((Vector4*)(_buffer + positionInBytes)) = value; - } - } - - /// - /// Sets the specified value. - /// - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// The value. - public void Set(int positionInBytes, Color3 value) - { - unsafe - { - *((Color3*)(_buffer + positionInBytes)) = value; - } - } - - /// - /// Sets the specified value. - /// - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// The value. - public void Set(int positionInBytes, Color4 value) - { - unsafe - { - *((Color4*)(_buffer + positionInBytes)) = value; - } - } - - /// - /// Sets the specified value. - /// - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// The value. - public void Set(int positionInBytes, Half value) - { - unsafe - { - *((Half*)(_buffer + positionInBytes)) = value; - } - } - - /// - /// Sets the specified value. - /// - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// The value. - public void Set(int positionInBytes, Half2 value) - { - unsafe - { - *((Half2*)(_buffer + positionInBytes)) = value; - } - } - - /// - /// Sets the specified value. - /// - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// The value. - public void Set(int positionInBytes, Half3 value) - { - unsafe - { - *((Half3*)(_buffer + positionInBytes)) = value; - } - } - - /// - /// Sets the specified value. - /// - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// The value. - public void Set(int positionInBytes, Half4 value) - { - unsafe - { - *((Half4*)(_buffer + positionInBytes)) = value; - } - } - - /// - /// Sets the specified value. - /// - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// The value. - public void Set(int positionInBytes, Matrix value) - { - unsafe - { - *((Matrix*)(_buffer + positionInBytes)) = value; - } - } - - /// - /// Sets the specified value. - /// - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// The value. - public void Set(int positionInBytes, Quaternion value) - { - unsafe - { - *((Quaternion*)(_buffer + positionInBytes)) = value; - } - } - - /// - /// Sets an array of values to a specified position into the buffer. - /// - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// An array of values to be written to the current buffer. - public void Set(int positionInBytes, T[] data) where T : struct - { - Set(positionInBytes, data, 0, data.Length); - } - - /// - /// Sets a range of data to a specified position into the buffer. - /// - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// A pointer to the location to start copying from. - /// The number of bytes to copy from source to the current buffer. - public void Set(int positionInBytes, IntPtr source, long count) - { - unsafe - { - Utilities.CopyMemory((IntPtr)(_buffer + positionInBytes), source, (int)count); - } - } - - /// - /// Sets an array of values to a specified position into the buffer. - /// - /// The type of the values to be written to the buffer. - /// Relative position in bytes from the beginning of the buffer to set the data to. - /// An array of values to be written to the buffer. - /// The zero-based offset in data at which to begin copying values to the current buffer. - /// The number of values to be written to the current buffer. If this is zero, - /// all of the contents will be written. - public void Set(int positionInBytes, T[] data, int offset, int count) where T : struct - { - unsafe - { - Utilities.Write((IntPtr)(_buffer + positionInBytes), data, offset, count); - } - } - - - /// - /// Gets a pointer to the buffer used as a backing store.. - /// - /// An IntPtr to the buffer being used as a backing store. - public IntPtr DataPointer - { - get - { - unsafe - { - return new IntPtr(_buffer); - } - } - } - - /// - /// Gets the length in bytes of the buffer. - /// - /// A long value representing the length of the buffer in bytes. - public int Size - { - get { return _size; } - } - - /// - /// Performs an explicit conversion from to . - /// - /// The from value. - /// The result of the conversion. - public static implicit operator DataPointer(DataBuffer from) - { - return new DataPointer(from.DataPointer, (int)from.Size); - } - } +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Runtime.InteropServices; +using SharpDX.Direct3D; + +namespace SharpDX +{ + /// + /// Provides methods to perform fast read/write random access data on a buffer located in an unmanaged memory. + /// + /// + /// This class doesn't validate the position read/write from. It is the responsibility of the client of this class + /// to verify that access is done within the size of the buffer. + /// + public class DataBuffer : DisposeBase + { + private unsafe sbyte* _buffer; + private GCHandle _gCHandle; + private Blob _blob; + private readonly bool _ownsBuffer; + private readonly int _size; + + /// + /// Creates the specified user buffer. + /// + /// Type of the buffer. + /// The buffer to use as a DataBuffer. + /// Index inside the buffer in terms of element count (not size in bytes). + /// True to keep the managed buffer and pin it, false will allocate unmanaged memory and make a copy of it. Default is true. + /// An instance of a DataBuffer + public static DataBuffer Create(T[] userBuffer, int index = 0, bool pinBuffer = true) where T : struct + { + unsafe + { + if (userBuffer == null) + throw new ArgumentNullException("userBuffer"); + + if (index < 0 || index > userBuffer.Length) + throw new ArgumentException("Index is out of range [0, userBuffer.Length-1]", "index"); + + DataBuffer buffer; + + var sizeOfBuffer = Utilities.SizeOf(userBuffer); + + if (pinBuffer) + { + var handle = GCHandle.Alloc(userBuffer, GCHandleType.Pinned); + var indexOffset = index * Utilities.SizeOf(); + buffer = new DataBuffer(indexOffset + (byte*)handle.AddrOfPinnedObject(), sizeOfBuffer - indexOffset, handle); + } + else + { + buffer = new DataBuffer(Interop.Fixed(userBuffer), sizeOfBuffer, true); + } + + return buffer; + } + } + + /// + /// Initializes a new instance of the class, and allocates a new buffer to use as a backing store. + /// + /// The size of the buffer to be allocated, in bytes. + /// + /// is less than 1. + public DataBuffer(int sizeInBytes) + { + unsafe + { + System.Diagnostics.Debug.Assert(sizeInBytes > 0); + + _buffer = (sbyte*)Utilities.AllocateMemory(sizeInBytes); + _size = sizeInBytes; + _ownsBuffer = true; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// The data pointer. + public DataBuffer(DataPointer dataPointer) + : this(dataPointer.Pointer, dataPointer.Size) + { + } + + + /// + /// Initializes a new instance of the class, using an unmanaged buffer as a backing store. + /// + /// A pointer to the buffer to be used as a backing store. + /// The size of the buffer provided, in bytes. + public unsafe DataBuffer(IntPtr userBuffer, int sizeInBytes) + : this((void*)userBuffer, sizeInBytes, false) + { + } + + + internal unsafe DataBuffer(void* buffer, int sizeInBytes, GCHandle handle) + { + System.Diagnostics.Debug.Assert(sizeInBytes > 0); + + _buffer = (sbyte*)buffer; + _size = sizeInBytes; + _gCHandle = handle; + _ownsBuffer = false; + } + + internal unsafe DataBuffer(void* buffer, int sizeInBytes, bool makeCopy) + { + System.Diagnostics.Debug.Assert(sizeInBytes > 0); + + if (makeCopy) + { + _buffer = (sbyte*)Utilities.AllocateMemory(sizeInBytes); + Utilities.CopyMemory((IntPtr)_buffer, (IntPtr)buffer, sizeInBytes); + } + else + { + _buffer = (sbyte*)buffer; + } + _size = sizeInBytes; + _ownsBuffer = makeCopy; + } + + internal unsafe DataBuffer(Blob buffer) + { + System.Diagnostics.Debug.Assert(buffer.GetBufferSize() > 0); + + _buffer = (sbyte*)buffer.GetBufferPointer(); + _size = buffer.GetBufferSize(); + _blob = buffer; + } + + + /// + /// Releases unmanaged and - optionally - managed resources + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (_blob != null) + { + _blob.Dispose(); + _blob = null; + } + } + + if (_gCHandle.IsAllocated) + _gCHandle.Free(); + + unsafe + { + if (_ownsBuffer && _buffer != (sbyte*)0) + { + Utilities.FreeMemory((IntPtr)_buffer); + _buffer = (sbyte*)0; + } + } + } + + /// + /// Clears the buffer. + /// + public unsafe void Clear(byte value = 0) + { + Utilities.ClearMemory((IntPtr)_buffer, value, Size); + } + + /// + /// Gets a single value from the current buffer at the specified position. + /// + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// The type of the value to be read from the buffer. + /// The value that was read. + public T Get(int positionInBytes) where T : struct + { + unsafe + { + T result = default(T); + Utilities.Read((IntPtr)(_buffer + positionInBytes), ref result); + return result; + } + } + + /// + /// Gets a single value from the current buffer at the specified position. + /// + /// The type of the value to be read from the buffer. + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// The value as out. + /// The value that was read. + public void Get(int positionInBytes, out T value) where T : struct + { + unsafe + { + Utilities.ReadOut((IntPtr)(_buffer + positionInBytes), out value); + } + } + + /// + /// Gets a float. + /// + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// a float from the buffer + public float GetFloat(int positionInBytes) + { + unsafe + { + return *((float*)(_buffer + positionInBytes)); + } + } + + /// + /// Gets a int. + /// + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// an int from the buffer + public int GetInt(int positionInBytes) + { + unsafe + { + return *((int*)(_buffer + positionInBytes)); + } + } + + /// + /// Gets a short. + /// + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// an short from the buffer + public short GetShort(int positionInBytes) + { + unsafe + { + return *((short*)(_buffer + positionInBytes)); + } + } + + /// + /// Gets a bool. + /// + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// an bool from the buffer + public bool GetBoolean(int positionInBytes) + { + unsafe + { + return *((int*) (_buffer + positionInBytes)) != 0; + } + } + + /// + /// Gets a Vector2. + /// + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// an Vector2 from the buffer + public Vector2 GetVector2(int positionInBytes) + { + unsafe + { + return *((Vector2*)(_buffer + positionInBytes)); + } + } + + /// + /// Gets a Vector3. + /// + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// an Vector3 from the buffer + public Vector3 GetVector3(int positionInBytes) + { + unsafe + { + return *((Vector3*)(_buffer + positionInBytes)); + } + } + + /// + /// Gets a Vector4. + /// + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// an Vector4 from the buffer + public Vector4 GetVector4(int positionInBytes) + { + unsafe + { + return *((Vector4*)(_buffer + positionInBytes)); + } + } + + /// + /// Gets a Color3. + /// + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// an Color3 from the buffer + public Color3 GetColor3(int positionInBytes) + { + unsafe + { + return *((Color3*)(_buffer + positionInBytes)); + } + } + + /// + /// Gets a Color4. + /// + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// an Color4 from the buffer + public Color4 GetColor4(int positionInBytes) + { + unsafe + { + return *((Color4*)(_buffer + positionInBytes)); + } + } + + /// + /// Gets a Half. + /// + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// an Half from the buffer + public Half GetHalf(int positionInBytes) + { + unsafe + { + return *((Half*)(_buffer + positionInBytes)); + } + } + + /// + /// Gets a Half2. + /// + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// an Half2 from the buffer + public Half2 GetHalf2(int positionInBytes) + { + unsafe + { + return *((Half2*)(_buffer + positionInBytes)); + } + } + + /// + /// Gets a Half3. + /// + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// an Half3 from the buffer + public Half3 GetHalf3(int positionInBytes) + { + unsafe + { + return *((Half3*)(_buffer + positionInBytes)); + } + } + + /// + /// Gets a Half4. + /// + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// an Half4 from the buffer + public Half4 GetHalf4(int positionInBytes) + { + unsafe + { + return *((Half4*)(_buffer + positionInBytes)); + } + } + + /// + /// Gets a Matrix. + /// + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// a Matrix from the buffer + public Matrix GetMatrix(int positionInBytes) + { + unsafe + { + return *((Matrix*)(_buffer + positionInBytes)); + } + } + + /// + /// Gets a Quaternion. + /// + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// a Quaternion from the buffer + public Quaternion GetQuaternion(int positionInBytes) + { + unsafe + { + return *((Quaternion*)(_buffer + positionInBytes)); + } + } + + /// + /// Gets an array of values from a position in the buffer. + /// + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// number of T instance to get from the positionInBytes + /// The type of the values to be read from the buffer. + /// An array of values that was read from the current buffer. + public T[] GetRange(int positionInBytes, int count) where T : struct + { + unsafe + { + var result = new T[count]; + Utilities.Read((IntPtr)(_buffer + positionInBytes), result, 0, count); + return result; + } + } + + /// + /// Gets a sequence of elements from a position in the buffer into a target buffer. + /// + /// Relative position in bytes from the beginning of the buffer to get the data from. + /// An array of values to be read from the buffer. + /// The zero-based byte offset in buffer at which to begin storing + /// the data read from the current buffer. + /// The number of values to be read from the current buffer. + public void GetRange(int positionInBytes, T[] buffer, int offset, int count) where T : struct + { + unsafe + { + Utilities.Read((IntPtr) (_buffer + positionInBytes), buffer, offset, count); + } + } + + /// + /// Sets a single value to the buffer at a specified position. + /// + /// The type of the value to be written to the buffer. + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// The value to write to the buffer. + public void Set(int positionInBytes, ref T value) where T : struct + { + unsafe + { + Interop.CopyInline(_buffer + positionInBytes, ref value); + } + } + + /// + /// Sets a single value to the buffer at a specified position. + /// + /// The type of the value to be written to the buffer. + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// The value to write to the buffer. + public void Set(int positionInBytes, T value) where T : struct + { + unsafe + { + Interop.CopyInline(_buffer + positionInBytes, ref value); + } + } + + /// + /// Sets the specified value. + /// + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// The value. + public void Set(int positionInBytes, float value) + { + unsafe + { + *((float*)(_buffer + positionInBytes)) = value; + } + } + + /// + /// Sets the specified value. + /// + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// The value. + public void Set(int positionInBytes, int value) + { + unsafe + { + *((int*)(_buffer + positionInBytes)) = value; + } + } + + /// + /// Sets the specified value. + /// + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// The value. + public void Set(int positionInBytes, short value) + { + unsafe + { + *((short*)(_buffer + positionInBytes)) = value; + } + } + + /// + /// Sets the specified value. + /// + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// The value. + public void Set(int positionInBytes, bool value) + { + unsafe + { + *((int*)(_buffer + positionInBytes)) = value?1:0; + } + } + + /// + /// Sets the specified value. + /// + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// The value. + public void Set(int positionInBytes, Vector2 value) + { + unsafe + { + *((Vector2*)(_buffer + positionInBytes)) = value; + } + } + + /// + /// Sets the specified value. + /// + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// The value. + public void Set(int positionInBytes, Vector3 value) + { + unsafe + { + *((Vector3*)(_buffer + positionInBytes)) = value; + } + } + + /// + /// Sets the specified value. + /// + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// The value. + public void Set(int positionInBytes, Vector4 value) + { + unsafe + { + *((Vector4*)(_buffer + positionInBytes)) = value; + } + } + + /// + /// Sets the specified value. + /// + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// The value. + public void Set(int positionInBytes, Color3 value) + { + unsafe + { + *((Color3*)(_buffer + positionInBytes)) = value; + } + } + + /// + /// Sets the specified value. + /// + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// The value. + public void Set(int positionInBytes, Color4 value) + { + unsafe + { + *((Color4*)(_buffer + positionInBytes)) = value; + } + } + + /// + /// Sets the specified value. + /// + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// The value. + public void Set(int positionInBytes, Half value) + { + unsafe + { + *((Half*)(_buffer + positionInBytes)) = value; + } + } + + /// + /// Sets the specified value. + /// + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// The value. + public void Set(int positionInBytes, Half2 value) + { + unsafe + { + *((Half2*)(_buffer + positionInBytes)) = value; + } + } + + /// + /// Sets the specified value. + /// + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// The value. + public void Set(int positionInBytes, Half3 value) + { + unsafe + { + *((Half3*)(_buffer + positionInBytes)) = value; + } + } + + /// + /// Sets the specified value. + /// + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// The value. + public void Set(int positionInBytes, Half4 value) + { + unsafe + { + *((Half4*)(_buffer + positionInBytes)) = value; + } + } + + /// + /// Sets the specified value. + /// + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// The value. + public void Set(int positionInBytes, Matrix value) + { + unsafe + { + *((Matrix*)(_buffer + positionInBytes)) = value; + } + } + + /// + /// Sets the specified value. + /// + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// The value. + public void Set(int positionInBytes, Quaternion value) + { + unsafe + { + *((Quaternion*)(_buffer + positionInBytes)) = value; + } + } + + /// + /// Sets an array of values to a specified position into the buffer. + /// + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// An array of values to be written to the current buffer. + public void Set(int positionInBytes, T[] data) where T : struct + { + Set(positionInBytes, data, 0, data.Length); + } + + /// + /// Sets a range of data to a specified position into the buffer. + /// + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// A pointer to the location to start copying from. + /// The number of bytes to copy from source to the current buffer. + public void Set(int positionInBytes, IntPtr source, long count) + { + unsafe + { + Utilities.CopyMemory((IntPtr)(_buffer + positionInBytes), source, (int)count); + } + } + + /// + /// Sets an array of values to a specified position into the buffer. + /// + /// The type of the values to be written to the buffer. + /// Relative position in bytes from the beginning of the buffer to set the data to. + /// An array of values to be written to the buffer. + /// The zero-based offset in data at which to begin copying values to the current buffer. + /// The number of values to be written to the current buffer. If this is zero, + /// all of the contents will be written. + public void Set(int positionInBytes, T[] data, int offset, int count) where T : struct + { + unsafe + { + Utilities.Write((IntPtr)(_buffer + positionInBytes), data, offset, count); + } + } + + + /// + /// Gets a pointer to the buffer used as a backing store.. + /// + /// An IntPtr to the buffer being used as a backing store. + public IntPtr DataPointer + { + get + { + unsafe + { + return new IntPtr(_buffer); + } + } + } + + /// + /// Gets the length in bytes of the buffer. + /// + /// A long value representing the length of the buffer in bytes. + public int Size + { + get { return _size; } + } + + /// + /// Performs an explicit conversion from to . + /// + /// The from value. + /// The result of the conversion. + public static implicit operator DataPointer(DataBuffer from) + { + return new DataPointer(from.DataPointer, (int)from.Size); + } + } } \ No newline at end of file diff --git a/Source/SharpDX/CompilationException.cs b/Source/SharpDX/Direct3D/CompilationException.cs similarity index 100% rename from Source/SharpDX/CompilationException.cs rename to Source/SharpDX/Direct3D/CompilationException.cs diff --git a/Source/SharpDX/CompilationResultBase.cs b/Source/SharpDX/Direct3D/CompilationResultBase.cs similarity index 100% rename from Source/SharpDX/CompilationResultBase.cs rename to Source/SharpDX/Direct3D/CompilationResultBase.cs diff --git a/Source/SharpDX/Direct3D/Mapping.xml b/Source/SharpDX/Direct3D/Mapping.xml index 22220b7a6..4e8274ecf 100644 --- a/Source/SharpDX/Direct3D/Mapping.xml +++ b/Source/SharpDX/Direct3D/Mapping.xml @@ -1,143 +1,143 @@ - - - - sharpdx-core - - SharpDX - SharpDX.Direct3D - - - - - - - ID3D10Multithread - - - - - - - d3dcommon - - new System.Guid("$1") - - - - - - - - - - - - - d3d10 - - - - - d3dcommon - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + sharpdx-core + + SharpDX + SharpDX.Direct3D + + + + + + + ID3D10Multithread + + + + + + + d3dcommon + + new System.Guid("$1") + + + + + + + + + + + + + d3d10 + + + + + d3dcommon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/SharpDX/Direct3D/ShaderMacro.cs b/Source/SharpDX/Direct3D/ShaderMacro.cs index 16a2bdef5..2f2fb4a08 100644 --- a/Source/SharpDX/Direct3D/ShaderMacro.cs +++ b/Source/SharpDX/Direct3D/ShaderMacro.cs @@ -1,80 +1,72 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; - -using SharpDX.Serialization; - -namespace SharpDX.Direct3D -{ - public partial struct ShaderMacro : IEquatable, IDataSerializable - { - /// - /// Initializes a new instance of the struct. - /// - /// - /// The name. - /// - /// - /// The definition. - /// - public ShaderMacro(string name, object definition) - { - Name = name; - Definition = definition == null ? null : definition.ToString(); - } - - public bool Equals(ShaderMacro other) - { - return string.Equals(this.Name, other.Name) && string.Equals(this.Definition, other.Definition); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) - return false; - return obj is ShaderMacro && Equals((ShaderMacro)obj); - } - - public override int GetHashCode() - { - unchecked - { - return ((this.Name != null ? this.Name.GetHashCode() : 0) * 397) ^ (this.Definition != null ? this.Definition.GetHashCode() : 0); - } - } - - void IDataSerializable.Serialize(BinarySerializer serializer) - { - serializer.Serialize(ref Name); - serializer.Serialize(ref Definition, SerializeFlags.Nullable); - } - - public static bool operator ==(ShaderMacro left, ShaderMacro right) - { - return left.Equals(right); - } - - public static bool operator !=(ShaderMacro left, ShaderMacro right) - { - return !left.Equals(right); - } - } +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; + +namespace SharpDX.Direct3D +{ + public partial struct ShaderMacro : IEquatable + { + /// + /// Initializes a new instance of the struct. + /// + /// + /// The name. + /// + /// + /// The definition. + /// + public ShaderMacro(string name, object definition) + { + Name = name; + Definition = definition == null ? null : definition.ToString(); + } + + public bool Equals(ShaderMacro other) + { + return string.Equals(this.Name, other.Name) && string.Equals(this.Definition, other.Definition); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + return false; + return obj is ShaderMacro && Equals((ShaderMacro)obj); + } + + public override int GetHashCode() + { + unchecked + { + return ((this.Name != null ? this.Name.GetHashCode() : 0) * 397) ^ (this.Definition != null ? this.Definition.GetHashCode() : 0); + } + } + + public static bool operator ==(ShaderMacro left, ShaderMacro right) + { + return left.Equals(right); + } + + public static bool operator !=(ShaderMacro left, ShaderMacro right) + { + return !left.Equals(right); + } + } } \ No newline at end of file diff --git a/Source/SharpDX/DisposeCollector.cs b/Source/SharpDX/DisposeCollector.cs index afe6e72fc..d1dde1a88 100644 --- a/Source/SharpDX/DisposeCollector.cs +++ b/Source/SharpDX/DisposeCollector.cs @@ -98,12 +98,6 @@ public T Collect(T toDispose) throw new ArgumentException("Memory pointer is invalid. Memory must have been allocated with Utilties.AllocateMemory"); } - var toDisposeComponent = toDispose as Component; - - // If this is a component and It's already attached, don't add it - if (toDisposeComponent != null && toDisposeComponent.IsAttached) - return toDispose; - if (!Equals(toDispose, default(T))) { if (disposables == null) @@ -112,10 +106,6 @@ public T Collect(T toDispose) if (!disposables.Contains(toDispose)) { disposables.Add(toDispose); - - // Set attached flag for Component - if (toDisposeComponent != null) - toDisposeComponent.IsAttached = true; } } return toDispose; @@ -157,11 +147,6 @@ public void Remove(T toDisposeArg) if (disposables != null && disposables.Contains(toDisposeArg)) { disposables.Remove(toDisposeArg); - - // Set not attached flag - var toDisposeComponent = toDisposeArg as Component; - if (toDisposeComponent != null) - toDisposeComponent.IsAttached = false; } } } diff --git a/Source/SharpDX/Mapping.xml b/Source/SharpDX/Mapping.xml index 937355c46..feba74b35 100644 --- a/Source/SharpDX/Mapping.xml +++ b/Source/SharpDX/Mapping.xml @@ -1,32 +1,32 @@ - - - - sharpdx-root - sharpdx-core - sharpdx-core-direct3d - sharpdx-core-multimedia - - Mapping-core.xml - Direct3D\Mapping.xml - Multimedia\Mapping.xml + + + + sharpdx-root + sharpdx-core + sharpdx-core-direct3d + sharpdx-core-multimedia + + Mapping-core.xml + Direct3D\Mapping.xml + Multimedia\Mapping.xml \ No newline at end of file diff --git a/Source/SharpDX/Bool.cs b/Source/SharpDX/Mathematics/Bool.cs similarity index 88% rename from Source/SharpDX/Bool.cs rename to Source/SharpDX/Mathematics/Bool.cs index ba39db152..e87c174c8 100644 --- a/Source/SharpDX/Bool.cs +++ b/Source/SharpDX/Mathematics/Bool.cs @@ -20,7 +20,6 @@ using System; using System.Runtime.InteropServices; -using SharpDX.Serialization; namespace SharpDX { @@ -28,8 +27,7 @@ namespace SharpDX /// A boolean value stored on 4 bytes (instead of 1 in .NET). /// [StructLayout(LayoutKind.Sequential, Size = 4)] - [DynamicSerializer("TKB1")] - public struct Bool : IEquatable, IDataSerializable + public struct Bool : IEquatable { private int boolValue; @@ -110,20 +108,5 @@ public override string ToString() { return string.Format("{0}", boolValue != 0); } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(boolValue); - } - else - { - boolValue = serializer.Reader.ReadInt32(); - } - } - } } \ No newline at end of file diff --git a/Source/SharpDX/Bool4.cs b/Source/SharpDX/Mathematics/Bool4.cs similarity index 93% rename from Source/SharpDX/Bool4.cs rename to Source/SharpDX/Mathematics/Bool4.cs index 15a0d8f70..160fc3da1 100644 --- a/Source/SharpDX/Bool4.cs +++ b/Source/SharpDX/Mathematics/Bool4.cs @@ -20,7 +20,6 @@ using System; using System.Globalization; using System.Runtime.InteropServices; -using SharpDX.Serialization; namespace SharpDX { @@ -28,8 +27,7 @@ namespace SharpDX /// Represents a four dimensional mathematical vector of bool (32 bits per bool value). /// [StructLayout(LayoutKind.Sequential, Pack = 4)] - [DynamicSerializer("TKB4")] - public struct Bool4 : IEquatable, IFormattable, IDataSerializable + public struct Bool4 : IEquatable, IFormattable { /// /// The size of the type, in bytes. @@ -365,25 +363,5 @@ public static implicit operator bool[](Bool4 input) { return input.ToArray(); } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(iX); - serializer.Writer.Write(iY); - serializer.Writer.Write(iZ); - serializer.Writer.Write(iW); - } - else - { - iX = serializer.Reader.ReadInt32(); - iY = serializer.Reader.ReadInt32(); - iZ = serializer.Reader.ReadInt32(); - iW = serializer.Reader.ReadInt32(); - } - } } } diff --git a/Source/SharpDX/Color.Palette.cs b/Source/SharpDX/Mathematics/Color.Palette.cs similarity index 100% rename from Source/SharpDX/Color.Palette.cs rename to Source/SharpDX/Mathematics/Color.Palette.cs diff --git a/Source/SharpDX/Color.cs b/Source/SharpDX/Mathematics/Color.cs similarity index 96% rename from Source/SharpDX/Color.cs rename to Source/SharpDX/Mathematics/Color.cs index 696c11dba..d0483cb8d 100644 --- a/Source/SharpDX/Color.cs +++ b/Source/SharpDX/Mathematics/Color.cs @@ -1,1246 +1,1230 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Represents a 32-bit color (4 bytes) in the form of RGBA (in byte order: R, G, B, A). - /// - [StructLayout(LayoutKind.Sequential, Size = 4)] - [DynamicSerializer("TKC1")] - public partial struct Color : IEquatable, IFormattable, IDataSerializable - { - private const string toStringFormat = "A:{0} R:{1} G:{2} B:{3}"; - - /// - /// The red component of the color. - /// - public byte R; - - /// - /// The green component of the color. - /// - public byte G; - - /// - /// The blue component of the color. - /// - public byte B; - - /// - /// The alpha component of the color. - /// - public byte A; - - /// - /// Initializes a new instance of the struct. - /// - /// The value that will be assigned to all components. - public Color(byte value) - { - A = R = G = B = value; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The value that will be assigned to all components. - public Color(float value) - { - A = R = G = B = ToByte(value); - } - - /// - /// Initializes a new instance of the struct. - /// - /// The red component of the color. - /// The green component of the color. - /// The blue component of the color. - /// The alpha component of the color. - public Color(byte red, byte green, byte blue, byte alpha) - { - R = red; - G = green; - B = blue; - A = alpha; - } - - /// - /// Initializes a new instance of the struct. Alpha is set to 255. - /// - /// The red component of the color. - /// The green component of the color. - /// The blue component of the color. - public Color(byte red, byte green, byte blue) - { - R = red; - G = green; - B = blue; - A = 255; - } - - /// - /// Initializes a new instance of the struct. Passed values are clamped within byte range. - /// - /// The red component of the color. - /// The green component of the color. - /// The blue component of the color. - public Color(int red, int green, int blue, int alpha) - { - R = ToByte(red); - G = ToByte(green); - B = ToByte(blue); - A = ToByte(alpha); - } - - /// - /// Initializes a new instance of the struct. Alpha is set to 255. Passed values are clamped within byte range. - /// - /// The red component of the color. - /// The green component of the color. - /// The blue component of the color. - public Color(int red, int green, int blue) - : this (red, green, blue, 255) { } - - /// - /// Initializes a new instance of the struct. - /// - /// The red component of the color. - /// The green component of the color. - /// The blue component of the color. - /// The alpha component of the color. - public Color(float red, float green, float blue, float alpha) - { - R = ToByte(red); - G = ToByte(green); - B = ToByte(blue); - A = ToByte(alpha); - } - - /// - /// Initializes a new instance of the struct. Alpha is set to 255. - /// - /// The red component of the color. - /// The green component of the color. - /// The blue component of the color. - public Color(float red, float green, float blue) - { - R = ToByte(red); - G = ToByte(green); - B = ToByte(blue); - A = 255; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The red, green, blue, and alpha components of the color. - public Color(Vector4 value) - { - R = ToByte(value.X); - G = ToByte(value.Y); - B = ToByte(value.Z); - A = ToByte(value.W); - } - - /// - /// Initializes a new instance of the struct. - /// - /// The red, green, and blue components of the color. - /// The alpha component of the color. - public Color(Vector3 value, float alpha) - { - R = ToByte(value.X); - G = ToByte(value.Y); - B = ToByte(value.Z); - A = ToByte(alpha); - } - - /// - /// Initializes a new instance of the struct. Alpha is set to 255. - /// - /// The red, green, and blue components of the color. - public Color(Vector3 value) - { - R = ToByte(value.X); - G = ToByte(value.Y); - B = ToByte(value.Z); - A = 255; - } - - /// - /// Initializes a new instance of the struct. - /// - /// A packed integer containing all four color components in RGBA order. - public Color(uint rgba) - { - A = (byte)((rgba >> 24) & 255); - B = (byte)((rgba >> 16) & 255); - G = (byte)((rgba >> 8) & 255); - R = (byte)(rgba & 255); - } - - /// - /// Initializes a new instance of the struct. - /// - /// A packed integer containing all four color components in RGBA order. - public Color(int rgba) - { - A = (byte)((rgba >> 24) & 255); - B = (byte)((rgba >> 16) & 255); - G = (byte)((rgba >> 8) & 255); - R = (byte)(rgba & 255); - } - - /// - /// Initializes a new instance of the struct. - /// - /// The values to assign to the red, green, and blue, alpha components of the color. This must be an array with four elements. - /// Thrown when is null. - /// Thrown when contains more or less than four elements. - public Color(float[] values) - { - if (values == null) - throw new ArgumentNullException("values"); - if (values.Length != 4) - throw new ArgumentOutOfRangeException("values", "There must be four and only four input values for Color."); - - R = ToByte(values[0]); - G = ToByte(values[1]); - B = ToByte(values[2]); - A = ToByte(values[3]); - } - - /// - /// Initializes a new instance of the struct. - /// - /// The values to assign to the alpha, red, green, and blue components of the color. This must be an array with four elements. - /// Thrown when is null. - /// Thrown when contains more or less than four elements. - public Color(byte[] values) - { - if (values == null) - throw new ArgumentNullException("values"); - if (values.Length != 4) - throw new ArgumentOutOfRangeException("values", "There must be four and only four input values for Color."); - - R = values[0]; - G = values[1]; - B = values[2]; - A = values[3]; - } - - /// - /// Gets or sets the component at the specified index. - /// - /// The value of the alpha, red, green, or blue component, depending on the index. - /// The index of the component to access. Use 0 for the alpha component, 1 for the red component, 2 for the green component, and 3 for the blue component. - /// The value of the component at the specified index. - /// Thrown when the is out of the range [0, 3]. - public byte this[int index] - { - get - { - switch (index) - { - case 0: return R; - case 1: return G; - case 2: return B; - case 3: return A; - } - - throw new ArgumentOutOfRangeException("index", "Indices for Color run from 0 to 3, inclusive."); - } - - set - { - switch (index) - { - case 0: R = value; break; - case 1: G = value; break; - case 2: B = value; break; - case 3: A = value; break; - default: throw new ArgumentOutOfRangeException("index", "Indices for Color run from 0 to 3, inclusive."); - } - } - } - - /// - /// Converts the color into a packed integer. - /// - /// A packed integer containing all four color components. - public int ToBgra() - { - int value = B; - value |= G << 8; - value |= R << 16; - value |= A << 24; - - return (int)value; - } - - /// - /// Converts the color into a packed integer. - /// - /// A packed integer containing all four color components. - public int ToRgba() - { - int value = R; - value |= G << 8; - value |= B << 16; - value |= A << 24; - - return (int)value; - } - - /// - /// Converts the color into a packed integer. - /// - /// A packed integer containing all four color components. - public int ToAbgr() - { - int value = A; - value |= B << 8; - value |= G << 16; - value |= R << 24; - - return (int)value; - } - - /// - /// Converts the color into a three component vector. - /// - /// A three component vector containing the red, green, and blue components of the color. - public Vector3 ToVector3() - { - return new Vector3(R / 255.0f, G / 255.0f, B / 255.0f); - } - - /// - /// Converts the color into a three component color. - /// - /// A three component color containing the red, green, and blue components of the color. - public Color3 ToColor3() - { - return new Color3(R / 255.0f, G / 255.0f, B / 255.0f); - } - - /// - /// Converts the color into a four component vector. - /// - /// A four component vector containing all four color components. - public Vector4 ToVector4() - { - return new Vector4(R / 255.0f, G / 255.0f, B / 255.0f, A / 255.0f); - } - - /// - /// Creates an array containing the elements of the color. - /// - /// A four-element array containing the components of the color in RGBA order. - public byte[] ToArray() - { - return new [] { R, G , B, A }; - } - - /// - /// Gets the brightness. - /// - /// The Hue-Saturation-Brightness (HSB) saturation for this - public float GetBrightness() - { - float r = (float)R / 255.0f; - float g = (float)G / 255.0f; - float b = (float)B / 255.0f; - - float max, min; - - max = r; min = r; - - if (g > max) max = g; - if (b > max) max = b; - - if (g < min) min = g; - if (b < min) min = b; - - return (max + min) / 2; - } - - /// - /// Gets the hue. - /// - /// The Hue-Saturation-Brightness (HSB) saturation for this - public float GetHue() - { - if (R == G && G == B) - return 0; // 0 makes as good an UNDEFINED value as any - - float r = (float)R / 255.0f; - float g = (float)G / 255.0f; - float b = (float)B / 255.0f; - - float max, min; - float delta; - float hue = 0.0f; - - max = r; min = r; - - if (g > max) max = g; - if (b > max) max = b; - - if (g < min) min = g; - if (b < min) min = b; - - delta = max - min; - - if (r == max) - { - hue = (g - b) / delta; - } - else if (g == max) - { - hue = 2 + (b - r) / delta; - } - else if (b == max) - { - hue = 4 + (r - g) / delta; - } - hue *= 60; - - if (hue < 0.0f) - { - hue += 360.0f; - } - return hue; - } - - /// - /// Gets the saturation. - /// - /// The Hue-Saturation-Brightness (HSB) saturation for this - public float GetSaturation() - { - float r = (float)R / 255.0f; - float g = (float)G / 255.0f; - float b = (float)B / 255.0f; - - float max, min; - float l, s = 0; - - max = r; min = r; - - if (g > max) max = g; - if (b > max) max = b; - - if (g < min) min = g; - if (b < min) min = b; - - // if max == min, then there is no color and - // the saturation is zero. - // - if (max != min) - { - l = (max + min) / 2; - - if (l <= .5) - { - s = (max - min) / (max + min); - } - else - { - s = (max - min) / (2 - max - min); - } - } - return s; - } - - /// - /// Adds two colors. - /// - /// The first color to add. - /// The second color to add. - /// When the method completes, completes the sum of the two colors. - public static void Add(ref Color left, ref Color right, out Color result) - { - result.A = (byte)(left.A + right.A); - result.R = (byte)(left.R + right.R); - result.G = (byte)(left.G + right.G); - result.B = (byte)(left.B + right.B); - } - - /// - /// Adds two colors. - /// - /// The first color to add. - /// The second color to add. - /// The sum of the two colors. - public static Color Add(Color left, Color right) - { - return new Color(left.R + right.R, left.G + right.G, left.B + right.B, left.A + right.A); - } - - /// - /// Subtracts two colors. - /// - /// The first color to subtract. - /// The second color to subtract. - /// WHen the method completes, contains the difference of the two colors. - public static void Subtract(ref Color left, ref Color right, out Color result) - { - result.A = (byte)(left.A - right.A); - result.R = (byte)(left.R - right.R); - result.G = (byte)(left.G - right.G); - result.B = (byte)(left.B - right.B); - } - - /// - /// Subtracts two colors. - /// - /// The first color to subtract. - /// The second color to subtract - /// The difference of the two colors. - public static Color Subtract(Color left, Color right) - { - return new Color(left.R - right.R, left.G - right.G, left.B - right.B, left.A - right.A); - } - - /// - /// Modulates two colors. - /// - /// The first color to modulate. - /// The second color to modulate. - /// When the method completes, contains the modulated color. - public static void Modulate(ref Color left, ref Color right, out Color result) - { - result.A = (byte)(left.A * right.A / 255.0f); - result.R = (byte)(left.R * right.R / 255.0f); - result.G = (byte)(left.G * right.G / 255.0f); - result.B = (byte)(left.B * right.B / 255.0f); - } - - /// - /// Modulates two colors. - /// - /// The first color to modulate. - /// The second color to modulate. - /// The modulated color. - public static Color Modulate(Color left, Color right) - { - return new Color(left.R * right.R, left.G * right.G, left.B * right.B, left.A * right.A); - } - - /// - /// Scales a color. - /// - /// The color to scale. - /// The amount by which to scale. - /// When the method completes, contains the scaled color. - public static void Scale(ref Color value, float scale, out Color result) - { - result.A = (byte)(value.A * scale); - result.R = (byte)(value.R * scale); - result.G = (byte)(value.G * scale); - result.B = (byte)(value.B * scale); - } - - /// - /// Scales a color. - /// - /// The color to scale. - /// The amount by which to scale. - /// The scaled color. - public static Color Scale(Color value, float scale) - { - return new Color((byte)(value.R * scale), (byte)(value.G * scale), (byte)(value.B * scale), (byte)(value.A * scale)); - } - - /// - /// Negates a color. - /// - /// The color to negate. - /// When the method completes, contains the negated color. - public static void Negate(ref Color value, out Color result) - { - result.A = (byte)(255 - value.A); - result.R = (byte)(255 - value.R); - result.G = (byte)(255 - value.G); - result.B = (byte)(255 - value.B); - } - - /// - /// Negates a color. - /// - /// The color to negate. - /// The negated color. - public static Color Negate(Color value) - { - return new Color(255 - value.R, 255 - value.G, 255 - value.B, 255 - value.A); - } - - /// - /// Restricts a value to be within a specified range. - /// - /// The value to clamp. - /// The minimum value. - /// The maximum value. - /// When the method completes, contains the clamped value. - public static void Clamp(ref Color value, ref Color min, ref Color max, out Color result) - { - byte alpha = value.A; - alpha = (alpha > max.A) ? max.A : alpha; - alpha = (alpha < min.A) ? min.A : alpha; - - byte red = value.R; - red = (red > max.R) ? max.R : red; - red = (red < min.R) ? min.R : red; - - byte green = value.G; - green = (green > max.G) ? max.G : green; - green = (green < min.G) ? min.G : green; - - byte blue = value.B; - blue = (blue > max.B) ? max.B : blue; - blue = (blue < min.B) ? min.B : blue; - - result = new Color(red, green, blue, alpha); - } - - /// - /// Computes the premultiplied value of the provided color. - /// - /// The non-premultiplied value. - /// The premultiplied result. - public static void Premultiply(ref Color value, out Color result) - { - var a = value.A / (255f * 255f); - result.A = value.A; - result.R = ToByte(value.R * a); - result.G = ToByte(value.G * a); - result.B = ToByte(value.B * a); - } - - /// - /// Computes the premultiplied value of the provided color. - /// - /// The non-premultiplied value. - /// The premultiplied result. - public static Color Premultiply(Color value) - { - Color result; - Premultiply(ref value, out result); - return result; - } - - /// - /// Converts the color from a packed BGRA integer. - /// - /// A packed integer containing all four color components in BGRA order - /// A color. - public static Color FromBgra(int color) - { - return new Color((byte)((color >> 16) & 255), (byte)((color >> 8) & 255), (byte)(color & 255), (byte)((color >> 24) & 255)); - } - - /// - /// Converts the color from a packed BGRA integer. - /// - /// A packed integer containing all four color components in BGRA order - /// A color. - public static Color FromBgra(uint color) - { - return FromBgra(unchecked((int) color)); - } - - /// - /// Converts the color from a packed ABGR integer. - /// - /// A packed integer containing all four color components in ABGR order - /// A color. - public static Color FromAbgr(int color) - { - return new Color((byte)(color >> 24), (byte)(color >> 16), (byte)(color >> 8), (byte)color); - } - - /// - /// Converts the color from a packed ABGR integer. - /// - /// A packed integer containing all four color components in ABGR order - /// A color. - public static Color FromAbgr(uint color) - { - return FromAbgr(unchecked((int)color)); - } - - /// - /// Converts the color from a packed BGRA integer. - /// - /// A packed integer containing all four color components in RGBA order - /// A color. - public static Color FromRgba(int color) - { - return new Color(color); - } - - /// - /// Converts the color from a packed BGRA integer. - /// - /// A packed integer containing all four color components in RGBA order - /// A color. - public static Color FromRgba(uint color) - { - return new Color(color); - } - - /// - /// Restricts a value to be within a specified range. - /// - /// The value to clamp. - /// The minimum value. - /// The maximum value. - /// The clamped value. - public static Color Clamp(Color value, Color min, Color max) - { - Color result; - Clamp(ref value, ref min, ref max, out result); - return result; - } - - /// - /// Performs a linear interpolation between two colors. - /// - /// Start color. - /// End color. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the linear interpolation of the two colors. - /// - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static void Lerp(ref Color start, ref Color end, float amount, out Color result) - { - result.R = MathUtil.Lerp(start.R, end.R, amount); - result.G = MathUtil.Lerp(start.G, end.G, amount); - result.B = MathUtil.Lerp(start.B, end.B, amount); - result.A = MathUtil.Lerp(start.A, end.A, amount); - } - - /// - /// Performs a linear interpolation between two colors. - /// - /// Start color. - /// End color. - /// Value between 0 and 1 indicating the weight of . - /// The linear interpolation of the two colors. - /// - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static Color Lerp(Color start, Color end, float amount) - { - Color result; - Lerp(ref start, ref end, amount, out result); - return result; - } - - /// - /// Performs a cubic interpolation between two colors. - /// - /// Start color. - /// End color. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the cubic interpolation of the two colors. - public static void SmoothStep(ref Color start, ref Color end, float amount, out Color result) - { - amount = MathUtil.SmoothStep(amount); - Lerp(ref start, ref end, amount, out result); - } - - /// - /// Performs a cubic interpolation between two colors. - /// - /// Start color. - /// End color. - /// Value between 0 and 1 indicating the weight of . - /// The cubic interpolation of the two colors. - public static Color SmoothStep(Color start, Color end, float amount) - { - Color result; - SmoothStep(ref start, ref end, amount, out result); - return result; - } - - /// - /// Returns a color containing the smallest components of the specified colors. - /// - /// The first source color. - /// The second source color. - /// When the method completes, contains an new color composed of the largest components of the source colors. - public static void Max(ref Color left, ref Color right, out Color result) - { - result.A = (left.A > right.A) ? left.A : right.A; - result.R = (left.R > right.R) ? left.R : right.R; - result.G = (left.G > right.G) ? left.G : right.G; - result.B = (left.B > right.B) ? left.B : right.B; - } - - /// - /// Returns a color containing the largest components of the specified colorss. - /// - /// The first source color. - /// The second source color. - /// A color containing the largest components of the source colors. - public static Color Max(Color left, Color right) - { - Color result; - Max(ref left, ref right, out result); - return result; - } - - /// - /// Returns a color containing the smallest components of the specified colors. - /// - /// The first source color. - /// The second source color. - /// When the method completes, contains an new color composed of the smallest components of the source colors. - public static void Min(ref Color left, ref Color right, out Color result) - { - result.A = (left.A < right.A) ? left.A : right.A; - result.R = (left.R < right.R) ? left.R : right.R; - result.G = (left.G < right.G) ? left.G : right.G; - result.B = (left.B < right.B) ? left.B : right.B; - } - - /// - /// Returns a color containing the smallest components of the specified colors. - /// - /// The first source color. - /// The second source color. - /// A color containing the smallest components of the source colors. - public static Color Min(Color left, Color right) - { - Color result; - Min(ref left, ref right, out result); - return result; - } - - /// - /// Adjusts the contrast of a color. - /// - /// The color whose contrast is to be adjusted. - /// The amount by which to adjust the contrast. - /// When the method completes, contains the adjusted color. - public static void AdjustContrast(ref Color value, float contrast, out Color result) - { - result.A = value.A; - result.R = ToByte(0.5f + contrast * (value.R / 255.0f - 0.5f)); - result.G = ToByte(0.5f + contrast * (value.G / 255.0f - 0.5f)); - result.B = ToByte(0.5f + contrast * (value.B / 255.0f - 0.5f)); - } - - /// - /// Adjusts the contrast of a color. - /// - /// The color whose contrast is to be adjusted. - /// The amount by which to adjust the contrast. - /// The adjusted color. - public static Color AdjustContrast(Color value, float contrast) - { - return new Color( - ToByte(0.5f + contrast * (value.R / 255.0f - 0.5f)), - ToByte(0.5f + contrast * (value.G / 255.0f - 0.5f)), - ToByte(0.5f + contrast * (value.B / 255.0f- 0.5f)), - value.A); - } - - /// - /// Adjusts the saturation of a color. - /// - /// The color whose saturation is to be adjusted. - /// The amount by which to adjust the saturation. - /// When the method completes, contains the adjusted color. - public static void AdjustSaturation(ref Color value, float saturation, out Color result) - { - float grey = value.R / 255.0f * 0.2125f + value.G / 255.0f * 0.7154f + value.B / 255.0f * 0.0721f; - - result.A = value.A; - result.R = ToByte(grey + saturation * (value.R / 255.0f - grey)); - result.G = ToByte(grey + saturation * (value.G / 255.0f- grey)); - result.B = ToByte(grey + saturation * (value.B / 255.0f - grey)); - } - - /// - /// Adjusts the saturation of a color. - /// - /// The color whose saturation is to be adjusted. - /// The amount by which to adjust the saturation. - /// The adjusted color. - public static Color AdjustSaturation(Color value, float saturation) - { - float grey = value.R / 255.0f * 0.2125f + value.G / 255.0f * 0.7154f + value.B / 255.0f * 0.0721f; - - return new Color( - ToByte(grey + saturation * (value.R / 255.0f - grey)), - ToByte(grey + saturation * (value.G / 255.0f - grey)), - ToByte(grey + saturation * (value.B / 255.0f - grey)), - value.A); - } - - /// - /// Adds two colors. - /// - /// The first color to add. - /// The second color to add. - /// The sum of the two colors. - public static Color operator +(Color left, Color right) - { - return new Color(left.R + right.R, left.G + right.G, left.B + right.B, left.A + right.A); - } - - /// - /// Assert a color (return it unchanged). - /// - /// The color to assert (unchanged). - /// The asserted (unchanged) color. - public static Color operator +(Color value) - { - return value; - } - - /// - /// Subtracts two colors. - /// - /// The first color to subtract. - /// The second color to subtract. - /// The difference of the two colors. - public static Color operator -(Color left, Color right) - { - return new Color(left.R - right.R, left.G - right.G, left.B - right.B, left.A - right.A); - } - - /// - /// Negates a color. - /// - /// The color to negate. - /// A negated color. - public static Color operator -(Color value) - { - return new Color(-value.R, -value.G, -value.B, -value.A); - } - - /// - /// Scales a color. - /// - /// The factor by which to scale the color. - /// The color to scale. - /// The scaled color. - public static Color operator *(float scale, Color value) - { - return new Color((byte)(value.R * scale), (byte)(value.G * scale), (byte)(value.B * scale), (byte)(value.A * scale)); - } - - /// - /// Scales a color. - /// - /// The factor by which to scale the color. - /// The color to scale. - /// The scaled color. - public static Color operator *(Color value, float scale) - { - return new Color((byte)(value.R * scale), (byte)(value.G * scale), (byte)(value.B * scale), (byte)(value.A * scale)); - } - - /// - /// Modulates two colors. - /// - /// The first color to modulate. - /// The second color to modulate. - /// The modulated color. - public static Color operator *(Color left, Color right) - { - return new Color((byte)(left.R * right.R / 255.0f), (byte)(left.G * right.G / 255.0f), (byte)(left.B * right.B / 255.0f), (byte)(left.A * right.A / 255.0f)); - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has the same value as ; otherwise, false. - public static bool operator ==(Color left, Color right) - { - return left.Equals(right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has a different value than ; otherwise, false. - public static bool operator !=(Color left, Color right) - { - return !left.Equals(right); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Color3(Color value) - { - return value.ToColor3(); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Vector3(Color value) - { - return new Vector3(value.R / 255.0f, value.G / 255.0f, value.B / 255.0f); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Vector4(Color value) - { - return new Vector4(value.R / 255.0f, value.G / 255.0f, value.B / 255.0f, value.A / 255.0f); - } - - /// - /// Convert this instance to a - /// - /// The result of the conversion. - public Color4 ToColor4() - { - return new Color4(R / 255.0f, G / 255.0f, B / 255.0f, A / 255.0f); - } - - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Color4(Color value) - { - return value.ToColor4(); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Color(Vector3 value) - { - return new Color(value.X, value.Y, value.Z, 1.0f); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Color(Color3 value) - { - return new Color(value.Red, value.Green, value.Blue, 1.0f); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Color(Vector4 value) - { - return new Color(value.X, value.Y, value.Z, value.W); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Color(Color4 value) - { - return new Color(value.Red, value.Green, value.Blue, value.Alpha); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// - /// The result of the conversion. - /// - public static explicit operator int(Color value) - { - return value.ToRgba(); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// - /// The result of the conversion. - /// - public static explicit operator Color(int value) - { - return new Color(value); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return ToString(CultureInfo.CurrentCulture); - } - - /// - /// Returns a that represents this instance. - /// - /// The format to apply to each channel element (byte). - /// - /// A that represents this instance. - /// - public string ToString(string format) - { - return ToString(format, CultureInfo.CurrentCulture); - } - - /// - /// Returns a that represents this instance. - /// - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(IFormatProvider formatProvider) - { - return string.Format(formatProvider, toStringFormat, A, R, G, B); - } - - /// - /// Returns a that represents this instance. - /// - /// The format to apply to each channel element (byte). - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - if (format == null) - return ToString(formatProvider); - - return string.Format(formatProvider, - toStringFormat, - A.ToString(format, formatProvider), - R.ToString(format, formatProvider), - G.ToString(format, formatProvider), - B.ToString(format, formatProvider)); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - var hashCode = R.GetHashCode(); - hashCode = (hashCode * 397) ^ G.GetHashCode(); - hashCode = (hashCode * 397) ^ B.GetHashCode(); - hashCode = (hashCode * 397) ^ A.GetHashCode(); - return hashCode; - } - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(Color other) - { - return R == other.R && G == other.G && B == other.B && A == other.A; - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object value) - { - if (value == null) - return false; - - if (!ReferenceEquals(value.GetType(), typeof(Color))) - return false; - - return Equals((Color)value); - } - - private static byte ToByte(float component) - { - var value = (int)(component * 255.0f); - return ToByte(value); - } - - public static byte ToByte(int value) - { - return (byte)(value < 0 ? 0 : value > 255 ? 255 : value); - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(ToRgba()); - } - else - { - this = FromRgba(serializer.Reader.ReadInt32()); - } - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Represents a 32-bit color (4 bytes) in the form of RGBA (in byte order: R, G, B, A). + /// + [StructLayout(LayoutKind.Sequential, Size = 4)] + public partial struct Color : IEquatable, IFormattable + { + private const string toStringFormat = "A:{0} R:{1} G:{2} B:{3}"; + + /// + /// The red component of the color. + /// + public byte R; + + /// + /// The green component of the color. + /// + public byte G; + + /// + /// The blue component of the color. + /// + public byte B; + + /// + /// The alpha component of the color. + /// + public byte A; + + /// + /// Initializes a new instance of the struct. + /// + /// The value that will be assigned to all components. + public Color(byte value) + { + A = R = G = B = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value that will be assigned to all components. + public Color(float value) + { + A = R = G = B = ToByte(value); + } + + /// + /// Initializes a new instance of the struct. + /// + /// The red component of the color. + /// The green component of the color. + /// The blue component of the color. + /// The alpha component of the color. + public Color(byte red, byte green, byte blue, byte alpha) + { + R = red; + G = green; + B = blue; + A = alpha; + } + + /// + /// Initializes a new instance of the struct. Alpha is set to 255. + /// + /// The red component of the color. + /// The green component of the color. + /// The blue component of the color. + public Color(byte red, byte green, byte blue) + { + R = red; + G = green; + B = blue; + A = 255; + } + + /// + /// Initializes a new instance of the struct. Passed values are clamped within byte range. + /// + /// The red component of the color. + /// The green component of the color. + /// The blue component of the color. + public Color(int red, int green, int blue, int alpha) + { + R = ToByte(red); + G = ToByte(green); + B = ToByte(blue); + A = ToByte(alpha); + } + + /// + /// Initializes a new instance of the struct. Alpha is set to 255. Passed values are clamped within byte range. + /// + /// The red component of the color. + /// The green component of the color. + /// The blue component of the color. + public Color(int red, int green, int blue) + : this (red, green, blue, 255) { } + + /// + /// Initializes a new instance of the struct. + /// + /// The red component of the color. + /// The green component of the color. + /// The blue component of the color. + /// The alpha component of the color. + public Color(float red, float green, float blue, float alpha) + { + R = ToByte(red); + G = ToByte(green); + B = ToByte(blue); + A = ToByte(alpha); + } + + /// + /// Initializes a new instance of the struct. Alpha is set to 255. + /// + /// The red component of the color. + /// The green component of the color. + /// The blue component of the color. + public Color(float red, float green, float blue) + { + R = ToByte(red); + G = ToByte(green); + B = ToByte(blue); + A = 255; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The red, green, blue, and alpha components of the color. + public Color(Vector4 value) + { + R = ToByte(value.X); + G = ToByte(value.Y); + B = ToByte(value.Z); + A = ToByte(value.W); + } + + /// + /// Initializes a new instance of the struct. + /// + /// The red, green, and blue components of the color. + /// The alpha component of the color. + public Color(Vector3 value, float alpha) + { + R = ToByte(value.X); + G = ToByte(value.Y); + B = ToByte(value.Z); + A = ToByte(alpha); + } + + /// + /// Initializes a new instance of the struct. Alpha is set to 255. + /// + /// The red, green, and blue components of the color. + public Color(Vector3 value) + { + R = ToByte(value.X); + G = ToByte(value.Y); + B = ToByte(value.Z); + A = 255; + } + + /// + /// Initializes a new instance of the struct. + /// + /// A packed integer containing all four color components in RGBA order. + public Color(uint rgba) + { + A = (byte)((rgba >> 24) & 255); + B = (byte)((rgba >> 16) & 255); + G = (byte)((rgba >> 8) & 255); + R = (byte)(rgba & 255); + } + + /// + /// Initializes a new instance of the struct. + /// + /// A packed integer containing all four color components in RGBA order. + public Color(int rgba) + { + A = (byte)((rgba >> 24) & 255); + B = (byte)((rgba >> 16) & 255); + G = (byte)((rgba >> 8) & 255); + R = (byte)(rgba & 255); + } + + /// + /// Initializes a new instance of the struct. + /// + /// The values to assign to the red, green, and blue, alpha components of the color. This must be an array with four elements. + /// Thrown when is null. + /// Thrown when contains more or less than four elements. + public Color(float[] values) + { + if (values == null) + throw new ArgumentNullException("values"); + if (values.Length != 4) + throw new ArgumentOutOfRangeException("values", "There must be four and only four input values for Color."); + + R = ToByte(values[0]); + G = ToByte(values[1]); + B = ToByte(values[2]); + A = ToByte(values[3]); + } + + /// + /// Initializes a new instance of the struct. + /// + /// The values to assign to the alpha, red, green, and blue components of the color. This must be an array with four elements. + /// Thrown when is null. + /// Thrown when contains more or less than four elements. + public Color(byte[] values) + { + if (values == null) + throw new ArgumentNullException("values"); + if (values.Length != 4) + throw new ArgumentOutOfRangeException("values", "There must be four and only four input values for Color."); + + R = values[0]; + G = values[1]; + B = values[2]; + A = values[3]; + } + + /// + /// Gets or sets the component at the specified index. + /// + /// The value of the alpha, red, green, or blue component, depending on the index. + /// The index of the component to access. Use 0 for the alpha component, 1 for the red component, 2 for the green component, and 3 for the blue component. + /// The value of the component at the specified index. + /// Thrown when the is out of the range [0, 3]. + public byte this[int index] + { + get + { + switch (index) + { + case 0: return R; + case 1: return G; + case 2: return B; + case 3: return A; + } + + throw new ArgumentOutOfRangeException("index", "Indices for Color run from 0 to 3, inclusive."); + } + + set + { + switch (index) + { + case 0: R = value; break; + case 1: G = value; break; + case 2: B = value; break; + case 3: A = value; break; + default: throw new ArgumentOutOfRangeException("index", "Indices for Color run from 0 to 3, inclusive."); + } + } + } + + /// + /// Converts the color into a packed integer. + /// + /// A packed integer containing all four color components. + public int ToBgra() + { + int value = B; + value |= G << 8; + value |= R << 16; + value |= A << 24; + + return (int)value; + } + + /// + /// Converts the color into a packed integer. + /// + /// A packed integer containing all four color components. + public int ToRgba() + { + int value = R; + value |= G << 8; + value |= B << 16; + value |= A << 24; + + return (int)value; + } + + /// + /// Converts the color into a packed integer. + /// + /// A packed integer containing all four color components. + public int ToAbgr() + { + int value = A; + value |= B << 8; + value |= G << 16; + value |= R << 24; + + return (int)value; + } + + /// + /// Converts the color into a three component vector. + /// + /// A three component vector containing the red, green, and blue components of the color. + public Vector3 ToVector3() + { + return new Vector3(R / 255.0f, G / 255.0f, B / 255.0f); + } + + /// + /// Converts the color into a three component color. + /// + /// A three component color containing the red, green, and blue components of the color. + public Color3 ToColor3() + { + return new Color3(R / 255.0f, G / 255.0f, B / 255.0f); + } + + /// + /// Converts the color into a four component vector. + /// + /// A four component vector containing all four color components. + public Vector4 ToVector4() + { + return new Vector4(R / 255.0f, G / 255.0f, B / 255.0f, A / 255.0f); + } + + /// + /// Creates an array containing the elements of the color. + /// + /// A four-element array containing the components of the color in RGBA order. + public byte[] ToArray() + { + return new [] { R, G , B, A }; + } + + /// + /// Gets the brightness. + /// + /// The Hue-Saturation-Brightness (HSB) saturation for this + public float GetBrightness() + { + float r = (float)R / 255.0f; + float g = (float)G / 255.0f; + float b = (float)B / 255.0f; + + float max, min; + + max = r; min = r; + + if (g > max) max = g; + if (b > max) max = b; + + if (g < min) min = g; + if (b < min) min = b; + + return (max + min) / 2; + } + + /// + /// Gets the hue. + /// + /// The Hue-Saturation-Brightness (HSB) saturation for this + public float GetHue() + { + if (R == G && G == B) + return 0; // 0 makes as good an UNDEFINED value as any + + float r = (float)R / 255.0f; + float g = (float)G / 255.0f; + float b = (float)B / 255.0f; + + float max, min; + float delta; + float hue = 0.0f; + + max = r; min = r; + + if (g > max) max = g; + if (b > max) max = b; + + if (g < min) min = g; + if (b < min) min = b; + + delta = max - min; + + if (r == max) + { + hue = (g - b) / delta; + } + else if (g == max) + { + hue = 2 + (b - r) / delta; + } + else if (b == max) + { + hue = 4 + (r - g) / delta; + } + hue *= 60; + + if (hue < 0.0f) + { + hue += 360.0f; + } + return hue; + } + + /// + /// Gets the saturation. + /// + /// The Hue-Saturation-Brightness (HSB) saturation for this + public float GetSaturation() + { + float r = (float)R / 255.0f; + float g = (float)G / 255.0f; + float b = (float)B / 255.0f; + + float max, min; + float l, s = 0; + + max = r; min = r; + + if (g > max) max = g; + if (b > max) max = b; + + if (g < min) min = g; + if (b < min) min = b; + + // if max == min, then there is no color and + // the saturation is zero. + // + if (max != min) + { + l = (max + min) / 2; + + if (l <= .5) + { + s = (max - min) / (max + min); + } + else + { + s = (max - min) / (2 - max - min); + } + } + return s; + } + + /// + /// Adds two colors. + /// + /// The first color to add. + /// The second color to add. + /// When the method completes, completes the sum of the two colors. + public static void Add(ref Color left, ref Color right, out Color result) + { + result.A = (byte)(left.A + right.A); + result.R = (byte)(left.R + right.R); + result.G = (byte)(left.G + right.G); + result.B = (byte)(left.B + right.B); + } + + /// + /// Adds two colors. + /// + /// The first color to add. + /// The second color to add. + /// The sum of the two colors. + public static Color Add(Color left, Color right) + { + return new Color(left.R + right.R, left.G + right.G, left.B + right.B, left.A + right.A); + } + + /// + /// Subtracts two colors. + /// + /// The first color to subtract. + /// The second color to subtract. + /// WHen the method completes, contains the difference of the two colors. + public static void Subtract(ref Color left, ref Color right, out Color result) + { + result.A = (byte)(left.A - right.A); + result.R = (byte)(left.R - right.R); + result.G = (byte)(left.G - right.G); + result.B = (byte)(left.B - right.B); + } + + /// + /// Subtracts two colors. + /// + /// The first color to subtract. + /// The second color to subtract + /// The difference of the two colors. + public static Color Subtract(Color left, Color right) + { + return new Color(left.R - right.R, left.G - right.G, left.B - right.B, left.A - right.A); + } + + /// + /// Modulates two colors. + /// + /// The first color to modulate. + /// The second color to modulate. + /// When the method completes, contains the modulated color. + public static void Modulate(ref Color left, ref Color right, out Color result) + { + result.A = (byte)(left.A * right.A / 255.0f); + result.R = (byte)(left.R * right.R / 255.0f); + result.G = (byte)(left.G * right.G / 255.0f); + result.B = (byte)(left.B * right.B / 255.0f); + } + + /// + /// Modulates two colors. + /// + /// The first color to modulate. + /// The second color to modulate. + /// The modulated color. + public static Color Modulate(Color left, Color right) + { + return new Color(left.R * right.R, left.G * right.G, left.B * right.B, left.A * right.A); + } + + /// + /// Scales a color. + /// + /// The color to scale. + /// The amount by which to scale. + /// When the method completes, contains the scaled color. + public static void Scale(ref Color value, float scale, out Color result) + { + result.A = (byte)(value.A * scale); + result.R = (byte)(value.R * scale); + result.G = (byte)(value.G * scale); + result.B = (byte)(value.B * scale); + } + + /// + /// Scales a color. + /// + /// The color to scale. + /// The amount by which to scale. + /// The scaled color. + public static Color Scale(Color value, float scale) + { + return new Color((byte)(value.R * scale), (byte)(value.G * scale), (byte)(value.B * scale), (byte)(value.A * scale)); + } + + /// + /// Negates a color. + /// + /// The color to negate. + /// When the method completes, contains the negated color. + public static void Negate(ref Color value, out Color result) + { + result.A = (byte)(255 - value.A); + result.R = (byte)(255 - value.R); + result.G = (byte)(255 - value.G); + result.B = (byte)(255 - value.B); + } + + /// + /// Negates a color. + /// + /// The color to negate. + /// The negated color. + public static Color Negate(Color value) + { + return new Color(255 - value.R, 255 - value.G, 255 - value.B, 255 - value.A); + } + + /// + /// Restricts a value to be within a specified range. + /// + /// The value to clamp. + /// The minimum value. + /// The maximum value. + /// When the method completes, contains the clamped value. + public static void Clamp(ref Color value, ref Color min, ref Color max, out Color result) + { + byte alpha = value.A; + alpha = (alpha > max.A) ? max.A : alpha; + alpha = (alpha < min.A) ? min.A : alpha; + + byte red = value.R; + red = (red > max.R) ? max.R : red; + red = (red < min.R) ? min.R : red; + + byte green = value.G; + green = (green > max.G) ? max.G : green; + green = (green < min.G) ? min.G : green; + + byte blue = value.B; + blue = (blue > max.B) ? max.B : blue; + blue = (blue < min.B) ? min.B : blue; + + result = new Color(red, green, blue, alpha); + } + + /// + /// Computes the premultiplied value of the provided color. + /// + /// The non-premultiplied value. + /// The premultiplied result. + public static void Premultiply(ref Color value, out Color result) + { + var a = value.A / (255f * 255f); + result.A = value.A; + result.R = ToByte(value.R * a); + result.G = ToByte(value.G * a); + result.B = ToByte(value.B * a); + } + + /// + /// Computes the premultiplied value of the provided color. + /// + /// The non-premultiplied value. + /// The premultiplied result. + public static Color Premultiply(Color value) + { + Color result; + Premultiply(ref value, out result); + return result; + } + + /// + /// Converts the color from a packed BGRA integer. + /// + /// A packed integer containing all four color components in BGRA order + /// A color. + public static Color FromBgra(int color) + { + return new Color((byte)((color >> 16) & 255), (byte)((color >> 8) & 255), (byte)(color & 255), (byte)((color >> 24) & 255)); + } + + /// + /// Converts the color from a packed BGRA integer. + /// + /// A packed integer containing all four color components in BGRA order + /// A color. + public static Color FromBgra(uint color) + { + return FromBgra(unchecked((int) color)); + } + + /// + /// Converts the color from a packed ABGR integer. + /// + /// A packed integer containing all four color components in ABGR order + /// A color. + public static Color FromAbgr(int color) + { + return new Color((byte)(color >> 24), (byte)(color >> 16), (byte)(color >> 8), (byte)color); + } + + /// + /// Converts the color from a packed ABGR integer. + /// + /// A packed integer containing all four color components in ABGR order + /// A color. + public static Color FromAbgr(uint color) + { + return FromAbgr(unchecked((int)color)); + } + + /// + /// Converts the color from a packed BGRA integer. + /// + /// A packed integer containing all four color components in RGBA order + /// A color. + public static Color FromRgba(int color) + { + return new Color(color); + } + + /// + /// Converts the color from a packed BGRA integer. + /// + /// A packed integer containing all four color components in RGBA order + /// A color. + public static Color FromRgba(uint color) + { + return new Color(color); + } + + /// + /// Restricts a value to be within a specified range. + /// + /// The value to clamp. + /// The minimum value. + /// The maximum value. + /// The clamped value. + public static Color Clamp(Color value, Color min, Color max) + { + Color result; + Clamp(ref value, ref min, ref max, out result); + return result; + } + + /// + /// Performs a linear interpolation between two colors. + /// + /// Start color. + /// End color. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the linear interpolation of the two colors. + /// + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static void Lerp(ref Color start, ref Color end, float amount, out Color result) + { + result.R = MathUtil.Lerp(start.R, end.R, amount); + result.G = MathUtil.Lerp(start.G, end.G, amount); + result.B = MathUtil.Lerp(start.B, end.B, amount); + result.A = MathUtil.Lerp(start.A, end.A, amount); + } + + /// + /// Performs a linear interpolation between two colors. + /// + /// Start color. + /// End color. + /// Value between 0 and 1 indicating the weight of . + /// The linear interpolation of the two colors. + /// + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static Color Lerp(Color start, Color end, float amount) + { + Color result; + Lerp(ref start, ref end, amount, out result); + return result; + } + + /// + /// Performs a cubic interpolation between two colors. + /// + /// Start color. + /// End color. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the cubic interpolation of the two colors. + public static void SmoothStep(ref Color start, ref Color end, float amount, out Color result) + { + amount = MathUtil.SmoothStep(amount); + Lerp(ref start, ref end, amount, out result); + } + + /// + /// Performs a cubic interpolation between two colors. + /// + /// Start color. + /// End color. + /// Value between 0 and 1 indicating the weight of . + /// The cubic interpolation of the two colors. + public static Color SmoothStep(Color start, Color end, float amount) + { + Color result; + SmoothStep(ref start, ref end, amount, out result); + return result; + } + + /// + /// Returns a color containing the smallest components of the specified colors. + /// + /// The first source color. + /// The second source color. + /// When the method completes, contains an new color composed of the largest components of the source colors. + public static void Max(ref Color left, ref Color right, out Color result) + { + result.A = (left.A > right.A) ? left.A : right.A; + result.R = (left.R > right.R) ? left.R : right.R; + result.G = (left.G > right.G) ? left.G : right.G; + result.B = (left.B > right.B) ? left.B : right.B; + } + + /// + /// Returns a color containing the largest components of the specified colorss. + /// + /// The first source color. + /// The second source color. + /// A color containing the largest components of the source colors. + public static Color Max(Color left, Color right) + { + Color result; + Max(ref left, ref right, out result); + return result; + } + + /// + /// Returns a color containing the smallest components of the specified colors. + /// + /// The first source color. + /// The second source color. + /// When the method completes, contains an new color composed of the smallest components of the source colors. + public static void Min(ref Color left, ref Color right, out Color result) + { + result.A = (left.A < right.A) ? left.A : right.A; + result.R = (left.R < right.R) ? left.R : right.R; + result.G = (left.G < right.G) ? left.G : right.G; + result.B = (left.B < right.B) ? left.B : right.B; + } + + /// + /// Returns a color containing the smallest components of the specified colors. + /// + /// The first source color. + /// The second source color. + /// A color containing the smallest components of the source colors. + public static Color Min(Color left, Color right) + { + Color result; + Min(ref left, ref right, out result); + return result; + } + + /// + /// Adjusts the contrast of a color. + /// + /// The color whose contrast is to be adjusted. + /// The amount by which to adjust the contrast. + /// When the method completes, contains the adjusted color. + public static void AdjustContrast(ref Color value, float contrast, out Color result) + { + result.A = value.A; + result.R = ToByte(0.5f + contrast * (value.R / 255.0f - 0.5f)); + result.G = ToByte(0.5f + contrast * (value.G / 255.0f - 0.5f)); + result.B = ToByte(0.5f + contrast * (value.B / 255.0f - 0.5f)); + } + + /// + /// Adjusts the contrast of a color. + /// + /// The color whose contrast is to be adjusted. + /// The amount by which to adjust the contrast. + /// The adjusted color. + public static Color AdjustContrast(Color value, float contrast) + { + return new Color( + ToByte(0.5f + contrast * (value.R / 255.0f - 0.5f)), + ToByte(0.5f + contrast * (value.G / 255.0f - 0.5f)), + ToByte(0.5f + contrast * (value.B / 255.0f- 0.5f)), + value.A); + } + + /// + /// Adjusts the saturation of a color. + /// + /// The color whose saturation is to be adjusted. + /// The amount by which to adjust the saturation. + /// When the method completes, contains the adjusted color. + public static void AdjustSaturation(ref Color value, float saturation, out Color result) + { + float grey = value.R / 255.0f * 0.2125f + value.G / 255.0f * 0.7154f + value.B / 255.0f * 0.0721f; + + result.A = value.A; + result.R = ToByte(grey + saturation * (value.R / 255.0f - grey)); + result.G = ToByte(grey + saturation * (value.G / 255.0f- grey)); + result.B = ToByte(grey + saturation * (value.B / 255.0f - grey)); + } + + /// + /// Adjusts the saturation of a color. + /// + /// The color whose saturation is to be adjusted. + /// The amount by which to adjust the saturation. + /// The adjusted color. + public static Color AdjustSaturation(Color value, float saturation) + { + float grey = value.R / 255.0f * 0.2125f + value.G / 255.0f * 0.7154f + value.B / 255.0f * 0.0721f; + + return new Color( + ToByte(grey + saturation * (value.R / 255.0f - grey)), + ToByte(grey + saturation * (value.G / 255.0f - grey)), + ToByte(grey + saturation * (value.B / 255.0f - grey)), + value.A); + } + + /// + /// Adds two colors. + /// + /// The first color to add. + /// The second color to add. + /// The sum of the two colors. + public static Color operator +(Color left, Color right) + { + return new Color(left.R + right.R, left.G + right.G, left.B + right.B, left.A + right.A); + } + + /// + /// Assert a color (return it unchanged). + /// + /// The color to assert (unchanged). + /// The asserted (unchanged) color. + public static Color operator +(Color value) + { + return value; + } + + /// + /// Subtracts two colors. + /// + /// The first color to subtract. + /// The second color to subtract. + /// The difference of the two colors. + public static Color operator -(Color left, Color right) + { + return new Color(left.R - right.R, left.G - right.G, left.B - right.B, left.A - right.A); + } + + /// + /// Negates a color. + /// + /// The color to negate. + /// A negated color. + public static Color operator -(Color value) + { + return new Color(-value.R, -value.G, -value.B, -value.A); + } + + /// + /// Scales a color. + /// + /// The factor by which to scale the color. + /// The color to scale. + /// The scaled color. + public static Color operator *(float scale, Color value) + { + return new Color((byte)(value.R * scale), (byte)(value.G * scale), (byte)(value.B * scale), (byte)(value.A * scale)); + } + + /// + /// Scales a color. + /// + /// The factor by which to scale the color. + /// The color to scale. + /// The scaled color. + public static Color operator *(Color value, float scale) + { + return new Color((byte)(value.R * scale), (byte)(value.G * scale), (byte)(value.B * scale), (byte)(value.A * scale)); + } + + /// + /// Modulates two colors. + /// + /// The first color to modulate. + /// The second color to modulate. + /// The modulated color. + public static Color operator *(Color left, Color right) + { + return new Color((byte)(left.R * right.R / 255.0f), (byte)(left.G * right.G / 255.0f), (byte)(left.B * right.B / 255.0f), (byte)(left.A * right.A / 255.0f)); + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has the same value as ; otherwise, false. + public static bool operator ==(Color left, Color right) + { + return left.Equals(right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has a different value than ; otherwise, false. + public static bool operator !=(Color left, Color right) + { + return !left.Equals(right); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Color3(Color value) + { + return value.ToColor3(); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Vector3(Color value) + { + return new Vector3(value.R / 255.0f, value.G / 255.0f, value.B / 255.0f); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Vector4(Color value) + { + return new Vector4(value.R / 255.0f, value.G / 255.0f, value.B / 255.0f, value.A / 255.0f); + } + + /// + /// Convert this instance to a + /// + /// The result of the conversion. + public Color4 ToColor4() + { + return new Color4(R / 255.0f, G / 255.0f, B / 255.0f, A / 255.0f); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Color4(Color value) + { + return value.ToColor4(); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Color(Vector3 value) + { + return new Color(value.X, value.Y, value.Z, 1.0f); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Color(Color3 value) + { + return new Color(value.Red, value.Green, value.Blue, 1.0f); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Color(Vector4 value) + { + return new Color(value.X, value.Y, value.Z, value.W); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Color(Color4 value) + { + return new Color(value.Red, value.Green, value.Blue, value.Alpha); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator int(Color value) + { + return value.ToRgba(); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator Color(int value) + { + return new Color(value); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return ToString(CultureInfo.CurrentCulture); + } + + /// + /// Returns a that represents this instance. + /// + /// The format to apply to each channel element (byte). + /// + /// A that represents this instance. + /// + public string ToString(string format) + { + return ToString(format, CultureInfo.CurrentCulture); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format(formatProvider, toStringFormat, A, R, G, B); + } + + /// + /// Returns a that represents this instance. + /// + /// The format to apply to each channel element (byte). + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(string format, IFormatProvider formatProvider) + { + if (format == null) + return ToString(formatProvider); + + return string.Format(formatProvider, + toStringFormat, + A.ToString(format, formatProvider), + R.ToString(format, formatProvider), + G.ToString(format, formatProvider), + B.ToString(format, formatProvider)); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + unchecked + { + var hashCode = R.GetHashCode(); + hashCode = (hashCode * 397) ^ G.GetHashCode(); + hashCode = (hashCode * 397) ^ B.GetHashCode(); + hashCode = (hashCode * 397) ^ A.GetHashCode(); + return hashCode; + } + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(Color other) + { + return R == other.R && G == other.G && B == other.B && A == other.A; + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object value) + { + if (value == null) + return false; + + if (!ReferenceEquals(value.GetType(), typeof(Color))) + return false; + + return Equals((Color)value); + } + + private static byte ToByte(float component) + { + var value = (int)(component * 255.0f); + return ToByte(value); + } + + public static byte ToByte(int value) + { + return (byte)(value < 0 ? 0 : value > 255 ? 255 : value); + } + } +} diff --git a/Source/SharpDX/Color3.cs b/Source/SharpDX/Mathematics/Color3.cs similarity index 95% rename from Source/SharpDX/Color3.cs rename to Source/SharpDX/Mathematics/Color3.cs index b44226f5c..8caab85dd 100644 --- a/Source/SharpDX/Color3.cs +++ b/Source/SharpDX/Mathematics/Color3.cs @@ -1,850 +1,830 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ----------------------------------------------------------------------------- -// Original code from SlimMath project. http://code.google.com/p/slimmath/ -// Greetings to SlimDX Group. Original code published with the following license: -// ----------------------------------------------------------------------------- -/* -* Copyright (c) 2007-2011 SlimDX Group -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Represents a color in the form of rgb. - /// - [StructLayout(LayoutKind.Sequential, Pack = 4)] - [DynamicSerializer("TKC3")] - public struct Color3 : IEquatable, IFormattable, IDataSerializable - { - private const string toStringFormat = "Red:{0} Green:{1} Blue:{2}"; - - /// - /// The Black color (0, 0, 0). - /// - public static readonly Color3 Black = new Color3(0.0f, 0.0f, 0.0f); - - /// - /// The White color (1, 1, 1, 1). - /// - public static readonly Color3 White = new Color3(1.0f, 1.0f, 1.0f); - - /// - /// The red component of the color. - /// - public float Red; - - /// - /// The green component of the color. - /// - public float Green; - - /// - /// The blue component of the color. - /// - public float Blue; - - /// - /// Initializes a new instance of the struct. - /// - /// The value that will be assigned to all components. - public Color3(float value) - { - Red = Green = Blue = value; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The red component of the color. - /// The green component of the color. - /// The blue component of the color. - public Color3(float red, float green, float blue) - { - Red = red; - Green = green; - Blue = blue; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The red, green, and blue components of the color. - public Color3(Vector3 value) - { - Red = value.X; - Green = value.Y; - Blue = value.Z; - } - - /// - /// Initializes a new instance of the struct. - /// - /// A packed integer containing all three color components in RGB order. - /// The alpha component is ignored. - public Color3(int rgb) - { - Blue = ((rgb >> 16) & 255) / 255.0f; - Green = ((rgb >> 8) & 255) / 255.0f; - Red = (rgb & 255) / 255.0f; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The values to assign to the red, green, and blue components of the color. This must be an array with three elements. - /// Thrown when is null. - /// Thrown when contains more or less than four elements. - public Color3(float[] values) - { - if (values == null) - throw new ArgumentNullException("values"); - if (values.Length != 3) - throw new ArgumentOutOfRangeException("values", "There must be three and only three input values for Color3."); - - Red = values[0]; - Green = values[1]; - Blue = values[2]; - } - - /// - /// Gets or sets the component at the specified index. - /// - /// The value of the red, green, or blue component, depending on the index. - /// The index of the component to access. Use 0 for the red component, 1 for the green component, and 2 for the blue component. - /// The value of the component at the specified index. - /// Thrown when the is out of the range [0, 2]. - public float this[int index] - { - get - { - switch (index) - { - case 0: return Red; - case 1: return Green; - case 2: return Blue; - } - - throw new ArgumentOutOfRangeException("index", "Indices for Color3 run from 0 to 2, inclusive."); - } - - set - { - switch (index) - { - case 0: Red = value; break; - case 1: Green = value; break; - case 2: Blue = value; break; - default: throw new ArgumentOutOfRangeException("index", "Indices for Color3 run from 0 to 2, inclusive."); - } - } - } - - /// - /// Converts the color into a packed integer. - /// - /// A packed integer containing all three color components. - /// The alpha channel is set to 255. - public int ToRgba() - { - uint a = 255; - uint r = (uint) (Red * 255.0f) & 255; - uint g = (uint) (Green * 255.0f) & 255; - uint b = (uint) (Blue * 255.0f) & 255; - - uint value = r; - value |= g << 8; - value |= b << 16; - value |= a << 24; - - return (int)value; - } - - /// - /// Converts the color into a packed integer. - /// - /// A packed integer containing all three color components. - /// The alpha channel is set to 255. - public int ToBgra() - { - uint a = 255; - uint r = (uint)(Red * 255.0f) & 255; - uint g = (uint)(Green * 255.0f) & 255; - uint b = (uint)(Blue * 255.0f) & 255; - - uint value = b; - value |= g << 8; - value |= r << 16; - value |= a << 24; - - return (int)value; - } - - /// - /// Converts the color into a three component vector. - /// - /// A three component vector containing the red, green, and blue components of the color. - public Vector3 ToVector3() - { - return new Vector3(Red, Green, Blue); - } - - /// - /// Creates an array containing the elements of the color. - /// - /// A three-element array containing the components of the color. - public float[] ToArray() - { - return new float[] { Red, Green, Blue }; - } - - /// - /// Adds two colors. - /// - /// The first color to add. - /// The second color to add. - /// When the method completes, completes the sum of the two colors. - public static void Add(ref Color3 left, ref Color3 right, out Color3 result) - { - result.Red = left.Red + right.Red; - result.Green = left.Green + right.Green; - result.Blue = left.Blue + right.Blue; - } - - /// - /// Adds two colors. - /// - /// The first color to add. - /// The second color to add. - /// The sum of the two colors. - public static Color3 Add(Color3 left, Color3 right) - { - return new Color3(left.Red + right.Red, left.Green + right.Green, left.Blue + right.Blue); - } - - /// - /// Subtracts two colors. - /// - /// The first color to subtract. - /// The second color to subtract. - /// WHen the method completes, contains the difference of the two colors. - public static void Subtract(ref Color3 left, ref Color3 right, out Color3 result) - { - result.Red = left.Red - right.Red; - result.Green = left.Green - right.Green; - result.Blue = left.Blue - right.Blue; - } - - /// - /// Subtracts two colors. - /// - /// The first color to subtract. - /// The second color to subtract - /// The difference of the two colors. - public static Color3 Subtract(Color3 left, Color3 right) - { - return new Color3(left.Red - right.Red, left.Green - right.Green, left.Blue - right.Blue); - } - - /// - /// Modulates two colors. - /// - /// The first color to modulate. - /// The second color to modulate. - /// When the method completes, contains the modulated color. - public static void Modulate(ref Color3 left, ref Color3 right, out Color3 result) - { - result.Red = left.Red * right.Red; - result.Green = left.Green * right.Green; - result.Blue = left.Blue * right.Blue; - } - - /// - /// Modulates two colors. - /// - /// The first color to modulate. - /// The second color to modulate. - /// The modulated color. - public static Color3 Modulate(Color3 left, Color3 right) - { - return new Color3(left.Red * right.Red, left.Green * right.Green, left.Blue * right.Blue); - } - - /// - /// Scales a color. - /// - /// The color to scale. - /// The amount by which to scale. - /// When the method completes, contains the scaled color. - public static void Scale(ref Color3 value, float scale, out Color3 result) - { - result.Red = value.Red * scale; - result.Green = value.Green * scale; - result.Blue = value.Blue * scale; - } - - /// - /// Scales a color. - /// - /// The color to scale. - /// The amount by which to scale. - /// The scaled color. - public static Color3 Scale(Color3 value, float scale) - { - return new Color3(value.Red * scale, value.Green * scale, value.Blue * scale); - } - - /// - /// Negates a color. - /// - /// The color to negate. - /// When the method completes, contains the negated color. - public static void Negate(ref Color3 value, out Color3 result) - { - result.Red = 1.0f - value.Red; - result.Green = 1.0f - value.Green; - result.Blue = 1.0f - value.Blue; - } - - /// - /// Negates a color. - /// - /// The color to negate. - /// The negated color. - public static Color3 Negate(Color3 value) - { - return new Color3(1.0f - value.Red, 1.0f - value.Green, 1.0f - value.Blue); - } - - /// - /// Restricts a value to be within a specified range. - /// - /// The value to clamp. - /// The minimum value. - /// The maximum value. - /// When the method completes, contains the clamped value. - public static void Clamp(ref Color3 value, ref Color3 min, ref Color3 max, out Color3 result) - { - float red = value.Red; - red = (red > max.Red) ? max.Red : red; - red = (red < min.Red) ? min.Red : red; - - float green = value.Green; - green = (green > max.Green) ? max.Green : green; - green = (green < min.Green) ? min.Green : green; - - float blue = value.Blue; - blue = (blue > max.Blue) ? max.Blue : blue; - blue = (blue < min.Blue) ? min.Blue : blue; - - result = new Color3(red, green, blue); - } - - /// - /// Restricts a value to be within a specified range. - /// - /// The value to clamp. - /// The minimum value. - /// The maximum value. - /// The clamped value. - public static Color3 Clamp(Color3 value, Color3 min, Color3 max) - { - Color3 result; - Clamp(ref value, ref min, ref max, out result); - return result; - } - - /// - /// Performs a linear interpolation between two colors. - /// - /// Start color. - /// End color. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the linear interpolation of the two colors. - /// - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static void Lerp(ref Color3 start, ref Color3 end, float amount, out Color3 result) - { - result.Red = MathUtil.Lerp(start.Red, end.Red, amount); - result.Green = MathUtil.Lerp(start.Green, end.Green, amount); - result.Blue = MathUtil.Lerp(start.Blue, end.Blue, amount); - } - - /// - /// Performs a linear interpolation between two colors. - /// - /// Start color. - /// End color. - /// Value between 0 and 1 indicating the weight of . - /// The linear interpolation of the two colors. - /// - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static Color3 Lerp(Color3 start, Color3 end, float amount) - { - Color3 result; - Lerp(ref start, ref end, amount, out result); - return result; - } - - /// - /// Performs a cubic interpolation between two colors. - /// - /// Start color. - /// End color. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the cubic interpolation of the two colors. - public static void SmoothStep(ref Color3 start, ref Color3 end, float amount, out Color3 result) - { - amount = MathUtil.SmoothStep(amount); - Lerp(ref start, ref end, amount, out result); - } - - /// - /// Performs a cubic interpolation between two colors. - /// - /// Start color. - /// End color. - /// Value between 0 and 1 indicating the weight of . - /// The cubic interpolation of the two colors. - public static Color3 SmoothStep(Color3 start, Color3 end, float amount) - { - Color3 result; - SmoothStep(ref start, ref end, amount, out result); - return result; - } - - /// - /// Returns a color containing the smallest components of the specified colors. - /// - /// The first source color. - /// The second source color. - /// When the method completes, contains an new color composed of the largest components of the source colors. - public static void Max(ref Color3 left, ref Color3 right, out Color3 result) - { - result.Red = (left.Red > right.Red) ? left.Red : right.Red; - result.Green = (left.Green > right.Green) ? left.Green : right.Green; - result.Blue = (left.Blue > right.Blue) ? left.Blue : right.Blue; - } - - /// - /// Returns a color containing the largest components of the specified colors. - /// - /// The first source color. - /// The second source color. - /// A color containing the largest components of the source colors. - public static Color3 Max(Color3 left, Color3 right) - { - Color3 result; - Max(ref left, ref right, out result); - return result; - } - - /// - /// Returns a color containing the smallest components of the specified colors. - /// - /// The first source color. - /// The second source color. - /// When the method completes, contains an new color composed of the smallest components of the source colors. - public static void Min(ref Color3 left, ref Color3 right, out Color3 result) - { - result.Red = (left.Red < right.Red) ? left.Red : right.Red; - result.Green = (left.Green < right.Green) ? left.Green : right.Green; - result.Blue = (left.Blue < right.Blue) ? left.Blue : right.Blue; - } - - /// - /// Returns a color containing the smallest components of the specified colors. - /// - /// The first source color. - /// The second source color. - /// A color containing the smallest components of the source colors. - public static Color3 Min(Color3 left, Color3 right) - { - Color3 result; - Min(ref left, ref right, out result); - return result; - } - - /// - /// Adjusts the contrast of a color. - /// - /// The color whose contrast is to be adjusted. - /// The amount by which to adjust the contrast. - /// When the method completes, contains the adjusted color. - public static void AdjustContrast(ref Color3 value, float contrast, out Color3 result) - { - result.Red = 0.5f + contrast * (value.Red - 0.5f); - result.Green = 0.5f + contrast * (value.Green - 0.5f); - result.Blue = 0.5f + contrast * (value.Blue - 0.5f); - } - - /// - /// Adjusts the contrast of a color. - /// - /// The color whose contrast is to be adjusted. - /// The amount by which to adjust the contrast. - /// The adjusted color. - public static Color3 AdjustContrast(Color3 value, float contrast) - { - return new Color3( - 0.5f + contrast * (value.Red - 0.5f), - 0.5f + contrast * (value.Green - 0.5f), - 0.5f + contrast * (value.Blue - 0.5f)); - } - - /// - /// Adjusts the saturation of a color. - /// - /// The color whose saturation is to be adjusted. - /// The amount by which to adjust the saturation. - /// When the method completes, contains the adjusted color. - public static void AdjustSaturation(ref Color3 value, float saturation, out Color3 result) - { - float grey = value.Red * 0.2125f + value.Green * 0.7154f + value.Blue * 0.0721f; - - result.Red = grey + saturation * (value.Red - grey); - result.Green = grey + saturation * (value.Green - grey); - result.Blue = grey + saturation * (value.Blue - grey); - } - - /// - /// Adjusts the saturation of a color. - /// - /// The color whose saturation is to be adjusted. - /// The amount by which to adjust the saturation. - /// The adjusted color. - public static Color3 AdjustSaturation(Color3 value, float saturation) - { - float grey = value.Red * 0.2125f + value.Green * 0.7154f + value.Blue * 0.0721f; - - return new Color3( - grey + saturation * (value.Red - grey), - grey + saturation * (value.Green - grey), - grey + saturation * (value.Blue - grey)); - } - - /// - /// Computes the premultiplied value of the provided color. - /// - /// The non-premultiplied value. - /// The color alpha. - /// The premultiplied result. - public static void Premultiply(ref Color3 value, float alpha, out Color3 result) - { - result.Red = value.Red * alpha; - result.Green = value.Green * alpha; - result.Blue = value.Blue * alpha; - } - - /// - /// Computes the premultiplied value of the provided color. - /// - /// The non-premultiplied value. - /// The color alpha. - /// The premultiplied color. - public static Color3 Premultiply(Color3 value, float alpha) - { - Color3 result; - Premultiply(ref value, alpha, out result); - return result; - } - - /// - /// Adds two colors. - /// - /// The first color to add. - /// The second color to add. - /// The sum of the two colors. - public static Color3 operator +(Color3 left, Color3 right) - { - return new Color3(left.Red + right.Red, left.Green + right.Green, left.Blue + right.Blue); - } - - /// - /// Assert a color (return it unchanged). - /// - /// The color to assert (unchanged). - /// The asserted (unchanged) color. - public static Color3 operator +(Color3 value) - { - return value; - } - - /// - /// Subtracts two colors. - /// - /// The first color to subtract. - /// The second color to subtract. - /// The difference of the two colors. - public static Color3 operator -(Color3 left, Color3 right) - { - return new Color3(left.Red - right.Red, left.Green - right.Green, left.Blue - right.Blue); - } - - /// - /// Negates a color. - /// - /// The color to negate. - /// A negated color. - public static Color3 operator -(Color3 value) - { - return new Color3(-value.Red, -value.Green, -value.Blue); - } - - /// - /// Scales a color. - /// - /// The factor by which to scale the color. - /// The color to scale. - /// The scaled color. - public static Color3 operator *(float scale, Color3 value) - { - return new Color3(value.Red * scale, value.Green * scale, value.Blue * scale); - } - - /// - /// Scales a color. - /// - /// The factor by which to scale the color. - /// The color to scale. - /// The scaled color. - public static Color3 operator *(Color3 value, float scale) - { - return new Color3(value.Red * scale, value.Green * scale, value.Blue * scale); - } - - /// - /// Modulates two colors. - /// - /// The first color to modulate. - /// The second color to modulate. - /// The modulated color. - public static Color3 operator *(Color3 left, Color3 right) - { - return new Color3(left.Red * right.Red, left.Green * right.Green, left.Blue * right.Blue); - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has the same value as ; otherwise, false. - public static bool operator ==(Color3 left, Color3 right) - { - return left.Equals(right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has a different value than ; otherwise, false. - public static bool operator !=(Color3 left, Color3 right) - { - return !left.Equals(right); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Color4(Color3 value) - { - return new Color4(value.Red, value.Green, value.Blue, 1.0f); - } - - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Vector3(Color3 value) - { - return new Vector3(value.Red, value.Green, value.Blue); - } - - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Color3(Vector3 value) - { - return new Color3(value.X, value.Y, value.Z); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Color3(int value) - { - return new Color3(value); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return ToString(CultureInfo.CurrentCulture); - } - - /// - /// Returns a that represents this instance. - /// - /// The format to apply to each channel element (float) - /// - /// A that represents this instance. - /// - public string ToString(string format) - { - return ToString(format, CultureInfo.CurrentCulture); - } - - /// - /// Returns a that represents this instance. - /// - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(IFormatProvider formatProvider) - { - return string.Format(formatProvider, toStringFormat, Red, Green, Blue); - } - - /// - /// Returns a that represents this instance. - /// - /// The format to apply to each channel element (float). - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - if (format == null) - return ToString(formatProvider); - - return string.Format(formatProvider, - toStringFormat, - Red.ToString(format, formatProvider), - Green.ToString(format, formatProvider), - Blue.ToString(format, formatProvider)); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - var hashCode = Red.GetHashCode(); - hashCode = (hashCode * 397) ^ Green.GetHashCode(); - hashCode = (hashCode * 397) ^ Blue.GetHashCode(); - return hashCode; - } - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(Color3 other) - { - return Red == other.Red && Green == other.Green && Blue == other.Blue; - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object value) - { - if (value == null) - return false; - - if (!ReferenceEquals(value.GetType(), typeof(Color3))) - return false; - - return Equals((Color3)value); - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(Red); - serializer.Writer.Write(Green); - serializer.Writer.Write(Blue); - } - else - { - Red = serializer.Reader.ReadSingle(); - Green = serializer.Reader.ReadSingle(); - Blue = serializer.Reader.ReadSingle(); - } - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from SlimMath project. http://code.google.com/p/slimmath/ +// Greetings to SlimDX Group. Original code published with the following license: +// ----------------------------------------------------------------------------- +/* +* Copyright (c) 2007-2011 SlimDX Group +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Represents a color in the form of rgb. + /// + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct Color3 : IEquatable, IFormattable + { + private const string toStringFormat = "Red:{0} Green:{1} Blue:{2}"; + + /// + /// The Black color (0, 0, 0). + /// + public static readonly Color3 Black = new Color3(0.0f, 0.0f, 0.0f); + + /// + /// The White color (1, 1, 1, 1). + /// + public static readonly Color3 White = new Color3(1.0f, 1.0f, 1.0f); + + /// + /// The red component of the color. + /// + public float Red; + + /// + /// The green component of the color. + /// + public float Green; + + /// + /// The blue component of the color. + /// + public float Blue; + + /// + /// Initializes a new instance of the struct. + /// + /// The value that will be assigned to all components. + public Color3(float value) + { + Red = Green = Blue = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The red component of the color. + /// The green component of the color. + /// The blue component of the color. + public Color3(float red, float green, float blue) + { + Red = red; + Green = green; + Blue = blue; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The red, green, and blue components of the color. + public Color3(Vector3 value) + { + Red = value.X; + Green = value.Y; + Blue = value.Z; + } + + /// + /// Initializes a new instance of the struct. + /// + /// A packed integer containing all three color components in RGB order. + /// The alpha component is ignored. + public Color3(int rgb) + { + Blue = ((rgb >> 16) & 255) / 255.0f; + Green = ((rgb >> 8) & 255) / 255.0f; + Red = (rgb & 255) / 255.0f; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The values to assign to the red, green, and blue components of the color. This must be an array with three elements. + /// Thrown when is null. + /// Thrown when contains more or less than four elements. + public Color3(float[] values) + { + if (values == null) + throw new ArgumentNullException("values"); + if (values.Length != 3) + throw new ArgumentOutOfRangeException("values", "There must be three and only three input values for Color3."); + + Red = values[0]; + Green = values[1]; + Blue = values[2]; + } + + /// + /// Gets or sets the component at the specified index. + /// + /// The value of the red, green, or blue component, depending on the index. + /// The index of the component to access. Use 0 for the red component, 1 for the green component, and 2 for the blue component. + /// The value of the component at the specified index. + /// Thrown when the is out of the range [0, 2]. + public float this[int index] + { + get + { + switch (index) + { + case 0: return Red; + case 1: return Green; + case 2: return Blue; + } + + throw new ArgumentOutOfRangeException("index", "Indices for Color3 run from 0 to 2, inclusive."); + } + + set + { + switch (index) + { + case 0: Red = value; break; + case 1: Green = value; break; + case 2: Blue = value; break; + default: throw new ArgumentOutOfRangeException("index", "Indices for Color3 run from 0 to 2, inclusive."); + } + } + } + + /// + /// Converts the color into a packed integer. + /// + /// A packed integer containing all three color components. + /// The alpha channel is set to 255. + public int ToRgba() + { + uint a = 255; + uint r = (uint) (Red * 255.0f) & 255; + uint g = (uint) (Green * 255.0f) & 255; + uint b = (uint) (Blue * 255.0f) & 255; + + uint value = r; + value |= g << 8; + value |= b << 16; + value |= a << 24; + + return (int)value; + } + + /// + /// Converts the color into a packed integer. + /// + /// A packed integer containing all three color components. + /// The alpha channel is set to 255. + public int ToBgra() + { + uint a = 255; + uint r = (uint)(Red * 255.0f) & 255; + uint g = (uint)(Green * 255.0f) & 255; + uint b = (uint)(Blue * 255.0f) & 255; + + uint value = b; + value |= g << 8; + value |= r << 16; + value |= a << 24; + + return (int)value; + } + + /// + /// Converts the color into a three component vector. + /// + /// A three component vector containing the red, green, and blue components of the color. + public Vector3 ToVector3() + { + return new Vector3(Red, Green, Blue); + } + + /// + /// Creates an array containing the elements of the color. + /// + /// A three-element array containing the components of the color. + public float[] ToArray() + { + return new float[] { Red, Green, Blue }; + } + + /// + /// Adds two colors. + /// + /// The first color to add. + /// The second color to add. + /// When the method completes, completes the sum of the two colors. + public static void Add(ref Color3 left, ref Color3 right, out Color3 result) + { + result.Red = left.Red + right.Red; + result.Green = left.Green + right.Green; + result.Blue = left.Blue + right.Blue; + } + + /// + /// Adds two colors. + /// + /// The first color to add. + /// The second color to add. + /// The sum of the two colors. + public static Color3 Add(Color3 left, Color3 right) + { + return new Color3(left.Red + right.Red, left.Green + right.Green, left.Blue + right.Blue); + } + + /// + /// Subtracts two colors. + /// + /// The first color to subtract. + /// The second color to subtract. + /// WHen the method completes, contains the difference of the two colors. + public static void Subtract(ref Color3 left, ref Color3 right, out Color3 result) + { + result.Red = left.Red - right.Red; + result.Green = left.Green - right.Green; + result.Blue = left.Blue - right.Blue; + } + + /// + /// Subtracts two colors. + /// + /// The first color to subtract. + /// The second color to subtract + /// The difference of the two colors. + public static Color3 Subtract(Color3 left, Color3 right) + { + return new Color3(left.Red - right.Red, left.Green - right.Green, left.Blue - right.Blue); + } + + /// + /// Modulates two colors. + /// + /// The first color to modulate. + /// The second color to modulate. + /// When the method completes, contains the modulated color. + public static void Modulate(ref Color3 left, ref Color3 right, out Color3 result) + { + result.Red = left.Red * right.Red; + result.Green = left.Green * right.Green; + result.Blue = left.Blue * right.Blue; + } + + /// + /// Modulates two colors. + /// + /// The first color to modulate. + /// The second color to modulate. + /// The modulated color. + public static Color3 Modulate(Color3 left, Color3 right) + { + return new Color3(left.Red * right.Red, left.Green * right.Green, left.Blue * right.Blue); + } + + /// + /// Scales a color. + /// + /// The color to scale. + /// The amount by which to scale. + /// When the method completes, contains the scaled color. + public static void Scale(ref Color3 value, float scale, out Color3 result) + { + result.Red = value.Red * scale; + result.Green = value.Green * scale; + result.Blue = value.Blue * scale; + } + + /// + /// Scales a color. + /// + /// The color to scale. + /// The amount by which to scale. + /// The scaled color. + public static Color3 Scale(Color3 value, float scale) + { + return new Color3(value.Red * scale, value.Green * scale, value.Blue * scale); + } + + /// + /// Negates a color. + /// + /// The color to negate. + /// When the method completes, contains the negated color. + public static void Negate(ref Color3 value, out Color3 result) + { + result.Red = 1.0f - value.Red; + result.Green = 1.0f - value.Green; + result.Blue = 1.0f - value.Blue; + } + + /// + /// Negates a color. + /// + /// The color to negate. + /// The negated color. + public static Color3 Negate(Color3 value) + { + return new Color3(1.0f - value.Red, 1.0f - value.Green, 1.0f - value.Blue); + } + + /// + /// Restricts a value to be within a specified range. + /// + /// The value to clamp. + /// The minimum value. + /// The maximum value. + /// When the method completes, contains the clamped value. + public static void Clamp(ref Color3 value, ref Color3 min, ref Color3 max, out Color3 result) + { + float red = value.Red; + red = (red > max.Red) ? max.Red : red; + red = (red < min.Red) ? min.Red : red; + + float green = value.Green; + green = (green > max.Green) ? max.Green : green; + green = (green < min.Green) ? min.Green : green; + + float blue = value.Blue; + blue = (blue > max.Blue) ? max.Blue : blue; + blue = (blue < min.Blue) ? min.Blue : blue; + + result = new Color3(red, green, blue); + } + + /// + /// Restricts a value to be within a specified range. + /// + /// The value to clamp. + /// The minimum value. + /// The maximum value. + /// The clamped value. + public static Color3 Clamp(Color3 value, Color3 min, Color3 max) + { + Color3 result; + Clamp(ref value, ref min, ref max, out result); + return result; + } + + /// + /// Performs a linear interpolation between two colors. + /// + /// Start color. + /// End color. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the linear interpolation of the two colors. + /// + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static void Lerp(ref Color3 start, ref Color3 end, float amount, out Color3 result) + { + result.Red = MathUtil.Lerp(start.Red, end.Red, amount); + result.Green = MathUtil.Lerp(start.Green, end.Green, amount); + result.Blue = MathUtil.Lerp(start.Blue, end.Blue, amount); + } + + /// + /// Performs a linear interpolation between two colors. + /// + /// Start color. + /// End color. + /// Value between 0 and 1 indicating the weight of . + /// The linear interpolation of the two colors. + /// + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static Color3 Lerp(Color3 start, Color3 end, float amount) + { + Color3 result; + Lerp(ref start, ref end, amount, out result); + return result; + } + + /// + /// Performs a cubic interpolation between two colors. + /// + /// Start color. + /// End color. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the cubic interpolation of the two colors. + public static void SmoothStep(ref Color3 start, ref Color3 end, float amount, out Color3 result) + { + amount = MathUtil.SmoothStep(amount); + Lerp(ref start, ref end, amount, out result); + } + + /// + /// Performs a cubic interpolation between two colors. + /// + /// Start color. + /// End color. + /// Value between 0 and 1 indicating the weight of . + /// The cubic interpolation of the two colors. + public static Color3 SmoothStep(Color3 start, Color3 end, float amount) + { + Color3 result; + SmoothStep(ref start, ref end, amount, out result); + return result; + } + + /// + /// Returns a color containing the smallest components of the specified colors. + /// + /// The first source color. + /// The second source color. + /// When the method completes, contains an new color composed of the largest components of the source colors. + public static void Max(ref Color3 left, ref Color3 right, out Color3 result) + { + result.Red = (left.Red > right.Red) ? left.Red : right.Red; + result.Green = (left.Green > right.Green) ? left.Green : right.Green; + result.Blue = (left.Blue > right.Blue) ? left.Blue : right.Blue; + } + + /// + /// Returns a color containing the largest components of the specified colors. + /// + /// The first source color. + /// The second source color. + /// A color containing the largest components of the source colors. + public static Color3 Max(Color3 left, Color3 right) + { + Color3 result; + Max(ref left, ref right, out result); + return result; + } + + /// + /// Returns a color containing the smallest components of the specified colors. + /// + /// The first source color. + /// The second source color. + /// When the method completes, contains an new color composed of the smallest components of the source colors. + public static void Min(ref Color3 left, ref Color3 right, out Color3 result) + { + result.Red = (left.Red < right.Red) ? left.Red : right.Red; + result.Green = (left.Green < right.Green) ? left.Green : right.Green; + result.Blue = (left.Blue < right.Blue) ? left.Blue : right.Blue; + } + + /// + /// Returns a color containing the smallest components of the specified colors. + /// + /// The first source color. + /// The second source color. + /// A color containing the smallest components of the source colors. + public static Color3 Min(Color3 left, Color3 right) + { + Color3 result; + Min(ref left, ref right, out result); + return result; + } + + /// + /// Adjusts the contrast of a color. + /// + /// The color whose contrast is to be adjusted. + /// The amount by which to adjust the contrast. + /// When the method completes, contains the adjusted color. + public static void AdjustContrast(ref Color3 value, float contrast, out Color3 result) + { + result.Red = 0.5f + contrast * (value.Red - 0.5f); + result.Green = 0.5f + contrast * (value.Green - 0.5f); + result.Blue = 0.5f + contrast * (value.Blue - 0.5f); + } + + /// + /// Adjusts the contrast of a color. + /// + /// The color whose contrast is to be adjusted. + /// The amount by which to adjust the contrast. + /// The adjusted color. + public static Color3 AdjustContrast(Color3 value, float contrast) + { + return new Color3( + 0.5f + contrast * (value.Red - 0.5f), + 0.5f + contrast * (value.Green - 0.5f), + 0.5f + contrast * (value.Blue - 0.5f)); + } + + /// + /// Adjusts the saturation of a color. + /// + /// The color whose saturation is to be adjusted. + /// The amount by which to adjust the saturation. + /// When the method completes, contains the adjusted color. + public static void AdjustSaturation(ref Color3 value, float saturation, out Color3 result) + { + float grey = value.Red * 0.2125f + value.Green * 0.7154f + value.Blue * 0.0721f; + + result.Red = grey + saturation * (value.Red - grey); + result.Green = grey + saturation * (value.Green - grey); + result.Blue = grey + saturation * (value.Blue - grey); + } + + /// + /// Adjusts the saturation of a color. + /// + /// The color whose saturation is to be adjusted. + /// The amount by which to adjust the saturation. + /// The adjusted color. + public static Color3 AdjustSaturation(Color3 value, float saturation) + { + float grey = value.Red * 0.2125f + value.Green * 0.7154f + value.Blue * 0.0721f; + + return new Color3( + grey + saturation * (value.Red - grey), + grey + saturation * (value.Green - grey), + grey + saturation * (value.Blue - grey)); + } + + /// + /// Computes the premultiplied value of the provided color. + /// + /// The non-premultiplied value. + /// The color alpha. + /// The premultiplied result. + public static void Premultiply(ref Color3 value, float alpha, out Color3 result) + { + result.Red = value.Red * alpha; + result.Green = value.Green * alpha; + result.Blue = value.Blue * alpha; + } + + /// + /// Computes the premultiplied value of the provided color. + /// + /// The non-premultiplied value. + /// The color alpha. + /// The premultiplied color. + public static Color3 Premultiply(Color3 value, float alpha) + { + Color3 result; + Premultiply(ref value, alpha, out result); + return result; + } + + /// + /// Adds two colors. + /// + /// The first color to add. + /// The second color to add. + /// The sum of the two colors. + public static Color3 operator +(Color3 left, Color3 right) + { + return new Color3(left.Red + right.Red, left.Green + right.Green, left.Blue + right.Blue); + } + + /// + /// Assert a color (return it unchanged). + /// + /// The color to assert (unchanged). + /// The asserted (unchanged) color. + public static Color3 operator +(Color3 value) + { + return value; + } + + /// + /// Subtracts two colors. + /// + /// The first color to subtract. + /// The second color to subtract. + /// The difference of the two colors. + public static Color3 operator -(Color3 left, Color3 right) + { + return new Color3(left.Red - right.Red, left.Green - right.Green, left.Blue - right.Blue); + } + + /// + /// Negates a color. + /// + /// The color to negate. + /// A negated color. + public static Color3 operator -(Color3 value) + { + return new Color3(-value.Red, -value.Green, -value.Blue); + } + + /// + /// Scales a color. + /// + /// The factor by which to scale the color. + /// The color to scale. + /// The scaled color. + public static Color3 operator *(float scale, Color3 value) + { + return new Color3(value.Red * scale, value.Green * scale, value.Blue * scale); + } + + /// + /// Scales a color. + /// + /// The factor by which to scale the color. + /// The color to scale. + /// The scaled color. + public static Color3 operator *(Color3 value, float scale) + { + return new Color3(value.Red * scale, value.Green * scale, value.Blue * scale); + } + + /// + /// Modulates two colors. + /// + /// The first color to modulate. + /// The second color to modulate. + /// The modulated color. + public static Color3 operator *(Color3 left, Color3 right) + { + return new Color3(left.Red * right.Red, left.Green * right.Green, left.Blue * right.Blue); + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has the same value as ; otherwise, false. + public static bool operator ==(Color3 left, Color3 right) + { + return left.Equals(right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has a different value than ; otherwise, false. + public static bool operator !=(Color3 left, Color3 right) + { + return !left.Equals(right); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Color4(Color3 value) + { + return new Color4(value.Red, value.Green, value.Blue, 1.0f); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Vector3(Color3 value) + { + return new Vector3(value.Red, value.Green, value.Blue); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Color3(Vector3 value) + { + return new Color3(value.X, value.Y, value.Z); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Color3(int value) + { + return new Color3(value); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return ToString(CultureInfo.CurrentCulture); + } + + /// + /// Returns a that represents this instance. + /// + /// The format to apply to each channel element (float) + /// + /// A that represents this instance. + /// + public string ToString(string format) + { + return ToString(format, CultureInfo.CurrentCulture); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format(formatProvider, toStringFormat, Red, Green, Blue); + } + + /// + /// Returns a that represents this instance. + /// + /// The format to apply to each channel element (float). + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(string format, IFormatProvider formatProvider) + { + if (format == null) + return ToString(formatProvider); + + return string.Format(formatProvider, + toStringFormat, + Red.ToString(format, formatProvider), + Green.ToString(format, formatProvider), + Blue.ToString(format, formatProvider)); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + unchecked + { + var hashCode = Red.GetHashCode(); + hashCode = (hashCode * 397) ^ Green.GetHashCode(); + hashCode = (hashCode * 397) ^ Blue.GetHashCode(); + return hashCode; + } + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(Color3 other) + { + return Red == other.Red && Green == other.Green && Blue == other.Blue; + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object value) + { + if (value == null) + return false; + + if (!ReferenceEquals(value.GetType(), typeof(Color3))) + return false; + + return Equals((Color3)value); + } + } +} diff --git a/Source/SharpDX/Color4.cs b/Source/SharpDX/Mathematics/Color4.cs similarity index 95% rename from Source/SharpDX/Color4.cs rename to Source/SharpDX/Mathematics/Color4.cs index 0c68147e5..5dac48bbf 100644 --- a/Source/SharpDX/Color4.cs +++ b/Source/SharpDX/Mathematics/Color4.cs @@ -1,1003 +1,981 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ----------------------------------------------------------------------------- -// Original code from SlimMath project. http://code.google.com/p/slimmath/ -// Greetings to SlimDX Group. Original code published with the following license: -// ----------------------------------------------------------------------------- -/* -* Copyright (c) 2007-2011 SlimDX Group -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Represents a color in the form of rgba. - /// - [StructLayout(LayoutKind.Sequential, Pack = 4)] - [DynamicSerializer("TKC4")] - public struct Color4 : IEquatable, IFormattable, IDataSerializable - { - private const string toStringFormat = "Alpha:{0} Red:{1} Green:{2} Blue:{3}"; - - /// - /// The Black color (0, 0, 0, 1). - /// - public static readonly Color4 Black = new Color4(0.0f, 0.0f, 0.0f, 1.0f); - - /// - /// The White color (1, 1, 1, 1). - /// - public static readonly Color4 White = new Color4(1.0f, 1.0f, 1.0f, 1.0f); - - /// - /// The red component of the color. - /// - public float Red; - - /// - /// The green component of the color. - /// - public float Green; - - /// - /// The blue component of the color. - /// - public float Blue; - - /// - /// The alpha component of the color. - /// - public float Alpha; - - /// - /// Initializes a new instance of the struct. - /// - /// The value that will be assigned to all components. - public Color4(float value) - { - Alpha = Red = Green = Blue = value; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The red component of the color. - /// The green component of the color. - /// The blue component of the color. - /// The alpha component of the color. - public Color4(float red, float green, float blue, float alpha) - { - Red = red; - Green = green; - Blue = blue; - Alpha = alpha; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The red, green, blue, and alpha components of the color. - public Color4(Vector4 value) - { - Red = value.X; - Green = value.Y; - Blue = value.Z; - Alpha = value.W; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The red, green, and blue components of the color. - /// The alpha component of the color. - public Color4(Vector3 value, float alpha) - { - Red = value.X; - Green = value.Y; - Blue = value.Z; - Alpha = alpha; - } - - /// - /// Initializes a new instance of the struct. - /// - /// A packed integer containing all four color components in RGBA order. - public Color4(uint rgba) - { - Alpha = ((rgba >> 24) & 255) / 255.0f; - Blue = ((rgba >> 16) & 255) / 255.0f; - Green = ((rgba >> 8) & 255) / 255.0f; - Red = (rgba & 255) / 255.0f; - } - - /// - /// Initializes a new instance of the struct. - /// - /// A packed integer containing all four color components in RGBA order. - public Color4(int rgba) - { - Alpha = ((rgba >> 24) & 255) / 255.0f; - Blue = ((rgba >> 16) & 255) / 255.0f; - Green = ((rgba >> 8) & 255) / 255.0f; - Red = (rgba & 255) / 255.0f; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The values to assign to the red, green, blue, and alpha components of the color. This must be an array with four elements. - /// Thrown when is null. - /// Thrown when contains more or less than four elements. - public Color4(float[] values) - { - if (values == null) - throw new ArgumentNullException("values"); - if (values.Length != 4) - throw new ArgumentOutOfRangeException("values", "There must be four and only four input values for Color4."); - - Red = values[0]; - Green = values[1]; - Blue = values[2]; - Alpha = values[3]; - } - - /// - /// Initializes a new instance of the struct. - /// - /// used to initialize the color. - public Color4(Color3 color) - { - Red = color.Red; - Green = color.Green; - Blue = color.Blue; - Alpha = 1.0f; - } - - /// - /// Initializes a new instance of the struct. - /// - /// used to initialize the color. - /// The alpha component of the color. - public Color4(Color3 color, float alpha) - { - Red = color.Red; - Green = color.Green; - Blue = color.Blue; - Alpha = alpha; - } - - /// - /// Gets or sets the component at the specified index. - /// - /// The value of the red, green, blue, and alpha components, depending on the index. - /// The index of the component to access. Use 0 for the alpha component, 1 for the red component, 2 for the green component, and 3 for the blue component. - /// The value of the component at the specified index. - /// Thrown when the is out of the range [0, 3]. - public float this[int index] - { - get - { - switch (index) - { - case 0: return Red; - case 1: return Green; - case 2: return Blue; - case 3: return Alpha; - } - - throw new ArgumentOutOfRangeException("index", "Indices for Color4 run from 0 to 3, inclusive."); - } - - set - { - switch (index) - { - case 0: Red = value; break; - case 1: Green = value; break; - case 2: Blue = value; break; - case 3: Alpha = value; break; - default: throw new ArgumentOutOfRangeException("index", "Indices for Color4 run from 0 to 3, inclusive."); - } - } - } - - /// - /// Converts the color into a packed integer. - /// - /// A packed integer containing all four color components. - public int ToBgra() - { - uint a = (uint)(Alpha * 255.0f) & 255; - uint r = (uint)(Red * 255.0f) & 255; - uint g = (uint)(Green * 255.0f) & 255; - uint b = (uint)(Blue * 255.0f) & 255; - - uint value = b; - value |= g << 8; - value |= r << 16; - value |= a << 24; - - return (int)value; - } - - /// - /// Converts the color into a packed integer. - /// - /// A packed integer containing all four color components. - public void ToBgra(out byte r, out byte g, out byte b, out byte a) - { - a = (byte)(Alpha * 255.0f); - r = (byte)(Red * 255.0f); - g = (byte)(Green * 255.0f); - b = (byte)(Blue * 255.0f); - } - - /// - /// Converts the color into a packed integer. - /// - /// A packed integer containing all four color components. - public int ToRgba() - { - uint a = (uint) (Alpha * 255.0f) & 255; - uint r = (uint) (Red * 255.0f) & 255; - uint g = (uint) (Green * 255.0f) & 255; - uint b = (uint) (Blue * 255.0f) & 255; - - uint value = r; - value |= g << 8; - value |= b << 16; - value |= a << 24; - - return (int)value; - } - - /// - /// Converts the color into a three component vector. - /// - /// A three component vector containing the red, green, and blue components of the color. - public Vector3 ToVector3() - { - return new Vector3(Red, Green, Blue); - } - - /// - /// Converts the color into a four component vector. - /// - /// A four component vector containing all four color components. - public Vector4 ToVector4() - { - return new Vector4(Red, Green, Blue, Alpha); - } - - /// - /// Creates an array containing the elements of the color. - /// - /// A four-element array containing the components of the color. - public float[] ToArray() - { - return new float[] { Red, Green, Blue, Alpha }; - } - - /// - /// Adds two colors. - /// - /// The first color to add. - /// The second color to add. - /// When the method completes, completes the sum of the two colors. - public static void Add(ref Color4 left, ref Color4 right, out Color4 result) - { - result.Alpha = left.Alpha + right.Alpha; - result.Red = left.Red + right.Red; - result.Green = left.Green + right.Green; - result.Blue = left.Blue + right.Blue; - } - - /// - /// Adds two colors. - /// - /// The first color to add. - /// The second color to add. - /// The sum of the two colors. - public static Color4 Add(Color4 left, Color4 right) - { - return new Color4(left.Red + right.Red, left.Green + right.Green, left.Blue + right.Blue, left.Alpha + right.Alpha); - } - - /// - /// Subtracts two colors. - /// - /// The first color to subtract. - /// The second color to subtract. - /// WHen the method completes, contains the difference of the two colors. - public static void Subtract(ref Color4 left, ref Color4 right, out Color4 result) - { - result.Alpha = left.Alpha - right.Alpha; - result.Red = left.Red - right.Red; - result.Green = left.Green - right.Green; - result.Blue = left.Blue - right.Blue; - } - - /// - /// Subtracts two colors. - /// - /// The first color to subtract. - /// The second color to subtract - /// The difference of the two colors. - public static Color4 Subtract(Color4 left, Color4 right) - { - return new Color4(left.Red - right.Red, left.Green - right.Green, left.Blue - right.Blue, left.Alpha - right.Alpha); - } - - /// - /// Modulates two colors. - /// - /// The first color to modulate. - /// The second color to modulate. - /// When the method completes, contains the modulated color. - public static void Modulate(ref Color4 left, ref Color4 right, out Color4 result) - { - result.Alpha = left.Alpha * right.Alpha; - result.Red = left.Red * right.Red; - result.Green = left.Green * right.Green; - result.Blue = left.Blue * right.Blue; - } - - /// - /// Modulates two colors. - /// - /// The first color to modulate. - /// The second color to modulate. - /// The modulated color. - public static Color4 Modulate(Color4 left, Color4 right) - { - return new Color4(left.Red * right.Red, left.Green * right.Green, left.Blue * right.Blue, left.Alpha * right.Alpha); - } - - /// - /// Scales a color. - /// - /// The color to scale. - /// The amount by which to scale. - /// When the method completes, contains the scaled color. - public static void Scale(ref Color4 value, float scale, out Color4 result) - { - result.Alpha = value.Alpha * scale; - result.Red = value.Red * scale; - result.Green = value.Green * scale; - result.Blue = value.Blue * scale; - } - - /// - /// Scales a color. - /// - /// The color to scale. - /// The amount by which to scale. - /// The scaled color. - public static Color4 Scale(Color4 value, float scale) - { - return new Color4(value.Red * scale, value.Green * scale, value.Blue * scale, value.Alpha * scale); - } - - /// - /// Negates a color. - /// - /// The color to negate. - /// When the method completes, contains the negated color. - public static void Negate(ref Color4 value, out Color4 result) - { - result.Alpha = 1.0f - value.Alpha; - result.Red = 1.0f - value.Red; - result.Green = 1.0f - value.Green; - result.Blue = 1.0f - value.Blue; - } - - /// - /// Negates a color. - /// - /// The color to negate. - /// The negated color. - public static Color4 Negate(Color4 value) - { - return new Color4(1.0f - value.Red, 1.0f - value.Green, 1.0f - value.Blue, 1.0f - value.Alpha); - } - - /// - /// Restricts a value to be within a specified range. - /// - /// The value to clamp. - /// The minimum value. - /// The maximum value. - /// When the method completes, contains the clamped value. - public static void Clamp(ref Color4 value, ref Color4 min, ref Color4 max, out Color4 result) - { - float alpha = value.Alpha; - alpha = (alpha > max.Alpha) ? max.Alpha : alpha; - alpha = (alpha < min.Alpha) ? min.Alpha : alpha; - - float red = value.Red; - red = (red > max.Red) ? max.Red : red; - red = (red < min.Red) ? min.Red : red; - - float green = value.Green; - green = (green > max.Green) ? max.Green : green; - green = (green < min.Green) ? min.Green : green; - - float blue = value.Blue; - blue = (blue > max.Blue) ? max.Blue : blue; - blue = (blue < min.Blue) ? min.Blue : blue; - - result = new Color4(red, green, blue, alpha); - } - - /// - /// Restricts a value to be within a specified range. - /// - /// The value to clamp. - /// The minimum value. - /// The maximum value. - /// The clamped value. - public static Color4 Clamp(Color4 value, Color4 min, Color4 max) - { - Color4 result; - Clamp(ref value, ref min, ref max, out result); - return result; - } - - /// - /// Performs a linear interpolation between two colors. - /// - /// Start color. - /// End color. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the linear interpolation of the two colors. - /// - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static void Lerp(ref Color4 start, ref Color4 end, float amount, out Color4 result) - { - result.Red = MathUtil.Lerp(start.Red, end.Red, amount); - result.Green = MathUtil.Lerp(start.Green, end.Green, amount); - result.Blue = MathUtil.Lerp(start.Blue, end.Blue, amount); - result.Alpha = MathUtil.Lerp(start.Alpha, end.Alpha, amount); - } - - /// - /// Performs a linear interpolation between two colors. - /// - /// Start color. - /// End color. - /// Value between 0 and 1 indicating the weight of . - /// The linear interpolation of the two colors. - /// - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static Color4 Lerp(Color4 start, Color4 end, float amount) - { - Color4 result; - Lerp(ref start, ref end, amount, out result); - return result; - } - - /// - /// Performs a cubic interpolation between two colors. - /// - /// Start color. - /// End color. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the cubic interpolation of the two colors. - public static void SmoothStep(ref Color4 start, ref Color4 end, float amount, out Color4 result) - { - amount = MathUtil.SmoothStep(amount); - Lerp(ref start, ref end, amount, out result); - } - - /// - /// Performs a cubic interpolation between two colors. - /// - /// Start color. - /// End color. - /// Value between 0 and 1 indicating the weight of . - /// The cubic interpolation of the two colors. - public static Color4 SmoothStep(Color4 start, Color4 end, float amount) - { - Color4 result; - SmoothStep(ref start, ref end, amount, out result); - return result; - } - - /// - /// Returns a color containing the smallest components of the specified colors. - /// - /// The first source color. - /// The second source color. - /// When the method completes, contains an new color composed of the largest components of the source colors. - public static void Max(ref Color4 left, ref Color4 right, out Color4 result) - { - result.Alpha = (left.Alpha > right.Alpha) ? left.Alpha : right.Alpha; - result.Red = (left.Red > right.Red) ? left.Red : right.Red; - result.Green = (left.Green > right.Green) ? left.Green : right.Green; - result.Blue = (left.Blue > right.Blue) ? left.Blue : right.Blue; - } - - /// - /// Returns a color containing the largest components of the specified colors. - /// - /// The first source color. - /// The second source color. - /// A color containing the largest components of the source colors. - public static Color4 Max(Color4 left, Color4 right) - { - Color4 result; - Max(ref left, ref right, out result); - return result; - } - - /// - /// Returns a color containing the smallest components of the specified colors. - /// - /// The first source color. - /// The second source color. - /// When the method completes, contains an new color composed of the smallest components of the source colors. - public static void Min(ref Color4 left, ref Color4 right, out Color4 result) - { - result.Alpha = (left.Alpha < right.Alpha) ? left.Alpha : right.Alpha; - result.Red = (left.Red < right.Red) ? left.Red : right.Red; - result.Green = (left.Green < right.Green) ? left.Green : right.Green; - result.Blue = (left.Blue < right.Blue) ? left.Blue : right.Blue; - } - - /// - /// Returns a color containing the smallest components of the specified colors. - /// - /// The first source color. - /// The second source color. - /// A color containing the smallest components of the source colors. - public static Color4 Min(Color4 left, Color4 right) - { - Color4 result; - Min(ref left, ref right, out result); - return result; - } - - /// - /// Adjusts the contrast of a color. - /// - /// The color whose contrast is to be adjusted. - /// The amount by which to adjust the contrast. - /// When the method completes, contains the adjusted color. - public static void AdjustContrast(ref Color4 value, float contrast, out Color4 result) - { - result.Alpha = value.Alpha; - result.Red = 0.5f + contrast * (value.Red - 0.5f); - result.Green = 0.5f + contrast * (value.Green - 0.5f); - result.Blue = 0.5f + contrast * (value.Blue - 0.5f); - } - - /// - /// Adjusts the contrast of a color. - /// - /// The color whose contrast is to be adjusted. - /// The amount by which to adjust the contrast. - /// The adjusted color. - public static Color4 AdjustContrast(Color4 value, float contrast) - { - return new Color4( - 0.5f + contrast * (value.Red - 0.5f), - 0.5f + contrast * (value.Green - 0.5f), - 0.5f + contrast * (value.Blue - 0.5f), - value.Alpha); - } - - /// - /// Adjusts the saturation of a color. - /// - /// The color whose saturation is to be adjusted. - /// The amount by which to adjust the saturation. - /// When the method completes, contains the adjusted color. - public static void AdjustSaturation(ref Color4 value, float saturation, out Color4 result) - { - float grey = value.Red * 0.2125f + value.Green * 0.7154f + value.Blue * 0.0721f; - - result.Alpha = value.Alpha; - result.Red = grey + saturation * (value.Red - grey); - result.Green = grey + saturation * (value.Green - grey); - result.Blue = grey + saturation * (value.Blue - grey); - } - - /// - /// Adjusts the saturation of a color. - /// - /// The color whose saturation is to be adjusted. - /// The amount by which to adjust the saturation. - /// The adjusted color. - public static Color4 AdjustSaturation(Color4 value, float saturation) - { - float grey = value.Red * 0.2125f + value.Green * 0.7154f + value.Blue * 0.0721f; - - return new Color4( - grey + saturation * (value.Red - grey), - grey + saturation * (value.Green - grey), - grey + saturation * (value.Blue - grey), - value.Alpha); - } - - /// - /// Computes the premultiplied value of the provided color. - /// - /// The non-premultiplied value. - /// The premultiplied result. - public static void Premultiply(ref Color4 value, out Color4 result) - { - result.Alpha = value.Alpha; - result.Red = value.Red * value.Alpha; - result.Green = value.Green * value.Alpha; - result.Blue = value.Blue * value.Alpha; - } - - /// - /// Computes the premultiplied value of the provided color. - /// - /// The non-premultiplied value. - /// The premultiplied result. - public static Color4 Premultiply(Color4 value) - { - Color4 result; - Premultiply(ref value, out result); - return result; - } - - /// - /// Adds two colors. - /// - /// The first color to add. - /// The second color to add. - /// The sum of the two colors. - public static Color4 operator +(Color4 left, Color4 right) - { - return new Color4(left.Red + right.Red, left.Green + right.Green, left.Blue + right.Blue, left.Alpha + right.Alpha); - } - - /// - /// Assert a color (return it unchanged). - /// - /// The color to assert (unchanged). - /// The asserted (unchanged) color. - public static Color4 operator +(Color4 value) - { - return value; - } - - /// - /// Subtracts two colors. - /// - /// The first color to subtract. - /// The second color to subtract. - /// The difference of the two colors. - public static Color4 operator -(Color4 left, Color4 right) - { - return new Color4(left.Red - right.Red, left.Green - right.Green, left.Blue - right.Blue, left.Alpha - right.Alpha); - } - - /// - /// Negates a color. - /// - /// The color to negate. - /// A negated color. - public static Color4 operator -(Color4 value) - { - return new Color4(-value.Red, -value.Green, -value.Blue, -value.Alpha); - } - - /// - /// Scales a color. - /// - /// The factor by which to scale the color. - /// The color to scale. - /// The scaled color. - public static Color4 operator *(float scale, Color4 value) - { - return new Color4(value.Red * scale, value.Green * scale, value.Blue * scale, value.Alpha * scale); - } - - /// - /// Scales a color. - /// - /// The factor by which to scale the color. - /// The color to scale. - /// The scaled color. - public static Color4 operator *(Color4 value, float scale) - { - return new Color4(value.Red * scale, value.Green * scale, value.Blue * scale, value.Alpha * scale); - } - - /// - /// Modulates two colors. - /// - /// The first color to modulate. - /// The second color to modulate. - /// The modulated color. - public static Color4 operator *(Color4 left, Color4 right) - { - return new Color4(left.Red * right.Red, left.Green * right.Green, left.Blue * right.Blue, left.Alpha * right.Alpha); - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has the same value as ; otherwise, false. - public static bool operator ==(Color4 left, Color4 right) - { - return left.Equals(right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has a different value than ; otherwise, false. - public static bool operator !=(Color4 left, Color4 right) - { - return !left.Equals(right); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Color3(Color4 value) - { - return new Color3(value.Red, value.Green, value.Blue); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Vector3(Color4 value) - { - return new Vector3(value.Red, value.Green, value.Blue); - } - - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Vector4(Color4 value) - { - return new Vector4(value.Red, value.Green, value.Blue, value.Alpha); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Color4(Vector3 value) - { - return new Color4(value.X, value.Y, value.Z, 1.0f); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Color4(Vector4 value) - { - return new Color4(value.X, value.Y, value.Z, value.W); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Color4(ColorBGRA value) - { - return new Color4(value.R, value.G, value.B, value.A); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator ColorBGRA(Color4 value) - { - return new ColorBGRA(value.Red, value.Green, value.Blue, value.Alpha); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// - /// The result of the conversion. - /// - public static explicit operator int(Color4 value) - { - return value.ToRgba(); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// - /// The result of the conversion. - /// - public static explicit operator Color4(int value) - { - return new Color4(value); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return ToString(CultureInfo.CurrentCulture); - } - - /// - /// Returns a that represents this instance. - /// - /// The format to apply to each channel (float). - /// - /// A that represents this instance. - /// - public string ToString(string format) - { - return ToString(format, CultureInfo.CurrentCulture); - } - - /// - /// Returns a that represents this instance. - /// - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(IFormatProvider formatProvider) - { - return string.Format(formatProvider, toStringFormat, Alpha, Red, Green, Blue); - } - - /// - /// Returns a that represents this instance. - /// - /// The format to apply to each channel (float). - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - if (format == null) - return ToString(formatProvider); - - return string.Format(formatProvider, - toStringFormat, - Alpha.ToString(format, formatProvider), - Red.ToString(format, formatProvider), - Green.ToString(format, formatProvider), - Blue.ToString(format, formatProvider)); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - var hashCode = Red.GetHashCode(); - hashCode = (hashCode * 397) ^ Green.GetHashCode(); - hashCode = (hashCode * 397) ^ Blue.GetHashCode(); - hashCode = (hashCode * 397) ^ Alpha.GetHashCode(); - return hashCode; - } - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(Color4 other) - { - return Alpha == other.Alpha && Red == other.Red && Green == other.Green && Blue == other.Blue; - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object value) - { - if (value == null) - return false; - - if (!ReferenceEquals(value.GetType(), typeof(Color4))) - return false; - - return Equals((Color4)value); - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(Red); - serializer.Writer.Write(Green); - serializer.Writer.Write(Blue); - serializer.Writer.Write(Alpha); - } - else - { - Red = serializer.Reader.ReadSingle(); - Green = serializer.Reader.ReadSingle(); - Blue = serializer.Reader.ReadSingle(); - Alpha = serializer.Reader.ReadSingle(); - } - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from SlimMath project. http://code.google.com/p/slimmath/ +// Greetings to SlimDX Group. Original code published with the following license: +// ----------------------------------------------------------------------------- +/* +* Copyright (c) 2007-2011 SlimDX Group +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Represents a color in the form of rgba. + /// + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct Color4 : IEquatable, IFormattable + { + private const string toStringFormat = "Alpha:{0} Red:{1} Green:{2} Blue:{3}"; + + /// + /// The Black color (0, 0, 0, 1). + /// + public static readonly Color4 Black = new Color4(0.0f, 0.0f, 0.0f, 1.0f); + + /// + /// The White color (1, 1, 1, 1). + /// + public static readonly Color4 White = new Color4(1.0f, 1.0f, 1.0f, 1.0f); + + /// + /// The red component of the color. + /// + public float Red; + + /// + /// The green component of the color. + /// + public float Green; + + /// + /// The blue component of the color. + /// + public float Blue; + + /// + /// The alpha component of the color. + /// + public float Alpha; + + /// + /// Initializes a new instance of the struct. + /// + /// The value that will be assigned to all components. + public Color4(float value) + { + Alpha = Red = Green = Blue = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The red component of the color. + /// The green component of the color. + /// The blue component of the color. + /// The alpha component of the color. + public Color4(float red, float green, float blue, float alpha) + { + Red = red; + Green = green; + Blue = blue; + Alpha = alpha; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The red, green, blue, and alpha components of the color. + public Color4(Vector4 value) + { + Red = value.X; + Green = value.Y; + Blue = value.Z; + Alpha = value.W; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The red, green, and blue components of the color. + /// The alpha component of the color. + public Color4(Vector3 value, float alpha) + { + Red = value.X; + Green = value.Y; + Blue = value.Z; + Alpha = alpha; + } + + /// + /// Initializes a new instance of the struct. + /// + /// A packed integer containing all four color components in RGBA order. + public Color4(uint rgba) + { + Alpha = ((rgba >> 24) & 255) / 255.0f; + Blue = ((rgba >> 16) & 255) / 255.0f; + Green = ((rgba >> 8) & 255) / 255.0f; + Red = (rgba & 255) / 255.0f; + } + + /// + /// Initializes a new instance of the struct. + /// + /// A packed integer containing all four color components in RGBA order. + public Color4(int rgba) + { + Alpha = ((rgba >> 24) & 255) / 255.0f; + Blue = ((rgba >> 16) & 255) / 255.0f; + Green = ((rgba >> 8) & 255) / 255.0f; + Red = (rgba & 255) / 255.0f; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The values to assign to the red, green, blue, and alpha components of the color. This must be an array with four elements. + /// Thrown when is null. + /// Thrown when contains more or less than four elements. + public Color4(float[] values) + { + if (values == null) + throw new ArgumentNullException("values"); + if (values.Length != 4) + throw new ArgumentOutOfRangeException("values", "There must be four and only four input values for Color4."); + + Red = values[0]; + Green = values[1]; + Blue = values[2]; + Alpha = values[3]; + } + + /// + /// Initializes a new instance of the struct. + /// + /// used to initialize the color. + public Color4(Color3 color) + { + Red = color.Red; + Green = color.Green; + Blue = color.Blue; + Alpha = 1.0f; + } + + /// + /// Initializes a new instance of the struct. + /// + /// used to initialize the color. + /// The alpha component of the color. + public Color4(Color3 color, float alpha) + { + Red = color.Red; + Green = color.Green; + Blue = color.Blue; + Alpha = alpha; + } + + /// + /// Gets or sets the component at the specified index. + /// + /// The value of the red, green, blue, and alpha components, depending on the index. + /// The index of the component to access. Use 0 for the alpha component, 1 for the red component, 2 for the green component, and 3 for the blue component. + /// The value of the component at the specified index. + /// Thrown when the is out of the range [0, 3]. + public float this[int index] + { + get + { + switch (index) + { + case 0: return Red; + case 1: return Green; + case 2: return Blue; + case 3: return Alpha; + } + + throw new ArgumentOutOfRangeException("index", "Indices for Color4 run from 0 to 3, inclusive."); + } + + set + { + switch (index) + { + case 0: Red = value; break; + case 1: Green = value; break; + case 2: Blue = value; break; + case 3: Alpha = value; break; + default: throw new ArgumentOutOfRangeException("index", "Indices for Color4 run from 0 to 3, inclusive."); + } + } + } + + /// + /// Converts the color into a packed integer. + /// + /// A packed integer containing all four color components. + public int ToBgra() + { + uint a = (uint)(Alpha * 255.0f) & 255; + uint r = (uint)(Red * 255.0f) & 255; + uint g = (uint)(Green * 255.0f) & 255; + uint b = (uint)(Blue * 255.0f) & 255; + + uint value = b; + value |= g << 8; + value |= r << 16; + value |= a << 24; + + return (int)value; + } + + /// + /// Converts the color into a packed integer. + /// + /// A packed integer containing all four color components. + public void ToBgra(out byte r, out byte g, out byte b, out byte a) + { + a = (byte)(Alpha * 255.0f); + r = (byte)(Red * 255.0f); + g = (byte)(Green * 255.0f); + b = (byte)(Blue * 255.0f); + } + + /// + /// Converts the color into a packed integer. + /// + /// A packed integer containing all four color components. + public int ToRgba() + { + uint a = (uint) (Alpha * 255.0f) & 255; + uint r = (uint) (Red * 255.0f) & 255; + uint g = (uint) (Green * 255.0f) & 255; + uint b = (uint) (Blue * 255.0f) & 255; + + uint value = r; + value |= g << 8; + value |= b << 16; + value |= a << 24; + + return (int)value; + } + + /// + /// Converts the color into a three component vector. + /// + /// A three component vector containing the red, green, and blue components of the color. + public Vector3 ToVector3() + { + return new Vector3(Red, Green, Blue); + } + + /// + /// Converts the color into a four component vector. + /// + /// A four component vector containing all four color components. + public Vector4 ToVector4() + { + return new Vector4(Red, Green, Blue, Alpha); + } + + /// + /// Creates an array containing the elements of the color. + /// + /// A four-element array containing the components of the color. + public float[] ToArray() + { + return new float[] { Red, Green, Blue, Alpha }; + } + + /// + /// Adds two colors. + /// + /// The first color to add. + /// The second color to add. + /// When the method completes, completes the sum of the two colors. + public static void Add(ref Color4 left, ref Color4 right, out Color4 result) + { + result.Alpha = left.Alpha + right.Alpha; + result.Red = left.Red + right.Red; + result.Green = left.Green + right.Green; + result.Blue = left.Blue + right.Blue; + } + + /// + /// Adds two colors. + /// + /// The first color to add. + /// The second color to add. + /// The sum of the two colors. + public static Color4 Add(Color4 left, Color4 right) + { + return new Color4(left.Red + right.Red, left.Green + right.Green, left.Blue + right.Blue, left.Alpha + right.Alpha); + } + + /// + /// Subtracts two colors. + /// + /// The first color to subtract. + /// The second color to subtract. + /// WHen the method completes, contains the difference of the two colors. + public static void Subtract(ref Color4 left, ref Color4 right, out Color4 result) + { + result.Alpha = left.Alpha - right.Alpha; + result.Red = left.Red - right.Red; + result.Green = left.Green - right.Green; + result.Blue = left.Blue - right.Blue; + } + + /// + /// Subtracts two colors. + /// + /// The first color to subtract. + /// The second color to subtract + /// The difference of the two colors. + public static Color4 Subtract(Color4 left, Color4 right) + { + return new Color4(left.Red - right.Red, left.Green - right.Green, left.Blue - right.Blue, left.Alpha - right.Alpha); + } + + /// + /// Modulates two colors. + /// + /// The first color to modulate. + /// The second color to modulate. + /// When the method completes, contains the modulated color. + public static void Modulate(ref Color4 left, ref Color4 right, out Color4 result) + { + result.Alpha = left.Alpha * right.Alpha; + result.Red = left.Red * right.Red; + result.Green = left.Green * right.Green; + result.Blue = left.Blue * right.Blue; + } + + /// + /// Modulates two colors. + /// + /// The first color to modulate. + /// The second color to modulate. + /// The modulated color. + public static Color4 Modulate(Color4 left, Color4 right) + { + return new Color4(left.Red * right.Red, left.Green * right.Green, left.Blue * right.Blue, left.Alpha * right.Alpha); + } + + /// + /// Scales a color. + /// + /// The color to scale. + /// The amount by which to scale. + /// When the method completes, contains the scaled color. + public static void Scale(ref Color4 value, float scale, out Color4 result) + { + result.Alpha = value.Alpha * scale; + result.Red = value.Red * scale; + result.Green = value.Green * scale; + result.Blue = value.Blue * scale; + } + + /// + /// Scales a color. + /// + /// The color to scale. + /// The amount by which to scale. + /// The scaled color. + public static Color4 Scale(Color4 value, float scale) + { + return new Color4(value.Red * scale, value.Green * scale, value.Blue * scale, value.Alpha * scale); + } + + /// + /// Negates a color. + /// + /// The color to negate. + /// When the method completes, contains the negated color. + public static void Negate(ref Color4 value, out Color4 result) + { + result.Alpha = 1.0f - value.Alpha; + result.Red = 1.0f - value.Red; + result.Green = 1.0f - value.Green; + result.Blue = 1.0f - value.Blue; + } + + /// + /// Negates a color. + /// + /// The color to negate. + /// The negated color. + public static Color4 Negate(Color4 value) + { + return new Color4(1.0f - value.Red, 1.0f - value.Green, 1.0f - value.Blue, 1.0f - value.Alpha); + } + + /// + /// Restricts a value to be within a specified range. + /// + /// The value to clamp. + /// The minimum value. + /// The maximum value. + /// When the method completes, contains the clamped value. + public static void Clamp(ref Color4 value, ref Color4 min, ref Color4 max, out Color4 result) + { + float alpha = value.Alpha; + alpha = (alpha > max.Alpha) ? max.Alpha : alpha; + alpha = (alpha < min.Alpha) ? min.Alpha : alpha; + + float red = value.Red; + red = (red > max.Red) ? max.Red : red; + red = (red < min.Red) ? min.Red : red; + + float green = value.Green; + green = (green > max.Green) ? max.Green : green; + green = (green < min.Green) ? min.Green : green; + + float blue = value.Blue; + blue = (blue > max.Blue) ? max.Blue : blue; + blue = (blue < min.Blue) ? min.Blue : blue; + + result = new Color4(red, green, blue, alpha); + } + + /// + /// Restricts a value to be within a specified range. + /// + /// The value to clamp. + /// The minimum value. + /// The maximum value. + /// The clamped value. + public static Color4 Clamp(Color4 value, Color4 min, Color4 max) + { + Color4 result; + Clamp(ref value, ref min, ref max, out result); + return result; + } + + /// + /// Performs a linear interpolation between two colors. + /// + /// Start color. + /// End color. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the linear interpolation of the two colors. + /// + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static void Lerp(ref Color4 start, ref Color4 end, float amount, out Color4 result) + { + result.Red = MathUtil.Lerp(start.Red, end.Red, amount); + result.Green = MathUtil.Lerp(start.Green, end.Green, amount); + result.Blue = MathUtil.Lerp(start.Blue, end.Blue, amount); + result.Alpha = MathUtil.Lerp(start.Alpha, end.Alpha, amount); + } + + /// + /// Performs a linear interpolation between two colors. + /// + /// Start color. + /// End color. + /// Value between 0 and 1 indicating the weight of . + /// The linear interpolation of the two colors. + /// + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static Color4 Lerp(Color4 start, Color4 end, float amount) + { + Color4 result; + Lerp(ref start, ref end, amount, out result); + return result; + } + + /// + /// Performs a cubic interpolation between two colors. + /// + /// Start color. + /// End color. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the cubic interpolation of the two colors. + public static void SmoothStep(ref Color4 start, ref Color4 end, float amount, out Color4 result) + { + amount = MathUtil.SmoothStep(amount); + Lerp(ref start, ref end, amount, out result); + } + + /// + /// Performs a cubic interpolation between two colors. + /// + /// Start color. + /// End color. + /// Value between 0 and 1 indicating the weight of . + /// The cubic interpolation of the two colors. + public static Color4 SmoothStep(Color4 start, Color4 end, float amount) + { + Color4 result; + SmoothStep(ref start, ref end, amount, out result); + return result; + } + + /// + /// Returns a color containing the smallest components of the specified colors. + /// + /// The first source color. + /// The second source color. + /// When the method completes, contains an new color composed of the largest components of the source colors. + public static void Max(ref Color4 left, ref Color4 right, out Color4 result) + { + result.Alpha = (left.Alpha > right.Alpha) ? left.Alpha : right.Alpha; + result.Red = (left.Red > right.Red) ? left.Red : right.Red; + result.Green = (left.Green > right.Green) ? left.Green : right.Green; + result.Blue = (left.Blue > right.Blue) ? left.Blue : right.Blue; + } + + /// + /// Returns a color containing the largest components of the specified colors. + /// + /// The first source color. + /// The second source color. + /// A color containing the largest components of the source colors. + public static Color4 Max(Color4 left, Color4 right) + { + Color4 result; + Max(ref left, ref right, out result); + return result; + } + + /// + /// Returns a color containing the smallest components of the specified colors. + /// + /// The first source color. + /// The second source color. + /// When the method completes, contains an new color composed of the smallest components of the source colors. + public static void Min(ref Color4 left, ref Color4 right, out Color4 result) + { + result.Alpha = (left.Alpha < right.Alpha) ? left.Alpha : right.Alpha; + result.Red = (left.Red < right.Red) ? left.Red : right.Red; + result.Green = (left.Green < right.Green) ? left.Green : right.Green; + result.Blue = (left.Blue < right.Blue) ? left.Blue : right.Blue; + } + + /// + /// Returns a color containing the smallest components of the specified colors. + /// + /// The first source color. + /// The second source color. + /// A color containing the smallest components of the source colors. + public static Color4 Min(Color4 left, Color4 right) + { + Color4 result; + Min(ref left, ref right, out result); + return result; + } + + /// + /// Adjusts the contrast of a color. + /// + /// The color whose contrast is to be adjusted. + /// The amount by which to adjust the contrast. + /// When the method completes, contains the adjusted color. + public static void AdjustContrast(ref Color4 value, float contrast, out Color4 result) + { + result.Alpha = value.Alpha; + result.Red = 0.5f + contrast * (value.Red - 0.5f); + result.Green = 0.5f + contrast * (value.Green - 0.5f); + result.Blue = 0.5f + contrast * (value.Blue - 0.5f); + } + + /// + /// Adjusts the contrast of a color. + /// + /// The color whose contrast is to be adjusted. + /// The amount by which to adjust the contrast. + /// The adjusted color. + public static Color4 AdjustContrast(Color4 value, float contrast) + { + return new Color4( + 0.5f + contrast * (value.Red - 0.5f), + 0.5f + contrast * (value.Green - 0.5f), + 0.5f + contrast * (value.Blue - 0.5f), + value.Alpha); + } + + /// + /// Adjusts the saturation of a color. + /// + /// The color whose saturation is to be adjusted. + /// The amount by which to adjust the saturation. + /// When the method completes, contains the adjusted color. + public static void AdjustSaturation(ref Color4 value, float saturation, out Color4 result) + { + float grey = value.Red * 0.2125f + value.Green * 0.7154f + value.Blue * 0.0721f; + + result.Alpha = value.Alpha; + result.Red = grey + saturation * (value.Red - grey); + result.Green = grey + saturation * (value.Green - grey); + result.Blue = grey + saturation * (value.Blue - grey); + } + + /// + /// Adjusts the saturation of a color. + /// + /// The color whose saturation is to be adjusted. + /// The amount by which to adjust the saturation. + /// The adjusted color. + public static Color4 AdjustSaturation(Color4 value, float saturation) + { + float grey = value.Red * 0.2125f + value.Green * 0.7154f + value.Blue * 0.0721f; + + return new Color4( + grey + saturation * (value.Red - grey), + grey + saturation * (value.Green - grey), + grey + saturation * (value.Blue - grey), + value.Alpha); + } + + /// + /// Computes the premultiplied value of the provided color. + /// + /// The non-premultiplied value. + /// The premultiplied result. + public static void Premultiply(ref Color4 value, out Color4 result) + { + result.Alpha = value.Alpha; + result.Red = value.Red * value.Alpha; + result.Green = value.Green * value.Alpha; + result.Blue = value.Blue * value.Alpha; + } + + /// + /// Computes the premultiplied value of the provided color. + /// + /// The non-premultiplied value. + /// The premultiplied result. + public static Color4 Premultiply(Color4 value) + { + Color4 result; + Premultiply(ref value, out result); + return result; + } + + /// + /// Adds two colors. + /// + /// The first color to add. + /// The second color to add. + /// The sum of the two colors. + public static Color4 operator +(Color4 left, Color4 right) + { + return new Color4(left.Red + right.Red, left.Green + right.Green, left.Blue + right.Blue, left.Alpha + right.Alpha); + } + + /// + /// Assert a color (return it unchanged). + /// + /// The color to assert (unchanged). + /// The asserted (unchanged) color. + public static Color4 operator +(Color4 value) + { + return value; + } + + /// + /// Subtracts two colors. + /// + /// The first color to subtract. + /// The second color to subtract. + /// The difference of the two colors. + public static Color4 operator -(Color4 left, Color4 right) + { + return new Color4(left.Red - right.Red, left.Green - right.Green, left.Blue - right.Blue, left.Alpha - right.Alpha); + } + + /// + /// Negates a color. + /// + /// The color to negate. + /// A negated color. + public static Color4 operator -(Color4 value) + { + return new Color4(-value.Red, -value.Green, -value.Blue, -value.Alpha); + } + + /// + /// Scales a color. + /// + /// The factor by which to scale the color. + /// The color to scale. + /// The scaled color. + public static Color4 operator *(float scale, Color4 value) + { + return new Color4(value.Red * scale, value.Green * scale, value.Blue * scale, value.Alpha * scale); + } + + /// + /// Scales a color. + /// + /// The factor by which to scale the color. + /// The color to scale. + /// The scaled color. + public static Color4 operator *(Color4 value, float scale) + { + return new Color4(value.Red * scale, value.Green * scale, value.Blue * scale, value.Alpha * scale); + } + + /// + /// Modulates two colors. + /// + /// The first color to modulate. + /// The second color to modulate. + /// The modulated color. + public static Color4 operator *(Color4 left, Color4 right) + { + return new Color4(left.Red * right.Red, left.Green * right.Green, left.Blue * right.Blue, left.Alpha * right.Alpha); + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has the same value as ; otherwise, false. + public static bool operator ==(Color4 left, Color4 right) + { + return left.Equals(right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has a different value than ; otherwise, false. + public static bool operator !=(Color4 left, Color4 right) + { + return !left.Equals(right); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Color3(Color4 value) + { + return new Color3(value.Red, value.Green, value.Blue); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Vector3(Color4 value) + { + return new Vector3(value.Red, value.Green, value.Blue); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Vector4(Color4 value) + { + return new Vector4(value.Red, value.Green, value.Blue, value.Alpha); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Color4(Vector3 value) + { + return new Color4(value.X, value.Y, value.Z, 1.0f); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Color4(Vector4 value) + { + return new Color4(value.X, value.Y, value.Z, value.W); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Color4(ColorBGRA value) + { + return new Color4(value.R, value.G, value.B, value.A); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator ColorBGRA(Color4 value) + { + return new ColorBGRA(value.Red, value.Green, value.Blue, value.Alpha); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator int(Color4 value) + { + return value.ToRgba(); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// + /// The result of the conversion. + /// + public static explicit operator Color4(int value) + { + return new Color4(value); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return ToString(CultureInfo.CurrentCulture); + } + + /// + /// Returns a that represents this instance. + /// + /// The format to apply to each channel (float). + /// + /// A that represents this instance. + /// + public string ToString(string format) + { + return ToString(format, CultureInfo.CurrentCulture); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format(formatProvider, toStringFormat, Alpha, Red, Green, Blue); + } + + /// + /// Returns a that represents this instance. + /// + /// The format to apply to each channel (float). + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(string format, IFormatProvider formatProvider) + { + if (format == null) + return ToString(formatProvider); + + return string.Format(formatProvider, + toStringFormat, + Alpha.ToString(format, formatProvider), + Red.ToString(format, formatProvider), + Green.ToString(format, formatProvider), + Blue.ToString(format, formatProvider)); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + unchecked + { + var hashCode = Red.GetHashCode(); + hashCode = (hashCode * 397) ^ Green.GetHashCode(); + hashCode = (hashCode * 397) ^ Blue.GetHashCode(); + hashCode = (hashCode * 397) ^ Alpha.GetHashCode(); + return hashCode; + } + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(Color4 other) + { + return Alpha == other.Alpha && Red == other.Red && Green == other.Green && Blue == other.Blue; + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object value) + { + if (value == null) + return false; + + if (!ReferenceEquals(value.GetType(), typeof(Color4))) + return false; + + return Equals((Color4)value); + } + } +} diff --git a/Source/SharpDX/ColorBGRA.cs b/Source/SharpDX/Mathematics/ColorBGRA.cs similarity index 98% rename from Source/SharpDX/ColorBGRA.cs rename to Source/SharpDX/Mathematics/ColorBGRA.cs index c0974687d..b8a6b24ad 100644 --- a/Source/SharpDX/ColorBGRA.cs +++ b/Source/SharpDX/Mathematics/ColorBGRA.cs @@ -20,7 +20,6 @@ using System; using System.Globalization; using System.Runtime.InteropServices; -using SharpDX.Serialization; namespace SharpDX { @@ -28,11 +27,10 @@ namespace SharpDX /// Represents a 32-bit color (4 bytes) in the form of BGRA (in byte order: B, G, B, A). /// [StructLayout(LayoutKind.Sequential, Size = 4)] - [DynamicSerializer("TKC0")] - public partial struct ColorBGRA : IEquatable, IFormattable, IDataSerializable - { - private const string toStringFormat = "A:{0} R:{1} G:{2} B:{3}"; - + public partial struct ColorBGRA : IEquatable, IFormattable + { + private const string toStringFormat = "A:{0} R:{1} G:{2} B:{3}"; + /// /// The blue component of the color. /// @@ -613,11 +611,11 @@ public static ColorBGRA Clamp(ColorBGRA value, ColorBGRA min, ColorBGRA max) /// /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. /// - public static void Lerp(ref ColorBGRA start, ref ColorBGRA end, float amount, out ColorBGRA result) - { - result.B = MathUtil.Lerp(start.B, end.B, amount); - result.G = MathUtil.Lerp(start.G, end.G, amount); - result.R = MathUtil.Lerp(start.R, end.R, amount); + public static void Lerp(ref ColorBGRA start, ref ColorBGRA end, float amount, out ColorBGRA result) + { + result.B = MathUtil.Lerp(start.B, end.B, amount); + result.G = MathUtil.Lerp(start.G, end.G, amount); + result.R = MathUtil.Lerp(start.R, end.R, amount); result.A = MathUtil.Lerp(start.A, end.A, amount); } @@ -632,9 +630,9 @@ public static void Lerp(ref ColorBGRA start, ref ColorBGRA end, float amount, ou /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. /// public static ColorBGRA Lerp(ColorBGRA start, ColorBGRA end, float amount) - { - ColorBGRA result; - Lerp(ref start, ref end, amount, out result); + { + ColorBGRA result; + Lerp(ref start, ref end, amount, out result); return result; } @@ -645,9 +643,9 @@ public static ColorBGRA Lerp(ColorBGRA start, ColorBGRA end, float amount) /// End color. /// Value between 0 and 1 indicating the weight of . /// When the method completes, contains the cubic interpolation of the two colors. - public static void SmoothStep(ref ColorBGRA start, ref ColorBGRA end, float amount, out ColorBGRA result) - { - amount = MathUtil.SmoothStep(amount); + public static void SmoothStep(ref ColorBGRA start, ref ColorBGRA end, float amount, out ColorBGRA result) + { + amount = MathUtil.SmoothStep(amount); Lerp(ref start, ref end, amount, out result); } @@ -659,9 +657,9 @@ public static void SmoothStep(ref ColorBGRA start, ref ColorBGRA end, float amou /// Value between 0 and 1 indicating the weight of . /// The cubic interpolation of the two colors. public static ColorBGRA SmoothStep(ColorBGRA start, ColorBGRA end, float amount) - { - ColorBGRA result; - SmoothStep(ref start, ref end, amount, out result); + { + ColorBGRA result; + SmoothStep(ref start, ref end, amount, out result); return result; } @@ -779,32 +777,32 @@ public static ColorBGRA AdjustSaturation(ColorBGRA value, float saturation) ToByte(grey + saturation * (value.G / 255.0f - grey)), ToByte(grey + saturation * (value.B / 255.0f - grey)), value.A); - } - - /// - /// Computes the premultiplied value of the provided color. - /// - /// The non-premultiplied value. - /// The premultiplied result. - public static void Premultiply(ref ColorBGRA value, out ColorBGRA result) - { - var a = value.A / (255f * 255f); - result.A = value.A; - result.R = ToByte(value.R * a); - result.G = ToByte(value.G * a); - result.B = ToByte(value.B * a); - } - - /// - /// Computes the premultiplied value of the provided color. - /// - /// The non-premultiplied value. - /// The premultiplied result. - public static ColorBGRA Premultiply(ColorBGRA value) - { - ColorBGRA result; - Premultiply(ref value, out result); - return result; + } + + /// + /// Computes the premultiplied value of the provided color. + /// + /// The non-premultiplied value. + /// The premultiplied result. + public static void Premultiply(ref ColorBGRA value, out ColorBGRA result) + { + var a = value.A / (255f * 255f); + result.A = value.A; + result.R = ToByte(value.R * a); + result.G = ToByte(value.G * a); + result.B = ToByte(value.B * a); + } + + /// + /// Computes the premultiplied value of the provided color. + /// + /// The non-premultiplied value. + /// The premultiplied result. + public static ColorBGRA Premultiply(ColorBGRA value) + { + ColorBGRA result; + Premultiply(ref value, out result); + return result; } /// @@ -984,7 +982,7 @@ public static explicit operator ColorBGRA(Color4 value) return new ColorBGRA(value.Red, value.Green, value.Blue, value.Alpha); } - /// + /// /// Performs an implicit conversion from to . /// /// The value. @@ -994,7 +992,7 @@ public static implicit operator ColorBGRA(Color value) return new ColorBGRA(value.R, value.G, value.B, value.A); } - /// + /// /// Performs an implicit conversion from to . /// /// The value. @@ -1034,8 +1032,8 @@ public static explicit operator ColorBGRA(int value) /// /// A that represents this instance. /// - public override string ToString() - { + public override string ToString() + { return ToString(CultureInfo.CurrentCulture); } @@ -1046,8 +1044,8 @@ public override string ToString() /// /// A that represents this instance. /// - public string ToString(string format) - { + public string ToString(string format) + { return ToString(format, CultureInfo.CurrentCulture); } @@ -1065,7 +1063,7 @@ public string ToString(IFormatProvider formatProvider) /// /// Returns a that represents this instance. - /// + /// /// The format to apply to each channel (byte). /// The format provider. /// @@ -1074,14 +1072,14 @@ public string ToString(IFormatProvider formatProvider) public string ToString(string format, IFormatProvider formatProvider) { if (format == null) - return ToString(formatProvider); - - return string.Format(formatProvider, - toStringFormat, - A.ToString(format, formatProvider), - R.ToString(format, formatProvider), - G.ToString(format, formatProvider), - B.ToString(format, formatProvider)); + return ToString(formatProvider); + + return string.Format(formatProvider, + toStringFormat, + A.ToString(format, formatProvider), + R.ToString(format, formatProvider), + G.ToString(format, formatProvider), + B.ToString(format, formatProvider)); } /// @@ -1089,17 +1087,17 @@ public string ToString(string format, IFormatProvider formatProvider) /// /// /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - var hashCode = B.GetHashCode(); - hashCode = (hashCode * 397) ^ G.GetHashCode(); - hashCode = (hashCode * 397) ^ R.GetHashCode(); - hashCode = (hashCode * 397) ^ A.GetHashCode(); - return hashCode; - } + /// + public override int GetHashCode() + { + unchecked + { + var hashCode = B.GetHashCode(); + hashCode = (hashCode * 397) ^ G.GetHashCode(); + hashCode = (hashCode * 397) ^ R.GetHashCode(); + hashCode = (hashCode * 397) ^ A.GetHashCode(); + return hashCode; + } } /// @@ -1137,19 +1135,5 @@ private static byte ToByte(float component) var value = (int)(component * 255.0f); return (byte)(value < 0 ? 0 : value > 255 ? 255 : value); } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(ToBgra()); - } - else - { - this = FromBgra(serializer.Reader.ReadInt32()); - } - } } } diff --git a/Source/SharpDX/Half.cs b/Source/SharpDX/Mathematics/Half.cs similarity index 92% rename from Source/SharpDX/Half.cs rename to Source/SharpDX/Mathematics/Half.cs index 1651abf70..0ad9917a9 100644 --- a/Source/SharpDX/Half.cs +++ b/Source/SharpDX/Mathematics/Half.cs @@ -1,274 +1,258 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System.Globalization; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// A half precision (16 bit) floating point value. - /// - [StructLayout(LayoutKind.Sequential)] - [DynamicSerializer("TKH1")] - public struct Half : IDataSerializable - { - private ushort value; - - /// - /// Number of decimal digits of precision. - /// - public const int PrecisionDigits = 3; - - /// - /// Number of bits in the mantissa. - /// - public const int MantissaBits = 11; - - /// - /// Maximum decimal exponent. - /// - public const int MaximumDecimalExponent = 4; - - /// - /// Maximum binary exponent. - /// - public const int MaximumBinaryExponent = 15; - - /// - /// Minimum decimal exponent. - /// - public const int MinimumDecimalExponent = -4; - - /// - /// Minimum binary exponent. - /// - public const int MinimumBinaryExponent = -14; - - /// - /// Exponent radix. - /// - public const int ExponentRadix = 2; - - /// - /// Additional rounding. - /// - public const int AdditionRounding = 1; - - /// - /// Smallest such that 1.0 + epsilon != 1.0 - /// - public static readonly float Epsilon; - - /// - /// Maximum value of the number. - /// - public static readonly float MaxValue; - - /// - /// Minimum value of the number. - /// - public static readonly float MinValue; - - - /// - /// Initializes a new instance of the structure. - /// - /// The floating point value that should be stored in 16 bit format. - public Half(float value) - { - this.value = HalfUtils.Pack(value); - } - - /// - /// Initializes a new instance of the structure. - /// - /// The floating point value that should be stored in 16 bit format. - public Half(ushort rawvalue) - { - this.value = rawvalue; - } - - /// - /// Gets or sets the raw 16 bit value used to back this half-float. - /// - public ushort RawValue - { - get { return value; } - set { this.value = value; } - } - - /// - /// Converts an array of half precision values into full precision values. - /// - /// The values to be converted. - /// An array of converted values. - public static float[] ConvertToFloat(Half[] values) - { - float[] results = new float[values.Length]; - for(int i = 0; i < results.Length; i++) - results[i] = HalfUtils.Unpack(values[i].RawValue); - return results; - } - - /// - /// Converts an array of full precision values into half precision values. - /// - /// The values to be converted. - /// An array of converted values. - public static Half[] ConvertToHalf(float[] values) - { - Half[] results = new Half[values.Length]; - for(int i = 0; i < results.Length; i++) - results[i] = new Half(values[i]); - return results; - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value to be converted. - /// The converted value. - public static implicit operator Half(float value) - { - return new Half(value); - } - - /// - /// Performs an implicit conversion from to . - /// - /// The value to be converted. - /// The converted value. - public static implicit operator float(Half value) - { - return HalfUtils.Unpack(value.value); - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// true if has the same value as ; otherwise, false. - public static bool operator ==(Half left, Half right) - { - return left.value == right.value; - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// true if has a different value than ; otherwise, false. - public static bool operator !=(Half left, Half right) - { - return left.value != right.value; - } - - /// - /// Converts the value of the object to its equivalent string representation. - /// - /// The string representation of the value of this instance. - public override string ToString() - { - float num = this; - return num.ToString(CultureInfo.CurrentCulture); - } - - /// - /// Returns the hash code for this instance. - /// - /// A 32-bit signed integer hash code. - public override int GetHashCode() - { - ushort num = value; - return (((num*3)/2) ^ num); - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(value); - } - else - { - value = serializer.Reader.ReadUInt16(); - } - } - - /// - /// Determines whether the specified object instances are considered equal. - /// - /// - /// - /// - /// true if is the same instance as or - /// if both are null references or if value1.Equals(value2) returns true; otherwise, false. - public static bool Equals(ref Half value1, ref Half value2) - { - return value1.value == value2.value; - } - - /// - /// Returns a value that indicates whether the current instance is equal to the specified object. - /// - /// Object to make the comparison with. - /// - /// true if the current instance is equal to the specified object; false otherwise. - public bool Equals(Half other) - { - return other.value == value; - } - - /// - /// Returns a value that indicates whether the current instance is equal to a specified object. - /// - /// Object to make the comparison with. - /// - /// true if the current instance is equal to the specified object; false otherwise. - public override bool Equals(object obj) - { - if (obj == null) - { - return false; - } - if (!ReferenceEquals(obj.GetType(), typeof(Half))) - { - return false; - } - Half half = (Half) obj; - return half.value == value; - } - - static Half() - { - Epsilon = 0.0004887581f; - MaxValue = 65504f; - MinValue = 6.103516E-05f; - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// A half precision (16 bit) floating point value. + /// + [StructLayout(LayoutKind.Sequential)] + public struct Half + { + private ushort value; + + /// + /// Number of decimal digits of precision. + /// + public const int PrecisionDigits = 3; + + /// + /// Number of bits in the mantissa. + /// + public const int MantissaBits = 11; + + /// + /// Maximum decimal exponent. + /// + public const int MaximumDecimalExponent = 4; + + /// + /// Maximum binary exponent. + /// + public const int MaximumBinaryExponent = 15; + + /// + /// Minimum decimal exponent. + /// + public const int MinimumDecimalExponent = -4; + + /// + /// Minimum binary exponent. + /// + public const int MinimumBinaryExponent = -14; + + /// + /// Exponent radix. + /// + public const int ExponentRadix = 2; + + /// + /// Additional rounding. + /// + public const int AdditionRounding = 1; + + /// + /// Smallest such that 1.0 + epsilon != 1.0 + /// + public static readonly float Epsilon; + + /// + /// Maximum value of the number. + /// + public static readonly float MaxValue; + + /// + /// Minimum value of the number. + /// + public static readonly float MinValue; + + + /// + /// Initializes a new instance of the structure. + /// + /// The floating point value that should be stored in 16 bit format. + public Half(float value) + { + this.value = HalfUtils.Pack(value); + } + + /// + /// Initializes a new instance of the structure. + /// + /// The floating point value that should be stored in 16 bit format. + public Half(ushort rawvalue) + { + this.value = rawvalue; + } + + /// + /// Gets or sets the raw 16 bit value used to back this half-float. + /// + public ushort RawValue + { + get { return value; } + set { this.value = value; } + } + + /// + /// Converts an array of half precision values into full precision values. + /// + /// The values to be converted. + /// An array of converted values. + public static float[] ConvertToFloat(Half[] values) + { + float[] results = new float[values.Length]; + for(int i = 0; i < results.Length; i++) + results[i] = HalfUtils.Unpack(values[i].RawValue); + return results; + } + + /// + /// Converts an array of full precision values into half precision values. + /// + /// The values to be converted. + /// An array of converted values. + public static Half[] ConvertToHalf(float[] values) + { + Half[] results = new Half[values.Length]; + for(int i = 0; i < results.Length; i++) + results[i] = new Half(values[i]); + return results; + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value to be converted. + /// The converted value. + public static implicit operator Half(float value) + { + return new Half(value); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value to be converted. + /// The converted value. + public static implicit operator float(Half value) + { + return HalfUtils.Unpack(value.value); + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// + /// true if has the same value as ; otherwise, false. + public static bool operator ==(Half left, Half right) + { + return left.value == right.value; + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// + /// true if has a different value than ; otherwise, false. + public static bool operator !=(Half left, Half right) + { + return left.value != right.value; + } + + /// + /// Converts the value of the object to its equivalent string representation. + /// + /// The string representation of the value of this instance. + public override string ToString() + { + float num = this; + return num.ToString(CultureInfo.CurrentCulture); + } + + /// + /// Returns the hash code for this instance. + /// + /// A 32-bit signed integer hash code. + public override int GetHashCode() + { + ushort num = value; + return (((num*3)/2) ^ num); + } + + /// + /// Determines whether the specified object instances are considered equal. + /// + /// + /// + /// + /// true if is the same instance as or + /// if both are null references or if value1.Equals(value2) returns true; otherwise, false. + public static bool Equals(ref Half value1, ref Half value2) + { + return value1.value == value2.value; + } + + /// + /// Returns a value that indicates whether the current instance is equal to the specified object. + /// + /// Object to make the comparison with. + /// + /// true if the current instance is equal to the specified object; false otherwise. + public bool Equals(Half other) + { + return other.value == value; + } + + /// + /// Returns a value that indicates whether the current instance is equal to a specified object. + /// + /// Object to make the comparison with. + /// + /// true if the current instance is equal to the specified object; false otherwise. + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (!ReferenceEquals(obj.GetType(), typeof(Half))) + { + return false; + } + Half half = (Half) obj; + return half.value == value; + } + + static Half() + { + Epsilon = 0.0004887581f; + MaxValue = 65504f; + MinValue = 6.103516E-05f; + } + } +} diff --git a/Source/SharpDX/Half2.cs b/Source/SharpDX/Mathematics/Half2.cs similarity index 89% rename from Source/SharpDX/Half2.cs rename to Source/SharpDX/Mathematics/Half2.cs index 17d5f6897..b1796e628 100644 --- a/Source/SharpDX/Half2.cs +++ b/Source/SharpDX/Mathematics/Half2.cs @@ -1,214 +1,196 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Defines a two component vector, using half precision floating point coordinates. - /// - [StructLayout(LayoutKind.Sequential)] - [DynamicSerializer("TKH2")] - public struct Half2 : IEquatable, IDataSerializable - { - /// - /// Gets or sets the X component of the vector. - /// - /// The X component of the vector. - public Half X; - /// - /// Gets or sets the Y component of the vector. - /// - /// The Y component of the vector. - public Half Y; - - /// - /// Initializes a new instance of the structure. - /// - /// The X component. - /// The Y component. - public Half2(Half x, Half y) - { - this.X = x; - this.Y = y; - } - - /// - /// Initializes a new instance of the structure. - /// - /// The X component. - /// The Y component. - public Half2(float x, float y) - { - this.X = new Half(x); - this.Y = new Half(y); - } - - /// - /// Initializes a new instance of the structure. - /// - /// The X component. - /// The Y component. - public Half2(ushort x, ushort y) - { - this.X = new Half(x); - this.Y = new Half(y); - } - - /// - /// Initializes a new instance of the structure. - /// - /// The value to set for both the X and Y components. - public Half2(Half value) - { - this.X = value; - this.Y = value; - } - - /// - /// Initializes a new instance of the structure. - /// - /// Value to initialize X and Y components with. - public Half2(float value) - { - this.X = new Half(value); - this.Y = new Half(value); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Half2(Vector2 value) - { - return new Half2(value.X, value.Y); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Vector2(Half2 value) - { - return new Vector2(value.X, value.Y); - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// true if has the same value as ; otherwise, false. - public static bool operator ==(Half2 left, Half2 right) - { - return Equals(ref left, ref right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// true if has a different value than ; otherwise, false. - [return: MarshalAs(UnmanagedType.U1)] - public static bool operator !=(Half2 left, Half2 right) - { - return !Equals(ref left, ref right); - } - - /// - /// Returns the hash code for this instance. - /// - /// A 32-bit signed integer hash code. - public override int GetHashCode() - { - unchecked - { - return (X.GetHashCode() * 397) ^ Y.GetHashCode(); - } - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(X.RawValue); - serializer.Writer.Write(Y.RawValue); - } - else - { - X.RawValue = serializer.Reader.ReadUInt16(); - Y.RawValue = serializer.Reader.ReadUInt16(); - } - } - - /// - /// Determines whether the specified object instances are considered equal. - /// - /// - /// - /// - /// true if is the same instance as or - /// if both are null references or if value1.Equals(value2) returns true; otherwise, false. - public static bool Equals(ref Half2 value1, ref Half2 value2) - { - return ((value1.X == value2.X) && (value1.Y == value2.Y)); - } - - /// - /// Returns a value that indicates whether the current instance is equal to the specified object. - /// - /// Object to make the comparison with. - /// - /// true if the current instance is equal to the specified object; false otherwise. - public bool Equals(Half2 other) - { - return ((this.X == other.X) && (this.Y == other.Y)); - } - - /// - /// Returns a value that indicates whether the current instance is equal to a specified object. - /// - /// Object to make the comparison with. - /// - /// true if the current instance is equal to the specified object; false otherwise. - public override bool Equals(object obj) - { - if (obj == null) - { - return false; - } - if (!ReferenceEquals(obj.GetType(), typeof(Half2))) - { - return false; - } - return this.Equals((Half2)obj); - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Defines a two component vector, using half precision floating point coordinates. + /// + [StructLayout(LayoutKind.Sequential)] + public struct Half2 : IEquatable + { + /// + /// Gets or sets the X component of the vector. + /// + /// The X component of the vector. + public Half X; + /// + /// Gets or sets the Y component of the vector. + /// + /// The Y component of the vector. + public Half Y; + + /// + /// Initializes a new instance of the structure. + /// + /// The X component. + /// The Y component. + public Half2(Half x, Half y) + { + this.X = x; + this.Y = y; + } + + /// + /// Initializes a new instance of the structure. + /// + /// The X component. + /// The Y component. + public Half2(float x, float y) + { + this.X = new Half(x); + this.Y = new Half(y); + } + + /// + /// Initializes a new instance of the structure. + /// + /// The X component. + /// The Y component. + public Half2(ushort x, ushort y) + { + this.X = new Half(x); + this.Y = new Half(y); + } + + /// + /// Initializes a new instance of the structure. + /// + /// The value to set for both the X and Y components. + public Half2(Half value) + { + this.X = value; + this.Y = value; + } + + /// + /// Initializes a new instance of the structure. + /// + /// Value to initialize X and Y components with. + public Half2(float value) + { + this.X = new Half(value); + this.Y = new Half(value); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Half2(Vector2 value) + { + return new Half2(value.X, value.Y); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Vector2(Half2 value) + { + return new Vector2(value.X, value.Y); + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// + /// true if has the same value as ; otherwise, false. + public static bool operator ==(Half2 left, Half2 right) + { + return Equals(ref left, ref right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// + /// true if has a different value than ; otherwise, false. + [return: MarshalAs(UnmanagedType.U1)] + public static bool operator !=(Half2 left, Half2 right) + { + return !Equals(ref left, ref right); + } + + /// + /// Returns the hash code for this instance. + /// + /// A 32-bit signed integer hash code. + public override int GetHashCode() + { + unchecked + { + return (X.GetHashCode() * 397) ^ Y.GetHashCode(); + } + } + + /// + /// Determines whether the specified object instances are considered equal. + /// + /// + /// + /// + /// true if is the same instance as or + /// if both are null references or if value1.Equals(value2) returns true; otherwise, false. + public static bool Equals(ref Half2 value1, ref Half2 value2) + { + return ((value1.X == value2.X) && (value1.Y == value2.Y)); + } + + /// + /// Returns a value that indicates whether the current instance is equal to the specified object. + /// + /// Object to make the comparison with. + /// + /// true if the current instance is equal to the specified object; false otherwise. + public bool Equals(Half2 other) + { + return ((this.X == other.X) && (this.Y == other.Y)); + } + + /// + /// Returns a value that indicates whether the current instance is equal to a specified object. + /// + /// Object to make the comparison with. + /// + /// true if the current instance is equal to the specified object; false otherwise. + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (!ReferenceEquals(obj.GetType(), typeof(Half2))) + { + return false; + } + return this.Equals((Half2)obj); + } + } +} diff --git a/Source/SharpDX/Half3.cs b/Source/SharpDX/Mathematics/Half3.cs similarity index 89% rename from Source/SharpDX/Half3.cs rename to Source/SharpDX/Mathematics/Half3.cs index f7b8bb34b..f21683008 100644 --- a/Source/SharpDX/Half3.cs +++ b/Source/SharpDX/Mathematics/Half3.cs @@ -1,241 +1,221 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Defines a three component vector, using half precision floating point coordinates. - /// - [StructLayout(LayoutKind.Sequential)] - [DynamicSerializer("TKH3")] - public struct Half3 : IEquatable, IDataSerializable - { - /// - /// Gets or sets the X component of the vector. - /// - /// The X component of the vector. - public Half X; - /// - /// Gets or sets the Y component of the vector. - /// - /// The Y component of the vector. - public Half Y; - /// - /// Gets or sets the Z component of the vector. - /// - /// The Z component of the vector. - public Half Z; - - /// - /// Initializes a new instance of the structure. - /// - /// The X component. - /// The Y component. - /// The Z component. - public Half3(Half x, Half y, Half z) - { - this.X = x; - this.Y = y; - this.Z = z; - } - - /// - /// Initializes a new instance of the structure. - /// - /// The X component. - /// The Y component. - /// The Z component. - public Half3(float x, float y, float z) - { - this.X = new Half(x); - this.Y = new Half(y); - this.Z = new Half(z); - } - - /// - /// Initializes a new instance of the structure. - /// - /// The X component. - /// The Y component. - /// The Z component. - public Half3(ushort x, ushort y, ushort z) - { - this.X = new Half(x); - this.Y = new Half(y); - this.Z = new Half(z); - } - - /// - /// Initializes a new instance of the structure. - /// - /// The value to set for the X, Y, and Z components. - public Half3(Half value) - { - this.X = value; - this.Y = value; - this.Z = value; - } - - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Half3(Vector3 value) - { - return new Half3(value.X, value.Y, value.Z); - } - - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Vector3(Half3 value) - { - return new Vector3(value.X, value.Y, value.Z); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Half3(Vector2 value) - { - return new Half3(value.X, value.Y, 0.0f); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Vector2(Half3 value) - { - return new Vector2(value.X, value.Y); - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// true if has the same value as ; otherwise, false. - public static bool operator ==(Half3 left, Half3 right) - { - return Equals(ref left, ref right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// true if has a different value than ; otherwise, false. - [return: MarshalAs(UnmanagedType.U1)] - public static bool operator !=(Half3 left, Half3 right) - { - return !Equals(ref left, ref right); - } - - /// - /// Returns the hash code for this instance. - /// - /// A 32-bit signed integer hash code. - public override int GetHashCode() - { - unchecked - { - var hashCode = X.GetHashCode(); - hashCode = (hashCode * 397) ^ Y.GetHashCode(); - hashCode = (hashCode * 397) ^ Z.GetHashCode(); - return hashCode; - } - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(X.RawValue); - serializer.Writer.Write(Y.RawValue); - serializer.Writer.Write(Z.RawValue); - } - else - { - X.RawValue = serializer.Reader.ReadUInt16(); - Y.RawValue = serializer.Reader.ReadUInt16(); - Z.RawValue = serializer.Reader.ReadUInt16(); - } - } - - /// - /// Determines whether the specified object instances are considered equal. - /// - /// - /// - /// - /// true if is the same instance as or - /// if both are null references or if value1.Equals(value2) returns true; otherwise, false. - public static bool Equals(ref Half3 value1, ref Half3 value2) - { - return (((value1.X == value2.X) && (value1.Y == value2.Y)) && (value1.Z == value2.Z)); - } - - /// - /// Returns a value that indicates whether the current instance is equal to the specified object. - /// - /// Object to make the comparison with. - /// - /// true if the current instance is equal to the specified object; false otherwise. - public bool Equals(Half3 other) - { - return (((this.X == other.X) && (this.Y == other.Y)) && (this.Z == other.Z)); - } - - /// - /// Returns a value that indicates whether the current instance is equal to a specified object. - /// - /// Object to make the comparison with. - /// - /// true if the current instance is equal to the specified object; false otherwise. - public override bool Equals(object obj) - { - if (obj == null) - { - return false; - } - if (!ReferenceEquals(obj.GetType(), typeof(Half3))) - { - return false; - } - return this.Equals((Half3)obj); - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Defines a three component vector, using half precision floating point coordinates. + /// + [StructLayout(LayoutKind.Sequential)] + public struct Half3 : IEquatable + { + /// + /// Gets or sets the X component of the vector. + /// + /// The X component of the vector. + public Half X; + /// + /// Gets or sets the Y component of the vector. + /// + /// The Y component of the vector. + public Half Y; + /// + /// Gets or sets the Z component of the vector. + /// + /// The Z component of the vector. + public Half Z; + + /// + /// Initializes a new instance of the structure. + /// + /// The X component. + /// The Y component. + /// The Z component. + public Half3(Half x, Half y, Half z) + { + this.X = x; + this.Y = y; + this.Z = z; + } + + /// + /// Initializes a new instance of the structure. + /// + /// The X component. + /// The Y component. + /// The Z component. + public Half3(float x, float y, float z) + { + this.X = new Half(x); + this.Y = new Half(y); + this.Z = new Half(z); + } + + /// + /// Initializes a new instance of the structure. + /// + /// The X component. + /// The Y component. + /// The Z component. + public Half3(ushort x, ushort y, ushort z) + { + this.X = new Half(x); + this.Y = new Half(y); + this.Z = new Half(z); + } + + /// + /// Initializes a new instance of the structure. + /// + /// The value to set for the X, Y, and Z components. + public Half3(Half value) + { + this.X = value; + this.Y = value; + this.Z = value; + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Half3(Vector3 value) + { + return new Half3(value.X, value.Y, value.Z); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Vector3(Half3 value) + { + return new Vector3(value.X, value.Y, value.Z); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Half3(Vector2 value) + { + return new Half3(value.X, value.Y, 0.0f); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Vector2(Half3 value) + { + return new Vector2(value.X, value.Y); + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// + /// true if has the same value as ; otherwise, false. + public static bool operator ==(Half3 left, Half3 right) + { + return Equals(ref left, ref right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// + /// true if has a different value than ; otherwise, false. + [return: MarshalAs(UnmanagedType.U1)] + public static bool operator !=(Half3 left, Half3 right) + { + return !Equals(ref left, ref right); + } + + /// + /// Returns the hash code for this instance. + /// + /// A 32-bit signed integer hash code. + public override int GetHashCode() + { + unchecked + { + var hashCode = X.GetHashCode(); + hashCode = (hashCode * 397) ^ Y.GetHashCode(); + hashCode = (hashCode * 397) ^ Z.GetHashCode(); + return hashCode; + } + } + + /// + /// Determines whether the specified object instances are considered equal. + /// + /// + /// + /// + /// true if is the same instance as or + /// if both are null references or if value1.Equals(value2) returns true; otherwise, false. + public static bool Equals(ref Half3 value1, ref Half3 value2) + { + return (((value1.X == value2.X) && (value1.Y == value2.Y)) && (value1.Z == value2.Z)); + } + + /// + /// Returns a value that indicates whether the current instance is equal to the specified object. + /// + /// Object to make the comparison with. + /// + /// true if the current instance is equal to the specified object; false otherwise. + public bool Equals(Half3 other) + { + return (((this.X == other.X) && (this.Y == other.Y)) && (this.Z == other.Z)); + } + + /// + /// Returns a value that indicates whether the current instance is equal to a specified object. + /// + /// Object to make the comparison with. + /// + /// true if the current instance is equal to the specified object; false otherwise. + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (!ReferenceEquals(obj.GetType(), typeof(Half3))) + { + return false; + } + return this.Equals((Half3)obj); + } + } +} diff --git a/Source/SharpDX/Half4.cs b/Source/SharpDX/Mathematics/Half4.cs similarity index 89% rename from Source/SharpDX/Half4.cs rename to Source/SharpDX/Mathematics/Half4.cs index 4df50beea..2b669843f 100644 --- a/Source/SharpDX/Half4.cs +++ b/Source/SharpDX/Mathematics/Half4.cs @@ -1,275 +1,253 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Defines a four component vector, using half precision floating point coordinates. - /// - [StructLayout(LayoutKind.Sequential)] - [DynamicSerializer("TKH4")] - public struct Half4 : IEquatable, IDataSerializable - { - /// - /// Gets or sets the X component of the vector. - /// - /// The X component of the vector. - public Half X; - /// - /// Gets or sets the Y component of the vector. - /// - /// The Y component of the vector. - public Half Y; - /// - /// Gets or sets the Z component of the vector. - /// - /// The Z component of the vector. - public Half Z; - /// - /// Gets or sets the W component of the vector. - /// - /// The W component of the vector. - public Half W; - - /// - /// Initializes a new instance of the structure. - /// - /// The X component. - /// The Y component. - /// The Z component. - /// The W component. - public Half4(Half x, Half y, Half z, Half w) - { - this.X = x; - this.Y = y; - this.Z = z; - this.W = w; - } - - /// - /// Initializes a new instance of the structure. - /// - /// The X component. - /// The Y component. - /// The Z component. - /// The W component. - public Half4(float x, float y, float z, float w) - { - this.X = new Half(x); - this.Y = new Half(y); - this.Z = new Half(z); - this.W = new Half(w); - } - - /// - /// Initializes a new instance of the structure. - /// - /// The X component. - /// The Y component. - /// The Z component. - /// The W component. - public Half4(ushort x, ushort y, ushort z, ushort w) - { - this.X = new Half(x); - this.Y = new Half(y); - this.Z = new Half(z); - this.W = new Half(w); - } - - /// - /// Initializes a new instance of the structure. - /// - /// The value to set for the X, Y, Z, and W components. - public Half4(Half value) - { - this.X = value; - this.Y = value; - this.Z = value; - this.W = value; - } - - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Half4(Vector4 value) - { - return new Half4(value.X, value.Y, value.Z, value.W); - } - - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Vector4(Half4 value) - { - return new Vector4(value.X, value.Y, value.Z, value.W); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Half4(Vector3 value) - { - return new Half4(value.X, value.Y, value.Z, 0.0f); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Vector3(Half4 value) - { - return new Vector3(value.X, value.Y, value.Z); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Half4(Vector2 value) - { - return new Half4(value.X, value.Y, 0.0f, 0.0f); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Vector2(Half4 value) - { - return new Vector2(value.X, value.Y); - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// true if has the same value as ; otherwise, false. - public static bool operator ==(Half4 left, Half4 right) - { - return Equals(ref left, ref right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// true if has a different value than ; otherwise, false. - public static bool operator !=(Half4 left, Half4 right) - { - return !Equals(ref left, ref right); - } - - /// - /// Returns the hash code for this instance. - /// - /// A 32-bit signed integer hash code. - public override int GetHashCode() - { - unchecked - { - var hashCode = X.GetHashCode(); - hashCode = (hashCode * 397) ^ Y.GetHashCode(); - hashCode = (hashCode * 397) ^ Z.GetHashCode(); - hashCode = (hashCode * 397) ^ W.GetHashCode(); - return hashCode; - } - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(X.RawValue); - serializer.Writer.Write(Y.RawValue); - serializer.Writer.Write(Z.RawValue); - serializer.Writer.Write(W.RawValue); - } - else - { - X.RawValue = serializer.Reader.ReadUInt16(); - Y.RawValue = serializer.Reader.ReadUInt16(); - Z.RawValue = serializer.Reader.ReadUInt16(); - W.RawValue = serializer.Reader.ReadUInt16(); - } - } - - /// - /// Determines whether the specified object instances are considered equal. - /// - /// - /// - /// - /// true if is the same instance as or - /// if both are null references or if value1.Equals(value2) returns true; otherwise, false. - public static bool Equals(ref Half4 value1, ref Half4 value2) - { - return (((value1.X == value2.X) && (value1.Y == value2.Y)) && ((value1.Z == value2.Z) && (value1.W == value2.W))); - } - - /// - /// Returns a value that indicates whether the current instance is equal to the specified object. - /// - /// Object to make the comparison with. - /// - /// true if the current instance is equal to the specified object; false otherwise. - public bool Equals(Half4 other) - { - return (((this.X == other.X) && (this.Y == other.Y)) && ((this.Z == other.Z) && (this.W == other.W))); - } - - /// - /// Returns a value that indicates whether the current instance is equal to a specified object. - /// - /// Object to make the comparison with. - /// - /// true if the current instance is equal to the specified object; false otherwise. - public override bool Equals(object obj) - { - if (obj == null) - { - return false; - } - if (!ReferenceEquals(obj.GetType(), typeof(Half4))) - { - return false; - } - return this.Equals((Half4)obj); - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Defines a four component vector, using half precision floating point coordinates. + /// + [StructLayout(LayoutKind.Sequential)] + public struct Half4 : IEquatable + { + /// + /// Gets or sets the X component of the vector. + /// + /// The X component of the vector. + public Half X; + /// + /// Gets or sets the Y component of the vector. + /// + /// The Y component of the vector. + public Half Y; + /// + /// Gets or sets the Z component of the vector. + /// + /// The Z component of the vector. + public Half Z; + /// + /// Gets or sets the W component of the vector. + /// + /// The W component of the vector. + public Half W; + + /// + /// Initializes a new instance of the structure. + /// + /// The X component. + /// The Y component. + /// The Z component. + /// The W component. + public Half4(Half x, Half y, Half z, Half w) + { + this.X = x; + this.Y = y; + this.Z = z; + this.W = w; + } + + /// + /// Initializes a new instance of the structure. + /// + /// The X component. + /// The Y component. + /// The Z component. + /// The W component. + public Half4(float x, float y, float z, float w) + { + this.X = new Half(x); + this.Y = new Half(y); + this.Z = new Half(z); + this.W = new Half(w); + } + + /// + /// Initializes a new instance of the structure. + /// + /// The X component. + /// The Y component. + /// The Z component. + /// The W component. + public Half4(ushort x, ushort y, ushort z, ushort w) + { + this.X = new Half(x); + this.Y = new Half(y); + this.Z = new Half(z); + this.W = new Half(w); + } + + /// + /// Initializes a new instance of the structure. + /// + /// The value to set for the X, Y, Z, and W components. + public Half4(Half value) + { + this.X = value; + this.Y = value; + this.Z = value; + this.W = value; + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Half4(Vector4 value) + { + return new Half4(value.X, value.Y, value.Z, value.W); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Vector4(Half4 value) + { + return new Vector4(value.X, value.Y, value.Z, value.W); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Half4(Vector3 value) + { + return new Half4(value.X, value.Y, value.Z, 0.0f); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Vector3(Half4 value) + { + return new Vector3(value.X, value.Y, value.Z); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Half4(Vector2 value) + { + return new Half4(value.X, value.Y, 0.0f, 0.0f); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Vector2(Half4 value) + { + return new Vector2(value.X, value.Y); + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// + /// true if has the same value as ; otherwise, false. + public static bool operator ==(Half4 left, Half4 right) + { + return Equals(ref left, ref right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// + /// true if has a different value than ; otherwise, false. + public static bool operator !=(Half4 left, Half4 right) + { + return !Equals(ref left, ref right); + } + + /// + /// Returns the hash code for this instance. + /// + /// A 32-bit signed integer hash code. + public override int GetHashCode() + { + unchecked + { + var hashCode = X.GetHashCode(); + hashCode = (hashCode * 397) ^ Y.GetHashCode(); + hashCode = (hashCode * 397) ^ Z.GetHashCode(); + hashCode = (hashCode * 397) ^ W.GetHashCode(); + return hashCode; + } + } + + /// + /// Determines whether the specified object instances are considered equal. + /// + /// + /// + /// + /// true if is the same instance as or + /// if both are null references or if value1.Equals(value2) returns true; otherwise, false. + public static bool Equals(ref Half4 value1, ref Half4 value2) + { + return (((value1.X == value2.X) && (value1.Y == value2.Y)) && ((value1.Z == value2.Z) && (value1.W == value2.W))); + } + + /// + /// Returns a value that indicates whether the current instance is equal to the specified object. + /// + /// Object to make the comparison with. + /// + /// true if the current instance is equal to the specified object; false otherwise. + public bool Equals(Half4 other) + { + return (((this.X == other.X) && (this.Y == other.Y)) && ((this.Z == other.Z) && (this.W == other.W))); + } + + /// + /// Returns a value that indicates whether the current instance is equal to a specified object. + /// + /// Object to make the comparison with. + /// + /// true if the current instance is equal to the specified object; false otherwise. + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + if (!ReferenceEquals(obj.GetType(), typeof(Half4))) + { + return false; + } + return this.Equals((Half4)obj); + } + } +} diff --git a/Source/SharpDX/HalfUtils.cs b/Source/SharpDX/Mathematics/HalfUtils.cs similarity index 97% rename from Source/SharpDX/HalfUtils.cs rename to Source/SharpDX/Mathematics/HalfUtils.cs index 9a01b1301..80ee2c651 100644 --- a/Source/SharpDX/HalfUtils.cs +++ b/Source/SharpDX/Mathematics/HalfUtils.cs @@ -1,170 +1,170 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System.Runtime.InteropServices; - -namespace SharpDX -{ - /// - /// Helper class to perform Half/Float conversion. - /// Code extract from paper : www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf by Jeroen van der Zijp - /// - internal class HalfUtils - { - - [StructLayout(LayoutKind.Explicit)] - private struct FloatToUint - { - [FieldOffset(0)] - public uint uintValue; - [FieldOffset(0)] - public float floatValue; - } - - /// - /// Unpacks the specified h. - /// - /// The h. - /// - public static float Unpack(ushort h) - { - var conv = new FloatToUint(); - conv.uintValue = HalfToFloatMantissaTable[HalfToFloatOffsetTable[h >> 10] + (((uint)h) & 0x3ff)] + HalfToFloatExponentTable[h >> 10]; - return conv.floatValue; - } - - /// - /// Packs the specified f. - /// - /// The f. - /// - public static ushort Pack(float f) - { - FloatToUint conv = new FloatToUint(); - conv.floatValue = f; - return (ushort)(FloatToHalfBaseTable[(conv.uintValue >> 23) & 0x1ff] + ((conv.uintValue & 0x007fffff) >> FloatToHalfShiftTable[(conv.uintValue >> 23) & 0x1ff])); - } - - static readonly uint[] HalfToFloatMantissaTable = new uint[2048]; - static readonly uint[] HalfToFloatExponentTable = new uint[64]; - static readonly uint[] HalfToFloatOffsetTable = new uint[64]; - static readonly ushort[] FloatToHalfBaseTable = new ushort[512]; - static readonly byte[] FloatToHalfShiftTable = new byte[512]; - - static HalfUtils() - { - int i; - - // ------------------------------------------------------------------- - // Half to Float tables - // ------------------------------------------------------------------- - - // Mantissa table - - // 0 => 0 - HalfToFloatMantissaTable[0] = 0; - - // Transform subnormal to normalized - for (i = 1; i < 1024; i++) - { - uint m = ((uint)i) << 13; - uint e = 0; - - while ((m & 0x00800000) == 0) - { - e -= 0x00800000; - m <<= 1; - } - m &= ~ 0x00800000U; - e += 0x38800000; - HalfToFloatMantissaTable[i] = m | e; - } - - // Normal case - for (i = 1024; i < 2048; i++) - HalfToFloatMantissaTable[i] = 0x38000000 + (((uint)(i - 1024)) << 13); - - // Exponent table - - // 0 => 0 - HalfToFloatExponentTable[0] = 0; - - for (i = 1; i < 63; i++) - { - if (i < 31) // Positive Numbers - HalfToFloatExponentTable[i] = ((uint)i) << 23; - else // Negative Numbers - HalfToFloatExponentTable[i] = 0x80000000 + (((uint)(i - 32)) << 23); - } - HalfToFloatExponentTable[31] = 0x47800000; - HalfToFloatExponentTable[32] = 0x80000000; - HalfToFloatExponentTable[63] = 0xC7800000; - - // Offset table - HalfToFloatOffsetTable[0] = 0; - for (i = 1; i < 64; i++) - HalfToFloatOffsetTable[i] = 1024; - HalfToFloatOffsetTable[32] = 0; - - // ------------------------------------------------------------------- - // Float to Half tables - // ------------------------------------------------------------------- - - for (i = 0; i < 256; i++) - { - int e = i - 127; - if (e < -24) - { // Very small numbers map to zero - FloatToHalfBaseTable[i | 0x000] = 0x0000; - FloatToHalfBaseTable[i | 0x100] = 0x8000; - FloatToHalfShiftTable[i | 0x000] = 24; - FloatToHalfShiftTable[i | 0x100] = 24; - } - else if (e < -14) - { // Small numbers map to denorms - FloatToHalfBaseTable[i | 0x000] = (ushort)((0x0400 >> (-e - 14))); - FloatToHalfBaseTable[i | 0x100] = (ushort)((0x0400 >> (-e - 14)) | 0x8000); - FloatToHalfShiftTable[i | 0x000] = (byte)(-e - 1); - FloatToHalfShiftTable[i | 0x100] = (byte)(-e - 1); - } - else if (e <= 15) - { // Normal numbers just lose precision - FloatToHalfBaseTable[i | 0x000] = (ushort)(((e + 15) << 10)); - FloatToHalfBaseTable[i | 0x100] = (ushort)(((e + 15) << 10) | 0x8000); - FloatToHalfShiftTable[i | 0x000] = 13; - FloatToHalfShiftTable[i | 0x100] = 13; - } - else if (e < 128) - { // Large numbers map to Infinity - FloatToHalfBaseTable[i | 0x000] = 0x7C00; - FloatToHalfBaseTable[i | 0x100] = 0xFC00; - FloatToHalfShiftTable[i | 0x000] = 24; - FloatToHalfShiftTable[i | 0x100] = 24; - } - else - { // Infinity and NaN's stay Infinity and NaN's - FloatToHalfBaseTable[i | 0x000] = 0x7C00; - FloatToHalfBaseTable[i | 0x100] = 0xFC00; - FloatToHalfShiftTable[i | 0x000] = 13; - FloatToHalfShiftTable[i | 0x100] = 13; - } - } - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Helper class to perform Half/Float conversion. + /// Code extract from paper : www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf by Jeroen van der Zijp + /// + internal class HalfUtils + { + + [StructLayout(LayoutKind.Explicit)] + private struct FloatToUint + { + [FieldOffset(0)] + public uint uintValue; + [FieldOffset(0)] + public float floatValue; + } + + /// + /// Unpacks the specified h. + /// + /// The h. + /// + public static float Unpack(ushort h) + { + var conv = new FloatToUint(); + conv.uintValue = HalfToFloatMantissaTable[HalfToFloatOffsetTable[h >> 10] + (((uint)h) & 0x3ff)] + HalfToFloatExponentTable[h >> 10]; + return conv.floatValue; + } + + /// + /// Packs the specified f. + /// + /// The f. + /// + public static ushort Pack(float f) + { + FloatToUint conv = new FloatToUint(); + conv.floatValue = f; + return (ushort)(FloatToHalfBaseTable[(conv.uintValue >> 23) & 0x1ff] + ((conv.uintValue & 0x007fffff) >> FloatToHalfShiftTable[(conv.uintValue >> 23) & 0x1ff])); + } + + static readonly uint[] HalfToFloatMantissaTable = new uint[2048]; + static readonly uint[] HalfToFloatExponentTable = new uint[64]; + static readonly uint[] HalfToFloatOffsetTable = new uint[64]; + static readonly ushort[] FloatToHalfBaseTable = new ushort[512]; + static readonly byte[] FloatToHalfShiftTable = new byte[512]; + + static HalfUtils() + { + int i; + + // ------------------------------------------------------------------- + // Half to Float tables + // ------------------------------------------------------------------- + + // Mantissa table + + // 0 => 0 + HalfToFloatMantissaTable[0] = 0; + + // Transform subnormal to normalized + for (i = 1; i < 1024; i++) + { + uint m = ((uint)i) << 13; + uint e = 0; + + while ((m & 0x00800000) == 0) + { + e -= 0x00800000; + m <<= 1; + } + m &= ~ 0x00800000U; + e += 0x38800000; + HalfToFloatMantissaTable[i] = m | e; + } + + // Normal case + for (i = 1024; i < 2048; i++) + HalfToFloatMantissaTable[i] = 0x38000000 + (((uint)(i - 1024)) << 13); + + // Exponent table + + // 0 => 0 + HalfToFloatExponentTable[0] = 0; + + for (i = 1; i < 63; i++) + { + if (i < 31) // Positive Numbers + HalfToFloatExponentTable[i] = ((uint)i) << 23; + else // Negative Numbers + HalfToFloatExponentTable[i] = 0x80000000 + (((uint)(i - 32)) << 23); + } + HalfToFloatExponentTable[31] = 0x47800000; + HalfToFloatExponentTable[32] = 0x80000000; + HalfToFloatExponentTable[63] = 0xC7800000; + + // Offset table + HalfToFloatOffsetTable[0] = 0; + for (i = 1; i < 64; i++) + HalfToFloatOffsetTable[i] = 1024; + HalfToFloatOffsetTable[32] = 0; + + // ------------------------------------------------------------------- + // Float to Half tables + // ------------------------------------------------------------------- + + for (i = 0; i < 256; i++) + { + int e = i - 127; + if (e < -24) + { // Very small numbers map to zero + FloatToHalfBaseTable[i | 0x000] = 0x0000; + FloatToHalfBaseTable[i | 0x100] = 0x8000; + FloatToHalfShiftTable[i | 0x000] = 24; + FloatToHalfShiftTable[i | 0x100] = 24; + } + else if (e < -14) + { // Small numbers map to denorms + FloatToHalfBaseTable[i | 0x000] = (ushort)((0x0400 >> (-e - 14))); + FloatToHalfBaseTable[i | 0x100] = (ushort)((0x0400 >> (-e - 14)) | 0x8000); + FloatToHalfShiftTable[i | 0x000] = (byte)(-e - 1); + FloatToHalfShiftTable[i | 0x100] = (byte)(-e - 1); + } + else if (e <= 15) + { // Normal numbers just lose precision + FloatToHalfBaseTable[i | 0x000] = (ushort)(((e + 15) << 10)); + FloatToHalfBaseTable[i | 0x100] = (ushort)(((e + 15) << 10) | 0x8000); + FloatToHalfShiftTable[i | 0x000] = 13; + FloatToHalfShiftTable[i | 0x100] = 13; + } + else if (e < 128) + { // Large numbers map to Infinity + FloatToHalfBaseTable[i | 0x000] = 0x7C00; + FloatToHalfBaseTable[i | 0x100] = 0xFC00; + FloatToHalfShiftTable[i | 0x000] = 24; + FloatToHalfShiftTable[i | 0x100] = 24; + } + else + { // Infinity and NaN's stay Infinity and NaN's + FloatToHalfBaseTable[i | 0x000] = 0x7C00; + FloatToHalfBaseTable[i | 0x100] = 0xFC00; + FloatToHalfShiftTable[i | 0x000] = 13; + FloatToHalfShiftTable[i | 0x100] = 13; + } + } + } + } +} diff --git a/Source/SharpDX/Int3.cs b/Source/SharpDX/Mathematics/Int3.cs similarity index 97% rename from Source/SharpDX/Int3.cs rename to Source/SharpDX/Mathematics/Int3.cs index dd80187e9..078cfd25f 100644 --- a/Source/SharpDX/Int3.cs +++ b/Source/SharpDX/Mathematics/Int3.cs @@ -17,10 +17,9 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using System; +using System; using System.Globalization; -using System.Runtime.InteropServices; -using SharpDX.Serialization; +using System.Runtime.InteropServices; namespace SharpDX { @@ -28,8 +27,7 @@ namespace SharpDX /// Represents a three dimensional mathematical int vector. /// [StructLayout(LayoutKind.Sequential, Pack = 4)] - [DynamicSerializer("TKI3")] - public struct Int3 : IEquatable, IFormattable, IDataSerializable + public struct Int3 : IEquatable, IFormattable { /// /// The size of the type, in bytes. @@ -572,33 +570,15 @@ public string ToString(string format, IFormatProvider formatProvider) /// /// /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - var hashCode = X; - hashCode = (hashCode * 397) ^ Y; - hashCode = (hashCode * 397) ^ Z; - return hashCode; - } - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(X); - serializer.Writer.Write(Y); - serializer.Writer.Write(Z); - } - else + /// + public override int GetHashCode() + { + unchecked { - X = serializer.Reader.ReadInt32(); - Y = serializer.Reader.ReadInt32(); - Z = serializer.Reader.ReadInt32(); + var hashCode = X; + hashCode = (hashCode * 397) ^ Y; + hashCode = (hashCode * 397) ^ Z; + return hashCode; } } diff --git a/Source/SharpDX/Int4.cs b/Source/SharpDX/Mathematics/Int4.cs similarity index 94% rename from Source/SharpDX/Int4.cs rename to Source/SharpDX/Mathematics/Int4.cs index ac845e8aa..0c812a8c9 100644 --- a/Source/SharpDX/Int4.cs +++ b/Source/SharpDX/Mathematics/Int4.cs @@ -1,695 +1,673 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Represents a four dimensional mathematical vector. - /// - [StructLayout(LayoutKind.Sequential, Pack = 4)] - [DynamicSerializer("TKI4")] - public struct Int4 : IEquatable, IFormattable, IDataSerializable - { - /// - /// The size of the type, in bytes. - /// - public static readonly int SizeInBytes = Marshal.SizeOf(typeof (Int4)); - - /// - /// A with all of its components set to zero. - /// - public static readonly Int4 Zero = new Int4(); - - /// - /// The X unit (1, 0, 0, 0). - /// - public static readonly Int4 UnitX = new Int4(1, 0, 0, 0); - - /// - /// The Y unit (0, 1, 0, 0). - /// - public static readonly Int4 UnitY = new Int4(0, 1, 0, 0); - - /// - /// The Z unit (0, 0, 1, 0). - /// - public static readonly Int4 UnitZ = new Int4(0, 0, 1, 0); - - /// - /// The W unit (0, 0, 0, 1). - /// - public static readonly Int4 UnitW = new Int4(0, 0, 0, 1); - - /// - /// A with all of its components set to one. - /// - public static readonly Int4 One = new Int4(1, 1, 1, 1); - - /// - /// The X component of the vector. - /// - public int X; - - /// - /// The Y component of the vector. - /// - public int Y; - - /// - /// The Z component of the vector. - /// - public int Z; - - /// - /// The W component of the vector. - /// - public int W; - - /// - /// Initializes a new instance of the struct. - /// - /// The value that will be assigned to all components. - public Int4(int value) - { - X = value; - Y = value; - Z = value; - W = value; - } - - /// - /// Initializes a new instance of the struct. - /// - /// Initial value for the X component of the vector. - /// Initial value for the Y component of the vector. - /// Initial value for the Z component of the vector. - /// Initial value for the W component of the vector. - public Int4(int x, int y, int z, int w) - { - X = x; - Y = y; - Z = z; - W = w; - } - - - /// - /// Initializes a new instance of the struct. - /// - /// The values to assign to the X, Y, Z, and W components of the vector. This must be an array with four elements. - /// Thrown when is null. - /// Thrown when contains more or less than four elements. - public Int4(int[] values) - { - if (values == null) - throw new ArgumentNullException("values"); - if (values.Length != 4) - throw new ArgumentOutOfRangeException("values", - "There must be four and only four input values for Int4."); - - X = values[0]; - Y = values[1]; - Z = values[2]; - W = values[3]; - } - - /// - /// Gets or sets the component at the specified index. - /// - /// The value of the X, Y, Z, or W component, depending on the index. - /// The index of the component to access. Use 0 for the X component, 1 for the Y component, 2 for the Z component, and 3 for the W component. - /// The value of the component at the specified index. - /// Thrown when the is out of the range [0, 3]. - public int this[int index] - { - get - { - switch (index) - { - case 0: - return X; - case 1: - return Y; - case 2: - return Z; - case 3: - return W; - } - - throw new ArgumentOutOfRangeException("index", "Indices for Int4 run from 0 to 3, inclusive."); - } - - set - { - switch (index) - { - case 0: - X = value; - break; - case 1: - Y = value; - break; - case 2: - Z = value; - break; - case 3: - W = value; - break; - default: - throw new ArgumentOutOfRangeException("index", "Indices for Int4 run from 0 to 3, inclusive."); - } - } - } - - /// - /// Creates an array containing the elements of the vector. - /// - /// A four-element array containing the components of the vector. - public int[] ToArray() - { - return new int[] {X, Y, Z, W}; - } - - /// - /// Adds two vectors. - /// - /// The first vector to add. - /// The second vector to add. - /// When the method completes, contains the sum of the two vectors. - public static void Add(ref Int4 left, ref Int4 right, out Int4 result) - { - result = new Int4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W); - } - - /// - /// Adds two vectors. - /// - /// The first vector to add. - /// The second vector to add. - /// The sum of the two vectors. - public static Int4 Add(Int4 left, Int4 right) - { - return new Int4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W); - } - - /// - /// Subtracts two vectors. - /// - /// The first vector to subtract. - /// The second vector to subtract. - /// When the method completes, contains the difference of the two vectors. - public static void Subtract(ref Int4 left, ref Int4 right, out Int4 result) - { - result = new Int4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W); - } - - /// - /// Subtracts two vectors. - /// - /// The first vector to subtract. - /// The second vector to subtract. - /// The difference of the two vectors. - public static Int4 Subtract(Int4 left, Int4 right) - { - return new Int4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// When the method completes, contains the scaled vector. - public static void Multiply(ref Int4 value, int scale, out Int4 result) - { - result = new Int4(value.X*scale, value.Y*scale, value.Z*scale, value.W*scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Int4 Multiply(Int4 value, int scale) - { - return new Int4(value.X*scale, value.Y*scale, value.Z*scale, value.W*scale); - } - - /// - /// Modulates a vector with another by performing component-wise multiplication. - /// - /// The first vector to modulate. - /// The second vector to modulate. - /// When the method completes, contains the modulated vector. - public static void Modulate(ref Int4 left, ref Int4 right, out Int4 result) - { - result = new Int4(left.X*right.X, left.Y*right.Y, left.Z*right.Z, left.W*right.W); - } - - /// - /// Modulates a vector with another by performing component-wise multiplication. - /// - /// The first vector to modulate. - /// The second vector to modulate. - /// The modulated vector. - public static Int4 Modulate(Int4 left, Int4 right) - { - return new Int4(left.X*right.X, left.Y*right.Y, left.Z*right.Z, left.W*right.W); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// When the method completes, contains the scaled vector. - public static void Divide(ref Int4 value, int scale, out Int4 result) - { - result = new Int4(value.X/scale, value.Y/scale, value.Z/scale, value.W/scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Int4 Divide(Int4 value, int scale) - { - return new Int4(value.X/scale, value.Y/scale, value.Z/scale, value.W/scale); - } - - /// - /// Reverses the direction of a given vector. - /// - /// The vector to negate. - /// When the method completes, contains a vector facing in the opposite direction. - public static void Negate(ref Int4 value, out Int4 result) - { - result = new Int4(-value.X, -value.Y, -value.Z, -value.W); - } - - /// - /// Reverses the direction of a given vector. - /// - /// The vector to negate. - /// A vector facing in the opposite direction. - public static Int4 Negate(Int4 value) - { - return new Int4(-value.X, -value.Y, -value.Z, -value.W); - } - - /// - /// Restricts a value to be within a specified range. - /// - /// The value to clamp. - /// The minimum value. - /// The maximum value. - /// When the method completes, contains the clamped value. - public static void Clamp(ref Int4 value, ref Int4 min, ref Int4 max, out Int4 result) - { - int x = value.X; - x = (x > max.X) ? max.X : x; - x = (x < min.X) ? min.X : x; - - int y = value.Y; - y = (y > max.Y) ? max.Y : y; - y = (y < min.Y) ? min.Y : y; - - int z = value.Z; - z = (z > max.Z) ? max.Z : z; - z = (z < min.Z) ? min.Z : z; - - int w = value.W; - w = (w > max.W) ? max.W : w; - w = (w < min.W) ? min.W : w; - - result = new Int4(x, y, z, w); - } - - /// - /// Restricts a value to be within a specified range. - /// - /// The value to clamp. - /// The minimum value. - /// The maximum value. - /// The clamped value. - public static Int4 Clamp(Int4 value, Int4 min, Int4 max) - { - Int4 result; - Clamp(ref value, ref min, ref max, out result); - return result; - } - - /// - /// Returns a vector containing the smallest components of the specified vectors. - /// - /// The first source vector. - /// The second source vector. - /// When the method completes, contains an new vector composed of the largest components of the source vectors. - public static void Max(ref Int4 left, ref Int4 right, out Int4 result) - { - result.X = (left.X > right.X) ? left.X : right.X; - result.Y = (left.Y > right.Y) ? left.Y : right.Y; - result.Z = (left.Z > right.Z) ? left.Z : right.Z; - result.W = (left.W > right.W) ? left.W : right.W; - } - - /// - /// Returns a vector containing the largest components of the specified vectors. - /// - /// The first source vector. - /// The second source vector. - /// A vector containing the largest components of the source vectors. - public static Int4 Max(Int4 left, Int4 right) - { - Int4 result; - Max(ref left, ref right, out result); - return result; - } - - /// - /// Returns a vector containing the smallest components of the specified vectors. - /// - /// The first source vector. - /// The second source vector. - /// When the method completes, contains an new vector composed of the smallest components of the source vectors. - public static void Min(ref Int4 left, ref Int4 right, out Int4 result) - { - result.X = (left.X < right.X) ? left.X : right.X; - result.Y = (left.Y < right.Y) ? left.Y : right.Y; - result.Z = (left.Z < right.Z) ? left.Z : right.Z; - result.W = (left.W < right.W) ? left.W : right.W; - } - - /// - /// Returns a vector containing the smallest components of the specified vectors. - /// - /// The first source vector. - /// The second source vector. - /// A vector containing the smallest components of the source vectors. - public static Int4 Min(Int4 left, Int4 right) - { - Int4 result; - Min(ref left, ref right, out result); - return result; - } - - /// - /// Adds two vectors. - /// - /// The first vector to add. - /// The second vector to add. - /// The sum of the two vectors. - public static Int4 operator +(Int4 left, Int4 right) - { - return new Int4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W); - } - - /// - /// Assert a vector (return it unchanged). - /// - /// The vector to assert (unchanged). - /// The asserted (unchanged) vector. - public static Int4 operator +(Int4 value) - { - return value; - } - - /// - /// Subtracts two vectors. - /// - /// The first vector to subtract. - /// The second vector to subtract. - /// The difference of the two vectors. - public static Int4 operator -(Int4 left, Int4 right) - { - return new Int4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W); - } - - /// - /// Reverses the direction of a given vector. - /// - /// The vector to negate. - /// A vector facing in the opposite direction. - public static Int4 operator -(Int4 value) - { - return new Int4(-value.X, -value.Y, -value.Z, -value.W); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Int4 operator *(int scale, Int4 value) - { - return new Int4(value.X*scale, value.Y*scale, value.Z*scale, value.W*scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Int4 operator *(Int4 value, int scale) - { - return new Int4(value.X*scale, value.Y*scale, value.Z*scale, value.W*scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Int4 operator /(Int4 value, int scale) - { - return new Int4(value.X/scale, value.Y/scale, value.Z/scale, value.W/scale); - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has the same value as ; otherwise, false. - public static bool operator ==(Int4 left, Int4 right) - { - return left.Equals(right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has a different value than ; otherwise, false. - public static bool operator !=(Int4 left, Int4 right) - { - return !left.Equals(right); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Vector2(Int4 value) - { - return new Vector2(value.X, value.Y); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Vector3(Int4 value) - { - return new Vector3(value.X, value.Y, value.Z); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Vector4(Int4 value) - { - return new Vector4(value.X, value.Y, value.Z, value.W); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// - /// A that represents this instance. - /// - public string ToString(string format) - { - if (format == null) - return ToString(); - - return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2} W:{3}", - X.ToString(format, CultureInfo.CurrentCulture), - Y.ToString(format, CultureInfo.CurrentCulture), - Z.ToString(format, CultureInfo.CurrentCulture), - W.ToString(format, CultureInfo.CurrentCulture)); - } - - /// - /// Returns a that represents this instance. - /// - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(IFormatProvider formatProvider) - { - return string.Format(formatProvider, "X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - if (format == null) - ToString(formatProvider); - - return string.Format(formatProvider, "X:{0} Y:{1} Z:{2} W:{3}", X.ToString(format, formatProvider), - Y.ToString(format, formatProvider), Z.ToString(format, formatProvider), - W.ToString(format, formatProvider)); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - var hashCode = X; - hashCode = (hashCode * 397) ^ Y; - hashCode = (hashCode * 397) ^ Z; - hashCode = (hashCode * 397) ^ W; - return hashCode; - } - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(X); - serializer.Writer.Write(Y); - serializer.Writer.Write(Z); - serializer.Writer.Write(W); - } - else - { - X = serializer.Reader.ReadInt32(); - Y = serializer.Reader.ReadInt32(); - Z = serializer.Reader.ReadInt32(); - W = serializer.Reader.ReadInt32(); - } - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(Int4 other) - { - return other.X == X && other.Y == Y && other.Z == Z && other.W == W; - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object value) - { - if (value == null) - return false; - - if (!ReferenceEquals(value.GetType(), typeof(Int4))) - return false; - - return Equals((Int4) value); - } - - /// - /// Performs an implicit conversion from array to . - /// - /// The input. - /// The result of the conversion. - public static implicit operator Int4(int[] input) - { - return new Int4(input); - } - - /// - /// Performs an implicit conversion from to array. - /// - /// The input. - /// The result of the conversion. - public static implicit operator int[](Int4 input) - { - return input.ToArray(); - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Represents a four dimensional mathematical vector. + /// + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct Int4 : IEquatable, IFormattable + { + /// + /// The size of the type, in bytes. + /// + public static readonly int SizeInBytes = Marshal.SizeOf(typeof (Int4)); + + /// + /// A with all of its components set to zero. + /// + public static readonly Int4 Zero = new Int4(); + + /// + /// The X unit (1, 0, 0, 0). + /// + public static readonly Int4 UnitX = new Int4(1, 0, 0, 0); + + /// + /// The Y unit (0, 1, 0, 0). + /// + public static readonly Int4 UnitY = new Int4(0, 1, 0, 0); + + /// + /// The Z unit (0, 0, 1, 0). + /// + public static readonly Int4 UnitZ = new Int4(0, 0, 1, 0); + + /// + /// The W unit (0, 0, 0, 1). + /// + public static readonly Int4 UnitW = new Int4(0, 0, 0, 1); + + /// + /// A with all of its components set to one. + /// + public static readonly Int4 One = new Int4(1, 1, 1, 1); + + /// + /// The X component of the vector. + /// + public int X; + + /// + /// The Y component of the vector. + /// + public int Y; + + /// + /// The Z component of the vector. + /// + public int Z; + + /// + /// The W component of the vector. + /// + public int W; + + /// + /// Initializes a new instance of the struct. + /// + /// The value that will be assigned to all components. + public Int4(int value) + { + X = value; + Y = value; + Z = value; + W = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// Initial value for the X component of the vector. + /// Initial value for the Y component of the vector. + /// Initial value for the Z component of the vector. + /// Initial value for the W component of the vector. + public Int4(int x, int y, int z, int w) + { + X = x; + Y = y; + Z = z; + W = w; + } + + + /// + /// Initializes a new instance of the struct. + /// + /// The values to assign to the X, Y, Z, and W components of the vector. This must be an array with four elements. + /// Thrown when is null. + /// Thrown when contains more or less than four elements. + public Int4(int[] values) + { + if (values == null) + throw new ArgumentNullException("values"); + if (values.Length != 4) + throw new ArgumentOutOfRangeException("values", + "There must be four and only four input values for Int4."); + + X = values[0]; + Y = values[1]; + Z = values[2]; + W = values[3]; + } + + /// + /// Gets or sets the component at the specified index. + /// + /// The value of the X, Y, Z, or W component, depending on the index. + /// The index of the component to access. Use 0 for the X component, 1 for the Y component, 2 for the Z component, and 3 for the W component. + /// The value of the component at the specified index. + /// Thrown when the is out of the range [0, 3]. + public int this[int index] + { + get + { + switch (index) + { + case 0: + return X; + case 1: + return Y; + case 2: + return Z; + case 3: + return W; + } + + throw new ArgumentOutOfRangeException("index", "Indices for Int4 run from 0 to 3, inclusive."); + } + + set + { + switch (index) + { + case 0: + X = value; + break; + case 1: + Y = value; + break; + case 2: + Z = value; + break; + case 3: + W = value; + break; + default: + throw new ArgumentOutOfRangeException("index", "Indices for Int4 run from 0 to 3, inclusive."); + } + } + } + + /// + /// Creates an array containing the elements of the vector. + /// + /// A four-element array containing the components of the vector. + public int[] ToArray() + { + return new int[] {X, Y, Z, W}; + } + + /// + /// Adds two vectors. + /// + /// The first vector to add. + /// The second vector to add. + /// When the method completes, contains the sum of the two vectors. + public static void Add(ref Int4 left, ref Int4 right, out Int4 result) + { + result = new Int4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W); + } + + /// + /// Adds two vectors. + /// + /// The first vector to add. + /// The second vector to add. + /// The sum of the two vectors. + public static Int4 Add(Int4 left, Int4 right) + { + return new Int4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W); + } + + /// + /// Subtracts two vectors. + /// + /// The first vector to subtract. + /// The second vector to subtract. + /// When the method completes, contains the difference of the two vectors. + public static void Subtract(ref Int4 left, ref Int4 right, out Int4 result) + { + result = new Int4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W); + } + + /// + /// Subtracts two vectors. + /// + /// The first vector to subtract. + /// The second vector to subtract. + /// The difference of the two vectors. + public static Int4 Subtract(Int4 left, Int4 right) + { + return new Int4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// When the method completes, contains the scaled vector. + public static void Multiply(ref Int4 value, int scale, out Int4 result) + { + result = new Int4(value.X*scale, value.Y*scale, value.Z*scale, value.W*scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Int4 Multiply(Int4 value, int scale) + { + return new Int4(value.X*scale, value.Y*scale, value.Z*scale, value.W*scale); + } + + /// + /// Modulates a vector with another by performing component-wise multiplication. + /// + /// The first vector to modulate. + /// The second vector to modulate. + /// When the method completes, contains the modulated vector. + public static void Modulate(ref Int4 left, ref Int4 right, out Int4 result) + { + result = new Int4(left.X*right.X, left.Y*right.Y, left.Z*right.Z, left.W*right.W); + } + + /// + /// Modulates a vector with another by performing component-wise multiplication. + /// + /// The first vector to modulate. + /// The second vector to modulate. + /// The modulated vector. + public static Int4 Modulate(Int4 left, Int4 right) + { + return new Int4(left.X*right.X, left.Y*right.Y, left.Z*right.Z, left.W*right.W); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// When the method completes, contains the scaled vector. + public static void Divide(ref Int4 value, int scale, out Int4 result) + { + result = new Int4(value.X/scale, value.Y/scale, value.Z/scale, value.W/scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Int4 Divide(Int4 value, int scale) + { + return new Int4(value.X/scale, value.Y/scale, value.Z/scale, value.W/scale); + } + + /// + /// Reverses the direction of a given vector. + /// + /// The vector to negate. + /// When the method completes, contains a vector facing in the opposite direction. + public static void Negate(ref Int4 value, out Int4 result) + { + result = new Int4(-value.X, -value.Y, -value.Z, -value.W); + } + + /// + /// Reverses the direction of a given vector. + /// + /// The vector to negate. + /// A vector facing in the opposite direction. + public static Int4 Negate(Int4 value) + { + return new Int4(-value.X, -value.Y, -value.Z, -value.W); + } + + /// + /// Restricts a value to be within a specified range. + /// + /// The value to clamp. + /// The minimum value. + /// The maximum value. + /// When the method completes, contains the clamped value. + public static void Clamp(ref Int4 value, ref Int4 min, ref Int4 max, out Int4 result) + { + int x = value.X; + x = (x > max.X) ? max.X : x; + x = (x < min.X) ? min.X : x; + + int y = value.Y; + y = (y > max.Y) ? max.Y : y; + y = (y < min.Y) ? min.Y : y; + + int z = value.Z; + z = (z > max.Z) ? max.Z : z; + z = (z < min.Z) ? min.Z : z; + + int w = value.W; + w = (w > max.W) ? max.W : w; + w = (w < min.W) ? min.W : w; + + result = new Int4(x, y, z, w); + } + + /// + /// Restricts a value to be within a specified range. + /// + /// The value to clamp. + /// The minimum value. + /// The maximum value. + /// The clamped value. + public static Int4 Clamp(Int4 value, Int4 min, Int4 max) + { + Int4 result; + Clamp(ref value, ref min, ref max, out result); + return result; + } + + /// + /// Returns a vector containing the smallest components of the specified vectors. + /// + /// The first source vector. + /// The second source vector. + /// When the method completes, contains an new vector composed of the largest components of the source vectors. + public static void Max(ref Int4 left, ref Int4 right, out Int4 result) + { + result.X = (left.X > right.X) ? left.X : right.X; + result.Y = (left.Y > right.Y) ? left.Y : right.Y; + result.Z = (left.Z > right.Z) ? left.Z : right.Z; + result.W = (left.W > right.W) ? left.W : right.W; + } + + /// + /// Returns a vector containing the largest components of the specified vectors. + /// + /// The first source vector. + /// The second source vector. + /// A vector containing the largest components of the source vectors. + public static Int4 Max(Int4 left, Int4 right) + { + Int4 result; + Max(ref left, ref right, out result); + return result; + } + + /// + /// Returns a vector containing the smallest components of the specified vectors. + /// + /// The first source vector. + /// The second source vector. + /// When the method completes, contains an new vector composed of the smallest components of the source vectors. + public static void Min(ref Int4 left, ref Int4 right, out Int4 result) + { + result.X = (left.X < right.X) ? left.X : right.X; + result.Y = (left.Y < right.Y) ? left.Y : right.Y; + result.Z = (left.Z < right.Z) ? left.Z : right.Z; + result.W = (left.W < right.W) ? left.W : right.W; + } + + /// + /// Returns a vector containing the smallest components of the specified vectors. + /// + /// The first source vector. + /// The second source vector. + /// A vector containing the smallest components of the source vectors. + public static Int4 Min(Int4 left, Int4 right) + { + Int4 result; + Min(ref left, ref right, out result); + return result; + } + + /// + /// Adds two vectors. + /// + /// The first vector to add. + /// The second vector to add. + /// The sum of the two vectors. + public static Int4 operator +(Int4 left, Int4 right) + { + return new Int4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W); + } + + /// + /// Assert a vector (return it unchanged). + /// + /// The vector to assert (unchanged). + /// The asserted (unchanged) vector. + public static Int4 operator +(Int4 value) + { + return value; + } + + /// + /// Subtracts two vectors. + /// + /// The first vector to subtract. + /// The second vector to subtract. + /// The difference of the two vectors. + public static Int4 operator -(Int4 left, Int4 right) + { + return new Int4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W); + } + + /// + /// Reverses the direction of a given vector. + /// + /// The vector to negate. + /// A vector facing in the opposite direction. + public static Int4 operator -(Int4 value) + { + return new Int4(-value.X, -value.Y, -value.Z, -value.W); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Int4 operator *(int scale, Int4 value) + { + return new Int4(value.X*scale, value.Y*scale, value.Z*scale, value.W*scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Int4 operator *(Int4 value, int scale) + { + return new Int4(value.X*scale, value.Y*scale, value.Z*scale, value.W*scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Int4 operator /(Int4 value, int scale) + { + return new Int4(value.X/scale, value.Y/scale, value.Z/scale, value.W/scale); + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has the same value as ; otherwise, false. + public static bool operator ==(Int4 left, Int4 right) + { + return left.Equals(right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has a different value than ; otherwise, false. + public static bool operator !=(Int4 left, Int4 right) + { + return !left.Equals(right); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Vector2(Int4 value) + { + return new Vector2(value.X, value.Y); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Vector3(Int4 value) + { + return new Vector3(value.X, value.Y, value.Z); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Vector4(Int4 value) + { + return new Vector4(value.X, value.Y, value.Z, value.W); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// + /// A that represents this instance. + /// + public string ToString(string format) + { + if (format == null) + return ToString(); + + return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2} W:{3}", + X.ToString(format, CultureInfo.CurrentCulture), + Y.ToString(format, CultureInfo.CurrentCulture), + Z.ToString(format, CultureInfo.CurrentCulture), + W.ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format(formatProvider, "X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(string format, IFormatProvider formatProvider) + { + if (format == null) + ToString(formatProvider); + + return string.Format(formatProvider, "X:{0} Y:{1} Z:{2} W:{3}", X.ToString(format, formatProvider), + Y.ToString(format, formatProvider), Z.ToString(format, formatProvider), + W.ToString(format, formatProvider)); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + unchecked + { + var hashCode = X; + hashCode = (hashCode * 397) ^ Y; + hashCode = (hashCode * 397) ^ Z; + hashCode = (hashCode * 397) ^ W; + return hashCode; + } + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(Int4 other) + { + return other.X == X && other.Y == Y && other.Z == Z && other.W == W; + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object value) + { + if (value == null) + return false; + + if (!ReferenceEquals(value.GetType(), typeof(Int4))) + return false; + + return Equals((Int4) value); + } + + /// + /// Performs an implicit conversion from array to . + /// + /// The input. + /// The result of the conversion. + public static implicit operator Int4(int[] input) + { + return new Int4(input); + } + + /// + /// Performs an implicit conversion from to array. + /// + /// The input. + /// The result of the conversion. + public static implicit operator int[](Int4 input) + { + return input.ToArray(); + } + } +} diff --git a/Source/SharpDX/MathUtil.cs b/Source/SharpDX/Mathematics/MathUtil.cs similarity index 97% rename from Source/SharpDX/MathUtil.cs rename to Source/SharpDX/Mathematics/MathUtil.cs index 61f1e0a40..849ffe9c8 100644 --- a/Source/SharpDX/MathUtil.cs +++ b/Source/SharpDX/Mathematics/MathUtil.cs @@ -1,461 +1,461 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ----------------------------------------------------------------------------- -// Original code from SlimMath project. http://code.google.com/p/slimmath/ -// Greetings to SlimDX Group. Original code published with the following license: -// ----------------------------------------------------------------------------- -/* -* Copyright (c) 2007-2011 SlimDX Group -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ -using System; - -namespace SharpDX -{ - public static class MathUtil - { - /// - /// The value for which all absolute numbers smaller than are considered equal to zero. - /// - public const float ZeroTolerance = 1e-6f; // Value a 8x higher than 1.19209290E-07F - - /// - /// A value specifying the approximation of π which is 180 degrees. - /// - public const float Pi = (float)Math.PI; - - /// - /// A value specifying the approximation of 2π which is 360 degrees. - /// - public const float TwoPi = (float)(2 * Math.PI); - - /// - /// A value specifying the approximation of π/2 which is 90 degrees. - /// - public const float PiOverTwo = (float)(Math.PI / 2); - - /// - /// A value specifying the approximation of π/4 which is 45 degrees. - /// - public const float PiOverFour = (float)(Math.PI / 4); - - /// - /// Checks if a and b are almost equals, taking into account the magnitude of floating point numbers (unlike method). See Remarks. - /// See remarks. - /// - /// The left value to compare. - /// The right value to compare. - /// true if a almost equal to b, false otherwise - /// - /// The code is using the technique described by Bruce Dawson in - /// Comparing Floating point numbers 2012 edition. - /// - public unsafe static bool NearEqual(float a, float b) - { - // Check if the numbers are really close -- needed - // when comparing numbers near zero. - if (IsZero(a - b)) - return true; - - // Original from Bruce Dawson: http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ - int aInt = *(int*)&a; - int bInt = *(int*)&b; - - // Different signs means they do not match. - if((aInt < 0) != (bInt < 0)) - return false; - - // Find the difference in ULPs. - int ulp = Math.Abs(aInt - bInt); - - // Choose of maxUlp = 4 - // according to http://code.google.com/p/googletest/source/browse/trunk/include/gtest/internal/gtest-internal.h - const int maxUlp = 4; - return (ulp <= maxUlp); - } - - /// - /// Determines whether the specified value is close to zero (0.0f). - /// - /// The floating value. - /// true if the specified value is close to zero (0.0f); otherwise, false. - public static bool IsZero(float a) - { - return Math.Abs(a) < ZeroTolerance; - } - - /// - /// Determines whether the specified value is close to one (1.0f). - /// - /// The floating value. - /// true if the specified value is close to one (1.0f); otherwise, false. - public static bool IsOne(float a) - { - return IsZero(a - 1.0f); - } - - /// - /// Checks if a - b are almost equals within a float epsilon. - /// - /// The left value to compare. - /// The right value to compare. - /// Epsilon value - /// true if a almost equal to b within a float epsilon, false otherwise - public static bool WithinEpsilon(float a, float b, float epsilon) - { - float num = a - b; - return ((-epsilon <= num) && (num <= epsilon)); - } - - /// - /// Converts revolutions to degrees. - /// - /// The value to convert. - /// The converted value. - public static float RevolutionsToDegrees(float revolution) - { - return revolution * 360.0f; - } - - /// - /// Converts revolutions to radians. - /// - /// The value to convert. - /// The converted value. - public static float RevolutionsToRadians(float revolution) - { - return revolution * TwoPi; - } - - /// - /// Converts revolutions to gradians. - /// - /// The value to convert. - /// The converted value. - public static float RevolutionsToGradians(float revolution) - { - return revolution * 400.0f; - } - - /// - /// Converts degrees to revolutions. - /// - /// The value to convert. - /// The converted value. - public static float DegreesToRevolutions(float degree) - { - return degree / 360.0f; - } - - /// - /// Converts degrees to radians. - /// - /// The value to convert. - /// The converted value. - public static float DegreesToRadians(float degree) - { - return degree * (Pi / 180.0f); - } - - /// - /// Converts radians to revolutions. - /// - /// The value to convert. - /// The converted value. - public static float RadiansToRevolutions(float radian) - { - return radian / TwoPi; - } - - /// - /// Converts radians to gradians. - /// - /// The value to convert. - /// The converted value. - public static float RadiansToGradians(float radian) - { - return radian * (200.0f / Pi); - } - - /// - /// Converts gradians to revolutions. - /// - /// The value to convert. - /// The converted value. - public static float GradiansToRevolutions(float gradian) - { - return gradian / 400.0f; - } - - /// - /// Converts gradians to degrees. - /// - /// The value to convert. - /// The converted value. - public static float GradiansToDegrees(float gradian) - { - return gradian * (9.0f / 10.0f); - } - - /// - /// Converts gradians to radians. - /// - /// The value to convert. - /// The converted value. - public static float GradiansToRadians(float gradian) - { - return gradian * (Pi / 200.0f); - } - - /// - /// Converts radians to degrees. - /// - /// The value to convert. - /// The converted value. - public static float RadiansToDegrees(float radian) - { - return radian * (180.0f / Pi); - } - - /// - /// Clamps the specified value. - /// - /// The value. - /// The min. - /// The max. - /// The result of clamping a value between min and max - public static float Clamp(float value, float min, float max) - { - return value < min ? min : value > max ? max : value; - } - - /// - /// Clamps the specified value. - /// - /// The value. - /// The min. - /// The max. - /// The result of clamping a value between min and max - public static int Clamp(int value, int min, int max) - { - return value < min ? min : value > max ? max : value; - } - - /// - /// Interpolates between two values using a linear function by a given amount. - /// - /// - /// See http://www.encyclopediaofmath.org/index.php/Linear_interpolation and - /// http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ - /// - /// Value to interpolate from. - /// Value to interpolate to. - /// Interpolation amount. - /// The result of linear interpolation of values based on the amount. - public static double Lerp(double from, double to, double amount) - { - return (1 - amount) * from + amount * to; - } - - /// - /// Interpolates between two values using a linear function by a given amount. - /// - /// - /// See http://www.encyclopediaofmath.org/index.php/Linear_interpolation and - /// http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ - /// - /// Value to interpolate from. - /// Value to interpolate to. - /// Interpolation amount. - /// The result of linear interpolation of values based on the amount. - public static float Lerp(float from, float to, float amount) - { - return (1 - amount) * from + amount * to; - } - - /// - /// Interpolates between two values using a linear function by a given amount. - /// - /// - /// See http://www.encyclopediaofmath.org/index.php/Linear_interpolation and - /// http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ - /// - /// Value to interpolate from. - /// Value to interpolate to. - /// Interpolation amount. - /// The result of linear interpolation of values based on the amount. - public static byte Lerp(byte from, byte to, float amount) - { - return (byte)Lerp((float)from, (float)to, amount); - } - - /// - /// Performs smooth (cubic Hermite) interpolation between 0 and 1. - /// - /// - /// See https://en.wikipedia.org/wiki/Smoothstep - /// - /// Value between 0 and 1 indicating interpolation amount. - public static float SmoothStep(float amount) - { - return (amount <= 0) ? 0 - : (amount >= 1) ? 1 - : amount * amount * (3 - (2 * amount)); - } - - /// - /// Performs a smooth(er) interpolation between 0 and 1 with 1st and 2nd order derivatives of zero at endpoints. - /// - /// - /// See https://en.wikipedia.org/wiki/Smoothstep - /// - /// Value between 0 and 1 indicating interpolation amount. - public static float SmootherStep(float amount) - { - return (amount <= 0) ? 0 - : (amount >= 1) ? 1 - : amount * amount * amount * (amount * ((amount * 6) - 15) + 10); - } - - /// - /// Calculates the modulo of the specified value. - /// - /// The value. - /// The modulo. - /// The result of the modulo applied to value - public static float Mod(float value, float modulo) - { - if (modulo == 0.0f) - { - return value; - } - - return value % modulo; - } - - /// - /// Calculates the modulo 2*PI of the specified value. - /// - /// The value. - /// The result of the modulo applied to value - public static float Mod2PI(float value) - { - return Mod(value, TwoPi); - } - - /// - /// Wraps the specified value into a range [min, max] - /// - /// The value to wrap. - /// The min. - /// The max. - /// Result of the wrapping. - /// Is thrown when is greater than . - public static int Wrap(int value, int min, int max) - { - if (min > max) - throw new ArgumentException(string.Format("min {0} should be less than or equal to max {1}", min, max), "min"); - - // Code from http://stackoverflow.com/a/707426/1356325 - int range_size = max - min + 1; - - if (value < min) - value += range_size * ((min - value) / range_size + 1); - - return min + (value - min) % range_size; - } - - /// - /// Wraps the specified value into a range [min, max[ - /// - /// The value. - /// The min. - /// The max. - /// Result of the wrapping. - /// Is thrown when is greater than . - public static float Wrap(float value, float min, float max) - { - if (NearEqual(min, max)) return min; - - double mind = min; - double maxd = max; - double valued = value; - - if (mind > maxd) - throw new ArgumentException(string.Format("min {0} should be less than or equal to max {1}", min, max), "min"); - - var range_size = maxd - mind; - return (float)(mind + (valued - mind) - (range_size * Math.Floor((valued - mind) / range_size))); - } - - /// - /// Gauss function. - /// - /// Curve amplitude. - /// Position X. - /// Position Y - /// Radius X. - /// Radius Y. - /// Curve sigma X. - /// Curve sigma Y. - /// The result of Gaussian function. - public static float Gauss(float amplitude, float x, float y, float radX, float radY, float sigmaX, float sigmaY) - { - return (float)Gauss((double)amplitude, x, y, radX, radY, sigmaX, sigmaY); - } - - /// - /// Gauss function. - /// - /// Curve amplitude. - /// Position X. - /// Position Y - /// Radius X. - /// Radius Y. - /// Curve sigma X. - /// Curve sigma Y. - /// The result of Gaussian function. - public static double Gauss(double amplitude, double x, double y, double radX, double radY, double sigmaX, double sigmaY) - { - return (amplitude * Math.E) - - ( - Math.Pow(x - (radX / 2), 2) / (2 * Math.Pow(sigmaX, 2)) + - Math.Pow(y - (radY / 2), 2) / (2 * Math.Pow(sigmaY, 2)) - ); - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from SlimMath project. http://code.google.com/p/slimmath/ +// Greetings to SlimDX Group. Original code published with the following license: +// ----------------------------------------------------------------------------- +/* +* Copyright (c) 2007-2011 SlimDX Group +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +using System; + +namespace SharpDX +{ + public static class MathUtil + { + /// + /// The value for which all absolute numbers smaller than are considered equal to zero. + /// + public const float ZeroTolerance = 1e-6f; // Value a 8x higher than 1.19209290E-07F + + /// + /// A value specifying the approximation of π which is 180 degrees. + /// + public const float Pi = (float)Math.PI; + + /// + /// A value specifying the approximation of 2π which is 360 degrees. + /// + public const float TwoPi = (float)(2 * Math.PI); + + /// + /// A value specifying the approximation of π/2 which is 90 degrees. + /// + public const float PiOverTwo = (float)(Math.PI / 2); + + /// + /// A value specifying the approximation of π/4 which is 45 degrees. + /// + public const float PiOverFour = (float)(Math.PI / 4); + + /// + /// Checks if a and b are almost equals, taking into account the magnitude of floating point numbers (unlike method). See Remarks. + /// See remarks. + /// + /// The left value to compare. + /// The right value to compare. + /// true if a almost equal to b, false otherwise + /// + /// The code is using the technique described by Bruce Dawson in + /// Comparing Floating point numbers 2012 edition. + /// + public unsafe static bool NearEqual(float a, float b) + { + // Check if the numbers are really close -- needed + // when comparing numbers near zero. + if (IsZero(a - b)) + return true; + + // Original from Bruce Dawson: http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ + int aInt = *(int*)&a; + int bInt = *(int*)&b; + + // Different signs means they do not match. + if((aInt < 0) != (bInt < 0)) + return false; + + // Find the difference in ULPs. + int ulp = Math.Abs(aInt - bInt); + + // Choose of maxUlp = 4 + // according to http://code.google.com/p/googletest/source/browse/trunk/include/gtest/internal/gtest-internal.h + const int maxUlp = 4; + return (ulp <= maxUlp); + } + + /// + /// Determines whether the specified value is close to zero (0.0f). + /// + /// The floating value. + /// true if the specified value is close to zero (0.0f); otherwise, false. + public static bool IsZero(float a) + { + return Math.Abs(a) < ZeroTolerance; + } + + /// + /// Determines whether the specified value is close to one (1.0f). + /// + /// The floating value. + /// true if the specified value is close to one (1.0f); otherwise, false. + public static bool IsOne(float a) + { + return IsZero(a - 1.0f); + } + + /// + /// Checks if a - b are almost equals within a float epsilon. + /// + /// The left value to compare. + /// The right value to compare. + /// Epsilon value + /// true if a almost equal to b within a float epsilon, false otherwise + public static bool WithinEpsilon(float a, float b, float epsilon) + { + float num = a - b; + return ((-epsilon <= num) && (num <= epsilon)); + } + + /// + /// Converts revolutions to degrees. + /// + /// The value to convert. + /// The converted value. + public static float RevolutionsToDegrees(float revolution) + { + return revolution * 360.0f; + } + + /// + /// Converts revolutions to radians. + /// + /// The value to convert. + /// The converted value. + public static float RevolutionsToRadians(float revolution) + { + return revolution * TwoPi; + } + + /// + /// Converts revolutions to gradians. + /// + /// The value to convert. + /// The converted value. + public static float RevolutionsToGradians(float revolution) + { + return revolution * 400.0f; + } + + /// + /// Converts degrees to revolutions. + /// + /// The value to convert. + /// The converted value. + public static float DegreesToRevolutions(float degree) + { + return degree / 360.0f; + } + + /// + /// Converts degrees to radians. + /// + /// The value to convert. + /// The converted value. + public static float DegreesToRadians(float degree) + { + return degree * (Pi / 180.0f); + } + + /// + /// Converts radians to revolutions. + /// + /// The value to convert. + /// The converted value. + public static float RadiansToRevolutions(float radian) + { + return radian / TwoPi; + } + + /// + /// Converts radians to gradians. + /// + /// The value to convert. + /// The converted value. + public static float RadiansToGradians(float radian) + { + return radian * (200.0f / Pi); + } + + /// + /// Converts gradians to revolutions. + /// + /// The value to convert. + /// The converted value. + public static float GradiansToRevolutions(float gradian) + { + return gradian / 400.0f; + } + + /// + /// Converts gradians to degrees. + /// + /// The value to convert. + /// The converted value. + public static float GradiansToDegrees(float gradian) + { + return gradian * (9.0f / 10.0f); + } + + /// + /// Converts gradians to radians. + /// + /// The value to convert. + /// The converted value. + public static float GradiansToRadians(float gradian) + { + return gradian * (Pi / 200.0f); + } + + /// + /// Converts radians to degrees. + /// + /// The value to convert. + /// The converted value. + public static float RadiansToDegrees(float radian) + { + return radian * (180.0f / Pi); + } + + /// + /// Clamps the specified value. + /// + /// The value. + /// The min. + /// The max. + /// The result of clamping a value between min and max + public static float Clamp(float value, float min, float max) + { + return value < min ? min : value > max ? max : value; + } + + /// + /// Clamps the specified value. + /// + /// The value. + /// The min. + /// The max. + /// The result of clamping a value between min and max + public static int Clamp(int value, int min, int max) + { + return value < min ? min : value > max ? max : value; + } + + /// + /// Interpolates between two values using a linear function by a given amount. + /// + /// + /// See http://www.encyclopediaofmath.org/index.php/Linear_interpolation and + /// http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ + /// + /// Value to interpolate from. + /// Value to interpolate to. + /// Interpolation amount. + /// The result of linear interpolation of values based on the amount. + public static double Lerp(double from, double to, double amount) + { + return (1 - amount) * from + amount * to; + } + + /// + /// Interpolates between two values using a linear function by a given amount. + /// + /// + /// See http://www.encyclopediaofmath.org/index.php/Linear_interpolation and + /// http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ + /// + /// Value to interpolate from. + /// Value to interpolate to. + /// Interpolation amount. + /// The result of linear interpolation of values based on the amount. + public static float Lerp(float from, float to, float amount) + { + return (1 - amount) * from + amount * to; + } + + /// + /// Interpolates between two values using a linear function by a given amount. + /// + /// + /// See http://www.encyclopediaofmath.org/index.php/Linear_interpolation and + /// http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ + /// + /// Value to interpolate from. + /// Value to interpolate to. + /// Interpolation amount. + /// The result of linear interpolation of values based on the amount. + public static byte Lerp(byte from, byte to, float amount) + { + return (byte)Lerp((float)from, (float)to, amount); + } + + /// + /// Performs smooth (cubic Hermite) interpolation between 0 and 1. + /// + /// + /// See https://en.wikipedia.org/wiki/Smoothstep + /// + /// Value between 0 and 1 indicating interpolation amount. + public static float SmoothStep(float amount) + { + return (amount <= 0) ? 0 + : (amount >= 1) ? 1 + : amount * amount * (3 - (2 * amount)); + } + + /// + /// Performs a smooth(er) interpolation between 0 and 1 with 1st and 2nd order derivatives of zero at endpoints. + /// + /// + /// See https://en.wikipedia.org/wiki/Smoothstep + /// + /// Value between 0 and 1 indicating interpolation amount. + public static float SmootherStep(float amount) + { + return (amount <= 0) ? 0 + : (amount >= 1) ? 1 + : amount * amount * amount * (amount * ((amount * 6) - 15) + 10); + } + + /// + /// Calculates the modulo of the specified value. + /// + /// The value. + /// The modulo. + /// The result of the modulo applied to value + public static float Mod(float value, float modulo) + { + if (modulo == 0.0f) + { + return value; + } + + return value % modulo; + } + + /// + /// Calculates the modulo 2*PI of the specified value. + /// + /// The value. + /// The result of the modulo applied to value + public static float Mod2PI(float value) + { + return Mod(value, TwoPi); + } + + /// + /// Wraps the specified value into a range [min, max] + /// + /// The value to wrap. + /// The min. + /// The max. + /// Result of the wrapping. + /// Is thrown when is greater than . + public static int Wrap(int value, int min, int max) + { + if (min > max) + throw new ArgumentException(string.Format("min {0} should be less than or equal to max {1}", min, max), "min"); + + // Code from http://stackoverflow.com/a/707426/1356325 + int range_size = max - min + 1; + + if (value < min) + value += range_size * ((min - value) / range_size + 1); + + return min + (value - min) % range_size; + } + + /// + /// Wraps the specified value into a range [min, max[ + /// + /// The value. + /// The min. + /// The max. + /// Result of the wrapping. + /// Is thrown when is greater than . + public static float Wrap(float value, float min, float max) + { + if (NearEqual(min, max)) return min; + + double mind = min; + double maxd = max; + double valued = value; + + if (mind > maxd) + throw new ArgumentException(string.Format("min {0} should be less than or equal to max {1}", min, max), "min"); + + var range_size = maxd - mind; + return (float)(mind + (valued - mind) - (range_size * Math.Floor((valued - mind) / range_size))); + } + + /// + /// Gauss function. + /// + /// Curve amplitude. + /// Position X. + /// Position Y + /// Radius X. + /// Radius Y. + /// Curve sigma X. + /// Curve sigma Y. + /// The result of Gaussian function. + public static float Gauss(float amplitude, float x, float y, float radX, float radY, float sigmaX, float sigmaY) + { + return (float)Gauss((double)amplitude, x, y, radX, radY, sigmaX, sigmaY); + } + + /// + /// Gauss function. + /// + /// Curve amplitude. + /// Position X. + /// Position Y + /// Radius X. + /// Radius Y. + /// Curve sigma X. + /// Curve sigma Y. + /// The result of Gaussian function. + public static double Gauss(double amplitude, double x, double y, double radX, double radY, double sigmaX, double sigmaY) + { + return (amplitude * Math.E) - + ( + Math.Pow(x - (radX / 2), 2) / (2 * Math.Pow(sigmaX, 2)) + + Math.Pow(y - (radY / 2), 2) / (2 * Math.Pow(sigmaY, 2)) + ); + } + } +} diff --git a/Source/SharpDX/Matrix.cs b/Source/SharpDX/Mathematics/Matrix.cs similarity index 94% rename from Source/SharpDX/Matrix.cs rename to Source/SharpDX/Mathematics/Matrix.cs index 187c759ca..669b9f344 100644 --- a/Source/SharpDX/Matrix.cs +++ b/Source/SharpDX/Mathematics/Matrix.cs @@ -1,3503 +1,3367 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ----------------------------------------------------------------------------- -// Original code from SlimMath project. http://code.google.com/p/slimmath/ -// Greetings to SlimDX Group. Original code published with the following license: -// ----------------------------------------------------------------------------- -/* -* Copyright (c) 2007-2011 SlimDX Group -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ - -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Represents a 4x4 mathematical matrix. - /// - [StructLayout(LayoutKind.Sequential, Pack = 4)] - [DynamicSerializer("TKMX")] - public struct Matrix : IEquatable, IFormattable, IDataSerializable - { - /// - /// The size of the type, in bytes. - /// - public static readonly int SizeInBytes = Marshal.SizeOf(typeof(Matrix)); - - /// - /// A with all of its components set to zero. - /// - public static readonly Matrix Zero = new Matrix(); - - /// - /// The identity . - /// - public static readonly Matrix Identity = new Matrix() { M11 = 1.0f, M22 = 1.0f, M33 = 1.0f, M44 = 1.0f }; - - /// - /// Value at row 1 column 1 of the matrix. - /// - public float M11; - - /// - /// Value at row 1 column 2 of the matrix. - /// - public float M12; - - /// - /// Value at row 1 column 3 of the matrix. - /// - public float M13; - - /// - /// Value at row 1 column 4 of the matrix. - /// - public float M14; - - /// - /// Value at row 2 column 1 of the matrix. - /// - public float M21; - - /// - /// Value at row 2 column 2 of the matrix. - /// - public float M22; - - /// - /// Value at row 2 column 3 of the matrix. - /// - public float M23; - - /// - /// Value at row 2 column 4 of the matrix. - /// - public float M24; - - /// - /// Value at row 3 column 1 of the matrix. - /// - public float M31; - - /// - /// Value at row 3 column 2 of the matrix. - /// - public float M32; - - /// - /// Value at row 3 column 3 of the matrix. - /// - public float M33; - - /// - /// Value at row 3 column 4 of the matrix. - /// - public float M34; - - /// - /// Value at row 4 column 1 of the matrix. - /// - public float M41; - - /// - /// Value at row 4 column 2 of the matrix. - /// - public float M42; - - /// - /// Value at row 4 column 3 of the matrix. - /// - public float M43; - - /// - /// Value at row 4 column 4 of the matrix. - /// - public float M44; - - /// - /// Gets or sets the up of the matrix; that is M21, M22, and M23. - /// - public Vector3 Up - { - get - { - Vector3 vector3; - vector3.X = this.M21; - vector3.Y = this.M22; - vector3.Z = this.M23; - return vector3; - } - set - { - this.M21 = value.X; - this.M22 = value.Y; - this.M23 = value.Z; - } - } - - /// - /// Gets or sets the down of the matrix; that is -M21, -M22, and -M23. - /// - public Vector3 Down - { - get - { - Vector3 vector3; - vector3.X = -this.M21; - vector3.Y = -this.M22; - vector3.Z = -this.M23; - return vector3; - } - set - { - this.M21 = -value.X; - this.M22 = -value.Y; - this.M23 = -value.Z; - } - } - - /// - /// Gets or sets the right of the matrix; that is M11, M12, and M13. - /// - public Vector3 Right - { - get - { - Vector3 vector3; - vector3.X = this.M11; - vector3.Y = this.M12; - vector3.Z = this.M13; - return vector3; - } - set - { - this.M11 = value.X; - this.M12 = value.Y; - this.M13 = value.Z; - } - } - - /// - /// Gets or sets the left of the matrix; that is -M11, -M12, and -M13. - /// - public Vector3 Left - { - get - { - Vector3 vector3; - vector3.X = -this.M11; - vector3.Y = -this.M12; - vector3.Z = -this.M13; - return vector3; - } - set - { - this.M11 = -value.X; - this.M12 = -value.Y; - this.M13 = -value.Z; - } - } - - /// - /// Gets or sets the forward of the matrix; that is -M31, -M32, and -M33. - /// - public Vector3 Forward - { - get - { - Vector3 vector3; - vector3.X = -this.M31; - vector3.Y = -this.M32; - vector3.Z = -this.M33; - return vector3; - } - set - { - this.M31 = -value.X; - this.M32 = -value.Y; - this.M33 = -value.Z; - } - } - - /// - /// Gets or sets the backward of the matrix; that is M31, M32, and M33. - /// - public Vector3 Backward - { - get - { - Vector3 vector3; - vector3.X = this.M31; - vector3.Y = this.M32; - vector3.Z = this.M33; - return vector3; - } - set - { - this.M31 = value.X; - this.M32 = value.Y; - this.M33 = value.Z; - } - } - - /// - /// Initializes a new instance of the struct. - /// - /// The value that will be assigned to all components. - public Matrix(float value) - { - M11 = M12 = M13 = M14 = - M21 = M22 = M23 = M24 = - M31 = M32 = M33 = M34 = - M41 = M42 = M43 = M44 = value; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The value to assign at row 1 column 1 of the matrix. - /// The value to assign at row 1 column 2 of the matrix. - /// The value to assign at row 1 column 3 of the matrix. - /// The value to assign at row 1 column 4 of the matrix. - /// The value to assign at row 2 column 1 of the matrix. - /// The value to assign at row 2 column 2 of the matrix. - /// The value to assign at row 2 column 3 of the matrix. - /// The value to assign at row 2 column 4 of the matrix. - /// The value to assign at row 3 column 1 of the matrix. - /// The value to assign at row 3 column 2 of the matrix. - /// The value to assign at row 3 column 3 of the matrix. - /// The value to assign at row 3 column 4 of the matrix. - /// The value to assign at row 4 column 1 of the matrix. - /// The value to assign at row 4 column 2 of the matrix. - /// The value to assign at row 4 column 3 of the matrix. - /// The value to assign at row 4 column 4 of the matrix. - public Matrix(float M11, float M12, float M13, float M14, - float M21, float M22, float M23, float M24, - float M31, float M32, float M33, float M34, - float M41, float M42, float M43, float M44) - { - this.M11 = M11; this.M12 = M12; this.M13 = M13; this.M14 = M14; - this.M21 = M21; this.M22 = M22; this.M23 = M23; this.M24 = M24; - this.M31 = M31; this.M32 = M32; this.M33 = M33; this.M34 = M34; - this.M41 = M41; this.M42 = M42; this.M43 = M43; this.M44 = M44; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The values to assign to the components of the matrix. This must be an array with sixteen elements. - /// Thrown when is null. - /// Thrown when contains more or less than sixteen elements. - public Matrix(float[] values) - { - if (values == null) - throw new ArgumentNullException("values"); - if (values.Length != 16) - throw new ArgumentOutOfRangeException("values", "There must be sixteen and only sixteen input values for Matrix."); - - M11 = values[0]; - M12 = values[1]; - M13 = values[2]; - M14 = values[3]; - - M21 = values[4]; - M22 = values[5]; - M23 = values[6]; - M24 = values[7]; - - M31 = values[8]; - M32 = values[9]; - M33 = values[10]; - M34 = values[11]; - - M41 = values[12]; - M42 = values[13]; - M43 = values[14]; - M44 = values[15]; - } - - /// - /// Gets or sets the first row in the matrix; that is M11, M12, M13, and M14. - /// - public Vector4 Row1 - { - get { return new Vector4(M11, M12, M13, M14); } - set { M11 = value.X; M12 = value.Y; M13 = value.Z; M14 = value.W; } - } - - /// - /// Gets or sets the second row in the matrix; that is M21, M22, M23, and M24. - /// - public Vector4 Row2 - { - get { return new Vector4(M21, M22, M23, M24); } - set { M21 = value.X; M22 = value.Y; M23 = value.Z; M24 = value.W; } - } - - /// - /// Gets or sets the third row in the matrix; that is M31, M32, M33, and M34. - /// - public Vector4 Row3 - { - get { return new Vector4(M31, M32, M33, M34); } - set { M31 = value.X; M32 = value.Y; M33 = value.Z; M34 = value.W; } - } - - /// - /// Gets or sets the fourth row in the matrix; that is M41, M42, M43, and M44. - /// - public Vector4 Row4 - { - get { return new Vector4(M41, M42, M43, M44); } - set { M41 = value.X; M42 = value.Y; M43 = value.Z; M44 = value.W; } - } - - /// - /// Gets or sets the first column in the matrix; that is M11, M21, M31, and M41. - /// - public Vector4 Column1 - { - get { return new Vector4(M11, M21, M31, M41); } - set { M11 = value.X; M21 = value.Y; M31 = value.Z; M41 = value.W; } - } - - /// - /// Gets or sets the second column in the matrix; that is M12, M22, M32, and M42. - /// - public Vector4 Column2 - { - get { return new Vector4(M12, M22, M32, M42); } - set { M12 = value.X; M22 = value.Y; M32 = value.Z; M42 = value.W; } - } - - /// - /// Gets or sets the third column in the matrix; that is M13, M23, M33, and M43. - /// - public Vector4 Column3 - { - get { return new Vector4(M13, M23, M33, M43); } - set { M13 = value.X; M23 = value.Y; M33 = value.Z; M43 = value.W; } - } - - /// - /// Gets or sets the fourth column in the matrix; that is M14, M24, M34, and M44. - /// - public Vector4 Column4 - { - get { return new Vector4(M14, M24, M34, M44); } - set { M14 = value.X; M24 = value.Y; M34 = value.Z; M44 = value.W; } - } - - /// - /// Gets or sets the translation of the matrix; that is M41, M42, and M43. - /// - public Vector3 TranslationVector - { - get { return new Vector3(M41, M42, M43); } - set { M41 = value.X; M42 = value.Y; M43 = value.Z; } - } - - /// - /// Gets or sets the scale of the matrix; that is M11, M22, and M33. - /// - public Vector3 ScaleVector - { - get { return new Vector3(M11, M22, M33); } - set { M11 = value.X; M22 = value.Y; M33 = value.Z; } - } - - /// - /// Gets a value indicating whether this instance is an identity matrix. - /// - /// - /// true if this instance is an identity matrix; otherwise, false. - /// - public bool IsIdentity - { - get { return this.Equals(Identity); } - } - - /// - /// Gets or sets the component at the specified index. - /// - /// The value of the matrix component, depending on the index. - /// The zero-based index of the component to access. - /// The value of the component at the specified index. - /// Thrown when the is out of the range [0, 15]. - public float this[int index] - { - get - { - switch (index) - { - case 0: return M11; - case 1: return M12; - case 2: return M13; - case 3: return M14; - case 4: return M21; - case 5: return M22; - case 6: return M23; - case 7: return M24; - case 8: return M31; - case 9: return M32; - case 10: return M33; - case 11: return M34; - case 12: return M41; - case 13: return M42; - case 14: return M43; - case 15: return M44; - } - - throw new ArgumentOutOfRangeException("index", "Indices for Matrix run from 0 to 15, inclusive."); - } - - set - { - switch (index) - { - case 0: M11 = value; break; - case 1: M12 = value; break; - case 2: M13 = value; break; - case 3: M14 = value; break; - case 4: M21 = value; break; - case 5: M22 = value; break; - case 6: M23 = value; break; - case 7: M24 = value; break; - case 8: M31 = value; break; - case 9: M32 = value; break; - case 10: M33 = value; break; - case 11: M34 = value; break; - case 12: M41 = value; break; - case 13: M42 = value; break; - case 14: M43 = value; break; - case 15: M44 = value; break; - default: throw new ArgumentOutOfRangeException("index", "Indices for Matrix run from 0 to 15, inclusive."); - } - } - } - - /// - /// Gets or sets the component at the specified index. - /// - /// The value of the matrix component, depending on the index. - /// The row of the matrix to access. - /// The column of the matrix to access. - /// The value of the component at the specified index. - /// Thrown when the or is out of the range [0, 3]. - public float this[int row, int column] - { - get - { - if (row < 0 || row > 3) - throw new ArgumentOutOfRangeException("row", "Rows and columns for matrices run from 0 to 3, inclusive."); - if (column < 0 || column > 3) - throw new ArgumentOutOfRangeException("column", "Rows and columns for matrices run from 0 to 3, inclusive."); - - return this[(row * 4) + column]; - } - - set - { - if (row < 0 || row > 3) - throw new ArgumentOutOfRangeException("row", "Rows and columns for matrices run from 0 to 3, inclusive."); - if (column < 0 || column > 3) - throw new ArgumentOutOfRangeException("column", "Rows and columns for matrices run from 0 to 3, inclusive."); - - this[(row * 4) + column] = value; - } - } - - /// - /// Calculates the determinant of the matrix. - /// - /// The determinant of the matrix. - public float Determinant() - { - float temp1 = (M33 * M44) - (M34 * M43); - float temp2 = (M32 * M44) - (M34 * M42); - float temp3 = (M32 * M43) - (M33 * M42); - float temp4 = (M31 * M44) - (M34 * M41); - float temp5 = (M31 * M43) - (M33 * M41); - float temp6 = (M31 * M42) - (M32 * M41); - - return ((((M11 * (((M22 * temp1) - (M23 * temp2)) + (M24 * temp3))) - (M12 * (((M21 * temp1) - - (M23 * temp4)) + (M24 * temp5)))) + (M13 * (((M21 * temp2) - (M22 * temp4)) + (M24 * temp6)))) - - (M14 * (((M21 * temp3) - (M22 * temp5)) + (M23 * temp6)))); - } - - /// - /// Inverts the matrix. - /// - public void Invert() - { - Invert(ref this, out this); - } - - /// - /// Transposes the matrix. - /// - public void Transpose() - { - Transpose(ref this, out this); - } - - /// - /// Orthogonalizes the specified matrix. - /// - /// - /// Orthogonalization is the process of making all rows orthogonal to each other. This - /// means that any given row in the matrix will be orthogonal to any other given row in the - /// matrix. - /// Because this method uses the modified Gram-Schmidt process, the resulting matrix - /// tends to be numerically unstable. The numeric stability decreases according to the rows - /// so that the first row is the most stable and the last row is the least stable. - /// This operation is performed on the rows of the matrix rather than the columns. - /// If you wish for this operation to be performed on the columns, first transpose the - /// input and than transpose the output. - /// - public void Orthogonalize() - { - Orthogonalize(ref this, out this); - } - - /// - /// Orthonormalizes the specified matrix. - /// - /// - /// Orthonormalization is the process of making all rows and columns orthogonal to each - /// other and making all rows and columns of unit length. This means that any given row will - /// be orthogonal to any other given row and any given column will be orthogonal to any other - /// given column. Any given row will not be orthogonal to any given column. Every row and every - /// column will be of unit length. - /// Because this method uses the modified Gram-Schmidt process, the resulting matrix - /// tends to be numerically unstable. The numeric stability decreases according to the rows - /// so that the first row is the most stable and the last row is the least stable. - /// This operation is performed on the rows of the matrix rather than the columns. - /// If you wish for this operation to be performed on the columns, first transpose the - /// input and than transpose the output. - /// - public void Orthonormalize() - { - Orthonormalize(ref this, out this); - } - - /// - /// Decomposes a matrix into an orthonormalized matrix Q and a right triangular matrix R. - /// - /// When the method completes, contains the orthonormalized matrix of the decomposition. - /// When the method completes, contains the right triangular matrix of the decomposition. - public void DecomposeQR(out Matrix Q, out Matrix R) - { - Matrix temp = this; - temp.Transpose(); - Orthonormalize(ref temp, out Q); - Q.Transpose(); - - R = new Matrix(); - R.M11 = Vector4.Dot(Q.Column1, Column1); - R.M12 = Vector4.Dot(Q.Column1, Column2); - R.M13 = Vector4.Dot(Q.Column1, Column3); - R.M14 = Vector4.Dot(Q.Column1, Column4); - - R.M22 = Vector4.Dot(Q.Column2, Column2); - R.M23 = Vector4.Dot(Q.Column2, Column3); - R.M24 = Vector4.Dot(Q.Column2, Column4); - - R.M33 = Vector4.Dot(Q.Column3, Column3); - R.M34 = Vector4.Dot(Q.Column3, Column4); - - R.M44 = Vector4.Dot(Q.Column4, Column4); - } - - /// - /// Decomposes a matrix into a lower triangular matrix L and an orthonormalized matrix Q. - /// - /// When the method completes, contains the lower triangular matrix of the decomposition. - /// When the method completes, contains the orthonormalized matrix of the decomposition. - public void DecomposeLQ(out Matrix L, out Matrix Q) - { - Orthonormalize(ref this, out Q); - - L = new Matrix(); - L.M11 = Vector4.Dot(Q.Row1, Row1); - - L.M21 = Vector4.Dot(Q.Row1, Row2); - L.M22 = Vector4.Dot(Q.Row2, Row2); - - L.M31 = Vector4.Dot(Q.Row1, Row3); - L.M32 = Vector4.Dot(Q.Row2, Row3); - L.M33 = Vector4.Dot(Q.Row3, Row3); - - L.M41 = Vector4.Dot(Q.Row1, Row4); - L.M42 = Vector4.Dot(Q.Row2, Row4); - L.M43 = Vector4.Dot(Q.Row3, Row4); - L.M44 = Vector4.Dot(Q.Row4, Row4); - } - - /// - /// Decomposes a matrix into a scale, rotation, and translation. - /// - /// When the method completes, contains the scaling component of the decomposed matrix. - /// When the method completes, contains the rotation component of the decomposed matrix. - /// When the method completes, contains the translation component of the decomposed matrix. - /// - /// This method is designed to decompose an SRT transformation matrix only. - /// - public bool Decompose(out Vector3 scale, out Quaternion rotation, out Vector3 translation) - { - //Source: Unknown - //References: http://www.gamedev.net/community/forums/topic.asp?topic_id=441695 - - //Get the translation. - translation.X = this.M41; - translation.Y = this.M42; - translation.Z = this.M43; - - //Scaling is the length of the rows. - scale.X = (float)Math.Sqrt((M11 * M11) + (M12 * M12) + (M13 * M13)); - scale.Y = (float)Math.Sqrt((M21 * M21) + (M22 * M22) + (M23 * M23)); - scale.Z = (float)Math.Sqrt((M31 * M31) + (M32 * M32) + (M33 * M33)); - - //If any of the scaling factors are zero, than the rotation matrix can not exist. - if (MathUtil.IsZero(scale.X) || - MathUtil.IsZero(scale.Y) || - MathUtil.IsZero(scale.Z)) - { - rotation = Quaternion.Identity; - return false; - } - - //The rotation is the left over matrix after dividing out the scaling. - Matrix rotationmatrix = new Matrix(); - rotationmatrix.M11 = M11 / scale.X; - rotationmatrix.M12 = M12 / scale.X; - rotationmatrix.M13 = M13 / scale.X; - - rotationmatrix.M21 = M21 / scale.Y; - rotationmatrix.M22 = M22 / scale.Y; - rotationmatrix.M23 = M23 / scale.Y; - - rotationmatrix.M31 = M31 / scale.Z; - rotationmatrix.M32 = M32 / scale.Z; - rotationmatrix.M33 = M33 / scale.Z; - - rotationmatrix.M44 = 1f; - - Quaternion.RotationMatrix(ref rotationmatrix, out rotation); - return true; - } - - /// - /// Decomposes a uniform scale matrix into a scale, rotation, and translation. - /// A uniform scale matrix has the same scale in every axis. - /// - /// When the method completes, contains the scaling component of the decomposed matrix. - /// When the method completes, contains the rotation component of the decomposed matrix. - /// When the method completes, contains the translation component of the decomposed matrix. - /// - /// This method is designed to decompose only an SRT transformation matrix that has the same scale in every axis. - /// - public bool DecomposeUniformScale(out float scale, out Quaternion rotation, out Vector3 translation) - { - //Get the translation. - translation.X = this.M41; - translation.Y = this.M42; - translation.Z = this.M43; - - //Scaling is the length of the rows. ( just take one row since this is a uniform matrix) - scale = (float)Math.Sqrt((M11 * M11) + (M12 * M12) + (M13 * M13)); - var inv_scale = 1f / scale; - - //If any of the scaling factors are zero, then the rotation matrix can not exist. - if (Math.Abs(scale) < MathUtil.ZeroTolerance) - { - rotation = Quaternion.Identity; - return false; - } - - //The rotation is the left over matrix after dividing out the scaling. - Matrix rotationmatrix = new Matrix(); - rotationmatrix.M11 = M11 * inv_scale; - rotationmatrix.M12 = M12 * inv_scale; - rotationmatrix.M13 = M13 * inv_scale; - - rotationmatrix.M21 = M21 * inv_scale; - rotationmatrix.M22 = M22 * inv_scale; - rotationmatrix.M23 = M23 * inv_scale; - - rotationmatrix.M31 = M31 * inv_scale; - rotationmatrix.M32 = M32 * inv_scale; - rotationmatrix.M33 = M33 * inv_scale; - - rotationmatrix.M44 = 1f; - - Quaternion.RotationMatrix(ref rotationmatrix, out rotation); - return true; - } - - /// - /// Exchanges two rows in the matrix. - /// - /// The first row to exchange. This is an index of the row starting at zero. - /// The second row to exchange. This is an index of the row starting at zero. - public void ExchangeRows(int firstRow, int secondRow) - { - if (firstRow < 0) - throw new ArgumentOutOfRangeException("firstRow", "The parameter firstRow must be greater than or equal to zero."); - if (firstRow > 3) - throw new ArgumentOutOfRangeException("firstRow", "The parameter firstRow must be less than or equal to three."); - if (secondRow < 0) - throw new ArgumentOutOfRangeException("secondRow", "The parameter secondRow must be greater than or equal to zero."); - if (secondRow > 3) - throw new ArgumentOutOfRangeException("secondRow", "The parameter secondRow must be less than or equal to three."); - - if (firstRow == secondRow) - return; - - float temp0 = this[secondRow, 0]; - float temp1 = this[secondRow, 1]; - float temp2 = this[secondRow, 2]; - float temp3 = this[secondRow, 3]; - - this[secondRow, 0] = this[firstRow, 0]; - this[secondRow, 1] = this[firstRow, 1]; - this[secondRow, 2] = this[firstRow, 2]; - this[secondRow, 3] = this[firstRow, 3]; - - this[firstRow, 0] = temp0; - this[firstRow, 1] = temp1; - this[firstRow, 2] = temp2; - this[firstRow, 3] = temp3; - } - - /// - /// Exchanges two columns in the matrix. - /// - /// The first column to exchange. This is an index of the column starting at zero. - /// The second column to exchange. This is an index of the column starting at zero. - public void ExchangeColumns(int firstColumn, int secondColumn) - { - if (firstColumn < 0) - throw new ArgumentOutOfRangeException("firstColumn", "The parameter firstColumn must be greater than or equal to zero."); - if (firstColumn > 3) - throw new ArgumentOutOfRangeException("firstColumn", "The parameter firstColumn must be less than or equal to three."); - if (secondColumn < 0) - throw new ArgumentOutOfRangeException("secondColumn", "The parameter secondColumn must be greater than or equal to zero."); - if (secondColumn > 3) - throw new ArgumentOutOfRangeException("secondColumn", "The parameter secondColumn must be less than or equal to three."); - - if (firstColumn == secondColumn) - return; - - float temp0 = this[0, secondColumn]; - float temp1 = this[1, secondColumn]; - float temp2 = this[2, secondColumn]; - float temp3 = this[3, secondColumn]; - - this[0, secondColumn] = this[0, firstColumn]; - this[1, secondColumn] = this[1, firstColumn]; - this[2, secondColumn] = this[2, firstColumn]; - this[3, secondColumn] = this[3, firstColumn]; - - this[0, firstColumn] = temp0; - this[1, firstColumn] = temp1; - this[2, firstColumn] = temp2; - this[3, firstColumn] = temp3; - } - - /// - /// Creates an array containing the elements of the matrix. - /// - /// A sixteen-element array containing the components of the matrix. - public float[] ToArray() - { - return new[] { M11, M12, M13, M14, M21, M22, M23, M24, M31, M32, M33, M34, M41, M42, M43, M44 }; - } - - /// - /// Determines the sum of two matrices. - /// - /// The first matrix to add. - /// The second matrix to add. - /// When the method completes, contains the sum of the two matrices. - public static void Add(ref Matrix left, ref Matrix right, out Matrix result) - { - result.M11 = left.M11 + right.M11; - result.M12 = left.M12 + right.M12; - result.M13 = left.M13 + right.M13; - result.M14 = left.M14 + right.M14; - result.M21 = left.M21 + right.M21; - result.M22 = left.M22 + right.M22; - result.M23 = left.M23 + right.M23; - result.M24 = left.M24 + right.M24; - result.M31 = left.M31 + right.M31; - result.M32 = left.M32 + right.M32; - result.M33 = left.M33 + right.M33; - result.M34 = left.M34 + right.M34; - result.M41 = left.M41 + right.M41; - result.M42 = left.M42 + right.M42; - result.M43 = left.M43 + right.M43; - result.M44 = left.M44 + right.M44; - } - - /// - /// Determines the sum of two matrices. - /// - /// The first matrix to add. - /// The second matrix to add. - /// The sum of the two matrices. - public static Matrix Add(Matrix left, Matrix right) - { - Matrix result; - Add(ref left, ref right, out result); - return result; - } - - /// - /// Determines the difference between two matrices. - /// - /// The first matrix to subtract. - /// The second matrix to subtract. - /// When the method completes, contains the difference between the two matrices. - public static void Subtract(ref Matrix left, ref Matrix right, out Matrix result) - { - result.M11 = left.M11 - right.M11; - result.M12 = left.M12 - right.M12; - result.M13 = left.M13 - right.M13; - result.M14 = left.M14 - right.M14; - result.M21 = left.M21 - right.M21; - result.M22 = left.M22 - right.M22; - result.M23 = left.M23 - right.M23; - result.M24 = left.M24 - right.M24; - result.M31 = left.M31 - right.M31; - result.M32 = left.M32 - right.M32; - result.M33 = left.M33 - right.M33; - result.M34 = left.M34 - right.M34; - result.M41 = left.M41 - right.M41; - result.M42 = left.M42 - right.M42; - result.M43 = left.M43 - right.M43; - result.M44 = left.M44 - right.M44; - } - - /// - /// Determines the difference between two matrices. - /// - /// The first matrix to subtract. - /// The second matrix to subtract. - /// The difference between the two matrices. - public static Matrix Subtract(Matrix left, Matrix right) - { - Matrix result; - Subtract(ref left, ref right, out result); - return result; - } - - /// - /// Scales a matrix by the given value. - /// - /// The matrix to scale. - /// The amount by which to scale. - /// When the method completes, contains the scaled matrix. - public static void Multiply(ref Matrix left, float right, out Matrix result) - { - result.M11 = left.M11 * right; - result.M12 = left.M12 * right; - result.M13 = left.M13 * right; - result.M14 = left.M14 * right; - result.M21 = left.M21 * right; - result.M22 = left.M22 * right; - result.M23 = left.M23 * right; - result.M24 = left.M24 * right; - result.M31 = left.M31 * right; - result.M32 = left.M32 * right; - result.M33 = left.M33 * right; - result.M34 = left.M34 * right; - result.M41 = left.M41 * right; - result.M42 = left.M42 * right; - result.M43 = left.M43 * right; - result.M44 = left.M44 * right; - } - - /// - /// Scales a matrix by the given value. - /// - /// The matrix to scale. - /// The amount by which to scale. - /// The scaled matrix. - public static Matrix Multiply(Matrix left, float right) - { - Matrix result; - Multiply(ref left, right, out result); - return result; - } - - /// - /// Determines the product of two matrices. - /// - /// The first matrix to multiply. - /// The second matrix to multiply. - /// The product of the two matrices. - public static void Multiply(ref Matrix left, ref Matrix right, out Matrix result) - { - Matrix temp = new Matrix(); - temp.M11 = (left.M11 * right.M11) + (left.M12 * right.M21) + (left.M13 * right.M31) + (left.M14 * right.M41); - temp.M12 = (left.M11 * right.M12) + (left.M12 * right.M22) + (left.M13 * right.M32) + (left.M14 * right.M42); - temp.M13 = (left.M11 * right.M13) + (left.M12 * right.M23) + (left.M13 * right.M33) + (left.M14 * right.M43); - temp.M14 = (left.M11 * right.M14) + (left.M12 * right.M24) + (left.M13 * right.M34) + (left.M14 * right.M44); - temp.M21 = (left.M21 * right.M11) + (left.M22 * right.M21) + (left.M23 * right.M31) + (left.M24 * right.M41); - temp.M22 = (left.M21 * right.M12) + (left.M22 * right.M22) + (left.M23 * right.M32) + (left.M24 * right.M42); - temp.M23 = (left.M21 * right.M13) + (left.M22 * right.M23) + (left.M23 * right.M33) + (left.M24 * right.M43); - temp.M24 = (left.M21 * right.M14) + (left.M22 * right.M24) + (left.M23 * right.M34) + (left.M24 * right.M44); - temp.M31 = (left.M31 * right.M11) + (left.M32 * right.M21) + (left.M33 * right.M31) + (left.M34 * right.M41); - temp.M32 = (left.M31 * right.M12) + (left.M32 * right.M22) + (left.M33 * right.M32) + (left.M34 * right.M42); - temp.M33 = (left.M31 * right.M13) + (left.M32 * right.M23) + (left.M33 * right.M33) + (left.M34 * right.M43); - temp.M34 = (left.M31 * right.M14) + (left.M32 * right.M24) + (left.M33 * right.M34) + (left.M34 * right.M44); - temp.M41 = (left.M41 * right.M11) + (left.M42 * right.M21) + (left.M43 * right.M31) + (left.M44 * right.M41); - temp.M42 = (left.M41 * right.M12) + (left.M42 * right.M22) + (left.M43 * right.M32) + (left.M44 * right.M42); - temp.M43 = (left.M41 * right.M13) + (left.M42 * right.M23) + (left.M43 * right.M33) + (left.M44 * right.M43); - temp.M44 = (left.M41 * right.M14) + (left.M42 * right.M24) + (left.M43 * right.M34) + (left.M44 * right.M44); - result = temp; - } - - /// - /// Determines the product of two matrices. - /// - /// The first matrix to multiply. - /// The second matrix to multiply. - /// The product of the two matrices. - public static Matrix Multiply(Matrix left, Matrix right) - { - Matrix result; - Multiply(ref left, ref right, out result); - return result; - } - - /// - /// Scales a matrix by the given value. - /// - /// The matrix to scale. - /// The amount by which to scale. - /// When the method completes, contains the scaled matrix. - public static void Divide(ref Matrix left, float right, out Matrix result) - { - float inv = 1.0f / right; - - result.M11 = left.M11 * inv; - result.M12 = left.M12 * inv; - result.M13 = left.M13 * inv; - result.M14 = left.M14 * inv; - result.M21 = left.M21 * inv; - result.M22 = left.M22 * inv; - result.M23 = left.M23 * inv; - result.M24 = left.M24 * inv; - result.M31 = left.M31 * inv; - result.M32 = left.M32 * inv; - result.M33 = left.M33 * inv; - result.M34 = left.M34 * inv; - result.M41 = left.M41 * inv; - result.M42 = left.M42 * inv; - result.M43 = left.M43 * inv; - result.M44 = left.M44 * inv; - } - - /// - /// Scales a matrix by the given value. - /// - /// The matrix to scale. - /// The amount by which to scale. - /// The scaled matrix. - public static Matrix Divide(Matrix left, float right) - { - Matrix result; - Divide(ref left, right, out result); - return result; - } - - /// - /// Determines the quotient of two matrices. - /// - /// The first matrix to divide. - /// The second matrix to divide. - /// When the method completes, contains the quotient of the two matrices. - public static void Divide(ref Matrix left, ref Matrix right, out Matrix result) - { - result.M11 = left.M11 / right.M11; - result.M12 = left.M12 / right.M12; - result.M13 = left.M13 / right.M13; - result.M14 = left.M14 / right.M14; - result.M21 = left.M21 / right.M21; - result.M22 = left.M22 / right.M22; - result.M23 = left.M23 / right.M23; - result.M24 = left.M24 / right.M24; - result.M31 = left.M31 / right.M31; - result.M32 = left.M32 / right.M32; - result.M33 = left.M33 / right.M33; - result.M34 = left.M34 / right.M34; - result.M41 = left.M41 / right.M41; - result.M42 = left.M42 / right.M42; - result.M43 = left.M43 / right.M43; - result.M44 = left.M44 / right.M44; - } - - /// - /// Determines the quotient of two matrices. - /// - /// The first matrix to divide. - /// The second matrix to divide. - /// The quotient of the two matrices. - public static Matrix Divide(Matrix left, Matrix right) - { - Matrix result; - Divide(ref left, ref right, out result); - return result; - } - - /// - /// Performs the exponential operation on a matrix. - /// - /// The matrix to perform the operation on. - /// The exponent to raise the matrix to. - /// When the method completes, contains the exponential matrix. - /// Thrown when the is negative. - public static void Exponent(ref Matrix value, int exponent, out Matrix result) - { - //Source: http://rosettacode.org - //Reference: http://rosettacode.org/wiki/Matrix-exponentiation_operator - - if (exponent < 0) - throw new ArgumentOutOfRangeException("exponent", "The exponent can not be negative."); - - if (exponent == 0) - { - result = Matrix.Identity; - return; - } - - if (exponent == 1) - { - result = value; - return; - } - - Matrix identity = Matrix.Identity; - Matrix temp = value; - - while (true) - { - if ((exponent & 1) != 0) - identity = identity * temp; - - exponent /= 2; - - if (exponent > 0) - temp *= temp; - else - break; - } - - result = identity; - } - - /// - /// Performs the exponential operation on a matrix. - /// - /// The matrix to perform the operation on. - /// The exponent to raise the matrix to. - /// The exponential matrix. - /// Thrown when the is negative. - public static Matrix Exponent(Matrix value, int exponent) - { - Matrix result; - Exponent(ref value, exponent, out result); - return result; - } - - /// - /// Negates a matrix. - /// - /// The matrix to be negated. - /// When the method completes, contains the negated matrix. - public static void Negate(ref Matrix value, out Matrix result) - { - result.M11 = -value.M11; - result.M12 = -value.M12; - result.M13 = -value.M13; - result.M14 = -value.M14; - result.M21 = -value.M21; - result.M22 = -value.M22; - result.M23 = -value.M23; - result.M24 = -value.M24; - result.M31 = -value.M31; - result.M32 = -value.M32; - result.M33 = -value.M33; - result.M34 = -value.M34; - result.M41 = -value.M41; - result.M42 = -value.M42; - result.M43 = -value.M43; - result.M44 = -value.M44; - } - - /// - /// Negates a matrix. - /// - /// The matrix to be negated. - /// The negated matrix. - public static Matrix Negate(Matrix value) - { - Matrix result; - Negate(ref value, out result); - return result; - } - - /// - /// Performs a linear interpolation between two matrices. - /// - /// Start matrix. - /// End matrix. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the linear interpolation of the two matrices. - /// - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static void Lerp(ref Matrix start, ref Matrix end, float amount, out Matrix result) - { - result.M11 = MathUtil.Lerp(start.M11, end.M11, amount); - result.M12 = MathUtil.Lerp(start.M12, end.M12, amount); - result.M13 = MathUtil.Lerp(start.M13, end.M13, amount); - result.M14 = MathUtil.Lerp(start.M14, end.M14, amount); - result.M21 = MathUtil.Lerp(start.M21, end.M21, amount); - result.M22 = MathUtil.Lerp(start.M22, end.M22, amount); - result.M23 = MathUtil.Lerp(start.M23, end.M23, amount); - result.M24 = MathUtil.Lerp(start.M24, end.M24, amount); - result.M31 = MathUtil.Lerp(start.M31, end.M31, amount); - result.M32 = MathUtil.Lerp(start.M32, end.M32, amount); - result.M33 = MathUtil.Lerp(start.M33, end.M33, amount); - result.M34 = MathUtil.Lerp(start.M34, end.M34, amount); - result.M41 = MathUtil.Lerp(start.M41, end.M41, amount); - result.M42 = MathUtil.Lerp(start.M42, end.M42, amount); - result.M43 = MathUtil.Lerp(start.M43, end.M43, amount); - result.M44 = MathUtil.Lerp(start.M44, end.M44, amount); - } - - /// - /// Performs a linear interpolation between two matrices. - /// - /// Start matrix. - /// End matrix. - /// Value between 0 and 1 indicating the weight of . - /// The linear interpolation of the two matrices. - /// - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static Matrix Lerp(Matrix start, Matrix end, float amount) - { - Matrix result; - Lerp(ref start, ref end, amount, out result); - return result; - } - - /// - /// Performs a cubic interpolation between two matrices. - /// - /// Start matrix. - /// End matrix. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the cubic interpolation of the two matrices. - public static void SmoothStep(ref Matrix start, ref Matrix end, float amount, out Matrix result) - { - amount = MathUtil.SmoothStep(amount); - Lerp(ref start, ref end, amount, out result); - } - - /// - /// Performs a cubic interpolation between two matrices. - /// - /// Start matrix. - /// End matrix. - /// Value between 0 and 1 indicating the weight of . - /// The cubic interpolation of the two matrices. - public static Matrix SmoothStep(Matrix start, Matrix end, float amount) - { - Matrix result; - SmoothStep(ref start, ref end, amount, out result); - return result; - } - - /// - /// Calculates the transpose of the specified matrix. - /// - /// The matrix whose transpose is to be calculated. - /// When the method completes, contains the transpose of the specified matrix. - public static void Transpose(ref Matrix value, out Matrix result) - { - Matrix temp = new Matrix(); - temp.M11 = value.M11; - temp.M12 = value.M21; - temp.M13 = value.M31; - temp.M14 = value.M41; - temp.M21 = value.M12; - temp.M22 = value.M22; - temp.M23 = value.M32; - temp.M24 = value.M42; - temp.M31 = value.M13; - temp.M32 = value.M23; - temp.M33 = value.M33; - temp.M34 = value.M43; - temp.M41 = value.M14; - temp.M42 = value.M24; - temp.M43 = value.M34; - temp.M44 = value.M44; - - result = temp; - } - - /// - /// Calculates the transpose of the specified matrix. - /// - /// The matrix whose transpose is to be calculated. - /// When the method completes, contains the transpose of the specified matrix. - public static void TransposeByRef(ref Matrix value, ref Matrix result) - { - result.M11 = value.M11; - result.M12 = value.M21; - result.M13 = value.M31; - result.M14 = value.M41; - result.M21 = value.M12; - result.M22 = value.M22; - result.M23 = value.M32; - result.M24 = value.M42; - result.M31 = value.M13; - result.M32 = value.M23; - result.M33 = value.M33; - result.M34 = value.M43; - result.M41 = value.M14; - result.M42 = value.M24; - result.M43 = value.M34; - result.M44 = value.M44; - } - - /// - /// Calculates the transpose of the specified matrix. - /// - /// The matrix whose transpose is to be calculated. - /// The transpose of the specified matrix. - public static Matrix Transpose(Matrix value) - { - Matrix result; - Transpose(ref value, out result); - return result; - } - - /// - /// Calculates the inverse of the specified matrix. - /// - /// The matrix whose inverse is to be calculated. - /// When the method completes, contains the inverse of the specified matrix. - public static void Invert(ref Matrix value, out Matrix result) - { - float b0 = (value.M31 * value.M42) - (value.M32 * value.M41); - float b1 = (value.M31 * value.M43) - (value.M33 * value.M41); - float b2 = (value.M34 * value.M41) - (value.M31 * value.M44); - float b3 = (value.M32 * value.M43) - (value.M33 * value.M42); - float b4 = (value.M34 * value.M42) - (value.M32 * value.M44); - float b5 = (value.M33 * value.M44) - (value.M34 * value.M43); - - float d11 = value.M22 * b5 + value.M23 * b4 + value.M24 * b3; - float d12 = value.M21 * b5 + value.M23 * b2 + value.M24 * b1; - float d13 = value.M21 * -b4 + value.M22 * b2 + value.M24 * b0; - float d14 = value.M21 * b3 + value.M22 * -b1 + value.M23 * b0; - - float det = value.M11 * d11 - value.M12 * d12 + value.M13 * d13 - value.M14 * d14; - if (Math.Abs(det) == 0.0f) - { - result = Matrix.Zero; - return; - } - - det = 1f / det; - - float a0 = (value.M11 * value.M22) - (value.M12 * value.M21); - float a1 = (value.M11 * value.M23) - (value.M13 * value.M21); - float a2 = (value.M14 * value.M21) - (value.M11 * value.M24); - float a3 = (value.M12 * value.M23) - (value.M13 * value.M22); - float a4 = (value.M14 * value.M22) - (value.M12 * value.M24); - float a5 = (value.M13 * value.M24) - (value.M14 * value.M23); - - float d21 = value.M12 * b5 + value.M13 * b4 + value.M14 * b3; - float d22 = value.M11 * b5 + value.M13 * b2 + value.M14 * b1; - float d23 = value.M11 * -b4 + value.M12 * b2 + value.M14 * b0; - float d24 = value.M11 * b3 + value.M12 * -b1 + value.M13 * b0; - - float d31 = value.M42 * a5 + value.M43 * a4 + value.M44 * a3; - float d32 = value.M41 * a5 + value.M43 * a2 + value.M44 * a1; - float d33 = value.M41 * -a4 + value.M42 * a2 + value.M44 * a0; - float d34 = value.M41 * a3 + value.M42 * -a1 + value.M43 * a0; - - float d41 = value.M32 * a5 + value.M33 * a4 + value.M34 * a3; - float d42 = value.M31 * a5 + value.M33 * a2 + value.M34 * a1; - float d43 = value.M31 * -a4 + value.M32 * a2 + value.M34 * a0; - float d44 = value.M31 * a3 + value.M32 * -a1 + value.M33 * a0; - - result.M11 = +d11 * det; result.M12 = -d21 * det; result.M13 = +d31 * det; result.M14 = -d41 * det; - result.M21 = -d12 * det; result.M22 = +d22 * det; result.M23 = -d32 * det; result.M24 = +d42 * det; - result.M31 = +d13 * det; result.M32 = -d23 * det; result.M33 = +d33 * det; result.M34 = -d43 * det; - result.M41 = -d14 * det; result.M42 = +d24 * det; result.M43 = -d34 * det; result.M44 = +d44 * det; - } - - /// - /// Calculates the inverse of the specified matrix. - /// - /// The matrix whose inverse is to be calculated. - /// The inverse of the specified matrix. - public static Matrix Invert(Matrix value) - { - value.Invert(); - return value; - } - - /// - /// Orthogonalizes the specified matrix. - /// - /// The matrix to orthogonalize. - /// When the method completes, contains the orthogonalized matrix. - /// - /// Orthogonalization is the process of making all rows orthogonal to each other. This - /// means that any given row in the matrix will be orthogonal to any other given row in the - /// matrix. - /// Because this method uses the modified Gram-Schmidt process, the resulting matrix - /// tends to be numerically unstable. The numeric stability decreases according to the rows - /// so that the first row is the most stable and the last row is the least stable. - /// This operation is performed on the rows of the matrix rather than the columns. - /// If you wish for this operation to be performed on the columns, first transpose the - /// input and than transpose the output. - /// - public static void Orthogonalize(ref Matrix value, out Matrix result) - { - //Uses the modified Gram-Schmidt process. - //q1 = m1 - //q2 = m2 - ((q1 ⋅ m2) / (q1 ⋅ q1)) * q1 - //q3 = m3 - ((q1 ⋅ m3) / (q1 ⋅ q1)) * q1 - ((q2 ⋅ m3) / (q2 ⋅ q2)) * q2 - //q4 = m4 - ((q1 ⋅ m4) / (q1 ⋅ q1)) * q1 - ((q2 ⋅ m4) / (q2 ⋅ q2)) * q2 - ((q3 ⋅ m4) / (q3 ⋅ q3)) * q3 - - //By separating the above algorithm into multiple lines, we actually increase accuracy. - result = value; - - result.Row2 = result.Row2 - (Vector4.Dot(result.Row1, result.Row2) / Vector4.Dot(result.Row1, result.Row1)) * result.Row1; - - result.Row3 = result.Row3 - (Vector4.Dot(result.Row1, result.Row3) / Vector4.Dot(result.Row1, result.Row1)) * result.Row1; - result.Row3 = result.Row3 - (Vector4.Dot(result.Row2, result.Row3) / Vector4.Dot(result.Row2, result.Row2)) * result.Row2; - - result.Row4 = result.Row4 - (Vector4.Dot(result.Row1, result.Row4) / Vector4.Dot(result.Row1, result.Row1)) * result.Row1; - result.Row4 = result.Row4 - (Vector4.Dot(result.Row2, result.Row4) / Vector4.Dot(result.Row2, result.Row2)) * result.Row2; - result.Row4 = result.Row4 - (Vector4.Dot(result.Row3, result.Row4) / Vector4.Dot(result.Row3, result.Row3)) * result.Row3; - } - - /// - /// Orthogonalizes the specified matrix. - /// - /// The matrix to orthogonalize. - /// The orthogonalized matrix. - /// - /// Orthogonalization is the process of making all rows orthogonal to each other. This - /// means that any given row in the matrix will be orthogonal to any other given row in the - /// matrix. - /// Because this method uses the modified Gram-Schmidt process, the resulting matrix - /// tends to be numerically unstable. The numeric stability decreases according to the rows - /// so that the first row is the most stable and the last row is the least stable. - /// This operation is performed on the rows of the matrix rather than the columns. - /// If you wish for this operation to be performed on the columns, first transpose the - /// input and than transpose the output. - /// - public static Matrix Orthogonalize(Matrix value) - { - Matrix result; - Orthogonalize(ref value, out result); - return result; - } - - /// - /// Orthonormalizes the specified matrix. - /// - /// The matrix to orthonormalize. - /// When the method completes, contains the orthonormalized matrix. - /// - /// Orthonormalization is the process of making all rows and columns orthogonal to each - /// other and making all rows and columns of unit length. This means that any given row will - /// be orthogonal to any other given row and any given column will be orthogonal to any other - /// given column. Any given row will not be orthogonal to any given column. Every row and every - /// column will be of unit length. - /// Because this method uses the modified Gram-Schmidt process, the resulting matrix - /// tends to be numerically unstable. The numeric stability decreases according to the rows - /// so that the first row is the most stable and the last row is the least stable. - /// This operation is performed on the rows of the matrix rather than the columns. - /// If you wish for this operation to be performed on the columns, first transpose the - /// input and than transpose the output. - /// - public static void Orthonormalize(ref Matrix value, out Matrix result) - { - //Uses the modified Gram-Schmidt process. - //Because we are making unit vectors, we can optimize the math for orthonormalization - //and simplify the projection operation to remove the division. - //q1 = m1 / |m1| - //q2 = (m2 - (q1 ⋅ m2) * q1) / |m2 - (q1 ⋅ m2) * q1| - //q3 = (m3 - (q1 ⋅ m3) * q1 - (q2 ⋅ m3) * q2) / |m3 - (q1 ⋅ m3) * q1 - (q2 ⋅ m3) * q2| - //q4 = (m4 - (q1 ⋅ m4) * q1 - (q2 ⋅ m4) * q2 - (q3 ⋅ m4) * q3) / |m4 - (q1 ⋅ m4) * q1 - (q2 ⋅ m4) * q2 - (q3 ⋅ m4) * q3| - - //By separating the above algorithm into multiple lines, we actually increase accuracy. - result = value; - - result.Row1 = Vector4.Normalize(result.Row1); - - result.Row2 = result.Row2 - Vector4.Dot(result.Row1, result.Row2) * result.Row1; - result.Row2 = Vector4.Normalize(result.Row2); - - result.Row3 = result.Row3 - Vector4.Dot(result.Row1, result.Row3) * result.Row1; - result.Row3 = result.Row3 - Vector4.Dot(result.Row2, result.Row3) * result.Row2; - result.Row3 = Vector4.Normalize(result.Row3); - - result.Row4 = result.Row4 - Vector4.Dot(result.Row1, result.Row4) * result.Row1; - result.Row4 = result.Row4 - Vector4.Dot(result.Row2, result.Row4) * result.Row2; - result.Row4 = result.Row4 - Vector4.Dot(result.Row3, result.Row4) * result.Row3; - result.Row4 = Vector4.Normalize(result.Row4); - } - - /// - /// Orthonormalizes the specified matrix. - /// - /// The matrix to orthonormalize. - /// The orthonormalized matrix. - /// - /// Orthonormalization is the process of making all rows and columns orthogonal to each - /// other and making all rows and columns of unit length. This means that any given row will - /// be orthogonal to any other given row and any given column will be orthogonal to any other - /// given column. Any given row will not be orthogonal to any given column. Every row and every - /// column will be of unit length. - /// Because this method uses the modified Gram-Schmidt process, the resulting matrix - /// tends to be numerically unstable. The numeric stability decreases according to the rows - /// so that the first row is the most stable and the last row is the least stable. - /// This operation is performed on the rows of the matrix rather than the columns. - /// If you wish for this operation to be performed on the columns, first transpose the - /// input and than transpose the output. - /// - public static Matrix Orthonormalize(Matrix value) - { - Matrix result; - Orthonormalize(ref value, out result); - return result; - } - - /// - /// Brings the matrix into upper triangular form using elementary row operations. - /// - /// The matrix to put into upper triangular form. - /// When the method completes, contains the upper triangular matrix. - /// - /// If the matrix is not invertible (i.e. its determinant is zero) than the result of this - /// method may produce Single.Nan and Single.Inf values. When the matrix represents a system - /// of linear equations, than this often means that either no solution exists or an infinite - /// number of solutions exist. - /// - public static void UpperTriangularForm(ref Matrix value, out Matrix result) - { - //Adapted from the row echelon code. - result = value; - int lead = 0; - int rowcount = 4; - int columncount = 4; - - for (int r = 0; r < rowcount; ++r) - { - if (columncount <= lead) - return; - - int i = r; - - while (MathUtil.IsZero(result[i, lead])) - { - i++; - - if (i == rowcount) - { - i = r; - lead++; - - if (lead == columncount) - return; - } - } - - if (i != r) - { - result.ExchangeRows(i, r); - } - - float multiplier = 1f / result[r, lead]; - - for (; i < rowcount; ++i) - { - if (i != r) - { - result[i, 0] -= result[r, 0] * multiplier * result[i, lead]; - result[i, 1] -= result[r, 1] * multiplier * result[i, lead]; - result[i, 2] -= result[r, 2] * multiplier * result[i, lead]; - result[i, 3] -= result[r, 3] * multiplier * result[i, lead]; - } - } - - lead++; - } - } - - /// - /// Brings the matrix into upper triangular form using elementary row operations. - /// - /// The matrix to put into upper triangular form. - /// The upper triangular matrix. - /// - /// If the matrix is not invertible (i.e. its determinant is zero) than the result of this - /// method may produce Single.Nan and Single.Inf values. When the matrix represents a system - /// of linear equations, than this often means that either no solution exists or an infinite - /// number of solutions exist. - /// - public static Matrix UpperTriangularForm(Matrix value) - { - Matrix result; - UpperTriangularForm(ref value, out result); - return result; - } - - /// - /// Brings the matrix into lower triangular form using elementary row operations. - /// - /// The matrix to put into lower triangular form. - /// When the method completes, contains the lower triangular matrix. - /// - /// If the matrix is not invertible (i.e. its determinant is zero) than the result of this - /// method may produce Single.Nan and Single.Inf values. When the matrix represents a system - /// of linear equations, than this often means that either no solution exists or an infinite - /// number of solutions exist. - /// - public static void LowerTriangularForm(ref Matrix value, out Matrix result) - { - //Adapted from the row echelon code. - Matrix temp = value; - Matrix.Transpose(ref temp, out result); - - int lead = 0; - int rowcount = 4; - int columncount = 4; - - for (int r = 0; r < rowcount; ++r) - { - if (columncount <= lead) - return; - - int i = r; - - while (MathUtil.IsZero(result[i, lead])) - { - i++; - - if (i == rowcount) - { - i = r; - lead++; - - if (lead == columncount) - return; - } - } - - if (i != r) - { - result.ExchangeRows(i, r); - } - - float multiplier = 1f / result[r, lead]; - - for (; i < rowcount; ++i) - { - if (i != r) - { - result[i, 0] -= result[r, 0] * multiplier * result[i, lead]; - result[i, 1] -= result[r, 1] * multiplier * result[i, lead]; - result[i, 2] -= result[r, 2] * multiplier * result[i, lead]; - result[i, 3] -= result[r, 3] * multiplier * result[i, lead]; - } - } - - lead++; - } - - Matrix.Transpose(ref result, out result); - } - - /// - /// Brings the matrix into lower triangular form using elementary row operations. - /// - /// The matrix to put into lower triangular form. - /// The lower triangular matrix. - /// - /// If the matrix is not invertible (i.e. its determinant is zero) than the result of this - /// method may produce Single.Nan and Single.Inf values. When the matrix represents a system - /// of linear equations, than this often means that either no solution exists or an infinite - /// number of solutions exist. - /// - public static Matrix LowerTriangularForm(Matrix value) - { - Matrix result; - LowerTriangularForm(ref value, out result); - return result; - } - - /// - /// Brings the matrix into row echelon form using elementary row operations; - /// - /// The matrix to put into row echelon form. - /// When the method completes, contains the row echelon form of the matrix. - public static void RowEchelonForm(ref Matrix value, out Matrix result) - { - //Source: Wikipedia pseudo code - //Reference: http://en.wikipedia.org/wiki/Row_echelon_form#Pseudocode - - result = value; - int lead = 0; - int rowcount = 4; - int columncount = 4; - - for (int r = 0; r < rowcount; ++r) - { - if (columncount <= lead) - return; - - int i = r; - - while (MathUtil.IsZero(result[i, lead])) - { - i++; - - if (i == rowcount) - { - i = r; - lead++; - - if (lead == columncount) - return; - } - } - - if (i != r) - { - result.ExchangeRows(i, r); - } - - float multiplier = 1f / result[r, lead]; - result[r, 0] *= multiplier; - result[r, 1] *= multiplier; - result[r, 2] *= multiplier; - result[r, 3] *= multiplier; - - for (; i < rowcount; ++i) - { - if (i != r) - { - result[i, 0] -= result[r, 0] * result[i, lead]; - result[i, 1] -= result[r, 1] * result[i, lead]; - result[i, 2] -= result[r, 2] * result[i, lead]; - result[i, 3] -= result[r, 3] * result[i, lead]; - } - } - - lead++; - } - } - - /// - /// Brings the matrix into row echelon form using elementary row operations; - /// - /// The matrix to put into row echelon form. - /// When the method completes, contains the row echelon form of the matrix. - public static Matrix RowEchelonForm(Matrix value) - { - Matrix result; - RowEchelonForm(ref value, out result); - return result; - } - - /// - /// Brings the matrix into reduced row echelon form using elementary row operations. - /// - /// The matrix to put into reduced row echelon form. - /// The fifth column of the matrix. - /// When the method completes, contains the resultant matrix after the operation. - /// When the method completes, contains the resultant fifth column of the matrix. - /// - /// The fifth column is often called the augmented part of the matrix. This is because the fifth - /// column is really just an extension of the matrix so that there is a place to put all of the - /// non-zero components after the operation is complete. - /// Often times the resultant matrix will the identity matrix or a matrix similar to the identity - /// matrix. Sometimes, however, that is not possible and numbers other than zero and one may appear. - /// This method can be used to solve systems of linear equations. Upon completion of this method, - /// the will contain the solution for the system. It is up to the user - /// to analyze both the input and the result to determine if a solution really exists. - /// - public static void ReducedRowEchelonForm(ref Matrix value, ref Vector4 augment, out Matrix result, out Vector4 augmentResult) - { - //Source: http://rosettacode.org - //Reference: http://rosettacode.org/wiki/Reduced_row_echelon_form - - float[,] matrix = new float[4, 5]; - - matrix[0, 0] = value[0, 0]; - matrix[0, 1] = value[0, 1]; - matrix[0, 2] = value[0, 2]; - matrix[0, 3] = value[0, 3]; - matrix[0, 4] = augment[0]; - - matrix[1, 0] = value[1, 0]; - matrix[1, 1] = value[1, 1]; - matrix[1, 2] = value[1, 2]; - matrix[1, 3] = value[1, 3]; - matrix[1, 4] = augment[1]; - - matrix[2, 0] = value[2, 0]; - matrix[2, 1] = value[2, 1]; - matrix[2, 2] = value[2, 2]; - matrix[2, 3] = value[2, 3]; - matrix[2, 4] = augment[2]; - - matrix[3, 0] = value[3, 0]; - matrix[3, 1] = value[3, 1]; - matrix[3, 2] = value[3, 2]; - matrix[3, 3] = value[3, 3]; - matrix[3, 4] = augment[3]; - - int lead = 0; - int rowcount = 4; - int columncount = 5; - - for (int r = 0; r < rowcount; r++) - { - if (columncount <= lead) - break; - - int i = r; - - while (matrix[i, lead] == 0) - { - i++; - - if (i == rowcount) - { - i = r; - lead++; - - if (columncount == lead) - break; - } - } - - for (int j = 0; j < columncount; j++) - { - float temp = matrix[r, j]; - matrix[r, j] = matrix[i, j]; - matrix[i, j] = temp; - } - - float div = matrix[r, lead]; - - for (int j = 0; j < columncount; j++) - { - matrix[r, j] /= div; - } - - for (int j = 0; j < rowcount; j++) - { - if (j != r) - { - float sub = matrix[j, lead]; - for (int k = 0; k < columncount; k++) matrix[j, k] -= (sub * matrix[r, k]); - } - } - - lead++; - } - - result.M11 = matrix[0, 0]; - result.M12 = matrix[0, 1]; - result.M13 = matrix[0, 2]; - result.M14 = matrix[0, 3]; - - result.M21 = matrix[1, 0]; - result.M22 = matrix[1, 1]; - result.M23 = matrix[1, 2]; - result.M24 = matrix[1, 3]; - - result.M31 = matrix[2, 0]; - result.M32 = matrix[2, 1]; - result.M33 = matrix[2, 2]; - result.M34 = matrix[2, 3]; - - result.M41 = matrix[3, 0]; - result.M42 = matrix[3, 1]; - result.M43 = matrix[3, 2]; - result.M44 = matrix[3, 3]; - - augmentResult.X = matrix[0, 4]; - augmentResult.Y = matrix[1, 4]; - augmentResult.Z = matrix[2, 4]; - augmentResult.W = matrix[3, 4]; - } - - /// - /// Creates a left-handed spherical billboard that rotates around a specified object position. - /// - /// The position of the object around which the billboard will rotate. - /// The position of the camera. - /// The up vector of the camera. - /// The forward vector of the camera. - /// When the method completes, contains the created billboard matrix. - public static void BillboardLH(ref Vector3 objectPosition, ref Vector3 cameraPosition, ref Vector3 cameraUpVector, ref Vector3 cameraForwardVector, out Matrix result) - { - Vector3 crossed; - Vector3 final; - Vector3 difference = objectPosition - cameraPosition; - - float lengthSq = difference.LengthSquared(); - if (MathUtil.IsZero(lengthSq)) - difference = -cameraForwardVector; - else - difference *= (float)(1.0 / Math.Sqrt(lengthSq)); - - Vector3.Cross(ref cameraUpVector, ref difference, out crossed); - crossed.Normalize(); - Vector3.Cross(ref difference, ref crossed, out final); - - result.M11 = crossed.X; - result.M12 = crossed.Y; - result.M13 = crossed.Z; - result.M14 = 0.0f; - result.M21 = final.X; - result.M22 = final.Y; - result.M23 = final.Z; - result.M24 = 0.0f; - result.M31 = difference.X; - result.M32 = difference.Y; - result.M33 = difference.Z; - result.M34 = 0.0f; - result.M41 = objectPosition.X; - result.M42 = objectPosition.Y; - result.M43 = objectPosition.Z; - result.M44 = 1.0f; - } - - /// - /// Creates a left-handed spherical billboard that rotates around a specified object position. - /// - /// The position of the object around which the billboard will rotate. - /// The position of the camera. - /// The up vector of the camera. - /// The forward vector of the camera. - /// The created billboard matrix. - public static Matrix BillboardLH(Vector3 objectPosition, Vector3 cameraPosition, Vector3 cameraUpVector, Vector3 cameraForwardVector) - { - Matrix result; - BillboardLH(ref objectPosition, ref cameraPosition, ref cameraUpVector, ref cameraForwardVector, out result); - return result; - } - - /// - /// Creates a right-handed spherical billboard that rotates around a specified object position. - /// - /// The position of the object around which the billboard will rotate. - /// The position of the camera. - /// The up vector of the camera. - /// The forward vector of the camera. - /// When the method completes, contains the created billboard matrix. - public static void BillboardRH(ref Vector3 objectPosition, ref Vector3 cameraPosition, ref Vector3 cameraUpVector, ref Vector3 cameraForwardVector, out Matrix result) { - Vector3 crossed; - Vector3 final; - Vector3 difference = cameraPosition - objectPosition; - - float lengthSq = difference.LengthSquared(); - if (MathUtil.IsZero(lengthSq)) - difference = -cameraForwardVector; - else - difference *= (float)(1.0 / Math.Sqrt(lengthSq)); - - Vector3.Cross(ref cameraUpVector, ref difference, out crossed); - crossed.Normalize(); - Vector3.Cross(ref difference, ref crossed, out final); - - result.M11 = crossed.X; - result.M12 = crossed.Y; - result.M13 = crossed.Z; - result.M14 = 0.0f; - result.M21 = final.X; - result.M22 = final.Y; - result.M23 = final.Z; - result.M24 = 0.0f; - result.M31 = difference.X; - result.M32 = difference.Y; - result.M33 = difference.Z; - result.M34 = 0.0f; - result.M41 = objectPosition.X; - result.M42 = objectPosition.Y; - result.M43 = objectPosition.Z; - result.M44 = 1.0f; - } - - /// - /// Creates a right-handed spherical billboard that rotates around a specified object position. - /// - /// The position of the object around which the billboard will rotate. - /// The position of the camera. - /// The up vector of the camera. - /// The forward vector of the camera. - /// The created billboard matrix. - public static Matrix BillboardRH(Vector3 objectPosition, Vector3 cameraPosition, Vector3 cameraUpVector, Vector3 cameraForwardVector) { - Matrix result; - BillboardRH(ref objectPosition, ref cameraPosition, ref cameraUpVector, ref cameraForwardVector, out result); - return result; - } - - /// - /// Creates a left-handed, look-at matrix. - /// - /// The position of the viewer's eye. - /// The camera look-at target. - /// The camera's up vector. - /// When the method completes, contains the created look-at matrix. - public static void LookAtLH(ref Vector3 eye, ref Vector3 target, ref Vector3 up, out Matrix result) - { - Vector3 xaxis, yaxis, zaxis; - Vector3.Subtract(ref target, ref eye, out zaxis); zaxis.Normalize(); - Vector3.Cross(ref up, ref zaxis, out xaxis); xaxis.Normalize(); - Vector3.Cross(ref zaxis, ref xaxis, out yaxis); - - result = Matrix.Identity; - result.M11 = xaxis.X; result.M21 = xaxis.Y; result.M31 = xaxis.Z; - result.M12 = yaxis.X; result.M22 = yaxis.Y; result.M32 = yaxis.Z; - result.M13 = zaxis.X; result.M23 = zaxis.Y; result.M33 = zaxis.Z; - - Vector3.Dot(ref xaxis, ref eye, out result.M41); - Vector3.Dot(ref yaxis, ref eye, out result.M42); - Vector3.Dot(ref zaxis, ref eye, out result.M43); - - result.M41 = -result.M41; - result.M42 = -result.M42; - result.M43 = -result.M43; - } - - /// - /// Creates a left-handed, look-at matrix. - /// - /// The position of the viewer's eye. - /// The camera look-at target. - /// The camera's up vector. - /// The created look-at matrix. - public static Matrix LookAtLH(Vector3 eye, Vector3 target, Vector3 up) - { - Matrix result; - LookAtLH(ref eye, ref target, ref up, out result); - return result; - } - - /// - /// Creates a right-handed, look-at matrix. - /// - /// The position of the viewer's eye. - /// The camera look-at target. - /// The camera's up vector. - /// When the method completes, contains the created look-at matrix. - public static void LookAtRH(ref Vector3 eye, ref Vector3 target, ref Vector3 up, out Matrix result) - { - Vector3 xaxis, yaxis, zaxis; - Vector3.Subtract(ref eye, ref target, out zaxis); zaxis.Normalize(); - Vector3.Cross(ref up, ref zaxis, out xaxis); xaxis.Normalize(); - Vector3.Cross(ref zaxis, ref xaxis, out yaxis); - - result = Matrix.Identity; - result.M11 = xaxis.X; result.M21 = xaxis.Y; result.M31 = xaxis.Z; - result.M12 = yaxis.X; result.M22 = yaxis.Y; result.M32 = yaxis.Z; - result.M13 = zaxis.X; result.M23 = zaxis.Y; result.M33 = zaxis.Z; - - Vector3.Dot(ref xaxis, ref eye, out result.M41); - Vector3.Dot(ref yaxis, ref eye, out result.M42); - Vector3.Dot(ref zaxis, ref eye, out result.M43); - - result.M41 = -result.M41; - result.M42 = -result.M42; - result.M43 = -result.M43; - } - - /// - /// Creates a right-handed, look-at matrix. - /// - /// The position of the viewer's eye. - /// The camera look-at target. - /// The camera's up vector. - /// The created look-at matrix. - public static Matrix LookAtRH(Vector3 eye, Vector3 target, Vector3 up) - { - Matrix result; - LookAtRH(ref eye, ref target, ref up, out result); - return result; - } - - /// - /// Creates a left-handed, orthographic projection matrix. - /// - /// Width of the viewing volume. - /// Height of the viewing volume. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// When the method completes, contains the created projection matrix. - public static void OrthoLH(float width, float height, float znear, float zfar, out Matrix result) - { - float halfWidth = width * 0.5f; - float halfHeight = height * 0.5f; - - OrthoOffCenterLH(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out result); - } - - /// - /// Creates a left-handed, orthographic projection matrix. - /// - /// Width of the viewing volume. - /// Height of the viewing volume. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// The created projection matrix. - public static Matrix OrthoLH(float width, float height, float znear, float zfar) - { - Matrix result; - OrthoLH(width, height, znear, zfar, out result); - return result; - } - - /// - /// Creates a right-handed, orthographic projection matrix. - /// - /// Width of the viewing volume. - /// Height of the viewing volume. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// When the method completes, contains the created projection matrix. - public static void OrthoRH(float width, float height, float znear, float zfar, out Matrix result) - { - float halfWidth = width * 0.5f; - float halfHeight = height * 0.5f; - - OrthoOffCenterRH(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out result); - } - - /// - /// Creates a right-handed, orthographic projection matrix. - /// - /// Width of the viewing volume. - /// Height of the viewing volume. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// The created projection matrix. - public static Matrix OrthoRH(float width, float height, float znear, float zfar) - { - Matrix result; - OrthoRH(width, height, znear, zfar, out result); - return result; - } - - /// - /// Creates a left-handed, customized orthographic projection matrix. - /// - /// Minimum x-value of the viewing volume. - /// Maximum x-value of the viewing volume. - /// Minimum y-value of the viewing volume. - /// Maximum y-value of the viewing volume. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// When the method completes, contains the created projection matrix. - public static void OrthoOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result) - { - float zRange = 1.0f / (zfar - znear); - - result = Matrix.Identity; - result.M11 = 2.0f / (right - left); - result.M22 = 2.0f / (top - bottom); - result.M33 = zRange; - result.M41 = (left + right) / (left - right); - result.M42 = (top + bottom) / (bottom - top); - result.M43 = -znear * zRange; - } - - /// - /// Creates a left-handed, customized orthographic projection matrix. - /// - /// Minimum x-value of the viewing volume. - /// Maximum x-value of the viewing volume. - /// Minimum y-value of the viewing volume. - /// Maximum y-value of the viewing volume. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// The created projection matrix. - public static Matrix OrthoOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar) - { - Matrix result; - OrthoOffCenterLH(left, right, bottom, top, znear, zfar, out result); - return result; - } - - /// - /// Creates a right-handed, customized orthographic projection matrix. - /// - /// Minimum x-value of the viewing volume. - /// Maximum x-value of the viewing volume. - /// Minimum y-value of the viewing volume. - /// Maximum y-value of the viewing volume. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// When the method completes, contains the created projection matrix. - public static void OrthoOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result) - { - OrthoOffCenterLH(left, right, bottom, top, znear, zfar, out result); - result.M33 *= -1.0f; - } - - /// - /// Creates a right-handed, customized orthographic projection matrix. - /// - /// Minimum x-value of the viewing volume. - /// Maximum x-value of the viewing volume. - /// Minimum y-value of the viewing volume. - /// Maximum y-value of the viewing volume. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// The created projection matrix. - public static Matrix OrthoOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar) - { - Matrix result; - OrthoOffCenterRH(left, right, bottom, top, znear, zfar, out result); - return result; - } - - /// - /// Creates a left-handed, perspective projection matrix. - /// - /// Width of the viewing volume. - /// Height of the viewing volume. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// When the method completes, contains the created projection matrix. - public static void PerspectiveLH(float width, float height, float znear, float zfar, out Matrix result) - { - float halfWidth = width * 0.5f; - float halfHeight = height * 0.5f; - - PerspectiveOffCenterLH(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out result); - } - - /// - /// Creates a left-handed, perspective projection matrix. - /// - /// Width of the viewing volume. - /// Height of the viewing volume. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// The created projection matrix. - public static Matrix PerspectiveLH(float width, float height, float znear, float zfar) - { - Matrix result; - PerspectiveLH(width, height, znear, zfar, out result); - return result; - } - - /// - /// Creates a right-handed, perspective projection matrix. - /// - /// Width of the viewing volume. - /// Height of the viewing volume. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// When the method completes, contains the created projection matrix. - public static void PerspectiveRH(float width, float height, float znear, float zfar, out Matrix result) - { - float halfWidth = width * 0.5f; - float halfHeight = height * 0.5f; - - PerspectiveOffCenterRH(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out result); - } - - /// - /// Creates a right-handed, perspective projection matrix. - /// - /// Width of the viewing volume. - /// Height of the viewing volume. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// The created projection matrix. - public static Matrix PerspectiveRH(float width, float height, float znear, float zfar) - { - Matrix result; - PerspectiveRH(width, height, znear, zfar, out result); - return result; - } - - /// - /// Creates a left-handed, perspective projection matrix based on a field of view. - /// - /// Field of view in the y direction, in radians. - /// Aspect ratio, defined as view space width divided by height. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// When the method completes, contains the created projection matrix. - public static void PerspectiveFovLH(float fov, float aspect, float znear, float zfar, out Matrix result) - { - float yScale = (float)(1.0 / Math.Tan(fov * 0.5f)); - float xScale = yScale / aspect; - - float halfWidth = znear / xScale; - float halfHeight = znear / yScale; - - PerspectiveOffCenterLH(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out result); - } - - /// - /// Creates a left-handed, perspective projection matrix based on a field of view. - /// - /// Field of view in the y direction, in radians. - /// Aspect ratio, defined as view space width divided by height. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// The created projection matrix. - public static Matrix PerspectiveFovLH(float fov, float aspect, float znear, float zfar) - { - Matrix result; - PerspectiveFovLH(fov, aspect, znear, zfar, out result); - return result; - } - - /// - /// Creates a right-handed, perspective projection matrix based on a field of view. - /// - /// Field of view in the y direction, in radians. - /// Aspect ratio, defined as view space width divided by height. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// When the method completes, contains the created projection matrix. - public static void PerspectiveFovRH(float fov, float aspect, float znear, float zfar, out Matrix result) - { - float yScale = (float)(1.0 / Math.Tan(fov * 0.5f)); - float xScale = yScale / aspect; - - float halfWidth = znear / xScale; - float halfHeight = znear / yScale; - - PerspectiveOffCenterRH(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out result); - } - - /// - /// Creates a right-handed, perspective projection matrix based on a field of view. - /// - /// Field of view in the y direction, in radians. - /// Aspect ratio, defined as view space width divided by height. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// The created projection matrix. - public static Matrix PerspectiveFovRH(float fov, float aspect, float znear, float zfar) - { - Matrix result; - PerspectiveFovRH(fov, aspect, znear, zfar, out result); - return result; - } - - /// - /// Creates a left-handed, customized perspective projection matrix. - /// - /// Minimum x-value of the viewing volume. - /// Maximum x-value of the viewing volume. - /// Minimum y-value of the viewing volume. - /// Maximum y-value of the viewing volume. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// When the method completes, contains the created projection matrix. - public static void PerspectiveOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result) - { - float zRange = zfar / (zfar - znear); - - result = new Matrix(); - result.M11 = 2.0f * znear / (right - left); - result.M22 = 2.0f * znear / (top - bottom); - result.M31 = (left + right) / (left - right); - result.M32 = (top + bottom) / (bottom - top); - result.M33 = zRange; - result.M34 = 1.0f; - result.M43 = -znear * zRange; - } - - /// - /// Creates a left-handed, customized perspective projection matrix. - /// - /// Minimum x-value of the viewing volume. - /// Maximum x-value of the viewing volume. - /// Minimum y-value of the viewing volume. - /// Maximum y-value of the viewing volume. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// The created projection matrix. - public static Matrix PerspectiveOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar) - { - Matrix result; - PerspectiveOffCenterLH(left, right, bottom, top, znear, zfar, out result); - return result; - } - - /// - /// Creates a right-handed, customized perspective projection matrix. - /// - /// Minimum x-value of the viewing volume. - /// Maximum x-value of the viewing volume. - /// Minimum y-value of the viewing volume. - /// Maximum y-value of the viewing volume. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// When the method completes, contains the created projection matrix. - public static void PerspectiveOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result) - { - PerspectiveOffCenterLH(left, right, bottom, top, znear, zfar, out result); - result.M31 *= -1.0f; - result.M32 *= -1.0f; - result.M33 *= -1.0f; - result.M34 *= -1.0f; - } - - /// - /// Creates a right-handed, customized perspective projection matrix. - /// - /// Minimum x-value of the viewing volume. - /// Maximum x-value of the viewing volume. - /// Minimum y-value of the viewing volume. - /// Maximum y-value of the viewing volume. - /// Minimum z-value of the viewing volume. - /// Maximum z-value of the viewing volume. - /// The created projection matrix. - public static Matrix PerspectiveOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar) - { - Matrix result; - PerspectiveOffCenterRH(left, right, bottom, top, znear, zfar, out result); - return result; - } - - /// - /// Builds a matrix that can be used to reflect vectors about a plane. - /// - /// The plane for which the reflection occurs. This parameter is assumed to be normalized. - /// When the method completes, contains the reflection matrix. - public static void Reflection(ref Plane plane, out Matrix result) - { - float x = plane.Normal.X; - float y = plane.Normal.Y; - float z = plane.Normal.Z; - float x2 = -2.0f * x; - float y2 = -2.0f * y; - float z2 = -2.0f * z; - - result.M11 = (x2 * x) + 1.0f; - result.M12 = y2 * x; - result.M13 = z2 * x; - result.M14 = 0.0f; - result.M21 = x2 * y; - result.M22 = (y2 * y) + 1.0f; - result.M23 = z2 * y; - result.M24 = 0.0f; - result.M31 = x2 * z; - result.M32 = y2 * z; - result.M33 = (z2 * z) + 1.0f; - result.M34 = 0.0f; - result.M41 = x2 * plane.D; - result.M42 = y2 * plane.D; - result.M43 = z2 * plane.D; - result.M44 = 1.0f; - } - - /// - /// Builds a matrix that can be used to reflect vectors about a plane. - /// - /// The plane for which the reflection occurs. This parameter is assumed to be normalized. - /// The reflection matrix. - public static Matrix Reflection(Plane plane) - { - Matrix result; - Reflection(ref plane, out result); - return result; - } - - /// - /// Creates a matrix that flattens geometry into a shadow. - /// - /// The light direction. If the W component is 0, the light is directional light; if the - /// W component is 1, the light is a point light. - /// The plane onto which to project the geometry as a shadow. This parameter is assumed to be normalized. - /// When the method completes, contains the shadow matrix. - public static void Shadow(ref Vector4 light, ref Plane plane, out Matrix result) - { - float dot = (plane.Normal.X * light.X) + (plane.Normal.Y * light.Y) + (plane.Normal.Z * light.Z) + (plane.D * light.W); - float x = -plane.Normal.X; - float y = -plane.Normal.Y; - float z = -plane.Normal.Z; - float d = -plane.D; - - result.M11 = (x * light.X) + dot; - result.M21 = y * light.X; - result.M31 = z * light.X; - result.M41 = d * light.X; - result.M12 = x * light.Y; - result.M22 = (y * light.Y) + dot; - result.M32 = z * light.Y; - result.M42 = d * light.Y; - result.M13 = x * light.Z; - result.M23 = y * light.Z; - result.M33 = (z * light.Z) + dot; - result.M43 = d * light.Z; - result.M14 = x * light.W; - result.M24 = y * light.W; - result.M34 = z * light.W; - result.M44 = (d * light.W) + dot; - } - - /// - /// Creates a matrix that flattens geometry into a shadow. - /// - /// The light direction. If the W component is 0, the light is directional light; if the - /// W component is 1, the light is a point light. - /// The plane onto which to project the geometry as a shadow. This parameter is assumed to be normalized. - /// The shadow matrix. - public static Matrix Shadow(Vector4 light, Plane plane) - { - Matrix result; - Shadow(ref light, ref plane, out result); - return result; - } - - /// - /// Creates a matrix that scales along the x-axis, y-axis, and y-axis. - /// - /// Scaling factor for all three axes. - /// When the method completes, contains the created scaling matrix. - public static void Scaling(ref Vector3 scale, out Matrix result) - { - Scaling(scale.X, scale.Y, scale.Z, out result); - } - - /// - /// Creates a matrix that scales along the x-axis, y-axis, and y-axis. - /// - /// Scaling factor for all three axes. - /// The created scaling matrix. - public static Matrix Scaling(Vector3 scale) - { - Matrix result; - Scaling(ref scale, out result); - return result; - } - - /// - /// Creates a matrix that scales along the x-axis, y-axis, and y-axis. - /// - /// Scaling factor that is applied along the x-axis. - /// Scaling factor that is applied along the y-axis. - /// Scaling factor that is applied along the z-axis. - /// When the method completes, contains the created scaling matrix. - public static void Scaling(float x, float y, float z, out Matrix result) - { - result = Matrix.Identity; - result.M11 = x; - result.M22 = y; - result.M33 = z; - } - - /// - /// Creates a matrix that scales along the x-axis, y-axis, and y-axis. - /// - /// Scaling factor that is applied along the x-axis. - /// Scaling factor that is applied along the y-axis. - /// Scaling factor that is applied along the z-axis. - /// The created scaling matrix. - public static Matrix Scaling(float x, float y, float z) - { - Matrix result; - Scaling(x, y, z, out result); - return result; - } - - /// - /// Creates a matrix that uniformly scales along all three axis. - /// - /// The uniform scale that is applied along all axis. - /// When the method completes, contains the created scaling matrix. - public static void Scaling(float scale, out Matrix result) - { - result = Matrix.Identity; - result.M11 = result.M22 = result.M33 = scale; - } - - /// - /// Creates a matrix that uniformly scales along all three axis. - /// - /// The uniform scale that is applied along all axis. - /// The created scaling matrix. - public static Matrix Scaling(float scale) - { - Matrix result; - Scaling(scale, out result); - return result; - } - - /// - /// Creates a matrix that rotates around the x-axis. - /// - /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. - /// When the method completes, contains the created rotation matrix. - public static void RotationX(float angle, out Matrix result) - { - float cos = (float)Math.Cos(angle); - float sin = (float)Math.Sin(angle); - - result = Matrix.Identity; - result.M22 = cos; - result.M23 = sin; - result.M32 = -sin; - result.M33 = cos; - } - - /// - /// Creates a matrix that rotates around the x-axis. - /// - /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. - /// The created rotation matrix. - public static Matrix RotationX(float angle) - { - Matrix result; - RotationX(angle, out result); - return result; - } - - /// - /// Creates a matrix that rotates around the y-axis. - /// - /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. - /// When the method completes, contains the created rotation matrix. - public static void RotationY(float angle, out Matrix result) - { - float cos = (float)Math.Cos(angle); - float sin = (float)Math.Sin(angle); - - result = Matrix.Identity; - result.M11 = cos; - result.M13 = -sin; - result.M31 = sin; - result.M33 = cos; - } - - /// - /// Creates a matrix that rotates around the y-axis. - /// - /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. - /// The created rotation matrix. - public static Matrix RotationY(float angle) - { - Matrix result; - RotationY(angle, out result); - return result; - } - - /// - /// Creates a matrix that rotates around the z-axis. - /// - /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. - /// When the method completes, contains the created rotation matrix. - public static void RotationZ(float angle, out Matrix result) - { - float cos = (float)Math.Cos(angle); - float sin = (float)Math.Sin(angle); - - result = Matrix.Identity; - result.M11 = cos; - result.M12 = sin; - result.M21 = -sin; - result.M22 = cos; - } - - /// - /// Creates a matrix that rotates around the z-axis. - /// - /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. - /// The created rotation matrix. - public static Matrix RotationZ(float angle) - { - Matrix result; - RotationZ(angle, out result); - return result; - } - - /// - /// Creates a matrix that rotates around an arbitrary axis. - /// - /// The axis around which to rotate. This parameter is assumed to be normalized. - /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. - /// When the method completes, contains the created rotation matrix. - public static void RotationAxis(ref Vector3 axis, float angle, out Matrix result) - { - float x = axis.X; - float y = axis.Y; - float z = axis.Z; - float cos = (float)Math.Cos(angle); - float sin = (float)Math.Sin(angle); - float xx = x * x; - float yy = y * y; - float zz = z * z; - float xy = x * y; - float xz = x * z; - float yz = y * z; - - result = Matrix.Identity; - result.M11 = xx + (cos * (1.0f - xx)); - result.M12 = (xy - (cos * xy)) + (sin * z); - result.M13 = (xz - (cos * xz)) - (sin * y); - result.M21 = (xy - (cos * xy)) - (sin * z); - result.M22 = yy + (cos * (1.0f - yy)); - result.M23 = (yz - (cos * yz)) + (sin * x); - result.M31 = (xz - (cos * xz)) + (sin * y); - result.M32 = (yz - (cos * yz)) - (sin * x); - result.M33 = zz + (cos * (1.0f - zz)); - } - - /// - /// Creates a matrix that rotates around an arbitrary axis. - /// - /// The axis around which to rotate. This parameter is assumed to be normalized. - /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. - /// The created rotation matrix. - public static Matrix RotationAxis(Vector3 axis, float angle) - { - Matrix result; - RotationAxis(ref axis, angle, out result); - return result; - } - - /// - /// Creates a rotation matrix from a quaternion. - /// - /// The quaternion to use to build the matrix. - /// The created rotation matrix. - public static void RotationQuaternion(ref Quaternion rotation, out Matrix result) - { - float xx = rotation.X * rotation.X; - float yy = rotation.Y * rotation.Y; - float zz = rotation.Z * rotation.Z; - float xy = rotation.X * rotation.Y; - float zw = rotation.Z * rotation.W; - float zx = rotation.Z * rotation.X; - float yw = rotation.Y * rotation.W; - float yz = rotation.Y * rotation.Z; - float xw = rotation.X * rotation.W; - - result = Matrix.Identity; - result.M11 = 1.0f - (2.0f * (yy + zz)); - result.M12 = 2.0f * (xy + zw); - result.M13 = 2.0f * (zx - yw); - result.M21 = 2.0f * (xy - zw); - result.M22 = 1.0f - (2.0f * (zz + xx)); - result.M23 = 2.0f * (yz + xw); - result.M31 = 2.0f * (zx + yw); - result.M32 = 2.0f * (yz - xw); - result.M33 = 1.0f - (2.0f * (yy + xx)); - } - - /// - /// Creates a rotation matrix from a quaternion. - /// - /// The quaternion to use to build the matrix. - /// The created rotation matrix. - public static Matrix RotationQuaternion(Quaternion rotation) - { - Matrix result; - RotationQuaternion(ref rotation, out result); - return result; - } - - /// - /// Creates a rotation matrix with a specified yaw, pitch, and roll. - /// - /// Yaw around the y-axis, in radians. - /// Pitch around the x-axis, in radians. - /// Roll around the z-axis, in radians. - /// When the method completes, contains the created rotation matrix. - public static void RotationYawPitchRoll(float yaw, float pitch, float roll, out Matrix result) - { - Quaternion quaternion = new Quaternion(); - Quaternion.RotationYawPitchRoll(yaw, pitch, roll, out quaternion); - RotationQuaternion(ref quaternion, out result); - } - - /// - /// Creates a rotation matrix with a specified yaw, pitch, and roll. - /// - /// Yaw around the y-axis, in radians. - /// Pitch around the x-axis, in radians. - /// Roll around the z-axis, in radians. - /// The created rotation matrix. - public static Matrix RotationYawPitchRoll(float yaw, float pitch, float roll) - { - Matrix result; - RotationYawPitchRoll(yaw, pitch, roll, out result); - return result; - } - - /// - /// Creates a translation matrix using the specified offsets. - /// - /// The offset for all three coordinate planes. - /// When the method completes, contains the created translation matrix. - public static void Translation(ref Vector3 value, out Matrix result) - { - Translation(value.X, value.Y, value.Z, out result); - } - - /// - /// Creates a translation matrix using the specified offsets. - /// - /// The offset for all three coordinate planes. - /// The created translation matrix. - public static Matrix Translation(Vector3 value) - { - Matrix result; - Translation(ref value, out result); - return result; - } - - /// - /// Creates a translation matrix using the specified offsets. - /// - /// X-coordinate offset. - /// Y-coordinate offset. - /// Z-coordinate offset. - /// When the method completes, contains the created translation matrix. - public static void Translation(float x, float y, float z, out Matrix result) - { - result = Matrix.Identity; - result.M41 = x; - result.M42 = y; - result.M43 = z; - } - - /// - /// Creates a translation matrix using the specified offsets. - /// - /// X-coordinate offset. - /// Y-coordinate offset. - /// Z-coordinate offset. - /// The created translation matrix. - public static Matrix Translation(float x, float y, float z) - { - Matrix result; - Translation(x, y, z, out result); - return result; - } - - /// - /// Creates a skew/shear matrix by means of a translation vector, a rotation vector, and a rotation angle. - /// shearing is performed in the direction of translation vector, where translation vector and rotation vector define the shearing plane. - /// The effect is such that the skewed rotation vector has the specified angle with rotation itself. - /// - /// The rotation angle. - /// The rotation vector - /// The translation vector - /// Contains the created skew/shear matrix. - public static void Skew(float angle, ref Vector3 rotationVec, ref Vector3 transVec, out Matrix matrix) - { - //http://elckerlyc.ewi.utwente.nl/browser/Elckerlyc/Hmi/HmiMath/src/hmi/math/Mat3f.java - float MINIMAL_SKEW_ANGLE = 0.000001f; - - Vector3 e0 = rotationVec; - Vector3 e1 = Vector3.Normalize(transVec); - - float rv1; - Vector3.Dot(ref rotationVec, ref e1, out rv1); - e0 += rv1 * e1; - float rv0; - Vector3.Dot(ref rotationVec, ref e0, out rv0); - float cosa = (float)Math.Cos(angle); - float sina = (float)Math.Sin(angle); - float rr0 = rv0 * cosa - rv1 * sina; - float rr1 = rv0 * sina + rv1 * cosa; - - if (rr0 < MINIMAL_SKEW_ANGLE) - throw new ArgumentException("illegal skew angle"); - - float d = (rr1 / rr0) - (rv1 / rv0); - - matrix = Matrix.Identity; - matrix.M11 = d * e1[0] * e0[0] + 1.0f; - matrix.M12 = d * e1[0] * e0[1]; - matrix.M13 = d * e1[0] * e0[2]; - matrix.M21 = d * e1[1] * e0[0]; - matrix.M22 = d * e1[1] * e0[1] + 1.0f; - matrix.M23 = d * e1[1] * e0[2]; - matrix.M31 = d * e1[2] * e0[0]; - matrix.M32 = d * e1[2] * e0[1]; - matrix.M33 = d * e1[2] * e0[2] + 1.0f; - } - - /// - /// Creates a 3D affine transformation matrix. - /// - /// Scaling factor. - /// The rotation of the transformation. - /// The translation factor of the transformation. - /// When the method completes, contains the created affine transformation matrix. - public static void AffineTransformation(float scaling, ref Quaternion rotation, ref Vector3 translation, out Matrix result) - { - result = Scaling(scaling) * RotationQuaternion(rotation) * Translation(translation); - } - - /// - /// Creates a 3D affine transformation matrix. - /// - /// Scaling factor. - /// The rotation of the transformation. - /// The translation factor of the transformation. - /// The created affine transformation matrix. - public static Matrix AffineTransformation(float scaling, Quaternion rotation, Vector3 translation) - { - Matrix result; - AffineTransformation(scaling, ref rotation, ref translation, out result); - return result; - } - - /// - /// Creates a 3D affine transformation matrix. - /// - /// Scaling factor. - /// The center of the rotation. - /// The rotation of the transformation. - /// The translation factor of the transformation. - /// When the method completes, contains the created affine transformation matrix. - public static void AffineTransformation(float scaling, ref Vector3 rotationCenter, ref Quaternion rotation, ref Vector3 translation, out Matrix result) - { - result = Scaling(scaling) * Translation(-rotationCenter) * RotationQuaternion(rotation) * - Translation(rotationCenter) * Translation(translation); - } - - /// - /// Creates a 3D affine transformation matrix. - /// - /// Scaling factor. - /// The center of the rotation. - /// The rotation of the transformation. - /// The translation factor of the transformation. - /// The created affine transformation matrix. - public static Matrix AffineTransformation(float scaling, Vector3 rotationCenter, Quaternion rotation, Vector3 translation) - { - Matrix result; - AffineTransformation(scaling, ref rotationCenter, ref rotation, ref translation, out result); - return result; - } - - /// - /// Creates a 2D affine transformation matrix. - /// - /// Scaling factor. - /// The rotation of the transformation. - /// The translation factor of the transformation. - /// When the method completes, contains the created affine transformation matrix. - public static void AffineTransformation2D(float scaling, float rotation, ref Vector2 translation, out Matrix result) - { - result = Scaling(scaling, scaling, 1.0f) * RotationZ(rotation) * Translation((Vector3)translation); - } - - /// - /// Creates a 2D affine transformation matrix. - /// - /// Scaling factor. - /// The rotation of the transformation. - /// The translation factor of the transformation. - /// The created affine transformation matrix. - public static Matrix AffineTransformation2D(float scaling, float rotation, Vector2 translation) - { - Matrix result; - AffineTransformation2D(scaling, rotation, ref translation, out result); - return result; - } - - /// - /// Creates a 2D affine transformation matrix. - /// - /// Scaling factor. - /// The center of the rotation. - /// The rotation of the transformation. - /// The translation factor of the transformation. - /// When the method completes, contains the created affine transformation matrix. - public static void AffineTransformation2D(float scaling, ref Vector2 rotationCenter, float rotation, ref Vector2 translation, out Matrix result) - { - result = Scaling(scaling, scaling, 1.0f) * Translation((Vector3)(-rotationCenter)) * RotationZ(rotation) * - Translation((Vector3)rotationCenter) * Translation((Vector3)translation); - } - - /// - /// Creates a 2D affine transformation matrix. - /// - /// Scaling factor. - /// The center of the rotation. - /// The rotation of the transformation. - /// The translation factor of the transformation. - /// The created affine transformation matrix. - public static Matrix AffineTransformation2D(float scaling, Vector2 rotationCenter, float rotation, Vector2 translation) - { - Matrix result; - AffineTransformation2D(scaling, ref rotationCenter, rotation, ref translation, out result); - return result; - } - - /// - /// Creates a transformation matrix. - /// - /// Center point of the scaling operation. - /// Scaling rotation amount. - /// Scaling factor. - /// The center of the rotation. - /// The rotation of the transformation. - /// The translation factor of the transformation. - /// When the method completes, contains the created transformation matrix. - public static void Transformation(ref Vector3 scalingCenter, ref Quaternion scalingRotation, ref Vector3 scaling, ref Vector3 rotationCenter, ref Quaternion rotation, ref Vector3 translation, out Matrix result) - { - Matrix sr = RotationQuaternion(scalingRotation); - - result = Translation(-scalingCenter) * Transpose(sr) * Scaling(scaling) * sr * Translation(scalingCenter) * Translation(-rotationCenter) * - RotationQuaternion(rotation) * Translation(rotationCenter) * Translation(translation); - } - - /// - /// Creates a transformation matrix. - /// - /// Center point of the scaling operation. - /// Scaling rotation amount. - /// Scaling factor. - /// The center of the rotation. - /// The rotation of the transformation. - /// The translation factor of the transformation. - /// The created transformation matrix. - public static Matrix Transformation(Vector3 scalingCenter, Quaternion scalingRotation, Vector3 scaling, Vector3 rotationCenter, Quaternion rotation, Vector3 translation) - { - Matrix result; - Transformation(ref scalingCenter, ref scalingRotation, ref scaling, ref rotationCenter, ref rotation, ref translation, out result); - return result; - } - - /// - /// Creates a 2D transformation matrix. - /// - /// Center point of the scaling operation. - /// Scaling rotation amount. - /// Scaling factor. - /// The center of the rotation. - /// The rotation of the transformation. - /// The translation factor of the transformation. - /// When the method completes, contains the created transformation matrix. - public static void Transformation2D(ref Vector2 scalingCenter, float scalingRotation, ref Vector2 scaling, ref Vector2 rotationCenter, float rotation, ref Vector2 translation, out Matrix result) - { - result = Translation((Vector3)(-scalingCenter)) * RotationZ(-scalingRotation) * Scaling((Vector3)scaling) * RotationZ(scalingRotation) * Translation((Vector3)scalingCenter) * - Translation((Vector3)(-rotationCenter)) * RotationZ(rotation) * Translation((Vector3)rotationCenter) * Translation((Vector3)translation); - - result.M33 = 1f; - result.M44 = 1f; - } - - /// - /// Creates a 2D transformation matrix. - /// - /// Center point of the scaling operation. - /// Scaling rotation amount. - /// Scaling factor. - /// The center of the rotation. - /// The rotation of the transformation. - /// The translation factor of the transformation. - /// The created transformation matrix. - public static Matrix Transformation2D(Vector2 scalingCenter, float scalingRotation, Vector2 scaling, Vector2 rotationCenter, float rotation, Vector2 translation) - { - Matrix result; - Transformation2D(ref scalingCenter, scalingRotation, ref scaling, ref rotationCenter, rotation, ref translation, out result); - return result; - } - - /// - /// Adds two matrices. - /// - /// The first matrix to add. - /// The second matrix to add. - /// The sum of the two matrices. - public static Matrix operator +(Matrix left, Matrix right) - { - Matrix result; - Add(ref left, ref right, out result); - return result; - } - - /// - /// Assert a matrix (return it unchanged). - /// - /// The matrix to assert (unchanged). - /// The asserted (unchanged) matrix. - public static Matrix operator +(Matrix value) - { - return value; - } - - /// - /// Subtracts two matrices. - /// - /// The first matrix to subtract. - /// The second matrix to subtract. - /// The difference between the two matrices. - public static Matrix operator -(Matrix left, Matrix right) - { - Matrix result; - Subtract(ref left, ref right, out result); - return result; - } - - /// - /// Negates a matrix. - /// - /// The matrix to negate. - /// The negated matrix. - public static Matrix operator -(Matrix value) - { - Matrix result; - Negate(ref value, out result); - return result; - } - - /// - /// Scales a matrix by a given value. - /// - /// The matrix to scale. - /// The amount by which to scale. - /// The scaled matrix. - public static Matrix operator *(float left, Matrix right) - { - Matrix result; - Multiply(ref right, left, out result); - return result; - } - - /// - /// Scales a matrix by a given value. - /// - /// The matrix to scale. - /// The amount by which to scale. - /// The scaled matrix. - public static Matrix operator *(Matrix left, float right) - { - Matrix result; - Multiply(ref left, right, out result); - return result; - } - - /// - /// Multiplies two matrices. - /// - /// The first matrix to multiply. - /// The second matrix to multiply. - /// The product of the two matrices. - public static Matrix operator *(Matrix left, Matrix right) - { - Matrix result; - Multiply(ref left, ref right, out result); - return result; - } - - /// - /// Scales a matrix by a given value. - /// - /// The matrix to scale. - /// The amount by which to scale. - /// The scaled matrix. - public static Matrix operator /(Matrix left, float right) - { - Matrix result; - Divide(ref left, right, out result); - return result; - } - - /// - /// Divides two matrices. - /// - /// The first matrix to divide. - /// The second matrix to divide. - /// The quotient of the two matrices. - public static Matrix operator /(Matrix left, Matrix right) - { - Matrix result; - Divide(ref left, ref right, out result); - return result; - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has the same value as ; otherwise, false. - public static bool operator ==(Matrix left, Matrix right) - { - return left.Equals(ref right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has a different value than ; otherwise, false. - public static bool operator !=(Matrix left, Matrix right) - { - return !left.Equals(ref right); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return string.Format(CultureInfo.CurrentCulture, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M23:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}]", - M11, M12, M13, M14, M21, M22, M23, M24, M31, M32, M33, M34, M41, M42, M43, M44); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// - /// A that represents this instance. - /// - public string ToString(string format) - { - if (format == null) - return ToString(); - - return string.Format(format, CultureInfo.CurrentCulture, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M23:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}]", - M11.ToString(format, CultureInfo.CurrentCulture), M12.ToString(format, CultureInfo.CurrentCulture), M13.ToString(format, CultureInfo.CurrentCulture), M14.ToString(format, CultureInfo.CurrentCulture), - M21.ToString(format, CultureInfo.CurrentCulture), M22.ToString(format, CultureInfo.CurrentCulture), M23.ToString(format, CultureInfo.CurrentCulture), M24.ToString(format, CultureInfo.CurrentCulture), - M31.ToString(format, CultureInfo.CurrentCulture), M32.ToString(format, CultureInfo.CurrentCulture), M33.ToString(format, CultureInfo.CurrentCulture), M34.ToString(format, CultureInfo.CurrentCulture), - M41.ToString(format, CultureInfo.CurrentCulture), M42.ToString(format, CultureInfo.CurrentCulture), M43.ToString(format, CultureInfo.CurrentCulture), M44.ToString(format, CultureInfo.CurrentCulture)); - } - - /// - /// Returns a that represents this instance. - /// - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(IFormatProvider formatProvider) - { - return string.Format(formatProvider, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M23:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}]", - M11.ToString(formatProvider), M12.ToString(formatProvider), M13.ToString(formatProvider), M14.ToString(formatProvider), - M21.ToString(formatProvider), M22.ToString(formatProvider), M23.ToString(formatProvider), M24.ToString(formatProvider), - M31.ToString(formatProvider), M32.ToString(formatProvider), M33.ToString(formatProvider), M34.ToString(formatProvider), - M41.ToString(formatProvider), M42.ToString(formatProvider), M43.ToString(formatProvider), M44.ToString(formatProvider)); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - if (format == null) - return ToString(formatProvider); - - return string.Format(format, formatProvider, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M23:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}]", - M11.ToString(format, formatProvider), M12.ToString(format, formatProvider), M13.ToString(format, formatProvider), M14.ToString(format, formatProvider), - M21.ToString(format, formatProvider), M22.ToString(format, formatProvider), M23.ToString(format, formatProvider), M24.ToString(format, formatProvider), - M31.ToString(format, formatProvider), M32.ToString(format, formatProvider), M33.ToString(format, formatProvider), M34.ToString(format, formatProvider), - M41.ToString(format, formatProvider), M42.ToString(format, formatProvider), M43.ToString(format, formatProvider), M44.ToString(format, formatProvider)); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - var hashCode = M11.GetHashCode(); - hashCode = (hashCode * 397) ^ M12.GetHashCode(); - hashCode = (hashCode * 397) ^ M13.GetHashCode(); - hashCode = (hashCode * 397) ^ M14.GetHashCode(); - hashCode = (hashCode * 397) ^ M21.GetHashCode(); - hashCode = (hashCode * 397) ^ M22.GetHashCode(); - hashCode = (hashCode * 397) ^ M23.GetHashCode(); - hashCode = (hashCode * 397) ^ M24.GetHashCode(); - hashCode = (hashCode * 397) ^ M31.GetHashCode(); - hashCode = (hashCode * 397) ^ M32.GetHashCode(); - hashCode = (hashCode * 397) ^ M33.GetHashCode(); - hashCode = (hashCode * 397) ^ M34.GetHashCode(); - hashCode = (hashCode * 397) ^ M41.GetHashCode(); - hashCode = (hashCode * 397) ^ M42.GetHashCode(); - hashCode = (hashCode * 397) ^ M43.GetHashCode(); - hashCode = (hashCode * 397) ^ M44.GetHashCode(); - return hashCode; - } - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(M11); - serializer.Writer.Write(M12); - serializer.Writer.Write(M13); - serializer.Writer.Write(M14); - serializer.Writer.Write(M21); - serializer.Writer.Write(M22); - serializer.Writer.Write(M23); - serializer.Writer.Write(M24); - serializer.Writer.Write(M31); - serializer.Writer.Write(M32); - serializer.Writer.Write(M33); - serializer.Writer.Write(M34); - serializer.Writer.Write(M41); - serializer.Writer.Write(M42); - serializer.Writer.Write(M43); - serializer.Writer.Write(M44); - } - else - { - M11 = serializer.Reader.ReadSingle(); - M12 = serializer.Reader.ReadSingle(); - M13 = serializer.Reader.ReadSingle(); - M14 = serializer.Reader.ReadSingle(); - M21 = serializer.Reader.ReadSingle(); - M22 = serializer.Reader.ReadSingle(); - M23 = serializer.Reader.ReadSingle(); - M24 = serializer.Reader.ReadSingle(); - M31 = serializer.Reader.ReadSingle(); - M32 = serializer.Reader.ReadSingle(); - M33 = serializer.Reader.ReadSingle(); - M34 = serializer.Reader.ReadSingle(); - M41 = serializer.Reader.ReadSingle(); - M42 = serializer.Reader.ReadSingle(); - M43 = serializer.Reader.ReadSingle(); - M44 = serializer.Reader.ReadSingle(); - } - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(ref Matrix other) - { - return (MathUtil.NearEqual(other.M11, M11) && - MathUtil.NearEqual(other.M12, M12) && - MathUtil.NearEqual(other.M13, M13) && - MathUtil.NearEqual(other.M14, M14) && - MathUtil.NearEqual(other.M21, M21) && - MathUtil.NearEqual(other.M22, M22) && - MathUtil.NearEqual(other.M23, M23) && - MathUtil.NearEqual(other.M24, M24) && - MathUtil.NearEqual(other.M31, M31) && - MathUtil.NearEqual(other.M32, M32) && - MathUtil.NearEqual(other.M33, M33) && - MathUtil.NearEqual(other.M34, M34) && - MathUtil.NearEqual(other.M41, M41) && - MathUtil.NearEqual(other.M42, M42) && - MathUtil.NearEqual(other.M43, M43) && - MathUtil.NearEqual(other.M44, M44)); - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(Matrix other) - { - return Equals(ref other); - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object value) - { - if (!(value is Matrix)) - return false; - - var strongValue = (Matrix)value; - return Equals(ref strongValue); - } - -#if SlimDX1xInterop - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator SlimDX.Matrix(Matrix value) - { - return new SlimDX.Matrix() - { - M11 = value.M11, M12 = value.M12, M13 = value.M13, M14 = value.M14, - M21 = value.M21, M22 = value.M22, M23 = value.M23, M24 = value.M24, - M31 = value.M31, M32 = value.M32, M33 = value.M33, M34 = value.M34, - M41 = value.M41, M42 = value.M42, M43 = value.M43, M44 = value.M44 - }; - } - - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Matrix(SlimDX.Matrix value) - { - return new Matrix() - { - M11 = value.M11, M12 = value.M12, M13 = value.M13, M14 = value.M14, - M21 = value.M21, M22 = value.M22, M23 = value.M23, M24 = value.M24, - M31 = value.M31, M32 = value.M32, M33 = value.M33, M34 = value.M34, - M41 = value.M41, M42 = value.M42, M43 = value.M43, M44 = value.M44 - }; - } -#endif - -#if WPFInterop - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator System.Windows.Media.Media3D.Matrix3D(Matrix value) - { - return new System.Windows.Media.Media3D.Matrix3D() - { - M11 = value.M11, M12 = value.M12, M13 = value.M13, M14 = value.M14, - M21 = value.M21, M22 = value.M22, M23 = value.M23, M24 = value.M24, - M31 = value.M31, M32 = value.M32, M33 = value.M33, M34 = value.M34, - OffsetX = value.M41, OffsetY = value.M42, OffsetZ = value.M43, M44 = value.M44 - }; - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Matrix(System.Windows.Media.Media3D.Matrix3D value) - { - return new Matrix() - { - M11 = (float)value.M11, M12 = (float)value.M12, M13 = (float)value.M13, M14 = (float)value.M14, - M21 = (float)value.M21, M22 = (float)value.M22, M23 = (float)value.M23, M24 = (float)value.M24, - M31 = (float)value.M31, M32 = (float)value.M32, M33 = (float)value.M33, M34 = (float)value.M34, - M41 = (float)value.OffsetX, M42 = (float)value.OffsetY, M43 = (float)value.OffsetZ, M44 = (float)value.M44 - }; - } -#endif - -#if XnaInterop - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Microsoft.Xna.Framework.Matrix(Matrix value) - { - return new Microsoft.Xna.Framework.Matrix() - { - M11 = value.M11, M12 = value.M12, M13 = value.M13, M14 = value.M14, - M21 = value.M21, M22 = value.M22, M23 = value.M23, M24 = value.M24, - M31 = value.M31, M32 = value.M32, M33 = value.M33, M34 = value.M34, - M41 = value.M41, M42 = value.M42, M43 = value.M43, M44 = value.M44 - }; - } - - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Matrix(Microsoft.Xna.Framework.Matrix value) - { - return new Matrix() - { - M11 = value.M11, M12 = value.M12, M13 = value.M13, M14 = value.M14, - M21 = value.M21, M22 = value.M22, M23 = value.M23, M24 = value.M24, - M31 = value.M31, M32 = value.M32, M33 = value.M33, M34 = value.M34, - M41 = value.M41, M42 = value.M42, M43 = value.M43, M44 = value.M44 - }; - } -#endif - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from SlimMath project. http://code.google.com/p/slimmath/ +// Greetings to SlimDX Group. Original code published with the following license: +// ----------------------------------------------------------------------------- +/* +* Copyright (c) 2007-2011 SlimDX Group +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Represents a 4x4 mathematical matrix. + /// + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct Matrix : IEquatable, IFormattable + { + /// + /// The size of the type, in bytes. + /// + public static readonly int SizeInBytes = Marshal.SizeOf(typeof(Matrix)); + + /// + /// A with all of its components set to zero. + /// + public static readonly Matrix Zero = new Matrix(); + + /// + /// The identity . + /// + public static readonly Matrix Identity = new Matrix() { M11 = 1.0f, M22 = 1.0f, M33 = 1.0f, M44 = 1.0f }; + + /// + /// Value at row 1 column 1 of the matrix. + /// + public float M11; + + /// + /// Value at row 1 column 2 of the matrix. + /// + public float M12; + + /// + /// Value at row 1 column 3 of the matrix. + /// + public float M13; + + /// + /// Value at row 1 column 4 of the matrix. + /// + public float M14; + + /// + /// Value at row 2 column 1 of the matrix. + /// + public float M21; + + /// + /// Value at row 2 column 2 of the matrix. + /// + public float M22; + + /// + /// Value at row 2 column 3 of the matrix. + /// + public float M23; + + /// + /// Value at row 2 column 4 of the matrix. + /// + public float M24; + + /// + /// Value at row 3 column 1 of the matrix. + /// + public float M31; + + /// + /// Value at row 3 column 2 of the matrix. + /// + public float M32; + + /// + /// Value at row 3 column 3 of the matrix. + /// + public float M33; + + /// + /// Value at row 3 column 4 of the matrix. + /// + public float M34; + + /// + /// Value at row 4 column 1 of the matrix. + /// + public float M41; + + /// + /// Value at row 4 column 2 of the matrix. + /// + public float M42; + + /// + /// Value at row 4 column 3 of the matrix. + /// + public float M43; + + /// + /// Value at row 4 column 4 of the matrix. + /// + public float M44; + + /// + /// Gets or sets the up of the matrix; that is M21, M22, and M23. + /// + public Vector3 Up + { + get + { + Vector3 vector3; + vector3.X = this.M21; + vector3.Y = this.M22; + vector3.Z = this.M23; + return vector3; + } + set + { + this.M21 = value.X; + this.M22 = value.Y; + this.M23 = value.Z; + } + } + + /// + /// Gets or sets the down of the matrix; that is -M21, -M22, and -M23. + /// + public Vector3 Down + { + get + { + Vector3 vector3; + vector3.X = -this.M21; + vector3.Y = -this.M22; + vector3.Z = -this.M23; + return vector3; + } + set + { + this.M21 = -value.X; + this.M22 = -value.Y; + this.M23 = -value.Z; + } + } + + /// + /// Gets or sets the right of the matrix; that is M11, M12, and M13. + /// + public Vector3 Right + { + get + { + Vector3 vector3; + vector3.X = this.M11; + vector3.Y = this.M12; + vector3.Z = this.M13; + return vector3; + } + set + { + this.M11 = value.X; + this.M12 = value.Y; + this.M13 = value.Z; + } + } + + /// + /// Gets or sets the left of the matrix; that is -M11, -M12, and -M13. + /// + public Vector3 Left + { + get + { + Vector3 vector3; + vector3.X = -this.M11; + vector3.Y = -this.M12; + vector3.Z = -this.M13; + return vector3; + } + set + { + this.M11 = -value.X; + this.M12 = -value.Y; + this.M13 = -value.Z; + } + } + + /// + /// Gets or sets the forward of the matrix; that is -M31, -M32, and -M33. + /// + public Vector3 Forward + { + get + { + Vector3 vector3; + vector3.X = -this.M31; + vector3.Y = -this.M32; + vector3.Z = -this.M33; + return vector3; + } + set + { + this.M31 = -value.X; + this.M32 = -value.Y; + this.M33 = -value.Z; + } + } + + /// + /// Gets or sets the backward of the matrix; that is M31, M32, and M33. + /// + public Vector3 Backward + { + get + { + Vector3 vector3; + vector3.X = this.M31; + vector3.Y = this.M32; + vector3.Z = this.M33; + return vector3; + } + set + { + this.M31 = value.X; + this.M32 = value.Y; + this.M33 = value.Z; + } + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value that will be assigned to all components. + public Matrix(float value) + { + M11 = M12 = M13 = M14 = + M21 = M22 = M23 = M24 = + M31 = M32 = M33 = M34 = + M41 = M42 = M43 = M44 = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value to assign at row 1 column 1 of the matrix. + /// The value to assign at row 1 column 2 of the matrix. + /// The value to assign at row 1 column 3 of the matrix. + /// The value to assign at row 1 column 4 of the matrix. + /// The value to assign at row 2 column 1 of the matrix. + /// The value to assign at row 2 column 2 of the matrix. + /// The value to assign at row 2 column 3 of the matrix. + /// The value to assign at row 2 column 4 of the matrix. + /// The value to assign at row 3 column 1 of the matrix. + /// The value to assign at row 3 column 2 of the matrix. + /// The value to assign at row 3 column 3 of the matrix. + /// The value to assign at row 3 column 4 of the matrix. + /// The value to assign at row 4 column 1 of the matrix. + /// The value to assign at row 4 column 2 of the matrix. + /// The value to assign at row 4 column 3 of the matrix. + /// The value to assign at row 4 column 4 of the matrix. + public Matrix(float M11, float M12, float M13, float M14, + float M21, float M22, float M23, float M24, + float M31, float M32, float M33, float M34, + float M41, float M42, float M43, float M44) + { + this.M11 = M11; this.M12 = M12; this.M13 = M13; this.M14 = M14; + this.M21 = M21; this.M22 = M22; this.M23 = M23; this.M24 = M24; + this.M31 = M31; this.M32 = M32; this.M33 = M33; this.M34 = M34; + this.M41 = M41; this.M42 = M42; this.M43 = M43; this.M44 = M44; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The values to assign to the components of the matrix. This must be an array with sixteen elements. + /// Thrown when is null. + /// Thrown when contains more or less than sixteen elements. + public Matrix(float[] values) + { + if (values == null) + throw new ArgumentNullException("values"); + if (values.Length != 16) + throw new ArgumentOutOfRangeException("values", "There must be sixteen and only sixteen input values for Matrix."); + + M11 = values[0]; + M12 = values[1]; + M13 = values[2]; + M14 = values[3]; + + M21 = values[4]; + M22 = values[5]; + M23 = values[6]; + M24 = values[7]; + + M31 = values[8]; + M32 = values[9]; + M33 = values[10]; + M34 = values[11]; + + M41 = values[12]; + M42 = values[13]; + M43 = values[14]; + M44 = values[15]; + } + + /// + /// Gets or sets the first row in the matrix; that is M11, M12, M13, and M14. + /// + public Vector4 Row1 + { + get { return new Vector4(M11, M12, M13, M14); } + set { M11 = value.X; M12 = value.Y; M13 = value.Z; M14 = value.W; } + } + + /// + /// Gets or sets the second row in the matrix; that is M21, M22, M23, and M24. + /// + public Vector4 Row2 + { + get { return new Vector4(M21, M22, M23, M24); } + set { M21 = value.X; M22 = value.Y; M23 = value.Z; M24 = value.W; } + } + + /// + /// Gets or sets the third row in the matrix; that is M31, M32, M33, and M34. + /// + public Vector4 Row3 + { + get { return new Vector4(M31, M32, M33, M34); } + set { M31 = value.X; M32 = value.Y; M33 = value.Z; M34 = value.W; } + } + + /// + /// Gets or sets the fourth row in the matrix; that is M41, M42, M43, and M44. + /// + public Vector4 Row4 + { + get { return new Vector4(M41, M42, M43, M44); } + set { M41 = value.X; M42 = value.Y; M43 = value.Z; M44 = value.W; } + } + + /// + /// Gets or sets the first column in the matrix; that is M11, M21, M31, and M41. + /// + public Vector4 Column1 + { + get { return new Vector4(M11, M21, M31, M41); } + set { M11 = value.X; M21 = value.Y; M31 = value.Z; M41 = value.W; } + } + + /// + /// Gets or sets the second column in the matrix; that is M12, M22, M32, and M42. + /// + public Vector4 Column2 + { + get { return new Vector4(M12, M22, M32, M42); } + set { M12 = value.X; M22 = value.Y; M32 = value.Z; M42 = value.W; } + } + + /// + /// Gets or sets the third column in the matrix; that is M13, M23, M33, and M43. + /// + public Vector4 Column3 + { + get { return new Vector4(M13, M23, M33, M43); } + set { M13 = value.X; M23 = value.Y; M33 = value.Z; M43 = value.W; } + } + + /// + /// Gets or sets the fourth column in the matrix; that is M14, M24, M34, and M44. + /// + public Vector4 Column4 + { + get { return new Vector4(M14, M24, M34, M44); } + set { M14 = value.X; M24 = value.Y; M34 = value.Z; M44 = value.W; } + } + + /// + /// Gets or sets the translation of the matrix; that is M41, M42, and M43. + /// + public Vector3 TranslationVector + { + get { return new Vector3(M41, M42, M43); } + set { M41 = value.X; M42 = value.Y; M43 = value.Z; } + } + + /// + /// Gets or sets the scale of the matrix; that is M11, M22, and M33. + /// + public Vector3 ScaleVector + { + get { return new Vector3(M11, M22, M33); } + set { M11 = value.X; M22 = value.Y; M33 = value.Z; } + } + + /// + /// Gets a value indicating whether this instance is an identity matrix. + /// + /// + /// true if this instance is an identity matrix; otherwise, false. + /// + public bool IsIdentity + { + get { return this.Equals(Identity); } + } + + /// + /// Gets or sets the component at the specified index. + /// + /// The value of the matrix component, depending on the index. + /// The zero-based index of the component to access. + /// The value of the component at the specified index. + /// Thrown when the is out of the range [0, 15]. + public float this[int index] + { + get + { + switch (index) + { + case 0: return M11; + case 1: return M12; + case 2: return M13; + case 3: return M14; + case 4: return M21; + case 5: return M22; + case 6: return M23; + case 7: return M24; + case 8: return M31; + case 9: return M32; + case 10: return M33; + case 11: return M34; + case 12: return M41; + case 13: return M42; + case 14: return M43; + case 15: return M44; + } + + throw new ArgumentOutOfRangeException("index", "Indices for Matrix run from 0 to 15, inclusive."); + } + + set + { + switch (index) + { + case 0: M11 = value; break; + case 1: M12 = value; break; + case 2: M13 = value; break; + case 3: M14 = value; break; + case 4: M21 = value; break; + case 5: M22 = value; break; + case 6: M23 = value; break; + case 7: M24 = value; break; + case 8: M31 = value; break; + case 9: M32 = value; break; + case 10: M33 = value; break; + case 11: M34 = value; break; + case 12: M41 = value; break; + case 13: M42 = value; break; + case 14: M43 = value; break; + case 15: M44 = value; break; + default: throw new ArgumentOutOfRangeException("index", "Indices for Matrix run from 0 to 15, inclusive."); + } + } + } + + /// + /// Gets or sets the component at the specified index. + /// + /// The value of the matrix component, depending on the index. + /// The row of the matrix to access. + /// The column of the matrix to access. + /// The value of the component at the specified index. + /// Thrown when the or is out of the range [0, 3]. + public float this[int row, int column] + { + get + { + if (row < 0 || row > 3) + throw new ArgumentOutOfRangeException("row", "Rows and columns for matrices run from 0 to 3, inclusive."); + if (column < 0 || column > 3) + throw new ArgumentOutOfRangeException("column", "Rows and columns for matrices run from 0 to 3, inclusive."); + + return this[(row * 4) + column]; + } + + set + { + if (row < 0 || row > 3) + throw new ArgumentOutOfRangeException("row", "Rows and columns for matrices run from 0 to 3, inclusive."); + if (column < 0 || column > 3) + throw new ArgumentOutOfRangeException("column", "Rows and columns for matrices run from 0 to 3, inclusive."); + + this[(row * 4) + column] = value; + } + } + + /// + /// Calculates the determinant of the matrix. + /// + /// The determinant of the matrix. + public float Determinant() + { + float temp1 = (M33 * M44) - (M34 * M43); + float temp2 = (M32 * M44) - (M34 * M42); + float temp3 = (M32 * M43) - (M33 * M42); + float temp4 = (M31 * M44) - (M34 * M41); + float temp5 = (M31 * M43) - (M33 * M41); + float temp6 = (M31 * M42) - (M32 * M41); + + return ((((M11 * (((M22 * temp1) - (M23 * temp2)) + (M24 * temp3))) - (M12 * (((M21 * temp1) - + (M23 * temp4)) + (M24 * temp5)))) + (M13 * (((M21 * temp2) - (M22 * temp4)) + (M24 * temp6)))) - + (M14 * (((M21 * temp3) - (M22 * temp5)) + (M23 * temp6)))); + } + + /// + /// Inverts the matrix. + /// + public void Invert() + { + Invert(ref this, out this); + } + + /// + /// Transposes the matrix. + /// + public void Transpose() + { + Transpose(ref this, out this); + } + + /// + /// Orthogonalizes the specified matrix. + /// + /// + /// Orthogonalization is the process of making all rows orthogonal to each other. This + /// means that any given row in the matrix will be orthogonal to any other given row in the + /// matrix. + /// Because this method uses the modified Gram-Schmidt process, the resulting matrix + /// tends to be numerically unstable. The numeric stability decreases according to the rows + /// so that the first row is the most stable and the last row is the least stable. + /// This operation is performed on the rows of the matrix rather than the columns. + /// If you wish for this operation to be performed on the columns, first transpose the + /// input and than transpose the output. + /// + public void Orthogonalize() + { + Orthogonalize(ref this, out this); + } + + /// + /// Orthonormalizes the specified matrix. + /// + /// + /// Orthonormalization is the process of making all rows and columns orthogonal to each + /// other and making all rows and columns of unit length. This means that any given row will + /// be orthogonal to any other given row and any given column will be orthogonal to any other + /// given column. Any given row will not be orthogonal to any given column. Every row and every + /// column will be of unit length. + /// Because this method uses the modified Gram-Schmidt process, the resulting matrix + /// tends to be numerically unstable. The numeric stability decreases according to the rows + /// so that the first row is the most stable and the last row is the least stable. + /// This operation is performed on the rows of the matrix rather than the columns. + /// If you wish for this operation to be performed on the columns, first transpose the + /// input and than transpose the output. + /// + public void Orthonormalize() + { + Orthonormalize(ref this, out this); + } + + /// + /// Decomposes a matrix into an orthonormalized matrix Q and a right triangular matrix R. + /// + /// When the method completes, contains the orthonormalized matrix of the decomposition. + /// When the method completes, contains the right triangular matrix of the decomposition. + public void DecomposeQR(out Matrix Q, out Matrix R) + { + Matrix temp = this; + temp.Transpose(); + Orthonormalize(ref temp, out Q); + Q.Transpose(); + + R = new Matrix(); + R.M11 = Vector4.Dot(Q.Column1, Column1); + R.M12 = Vector4.Dot(Q.Column1, Column2); + R.M13 = Vector4.Dot(Q.Column1, Column3); + R.M14 = Vector4.Dot(Q.Column1, Column4); + + R.M22 = Vector4.Dot(Q.Column2, Column2); + R.M23 = Vector4.Dot(Q.Column2, Column3); + R.M24 = Vector4.Dot(Q.Column2, Column4); + + R.M33 = Vector4.Dot(Q.Column3, Column3); + R.M34 = Vector4.Dot(Q.Column3, Column4); + + R.M44 = Vector4.Dot(Q.Column4, Column4); + } + + /// + /// Decomposes a matrix into a lower triangular matrix L and an orthonormalized matrix Q. + /// + /// When the method completes, contains the lower triangular matrix of the decomposition. + /// When the method completes, contains the orthonormalized matrix of the decomposition. + public void DecomposeLQ(out Matrix L, out Matrix Q) + { + Orthonormalize(ref this, out Q); + + L = new Matrix(); + L.M11 = Vector4.Dot(Q.Row1, Row1); + + L.M21 = Vector4.Dot(Q.Row1, Row2); + L.M22 = Vector4.Dot(Q.Row2, Row2); + + L.M31 = Vector4.Dot(Q.Row1, Row3); + L.M32 = Vector4.Dot(Q.Row2, Row3); + L.M33 = Vector4.Dot(Q.Row3, Row3); + + L.M41 = Vector4.Dot(Q.Row1, Row4); + L.M42 = Vector4.Dot(Q.Row2, Row4); + L.M43 = Vector4.Dot(Q.Row3, Row4); + L.M44 = Vector4.Dot(Q.Row4, Row4); + } + + /// + /// Decomposes a matrix into a scale, rotation, and translation. + /// + /// When the method completes, contains the scaling component of the decomposed matrix. + /// When the method completes, contains the rotation component of the decomposed matrix. + /// When the method completes, contains the translation component of the decomposed matrix. + /// + /// This method is designed to decompose an SRT transformation matrix only. + /// + public bool Decompose(out Vector3 scale, out Quaternion rotation, out Vector3 translation) + { + //Source: Unknown + //References: http://www.gamedev.net/community/forums/topic.asp?topic_id=441695 + + //Get the translation. + translation.X = this.M41; + translation.Y = this.M42; + translation.Z = this.M43; + + //Scaling is the length of the rows. + scale.X = (float)Math.Sqrt((M11 * M11) + (M12 * M12) + (M13 * M13)); + scale.Y = (float)Math.Sqrt((M21 * M21) + (M22 * M22) + (M23 * M23)); + scale.Z = (float)Math.Sqrt((M31 * M31) + (M32 * M32) + (M33 * M33)); + + //If any of the scaling factors are zero, than the rotation matrix can not exist. + if (MathUtil.IsZero(scale.X) || + MathUtil.IsZero(scale.Y) || + MathUtil.IsZero(scale.Z)) + { + rotation = Quaternion.Identity; + return false; + } + + //The rotation is the left over matrix after dividing out the scaling. + Matrix rotationmatrix = new Matrix(); + rotationmatrix.M11 = M11 / scale.X; + rotationmatrix.M12 = M12 / scale.X; + rotationmatrix.M13 = M13 / scale.X; + + rotationmatrix.M21 = M21 / scale.Y; + rotationmatrix.M22 = M22 / scale.Y; + rotationmatrix.M23 = M23 / scale.Y; + + rotationmatrix.M31 = M31 / scale.Z; + rotationmatrix.M32 = M32 / scale.Z; + rotationmatrix.M33 = M33 / scale.Z; + + rotationmatrix.M44 = 1f; + + Quaternion.RotationMatrix(ref rotationmatrix, out rotation); + return true; + } + + /// + /// Decomposes a uniform scale matrix into a scale, rotation, and translation. + /// A uniform scale matrix has the same scale in every axis. + /// + /// When the method completes, contains the scaling component of the decomposed matrix. + /// When the method completes, contains the rotation component of the decomposed matrix. + /// When the method completes, contains the translation component of the decomposed matrix. + /// + /// This method is designed to decompose only an SRT transformation matrix that has the same scale in every axis. + /// + public bool DecomposeUniformScale(out float scale, out Quaternion rotation, out Vector3 translation) + { + //Get the translation. + translation.X = this.M41; + translation.Y = this.M42; + translation.Z = this.M43; + + //Scaling is the length of the rows. ( just take one row since this is a uniform matrix) + scale = (float)Math.Sqrt((M11 * M11) + (M12 * M12) + (M13 * M13)); + var inv_scale = 1f / scale; + + //If any of the scaling factors are zero, then the rotation matrix can not exist. + if (Math.Abs(scale) < MathUtil.ZeroTolerance) + { + rotation = Quaternion.Identity; + return false; + } + + //The rotation is the left over matrix after dividing out the scaling. + Matrix rotationmatrix = new Matrix(); + rotationmatrix.M11 = M11 * inv_scale; + rotationmatrix.M12 = M12 * inv_scale; + rotationmatrix.M13 = M13 * inv_scale; + + rotationmatrix.M21 = M21 * inv_scale; + rotationmatrix.M22 = M22 * inv_scale; + rotationmatrix.M23 = M23 * inv_scale; + + rotationmatrix.M31 = M31 * inv_scale; + rotationmatrix.M32 = M32 * inv_scale; + rotationmatrix.M33 = M33 * inv_scale; + + rotationmatrix.M44 = 1f; + + Quaternion.RotationMatrix(ref rotationmatrix, out rotation); + return true; + } + + /// + /// Exchanges two rows in the matrix. + /// + /// The first row to exchange. This is an index of the row starting at zero. + /// The second row to exchange. This is an index of the row starting at zero. + public void ExchangeRows(int firstRow, int secondRow) + { + if (firstRow < 0) + throw new ArgumentOutOfRangeException("firstRow", "The parameter firstRow must be greater than or equal to zero."); + if (firstRow > 3) + throw new ArgumentOutOfRangeException("firstRow", "The parameter firstRow must be less than or equal to three."); + if (secondRow < 0) + throw new ArgumentOutOfRangeException("secondRow", "The parameter secondRow must be greater than or equal to zero."); + if (secondRow > 3) + throw new ArgumentOutOfRangeException("secondRow", "The parameter secondRow must be less than or equal to three."); + + if (firstRow == secondRow) + return; + + float temp0 = this[secondRow, 0]; + float temp1 = this[secondRow, 1]; + float temp2 = this[secondRow, 2]; + float temp3 = this[secondRow, 3]; + + this[secondRow, 0] = this[firstRow, 0]; + this[secondRow, 1] = this[firstRow, 1]; + this[secondRow, 2] = this[firstRow, 2]; + this[secondRow, 3] = this[firstRow, 3]; + + this[firstRow, 0] = temp0; + this[firstRow, 1] = temp1; + this[firstRow, 2] = temp2; + this[firstRow, 3] = temp3; + } + + /// + /// Exchanges two columns in the matrix. + /// + /// The first column to exchange. This is an index of the column starting at zero. + /// The second column to exchange. This is an index of the column starting at zero. + public void ExchangeColumns(int firstColumn, int secondColumn) + { + if (firstColumn < 0) + throw new ArgumentOutOfRangeException("firstColumn", "The parameter firstColumn must be greater than or equal to zero."); + if (firstColumn > 3) + throw new ArgumentOutOfRangeException("firstColumn", "The parameter firstColumn must be less than or equal to three."); + if (secondColumn < 0) + throw new ArgumentOutOfRangeException("secondColumn", "The parameter secondColumn must be greater than or equal to zero."); + if (secondColumn > 3) + throw new ArgumentOutOfRangeException("secondColumn", "The parameter secondColumn must be less than or equal to three."); + + if (firstColumn == secondColumn) + return; + + float temp0 = this[0, secondColumn]; + float temp1 = this[1, secondColumn]; + float temp2 = this[2, secondColumn]; + float temp3 = this[3, secondColumn]; + + this[0, secondColumn] = this[0, firstColumn]; + this[1, secondColumn] = this[1, firstColumn]; + this[2, secondColumn] = this[2, firstColumn]; + this[3, secondColumn] = this[3, firstColumn]; + + this[0, firstColumn] = temp0; + this[1, firstColumn] = temp1; + this[2, firstColumn] = temp2; + this[3, firstColumn] = temp3; + } + + /// + /// Creates an array containing the elements of the matrix. + /// + /// A sixteen-element array containing the components of the matrix. + public float[] ToArray() + { + return new[] { M11, M12, M13, M14, M21, M22, M23, M24, M31, M32, M33, M34, M41, M42, M43, M44 }; + } + + /// + /// Determines the sum of two matrices. + /// + /// The first matrix to add. + /// The second matrix to add. + /// When the method completes, contains the sum of the two matrices. + public static void Add(ref Matrix left, ref Matrix right, out Matrix result) + { + result.M11 = left.M11 + right.M11; + result.M12 = left.M12 + right.M12; + result.M13 = left.M13 + right.M13; + result.M14 = left.M14 + right.M14; + result.M21 = left.M21 + right.M21; + result.M22 = left.M22 + right.M22; + result.M23 = left.M23 + right.M23; + result.M24 = left.M24 + right.M24; + result.M31 = left.M31 + right.M31; + result.M32 = left.M32 + right.M32; + result.M33 = left.M33 + right.M33; + result.M34 = left.M34 + right.M34; + result.M41 = left.M41 + right.M41; + result.M42 = left.M42 + right.M42; + result.M43 = left.M43 + right.M43; + result.M44 = left.M44 + right.M44; + } + + /// + /// Determines the sum of two matrices. + /// + /// The first matrix to add. + /// The second matrix to add. + /// The sum of the two matrices. + public static Matrix Add(Matrix left, Matrix right) + { + Matrix result; + Add(ref left, ref right, out result); + return result; + } + + /// + /// Determines the difference between two matrices. + /// + /// The first matrix to subtract. + /// The second matrix to subtract. + /// When the method completes, contains the difference between the two matrices. + public static void Subtract(ref Matrix left, ref Matrix right, out Matrix result) + { + result.M11 = left.M11 - right.M11; + result.M12 = left.M12 - right.M12; + result.M13 = left.M13 - right.M13; + result.M14 = left.M14 - right.M14; + result.M21 = left.M21 - right.M21; + result.M22 = left.M22 - right.M22; + result.M23 = left.M23 - right.M23; + result.M24 = left.M24 - right.M24; + result.M31 = left.M31 - right.M31; + result.M32 = left.M32 - right.M32; + result.M33 = left.M33 - right.M33; + result.M34 = left.M34 - right.M34; + result.M41 = left.M41 - right.M41; + result.M42 = left.M42 - right.M42; + result.M43 = left.M43 - right.M43; + result.M44 = left.M44 - right.M44; + } + + /// + /// Determines the difference between two matrices. + /// + /// The first matrix to subtract. + /// The second matrix to subtract. + /// The difference between the two matrices. + public static Matrix Subtract(Matrix left, Matrix right) + { + Matrix result; + Subtract(ref left, ref right, out result); + return result; + } + + /// + /// Scales a matrix by the given value. + /// + /// The matrix to scale. + /// The amount by which to scale. + /// When the method completes, contains the scaled matrix. + public static void Multiply(ref Matrix left, float right, out Matrix result) + { + result.M11 = left.M11 * right; + result.M12 = left.M12 * right; + result.M13 = left.M13 * right; + result.M14 = left.M14 * right; + result.M21 = left.M21 * right; + result.M22 = left.M22 * right; + result.M23 = left.M23 * right; + result.M24 = left.M24 * right; + result.M31 = left.M31 * right; + result.M32 = left.M32 * right; + result.M33 = left.M33 * right; + result.M34 = left.M34 * right; + result.M41 = left.M41 * right; + result.M42 = left.M42 * right; + result.M43 = left.M43 * right; + result.M44 = left.M44 * right; + } + + /// + /// Scales a matrix by the given value. + /// + /// The matrix to scale. + /// The amount by which to scale. + /// The scaled matrix. + public static Matrix Multiply(Matrix left, float right) + { + Matrix result; + Multiply(ref left, right, out result); + return result; + } + + /// + /// Determines the product of two matrices. + /// + /// The first matrix to multiply. + /// The second matrix to multiply. + /// The product of the two matrices. + public static void Multiply(ref Matrix left, ref Matrix right, out Matrix result) + { + Matrix temp = new Matrix(); + temp.M11 = (left.M11 * right.M11) + (left.M12 * right.M21) + (left.M13 * right.M31) + (left.M14 * right.M41); + temp.M12 = (left.M11 * right.M12) + (left.M12 * right.M22) + (left.M13 * right.M32) + (left.M14 * right.M42); + temp.M13 = (left.M11 * right.M13) + (left.M12 * right.M23) + (left.M13 * right.M33) + (left.M14 * right.M43); + temp.M14 = (left.M11 * right.M14) + (left.M12 * right.M24) + (left.M13 * right.M34) + (left.M14 * right.M44); + temp.M21 = (left.M21 * right.M11) + (left.M22 * right.M21) + (left.M23 * right.M31) + (left.M24 * right.M41); + temp.M22 = (left.M21 * right.M12) + (left.M22 * right.M22) + (left.M23 * right.M32) + (left.M24 * right.M42); + temp.M23 = (left.M21 * right.M13) + (left.M22 * right.M23) + (left.M23 * right.M33) + (left.M24 * right.M43); + temp.M24 = (left.M21 * right.M14) + (left.M22 * right.M24) + (left.M23 * right.M34) + (left.M24 * right.M44); + temp.M31 = (left.M31 * right.M11) + (left.M32 * right.M21) + (left.M33 * right.M31) + (left.M34 * right.M41); + temp.M32 = (left.M31 * right.M12) + (left.M32 * right.M22) + (left.M33 * right.M32) + (left.M34 * right.M42); + temp.M33 = (left.M31 * right.M13) + (left.M32 * right.M23) + (left.M33 * right.M33) + (left.M34 * right.M43); + temp.M34 = (left.M31 * right.M14) + (left.M32 * right.M24) + (left.M33 * right.M34) + (left.M34 * right.M44); + temp.M41 = (left.M41 * right.M11) + (left.M42 * right.M21) + (left.M43 * right.M31) + (left.M44 * right.M41); + temp.M42 = (left.M41 * right.M12) + (left.M42 * right.M22) + (left.M43 * right.M32) + (left.M44 * right.M42); + temp.M43 = (left.M41 * right.M13) + (left.M42 * right.M23) + (left.M43 * right.M33) + (left.M44 * right.M43); + temp.M44 = (left.M41 * right.M14) + (left.M42 * right.M24) + (left.M43 * right.M34) + (left.M44 * right.M44); + result = temp; + } + + /// + /// Determines the product of two matrices. + /// + /// The first matrix to multiply. + /// The second matrix to multiply. + /// The product of the two matrices. + public static Matrix Multiply(Matrix left, Matrix right) + { + Matrix result; + Multiply(ref left, ref right, out result); + return result; + } + + /// + /// Scales a matrix by the given value. + /// + /// The matrix to scale. + /// The amount by which to scale. + /// When the method completes, contains the scaled matrix. + public static void Divide(ref Matrix left, float right, out Matrix result) + { + float inv = 1.0f / right; + + result.M11 = left.M11 * inv; + result.M12 = left.M12 * inv; + result.M13 = left.M13 * inv; + result.M14 = left.M14 * inv; + result.M21 = left.M21 * inv; + result.M22 = left.M22 * inv; + result.M23 = left.M23 * inv; + result.M24 = left.M24 * inv; + result.M31 = left.M31 * inv; + result.M32 = left.M32 * inv; + result.M33 = left.M33 * inv; + result.M34 = left.M34 * inv; + result.M41 = left.M41 * inv; + result.M42 = left.M42 * inv; + result.M43 = left.M43 * inv; + result.M44 = left.M44 * inv; + } + + /// + /// Scales a matrix by the given value. + /// + /// The matrix to scale. + /// The amount by which to scale. + /// The scaled matrix. + public static Matrix Divide(Matrix left, float right) + { + Matrix result; + Divide(ref left, right, out result); + return result; + } + + /// + /// Determines the quotient of two matrices. + /// + /// The first matrix to divide. + /// The second matrix to divide. + /// When the method completes, contains the quotient of the two matrices. + public static void Divide(ref Matrix left, ref Matrix right, out Matrix result) + { + result.M11 = left.M11 / right.M11; + result.M12 = left.M12 / right.M12; + result.M13 = left.M13 / right.M13; + result.M14 = left.M14 / right.M14; + result.M21 = left.M21 / right.M21; + result.M22 = left.M22 / right.M22; + result.M23 = left.M23 / right.M23; + result.M24 = left.M24 / right.M24; + result.M31 = left.M31 / right.M31; + result.M32 = left.M32 / right.M32; + result.M33 = left.M33 / right.M33; + result.M34 = left.M34 / right.M34; + result.M41 = left.M41 / right.M41; + result.M42 = left.M42 / right.M42; + result.M43 = left.M43 / right.M43; + result.M44 = left.M44 / right.M44; + } + + /// + /// Determines the quotient of two matrices. + /// + /// The first matrix to divide. + /// The second matrix to divide. + /// The quotient of the two matrices. + public static Matrix Divide(Matrix left, Matrix right) + { + Matrix result; + Divide(ref left, ref right, out result); + return result; + } + + /// + /// Performs the exponential operation on a matrix. + /// + /// The matrix to perform the operation on. + /// The exponent to raise the matrix to. + /// When the method completes, contains the exponential matrix. + /// Thrown when the is negative. + public static void Exponent(ref Matrix value, int exponent, out Matrix result) + { + //Source: http://rosettacode.org + //Reference: http://rosettacode.org/wiki/Matrix-exponentiation_operator + + if (exponent < 0) + throw new ArgumentOutOfRangeException("exponent", "The exponent can not be negative."); + + if (exponent == 0) + { + result = Matrix.Identity; + return; + } + + if (exponent == 1) + { + result = value; + return; + } + + Matrix identity = Matrix.Identity; + Matrix temp = value; + + while (true) + { + if ((exponent & 1) != 0) + identity = identity * temp; + + exponent /= 2; + + if (exponent > 0) + temp *= temp; + else + break; + } + + result = identity; + } + + /// + /// Performs the exponential operation on a matrix. + /// + /// The matrix to perform the operation on. + /// The exponent to raise the matrix to. + /// The exponential matrix. + /// Thrown when the is negative. + public static Matrix Exponent(Matrix value, int exponent) + { + Matrix result; + Exponent(ref value, exponent, out result); + return result; + } + + /// + /// Negates a matrix. + /// + /// The matrix to be negated. + /// When the method completes, contains the negated matrix. + public static void Negate(ref Matrix value, out Matrix result) + { + result.M11 = -value.M11; + result.M12 = -value.M12; + result.M13 = -value.M13; + result.M14 = -value.M14; + result.M21 = -value.M21; + result.M22 = -value.M22; + result.M23 = -value.M23; + result.M24 = -value.M24; + result.M31 = -value.M31; + result.M32 = -value.M32; + result.M33 = -value.M33; + result.M34 = -value.M34; + result.M41 = -value.M41; + result.M42 = -value.M42; + result.M43 = -value.M43; + result.M44 = -value.M44; + } + + /// + /// Negates a matrix. + /// + /// The matrix to be negated. + /// The negated matrix. + public static Matrix Negate(Matrix value) + { + Matrix result; + Negate(ref value, out result); + return result; + } + + /// + /// Performs a linear interpolation between two matrices. + /// + /// Start matrix. + /// End matrix. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the linear interpolation of the two matrices. + /// + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static void Lerp(ref Matrix start, ref Matrix end, float amount, out Matrix result) + { + result.M11 = MathUtil.Lerp(start.M11, end.M11, amount); + result.M12 = MathUtil.Lerp(start.M12, end.M12, amount); + result.M13 = MathUtil.Lerp(start.M13, end.M13, amount); + result.M14 = MathUtil.Lerp(start.M14, end.M14, amount); + result.M21 = MathUtil.Lerp(start.M21, end.M21, amount); + result.M22 = MathUtil.Lerp(start.M22, end.M22, amount); + result.M23 = MathUtil.Lerp(start.M23, end.M23, amount); + result.M24 = MathUtil.Lerp(start.M24, end.M24, amount); + result.M31 = MathUtil.Lerp(start.M31, end.M31, amount); + result.M32 = MathUtil.Lerp(start.M32, end.M32, amount); + result.M33 = MathUtil.Lerp(start.M33, end.M33, amount); + result.M34 = MathUtil.Lerp(start.M34, end.M34, amount); + result.M41 = MathUtil.Lerp(start.M41, end.M41, amount); + result.M42 = MathUtil.Lerp(start.M42, end.M42, amount); + result.M43 = MathUtil.Lerp(start.M43, end.M43, amount); + result.M44 = MathUtil.Lerp(start.M44, end.M44, amount); + } + + /// + /// Performs a linear interpolation between two matrices. + /// + /// Start matrix. + /// End matrix. + /// Value between 0 and 1 indicating the weight of . + /// The linear interpolation of the two matrices. + /// + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static Matrix Lerp(Matrix start, Matrix end, float amount) + { + Matrix result; + Lerp(ref start, ref end, amount, out result); + return result; + } + + /// + /// Performs a cubic interpolation between two matrices. + /// + /// Start matrix. + /// End matrix. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the cubic interpolation of the two matrices. + public static void SmoothStep(ref Matrix start, ref Matrix end, float amount, out Matrix result) + { + amount = MathUtil.SmoothStep(amount); + Lerp(ref start, ref end, amount, out result); + } + + /// + /// Performs a cubic interpolation between two matrices. + /// + /// Start matrix. + /// End matrix. + /// Value between 0 and 1 indicating the weight of . + /// The cubic interpolation of the two matrices. + public static Matrix SmoothStep(Matrix start, Matrix end, float amount) + { + Matrix result; + SmoothStep(ref start, ref end, amount, out result); + return result; + } + + /// + /// Calculates the transpose of the specified matrix. + /// + /// The matrix whose transpose is to be calculated. + /// When the method completes, contains the transpose of the specified matrix. + public static void Transpose(ref Matrix value, out Matrix result) + { + Matrix temp = new Matrix(); + temp.M11 = value.M11; + temp.M12 = value.M21; + temp.M13 = value.M31; + temp.M14 = value.M41; + temp.M21 = value.M12; + temp.M22 = value.M22; + temp.M23 = value.M32; + temp.M24 = value.M42; + temp.M31 = value.M13; + temp.M32 = value.M23; + temp.M33 = value.M33; + temp.M34 = value.M43; + temp.M41 = value.M14; + temp.M42 = value.M24; + temp.M43 = value.M34; + temp.M44 = value.M44; + + result = temp; + } + + /// + /// Calculates the transpose of the specified matrix. + /// + /// The matrix whose transpose is to be calculated. + /// When the method completes, contains the transpose of the specified matrix. + public static void TransposeByRef(ref Matrix value, ref Matrix result) + { + result.M11 = value.M11; + result.M12 = value.M21; + result.M13 = value.M31; + result.M14 = value.M41; + result.M21 = value.M12; + result.M22 = value.M22; + result.M23 = value.M32; + result.M24 = value.M42; + result.M31 = value.M13; + result.M32 = value.M23; + result.M33 = value.M33; + result.M34 = value.M43; + result.M41 = value.M14; + result.M42 = value.M24; + result.M43 = value.M34; + result.M44 = value.M44; + } + + /// + /// Calculates the transpose of the specified matrix. + /// + /// The matrix whose transpose is to be calculated. + /// The transpose of the specified matrix. + public static Matrix Transpose(Matrix value) + { + Matrix result; + Transpose(ref value, out result); + return result; + } + + /// + /// Calculates the inverse of the specified matrix. + /// + /// The matrix whose inverse is to be calculated. + /// When the method completes, contains the inverse of the specified matrix. + public static void Invert(ref Matrix value, out Matrix result) + { + float b0 = (value.M31 * value.M42) - (value.M32 * value.M41); + float b1 = (value.M31 * value.M43) - (value.M33 * value.M41); + float b2 = (value.M34 * value.M41) - (value.M31 * value.M44); + float b3 = (value.M32 * value.M43) - (value.M33 * value.M42); + float b4 = (value.M34 * value.M42) - (value.M32 * value.M44); + float b5 = (value.M33 * value.M44) - (value.M34 * value.M43); + + float d11 = value.M22 * b5 + value.M23 * b4 + value.M24 * b3; + float d12 = value.M21 * b5 + value.M23 * b2 + value.M24 * b1; + float d13 = value.M21 * -b4 + value.M22 * b2 + value.M24 * b0; + float d14 = value.M21 * b3 + value.M22 * -b1 + value.M23 * b0; + + float det = value.M11 * d11 - value.M12 * d12 + value.M13 * d13 - value.M14 * d14; + if (Math.Abs(det) == 0.0f) + { + result = Matrix.Zero; + return; + } + + det = 1f / det; + + float a0 = (value.M11 * value.M22) - (value.M12 * value.M21); + float a1 = (value.M11 * value.M23) - (value.M13 * value.M21); + float a2 = (value.M14 * value.M21) - (value.M11 * value.M24); + float a3 = (value.M12 * value.M23) - (value.M13 * value.M22); + float a4 = (value.M14 * value.M22) - (value.M12 * value.M24); + float a5 = (value.M13 * value.M24) - (value.M14 * value.M23); + + float d21 = value.M12 * b5 + value.M13 * b4 + value.M14 * b3; + float d22 = value.M11 * b5 + value.M13 * b2 + value.M14 * b1; + float d23 = value.M11 * -b4 + value.M12 * b2 + value.M14 * b0; + float d24 = value.M11 * b3 + value.M12 * -b1 + value.M13 * b0; + + float d31 = value.M42 * a5 + value.M43 * a4 + value.M44 * a3; + float d32 = value.M41 * a5 + value.M43 * a2 + value.M44 * a1; + float d33 = value.M41 * -a4 + value.M42 * a2 + value.M44 * a0; + float d34 = value.M41 * a3 + value.M42 * -a1 + value.M43 * a0; + + float d41 = value.M32 * a5 + value.M33 * a4 + value.M34 * a3; + float d42 = value.M31 * a5 + value.M33 * a2 + value.M34 * a1; + float d43 = value.M31 * -a4 + value.M32 * a2 + value.M34 * a0; + float d44 = value.M31 * a3 + value.M32 * -a1 + value.M33 * a0; + + result.M11 = +d11 * det; result.M12 = -d21 * det; result.M13 = +d31 * det; result.M14 = -d41 * det; + result.M21 = -d12 * det; result.M22 = +d22 * det; result.M23 = -d32 * det; result.M24 = +d42 * det; + result.M31 = +d13 * det; result.M32 = -d23 * det; result.M33 = +d33 * det; result.M34 = -d43 * det; + result.M41 = -d14 * det; result.M42 = +d24 * det; result.M43 = -d34 * det; result.M44 = +d44 * det; + } + + /// + /// Calculates the inverse of the specified matrix. + /// + /// The matrix whose inverse is to be calculated. + /// The inverse of the specified matrix. + public static Matrix Invert(Matrix value) + { + value.Invert(); + return value; + } + + /// + /// Orthogonalizes the specified matrix. + /// + /// The matrix to orthogonalize. + /// When the method completes, contains the orthogonalized matrix. + /// + /// Orthogonalization is the process of making all rows orthogonal to each other. This + /// means that any given row in the matrix will be orthogonal to any other given row in the + /// matrix. + /// Because this method uses the modified Gram-Schmidt process, the resulting matrix + /// tends to be numerically unstable. The numeric stability decreases according to the rows + /// so that the first row is the most stable and the last row is the least stable. + /// This operation is performed on the rows of the matrix rather than the columns. + /// If you wish for this operation to be performed on the columns, first transpose the + /// input and than transpose the output. + /// + public static void Orthogonalize(ref Matrix value, out Matrix result) + { + //Uses the modified Gram-Schmidt process. + //q1 = m1 + //q2 = m2 - ((q1 ⋅ m2) / (q1 ⋅ q1)) * q1 + //q3 = m3 - ((q1 ⋅ m3) / (q1 ⋅ q1)) * q1 - ((q2 ⋅ m3) / (q2 ⋅ q2)) * q2 + //q4 = m4 - ((q1 ⋅ m4) / (q1 ⋅ q1)) * q1 - ((q2 ⋅ m4) / (q2 ⋅ q2)) * q2 - ((q3 ⋅ m4) / (q3 ⋅ q3)) * q3 + + //By separating the above algorithm into multiple lines, we actually increase accuracy. + result = value; + + result.Row2 = result.Row2 - (Vector4.Dot(result.Row1, result.Row2) / Vector4.Dot(result.Row1, result.Row1)) * result.Row1; + + result.Row3 = result.Row3 - (Vector4.Dot(result.Row1, result.Row3) / Vector4.Dot(result.Row1, result.Row1)) * result.Row1; + result.Row3 = result.Row3 - (Vector4.Dot(result.Row2, result.Row3) / Vector4.Dot(result.Row2, result.Row2)) * result.Row2; + + result.Row4 = result.Row4 - (Vector4.Dot(result.Row1, result.Row4) / Vector4.Dot(result.Row1, result.Row1)) * result.Row1; + result.Row4 = result.Row4 - (Vector4.Dot(result.Row2, result.Row4) / Vector4.Dot(result.Row2, result.Row2)) * result.Row2; + result.Row4 = result.Row4 - (Vector4.Dot(result.Row3, result.Row4) / Vector4.Dot(result.Row3, result.Row3)) * result.Row3; + } + + /// + /// Orthogonalizes the specified matrix. + /// + /// The matrix to orthogonalize. + /// The orthogonalized matrix. + /// + /// Orthogonalization is the process of making all rows orthogonal to each other. This + /// means that any given row in the matrix will be orthogonal to any other given row in the + /// matrix. + /// Because this method uses the modified Gram-Schmidt process, the resulting matrix + /// tends to be numerically unstable. The numeric stability decreases according to the rows + /// so that the first row is the most stable and the last row is the least stable. + /// This operation is performed on the rows of the matrix rather than the columns. + /// If you wish for this operation to be performed on the columns, first transpose the + /// input and than transpose the output. + /// + public static Matrix Orthogonalize(Matrix value) + { + Matrix result; + Orthogonalize(ref value, out result); + return result; + } + + /// + /// Orthonormalizes the specified matrix. + /// + /// The matrix to orthonormalize. + /// When the method completes, contains the orthonormalized matrix. + /// + /// Orthonormalization is the process of making all rows and columns orthogonal to each + /// other and making all rows and columns of unit length. This means that any given row will + /// be orthogonal to any other given row and any given column will be orthogonal to any other + /// given column. Any given row will not be orthogonal to any given column. Every row and every + /// column will be of unit length. + /// Because this method uses the modified Gram-Schmidt process, the resulting matrix + /// tends to be numerically unstable. The numeric stability decreases according to the rows + /// so that the first row is the most stable and the last row is the least stable. + /// This operation is performed on the rows of the matrix rather than the columns. + /// If you wish for this operation to be performed on the columns, first transpose the + /// input and than transpose the output. + /// + public static void Orthonormalize(ref Matrix value, out Matrix result) + { + //Uses the modified Gram-Schmidt process. + //Because we are making unit vectors, we can optimize the math for orthonormalization + //and simplify the projection operation to remove the division. + //q1 = m1 / |m1| + //q2 = (m2 - (q1 ⋅ m2) * q1) / |m2 - (q1 ⋅ m2) * q1| + //q3 = (m3 - (q1 ⋅ m3) * q1 - (q2 ⋅ m3) * q2) / |m3 - (q1 ⋅ m3) * q1 - (q2 ⋅ m3) * q2| + //q4 = (m4 - (q1 ⋅ m4) * q1 - (q2 ⋅ m4) * q2 - (q3 ⋅ m4) * q3) / |m4 - (q1 ⋅ m4) * q1 - (q2 ⋅ m4) * q2 - (q3 ⋅ m4) * q3| + + //By separating the above algorithm into multiple lines, we actually increase accuracy. + result = value; + + result.Row1 = Vector4.Normalize(result.Row1); + + result.Row2 = result.Row2 - Vector4.Dot(result.Row1, result.Row2) * result.Row1; + result.Row2 = Vector4.Normalize(result.Row2); + + result.Row3 = result.Row3 - Vector4.Dot(result.Row1, result.Row3) * result.Row1; + result.Row3 = result.Row3 - Vector4.Dot(result.Row2, result.Row3) * result.Row2; + result.Row3 = Vector4.Normalize(result.Row3); + + result.Row4 = result.Row4 - Vector4.Dot(result.Row1, result.Row4) * result.Row1; + result.Row4 = result.Row4 - Vector4.Dot(result.Row2, result.Row4) * result.Row2; + result.Row4 = result.Row4 - Vector4.Dot(result.Row3, result.Row4) * result.Row3; + result.Row4 = Vector4.Normalize(result.Row4); + } + + /// + /// Orthonormalizes the specified matrix. + /// + /// The matrix to orthonormalize. + /// The orthonormalized matrix. + /// + /// Orthonormalization is the process of making all rows and columns orthogonal to each + /// other and making all rows and columns of unit length. This means that any given row will + /// be orthogonal to any other given row and any given column will be orthogonal to any other + /// given column. Any given row will not be orthogonal to any given column. Every row and every + /// column will be of unit length. + /// Because this method uses the modified Gram-Schmidt process, the resulting matrix + /// tends to be numerically unstable. The numeric stability decreases according to the rows + /// so that the first row is the most stable and the last row is the least stable. + /// This operation is performed on the rows of the matrix rather than the columns. + /// If you wish for this operation to be performed on the columns, first transpose the + /// input and than transpose the output. + /// + public static Matrix Orthonormalize(Matrix value) + { + Matrix result; + Orthonormalize(ref value, out result); + return result; + } + + /// + /// Brings the matrix into upper triangular form using elementary row operations. + /// + /// The matrix to put into upper triangular form. + /// When the method completes, contains the upper triangular matrix. + /// + /// If the matrix is not invertible (i.e. its determinant is zero) than the result of this + /// method may produce Single.Nan and Single.Inf values. When the matrix represents a system + /// of linear equations, than this often means that either no solution exists or an infinite + /// number of solutions exist. + /// + public static void UpperTriangularForm(ref Matrix value, out Matrix result) + { + //Adapted from the row echelon code. + result = value; + int lead = 0; + int rowcount = 4; + int columncount = 4; + + for (int r = 0; r < rowcount; ++r) + { + if (columncount <= lead) + return; + + int i = r; + + while (MathUtil.IsZero(result[i, lead])) + { + i++; + + if (i == rowcount) + { + i = r; + lead++; + + if (lead == columncount) + return; + } + } + + if (i != r) + { + result.ExchangeRows(i, r); + } + + float multiplier = 1f / result[r, lead]; + + for (; i < rowcount; ++i) + { + if (i != r) + { + result[i, 0] -= result[r, 0] * multiplier * result[i, lead]; + result[i, 1] -= result[r, 1] * multiplier * result[i, lead]; + result[i, 2] -= result[r, 2] * multiplier * result[i, lead]; + result[i, 3] -= result[r, 3] * multiplier * result[i, lead]; + } + } + + lead++; + } + } + + /// + /// Brings the matrix into upper triangular form using elementary row operations. + /// + /// The matrix to put into upper triangular form. + /// The upper triangular matrix. + /// + /// If the matrix is not invertible (i.e. its determinant is zero) than the result of this + /// method may produce Single.Nan and Single.Inf values. When the matrix represents a system + /// of linear equations, than this often means that either no solution exists or an infinite + /// number of solutions exist. + /// + public static Matrix UpperTriangularForm(Matrix value) + { + Matrix result; + UpperTriangularForm(ref value, out result); + return result; + } + + /// + /// Brings the matrix into lower triangular form using elementary row operations. + /// + /// The matrix to put into lower triangular form. + /// When the method completes, contains the lower triangular matrix. + /// + /// If the matrix is not invertible (i.e. its determinant is zero) than the result of this + /// method may produce Single.Nan and Single.Inf values. When the matrix represents a system + /// of linear equations, than this often means that either no solution exists or an infinite + /// number of solutions exist. + /// + public static void LowerTriangularForm(ref Matrix value, out Matrix result) + { + //Adapted from the row echelon code. + Matrix temp = value; + Matrix.Transpose(ref temp, out result); + + int lead = 0; + int rowcount = 4; + int columncount = 4; + + for (int r = 0; r < rowcount; ++r) + { + if (columncount <= lead) + return; + + int i = r; + + while (MathUtil.IsZero(result[i, lead])) + { + i++; + + if (i == rowcount) + { + i = r; + lead++; + + if (lead == columncount) + return; + } + } + + if (i != r) + { + result.ExchangeRows(i, r); + } + + float multiplier = 1f / result[r, lead]; + + for (; i < rowcount; ++i) + { + if (i != r) + { + result[i, 0] -= result[r, 0] * multiplier * result[i, lead]; + result[i, 1] -= result[r, 1] * multiplier * result[i, lead]; + result[i, 2] -= result[r, 2] * multiplier * result[i, lead]; + result[i, 3] -= result[r, 3] * multiplier * result[i, lead]; + } + } + + lead++; + } + + Matrix.Transpose(ref result, out result); + } + + /// + /// Brings the matrix into lower triangular form using elementary row operations. + /// + /// The matrix to put into lower triangular form. + /// The lower triangular matrix. + /// + /// If the matrix is not invertible (i.e. its determinant is zero) than the result of this + /// method may produce Single.Nan and Single.Inf values. When the matrix represents a system + /// of linear equations, than this often means that either no solution exists or an infinite + /// number of solutions exist. + /// + public static Matrix LowerTriangularForm(Matrix value) + { + Matrix result; + LowerTriangularForm(ref value, out result); + return result; + } + + /// + /// Brings the matrix into row echelon form using elementary row operations; + /// + /// The matrix to put into row echelon form. + /// When the method completes, contains the row echelon form of the matrix. + public static void RowEchelonForm(ref Matrix value, out Matrix result) + { + //Source: Wikipedia pseudo code + //Reference: http://en.wikipedia.org/wiki/Row_echelon_form#Pseudocode + + result = value; + int lead = 0; + int rowcount = 4; + int columncount = 4; + + for (int r = 0; r < rowcount; ++r) + { + if (columncount <= lead) + return; + + int i = r; + + while (MathUtil.IsZero(result[i, lead])) + { + i++; + + if (i == rowcount) + { + i = r; + lead++; + + if (lead == columncount) + return; + } + } + + if (i != r) + { + result.ExchangeRows(i, r); + } + + float multiplier = 1f / result[r, lead]; + result[r, 0] *= multiplier; + result[r, 1] *= multiplier; + result[r, 2] *= multiplier; + result[r, 3] *= multiplier; + + for (; i < rowcount; ++i) + { + if (i != r) + { + result[i, 0] -= result[r, 0] * result[i, lead]; + result[i, 1] -= result[r, 1] * result[i, lead]; + result[i, 2] -= result[r, 2] * result[i, lead]; + result[i, 3] -= result[r, 3] * result[i, lead]; + } + } + + lead++; + } + } + + /// + /// Brings the matrix into row echelon form using elementary row operations; + /// + /// The matrix to put into row echelon form. + /// When the method completes, contains the row echelon form of the matrix. + public static Matrix RowEchelonForm(Matrix value) + { + Matrix result; + RowEchelonForm(ref value, out result); + return result; + } + + /// + /// Brings the matrix into reduced row echelon form using elementary row operations. + /// + /// The matrix to put into reduced row echelon form. + /// The fifth column of the matrix. + /// When the method completes, contains the resultant matrix after the operation. + /// When the method completes, contains the resultant fifth column of the matrix. + /// + /// The fifth column is often called the augmented part of the matrix. This is because the fifth + /// column is really just an extension of the matrix so that there is a place to put all of the + /// non-zero components after the operation is complete. + /// Often times the resultant matrix will the identity matrix or a matrix similar to the identity + /// matrix. Sometimes, however, that is not possible and numbers other than zero and one may appear. + /// This method can be used to solve systems of linear equations. Upon completion of this method, + /// the will contain the solution for the system. It is up to the user + /// to analyze both the input and the result to determine if a solution really exists. + /// + public static void ReducedRowEchelonForm(ref Matrix value, ref Vector4 augment, out Matrix result, out Vector4 augmentResult) + { + //Source: http://rosettacode.org + //Reference: http://rosettacode.org/wiki/Reduced_row_echelon_form + + float[,] matrix = new float[4, 5]; + + matrix[0, 0] = value[0, 0]; + matrix[0, 1] = value[0, 1]; + matrix[0, 2] = value[0, 2]; + matrix[0, 3] = value[0, 3]; + matrix[0, 4] = augment[0]; + + matrix[1, 0] = value[1, 0]; + matrix[1, 1] = value[1, 1]; + matrix[1, 2] = value[1, 2]; + matrix[1, 3] = value[1, 3]; + matrix[1, 4] = augment[1]; + + matrix[2, 0] = value[2, 0]; + matrix[2, 1] = value[2, 1]; + matrix[2, 2] = value[2, 2]; + matrix[2, 3] = value[2, 3]; + matrix[2, 4] = augment[2]; + + matrix[3, 0] = value[3, 0]; + matrix[3, 1] = value[3, 1]; + matrix[3, 2] = value[3, 2]; + matrix[3, 3] = value[3, 3]; + matrix[3, 4] = augment[3]; + + int lead = 0; + int rowcount = 4; + int columncount = 5; + + for (int r = 0; r < rowcount; r++) + { + if (columncount <= lead) + break; + + int i = r; + + while (matrix[i, lead] == 0) + { + i++; + + if (i == rowcount) + { + i = r; + lead++; + + if (columncount == lead) + break; + } + } + + for (int j = 0; j < columncount; j++) + { + float temp = matrix[r, j]; + matrix[r, j] = matrix[i, j]; + matrix[i, j] = temp; + } + + float div = matrix[r, lead]; + + for (int j = 0; j < columncount; j++) + { + matrix[r, j] /= div; + } + + for (int j = 0; j < rowcount; j++) + { + if (j != r) + { + float sub = matrix[j, lead]; + for (int k = 0; k < columncount; k++) matrix[j, k] -= (sub * matrix[r, k]); + } + } + + lead++; + } + + result.M11 = matrix[0, 0]; + result.M12 = matrix[0, 1]; + result.M13 = matrix[0, 2]; + result.M14 = matrix[0, 3]; + + result.M21 = matrix[1, 0]; + result.M22 = matrix[1, 1]; + result.M23 = matrix[1, 2]; + result.M24 = matrix[1, 3]; + + result.M31 = matrix[2, 0]; + result.M32 = matrix[2, 1]; + result.M33 = matrix[2, 2]; + result.M34 = matrix[2, 3]; + + result.M41 = matrix[3, 0]; + result.M42 = matrix[3, 1]; + result.M43 = matrix[3, 2]; + result.M44 = matrix[3, 3]; + + augmentResult.X = matrix[0, 4]; + augmentResult.Y = matrix[1, 4]; + augmentResult.Z = matrix[2, 4]; + augmentResult.W = matrix[3, 4]; + } + + /// + /// Creates a left-handed spherical billboard that rotates around a specified object position. + /// + /// The position of the object around which the billboard will rotate. + /// The position of the camera. + /// The up vector of the camera. + /// The forward vector of the camera. + /// When the method completes, contains the created billboard matrix. + public static void BillboardLH(ref Vector3 objectPosition, ref Vector3 cameraPosition, ref Vector3 cameraUpVector, ref Vector3 cameraForwardVector, out Matrix result) + { + Vector3 crossed; + Vector3 final; + Vector3 difference = objectPosition - cameraPosition; + + float lengthSq = difference.LengthSquared(); + if (MathUtil.IsZero(lengthSq)) + difference = -cameraForwardVector; + else + difference *= (float)(1.0 / Math.Sqrt(lengthSq)); + + Vector3.Cross(ref cameraUpVector, ref difference, out crossed); + crossed.Normalize(); + Vector3.Cross(ref difference, ref crossed, out final); + + result.M11 = crossed.X; + result.M12 = crossed.Y; + result.M13 = crossed.Z; + result.M14 = 0.0f; + result.M21 = final.X; + result.M22 = final.Y; + result.M23 = final.Z; + result.M24 = 0.0f; + result.M31 = difference.X; + result.M32 = difference.Y; + result.M33 = difference.Z; + result.M34 = 0.0f; + result.M41 = objectPosition.X; + result.M42 = objectPosition.Y; + result.M43 = objectPosition.Z; + result.M44 = 1.0f; + } + + /// + /// Creates a left-handed spherical billboard that rotates around a specified object position. + /// + /// The position of the object around which the billboard will rotate. + /// The position of the camera. + /// The up vector of the camera. + /// The forward vector of the camera. + /// The created billboard matrix. + public static Matrix BillboardLH(Vector3 objectPosition, Vector3 cameraPosition, Vector3 cameraUpVector, Vector3 cameraForwardVector) + { + Matrix result; + BillboardLH(ref objectPosition, ref cameraPosition, ref cameraUpVector, ref cameraForwardVector, out result); + return result; + } + + /// + /// Creates a right-handed spherical billboard that rotates around a specified object position. + /// + /// The position of the object around which the billboard will rotate. + /// The position of the camera. + /// The up vector of the camera. + /// The forward vector of the camera. + /// When the method completes, contains the created billboard matrix. + public static void BillboardRH(ref Vector3 objectPosition, ref Vector3 cameraPosition, ref Vector3 cameraUpVector, ref Vector3 cameraForwardVector, out Matrix result) { + Vector3 crossed; + Vector3 final; + Vector3 difference = cameraPosition - objectPosition; + + float lengthSq = difference.LengthSquared(); + if (MathUtil.IsZero(lengthSq)) + difference = -cameraForwardVector; + else + difference *= (float)(1.0 / Math.Sqrt(lengthSq)); + + Vector3.Cross(ref cameraUpVector, ref difference, out crossed); + crossed.Normalize(); + Vector3.Cross(ref difference, ref crossed, out final); + + result.M11 = crossed.X; + result.M12 = crossed.Y; + result.M13 = crossed.Z; + result.M14 = 0.0f; + result.M21 = final.X; + result.M22 = final.Y; + result.M23 = final.Z; + result.M24 = 0.0f; + result.M31 = difference.X; + result.M32 = difference.Y; + result.M33 = difference.Z; + result.M34 = 0.0f; + result.M41 = objectPosition.X; + result.M42 = objectPosition.Y; + result.M43 = objectPosition.Z; + result.M44 = 1.0f; + } + + /// + /// Creates a right-handed spherical billboard that rotates around a specified object position. + /// + /// The position of the object around which the billboard will rotate. + /// The position of the camera. + /// The up vector of the camera. + /// The forward vector of the camera. + /// The created billboard matrix. + public static Matrix BillboardRH(Vector3 objectPosition, Vector3 cameraPosition, Vector3 cameraUpVector, Vector3 cameraForwardVector) { + Matrix result; + BillboardRH(ref objectPosition, ref cameraPosition, ref cameraUpVector, ref cameraForwardVector, out result); + return result; + } + + /// + /// Creates a left-handed, look-at matrix. + /// + /// The position of the viewer's eye. + /// The camera look-at target. + /// The camera's up vector. + /// When the method completes, contains the created look-at matrix. + public static void LookAtLH(ref Vector3 eye, ref Vector3 target, ref Vector3 up, out Matrix result) + { + Vector3 xaxis, yaxis, zaxis; + Vector3.Subtract(ref target, ref eye, out zaxis); zaxis.Normalize(); + Vector3.Cross(ref up, ref zaxis, out xaxis); xaxis.Normalize(); + Vector3.Cross(ref zaxis, ref xaxis, out yaxis); + + result = Matrix.Identity; + result.M11 = xaxis.X; result.M21 = xaxis.Y; result.M31 = xaxis.Z; + result.M12 = yaxis.X; result.M22 = yaxis.Y; result.M32 = yaxis.Z; + result.M13 = zaxis.X; result.M23 = zaxis.Y; result.M33 = zaxis.Z; + + Vector3.Dot(ref xaxis, ref eye, out result.M41); + Vector3.Dot(ref yaxis, ref eye, out result.M42); + Vector3.Dot(ref zaxis, ref eye, out result.M43); + + result.M41 = -result.M41; + result.M42 = -result.M42; + result.M43 = -result.M43; + } + + /// + /// Creates a left-handed, look-at matrix. + /// + /// The position of the viewer's eye. + /// The camera look-at target. + /// The camera's up vector. + /// The created look-at matrix. + public static Matrix LookAtLH(Vector3 eye, Vector3 target, Vector3 up) + { + Matrix result; + LookAtLH(ref eye, ref target, ref up, out result); + return result; + } + + /// + /// Creates a right-handed, look-at matrix. + /// + /// The position of the viewer's eye. + /// The camera look-at target. + /// The camera's up vector. + /// When the method completes, contains the created look-at matrix. + public static void LookAtRH(ref Vector3 eye, ref Vector3 target, ref Vector3 up, out Matrix result) + { + Vector3 xaxis, yaxis, zaxis; + Vector3.Subtract(ref eye, ref target, out zaxis); zaxis.Normalize(); + Vector3.Cross(ref up, ref zaxis, out xaxis); xaxis.Normalize(); + Vector3.Cross(ref zaxis, ref xaxis, out yaxis); + + result = Matrix.Identity; + result.M11 = xaxis.X; result.M21 = xaxis.Y; result.M31 = xaxis.Z; + result.M12 = yaxis.X; result.M22 = yaxis.Y; result.M32 = yaxis.Z; + result.M13 = zaxis.X; result.M23 = zaxis.Y; result.M33 = zaxis.Z; + + Vector3.Dot(ref xaxis, ref eye, out result.M41); + Vector3.Dot(ref yaxis, ref eye, out result.M42); + Vector3.Dot(ref zaxis, ref eye, out result.M43); + + result.M41 = -result.M41; + result.M42 = -result.M42; + result.M43 = -result.M43; + } + + /// + /// Creates a right-handed, look-at matrix. + /// + /// The position of the viewer's eye. + /// The camera look-at target. + /// The camera's up vector. + /// The created look-at matrix. + public static Matrix LookAtRH(Vector3 eye, Vector3 target, Vector3 up) + { + Matrix result; + LookAtRH(ref eye, ref target, ref up, out result); + return result; + } + + /// + /// Creates a left-handed, orthographic projection matrix. + /// + /// Width of the viewing volume. + /// Height of the viewing volume. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// When the method completes, contains the created projection matrix. + public static void OrthoLH(float width, float height, float znear, float zfar, out Matrix result) + { + float halfWidth = width * 0.5f; + float halfHeight = height * 0.5f; + + OrthoOffCenterLH(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out result); + } + + /// + /// Creates a left-handed, orthographic projection matrix. + /// + /// Width of the viewing volume. + /// Height of the viewing volume. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// The created projection matrix. + public static Matrix OrthoLH(float width, float height, float znear, float zfar) + { + Matrix result; + OrthoLH(width, height, znear, zfar, out result); + return result; + } + + /// + /// Creates a right-handed, orthographic projection matrix. + /// + /// Width of the viewing volume. + /// Height of the viewing volume. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// When the method completes, contains the created projection matrix. + public static void OrthoRH(float width, float height, float znear, float zfar, out Matrix result) + { + float halfWidth = width * 0.5f; + float halfHeight = height * 0.5f; + + OrthoOffCenterRH(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out result); + } + + /// + /// Creates a right-handed, orthographic projection matrix. + /// + /// Width of the viewing volume. + /// Height of the viewing volume. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// The created projection matrix. + public static Matrix OrthoRH(float width, float height, float znear, float zfar) + { + Matrix result; + OrthoRH(width, height, znear, zfar, out result); + return result; + } + + /// + /// Creates a left-handed, customized orthographic projection matrix. + /// + /// Minimum x-value of the viewing volume. + /// Maximum x-value of the viewing volume. + /// Minimum y-value of the viewing volume. + /// Maximum y-value of the viewing volume. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// When the method completes, contains the created projection matrix. + public static void OrthoOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result) + { + float zRange = 1.0f / (zfar - znear); + + result = Matrix.Identity; + result.M11 = 2.0f / (right - left); + result.M22 = 2.0f / (top - bottom); + result.M33 = zRange; + result.M41 = (left + right) / (left - right); + result.M42 = (top + bottom) / (bottom - top); + result.M43 = -znear * zRange; + } + + /// + /// Creates a left-handed, customized orthographic projection matrix. + /// + /// Minimum x-value of the viewing volume. + /// Maximum x-value of the viewing volume. + /// Minimum y-value of the viewing volume. + /// Maximum y-value of the viewing volume. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// The created projection matrix. + public static Matrix OrthoOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar) + { + Matrix result; + OrthoOffCenterLH(left, right, bottom, top, znear, zfar, out result); + return result; + } + + /// + /// Creates a right-handed, customized orthographic projection matrix. + /// + /// Minimum x-value of the viewing volume. + /// Maximum x-value of the viewing volume. + /// Minimum y-value of the viewing volume. + /// Maximum y-value of the viewing volume. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// When the method completes, contains the created projection matrix. + public static void OrthoOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result) + { + OrthoOffCenterLH(left, right, bottom, top, znear, zfar, out result); + result.M33 *= -1.0f; + } + + /// + /// Creates a right-handed, customized orthographic projection matrix. + /// + /// Minimum x-value of the viewing volume. + /// Maximum x-value of the viewing volume. + /// Minimum y-value of the viewing volume. + /// Maximum y-value of the viewing volume. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// The created projection matrix. + public static Matrix OrthoOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar) + { + Matrix result; + OrthoOffCenterRH(left, right, bottom, top, znear, zfar, out result); + return result; + } + + /// + /// Creates a left-handed, perspective projection matrix. + /// + /// Width of the viewing volume. + /// Height of the viewing volume. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// When the method completes, contains the created projection matrix. + public static void PerspectiveLH(float width, float height, float znear, float zfar, out Matrix result) + { + float halfWidth = width * 0.5f; + float halfHeight = height * 0.5f; + + PerspectiveOffCenterLH(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out result); + } + + /// + /// Creates a left-handed, perspective projection matrix. + /// + /// Width of the viewing volume. + /// Height of the viewing volume. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// The created projection matrix. + public static Matrix PerspectiveLH(float width, float height, float znear, float zfar) + { + Matrix result; + PerspectiveLH(width, height, znear, zfar, out result); + return result; + } + + /// + /// Creates a right-handed, perspective projection matrix. + /// + /// Width of the viewing volume. + /// Height of the viewing volume. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// When the method completes, contains the created projection matrix. + public static void PerspectiveRH(float width, float height, float znear, float zfar, out Matrix result) + { + float halfWidth = width * 0.5f; + float halfHeight = height * 0.5f; + + PerspectiveOffCenterRH(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out result); + } + + /// + /// Creates a right-handed, perspective projection matrix. + /// + /// Width of the viewing volume. + /// Height of the viewing volume. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// The created projection matrix. + public static Matrix PerspectiveRH(float width, float height, float znear, float zfar) + { + Matrix result; + PerspectiveRH(width, height, znear, zfar, out result); + return result; + } + + /// + /// Creates a left-handed, perspective projection matrix based on a field of view. + /// + /// Field of view in the y direction, in radians. + /// Aspect ratio, defined as view space width divided by height. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// When the method completes, contains the created projection matrix. + public static void PerspectiveFovLH(float fov, float aspect, float znear, float zfar, out Matrix result) + { + float yScale = (float)(1.0 / Math.Tan(fov * 0.5f)); + float xScale = yScale / aspect; + + float halfWidth = znear / xScale; + float halfHeight = znear / yScale; + + PerspectiveOffCenterLH(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out result); + } + + /// + /// Creates a left-handed, perspective projection matrix based on a field of view. + /// + /// Field of view in the y direction, in radians. + /// Aspect ratio, defined as view space width divided by height. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// The created projection matrix. + public static Matrix PerspectiveFovLH(float fov, float aspect, float znear, float zfar) + { + Matrix result; + PerspectiveFovLH(fov, aspect, znear, zfar, out result); + return result; + } + + /// + /// Creates a right-handed, perspective projection matrix based on a field of view. + /// + /// Field of view in the y direction, in radians. + /// Aspect ratio, defined as view space width divided by height. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// When the method completes, contains the created projection matrix. + public static void PerspectiveFovRH(float fov, float aspect, float znear, float zfar, out Matrix result) + { + float yScale = (float)(1.0 / Math.Tan(fov * 0.5f)); + float xScale = yScale / aspect; + + float halfWidth = znear / xScale; + float halfHeight = znear / yScale; + + PerspectiveOffCenterRH(-halfWidth, halfWidth, -halfHeight, halfHeight, znear, zfar, out result); + } + + /// + /// Creates a right-handed, perspective projection matrix based on a field of view. + /// + /// Field of view in the y direction, in radians. + /// Aspect ratio, defined as view space width divided by height. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// The created projection matrix. + public static Matrix PerspectiveFovRH(float fov, float aspect, float znear, float zfar) + { + Matrix result; + PerspectiveFovRH(fov, aspect, znear, zfar, out result); + return result; + } + + /// + /// Creates a left-handed, customized perspective projection matrix. + /// + /// Minimum x-value of the viewing volume. + /// Maximum x-value of the viewing volume. + /// Minimum y-value of the viewing volume. + /// Maximum y-value of the viewing volume. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// When the method completes, contains the created projection matrix. + public static void PerspectiveOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result) + { + float zRange = zfar / (zfar - znear); + + result = new Matrix(); + result.M11 = 2.0f * znear / (right - left); + result.M22 = 2.0f * znear / (top - bottom); + result.M31 = (left + right) / (left - right); + result.M32 = (top + bottom) / (bottom - top); + result.M33 = zRange; + result.M34 = 1.0f; + result.M43 = -znear * zRange; + } + + /// + /// Creates a left-handed, customized perspective projection matrix. + /// + /// Minimum x-value of the viewing volume. + /// Maximum x-value of the viewing volume. + /// Minimum y-value of the viewing volume. + /// Maximum y-value of the viewing volume. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// The created projection matrix. + public static Matrix PerspectiveOffCenterLH(float left, float right, float bottom, float top, float znear, float zfar) + { + Matrix result; + PerspectiveOffCenterLH(left, right, bottom, top, znear, zfar, out result); + return result; + } + + /// + /// Creates a right-handed, customized perspective projection matrix. + /// + /// Minimum x-value of the viewing volume. + /// Maximum x-value of the viewing volume. + /// Minimum y-value of the viewing volume. + /// Maximum y-value of the viewing volume. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// When the method completes, contains the created projection matrix. + public static void PerspectiveOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar, out Matrix result) + { + PerspectiveOffCenterLH(left, right, bottom, top, znear, zfar, out result); + result.M31 *= -1.0f; + result.M32 *= -1.0f; + result.M33 *= -1.0f; + result.M34 *= -1.0f; + } + + /// + /// Creates a right-handed, customized perspective projection matrix. + /// + /// Minimum x-value of the viewing volume. + /// Maximum x-value of the viewing volume. + /// Minimum y-value of the viewing volume. + /// Maximum y-value of the viewing volume. + /// Minimum z-value of the viewing volume. + /// Maximum z-value of the viewing volume. + /// The created projection matrix. + public static Matrix PerspectiveOffCenterRH(float left, float right, float bottom, float top, float znear, float zfar) + { + Matrix result; + PerspectiveOffCenterRH(left, right, bottom, top, znear, zfar, out result); + return result; + } + + + /// + /// Creates a matrix that scales along the x-axis, y-axis, and y-axis. + /// + /// Scaling factor for all three axes. + /// When the method completes, contains the created scaling matrix. + public static void Scaling(ref Vector3 scale, out Matrix result) + { + Scaling(scale.X, scale.Y, scale.Z, out result); + } + + /// + /// Creates a matrix that scales along the x-axis, y-axis, and y-axis. + /// + /// Scaling factor for all three axes. + /// The created scaling matrix. + public static Matrix Scaling(Vector3 scale) + { + Matrix result; + Scaling(ref scale, out result); + return result; + } + + /// + /// Creates a matrix that scales along the x-axis, y-axis, and y-axis. + /// + /// Scaling factor that is applied along the x-axis. + /// Scaling factor that is applied along the y-axis. + /// Scaling factor that is applied along the z-axis. + /// When the method completes, contains the created scaling matrix. + public static void Scaling(float x, float y, float z, out Matrix result) + { + result = Matrix.Identity; + result.M11 = x; + result.M22 = y; + result.M33 = z; + } + + /// + /// Creates a matrix that scales along the x-axis, y-axis, and y-axis. + /// + /// Scaling factor that is applied along the x-axis. + /// Scaling factor that is applied along the y-axis. + /// Scaling factor that is applied along the z-axis. + /// The created scaling matrix. + public static Matrix Scaling(float x, float y, float z) + { + Matrix result; + Scaling(x, y, z, out result); + return result; + } + + /// + /// Creates a matrix that uniformly scales along all three axis. + /// + /// The uniform scale that is applied along all axis. + /// When the method completes, contains the created scaling matrix. + public static void Scaling(float scale, out Matrix result) + { + result = Matrix.Identity; + result.M11 = result.M22 = result.M33 = scale; + } + + /// + /// Creates a matrix that uniformly scales along all three axis. + /// + /// The uniform scale that is applied along all axis. + /// The created scaling matrix. + public static Matrix Scaling(float scale) + { + Matrix result; + Scaling(scale, out result); + return result; + } + + /// + /// Creates a matrix that rotates around the x-axis. + /// + /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + /// When the method completes, contains the created rotation matrix. + public static void RotationX(float angle, out Matrix result) + { + float cos = (float)Math.Cos(angle); + float sin = (float)Math.Sin(angle); + + result = Matrix.Identity; + result.M22 = cos; + result.M23 = sin; + result.M32 = -sin; + result.M33 = cos; + } + + /// + /// Creates a matrix that rotates around the x-axis. + /// + /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + /// The created rotation matrix. + public static Matrix RotationX(float angle) + { + Matrix result; + RotationX(angle, out result); + return result; + } + + /// + /// Creates a matrix that rotates around the y-axis. + /// + /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + /// When the method completes, contains the created rotation matrix. + public static void RotationY(float angle, out Matrix result) + { + float cos = (float)Math.Cos(angle); + float sin = (float)Math.Sin(angle); + + result = Matrix.Identity; + result.M11 = cos; + result.M13 = -sin; + result.M31 = sin; + result.M33 = cos; + } + + /// + /// Creates a matrix that rotates around the y-axis. + /// + /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + /// The created rotation matrix. + public static Matrix RotationY(float angle) + { + Matrix result; + RotationY(angle, out result); + return result; + } + + /// + /// Creates a matrix that rotates around the z-axis. + /// + /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + /// When the method completes, contains the created rotation matrix. + public static void RotationZ(float angle, out Matrix result) + { + float cos = (float)Math.Cos(angle); + float sin = (float)Math.Sin(angle); + + result = Matrix.Identity; + result.M11 = cos; + result.M12 = sin; + result.M21 = -sin; + result.M22 = cos; + } + + /// + /// Creates a matrix that rotates around the z-axis. + /// + /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + /// The created rotation matrix. + public static Matrix RotationZ(float angle) + { + Matrix result; + RotationZ(angle, out result); + return result; + } + + /// + /// Creates a matrix that rotates around an arbitrary axis. + /// + /// The axis around which to rotate. This parameter is assumed to be normalized. + /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + /// When the method completes, contains the created rotation matrix. + public static void RotationAxis(ref Vector3 axis, float angle, out Matrix result) + { + float x = axis.X; + float y = axis.Y; + float z = axis.Z; + float cos = (float)Math.Cos(angle); + float sin = (float)Math.Sin(angle); + float xx = x * x; + float yy = y * y; + float zz = z * z; + float xy = x * y; + float xz = x * z; + float yz = y * z; + + result = Matrix.Identity; + result.M11 = xx + (cos * (1.0f - xx)); + result.M12 = (xy - (cos * xy)) + (sin * z); + result.M13 = (xz - (cos * xz)) - (sin * y); + result.M21 = (xy - (cos * xy)) - (sin * z); + result.M22 = yy + (cos * (1.0f - yy)); + result.M23 = (yz - (cos * yz)) + (sin * x); + result.M31 = (xz - (cos * xz)) + (sin * y); + result.M32 = (yz - (cos * yz)) - (sin * x); + result.M33 = zz + (cos * (1.0f - zz)); + } + + /// + /// Creates a matrix that rotates around an arbitrary axis. + /// + /// The axis around which to rotate. This parameter is assumed to be normalized. + /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + /// The created rotation matrix. + public static Matrix RotationAxis(Vector3 axis, float angle) + { + Matrix result; + RotationAxis(ref axis, angle, out result); + return result; + } + + /// + /// Creates a rotation matrix from a quaternion. + /// + /// The quaternion to use to build the matrix. + /// The created rotation matrix. + public static void RotationQuaternion(ref Quaternion rotation, out Matrix result) + { + float xx = rotation.X * rotation.X; + float yy = rotation.Y * rotation.Y; + float zz = rotation.Z * rotation.Z; + float xy = rotation.X * rotation.Y; + float zw = rotation.Z * rotation.W; + float zx = rotation.Z * rotation.X; + float yw = rotation.Y * rotation.W; + float yz = rotation.Y * rotation.Z; + float xw = rotation.X * rotation.W; + + result = Matrix.Identity; + result.M11 = 1.0f - (2.0f * (yy + zz)); + result.M12 = 2.0f * (xy + zw); + result.M13 = 2.0f * (zx - yw); + result.M21 = 2.0f * (xy - zw); + result.M22 = 1.0f - (2.0f * (zz + xx)); + result.M23 = 2.0f * (yz + xw); + result.M31 = 2.0f * (zx + yw); + result.M32 = 2.0f * (yz - xw); + result.M33 = 1.0f - (2.0f * (yy + xx)); + } + + /// + /// Creates a rotation matrix from a quaternion. + /// + /// The quaternion to use to build the matrix. + /// The created rotation matrix. + public static Matrix RotationQuaternion(Quaternion rotation) + { + Matrix result; + RotationQuaternion(ref rotation, out result); + return result; + } + + /// + /// Creates a rotation matrix with a specified yaw, pitch, and roll. + /// + /// Yaw around the y-axis, in radians. + /// Pitch around the x-axis, in radians. + /// Roll around the z-axis, in radians. + /// When the method completes, contains the created rotation matrix. + public static void RotationYawPitchRoll(float yaw, float pitch, float roll, out Matrix result) + { + Quaternion quaternion = new Quaternion(); + Quaternion.RotationYawPitchRoll(yaw, pitch, roll, out quaternion); + RotationQuaternion(ref quaternion, out result); + } + + /// + /// Creates a rotation matrix with a specified yaw, pitch, and roll. + /// + /// Yaw around the y-axis, in radians. + /// Pitch around the x-axis, in radians. + /// Roll around the z-axis, in radians. + /// The created rotation matrix. + public static Matrix RotationYawPitchRoll(float yaw, float pitch, float roll) + { + Matrix result; + RotationYawPitchRoll(yaw, pitch, roll, out result); + return result; + } + + /// + /// Creates a translation matrix using the specified offsets. + /// + /// The offset for all three coordinate planes. + /// When the method completes, contains the created translation matrix. + public static void Translation(ref Vector3 value, out Matrix result) + { + Translation(value.X, value.Y, value.Z, out result); + } + + /// + /// Creates a translation matrix using the specified offsets. + /// + /// The offset for all three coordinate planes. + /// The created translation matrix. + public static Matrix Translation(Vector3 value) + { + Matrix result; + Translation(ref value, out result); + return result; + } + + /// + /// Creates a translation matrix using the specified offsets. + /// + /// X-coordinate offset. + /// Y-coordinate offset. + /// Z-coordinate offset. + /// When the method completes, contains the created translation matrix. + public static void Translation(float x, float y, float z, out Matrix result) + { + result = Matrix.Identity; + result.M41 = x; + result.M42 = y; + result.M43 = z; + } + + /// + /// Creates a translation matrix using the specified offsets. + /// + /// X-coordinate offset. + /// Y-coordinate offset. + /// Z-coordinate offset. + /// The created translation matrix. + public static Matrix Translation(float x, float y, float z) + { + Matrix result; + Translation(x, y, z, out result); + return result; + } + + /// + /// Creates a skew/shear matrix by means of a translation vector, a rotation vector, and a rotation angle. + /// shearing is performed in the direction of translation vector, where translation vector and rotation vector define the shearing plane. + /// The effect is such that the skewed rotation vector has the specified angle with rotation itself. + /// + /// The rotation angle. + /// The rotation vector + /// The translation vector + /// Contains the created skew/shear matrix. + public static void Skew(float angle, ref Vector3 rotationVec, ref Vector3 transVec, out Matrix matrix) + { + //http://elckerlyc.ewi.utwente.nl/browser/Elckerlyc/Hmi/HmiMath/src/hmi/math/Mat3f.java + float MINIMAL_SKEW_ANGLE = 0.000001f; + + Vector3 e0 = rotationVec; + Vector3 e1 = Vector3.Normalize(transVec); + + float rv1; + Vector3.Dot(ref rotationVec, ref e1, out rv1); + e0 += rv1 * e1; + float rv0; + Vector3.Dot(ref rotationVec, ref e0, out rv0); + float cosa = (float)Math.Cos(angle); + float sina = (float)Math.Sin(angle); + float rr0 = rv0 * cosa - rv1 * sina; + float rr1 = rv0 * sina + rv1 * cosa; + + if (rr0 < MINIMAL_SKEW_ANGLE) + throw new ArgumentException("illegal skew angle"); + + float d = (rr1 / rr0) - (rv1 / rv0); + + matrix = Matrix.Identity; + matrix.M11 = d * e1[0] * e0[0] + 1.0f; + matrix.M12 = d * e1[0] * e0[1]; + matrix.M13 = d * e1[0] * e0[2]; + matrix.M21 = d * e1[1] * e0[0]; + matrix.M22 = d * e1[1] * e0[1] + 1.0f; + matrix.M23 = d * e1[1] * e0[2]; + matrix.M31 = d * e1[2] * e0[0]; + matrix.M32 = d * e1[2] * e0[1]; + matrix.M33 = d * e1[2] * e0[2] + 1.0f; + } + + /// + /// Creates a 3D affine transformation matrix. + /// + /// Scaling factor. + /// The rotation of the transformation. + /// The translation factor of the transformation. + /// When the method completes, contains the created affine transformation matrix. + public static void AffineTransformation(float scaling, ref Quaternion rotation, ref Vector3 translation, out Matrix result) + { + result = Scaling(scaling) * RotationQuaternion(rotation) * Translation(translation); + } + + /// + /// Creates a 3D affine transformation matrix. + /// + /// Scaling factor. + /// The rotation of the transformation. + /// The translation factor of the transformation. + /// The created affine transformation matrix. + public static Matrix AffineTransformation(float scaling, Quaternion rotation, Vector3 translation) + { + Matrix result; + AffineTransformation(scaling, ref rotation, ref translation, out result); + return result; + } + + /// + /// Creates a 3D affine transformation matrix. + /// + /// Scaling factor. + /// The center of the rotation. + /// The rotation of the transformation. + /// The translation factor of the transformation. + /// When the method completes, contains the created affine transformation matrix. + public static void AffineTransformation(float scaling, ref Vector3 rotationCenter, ref Quaternion rotation, ref Vector3 translation, out Matrix result) + { + result = Scaling(scaling) * Translation(-rotationCenter) * RotationQuaternion(rotation) * + Translation(rotationCenter) * Translation(translation); + } + + /// + /// Creates a 3D affine transformation matrix. + /// + /// Scaling factor. + /// The center of the rotation. + /// The rotation of the transformation. + /// The translation factor of the transformation. + /// The created affine transformation matrix. + public static Matrix AffineTransformation(float scaling, Vector3 rotationCenter, Quaternion rotation, Vector3 translation) + { + Matrix result; + AffineTransformation(scaling, ref rotationCenter, ref rotation, ref translation, out result); + return result; + } + + /// + /// Creates a 2D affine transformation matrix. + /// + /// Scaling factor. + /// The rotation of the transformation. + /// The translation factor of the transformation. + /// When the method completes, contains the created affine transformation matrix. + public static void AffineTransformation2D(float scaling, float rotation, ref Vector2 translation, out Matrix result) + { + result = Scaling(scaling, scaling, 1.0f) * RotationZ(rotation) * Translation((Vector3)translation); + } + + /// + /// Creates a 2D affine transformation matrix. + /// + /// Scaling factor. + /// The rotation of the transformation. + /// The translation factor of the transformation. + /// The created affine transformation matrix. + public static Matrix AffineTransformation2D(float scaling, float rotation, Vector2 translation) + { + Matrix result; + AffineTransformation2D(scaling, rotation, ref translation, out result); + return result; + } + + /// + /// Creates a 2D affine transformation matrix. + /// + /// Scaling factor. + /// The center of the rotation. + /// The rotation of the transformation. + /// The translation factor of the transformation. + /// When the method completes, contains the created affine transformation matrix. + public static void AffineTransformation2D(float scaling, ref Vector2 rotationCenter, float rotation, ref Vector2 translation, out Matrix result) + { + result = Scaling(scaling, scaling, 1.0f) * Translation((Vector3)(-rotationCenter)) * RotationZ(rotation) * + Translation((Vector3)rotationCenter) * Translation((Vector3)translation); + } + + /// + /// Creates a 2D affine transformation matrix. + /// + /// Scaling factor. + /// The center of the rotation. + /// The rotation of the transformation. + /// The translation factor of the transformation. + /// The created affine transformation matrix. + public static Matrix AffineTransformation2D(float scaling, Vector2 rotationCenter, float rotation, Vector2 translation) + { + Matrix result; + AffineTransformation2D(scaling, ref rotationCenter, rotation, ref translation, out result); + return result; + } + + /// + /// Creates a transformation matrix. + /// + /// Center point of the scaling operation. + /// Scaling rotation amount. + /// Scaling factor. + /// The center of the rotation. + /// The rotation of the transformation. + /// The translation factor of the transformation. + /// When the method completes, contains the created transformation matrix. + public static void Transformation(ref Vector3 scalingCenter, ref Quaternion scalingRotation, ref Vector3 scaling, ref Vector3 rotationCenter, ref Quaternion rotation, ref Vector3 translation, out Matrix result) + { + Matrix sr = RotationQuaternion(scalingRotation); + + result = Translation(-scalingCenter) * Transpose(sr) * Scaling(scaling) * sr * Translation(scalingCenter) * Translation(-rotationCenter) * + RotationQuaternion(rotation) * Translation(rotationCenter) * Translation(translation); + } + + /// + /// Creates a transformation matrix. + /// + /// Center point of the scaling operation. + /// Scaling rotation amount. + /// Scaling factor. + /// The center of the rotation. + /// The rotation of the transformation. + /// The translation factor of the transformation. + /// The created transformation matrix. + public static Matrix Transformation(Vector3 scalingCenter, Quaternion scalingRotation, Vector3 scaling, Vector3 rotationCenter, Quaternion rotation, Vector3 translation) + { + Matrix result; + Transformation(ref scalingCenter, ref scalingRotation, ref scaling, ref rotationCenter, ref rotation, ref translation, out result); + return result; + } + + /// + /// Creates a 2D transformation matrix. + /// + /// Center point of the scaling operation. + /// Scaling rotation amount. + /// Scaling factor. + /// The center of the rotation. + /// The rotation of the transformation. + /// The translation factor of the transformation. + /// When the method completes, contains the created transformation matrix. + public static void Transformation2D(ref Vector2 scalingCenter, float scalingRotation, ref Vector2 scaling, ref Vector2 rotationCenter, float rotation, ref Vector2 translation, out Matrix result) + { + result = Translation((Vector3)(-scalingCenter)) * RotationZ(-scalingRotation) * Scaling((Vector3)scaling) * RotationZ(scalingRotation) * Translation((Vector3)scalingCenter) * + Translation((Vector3)(-rotationCenter)) * RotationZ(rotation) * Translation((Vector3)rotationCenter) * Translation((Vector3)translation); + + result.M33 = 1f; + result.M44 = 1f; + } + + /// + /// Creates a 2D transformation matrix. + /// + /// Center point of the scaling operation. + /// Scaling rotation amount. + /// Scaling factor. + /// The center of the rotation. + /// The rotation of the transformation. + /// The translation factor of the transformation. + /// The created transformation matrix. + public static Matrix Transformation2D(Vector2 scalingCenter, float scalingRotation, Vector2 scaling, Vector2 rotationCenter, float rotation, Vector2 translation) + { + Matrix result; + Transformation2D(ref scalingCenter, scalingRotation, ref scaling, ref rotationCenter, rotation, ref translation, out result); + return result; + } + + /// + /// Adds two matrices. + /// + /// The first matrix to add. + /// The second matrix to add. + /// The sum of the two matrices. + public static Matrix operator +(Matrix left, Matrix right) + { + Matrix result; + Add(ref left, ref right, out result); + return result; + } + + /// + /// Assert a matrix (return it unchanged). + /// + /// The matrix to assert (unchanged). + /// The asserted (unchanged) matrix. + public static Matrix operator +(Matrix value) + { + return value; + } + + /// + /// Subtracts two matrices. + /// + /// The first matrix to subtract. + /// The second matrix to subtract. + /// The difference between the two matrices. + public static Matrix operator -(Matrix left, Matrix right) + { + Matrix result; + Subtract(ref left, ref right, out result); + return result; + } + + /// + /// Negates a matrix. + /// + /// The matrix to negate. + /// The negated matrix. + public static Matrix operator -(Matrix value) + { + Matrix result; + Negate(ref value, out result); + return result; + } + + /// + /// Scales a matrix by a given value. + /// + /// The matrix to scale. + /// The amount by which to scale. + /// The scaled matrix. + public static Matrix operator *(float left, Matrix right) + { + Matrix result; + Multiply(ref right, left, out result); + return result; + } + + /// + /// Scales a matrix by a given value. + /// + /// The matrix to scale. + /// The amount by which to scale. + /// The scaled matrix. + public static Matrix operator *(Matrix left, float right) + { + Matrix result; + Multiply(ref left, right, out result); + return result; + } + + /// + /// Multiplies two matrices. + /// + /// The first matrix to multiply. + /// The second matrix to multiply. + /// The product of the two matrices. + public static Matrix operator *(Matrix left, Matrix right) + { + Matrix result; + Multiply(ref left, ref right, out result); + return result; + } + + /// + /// Scales a matrix by a given value. + /// + /// The matrix to scale. + /// The amount by which to scale. + /// The scaled matrix. + public static Matrix operator /(Matrix left, float right) + { + Matrix result; + Divide(ref left, right, out result); + return result; + } + + /// + /// Divides two matrices. + /// + /// The first matrix to divide. + /// The second matrix to divide. + /// The quotient of the two matrices. + public static Matrix operator /(Matrix left, Matrix right) + { + Matrix result; + Divide(ref left, ref right, out result); + return result; + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has the same value as ; otherwise, false. + public static bool operator ==(Matrix left, Matrix right) + { + return left.Equals(ref right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has a different value than ; otherwise, false. + public static bool operator !=(Matrix left, Matrix right) + { + return !left.Equals(ref right); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return string.Format(CultureInfo.CurrentCulture, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M23:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}]", + M11, M12, M13, M14, M21, M22, M23, M24, M31, M32, M33, M34, M41, M42, M43, M44); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// + /// A that represents this instance. + /// + public string ToString(string format) + { + if (format == null) + return ToString(); + + return string.Format(format, CultureInfo.CurrentCulture, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M23:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}]", + M11.ToString(format, CultureInfo.CurrentCulture), M12.ToString(format, CultureInfo.CurrentCulture), M13.ToString(format, CultureInfo.CurrentCulture), M14.ToString(format, CultureInfo.CurrentCulture), + M21.ToString(format, CultureInfo.CurrentCulture), M22.ToString(format, CultureInfo.CurrentCulture), M23.ToString(format, CultureInfo.CurrentCulture), M24.ToString(format, CultureInfo.CurrentCulture), + M31.ToString(format, CultureInfo.CurrentCulture), M32.ToString(format, CultureInfo.CurrentCulture), M33.ToString(format, CultureInfo.CurrentCulture), M34.ToString(format, CultureInfo.CurrentCulture), + M41.ToString(format, CultureInfo.CurrentCulture), M42.ToString(format, CultureInfo.CurrentCulture), M43.ToString(format, CultureInfo.CurrentCulture), M44.ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format(formatProvider, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M23:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}]", + M11.ToString(formatProvider), M12.ToString(formatProvider), M13.ToString(formatProvider), M14.ToString(formatProvider), + M21.ToString(formatProvider), M22.ToString(formatProvider), M23.ToString(formatProvider), M24.ToString(formatProvider), + M31.ToString(formatProvider), M32.ToString(formatProvider), M33.ToString(formatProvider), M34.ToString(formatProvider), + M41.ToString(formatProvider), M42.ToString(formatProvider), M43.ToString(formatProvider), M44.ToString(formatProvider)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(string format, IFormatProvider formatProvider) + { + if (format == null) + return ToString(formatProvider); + + return string.Format(format, formatProvider, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M23:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}]", + M11.ToString(format, formatProvider), M12.ToString(format, formatProvider), M13.ToString(format, formatProvider), M14.ToString(format, formatProvider), + M21.ToString(format, formatProvider), M22.ToString(format, formatProvider), M23.ToString(format, formatProvider), M24.ToString(format, formatProvider), + M31.ToString(format, formatProvider), M32.ToString(format, formatProvider), M33.ToString(format, formatProvider), M34.ToString(format, formatProvider), + M41.ToString(format, formatProvider), M42.ToString(format, formatProvider), M43.ToString(format, formatProvider), M44.ToString(format, formatProvider)); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + unchecked + { + var hashCode = M11.GetHashCode(); + hashCode = (hashCode * 397) ^ M12.GetHashCode(); + hashCode = (hashCode * 397) ^ M13.GetHashCode(); + hashCode = (hashCode * 397) ^ M14.GetHashCode(); + hashCode = (hashCode * 397) ^ M21.GetHashCode(); + hashCode = (hashCode * 397) ^ M22.GetHashCode(); + hashCode = (hashCode * 397) ^ M23.GetHashCode(); + hashCode = (hashCode * 397) ^ M24.GetHashCode(); + hashCode = (hashCode * 397) ^ M31.GetHashCode(); + hashCode = (hashCode * 397) ^ M32.GetHashCode(); + hashCode = (hashCode * 397) ^ M33.GetHashCode(); + hashCode = (hashCode * 397) ^ M34.GetHashCode(); + hashCode = (hashCode * 397) ^ M41.GetHashCode(); + hashCode = (hashCode * 397) ^ M42.GetHashCode(); + hashCode = (hashCode * 397) ^ M43.GetHashCode(); + hashCode = (hashCode * 397) ^ M44.GetHashCode(); + return hashCode; + } + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(ref Matrix other) + { + return (MathUtil.NearEqual(other.M11, M11) && + MathUtil.NearEqual(other.M12, M12) && + MathUtil.NearEqual(other.M13, M13) && + MathUtil.NearEqual(other.M14, M14) && + MathUtil.NearEqual(other.M21, M21) && + MathUtil.NearEqual(other.M22, M22) && + MathUtil.NearEqual(other.M23, M23) && + MathUtil.NearEqual(other.M24, M24) && + MathUtil.NearEqual(other.M31, M31) && + MathUtil.NearEqual(other.M32, M32) && + MathUtil.NearEqual(other.M33, M33) && + MathUtil.NearEqual(other.M34, M34) && + MathUtil.NearEqual(other.M41, M41) && + MathUtil.NearEqual(other.M42, M42) && + MathUtil.NearEqual(other.M43, M43) && + MathUtil.NearEqual(other.M44, M44)); + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(Matrix other) + { + return Equals(ref other); + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object value) + { + if (!(value is Matrix)) + return false; + + var strongValue = (Matrix)value; + return Equals(ref strongValue); + } + +#if SlimDX1xInterop + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator SlimDX.Matrix(Matrix value) + { + return new SlimDX.Matrix() + { + M11 = value.M11, M12 = value.M12, M13 = value.M13, M14 = value.M14, + M21 = value.M21, M22 = value.M22, M23 = value.M23, M24 = value.M24, + M31 = value.M31, M32 = value.M32, M33 = value.M33, M34 = value.M34, + M41 = value.M41, M42 = value.M42, M43 = value.M43, M44 = value.M44 + }; + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Matrix(SlimDX.Matrix value) + { + return new Matrix() + { + M11 = value.M11, M12 = value.M12, M13 = value.M13, M14 = value.M14, + M21 = value.M21, M22 = value.M22, M23 = value.M23, M24 = value.M24, + M31 = value.M31, M32 = value.M32, M33 = value.M33, M34 = value.M34, + M41 = value.M41, M42 = value.M42, M43 = value.M43, M44 = value.M44 + }; + } +#endif + +#if WPFInterop + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator System.Windows.Media.Media3D.Matrix3D(Matrix value) + { + return new System.Windows.Media.Media3D.Matrix3D() + { + M11 = value.M11, M12 = value.M12, M13 = value.M13, M14 = value.M14, + M21 = value.M21, M22 = value.M22, M23 = value.M23, M24 = value.M24, + M31 = value.M31, M32 = value.M32, M33 = value.M33, M34 = value.M34, + OffsetX = value.M41, OffsetY = value.M42, OffsetZ = value.M43, M44 = value.M44 + }; + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Matrix(System.Windows.Media.Media3D.Matrix3D value) + { + return new Matrix() + { + M11 = (float)value.M11, M12 = (float)value.M12, M13 = (float)value.M13, M14 = (float)value.M14, + M21 = (float)value.M21, M22 = (float)value.M22, M23 = (float)value.M23, M24 = (float)value.M24, + M31 = (float)value.M31, M32 = (float)value.M32, M33 = (float)value.M33, M34 = (float)value.M34, + M41 = (float)value.OffsetX, M42 = (float)value.OffsetY, M43 = (float)value.OffsetZ, M44 = (float)value.M44 + }; + } +#endif + +#if XnaInterop + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Microsoft.Xna.Framework.Matrix(Matrix value) + { + return new Microsoft.Xna.Framework.Matrix() + { + M11 = value.M11, M12 = value.M12, M13 = value.M13, M14 = value.M14, + M21 = value.M21, M22 = value.M22, M23 = value.M23, M24 = value.M24, + M31 = value.M31, M32 = value.M32, M33 = value.M33, M34 = value.M34, + M41 = value.M41, M42 = value.M42, M43 = value.M43, M44 = value.M44 + }; + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Matrix(Microsoft.Xna.Framework.Matrix value) + { + return new Matrix() + { + M11 = value.M11, M12 = value.M12, M13 = value.M13, M14 = value.M14, + M21 = value.M21, M22 = value.M22, M23 = value.M23, M24 = value.M24, + M31 = value.M31, M32 = value.M32, M33 = value.M33, M34 = value.M34, + M41 = value.M41, M42 = value.M42, M43 = value.M43, M44 = value.M44 + }; + } +#endif + } +} diff --git a/Source/SharpDX/Matrix3x2.cs b/Source/SharpDX/Mathematics/Matrix3x2.cs similarity index 95% rename from Source/SharpDX/Matrix3x2.cs rename to Source/SharpDX/Mathematics/Matrix3x2.cs index f79155173..c1aed8755 100644 --- a/Source/SharpDX/Matrix3x2.cs +++ b/Source/SharpDX/Mathematics/Matrix3x2.cs @@ -1,1166 +1,1141 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE.using System; - -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Direct2D Matrix3x2. Supports implicit cast from . - /// - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct Matrix3x2 : IDataSerializable - { - /// - /// Gets the identity matrix. - /// - /// The identity matrix. - public readonly static Matrix3x2 Identity = new Matrix3x2(1, 0, 0, 1, 0, 0); - - /// - /// Element (1,1) - /// - public float M11; - - /// - /// Element (1,2) - /// - public float M12; - - /// - /// Element (2,1) - /// - public float M21; - - /// - /// Element (2,2) - /// - public float M22; - - /// - /// Element (3,1) - /// - public float M31; - - /// - /// Element (3,2) - /// - public float M32; - - /// - /// Initializes a new instance of the struct. - /// - /// The value that will be assigned to all components. - public Matrix3x2(float value) - { - M11 = M12 = - M21 = M22 = - M31 = M32 = value; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The value to assign at row 1 column 1 of the matrix. - /// The value to assign at row 1 column 2 of the matrix. - /// The value to assign at row 2 column 1 of the matrix. - /// The value to assign at row 2 column 2 of the matrix. - /// The value to assign at row 3 column 1 of the matrix. - /// The value to assign at row 3 column 2 of the matrix. - public Matrix3x2(float M11, float M12, float M21, float M22, float M31, float M32) - { - this.M11 = M11; this.M12 = M12; - this.M21 = M21; this.M22 = M22; - this.M31 = M31; this.M32 = M32; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The values to assign to the components of the matrix. This must be an array with six elements. - /// Thrown when is null. - /// Thrown when contains more or less than six elements. - public Matrix3x2(float[] values) - { - if (values == null) - throw new ArgumentNullException("values"); - if (values.Length != 6) - throw new ArgumentOutOfRangeException("values", "There must be six input values for Matrix3x2."); - - M11 = values[0]; - M12 = values[1]; - - M21 = values[2]; - M22 = values[3]; - - M31 = values[4]; - M32 = values[5]; - } - - /// - /// Gets or sets the first row in the matrix; that is M11 and M12. - /// - public Vector2 Row1 - { - get { return new Vector2(M11, M12); } - set { M11 = value.X; M12 = value.Y; } - } - - /// - /// Gets or sets the second row in the matrix; that is M21 and M22. - /// - public Vector2 Row2 - { - get { return new Vector2(M21, M22); } - set { M21 = value.X; M22 = value.Y; } - } - - /// - /// Gets or sets the third row in the matrix; that is M31 and M32. - /// - public Vector2 Row3 - { - get { return new Vector2(M31, M32); } - set { M31 = value.X; M32 = value.Y; } - } - - /// - /// Gets or sets the first column in the matrix; that is M11, M21, and M31. - /// - public Vector3 Column1 - { - get { return new Vector3(M11, M21, M31); } - set { M11 = value.X; M21 = value.Y; M31 = value.Z; } - } - - /// - /// Gets or sets the second column in the matrix; that is M12, M22, and M32. - /// - public Vector3 Column2 - { - get { return new Vector3(M12, M22, M32); } - set { M12 = value.X; M22 = value.Y; M32 = value.Z;} - } - - /// - /// Gets or sets the translation of the matrix; that is M31 and M32. - /// - public Vector2 TranslationVector - { - get { return new Vector2(M31, M32); } - set { M31 = value.X; M32 = value.Y; } - } - - /// - /// Gets or sets the scale of the matrix; that is M11 and M22. - /// - public Vector2 ScaleVector - { - get { return new Vector2(M11, M22); } - set { M11 = value.X; M22 = value.Y; } - } - - /// - /// Gets a value indicating whether this instance is an identity matrix. - /// - /// - /// true if this instance is an identity matrix; otherwise, false. - /// - public bool IsIdentity - { - get { return this.Equals(Identity); } - } - - /// - /// Gets or sets the component at the specified index. - /// - /// The value of the matrix component, depending on the index. - /// The zero-based index of the component to access. - /// The value of the component at the specified index. - /// Thrown when the is out of the range [0, 5]. - public float this[int index] - { - get - { - switch (index) - { - case 0: return M11; - case 1: return M12; - case 2: return M21; - case 3: return M22; - case 4: return M31; - case 5: return M32; - } - - throw new ArgumentOutOfRangeException("index", "Indices for Matrix3x2 run from 0 to 5, inclusive."); - } - - set - { - switch (index) - { - case 0: M11 = value; break; - case 1: M12 = value; break; - case 2: M21 = value; break; - case 3: M22 = value; break; - case 4: M31 = value; break; - case 5: M32 = value; break; - default: throw new ArgumentOutOfRangeException("index", "Indices for Matrix3x2 run from 0 to 5, inclusive."); - } - } - } - - /// - /// Gets or sets the component at the specified index. - /// - /// The value of the matrix component, depending on the index. - /// The row of the matrix to access. - /// The column of the matrix to access. - /// The value of the component at the specified index. - /// Thrown when the or is out of the range [0, 3]. - public float this[int row, int column] - { - get - { - if (row < 0 || row > 2) - throw new ArgumentOutOfRangeException("row", "Rows and columns for matrices run from 0 to 2, inclusive."); - if (column < 0 || column > 1) - throw new ArgumentOutOfRangeException("column", "Rows and columns for matrices run from 0 to 1, inclusive."); - - return this[(row * 2) + column]; - } - - set - { - if (row < 0 || row > 2) - throw new ArgumentOutOfRangeException("row", "Rows and columns for matrices run from 0 to 2, inclusive."); - if (column < 0 || column > 1) - throw new ArgumentOutOfRangeException("column", "Rows and columns for matrices run from 0 to 1, inclusive."); - - this[(row * 2) + column] = value; - } - } - - /// - /// Creates an array containing the elements of the matrix. - /// - /// A sixteen-element array containing the components of the matrix. - public float[] ToArray() - { - return new[] { M11, M12, M21, M22, M31, M32 }; - } - - /// - /// Determines the sum of two matrices. - /// - /// The first matrix to add. - /// The second matrix to add. - /// When the method completes, contains the sum of the two matrices. - public static void Add(ref Matrix3x2 left, ref Matrix3x2 right, out Matrix3x2 result) - { - result.M11 = left.M11 + right.M11; - result.M12 = left.M12 + right.M12; - result.M21 = left.M21 + right.M21; - result.M22 = left.M22 + right.M22; - result.M31 = left.M31 + right.M31; - result.M32 = left.M32 + right.M32; - } - - /// - /// Determines the sum of two matrices. - /// - /// The first matrix to add. - /// The second matrix to add. - /// The sum of the two matrices. - public static Matrix3x2 Add(Matrix3x2 left, Matrix3x2 right) - { - Matrix3x2 result; - Add(ref left, ref right, out result); - return result; - } - - /// - /// Determines the difference between two matrices. - /// - /// The first matrix to subtract. - /// The second matrix to subtract. - /// When the method completes, contains the difference between the two matrices. - public static void Subtract(ref Matrix3x2 left, ref Matrix3x2 right, out Matrix3x2 result) - { - result.M11 = left.M11 - right.M11; - result.M12 = left.M12 - right.M12; - result.M21 = left.M21 - right.M21; - result.M22 = left.M22 - right.M22; - result.M31 = left.M31 - right.M31; - result.M32 = left.M32 - right.M32; - } - - /// - /// Determines the difference between two matrices. - /// - /// The first matrix to subtract. - /// The second matrix to subtract. - /// The difference between the two matrices. - public static Matrix3x2 Subtract(Matrix3x2 left, Matrix3x2 right) - { - Matrix3x2 result; - Subtract(ref left, ref right, out result); - return result; - } - - /// - /// Scales a matrix by the given value. - /// - /// The matrix to scale. - /// The amount by which to scale. - /// When the method completes, contains the scaled matrix. - public static void Multiply(ref Matrix3x2 left, float right, out Matrix3x2 result) - { - result.M11 = left.M11 * right; - result.M12 = left.M12 * right; - result.M21 = left.M21 * right; - result.M22 = left.M22 * right; - result.M31 = left.M31 * right; - result.M32 = left.M32 * right; - } - - /// - /// Scales a matrix by the given value. - /// - /// The matrix to scale. - /// The amount by which to scale. - /// The scaled matrix. - public static Matrix3x2 Multiply(Matrix3x2 left, float right) - { - Matrix3x2 result; - Multiply(ref left, right, out result); - return result; - } - - /// - /// Determines the product of two matrices. - /// - /// The first matrix to multiply. - /// The second matrix to multiply. - /// The product of the two matrices. - public static void Multiply(ref Matrix3x2 left, ref Matrix3x2 right, out Matrix3x2 result) - { - result = new Matrix3x2(); - result.M11 = (left.M11 * right.M11) + (left.M12 * right.M21); - result.M12 = (left.M11 * right.M12) + (left.M12 * right.M22); - result.M21 = (left.M21 * right.M11) + (left.M22 * right.M21); - result.M22 = (left.M21 * right.M12) + (left.M22 * right.M22); - result.M31 = (left.M31 * right.M11) + (left.M32 * right.M21) + right.M31; - result.M32 = (left.M31 * right.M12) + (left.M32 * right.M22) + right.M32; - } - - /// - /// Determines the product of two matrices. - /// - /// The first matrix to multiply. - /// The second matrix to multiply. - /// The product of the two matrices. - public static Matrix3x2 Multiply(Matrix3x2 left, Matrix3x2 right) - { - Matrix3x2 result; - Multiply(ref left, ref right, out result); - return result; - } - - /// - /// Scales a matrix by the given value. - /// - /// The matrix to scale. - /// The amount by which to scale. - /// When the method completes, contains the scaled matrix. - public static void Divide(ref Matrix3x2 left, float right, out Matrix3x2 result) - { - float inv = 1.0f / right; - - result.M11 = left.M11 * inv; - result.M12 = left.M12 * inv; - result.M21 = left.M21 * inv; - result.M22 = left.M22 * inv; - result.M31 = left.M31 * inv; - result.M32 = left.M32 * inv; - } - - /// - /// Determines the quotient of two matrices. - /// - /// The first matrix to divide. - /// The second matrix to divide. - /// When the method completes, contains the quotient of the two matrices. - public static void Divide(ref Matrix3x2 left, ref Matrix3x2 right, out Matrix3x2 result) - { - result.M11 = left.M11 / right.M11; - result.M12 = left.M12 / right.M12; - result.M21 = left.M21 / right.M21; - result.M22 = left.M22 / right.M22; - result.M31 = left.M31 / right.M31; - result.M32 = left.M32 / right.M32; - } - - /// - /// Negates a matrix. - /// - /// The matrix to be negated. - /// When the method completes, contains the negated matrix. - public static void Negate(ref Matrix3x2 value, out Matrix3x2 result) - { - result.M11 = -value.M11; - result.M12 = -value.M12; - result.M21 = -value.M21; - result.M22 = -value.M22; - result.M31 = -value.M31; - result.M32 = -value.M32; - } - - /// - /// Negates a matrix. - /// - /// The matrix to be negated. - /// The negated matrix. - public static Matrix3x2 Negate(Matrix3x2 value) - { - Matrix3x2 result; - Negate(ref value, out result); - return result; - } - - /// - /// Performs a linear interpolation between two matrices. - /// - /// Start matrix. - /// End matrix. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the linear interpolation of the two matrices. - /// - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static void Lerp(ref Matrix3x2 start, ref Matrix3x2 end, float amount, out Matrix3x2 result) - { - result.M11 = MathUtil.Lerp(start.M11, end.M11, amount); - result.M12 = MathUtil.Lerp(start.M12, end.M12, amount); - result.M21 = MathUtil.Lerp(start.M21, end.M21, amount); - result.M22 = MathUtil.Lerp(start.M22, end.M22, amount); - result.M31 = MathUtil.Lerp(start.M31, end.M31, amount); - result.M32 = MathUtil.Lerp(start.M32, end.M32, amount); - } - - /// - /// Performs a linear interpolation between two matrices. - /// - /// Start matrix. - /// End matrix. - /// Value between 0 and 1 indicating the weight of . - /// The linear interpolation of the two matrices. - /// - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static Matrix3x2 Lerp(Matrix3x2 start, Matrix3x2 end, float amount) - { - Matrix3x2 result; - Lerp(ref start, ref end, amount, out result); - return result; - } - - /// - /// Performs a cubic interpolation between two matrices. - /// - /// Start matrix. - /// End matrix. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the cubic interpolation of the two matrices. - public static void SmoothStep(ref Matrix3x2 start, ref Matrix3x2 end, float amount, out Matrix3x2 result) - { - amount = MathUtil.SmoothStep(amount); - Lerp(ref start, ref end, amount, out result); - } - - /// - /// Performs a cubic interpolation between two matrices. - /// - /// Start matrix. - /// End matrix. - /// Value between 0 and 1 indicating the weight of . - /// The cubic interpolation of the two matrices. - public static Matrix3x2 SmoothStep(Matrix3x2 start, Matrix3x2 end, float amount) - { - Matrix3x2 result; - SmoothStep(ref start, ref end, amount, out result); - return result; - } - - /// - /// Creates a matrix that scales along the x-axis and y-axis. - /// - /// Scaling factor for both axes. - /// When the method completes, contains the created scaling matrix. - public static void Scaling(ref Vector2 scale, out Matrix3x2 result) - { - Scaling(scale.X, scale.Y, out result); - } - - /// - /// Creates a matrix that scales along the x-axis and y-axis. - /// - /// Scaling factor for both axes. - /// The created scaling matrix. - public static Matrix3x2 Scaling(Vector2 scale) - { - Matrix3x2 result; - Scaling(ref scale, out result); - return result; - } - - /// - /// Creates a matrix that scales along the x-axis and y-axis. - /// - /// Scaling factor that is applied along the x-axis. - /// Scaling factor that is applied along the y-axis. - /// When the method completes, contains the created scaling matrix. - public static void Scaling(float x, float y, out Matrix3x2 result) - { - result = Matrix3x2.Identity; - result.M11 = x; - result.M22 = y; - } - - /// - /// Creates a matrix that scales along the x-axis and y-axis. - /// - /// Scaling factor that is applied along the x-axis. - /// Scaling factor that is applied along the y-axis. - /// The created scaling matrix. - public static Matrix3x2 Scaling(float x, float y) - { - Matrix3x2 result; - Scaling(x, y, out result); - return result; - } - - /// - /// Creates a matrix that uniformly scales along both axes. - /// - /// The uniform scale that is applied along both axes. - /// When the method completes, contains the created scaling matrix. - public static void Scaling(float scale, out Matrix3x2 result) - { - result = Matrix3x2.Identity; - result.M11 = result.M22 = scale; - } - - /// - /// Creates a matrix that uniformly scales along both axes. - /// - /// The uniform scale that is applied along both axes. - /// The created scaling matrix. - public static Matrix3x2 Scaling(float scale) - { - Matrix3x2 result; - Scaling(scale, out result); - return result; - } - - /// - /// Creates a matrix that is scaling from a specified center. - /// - /// Scaling factor that is applied along the x-axis. - /// Scaling factor that is applied along the y-axis. - /// The center of the scaling. - /// The created scaling matrix. - public static Matrix3x2 Scaling(float x, float y, Vector2 center) - { - Matrix3x2 result; - - result.M11 = x; result.M12 = 0.0f; - result.M21 = 0.0f; result.M22 = y; - - result.M31 = center.X - (x * center.X); - result.M32 = center.Y - (y * center.Y); - - return result; - } - - /// - /// Creates a matrix that is scaling from a specified center. - /// - /// Scaling factor that is applied along the x-axis. - /// Scaling factor that is applied along the y-axis. - /// The center of the scaling. - /// The created scaling matrix. - public static void Scaling( float x, float y, ref Vector2 center, out Matrix3x2 result) - { - Matrix3x2 localResult; - - localResult.M11 = x; localResult.M12 = 0.0f; - localResult.M21 = 0.0f; localResult.M22 = y; - - localResult.M31 = center.X - (x * center.X); - localResult.M32 = center.Y - (y * center.Y); - - result = localResult; - } - - /// - /// Calculates the determinant of this matrix. - /// - /// Result of the determinant. - public float Determinant() - { - return (M11 * M22) - (M12 * M21); - } - - /// - /// Creates a matrix that rotates. - /// - /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis. - /// When the method completes, contains the created rotation matrix. - public static void Rotation(float angle, out Matrix3x2 result) - { - float cos = (float)Math.Cos(angle); - float sin = (float)Math.Sin(angle); - - result = Matrix3x2.Identity; - result.M11 = cos; - result.M12 = sin; - result.M21 = -sin; - result.M22 = cos; - } - - /// - /// Creates a matrix that rotates. - /// - /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis. - /// The created rotation matrix. - public static Matrix3x2 Rotation(float angle) - { - Matrix3x2 result; - Rotation(angle, out result); - return result; - } - - /// - /// Creates a matrix that rotates about a specified center. - /// - /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis. - /// The center of the rotation. - /// The created rotation matrix. - public static Matrix3x2 Rotation(float angle, Vector2 center) - { - Matrix3x2 result; - Rotation(angle, center, out result); - return result; - } - - /// - /// Creates a matrix that rotates about a specified center. - /// - /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis. - /// The center of the rotation. - /// When the method completes, contains the created rotation matrix. - public static void Rotation(float angle, Vector2 center, out Matrix3x2 result) - { - result = Translation(-center) * Rotation(angle) * Translation(center); - } - - /// - /// Creates a transformation matrix. - /// - /// Scaling factor that is applied along the x-axis. - /// Scaling factor that is applied along the y-axis. - /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis. - /// X-coordinate offset. - /// Y-coordinate offset. - /// When the method completes, contains the created transformation matrix. - public static void Transformation(float xScale, float yScale, float angle, float xOffset, float yOffset, out Matrix3x2 result) - { - result = Scaling(xScale, yScale) * Rotation(angle) * Translation(xOffset, yOffset); - } - - /// - /// Creates a transformation matrix. - /// - /// Scaling factor that is applied along the x-axis. - /// Scaling factor that is applied along the y-axis. - /// Angle of rotation in radians. - /// X-coordinate offset. - /// Y-coordinate offset. - /// The created transformation matrix. - public static Matrix3x2 Transformation(float xScale, float yScale, float angle, float xOffset, float yOffset) - { - Matrix3x2 result; - Transformation(xScale, yScale, angle, xOffset, yOffset, out result); - return result; - } - - /// - /// Creates a translation matrix using the specified offsets. - /// - /// The offset for both coordinate planes. - /// When the method completes, contains the created translation matrix. - public static void Translation(ref Vector2 value, out Matrix3x2 result) - { - Translation(value.X, value.Y, out result); - } - - /// - /// Creates a translation matrix using the specified offsets. - /// - /// The offset for both coordinate planes. - /// The created translation matrix. - public static Matrix3x2 Translation(Vector2 value) - { - Matrix3x2 result; - Translation(ref value, out result); - return result; - } - - /// - /// Creates a translation matrix using the specified offsets. - /// - /// X-coordinate offset. - /// Y-coordinate offset. - /// When the method completes, contains the created translation matrix. - public static void Translation(float x, float y, out Matrix3x2 result) - { - result = Matrix3x2.Identity; - result.M31 = x; - result.M32 = y; - } - - /// - /// Creates a translation matrix using the specified offsets. - /// - /// X-coordinate offset. - /// Y-coordinate offset. - /// The created translation matrix. - public static Matrix3x2 Translation(float x, float y) - { - Matrix3x2 result; - Translation(x, y, out result); - return result; - } - - /// - /// Transforms a vector by this matrix. - /// - /// The matrix to use as a transformation matrix. - /// The original vector to apply the transformation. - /// The result of the transformation for the input vector. - public static Vector2 TransformPoint(Matrix3x2 matrix, Vector2 point) - { - Vector2 result; - result.X = (point.X * matrix.M11) + (point.Y * matrix.M21) + matrix.M31; - result.Y = (point.X * matrix.M12) + (point.Y * matrix.M22) + matrix.M32; - return result; - } - - /// - /// Transforms a vector by this matrix. - /// - /// The matrix to use as a transformation matrix. - /// The original vector to apply the transformation. - /// The result of the transformation for the input vector. - /// - public static void TransformPoint(ref Matrix3x2 matrix, ref Vector2 point, out Vector2 result) - { - Vector2 localResult; - localResult.X = (point.X * matrix.M11) + (point.Y * matrix.M21) + matrix.M31; - localResult.Y = (point.X * matrix.M12) + (point.Y * matrix.M22) + matrix.M32; - result = localResult; - } - - /// - /// Calculates the inverse of this matrix instance. - /// - public void Invert() - { - Invert(ref this, out this); - } - - /// - /// Calculates the inverse of the specified matrix. - /// - /// The matrix whose inverse is to be calculated. - /// the inverse of the specified matrix. - public static Matrix3x2 Invert(Matrix3x2 value) - { - Matrix3x2 result; - Invert(ref value, out result); - return result; - } - - /// - /// Creates a skew matrix. - /// - /// Angle of skew along the X-axis in radians. - /// Angle of skew along the Y-axis in radians. - /// The created skew matrix. - public static Matrix3x2 Skew(float angleX, float angleY) - { - Matrix3x2 result; - Skew(angleX, angleY, out result); - return result; - } - - /// - /// Creates a skew matrix. - /// - /// Angle of skew along the X-axis in radians. - /// Angle of skew along the Y-axis in radians. - /// When the method completes, contains the created skew matrix. - public static void Skew(float angleX, float angleY, out Matrix3x2 result) - { - result = Matrix.Identity; - result.M12 = (float) Math.Tan(angleX); - result.M21 = (float) Math.Tan(angleY); - } - - /// - /// Calculates the inverse of the specified matrix. - /// - /// The matrix whose inverse is to be calculated. - /// When the method completes, contains the inverse of the specified matrix. - public static void Invert(ref Matrix3x2 value, out Matrix3x2 result) - { - float determinant = value.Determinant(); - - if (MathUtil.IsZero(determinant)) - { - result = Identity; - return; - } - - float invdet = 1.0f / determinant; - float _offsetX = value.M31; - float _offsetY = value.M32; - - result = new Matrix3x2( - value.M22 * invdet, - -value.M12 * invdet, - -value.M21 * invdet, - value.M11 * invdet, - (value.M21 * _offsetY - _offsetX * value.M22) * invdet, - (_offsetX * value.M12 - value.M11 * _offsetY) * invdet); - } - - /// - /// Adds two matrices. - /// - /// The first matrix to add. - /// The second matrix to add. - /// The sum of the two matrices. - public static Matrix3x2 operator +(Matrix3x2 left, Matrix3x2 right) - { - Matrix3x2 result; - Add(ref left, ref right, out result); - return result; - } - - /// - /// Assert a matrix (return it unchanged). - /// - /// The matrix to assert (unchanged). - /// The asserted (unchanged) matrix. - public static Matrix3x2 operator +(Matrix3x2 value) - { - return value; - } - - /// - /// Subtracts two matrices. - /// - /// The first matrix to subtract. - /// The second matrix to subtract. - /// The difference between the two matrices. - public static Matrix3x2 operator -(Matrix3x2 left, Matrix3x2 right) - { - Matrix3x2 result; - Subtract(ref left, ref right, out result); - return result; - } - - /// - /// Negates a matrix. - /// - /// The matrix to negate. - /// The negated matrix. - public static Matrix3x2 operator -(Matrix3x2 value) - { - Matrix3x2 result; - Negate(ref value, out result); - return result; - } - - /// - /// Scales a matrix by a given value. - /// - /// The matrix to scale. - /// The amount by which to scale. - /// The scaled matrix. - public static Matrix3x2 operator *(float left, Matrix3x2 right) - { - Matrix3x2 result; - Multiply(ref right, left, out result); - return result; - } - - /// - /// Scales a matrix by a given value. - /// - /// The matrix to scale. - /// The amount by which to scale. - /// The scaled matrix. - public static Matrix3x2 operator *(Matrix3x2 left, float right) - { - Matrix3x2 result; - Multiply(ref left, right, out result); - return result; - } - - /// - /// Multiplies two matrices. - /// - /// The first matrix to multiply. - /// The second matrix to multiply. - /// The product of the two matrices. - public static Matrix3x2 operator *(Matrix3x2 left, Matrix3x2 right) - { - Matrix3x2 result; - Multiply(ref left, ref right, out result); - return result; - } - - /// - /// Scales a matrix by a given value. - /// - /// The matrix to scale. - /// The amount by which to scale. - /// The scaled matrix. - public static Matrix3x2 operator /(Matrix3x2 left, float right) - { - Matrix3x2 result; - Divide(ref left, right, out result); - return result; - } - - /// - /// Divides two matrices. - /// - /// The first matrix to divide. - /// The second matrix to divide. - /// The quotient of the two matrices. - public static Matrix3x2 operator /(Matrix3x2 left, Matrix3x2 right) - { - Matrix3x2 result; - Divide(ref left, ref right, out result); - return result; - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has the same value as ; otherwise, false. - public static bool operator ==(Matrix3x2 left, Matrix3x2 right) - { - return left.Equals(right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has a different value than ; otherwise, false. - public static bool operator !=(Matrix3x2 left, Matrix3x2 right) - { - return !left.Equals(right); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return string.Format(CultureInfo.CurrentCulture, "[M11:{0} M12:{1}] [M21:{2} M22:{3}] [M31:{4} M32:{5}]", - M11, M12, M21, M22, M31, M32); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// - /// A that represents this instance. - /// - public string ToString(string format) - { - if (format == null) - return ToString(); - - return string.Format(format, CultureInfo.CurrentCulture, "[M11:{0} M12:{1}] [M21:{2} M22:{3}] [M31:{4} M32:{5}]", - M11.ToString(format, CultureInfo.CurrentCulture), M12.ToString(format, CultureInfo.CurrentCulture), - M21.ToString(format, CultureInfo.CurrentCulture), M22.ToString(format, CultureInfo.CurrentCulture), - M31.ToString(format, CultureInfo.CurrentCulture), M32.ToString(format, CultureInfo.CurrentCulture)); - } - - /// - /// Returns a that represents this instance. - /// - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(IFormatProvider formatProvider) - { - return string.Format(formatProvider, "[M11:{0} M12:{1}] [M21:{2} M22:{3}] [M31:{4} M32:{5}]", - M11.ToString(formatProvider), M12.ToString(formatProvider), - M21.ToString(formatProvider), M22.ToString(formatProvider), - M31.ToString(formatProvider), M32.ToString(formatProvider)); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - if (format == null) - return ToString(formatProvider); - - return string.Format(format, formatProvider, "[M11:{0} M12:{1}] [M21:{2} M22:{3}] [M31:{4} M32:{5}]", - M11.ToString(format, formatProvider), M12.ToString(format, formatProvider), - M21.ToString(format, formatProvider), M22.ToString(format, formatProvider), - M31.ToString(format, formatProvider), M32.ToString(format, formatProvider)); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - var hashCode = M11.GetHashCode(); - hashCode = (hashCode * 397) ^ M12.GetHashCode(); - hashCode = (hashCode * 397) ^ M21.GetHashCode(); - hashCode = (hashCode * 397) ^ M22.GetHashCode(); - hashCode = (hashCode * 397) ^ M31.GetHashCode(); - hashCode = (hashCode * 397) ^ M32.GetHashCode(); - return hashCode; - } - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(M11); - serializer.Writer.Write(M12); - serializer.Writer.Write(M21); - serializer.Writer.Write(M22); - serializer.Writer.Write(M31); - serializer.Writer.Write(M32); - } - else - { - M11 = serializer.Reader.ReadSingle(); - M12 = serializer.Reader.ReadSingle(); - M21 = serializer.Reader.ReadSingle(); - M22 = serializer.Reader.ReadSingle(); - M31 = serializer.Reader.ReadSingle(); - M32 = serializer.Reader.ReadSingle(); - } - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(Matrix3x2 other) - { - return (MathUtil.NearEqual(other.M11, M11) && - MathUtil.NearEqual(other.M12, M12) && - MathUtil.NearEqual(other.M21, M21) && - MathUtil.NearEqual(other.M22, M22) && - MathUtil.NearEqual(other.M31, M31) && - MathUtil.NearEqual(other.M32, M32)); - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object value) - { - if (value == null) - return false; - - if (!ReferenceEquals(value.GetType(), typeof(Matrix3x2))) - return false; - - return Equals((Matrix3x2)value); - } - - /// - /// Performs an implicit conversion from to . - /// - /// The matrix. - /// The result of the conversion. - public static implicit operator Matrix3x2(Matrix matrix) - { - return new Matrix3x2 - { - M11 = matrix.M11, - M12 = matrix.M12, - M21 = matrix.M21, - M22 = matrix.M22, - M31 = matrix.M41, - M32 = matrix.M42 - }; - } - } - -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE.using System; + +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Direct2D Matrix3x2. Supports implicit cast from . + /// + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct Matrix3x2 + { + /// + /// Gets the identity matrix. + /// + /// The identity matrix. + public readonly static Matrix3x2 Identity = new Matrix3x2(1, 0, 0, 1, 0, 0); + + /// + /// Element (1,1) + /// + public float M11; + + /// + /// Element (1,2) + /// + public float M12; + + /// + /// Element (2,1) + /// + public float M21; + + /// + /// Element (2,2) + /// + public float M22; + + /// + /// Element (3,1) + /// + public float M31; + + /// + /// Element (3,2) + /// + public float M32; + + /// + /// Initializes a new instance of the struct. + /// + /// The value that will be assigned to all components. + public Matrix3x2(float value) + { + M11 = M12 = + M21 = M22 = + M31 = M32 = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value to assign at row 1 column 1 of the matrix. + /// The value to assign at row 1 column 2 of the matrix. + /// The value to assign at row 2 column 1 of the matrix. + /// The value to assign at row 2 column 2 of the matrix. + /// The value to assign at row 3 column 1 of the matrix. + /// The value to assign at row 3 column 2 of the matrix. + public Matrix3x2(float M11, float M12, float M21, float M22, float M31, float M32) + { + this.M11 = M11; this.M12 = M12; + this.M21 = M21; this.M22 = M22; + this.M31 = M31; this.M32 = M32; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The values to assign to the components of the matrix. This must be an array with six elements. + /// Thrown when is null. + /// Thrown when contains more or less than six elements. + public Matrix3x2(float[] values) + { + if (values == null) + throw new ArgumentNullException("values"); + if (values.Length != 6) + throw new ArgumentOutOfRangeException("values", "There must be six input values for Matrix3x2."); + + M11 = values[0]; + M12 = values[1]; + + M21 = values[2]; + M22 = values[3]; + + M31 = values[4]; + M32 = values[5]; + } + + /// + /// Gets or sets the first row in the matrix; that is M11 and M12. + /// + public Vector2 Row1 + { + get { return new Vector2(M11, M12); } + set { M11 = value.X; M12 = value.Y; } + } + + /// + /// Gets or sets the second row in the matrix; that is M21 and M22. + /// + public Vector2 Row2 + { + get { return new Vector2(M21, M22); } + set { M21 = value.X; M22 = value.Y; } + } + + /// + /// Gets or sets the third row in the matrix; that is M31 and M32. + /// + public Vector2 Row3 + { + get { return new Vector2(M31, M32); } + set { M31 = value.X; M32 = value.Y; } + } + + /// + /// Gets or sets the first column in the matrix; that is M11, M21, and M31. + /// + public Vector3 Column1 + { + get { return new Vector3(M11, M21, M31); } + set { M11 = value.X; M21 = value.Y; M31 = value.Z; } + } + + /// + /// Gets or sets the second column in the matrix; that is M12, M22, and M32. + /// + public Vector3 Column2 + { + get { return new Vector3(M12, M22, M32); } + set { M12 = value.X; M22 = value.Y; M32 = value.Z;} + } + + /// + /// Gets or sets the translation of the matrix; that is M31 and M32. + /// + public Vector2 TranslationVector + { + get { return new Vector2(M31, M32); } + set { M31 = value.X; M32 = value.Y; } + } + + /// + /// Gets or sets the scale of the matrix; that is M11 and M22. + /// + public Vector2 ScaleVector + { + get { return new Vector2(M11, M22); } + set { M11 = value.X; M22 = value.Y; } + } + + /// + /// Gets a value indicating whether this instance is an identity matrix. + /// + /// + /// true if this instance is an identity matrix; otherwise, false. + /// + public bool IsIdentity + { + get { return this.Equals(Identity); } + } + + /// + /// Gets or sets the component at the specified index. + /// + /// The value of the matrix component, depending on the index. + /// The zero-based index of the component to access. + /// The value of the component at the specified index. + /// Thrown when the is out of the range [0, 5]. + public float this[int index] + { + get + { + switch (index) + { + case 0: return M11; + case 1: return M12; + case 2: return M21; + case 3: return M22; + case 4: return M31; + case 5: return M32; + } + + throw new ArgumentOutOfRangeException("index", "Indices for Matrix3x2 run from 0 to 5, inclusive."); + } + + set + { + switch (index) + { + case 0: M11 = value; break; + case 1: M12 = value; break; + case 2: M21 = value; break; + case 3: M22 = value; break; + case 4: M31 = value; break; + case 5: M32 = value; break; + default: throw new ArgumentOutOfRangeException("index", "Indices for Matrix3x2 run from 0 to 5, inclusive."); + } + } + } + + /// + /// Gets or sets the component at the specified index. + /// + /// The value of the matrix component, depending on the index. + /// The row of the matrix to access. + /// The column of the matrix to access. + /// The value of the component at the specified index. + /// Thrown when the or is out of the range [0, 3]. + public float this[int row, int column] + { + get + { + if (row < 0 || row > 2) + throw new ArgumentOutOfRangeException("row", "Rows and columns for matrices run from 0 to 2, inclusive."); + if (column < 0 || column > 1) + throw new ArgumentOutOfRangeException("column", "Rows and columns for matrices run from 0 to 1, inclusive."); + + return this[(row * 2) + column]; + } + + set + { + if (row < 0 || row > 2) + throw new ArgumentOutOfRangeException("row", "Rows and columns for matrices run from 0 to 2, inclusive."); + if (column < 0 || column > 1) + throw new ArgumentOutOfRangeException("column", "Rows and columns for matrices run from 0 to 1, inclusive."); + + this[(row * 2) + column] = value; + } + } + + /// + /// Creates an array containing the elements of the matrix. + /// + /// A sixteen-element array containing the components of the matrix. + public float[] ToArray() + { + return new[] { M11, M12, M21, M22, M31, M32 }; + } + + /// + /// Determines the sum of two matrices. + /// + /// The first matrix to add. + /// The second matrix to add. + /// When the method completes, contains the sum of the two matrices. + public static void Add(ref Matrix3x2 left, ref Matrix3x2 right, out Matrix3x2 result) + { + result.M11 = left.M11 + right.M11; + result.M12 = left.M12 + right.M12; + result.M21 = left.M21 + right.M21; + result.M22 = left.M22 + right.M22; + result.M31 = left.M31 + right.M31; + result.M32 = left.M32 + right.M32; + } + + /// + /// Determines the sum of two matrices. + /// + /// The first matrix to add. + /// The second matrix to add. + /// The sum of the two matrices. + public static Matrix3x2 Add(Matrix3x2 left, Matrix3x2 right) + { + Matrix3x2 result; + Add(ref left, ref right, out result); + return result; + } + + /// + /// Determines the difference between two matrices. + /// + /// The first matrix to subtract. + /// The second matrix to subtract. + /// When the method completes, contains the difference between the two matrices. + public static void Subtract(ref Matrix3x2 left, ref Matrix3x2 right, out Matrix3x2 result) + { + result.M11 = left.M11 - right.M11; + result.M12 = left.M12 - right.M12; + result.M21 = left.M21 - right.M21; + result.M22 = left.M22 - right.M22; + result.M31 = left.M31 - right.M31; + result.M32 = left.M32 - right.M32; + } + + /// + /// Determines the difference between two matrices. + /// + /// The first matrix to subtract. + /// The second matrix to subtract. + /// The difference between the two matrices. + public static Matrix3x2 Subtract(Matrix3x2 left, Matrix3x2 right) + { + Matrix3x2 result; + Subtract(ref left, ref right, out result); + return result; + } + + /// + /// Scales a matrix by the given value. + /// + /// The matrix to scale. + /// The amount by which to scale. + /// When the method completes, contains the scaled matrix. + public static void Multiply(ref Matrix3x2 left, float right, out Matrix3x2 result) + { + result.M11 = left.M11 * right; + result.M12 = left.M12 * right; + result.M21 = left.M21 * right; + result.M22 = left.M22 * right; + result.M31 = left.M31 * right; + result.M32 = left.M32 * right; + } + + /// + /// Scales a matrix by the given value. + /// + /// The matrix to scale. + /// The amount by which to scale. + /// The scaled matrix. + public static Matrix3x2 Multiply(Matrix3x2 left, float right) + { + Matrix3x2 result; + Multiply(ref left, right, out result); + return result; + } + + /// + /// Determines the product of two matrices. + /// + /// The first matrix to multiply. + /// The second matrix to multiply. + /// The product of the two matrices. + public static void Multiply(ref Matrix3x2 left, ref Matrix3x2 right, out Matrix3x2 result) + { + result = new Matrix3x2(); + result.M11 = (left.M11 * right.M11) + (left.M12 * right.M21); + result.M12 = (left.M11 * right.M12) + (left.M12 * right.M22); + result.M21 = (left.M21 * right.M11) + (left.M22 * right.M21); + result.M22 = (left.M21 * right.M12) + (left.M22 * right.M22); + result.M31 = (left.M31 * right.M11) + (left.M32 * right.M21) + right.M31; + result.M32 = (left.M31 * right.M12) + (left.M32 * right.M22) + right.M32; + } + + /// + /// Determines the product of two matrices. + /// + /// The first matrix to multiply. + /// The second matrix to multiply. + /// The product of the two matrices. + public static Matrix3x2 Multiply(Matrix3x2 left, Matrix3x2 right) + { + Matrix3x2 result; + Multiply(ref left, ref right, out result); + return result; + } + + /// + /// Scales a matrix by the given value. + /// + /// The matrix to scale. + /// The amount by which to scale. + /// When the method completes, contains the scaled matrix. + public static void Divide(ref Matrix3x2 left, float right, out Matrix3x2 result) + { + float inv = 1.0f / right; + + result.M11 = left.M11 * inv; + result.M12 = left.M12 * inv; + result.M21 = left.M21 * inv; + result.M22 = left.M22 * inv; + result.M31 = left.M31 * inv; + result.M32 = left.M32 * inv; + } + + /// + /// Determines the quotient of two matrices. + /// + /// The first matrix to divide. + /// The second matrix to divide. + /// When the method completes, contains the quotient of the two matrices. + public static void Divide(ref Matrix3x2 left, ref Matrix3x2 right, out Matrix3x2 result) + { + result.M11 = left.M11 / right.M11; + result.M12 = left.M12 / right.M12; + result.M21 = left.M21 / right.M21; + result.M22 = left.M22 / right.M22; + result.M31 = left.M31 / right.M31; + result.M32 = left.M32 / right.M32; + } + + /// + /// Negates a matrix. + /// + /// The matrix to be negated. + /// When the method completes, contains the negated matrix. + public static void Negate(ref Matrix3x2 value, out Matrix3x2 result) + { + result.M11 = -value.M11; + result.M12 = -value.M12; + result.M21 = -value.M21; + result.M22 = -value.M22; + result.M31 = -value.M31; + result.M32 = -value.M32; + } + + /// + /// Negates a matrix. + /// + /// The matrix to be negated. + /// The negated matrix. + public static Matrix3x2 Negate(Matrix3x2 value) + { + Matrix3x2 result; + Negate(ref value, out result); + return result; + } + + /// + /// Performs a linear interpolation between two matrices. + /// + /// Start matrix. + /// End matrix. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the linear interpolation of the two matrices. + /// + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static void Lerp(ref Matrix3x2 start, ref Matrix3x2 end, float amount, out Matrix3x2 result) + { + result.M11 = MathUtil.Lerp(start.M11, end.M11, amount); + result.M12 = MathUtil.Lerp(start.M12, end.M12, amount); + result.M21 = MathUtil.Lerp(start.M21, end.M21, amount); + result.M22 = MathUtil.Lerp(start.M22, end.M22, amount); + result.M31 = MathUtil.Lerp(start.M31, end.M31, amount); + result.M32 = MathUtil.Lerp(start.M32, end.M32, amount); + } + + /// + /// Performs a linear interpolation between two matrices. + /// + /// Start matrix. + /// End matrix. + /// Value between 0 and 1 indicating the weight of . + /// The linear interpolation of the two matrices. + /// + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static Matrix3x2 Lerp(Matrix3x2 start, Matrix3x2 end, float amount) + { + Matrix3x2 result; + Lerp(ref start, ref end, amount, out result); + return result; + } + + /// + /// Performs a cubic interpolation between two matrices. + /// + /// Start matrix. + /// End matrix. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the cubic interpolation of the two matrices. + public static void SmoothStep(ref Matrix3x2 start, ref Matrix3x2 end, float amount, out Matrix3x2 result) + { + amount = MathUtil.SmoothStep(amount); + Lerp(ref start, ref end, amount, out result); + } + + /// + /// Performs a cubic interpolation between two matrices. + /// + /// Start matrix. + /// End matrix. + /// Value between 0 and 1 indicating the weight of . + /// The cubic interpolation of the two matrices. + public static Matrix3x2 SmoothStep(Matrix3x2 start, Matrix3x2 end, float amount) + { + Matrix3x2 result; + SmoothStep(ref start, ref end, amount, out result); + return result; + } + + /// + /// Creates a matrix that scales along the x-axis and y-axis. + /// + /// Scaling factor for both axes. + /// When the method completes, contains the created scaling matrix. + public static void Scaling(ref Vector2 scale, out Matrix3x2 result) + { + Scaling(scale.X, scale.Y, out result); + } + + /// + /// Creates a matrix that scales along the x-axis and y-axis. + /// + /// Scaling factor for both axes. + /// The created scaling matrix. + public static Matrix3x2 Scaling(Vector2 scale) + { + Matrix3x2 result; + Scaling(ref scale, out result); + return result; + } + + /// + /// Creates a matrix that scales along the x-axis and y-axis. + /// + /// Scaling factor that is applied along the x-axis. + /// Scaling factor that is applied along the y-axis. + /// When the method completes, contains the created scaling matrix. + public static void Scaling(float x, float y, out Matrix3x2 result) + { + result = Matrix3x2.Identity; + result.M11 = x; + result.M22 = y; + } + + /// + /// Creates a matrix that scales along the x-axis and y-axis. + /// + /// Scaling factor that is applied along the x-axis. + /// Scaling factor that is applied along the y-axis. + /// The created scaling matrix. + public static Matrix3x2 Scaling(float x, float y) + { + Matrix3x2 result; + Scaling(x, y, out result); + return result; + } + + /// + /// Creates a matrix that uniformly scales along both axes. + /// + /// The uniform scale that is applied along both axes. + /// When the method completes, contains the created scaling matrix. + public static void Scaling(float scale, out Matrix3x2 result) + { + result = Matrix3x2.Identity; + result.M11 = result.M22 = scale; + } + + /// + /// Creates a matrix that uniformly scales along both axes. + /// + /// The uniform scale that is applied along both axes. + /// The created scaling matrix. + public static Matrix3x2 Scaling(float scale) + { + Matrix3x2 result; + Scaling(scale, out result); + return result; + } + + /// + /// Creates a matrix that is scaling from a specified center. + /// + /// Scaling factor that is applied along the x-axis. + /// Scaling factor that is applied along the y-axis. + /// The center of the scaling. + /// The created scaling matrix. + public static Matrix3x2 Scaling(float x, float y, Vector2 center) + { + Matrix3x2 result; + + result.M11 = x; result.M12 = 0.0f; + result.M21 = 0.0f; result.M22 = y; + + result.M31 = center.X - (x * center.X); + result.M32 = center.Y - (y * center.Y); + + return result; + } + + /// + /// Creates a matrix that is scaling from a specified center. + /// + /// Scaling factor that is applied along the x-axis. + /// Scaling factor that is applied along the y-axis. + /// The center of the scaling. + /// The created scaling matrix. + public static void Scaling( float x, float y, ref Vector2 center, out Matrix3x2 result) + { + Matrix3x2 localResult; + + localResult.M11 = x; localResult.M12 = 0.0f; + localResult.M21 = 0.0f; localResult.M22 = y; + + localResult.M31 = center.X - (x * center.X); + localResult.M32 = center.Y - (y * center.Y); + + result = localResult; + } + + /// + /// Calculates the determinant of this matrix. + /// + /// Result of the determinant. + public float Determinant() + { + return (M11 * M22) - (M12 * M21); + } + + /// + /// Creates a matrix that rotates. + /// + /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis. + /// When the method completes, contains the created rotation matrix. + public static void Rotation(float angle, out Matrix3x2 result) + { + float cos = (float)Math.Cos(angle); + float sin = (float)Math.Sin(angle); + + result = Matrix3x2.Identity; + result.M11 = cos; + result.M12 = sin; + result.M21 = -sin; + result.M22 = cos; + } + + /// + /// Creates a matrix that rotates. + /// + /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis. + /// The created rotation matrix. + public static Matrix3x2 Rotation(float angle) + { + Matrix3x2 result; + Rotation(angle, out result); + return result; + } + + /// + /// Creates a matrix that rotates about a specified center. + /// + /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis. + /// The center of the rotation. + /// The created rotation matrix. + public static Matrix3x2 Rotation(float angle, Vector2 center) + { + Matrix3x2 result; + Rotation(angle, center, out result); + return result; + } + + /// + /// Creates a matrix that rotates about a specified center. + /// + /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis. + /// The center of the rotation. + /// When the method completes, contains the created rotation matrix. + public static void Rotation(float angle, Vector2 center, out Matrix3x2 result) + { + result = Translation(-center) * Rotation(angle) * Translation(center); + } + + /// + /// Creates a transformation matrix. + /// + /// Scaling factor that is applied along the x-axis. + /// Scaling factor that is applied along the y-axis. + /// Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis. + /// X-coordinate offset. + /// Y-coordinate offset. + /// When the method completes, contains the created transformation matrix. + public static void Transformation(float xScale, float yScale, float angle, float xOffset, float yOffset, out Matrix3x2 result) + { + result = Scaling(xScale, yScale) * Rotation(angle) * Translation(xOffset, yOffset); + } + + /// + /// Creates a transformation matrix. + /// + /// Scaling factor that is applied along the x-axis. + /// Scaling factor that is applied along the y-axis. + /// Angle of rotation in radians. + /// X-coordinate offset. + /// Y-coordinate offset. + /// The created transformation matrix. + public static Matrix3x2 Transformation(float xScale, float yScale, float angle, float xOffset, float yOffset) + { + Matrix3x2 result; + Transformation(xScale, yScale, angle, xOffset, yOffset, out result); + return result; + } + + /// + /// Creates a translation matrix using the specified offsets. + /// + /// The offset for both coordinate planes. + /// When the method completes, contains the created translation matrix. + public static void Translation(ref Vector2 value, out Matrix3x2 result) + { + Translation(value.X, value.Y, out result); + } + + /// + /// Creates a translation matrix using the specified offsets. + /// + /// The offset for both coordinate planes. + /// The created translation matrix. + public static Matrix3x2 Translation(Vector2 value) + { + Matrix3x2 result; + Translation(ref value, out result); + return result; + } + + /// + /// Creates a translation matrix using the specified offsets. + /// + /// X-coordinate offset. + /// Y-coordinate offset. + /// When the method completes, contains the created translation matrix. + public static void Translation(float x, float y, out Matrix3x2 result) + { + result = Matrix3x2.Identity; + result.M31 = x; + result.M32 = y; + } + + /// + /// Creates a translation matrix using the specified offsets. + /// + /// X-coordinate offset. + /// Y-coordinate offset. + /// The created translation matrix. + public static Matrix3x2 Translation(float x, float y) + { + Matrix3x2 result; + Translation(x, y, out result); + return result; + } + + /// + /// Transforms a vector by this matrix. + /// + /// The matrix to use as a transformation matrix. + /// The original vector to apply the transformation. + /// The result of the transformation for the input vector. + public static Vector2 TransformPoint(Matrix3x2 matrix, Vector2 point) + { + Vector2 result; + result.X = (point.X * matrix.M11) + (point.Y * matrix.M21) + matrix.M31; + result.Y = (point.X * matrix.M12) + (point.Y * matrix.M22) + matrix.M32; + return result; + } + + /// + /// Transforms a vector by this matrix. + /// + /// The matrix to use as a transformation matrix. + /// The original vector to apply the transformation. + /// The result of the transformation for the input vector. + /// + public static void TransformPoint(ref Matrix3x2 matrix, ref Vector2 point, out Vector2 result) + { + Vector2 localResult; + localResult.X = (point.X * matrix.M11) + (point.Y * matrix.M21) + matrix.M31; + localResult.Y = (point.X * matrix.M12) + (point.Y * matrix.M22) + matrix.M32; + result = localResult; + } + + /// + /// Calculates the inverse of this matrix instance. + /// + public void Invert() + { + Invert(ref this, out this); + } + + /// + /// Calculates the inverse of the specified matrix. + /// + /// The matrix whose inverse is to be calculated. + /// the inverse of the specified matrix. + public static Matrix3x2 Invert(Matrix3x2 value) + { + Matrix3x2 result; + Invert(ref value, out result); + return result; + } + + /// + /// Creates a skew matrix. + /// + /// Angle of skew along the X-axis in radians. + /// Angle of skew along the Y-axis in radians. + /// The created skew matrix. + public static Matrix3x2 Skew(float angleX, float angleY) + { + Matrix3x2 result; + Skew(angleX, angleY, out result); + return result; + } + + /// + /// Creates a skew matrix. + /// + /// Angle of skew along the X-axis in radians. + /// Angle of skew along the Y-axis in radians. + /// When the method completes, contains the created skew matrix. + public static void Skew(float angleX, float angleY, out Matrix3x2 result) + { + result = Matrix.Identity; + result.M12 = (float) Math.Tan(angleX); + result.M21 = (float) Math.Tan(angleY); + } + + /// + /// Calculates the inverse of the specified matrix. + /// + /// The matrix whose inverse is to be calculated. + /// When the method completes, contains the inverse of the specified matrix. + public static void Invert(ref Matrix3x2 value, out Matrix3x2 result) + { + float determinant = value.Determinant(); + + if (MathUtil.IsZero(determinant)) + { + result = Identity; + return; + } + + float invdet = 1.0f / determinant; + float _offsetX = value.M31; + float _offsetY = value.M32; + + result = new Matrix3x2( + value.M22 * invdet, + -value.M12 * invdet, + -value.M21 * invdet, + value.M11 * invdet, + (value.M21 * _offsetY - _offsetX * value.M22) * invdet, + (_offsetX * value.M12 - value.M11 * _offsetY) * invdet); + } + + /// + /// Adds two matrices. + /// + /// The first matrix to add. + /// The second matrix to add. + /// The sum of the two matrices. + public static Matrix3x2 operator +(Matrix3x2 left, Matrix3x2 right) + { + Matrix3x2 result; + Add(ref left, ref right, out result); + return result; + } + + /// + /// Assert a matrix (return it unchanged). + /// + /// The matrix to assert (unchanged). + /// The asserted (unchanged) matrix. + public static Matrix3x2 operator +(Matrix3x2 value) + { + return value; + } + + /// + /// Subtracts two matrices. + /// + /// The first matrix to subtract. + /// The second matrix to subtract. + /// The difference between the two matrices. + public static Matrix3x2 operator -(Matrix3x2 left, Matrix3x2 right) + { + Matrix3x2 result; + Subtract(ref left, ref right, out result); + return result; + } + + /// + /// Negates a matrix. + /// + /// The matrix to negate. + /// The negated matrix. + public static Matrix3x2 operator -(Matrix3x2 value) + { + Matrix3x2 result; + Negate(ref value, out result); + return result; + } + + /// + /// Scales a matrix by a given value. + /// + /// The matrix to scale. + /// The amount by which to scale. + /// The scaled matrix. + public static Matrix3x2 operator *(float left, Matrix3x2 right) + { + Matrix3x2 result; + Multiply(ref right, left, out result); + return result; + } + + /// + /// Scales a matrix by a given value. + /// + /// The matrix to scale. + /// The amount by which to scale. + /// The scaled matrix. + public static Matrix3x2 operator *(Matrix3x2 left, float right) + { + Matrix3x2 result; + Multiply(ref left, right, out result); + return result; + } + + /// + /// Multiplies two matrices. + /// + /// The first matrix to multiply. + /// The second matrix to multiply. + /// The product of the two matrices. + public static Matrix3x2 operator *(Matrix3x2 left, Matrix3x2 right) + { + Matrix3x2 result; + Multiply(ref left, ref right, out result); + return result; + } + + /// + /// Scales a matrix by a given value. + /// + /// The matrix to scale. + /// The amount by which to scale. + /// The scaled matrix. + public static Matrix3x2 operator /(Matrix3x2 left, float right) + { + Matrix3x2 result; + Divide(ref left, right, out result); + return result; + } + + /// + /// Divides two matrices. + /// + /// The first matrix to divide. + /// The second matrix to divide. + /// The quotient of the two matrices. + public static Matrix3x2 operator /(Matrix3x2 left, Matrix3x2 right) + { + Matrix3x2 result; + Divide(ref left, ref right, out result); + return result; + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has the same value as ; otherwise, false. + public static bool operator ==(Matrix3x2 left, Matrix3x2 right) + { + return left.Equals(right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has a different value than ; otherwise, false. + public static bool operator !=(Matrix3x2 left, Matrix3x2 right) + { + return !left.Equals(right); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return string.Format(CultureInfo.CurrentCulture, "[M11:{0} M12:{1}] [M21:{2} M22:{3}] [M31:{4} M32:{5}]", + M11, M12, M21, M22, M31, M32); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// + /// A that represents this instance. + /// + public string ToString(string format) + { + if (format == null) + return ToString(); + + return string.Format(format, CultureInfo.CurrentCulture, "[M11:{0} M12:{1}] [M21:{2} M22:{3}] [M31:{4} M32:{5}]", + M11.ToString(format, CultureInfo.CurrentCulture), M12.ToString(format, CultureInfo.CurrentCulture), + M21.ToString(format, CultureInfo.CurrentCulture), M22.ToString(format, CultureInfo.CurrentCulture), + M31.ToString(format, CultureInfo.CurrentCulture), M32.ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format(formatProvider, "[M11:{0} M12:{1}] [M21:{2} M22:{3}] [M31:{4} M32:{5}]", + M11.ToString(formatProvider), M12.ToString(formatProvider), + M21.ToString(formatProvider), M22.ToString(formatProvider), + M31.ToString(formatProvider), M32.ToString(formatProvider)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(string format, IFormatProvider formatProvider) + { + if (format == null) + return ToString(formatProvider); + + return string.Format(format, formatProvider, "[M11:{0} M12:{1}] [M21:{2} M22:{3}] [M31:{4} M32:{5}]", + M11.ToString(format, formatProvider), M12.ToString(format, formatProvider), + M21.ToString(format, formatProvider), M22.ToString(format, formatProvider), + M31.ToString(format, formatProvider), M32.ToString(format, formatProvider)); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + unchecked + { + var hashCode = M11.GetHashCode(); + hashCode = (hashCode * 397) ^ M12.GetHashCode(); + hashCode = (hashCode * 397) ^ M21.GetHashCode(); + hashCode = (hashCode * 397) ^ M22.GetHashCode(); + hashCode = (hashCode * 397) ^ M31.GetHashCode(); + hashCode = (hashCode * 397) ^ M32.GetHashCode(); + return hashCode; + } + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(Matrix3x2 other) + { + return (MathUtil.NearEqual(other.M11, M11) && + MathUtil.NearEqual(other.M12, M12) && + MathUtil.NearEqual(other.M21, M21) && + MathUtil.NearEqual(other.M22, M22) && + MathUtil.NearEqual(other.M31, M31) && + MathUtil.NearEqual(other.M32, M32)); + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object value) + { + if (value == null) + return false; + + if (!ReferenceEquals(value.GetType(), typeof(Matrix3x2))) + return false; + + return Equals((Matrix3x2)value); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The matrix. + /// The result of the conversion. + public static implicit operator Matrix3x2(Matrix matrix) + { + return new Matrix3x2 + { + M11 = matrix.M11, + M12 = matrix.M12, + M21 = matrix.M21, + M22 = matrix.M22, + M31 = matrix.M41, + M32 = matrix.M42 + }; + } + } + +} diff --git a/Source/SharpDX/Matrix3x3.cs b/Source/SharpDX/Mathematics/Matrix3x3.cs similarity index 95% rename from Source/SharpDX/Matrix3x3.cs rename to Source/SharpDX/Mathematics/Matrix3x3.cs index 42a294aa3..3bc7bcd02 100644 --- a/Source/SharpDX/Matrix3x3.cs +++ b/Source/SharpDX/Mathematics/Matrix3x3.cs @@ -46,7 +46,6 @@ using System; using System.Globalization; using System.Runtime.InteropServices; -using SharpDX.Serialization; namespace SharpDX { @@ -54,8 +53,7 @@ namespace SharpDX /// Represents a 3x3 Matrix ( contains only Scale and Rotation ). /// [StructLayout(LayoutKind.Sequential, Pack = 4)] - [DynamicSerializer("TKM3")] - public struct Matrix3x3 : IEquatable, IFormattable, IDataSerializable + public struct Matrix3x3 : IEquatable, IFormattable { /// /// The size of the type, in bytes. @@ -1511,83 +1509,6 @@ public static Matrix3x3 LookAtRH(Vector3 eye, Vector3 target, Vector3 up) LookAtRH(ref eye, ref target, ref up, out result); return result; } - - /// - /// Builds a Matrix3x3 that can be used to reflect vectors about a plane. - /// - /// The plane for which the reflection occurs. This parameter is assumed to be normalized. - /// When the method completes, contains the reflection Matrix3x3. - public static void Reflection(ref Plane plane, out Matrix3x3 result) - { - float x = plane.Normal.X; - float y = plane.Normal.Y; - float z = plane.Normal.Z; - float x2 = -2.0f * x; - float y2 = -2.0f * y; - float z2 = -2.0f * z; - - result.M11 = (x2 * x) + 1.0f; - result.M12 = y2 * x; - result.M13 = z2 * x; - result.M21 = x2 * y; - result.M22 = (y2 * y) + 1.0f; - result.M23 = z2 * y; - result.M31 = x2 * z; - result.M32 = y2 * z; - result.M33 = (z2 * z) + 1.0f; - } - - /// - /// Builds a Matrix3x3 that can be used to reflect vectors about a plane. - /// - /// The plane for which the reflection occurs. This parameter is assumed to be normalized. - /// The reflection Matrix3x3. - public static Matrix3x3 Reflection(Plane plane) - { - Matrix3x3 result; - Reflection(ref plane, out result); - return result; - } - - /// - /// Creates a Matrix3x3 that flattens geometry into a shadow. - /// - /// The light direction. If the W component is 0, the light is directional light; if the - /// W component is 1, the light is a point light. - /// The plane onto which to project the geometry as a shadow. This parameter is assumed to be normalized. - /// When the method completes, contains the shadow Matrix3x3. - public static void Shadow(ref Vector4 light, ref Plane plane, out Matrix3x3 result) - { - float dot = (plane.Normal.X * light.X) + (plane.Normal.Y * light.Y) + (plane.Normal.Z * light.Z) + (plane.D * light.W); - float x = -plane.Normal.X; - float y = -plane.Normal.Y; - float z = -plane.Normal.Z; - float d = -plane.D; - - result.M11 = (x * light.X) + dot; - result.M21 = y * light.X; - result.M31 = z * light.X; - result.M12 = x * light.Y; - result.M22 = (y * light.Y) + dot; - result.M32 = z * light.Y; - result.M13 = x * light.Z; - result.M23 = y * light.Z; - result.M33 = (z * light.Z) + dot; - } - - /// - /// Creates a Matrix3x3 that flattens geometry into a shadow. - /// - /// The light direction. If the W component is 0, the light is directional light; if the - /// W component is 1, the light is a point light. - /// The plane onto which to project the geometry as a shadow. This parameter is assumed to be normalized. - /// The shadow Matrix3x3. - public static Matrix3x3 Shadow(Vector4 light, Plane plane) - { - Matrix3x3 result; - Shadow(ref light, ref plane, out result); - return result; - } /// /// Creates a Matrix3x3 that scales along the x-axis, y-axis, and y-axis. @@ -2113,36 +2034,6 @@ public override int GetHashCode() } } - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(M11); - serializer.Writer.Write(M12); - serializer.Writer.Write(M13); - serializer.Writer.Write(M21); - serializer.Writer.Write(M22); - serializer.Writer.Write(M23); - serializer.Writer.Write(M31); - serializer.Writer.Write(M32); - serializer.Writer.Write(M33); - } - else - { - M11 = serializer.Reader.ReadSingle(); - M12 = serializer.Reader.ReadSingle(); - M13 = serializer.Reader.ReadSingle(); - M21 = serializer.Reader.ReadSingle(); - M22 = serializer.Reader.ReadSingle(); - M23 = serializer.Reader.ReadSingle(); - M31 = serializer.Reader.ReadSingle(); - M32 = serializer.Reader.ReadSingle(); - M33 = serializer.Reader.ReadSingle(); - } - } - /// /// Determines whether the specified is equal to this instance. /// diff --git a/Source/SharpDX/Matrix5x4.cs b/Source/SharpDX/Mathematics/Matrix5x4.cs similarity index 93% rename from Source/SharpDX/Matrix5x4.cs rename to Source/SharpDX/Mathematics/Matrix5x4.cs index aed2b0b1b..4630c77e7 100644 --- a/Source/SharpDX/Matrix5x4.cs +++ b/Source/SharpDX/Mathematics/Matrix5x4.cs @@ -1,1120 +1,1067 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Represents a 4x4 mathematical Matrix5x4. - /// - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct Matrix5x4 : IEquatable, IFormattable, IDataSerializable - { - /// - /// The size of the type, in bytes. - /// - public static readonly int SizeInBytes = Marshal.SizeOf(typeof(Matrix5x4)); - - /// - /// A with all of its components set to zero. - /// - public static readonly Matrix5x4 Zero = new Matrix5x4(); - - /// - /// The identity . - /// - public static readonly Matrix5x4 Identity = new Matrix5x4() { M11 = 1.0f, M22 = 1.0f, M33 = 1.0f, M44 = 1.0f, M54 = 0.0f }; - - /// - /// Value at row 1 column 1 of the Matrix5x4. - /// - public float M11; - - /// - /// Value at row 1 column 2 of the Matrix5x4. - /// - public float M12; - - /// - /// Value at row 1 column 3 of the Matrix5x4. - /// - public float M13; - - /// - /// Value at row 1 column 4 of the Matrix5x4. - /// - public float M14; - - /// - /// Value at row 2 column 1 of the Matrix5x4. - /// - public float M21; - - /// - /// Value at row 2 column 2 of the Matrix5x4. - /// - public float M22; - - /// - /// Value at row 2 column 3 of the Matrix5x4. - /// - public float M23; - - /// - /// Value at row 2 column 4 of the Matrix5x4. - /// - public float M24; - - /// - /// Value at row 3 column 1 of the Matrix5x4. - /// - public float M31; - - /// - /// Value at row 3 column 2 of the Matrix5x4. - /// - public float M32; - - /// - /// Value at row 3 column 3 of the Matrix5x4. - /// - public float M33; - - /// - /// Value at row 3 column 4 of the Matrix5x4. - /// - public float M34; - - /// - /// Value at row 4 column 1 of the Matrix5x4. - /// - public float M41; - - /// - /// Value at row 4 column 2 of the Matrix5x4. - /// - public float M42; - - /// - /// Value at row 4 column 3 of the Matrix5x4. - /// - public float M43; - - /// - /// Value at row 4 column 4 of the Matrix5x4. - /// - public float M44; - - /// - /// Value at row 5 column 1 of the Matrix5x4. - /// - public float M51; - - /// - /// Value at row 5 column 2 of the Matrix5x4. - /// - public float M52; - - /// - /// Value at row 5 column 3 of the Matrix5x4. - /// - public float M53; - - /// - /// Value at row 5 column 4 of the Matrix5x4. - /// - public float M54; - - /// - /// Initializes a new instance of the struct. - /// - /// The value that will be assigned to all components. - public Matrix5x4(float value) - { - M11 = M12 = M13 = M14 = - M21 = M22 = M23 = M24 = - M31 = M32 = M33 = M34 = - M41 = M42 = M43 = M44 = - M51 = M52 = M53 = M54 = value; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The value to assign at row 1 column 1 of the Matrix5x4. - /// The value to assign at row 1 column 2 of the Matrix5x4. - /// The value to assign at row 1 column 3 of the Matrix5x4. - /// The value to assign at row 1 column 4 of the Matrix5x4. - /// The value to assign at row 2 column 1 of the Matrix5x4. - /// The value to assign at row 2 column 2 of the Matrix5x4. - /// The value to assign at row 2 column 3 of the Matrix5x4. - /// The value to assign at row 2 column 4 of the Matrix5x4. - /// The value to assign at row 3 column 1 of the Matrix5x4. - /// The value to assign at row 3 column 2 of the Matrix5x4. - /// The value to assign at row 3 column 3 of the Matrix5x4. - /// The value to assign at row 3 column 4 of the Matrix5x4. - /// The value to assign at row 4 column 1 of the Matrix5x4. - /// The value to assign at row 4 column 2 of the Matrix5x4. - /// The value to assign at row 4 column 3 of the Matrix5x4. - /// The value to assign at row 4 column 4 of the Matrix5x4. - /// The value to assign at row 5 column 1 of the Matrix5x4. - /// The value to assign at row 5 column 2 of the Matrix5x4. - /// The value to assign at row 5 column 3 of the Matrix5x4. - /// The value to assign at row 5 column 4 of the Matrix5x4. - public Matrix5x4(float M11, float M12, float M13, float M14, - float M21, float M22, float M23, float M24, - float M31, float M32, float M33, float M34, - float M41, float M42, float M43, float M44, - float M51, float M52, float M53, float M54) - { - this.M11 = M11; this.M12 = M12; this.M13 = M13; this.M14 = M14; - this.M21 = M21; this.M22 = M22; this.M23 = M23; this.M24 = M24; - this.M31 = M31; this.M32 = M32; this.M33 = M33; this.M34 = M34; - this.M41 = M41; this.M42 = M42; this.M43 = M43; this.M44 = M44; - this.M51 = M51; this.M52 = M52; this.M53 = M53; this.M54 = M54; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The values to assign to the components of the Matrix5x4. This must be an array with sixteen elements. - /// Thrown when is null. - /// Thrown when contains more or less than sixteen elements. - public Matrix5x4(float[] values) - { - if (values == null) - throw new ArgumentNullException("values"); - if (values.Length != 20) - throw new ArgumentOutOfRangeException("values", "There must be 20 input values for Matrix5x4."); - - M11 = values[0]; - M12 = values[1]; - M13 = values[2]; - M14 = values[3]; - - M21 = values[4]; - M22 = values[5]; - M23 = values[6]; - M24 = values[7]; - - M31 = values[8]; - M32 = values[9]; - M33 = values[10]; - M34 = values[11]; - - M41 = values[12]; - M42 = values[13]; - M43 = values[14]; - M44 = values[15]; - - M51 = values[16]; - M52 = values[17]; - M53 = values[18]; - M54 = values[19]; - } - - /// - /// Gets or sets the first row in the Matrix5x4; that is M11, M12, M13, and M14. - /// - public Vector4 Row1 - { - get { return new Vector4(M11, M12, M13, M14); } - set { M11 = value.X; M12 = value.Y; M13 = value.Z; M14 = value.W; } - } - - /// - /// Gets or sets the second row in the Matrix5x4; that is M21, M22, M23, and M24. - /// - public Vector4 Row2 - { - get { return new Vector4(M21, M22, M23, M24); } - set { M21 = value.X; M22 = value.Y; M23 = value.Z; M24 = value.W; } - } - - /// - /// Gets or sets the third row in the Matrix5x4; that is M31, M32, M33, and M34. - /// - public Vector4 Row3 - { - get { return new Vector4(M31, M32, M33, M34); } - set { M31 = value.X; M32 = value.Y; M33 = value.Z; M34 = value.W; } - } - - /// - /// Gets or sets the fourth row in the Matrix5x4; that is M41, M42, M43, and M44. - /// - public Vector4 Row4 - { - get { return new Vector4(M41, M42, M43, M44); } - set { M41 = value.X; M42 = value.Y; M43 = value.Z; M44 = value.W; } - } - - /// - /// Gets or sets the fifth row in the Matrix5x4; that is M51, M52, M53, and M54. - /// - public Vector4 Row5 - { - get { return new Vector4(M51, M52, M53, M54); } - set { M51 = value.X; M52 = value.Y; M53 = value.Z; M54 = value.W; } - } - - /// - /// Gets or sets the translation of the Matrix5x4; that is M41, M42, and M43. - /// - public Vector4 TranslationVector - { - get { return new Vector4(M51, M52, M53, M54); } - set { M51 = value.X; M52 = value.Y; M53 = value.Z; M54 = value.W; } - } - - /// - /// Gets or sets the scale of the Matrix5x4; that is M11, M22, and M33. - /// - public Vector4 ScaleVector - { - get { return new Vector4(M11, M22, M33, M44); } - set { M11 = value.X; M22 = value.Y; M33 = value.Z; M44 = value.W; } - } - - /// - /// Gets a value indicating whether this instance is an identity Matrix5x4. - /// - /// - /// true if this instance is an identity Matrix5x4; otherwise, false. - /// - public bool IsIdentity - { - get { return this.Equals(Identity); } - } - - /// - /// Gets or sets the component at the specified index. - /// - /// The value of the Matrix5x4 component, depending on the index. - /// The zero-based index of the component to access. - /// The value of the component at the specified index. - /// Thrown when the is out of the range [0, 15]. - public float this[int index] - { - get - { - switch (index) - { - case 0: return M11; - case 1: return M12; - case 2: return M13; - case 3: return M14; - case 4: return M21; - case 5: return M22; - case 6: return M23; - case 7: return M24; - case 8: return M31; - case 9: return M32; - case 10: return M33; - case 11: return M34; - case 12: return M41; - case 13: return M42; - case 14: return M43; - case 15: return M44; - case 16: return M51; - case 17: return M52; - case 18: return M53; - case 19: return M54; - } - - throw new ArgumentOutOfRangeException("index", "Indices for Matrix5x4 run from 0 to 19, inclusive."); - } - - set - { - switch (index) - { - case 0: M11 = value; break; - case 1: M12 = value; break; - case 2: M13 = value; break; - case 3: M14 = value; break; - case 4: M21 = value; break; - case 5: M22 = value; break; - case 6: M23 = value; break; - case 7: M24 = value; break; - case 8: M31 = value; break; - case 9: M32 = value; break; - case 10: M33 = value; break; - case 11: M34 = value; break; - case 12: M41 = value; break; - case 13: M42 = value; break; - case 14: M43 = value; break; - case 15: M44 = value; break; - case 16: M51 = value; break; - case 17: M52 = value; break; - case 18: M53 = value; break; - case 19: M54 = value; break; - default: throw new ArgumentOutOfRangeException("index", "Indices for Matrix5x4 run from 0 to 19, inclusive."); - } - } - } - - /// - /// Gets or sets the component at the specified index. - /// - /// The value of the Matrix5x4 component, depending on the index. - /// The row of the Matrix5x4 to access. - /// The column of the Matrix5x4 to access. - /// The value of the component at the specified index. - /// Thrown when the or is out of the range [0, 3]. - public float this[int row, int column] - { - get - { - if (row < 0 || row > 4) - throw new ArgumentOutOfRangeException("row", "Rows for matrices run from 0 to 4, inclusive."); - if (column < 0 || column > 3) - throw new ArgumentOutOfRangeException("column", "Columns for matrices run from 0 to 3, inclusive."); - - return this[(row * 4) + column]; - } - - set - { - if (row < 0 || row > 4) - throw new ArgumentOutOfRangeException("row", "Rows for matrices run from 0 to 4, inclusive."); - if (column < 0 || column > 3) - throw new ArgumentOutOfRangeException("column", "Columns for matrices run from 0 to 3, inclusive."); - - this[(row * 4) + column] = value; - } - } - - /// - /// Determines the sum of two matrices. - /// - /// The first Matrix5x4 to add. - /// The second Matrix5x4 to add. - /// When the method completes, contains the sum of the two matrices. - public static void Add(ref Matrix5x4 left, ref Matrix5x4 right, out Matrix5x4 result) - { - result.M11 = left.M11 + right.M11; - result.M12 = left.M12 + right.M12; - result.M13 = left.M13 + right.M13; - result.M14 = left.M14 + right.M14; - result.M21 = left.M21 + right.M21; - result.M22 = left.M22 + right.M22; - result.M23 = left.M23 + right.M23; - result.M24 = left.M24 + right.M24; - result.M31 = left.M31 + right.M31; - result.M32 = left.M32 + right.M32; - result.M33 = left.M33 + right.M33; - result.M34 = left.M34 + right.M34; - result.M41 = left.M41 + right.M41; - result.M42 = left.M42 + right.M42; - result.M43 = left.M43 + right.M43; - result.M44 = left.M44 + right.M44; - result.M51 = left.M51 + right.M51; - result.M52 = left.M52 + right.M52; - result.M53 = left.M53 + right.M53; - result.M54 = left.M54 + right.M54; - } - - /// - /// Determines the sum of two matrices. - /// - /// The first Matrix5x4 to add. - /// The second Matrix5x4 to add. - /// The sum of the two matrices. - public static Matrix5x4 Add(Matrix5x4 left, Matrix5x4 right) - { - Matrix5x4 result; - Add(ref left, ref right, out result); - return result; - } - - /// - /// Determines the difference between two matrices. - /// - /// The first Matrix5x4 to subtract. - /// The second Matrix5x4 to subtract. - /// When the method completes, contains the difference between the two matrices. - public static void Subtract(ref Matrix5x4 left, ref Matrix5x4 right, out Matrix5x4 result) - { - result.M11 = left.M11 - right.M11; - result.M12 = left.M12 - right.M12; - result.M13 = left.M13 - right.M13; - result.M14 = left.M14 - right.M14; - result.M21 = left.M21 - right.M21; - result.M22 = left.M22 - right.M22; - result.M23 = left.M23 - right.M23; - result.M24 = left.M24 - right.M24; - result.M31 = left.M31 - right.M31; - result.M32 = left.M32 - right.M32; - result.M33 = left.M33 - right.M33; - result.M34 = left.M34 - right.M34; - result.M41 = left.M41 - right.M41; - result.M42 = left.M42 - right.M42; - result.M43 = left.M43 - right.M43; - result.M44 = left.M44 - right.M44; - result.M51 = left.M51 - right.M51; - result.M52 = left.M52 - right.M52; - result.M53 = left.M53 - right.M53; - result.M54 = left.M54 - right.M54; - } - - /// - /// Determines the difference between two matrices. - /// - /// The first Matrix5x4 to subtract. - /// The second Matrix5x4 to subtract. - /// The difference between the two matrices. - public static Matrix5x4 Subtract(Matrix5x4 left, Matrix5x4 right) - { - Matrix5x4 result; - Subtract(ref left, ref right, out result); - return result; - } - - /// - /// Scales a Matrix5x4 by the given value. - /// - /// The Matrix5x4 to scale. - /// The amount by which to scale. - /// When the method completes, contains the scaled Matrix5x4. - public static void Multiply(ref Matrix5x4 left, float right, out Matrix5x4 result) - { - result.M11 = left.M11 * right; - result.M12 = left.M12 * right; - result.M13 = left.M13 * right; - result.M14 = left.M14 * right; - result.M21 = left.M21 * right; - result.M22 = left.M22 * right; - result.M23 = left.M23 * right; - result.M24 = left.M24 * right; - result.M31 = left.M31 * right; - result.M32 = left.M32 * right; - result.M33 = left.M33 * right; - result.M34 = left.M34 * right; - result.M41 = left.M41 * right; - result.M42 = left.M42 * right; - result.M43 = left.M43 * right; - result.M44 = left.M44 * right; - result.M51 = left.M51 * right; - result.M52 = left.M52 * right; - result.M53 = left.M53 * right; - result.M54 = left.M54 * right; - } - - /// - /// Scales a Matrix5x4 by the given value. - /// - /// The Matrix5x4 to scale. - /// The amount by which to scale. - /// When the method completes, contains the scaled Matrix5x4. - public static void Divide(ref Matrix5x4 left, float right, out Matrix5x4 result) - { - float inv = 1.0f / right; - - result.M11 = left.M11 * inv; - result.M12 = left.M12 * inv; - result.M13 = left.M13 * inv; - result.M14 = left.M14 * inv; - result.M21 = left.M21 * inv; - result.M22 = left.M22 * inv; - result.M23 = left.M23 * inv; - result.M24 = left.M24 * inv; - result.M31 = left.M31 * inv; - result.M32 = left.M32 * inv; - result.M33 = left.M33 * inv; - result.M34 = left.M34 * inv; - result.M41 = left.M41 * inv; - result.M42 = left.M42 * inv; - result.M43 = left.M43 * inv; - result.M44 = left.M44 * inv; - result.M51 = left.M51 * inv; - result.M52 = left.M52 * inv; - result.M53 = left.M53 * inv; - result.M54 = left.M54 * inv; - } - - /// - /// Negates a Matrix5x4. - /// - /// The Matrix5x4 to be negated. - /// When the method completes, contains the negated Matrix5x4. - public static void Negate(ref Matrix5x4 value, out Matrix5x4 result) - { - result.M11 = -value.M11; - result.M12 = -value.M12; - result.M13 = -value.M13; - result.M14 = -value.M14; - result.M21 = -value.M21; - result.M22 = -value.M22; - result.M23 = -value.M23; - result.M24 = -value.M24; - result.M31 = -value.M31; - result.M32 = -value.M32; - result.M33 = -value.M33; - result.M34 = -value.M34; - result.M41 = -value.M41; - result.M42 = -value.M42; - result.M43 = -value.M43; - result.M44 = -value.M44; - result.M51 = -value.M51; - result.M52 = -value.M52; - result.M53 = -value.M53; - result.M54 = -value.M54; - } - - /// - /// Negates a Matrix5x4. - /// - /// The Matrix5x4 to be negated. - /// The negated Matrix5x4. - public static Matrix5x4 Negate(Matrix5x4 value) - { - Matrix5x4 result; - Negate(ref value, out result); - return result; - } - - /// - /// Performs a linear interpolation between two matrices. - /// - /// Start Matrix5x4. - /// End Matrix5x4. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the linear interpolation of the two matrices. - /// - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static void Lerp(ref Matrix5x4 start, ref Matrix5x4 end, float amount, out Matrix5x4 result) - { - result.M11 = MathUtil.Lerp(start.M11, end.M11, amount); - result.M12 = MathUtil.Lerp(start.M12, end.M12, amount); - result.M13 = MathUtil.Lerp(start.M13, end.M13, amount); - result.M14 = MathUtil.Lerp(start.M14, end.M14, amount); - result.M21 = MathUtil.Lerp(start.M21, end.M21, amount); - result.M22 = MathUtil.Lerp(start.M22, end.M22, amount); - result.M23 = MathUtil.Lerp(start.M23, end.M23, amount); - result.M24 = MathUtil.Lerp(start.M24, end.M24, amount); - result.M31 = MathUtil.Lerp(start.M31, end.M31, amount); - result.M32 = MathUtil.Lerp(start.M32, end.M32, amount); - result.M33 = MathUtil.Lerp(start.M33, end.M33, amount); - result.M34 = MathUtil.Lerp(start.M34, end.M34, amount); - result.M41 = MathUtil.Lerp(start.M41, end.M41, amount); - result.M42 = MathUtil.Lerp(start.M42, end.M42, amount); - result.M43 = MathUtil.Lerp(start.M43, end.M43, amount); - result.M44 = MathUtil.Lerp(start.M44, end.M44, amount); - result.M51 = MathUtil.Lerp(start.M51, end.M51, amount); - result.M52 = MathUtil.Lerp(start.M52, end.M52, amount); - result.M53 = MathUtil.Lerp(start.M53, end.M53, amount); - result.M54 = MathUtil.Lerp(start.M54, end.M54, amount); - } - - /// - /// Performs a linear interpolation between two matrices. - /// - /// Start Matrix5x4. - /// End Matrix5x4. - /// Value between 0 and 1 indicating the weight of . - /// The linear interpolation of the two matrices. - /// - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static Matrix5x4 Lerp(Matrix5x4 start, Matrix5x4 end, float amount) - { - Matrix5x4 result; - Lerp(ref start, ref end, amount, out result); - return result; - } - - /// - /// Performs a cubic interpolation between two matrices. - /// - /// Start Matrix5x4. - /// End Matrix5x4. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the cubic interpolation of the two matrices. - public static void SmoothStep(ref Matrix5x4 start, ref Matrix5x4 end, float amount, out Matrix5x4 result) - { - amount = MathUtil.SmoothStep(amount); - Lerp(ref start, ref end, amount, out result); - } - - /// - /// Performs a cubic interpolation between two matrices. - /// - /// Start Matrix5x4. - /// End Matrix5x4. - /// Value between 0 and 1 indicating the weight of . - /// The cubic interpolation of the two matrices. - public static Matrix5x4 SmoothStep(Matrix5x4 start, Matrix5x4 end, float amount) - { - Matrix5x4 result; - SmoothStep(ref start, ref end, amount, out result); - return result; - } - - /// - /// Creates a Matrix5x4 that scales along the x-axis, y-axis, y-axis and w-axis - /// - /// Scaling factor for all three axes. - /// When the method completes, contains the created scaling Matrix5x4. - public static void Scaling(ref Vector4 scale, out Matrix5x4 result) - { - Scaling(scale.X, scale.Y, scale.Z, scale.W, out result); - } - - /// - /// Creates a Matrix5x4 that scales along the x-axis, y-axis, and y-axis. - /// - /// Scaling factor for all three axes. - /// The created scaling Matrix5x4. - public static Matrix5x4 Scaling(Vector4 scale) - { - Matrix5x4 result; - Scaling(ref scale, out result); - return result; - } - - /// - /// Creates a Matrix5x4 that scales along the x-axis, y-axis, z-axis and w-axis. - /// - /// Scaling factor that is applied along the x-axis. - /// Scaling factor that is applied along the y-axis. - /// Scaling factor that is applied along the z-axis. - /// Scaling factor that is applied along the w-axis. - /// When the method completes, contains the created scaling Matrix5x4. - public static void Scaling(float x, float y, float z, float w, out Matrix5x4 result) - { - result = Matrix5x4.Identity; - result.M11 = x; - result.M22 = y; - result.M33 = z; - result.M44 = w; - } - - /// - /// Creates a Matrix5x4 that scales along the x-axis, y-axis, z-axis and w-axis. - /// - /// Scaling factor that is applied along the x-axis. - /// Scaling factor that is applied along the y-axis. - /// Scaling factor that is applied along the z-axis. - /// Scaling factor that is applied along the w-axis. - /// The created scaling Matrix5x4. - public static Matrix5x4 Scaling(float x, float y, float z, float w) - { - Matrix5x4 result; - Scaling(x, y, z, w, out result); - return result; - } - - /// - /// Creates a Matrix5x4 that uniformly scales along all three axis. - /// - /// The uniform scale that is applied along all axis. - /// When the method completes, contains the created scaling Matrix5x4. - public static void Scaling(float scale, out Matrix5x4 result) - { - result = Matrix5x4.Identity; - result.M11 = result.M22 = result.M33 = result.M44 = scale; - } - - /// - /// Creates a Matrix5x4 that uniformly scales along all three axis. - /// - /// The uniform scale that is applied along all axis. - /// The created scaling Matrix5x4. - public static Matrix5x4 Scaling(float scale) - { - Matrix5x4 result; - Scaling(scale, out result); - return result; - } - - /// - /// Creates a translation Matrix5x4 using the specified offsets. - /// - /// The offset for all three coordinate planes. - /// When the method completes, contains the created translation Matrix5x4. - public static void Translation(ref Vector4 value, out Matrix5x4 result) - { - Translation(value.X, value.Y, value.Z, value.W, out result); - } - - /// - /// Creates a translation Matrix5x4 using the specified offsets. - /// - /// The offset for all three coordinate planes. - /// The created translation Matrix5x4. - public static Matrix5x4 Translation(Vector4 value) - { - Matrix5x4 result; - Translation(ref value, out result); - return result; - } - - /// - /// Creates a translation Matrix5x4 using the specified offsets. - /// - /// X-coordinate offset. - /// Y-coordinate offset. - /// Z-coordinate offset. - /// W-coordinate offset. - /// When the method completes, contains the created translation Matrix5x4. - public static void Translation(float x, float y, float z, float w, out Matrix5x4 result) - { - result = Matrix5x4.Identity; - result.M51 = x; - result.M52 = y; - result.M53 = z; - result.M54 = w; - } - - /// - /// Creates a translation Matrix5x4 using the specified offsets. - /// - /// X-coordinate offset. - /// Y-coordinate offset. - /// Z-coordinate offset. - /// W-coordinate offset. - /// The created translation Matrix5x4. - public static Matrix5x4 Translation(float x, float y, float z, float w) - { - Matrix5x4 result; - Translation(x, y, z, w, out result); - return result; - } - - /// - /// Adds two matrices. - /// - /// The first Matrix5x4 to add. - /// The second Matrix5x4 to add. - /// The sum of the two matrices. - public static Matrix5x4 operator +(Matrix5x4 left, Matrix5x4 right) - { - Matrix5x4 result; - Add(ref left, ref right, out result); - return result; - } - - /// - /// Assert a Matrix5x4 (return it unchanged). - /// - /// The Matrix5x4 to assert (unchanged). - /// The asserted (unchanged) Matrix5x4. - public static Matrix5x4 operator +(Matrix5x4 value) - { - return value; - } - - /// - /// Subtracts two matrices. - /// - /// The first Matrix5x4 to subtract. - /// The second Matrix5x4 to subtract. - /// The difference between the two matrices. - public static Matrix5x4 operator -(Matrix5x4 left, Matrix5x4 right) - { - Matrix5x4 result; - Subtract(ref left, ref right, out result); - return result; - } - - /// - /// Negates a Matrix5x4. - /// - /// The Matrix5x4 to negate. - /// The negated Matrix5x4. - public static Matrix5x4 operator -(Matrix5x4 value) - { - Matrix5x4 result; - Negate(ref value, out result); - return result; - } - - /// - /// Scales a Matrix5x4 by a given value. - /// - /// The Matrix5x4 to scale. - /// The amount by which to scale. - /// The scaled Matrix5x4. - public static Matrix5x4 operator *(float left, Matrix5x4 right) - { - Matrix5x4 result; - Multiply(ref right, left, out result); - return result; - } - - /// - /// Scales a Matrix5x4 by a given value. - /// - /// The Matrix5x4 to scale. - /// The amount by which to scale. - /// The scaled Matrix5x4. - public static Matrix5x4 operator *(Matrix5x4 left, float right) - { - Matrix5x4 result; - Multiply(ref left, right, out result); - return result; - } - - /// - /// Scales a Matrix5x4 by a given value. - /// - /// The Matrix5x4 to scale. - /// The amount by which to scale. - /// The scaled Matrix5x4. - public static Matrix5x4 operator /(Matrix5x4 left, float right) - { - Matrix5x4 result; - Divide(ref left, right, out result); - return result; - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has the same value as ; otherwise, false. - public static bool operator ==(Matrix5x4 left, Matrix5x4 right) - { - return left.Equals(right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has a different value than ; otherwise, false. - public static bool operator !=(Matrix5x4 left, Matrix5x4 right) - { - return !left.Equals(right); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return string.Format(CultureInfo.CurrentCulture, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M3:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}] [M51:{16} M52:{17} M53:{18} M54:{19}]", - M11, M12, M13, M14, M21, M22, M23, M24, M31, M32, M33, M34, M41, M42, M43, M44, M51, M52, M53, M54); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// - /// A that represents this instance. - /// - public string ToString(string format) - { - if (format == null) - return ToString(); - - return string.Format(format, CultureInfo.CurrentCulture, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M3:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}] [M51:{16} M52:{17} M53:{18} M54:{19}]", - M11.ToString(format, CultureInfo.CurrentCulture), M12.ToString(format, CultureInfo.CurrentCulture), M13.ToString(format, CultureInfo.CurrentCulture), M14.ToString(format, CultureInfo.CurrentCulture), - M21.ToString(format, CultureInfo.CurrentCulture), M22.ToString(format, CultureInfo.CurrentCulture), M23.ToString(format, CultureInfo.CurrentCulture), M24.ToString(format, CultureInfo.CurrentCulture), - M31.ToString(format, CultureInfo.CurrentCulture), M32.ToString(format, CultureInfo.CurrentCulture), M33.ToString(format, CultureInfo.CurrentCulture), M34.ToString(format, CultureInfo.CurrentCulture), - M41.ToString(format, CultureInfo.CurrentCulture), M42.ToString(format, CultureInfo.CurrentCulture), M43.ToString(format, CultureInfo.CurrentCulture), M44.ToString(format, CultureInfo.CurrentCulture), - M51.ToString(format, CultureInfo.CurrentCulture), M52.ToString(format, CultureInfo.CurrentCulture), M53.ToString(format, CultureInfo.CurrentCulture), M54.ToString(format, CultureInfo.CurrentCulture)); - } - - /// - /// Returns a that represents this instance. - /// - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(IFormatProvider formatProvider) - { - return string.Format(formatProvider, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M3:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}] [M51:{16} M52:{17} M53:{18} M54:{19}]", - M11.ToString(formatProvider), M12.ToString(formatProvider), M13.ToString(formatProvider), M14.ToString(formatProvider), - M21.ToString(formatProvider), M22.ToString(formatProvider), M23.ToString(formatProvider), M24.ToString(formatProvider), - M31.ToString(formatProvider), M32.ToString(formatProvider), M33.ToString(formatProvider), M34.ToString(formatProvider), - M41.ToString(formatProvider), M42.ToString(formatProvider), M43.ToString(formatProvider), M44.ToString(formatProvider), - M51.ToString(formatProvider), M52.ToString(formatProvider), M53.ToString(formatProvider), M54.ToString(formatProvider)); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - if (format == null) - return ToString(formatProvider); - - return string.Format(format, formatProvider, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M3:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}] [M51:{16} M52:{17} M53:{18} M54:{19}]", - M11.ToString(format, formatProvider), M12.ToString(format, formatProvider), M13.ToString(format, formatProvider), M14.ToString(format, formatProvider), - M21.ToString(format, formatProvider), M22.ToString(format, formatProvider), M23.ToString(format, formatProvider), M24.ToString(format, formatProvider), - M31.ToString(format, formatProvider), M32.ToString(format, formatProvider), M33.ToString(format, formatProvider), M34.ToString(format, formatProvider), - M41.ToString(format, formatProvider), M42.ToString(format, formatProvider), M43.ToString(format, formatProvider), M44.ToString(format, formatProvider), - M51.ToString(format, formatProvider), M52.ToString(format, formatProvider), M53.ToString(format, formatProvider), M54.ToString(format, formatProvider)); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - var hashCode = M11.GetHashCode(); - hashCode = (hashCode * 397) ^ M12.GetHashCode(); - hashCode = (hashCode * 397) ^ M13.GetHashCode(); - hashCode = (hashCode * 397) ^ M14.GetHashCode(); - hashCode = (hashCode * 397) ^ M21.GetHashCode(); - hashCode = (hashCode * 397) ^ M22.GetHashCode(); - hashCode = (hashCode * 397) ^ M23.GetHashCode(); - hashCode = (hashCode * 397) ^ M24.GetHashCode(); - hashCode = (hashCode * 397) ^ M31.GetHashCode(); - hashCode = (hashCode * 397) ^ M32.GetHashCode(); - hashCode = (hashCode * 397) ^ M33.GetHashCode(); - hashCode = (hashCode * 397) ^ M34.GetHashCode(); - hashCode = (hashCode * 397) ^ M41.GetHashCode(); - hashCode = (hashCode * 397) ^ M42.GetHashCode(); - hashCode = (hashCode * 397) ^ M43.GetHashCode(); - hashCode = (hashCode * 397) ^ M44.GetHashCode(); - hashCode = (hashCode * 397) ^ M51.GetHashCode(); - hashCode = (hashCode * 397) ^ M52.GetHashCode(); - hashCode = (hashCode * 397) ^ M53.GetHashCode(); - hashCode = (hashCode * 397) ^ M54.GetHashCode(); - return hashCode; - } - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(Matrix5x4 other) - { - return (MathUtil.NearEqual(other.M11, M11) && - MathUtil.NearEqual(other.M12, M12) && - MathUtil.NearEqual(other.M13, M13) && - MathUtil.NearEqual(other.M14, M14) && - MathUtil.NearEqual(other.M21, M21) && - MathUtil.NearEqual(other.M22, M22) && - MathUtil.NearEqual(other.M23, M23) && - MathUtil.NearEqual(other.M24, M24) && - MathUtil.NearEqual(other.M31, M31) && - MathUtil.NearEqual(other.M32, M32) && - MathUtil.NearEqual(other.M33, M33) && - MathUtil.NearEqual(other.M34, M34) && - MathUtil.NearEqual(other.M41, M41) && - MathUtil.NearEqual(other.M42, M42) && - MathUtil.NearEqual(other.M43, M43) && - MathUtil.NearEqual(other.M44, M44) && - MathUtil.NearEqual(other.M51, M51) && - MathUtil.NearEqual(other.M52, M52) && - MathUtil.NearEqual(other.M53, M53) && - MathUtil.NearEqual(other.M54, M54)); - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object value) - { - if (value == null) - return false; - - if (!ReferenceEquals(value.GetType(), typeof(Matrix5x4))) - return false; - - return Equals((Matrix5x4)value); - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(M11); - serializer.Writer.Write(M12); - serializer.Writer.Write(M13); - serializer.Writer.Write(M14); - serializer.Writer.Write(M21); - serializer.Writer.Write(M22); - serializer.Writer.Write(M23); - serializer.Writer.Write(M24); - serializer.Writer.Write(M31); - serializer.Writer.Write(M32); - serializer.Writer.Write(M33); - serializer.Writer.Write(M34); - serializer.Writer.Write(M41); - serializer.Writer.Write(M42); - serializer.Writer.Write(M43); - serializer.Writer.Write(M44); - serializer.Writer.Write(M51); - serializer.Writer.Write(M52); - serializer.Writer.Write(M53); - serializer.Writer.Write(M54); - } - else - { - M11 = serializer.Reader.ReadSingle(); - M12 = serializer.Reader.ReadSingle(); - M13 = serializer.Reader.ReadSingle(); - M14 = serializer.Reader.ReadSingle(); - M21 = serializer.Reader.ReadSingle(); - M22 = serializer.Reader.ReadSingle(); - M23 = serializer.Reader.ReadSingle(); - M24 = serializer.Reader.ReadSingle(); - M31 = serializer.Reader.ReadSingle(); - M32 = serializer.Reader.ReadSingle(); - M33 = serializer.Reader.ReadSingle(); - M34 = serializer.Reader.ReadSingle(); - M41 = serializer.Reader.ReadSingle(); - M42 = serializer.Reader.ReadSingle(); - M43 = serializer.Reader.ReadSingle(); - M44 = serializer.Reader.ReadSingle(); - M51 = serializer.Reader.ReadSingle(); - M52 = serializer.Reader.ReadSingle(); - M53 = serializer.Reader.ReadSingle(); - M54 = serializer.Reader.ReadSingle(); - } - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Represents a 4x4 mathematical Matrix5x4. + /// + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct Matrix5x4 : IEquatable, IFormattable + { + /// + /// The size of the type, in bytes. + /// + public static readonly int SizeInBytes = Marshal.SizeOf(typeof(Matrix5x4)); + + /// + /// A with all of its components set to zero. + /// + public static readonly Matrix5x4 Zero = new Matrix5x4(); + + /// + /// The identity . + /// + public static readonly Matrix5x4 Identity = new Matrix5x4() { M11 = 1.0f, M22 = 1.0f, M33 = 1.0f, M44 = 1.0f, M54 = 0.0f }; + + /// + /// Value at row 1 column 1 of the Matrix5x4. + /// + public float M11; + + /// + /// Value at row 1 column 2 of the Matrix5x4. + /// + public float M12; + + /// + /// Value at row 1 column 3 of the Matrix5x4. + /// + public float M13; + + /// + /// Value at row 1 column 4 of the Matrix5x4. + /// + public float M14; + + /// + /// Value at row 2 column 1 of the Matrix5x4. + /// + public float M21; + + /// + /// Value at row 2 column 2 of the Matrix5x4. + /// + public float M22; + + /// + /// Value at row 2 column 3 of the Matrix5x4. + /// + public float M23; + + /// + /// Value at row 2 column 4 of the Matrix5x4. + /// + public float M24; + + /// + /// Value at row 3 column 1 of the Matrix5x4. + /// + public float M31; + + /// + /// Value at row 3 column 2 of the Matrix5x4. + /// + public float M32; + + /// + /// Value at row 3 column 3 of the Matrix5x4. + /// + public float M33; + + /// + /// Value at row 3 column 4 of the Matrix5x4. + /// + public float M34; + + /// + /// Value at row 4 column 1 of the Matrix5x4. + /// + public float M41; + + /// + /// Value at row 4 column 2 of the Matrix5x4. + /// + public float M42; + + /// + /// Value at row 4 column 3 of the Matrix5x4. + /// + public float M43; + + /// + /// Value at row 4 column 4 of the Matrix5x4. + /// + public float M44; + + /// + /// Value at row 5 column 1 of the Matrix5x4. + /// + public float M51; + + /// + /// Value at row 5 column 2 of the Matrix5x4. + /// + public float M52; + + /// + /// Value at row 5 column 3 of the Matrix5x4. + /// + public float M53; + + /// + /// Value at row 5 column 4 of the Matrix5x4. + /// + public float M54; + + /// + /// Initializes a new instance of the struct. + /// + /// The value that will be assigned to all components. + public Matrix5x4(float value) + { + M11 = M12 = M13 = M14 = + M21 = M22 = M23 = M24 = + M31 = M32 = M33 = M34 = + M41 = M42 = M43 = M44 = + M51 = M52 = M53 = M54 = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The value to assign at row 1 column 1 of the Matrix5x4. + /// The value to assign at row 1 column 2 of the Matrix5x4. + /// The value to assign at row 1 column 3 of the Matrix5x4. + /// The value to assign at row 1 column 4 of the Matrix5x4. + /// The value to assign at row 2 column 1 of the Matrix5x4. + /// The value to assign at row 2 column 2 of the Matrix5x4. + /// The value to assign at row 2 column 3 of the Matrix5x4. + /// The value to assign at row 2 column 4 of the Matrix5x4. + /// The value to assign at row 3 column 1 of the Matrix5x4. + /// The value to assign at row 3 column 2 of the Matrix5x4. + /// The value to assign at row 3 column 3 of the Matrix5x4. + /// The value to assign at row 3 column 4 of the Matrix5x4. + /// The value to assign at row 4 column 1 of the Matrix5x4. + /// The value to assign at row 4 column 2 of the Matrix5x4. + /// The value to assign at row 4 column 3 of the Matrix5x4. + /// The value to assign at row 4 column 4 of the Matrix5x4. + /// The value to assign at row 5 column 1 of the Matrix5x4. + /// The value to assign at row 5 column 2 of the Matrix5x4. + /// The value to assign at row 5 column 3 of the Matrix5x4. + /// The value to assign at row 5 column 4 of the Matrix5x4. + public Matrix5x4(float M11, float M12, float M13, float M14, + float M21, float M22, float M23, float M24, + float M31, float M32, float M33, float M34, + float M41, float M42, float M43, float M44, + float M51, float M52, float M53, float M54) + { + this.M11 = M11; this.M12 = M12; this.M13 = M13; this.M14 = M14; + this.M21 = M21; this.M22 = M22; this.M23 = M23; this.M24 = M24; + this.M31 = M31; this.M32 = M32; this.M33 = M33; this.M34 = M34; + this.M41 = M41; this.M42 = M42; this.M43 = M43; this.M44 = M44; + this.M51 = M51; this.M52 = M52; this.M53 = M53; this.M54 = M54; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The values to assign to the components of the Matrix5x4. This must be an array with sixteen elements. + /// Thrown when is null. + /// Thrown when contains more or less than sixteen elements. + public Matrix5x4(float[] values) + { + if (values == null) + throw new ArgumentNullException("values"); + if (values.Length != 20) + throw new ArgumentOutOfRangeException("values", "There must be 20 input values for Matrix5x4."); + + M11 = values[0]; + M12 = values[1]; + M13 = values[2]; + M14 = values[3]; + + M21 = values[4]; + M22 = values[5]; + M23 = values[6]; + M24 = values[7]; + + M31 = values[8]; + M32 = values[9]; + M33 = values[10]; + M34 = values[11]; + + M41 = values[12]; + M42 = values[13]; + M43 = values[14]; + M44 = values[15]; + + M51 = values[16]; + M52 = values[17]; + M53 = values[18]; + M54 = values[19]; + } + + /// + /// Gets or sets the first row in the Matrix5x4; that is M11, M12, M13, and M14. + /// + public Vector4 Row1 + { + get { return new Vector4(M11, M12, M13, M14); } + set { M11 = value.X; M12 = value.Y; M13 = value.Z; M14 = value.W; } + } + + /// + /// Gets or sets the second row in the Matrix5x4; that is M21, M22, M23, and M24. + /// + public Vector4 Row2 + { + get { return new Vector4(M21, M22, M23, M24); } + set { M21 = value.X; M22 = value.Y; M23 = value.Z; M24 = value.W; } + } + + /// + /// Gets or sets the third row in the Matrix5x4; that is M31, M32, M33, and M34. + /// + public Vector4 Row3 + { + get { return new Vector4(M31, M32, M33, M34); } + set { M31 = value.X; M32 = value.Y; M33 = value.Z; M34 = value.W; } + } + + /// + /// Gets or sets the fourth row in the Matrix5x4; that is M41, M42, M43, and M44. + /// + public Vector4 Row4 + { + get { return new Vector4(M41, M42, M43, M44); } + set { M41 = value.X; M42 = value.Y; M43 = value.Z; M44 = value.W; } + } + + /// + /// Gets or sets the fifth row in the Matrix5x4; that is M51, M52, M53, and M54. + /// + public Vector4 Row5 + { + get { return new Vector4(M51, M52, M53, M54); } + set { M51 = value.X; M52 = value.Y; M53 = value.Z; M54 = value.W; } + } + + /// + /// Gets or sets the translation of the Matrix5x4; that is M41, M42, and M43. + /// + public Vector4 TranslationVector + { + get { return new Vector4(M51, M52, M53, M54); } + set { M51 = value.X; M52 = value.Y; M53 = value.Z; M54 = value.W; } + } + + /// + /// Gets or sets the scale of the Matrix5x4; that is M11, M22, and M33. + /// + public Vector4 ScaleVector + { + get { return new Vector4(M11, M22, M33, M44); } + set { M11 = value.X; M22 = value.Y; M33 = value.Z; M44 = value.W; } + } + + /// + /// Gets a value indicating whether this instance is an identity Matrix5x4. + /// + /// + /// true if this instance is an identity Matrix5x4; otherwise, false. + /// + public bool IsIdentity + { + get { return this.Equals(Identity); } + } + + /// + /// Gets or sets the component at the specified index. + /// + /// The value of the Matrix5x4 component, depending on the index. + /// The zero-based index of the component to access. + /// The value of the component at the specified index. + /// Thrown when the is out of the range [0, 15]. + public float this[int index] + { + get + { + switch (index) + { + case 0: return M11; + case 1: return M12; + case 2: return M13; + case 3: return M14; + case 4: return M21; + case 5: return M22; + case 6: return M23; + case 7: return M24; + case 8: return M31; + case 9: return M32; + case 10: return M33; + case 11: return M34; + case 12: return M41; + case 13: return M42; + case 14: return M43; + case 15: return M44; + case 16: return M51; + case 17: return M52; + case 18: return M53; + case 19: return M54; + } + + throw new ArgumentOutOfRangeException("index", "Indices for Matrix5x4 run from 0 to 19, inclusive."); + } + + set + { + switch (index) + { + case 0: M11 = value; break; + case 1: M12 = value; break; + case 2: M13 = value; break; + case 3: M14 = value; break; + case 4: M21 = value; break; + case 5: M22 = value; break; + case 6: M23 = value; break; + case 7: M24 = value; break; + case 8: M31 = value; break; + case 9: M32 = value; break; + case 10: M33 = value; break; + case 11: M34 = value; break; + case 12: M41 = value; break; + case 13: M42 = value; break; + case 14: M43 = value; break; + case 15: M44 = value; break; + case 16: M51 = value; break; + case 17: M52 = value; break; + case 18: M53 = value; break; + case 19: M54 = value; break; + default: throw new ArgumentOutOfRangeException("index", "Indices for Matrix5x4 run from 0 to 19, inclusive."); + } + } + } + + /// + /// Gets or sets the component at the specified index. + /// + /// The value of the Matrix5x4 component, depending on the index. + /// The row of the Matrix5x4 to access. + /// The column of the Matrix5x4 to access. + /// The value of the component at the specified index. + /// Thrown when the or is out of the range [0, 3]. + public float this[int row, int column] + { + get + { + if (row < 0 || row > 4) + throw new ArgumentOutOfRangeException("row", "Rows for matrices run from 0 to 4, inclusive."); + if (column < 0 || column > 3) + throw new ArgumentOutOfRangeException("column", "Columns for matrices run from 0 to 3, inclusive."); + + return this[(row * 4) + column]; + } + + set + { + if (row < 0 || row > 4) + throw new ArgumentOutOfRangeException("row", "Rows for matrices run from 0 to 4, inclusive."); + if (column < 0 || column > 3) + throw new ArgumentOutOfRangeException("column", "Columns for matrices run from 0 to 3, inclusive."); + + this[(row * 4) + column] = value; + } + } + + /// + /// Determines the sum of two matrices. + /// + /// The first Matrix5x4 to add. + /// The second Matrix5x4 to add. + /// When the method completes, contains the sum of the two matrices. + public static void Add(ref Matrix5x4 left, ref Matrix5x4 right, out Matrix5x4 result) + { + result.M11 = left.M11 + right.M11; + result.M12 = left.M12 + right.M12; + result.M13 = left.M13 + right.M13; + result.M14 = left.M14 + right.M14; + result.M21 = left.M21 + right.M21; + result.M22 = left.M22 + right.M22; + result.M23 = left.M23 + right.M23; + result.M24 = left.M24 + right.M24; + result.M31 = left.M31 + right.M31; + result.M32 = left.M32 + right.M32; + result.M33 = left.M33 + right.M33; + result.M34 = left.M34 + right.M34; + result.M41 = left.M41 + right.M41; + result.M42 = left.M42 + right.M42; + result.M43 = left.M43 + right.M43; + result.M44 = left.M44 + right.M44; + result.M51 = left.M51 + right.M51; + result.M52 = left.M52 + right.M52; + result.M53 = left.M53 + right.M53; + result.M54 = left.M54 + right.M54; + } + + /// + /// Determines the sum of two matrices. + /// + /// The first Matrix5x4 to add. + /// The second Matrix5x4 to add. + /// The sum of the two matrices. + public static Matrix5x4 Add(Matrix5x4 left, Matrix5x4 right) + { + Matrix5x4 result; + Add(ref left, ref right, out result); + return result; + } + + /// + /// Determines the difference between two matrices. + /// + /// The first Matrix5x4 to subtract. + /// The second Matrix5x4 to subtract. + /// When the method completes, contains the difference between the two matrices. + public static void Subtract(ref Matrix5x4 left, ref Matrix5x4 right, out Matrix5x4 result) + { + result.M11 = left.M11 - right.M11; + result.M12 = left.M12 - right.M12; + result.M13 = left.M13 - right.M13; + result.M14 = left.M14 - right.M14; + result.M21 = left.M21 - right.M21; + result.M22 = left.M22 - right.M22; + result.M23 = left.M23 - right.M23; + result.M24 = left.M24 - right.M24; + result.M31 = left.M31 - right.M31; + result.M32 = left.M32 - right.M32; + result.M33 = left.M33 - right.M33; + result.M34 = left.M34 - right.M34; + result.M41 = left.M41 - right.M41; + result.M42 = left.M42 - right.M42; + result.M43 = left.M43 - right.M43; + result.M44 = left.M44 - right.M44; + result.M51 = left.M51 - right.M51; + result.M52 = left.M52 - right.M52; + result.M53 = left.M53 - right.M53; + result.M54 = left.M54 - right.M54; + } + + /// + /// Determines the difference between two matrices. + /// + /// The first Matrix5x4 to subtract. + /// The second Matrix5x4 to subtract. + /// The difference between the two matrices. + public static Matrix5x4 Subtract(Matrix5x4 left, Matrix5x4 right) + { + Matrix5x4 result; + Subtract(ref left, ref right, out result); + return result; + } + + /// + /// Scales a Matrix5x4 by the given value. + /// + /// The Matrix5x4 to scale. + /// The amount by which to scale. + /// When the method completes, contains the scaled Matrix5x4. + public static void Multiply(ref Matrix5x4 left, float right, out Matrix5x4 result) + { + result.M11 = left.M11 * right; + result.M12 = left.M12 * right; + result.M13 = left.M13 * right; + result.M14 = left.M14 * right; + result.M21 = left.M21 * right; + result.M22 = left.M22 * right; + result.M23 = left.M23 * right; + result.M24 = left.M24 * right; + result.M31 = left.M31 * right; + result.M32 = left.M32 * right; + result.M33 = left.M33 * right; + result.M34 = left.M34 * right; + result.M41 = left.M41 * right; + result.M42 = left.M42 * right; + result.M43 = left.M43 * right; + result.M44 = left.M44 * right; + result.M51 = left.M51 * right; + result.M52 = left.M52 * right; + result.M53 = left.M53 * right; + result.M54 = left.M54 * right; + } + + /// + /// Scales a Matrix5x4 by the given value. + /// + /// The Matrix5x4 to scale. + /// The amount by which to scale. + /// When the method completes, contains the scaled Matrix5x4. + public static void Divide(ref Matrix5x4 left, float right, out Matrix5x4 result) + { + float inv = 1.0f / right; + + result.M11 = left.M11 * inv; + result.M12 = left.M12 * inv; + result.M13 = left.M13 * inv; + result.M14 = left.M14 * inv; + result.M21 = left.M21 * inv; + result.M22 = left.M22 * inv; + result.M23 = left.M23 * inv; + result.M24 = left.M24 * inv; + result.M31 = left.M31 * inv; + result.M32 = left.M32 * inv; + result.M33 = left.M33 * inv; + result.M34 = left.M34 * inv; + result.M41 = left.M41 * inv; + result.M42 = left.M42 * inv; + result.M43 = left.M43 * inv; + result.M44 = left.M44 * inv; + result.M51 = left.M51 * inv; + result.M52 = left.M52 * inv; + result.M53 = left.M53 * inv; + result.M54 = left.M54 * inv; + } + + /// + /// Negates a Matrix5x4. + /// + /// The Matrix5x4 to be negated. + /// When the method completes, contains the negated Matrix5x4. + public static void Negate(ref Matrix5x4 value, out Matrix5x4 result) + { + result.M11 = -value.M11; + result.M12 = -value.M12; + result.M13 = -value.M13; + result.M14 = -value.M14; + result.M21 = -value.M21; + result.M22 = -value.M22; + result.M23 = -value.M23; + result.M24 = -value.M24; + result.M31 = -value.M31; + result.M32 = -value.M32; + result.M33 = -value.M33; + result.M34 = -value.M34; + result.M41 = -value.M41; + result.M42 = -value.M42; + result.M43 = -value.M43; + result.M44 = -value.M44; + result.M51 = -value.M51; + result.M52 = -value.M52; + result.M53 = -value.M53; + result.M54 = -value.M54; + } + + /// + /// Negates a Matrix5x4. + /// + /// The Matrix5x4 to be negated. + /// The negated Matrix5x4. + public static Matrix5x4 Negate(Matrix5x4 value) + { + Matrix5x4 result; + Negate(ref value, out result); + return result; + } + + /// + /// Performs a linear interpolation between two matrices. + /// + /// Start Matrix5x4. + /// End Matrix5x4. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the linear interpolation of the two matrices. + /// + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static void Lerp(ref Matrix5x4 start, ref Matrix5x4 end, float amount, out Matrix5x4 result) + { + result.M11 = MathUtil.Lerp(start.M11, end.M11, amount); + result.M12 = MathUtil.Lerp(start.M12, end.M12, amount); + result.M13 = MathUtil.Lerp(start.M13, end.M13, amount); + result.M14 = MathUtil.Lerp(start.M14, end.M14, amount); + result.M21 = MathUtil.Lerp(start.M21, end.M21, amount); + result.M22 = MathUtil.Lerp(start.M22, end.M22, amount); + result.M23 = MathUtil.Lerp(start.M23, end.M23, amount); + result.M24 = MathUtil.Lerp(start.M24, end.M24, amount); + result.M31 = MathUtil.Lerp(start.M31, end.M31, amount); + result.M32 = MathUtil.Lerp(start.M32, end.M32, amount); + result.M33 = MathUtil.Lerp(start.M33, end.M33, amount); + result.M34 = MathUtil.Lerp(start.M34, end.M34, amount); + result.M41 = MathUtil.Lerp(start.M41, end.M41, amount); + result.M42 = MathUtil.Lerp(start.M42, end.M42, amount); + result.M43 = MathUtil.Lerp(start.M43, end.M43, amount); + result.M44 = MathUtil.Lerp(start.M44, end.M44, amount); + result.M51 = MathUtil.Lerp(start.M51, end.M51, amount); + result.M52 = MathUtil.Lerp(start.M52, end.M52, amount); + result.M53 = MathUtil.Lerp(start.M53, end.M53, amount); + result.M54 = MathUtil.Lerp(start.M54, end.M54, amount); + } + + /// + /// Performs a linear interpolation between two matrices. + /// + /// Start Matrix5x4. + /// End Matrix5x4. + /// Value between 0 and 1 indicating the weight of . + /// The linear interpolation of the two matrices. + /// + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static Matrix5x4 Lerp(Matrix5x4 start, Matrix5x4 end, float amount) + { + Matrix5x4 result; + Lerp(ref start, ref end, amount, out result); + return result; + } + + /// + /// Performs a cubic interpolation between two matrices. + /// + /// Start Matrix5x4. + /// End Matrix5x4. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the cubic interpolation of the two matrices. + public static void SmoothStep(ref Matrix5x4 start, ref Matrix5x4 end, float amount, out Matrix5x4 result) + { + amount = MathUtil.SmoothStep(amount); + Lerp(ref start, ref end, amount, out result); + } + + /// + /// Performs a cubic interpolation between two matrices. + /// + /// Start Matrix5x4. + /// End Matrix5x4. + /// Value between 0 and 1 indicating the weight of . + /// The cubic interpolation of the two matrices. + public static Matrix5x4 SmoothStep(Matrix5x4 start, Matrix5x4 end, float amount) + { + Matrix5x4 result; + SmoothStep(ref start, ref end, amount, out result); + return result; + } + + /// + /// Creates a Matrix5x4 that scales along the x-axis, y-axis, y-axis and w-axis + /// + /// Scaling factor for all three axes. + /// When the method completes, contains the created scaling Matrix5x4. + public static void Scaling(ref Vector4 scale, out Matrix5x4 result) + { + Scaling(scale.X, scale.Y, scale.Z, scale.W, out result); + } + + /// + /// Creates a Matrix5x4 that scales along the x-axis, y-axis, and y-axis. + /// + /// Scaling factor for all three axes. + /// The created scaling Matrix5x4. + public static Matrix5x4 Scaling(Vector4 scale) + { + Matrix5x4 result; + Scaling(ref scale, out result); + return result; + } + + /// + /// Creates a Matrix5x4 that scales along the x-axis, y-axis, z-axis and w-axis. + /// + /// Scaling factor that is applied along the x-axis. + /// Scaling factor that is applied along the y-axis. + /// Scaling factor that is applied along the z-axis. + /// Scaling factor that is applied along the w-axis. + /// When the method completes, contains the created scaling Matrix5x4. + public static void Scaling(float x, float y, float z, float w, out Matrix5x4 result) + { + result = Matrix5x4.Identity; + result.M11 = x; + result.M22 = y; + result.M33 = z; + result.M44 = w; + } + + /// + /// Creates a Matrix5x4 that scales along the x-axis, y-axis, z-axis and w-axis. + /// + /// Scaling factor that is applied along the x-axis. + /// Scaling factor that is applied along the y-axis. + /// Scaling factor that is applied along the z-axis. + /// Scaling factor that is applied along the w-axis. + /// The created scaling Matrix5x4. + public static Matrix5x4 Scaling(float x, float y, float z, float w) + { + Matrix5x4 result; + Scaling(x, y, z, w, out result); + return result; + } + + /// + /// Creates a Matrix5x4 that uniformly scales along all three axis. + /// + /// The uniform scale that is applied along all axis. + /// When the method completes, contains the created scaling Matrix5x4. + public static void Scaling(float scale, out Matrix5x4 result) + { + result = Matrix5x4.Identity; + result.M11 = result.M22 = result.M33 = result.M44 = scale; + } + + /// + /// Creates a Matrix5x4 that uniformly scales along all three axis. + /// + /// The uniform scale that is applied along all axis. + /// The created scaling Matrix5x4. + public static Matrix5x4 Scaling(float scale) + { + Matrix5x4 result; + Scaling(scale, out result); + return result; + } + + /// + /// Creates a translation Matrix5x4 using the specified offsets. + /// + /// The offset for all three coordinate planes. + /// When the method completes, contains the created translation Matrix5x4. + public static void Translation(ref Vector4 value, out Matrix5x4 result) + { + Translation(value.X, value.Y, value.Z, value.W, out result); + } + + /// + /// Creates a translation Matrix5x4 using the specified offsets. + /// + /// The offset for all three coordinate planes. + /// The created translation Matrix5x4. + public static Matrix5x4 Translation(Vector4 value) + { + Matrix5x4 result; + Translation(ref value, out result); + return result; + } + + /// + /// Creates a translation Matrix5x4 using the specified offsets. + /// + /// X-coordinate offset. + /// Y-coordinate offset. + /// Z-coordinate offset. + /// W-coordinate offset. + /// When the method completes, contains the created translation Matrix5x4. + public static void Translation(float x, float y, float z, float w, out Matrix5x4 result) + { + result = Matrix5x4.Identity; + result.M51 = x; + result.M52 = y; + result.M53 = z; + result.M54 = w; + } + + /// + /// Creates a translation Matrix5x4 using the specified offsets. + /// + /// X-coordinate offset. + /// Y-coordinate offset. + /// Z-coordinate offset. + /// W-coordinate offset. + /// The created translation Matrix5x4. + public static Matrix5x4 Translation(float x, float y, float z, float w) + { + Matrix5x4 result; + Translation(x, y, z, w, out result); + return result; + } + + /// + /// Adds two matrices. + /// + /// The first Matrix5x4 to add. + /// The second Matrix5x4 to add. + /// The sum of the two matrices. + public static Matrix5x4 operator +(Matrix5x4 left, Matrix5x4 right) + { + Matrix5x4 result; + Add(ref left, ref right, out result); + return result; + } + + /// + /// Assert a Matrix5x4 (return it unchanged). + /// + /// The Matrix5x4 to assert (unchanged). + /// The asserted (unchanged) Matrix5x4. + public static Matrix5x4 operator +(Matrix5x4 value) + { + return value; + } + + /// + /// Subtracts two matrices. + /// + /// The first Matrix5x4 to subtract. + /// The second Matrix5x4 to subtract. + /// The difference between the two matrices. + public static Matrix5x4 operator -(Matrix5x4 left, Matrix5x4 right) + { + Matrix5x4 result; + Subtract(ref left, ref right, out result); + return result; + } + + /// + /// Negates a Matrix5x4. + /// + /// The Matrix5x4 to negate. + /// The negated Matrix5x4. + public static Matrix5x4 operator -(Matrix5x4 value) + { + Matrix5x4 result; + Negate(ref value, out result); + return result; + } + + /// + /// Scales a Matrix5x4 by a given value. + /// + /// The Matrix5x4 to scale. + /// The amount by which to scale. + /// The scaled Matrix5x4. + public static Matrix5x4 operator *(float left, Matrix5x4 right) + { + Matrix5x4 result; + Multiply(ref right, left, out result); + return result; + } + + /// + /// Scales a Matrix5x4 by a given value. + /// + /// The Matrix5x4 to scale. + /// The amount by which to scale. + /// The scaled Matrix5x4. + public static Matrix5x4 operator *(Matrix5x4 left, float right) + { + Matrix5x4 result; + Multiply(ref left, right, out result); + return result; + } + + /// + /// Scales a Matrix5x4 by a given value. + /// + /// The Matrix5x4 to scale. + /// The amount by which to scale. + /// The scaled Matrix5x4. + public static Matrix5x4 operator /(Matrix5x4 left, float right) + { + Matrix5x4 result; + Divide(ref left, right, out result); + return result; + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has the same value as ; otherwise, false. + public static bool operator ==(Matrix5x4 left, Matrix5x4 right) + { + return left.Equals(right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has a different value than ; otherwise, false. + public static bool operator !=(Matrix5x4 left, Matrix5x4 right) + { + return !left.Equals(right); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return string.Format(CultureInfo.CurrentCulture, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M3:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}] [M51:{16} M52:{17} M53:{18} M54:{19}]", + M11, M12, M13, M14, M21, M22, M23, M24, M31, M32, M33, M34, M41, M42, M43, M44, M51, M52, M53, M54); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// + /// A that represents this instance. + /// + public string ToString(string format) + { + if (format == null) + return ToString(); + + return string.Format(format, CultureInfo.CurrentCulture, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M3:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}] [M51:{16} M52:{17} M53:{18} M54:{19}]", + M11.ToString(format, CultureInfo.CurrentCulture), M12.ToString(format, CultureInfo.CurrentCulture), M13.ToString(format, CultureInfo.CurrentCulture), M14.ToString(format, CultureInfo.CurrentCulture), + M21.ToString(format, CultureInfo.CurrentCulture), M22.ToString(format, CultureInfo.CurrentCulture), M23.ToString(format, CultureInfo.CurrentCulture), M24.ToString(format, CultureInfo.CurrentCulture), + M31.ToString(format, CultureInfo.CurrentCulture), M32.ToString(format, CultureInfo.CurrentCulture), M33.ToString(format, CultureInfo.CurrentCulture), M34.ToString(format, CultureInfo.CurrentCulture), + M41.ToString(format, CultureInfo.CurrentCulture), M42.ToString(format, CultureInfo.CurrentCulture), M43.ToString(format, CultureInfo.CurrentCulture), M44.ToString(format, CultureInfo.CurrentCulture), + M51.ToString(format, CultureInfo.CurrentCulture), M52.ToString(format, CultureInfo.CurrentCulture), M53.ToString(format, CultureInfo.CurrentCulture), M54.ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format(formatProvider, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M3:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}] [M51:{16} M52:{17} M53:{18} M54:{19}]", + M11.ToString(formatProvider), M12.ToString(formatProvider), M13.ToString(formatProvider), M14.ToString(formatProvider), + M21.ToString(formatProvider), M22.ToString(formatProvider), M23.ToString(formatProvider), M24.ToString(formatProvider), + M31.ToString(formatProvider), M32.ToString(formatProvider), M33.ToString(formatProvider), M34.ToString(formatProvider), + M41.ToString(formatProvider), M42.ToString(formatProvider), M43.ToString(formatProvider), M44.ToString(formatProvider), + M51.ToString(formatProvider), M52.ToString(formatProvider), M53.ToString(formatProvider), M54.ToString(formatProvider)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(string format, IFormatProvider formatProvider) + { + if (format == null) + return ToString(formatProvider); + + return string.Format(format, formatProvider, "[M11:{0} M12:{1} M13:{2} M14:{3}] [M21:{4} M22:{5} M3:{6} M24:{7}] [M31:{8} M32:{9} M33:{10} M34:{11}] [M41:{12} M42:{13} M43:{14} M44:{15}] [M51:{16} M52:{17} M53:{18} M54:{19}]", + M11.ToString(format, formatProvider), M12.ToString(format, formatProvider), M13.ToString(format, formatProvider), M14.ToString(format, formatProvider), + M21.ToString(format, formatProvider), M22.ToString(format, formatProvider), M23.ToString(format, formatProvider), M24.ToString(format, formatProvider), + M31.ToString(format, formatProvider), M32.ToString(format, formatProvider), M33.ToString(format, formatProvider), M34.ToString(format, formatProvider), + M41.ToString(format, formatProvider), M42.ToString(format, formatProvider), M43.ToString(format, formatProvider), M44.ToString(format, formatProvider), + M51.ToString(format, formatProvider), M52.ToString(format, formatProvider), M53.ToString(format, formatProvider), M54.ToString(format, formatProvider)); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + unchecked + { + var hashCode = M11.GetHashCode(); + hashCode = (hashCode * 397) ^ M12.GetHashCode(); + hashCode = (hashCode * 397) ^ M13.GetHashCode(); + hashCode = (hashCode * 397) ^ M14.GetHashCode(); + hashCode = (hashCode * 397) ^ M21.GetHashCode(); + hashCode = (hashCode * 397) ^ M22.GetHashCode(); + hashCode = (hashCode * 397) ^ M23.GetHashCode(); + hashCode = (hashCode * 397) ^ M24.GetHashCode(); + hashCode = (hashCode * 397) ^ M31.GetHashCode(); + hashCode = (hashCode * 397) ^ M32.GetHashCode(); + hashCode = (hashCode * 397) ^ M33.GetHashCode(); + hashCode = (hashCode * 397) ^ M34.GetHashCode(); + hashCode = (hashCode * 397) ^ M41.GetHashCode(); + hashCode = (hashCode * 397) ^ M42.GetHashCode(); + hashCode = (hashCode * 397) ^ M43.GetHashCode(); + hashCode = (hashCode * 397) ^ M44.GetHashCode(); + hashCode = (hashCode * 397) ^ M51.GetHashCode(); + hashCode = (hashCode * 397) ^ M52.GetHashCode(); + hashCode = (hashCode * 397) ^ M53.GetHashCode(); + hashCode = (hashCode * 397) ^ M54.GetHashCode(); + return hashCode; + } + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(Matrix5x4 other) + { + return (MathUtil.NearEqual(other.M11, M11) && + MathUtil.NearEqual(other.M12, M12) && + MathUtil.NearEqual(other.M13, M13) && + MathUtil.NearEqual(other.M14, M14) && + MathUtil.NearEqual(other.M21, M21) && + MathUtil.NearEqual(other.M22, M22) && + MathUtil.NearEqual(other.M23, M23) && + MathUtil.NearEqual(other.M24, M24) && + MathUtil.NearEqual(other.M31, M31) && + MathUtil.NearEqual(other.M32, M32) && + MathUtil.NearEqual(other.M33, M33) && + MathUtil.NearEqual(other.M34, M34) && + MathUtil.NearEqual(other.M41, M41) && + MathUtil.NearEqual(other.M42, M42) && + MathUtil.NearEqual(other.M43, M43) && + MathUtil.NearEqual(other.M44, M44) && + MathUtil.NearEqual(other.M51, M51) && + MathUtil.NearEqual(other.M52, M52) && + MathUtil.NearEqual(other.M53, M53) && + MathUtil.NearEqual(other.M54, M54)); + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object value) + { + if (value == null) + return false; + + if (!ReferenceEquals(value.GetType(), typeof(Matrix5x4))) + return false; + + return Equals((Matrix5x4)value); + } + } +} diff --git a/Source/SharpDX/Point.cs b/Source/SharpDX/Mathematics/Point.cs similarity index 88% rename from Source/SharpDX/Point.cs rename to Source/SharpDX/Mathematics/Point.cs index e9c453fd0..30c3f1580 100644 --- a/Source/SharpDX/Point.cs +++ b/Source/SharpDX/Mathematics/Point.cs @@ -20,7 +20,6 @@ using System; using System.Runtime.InteropServices; -using SharpDX.Serialization; namespace SharpDX { @@ -28,7 +27,7 @@ namespace SharpDX /// Structure using the same layout than . /// [StructLayout(LayoutKind.Sequential)] - public struct Point : IEquatable, IDataSerializable + public struct Point : IEquatable { /// /// A point with (0,0) coordinates. @@ -135,21 +134,5 @@ public static implicit operator Vector2(Point value) { return new Vector2(value.X, value.Y); } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(X); - serializer.Writer.Write(Y); - } - else - { - X = serializer.Reader.ReadInt32(); - Y = serializer.Reader.ReadInt32(); - } - } } } \ No newline at end of file diff --git a/Source/SharpDX/Quaternion.cs b/Source/SharpDX/Mathematics/Quaternion.cs similarity index 96% rename from Source/SharpDX/Quaternion.cs rename to Source/SharpDX/Mathematics/Quaternion.cs index 54f067310..677c4e25f 100644 --- a/Source/SharpDX/Quaternion.cs +++ b/Source/SharpDX/Mathematics/Quaternion.cs @@ -1,1523 +1,1502 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ----------------------------------------------------------------------------- -// Original code from SlimMath project. http://code.google.com/p/slimmath/ -// Greetings to SlimDX Group. Original code published with the following license: -// ----------------------------------------------------------------------------- -/* -* Copyright (c) 2007-2011 SlimDX Group -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Represents a four dimensional mathematical quaternion. - /// - [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct Quaternion : IEquatable, IFormattable, IDataSerializable - { - /// - /// The size of the type, in bytes. - /// - public static readonly int SizeInBytes = Marshal.SizeOf(typeof(Quaternion)); - - /// - /// A with all of its components set to zero. - /// - public static readonly Quaternion Zero = new Quaternion(); - - /// - /// A with all of its components set to one. - /// - public static readonly Quaternion One = new Quaternion(1.0f, 1.0f, 1.0f, 1.0f); - - /// - /// The identity (0, 0, 0, 1). - /// - public static readonly Quaternion Identity = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); - - /// - /// The X component of the quaternion. - /// - public float X; - - /// - /// The Y component of the quaternion. - /// - public float Y; - - /// - /// The Z component of the quaternion. - /// - public float Z; - - /// - /// The W component of the quaternion. - /// - public float W; - - /// - /// Initializes a new instance of the struct. - /// - /// The value that will be assigned to all components. - public Quaternion(float value) - { - X = value; - Y = value; - Z = value; - W = value; - } - - /// - /// Initializes a new instance of the struct. - /// - /// A vector containing the values with which to initialize the components. - public Quaternion(Vector4 value) - { - X = value.X; - Y = value.Y; - Z = value.Z; - W = value.W; - } - - /// - /// Initializes a new instance of the struct. - /// - /// A vector containing the values with which to initialize the X, Y, and Z components. - /// Initial value for the W component of the quaternion. - public Quaternion(Vector3 value, float w) - { - X = value.X; - Y = value.Y; - Z = value.Z; - W = w; - } - - /// - /// Initializes a new instance of the struct. - /// - /// A vector containing the values with which to initialize the X and Y components. - /// Initial value for the Z component of the quaternion. - /// Initial value for the W component of the quaternion. - public Quaternion(Vector2 value, float z, float w) - { - X = value.X; - Y = value.Y; - Z = z; - W = w; - } - - /// - /// Initializes a new instance of the struct. - /// - /// Initial value for the X component of the quaternion. - /// Initial value for the Y component of the quaternion. - /// Initial value for the Z component of the quaternion. - /// Initial value for the W component of the quaternion. - public Quaternion(float x, float y, float z, float w) - { - X = x; - Y = y; - Z = z; - W = w; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The values to assign to the X, Y, Z, and W components of the quaternion. This must be an array with four elements. - /// Thrown when is null. - /// Thrown when contains more or less than four elements. - public Quaternion(float[] values) - { - if (values == null) - throw new ArgumentNullException("values"); - if (values.Length != 4) - throw new ArgumentOutOfRangeException("values", "There must be four and only four input values for Quaternion."); - - X = values[0]; - Y = values[1]; - Z = values[2]; - W = values[3]; - } - - /// - /// Gets a value indicating whether this instance is equivalent to the identity quaternion. - /// - /// - /// true if this instance is an identity quaternion; otherwise, false. - /// - public bool IsIdentity - { - get { return this.Equals(Identity); } - } - - /// - /// Gets a value indicting whether this instance is normalized. - /// - public bool IsNormalized - { - get { return MathUtil.IsOne((X * X) + (Y * Y) + (Z * Z) + (W * W)); } - } - - /// - /// Gets the angle of the quaternion. - /// - /// The quaternion's angle. - public float Angle - { - get - { - float length = (X * X) + (Y * Y) + (Z * Z); - if (MathUtil.IsZero(length)) - return 0.0f; - - return (float)(2.0 * Math.Acos(MathUtil.Clamp(W, -1f, 1f))); - } - } - - /// - /// Gets the axis components of the quaternion. - /// - /// The axis components of the quaternion. - public Vector3 Axis - { - get - { - float length = (X * X) + (Y * Y) + (Z * Z); - if (MathUtil.IsZero(length)) - return Vector3.UnitX; - - float inv = 1.0f / (float)Math.Sqrt(length); - return new Vector3(X * inv, Y * inv, Z * inv); - } - } - - /// - /// Gets or sets the component at the specified index. - /// - /// The value of the X, Y, Z, or W component, depending on the index. - /// The index of the component to access. Use 0 for the X component, 1 for the Y component, 2 for the Z component, and 3 for the W component. - /// The value of the component at the specified index. - /// Thrown when the is out of the range [0, 3]. - public float this[int index] - { - get - { - switch (index) - { - case 0: return X; - case 1: return Y; - case 2: return Z; - case 3: return W; - } - - throw new ArgumentOutOfRangeException("index", "Indices for Quaternion run from 0 to 3, inclusive."); - } - - set - { - switch (index) - { - case 0: X = value; break; - case 1: Y = value; break; - case 2: Z = value; break; - case 3: W = value; break; - default: throw new ArgumentOutOfRangeException("index", "Indices for Quaternion run from 0 to 3, inclusive."); - } - } - } - - /// - /// Conjugates the quaternion. - /// - public void Conjugate() - { - X = -X; - Y = -Y; - Z = -Z; - } - - /// - /// Conjugates and renormalizes the quaternion. - /// - public void Invert() - { - float lengthSq = LengthSquared(); - if (!MathUtil.IsZero(lengthSq)) - { - lengthSq = 1.0f / lengthSq; - - X = -X * lengthSq; - Y = -Y * lengthSq; - Z = -Z * lengthSq; - W = W * lengthSq; - } - } - - /// - /// Calculates the length of the quaternion. - /// - /// The length of the quaternion. - /// - /// may be preferred when only the relative length is needed - /// and speed is of the essence. - /// - public float Length() - { - return (float)Math.Sqrt((X * X) + (Y * Y) + (Z * Z) + (W * W)); - } - - /// - /// Calculates the squared length of the quaternion. - /// - /// The squared length of the quaternion. - /// - /// This method may be preferred to when only a relative length is needed - /// and speed is of the essence. - /// - public float LengthSquared() - { - return (X * X) + (Y * Y) + (Z * Z) + (W * W); - } - - /// - /// Converts the quaternion into a unit quaternion. - /// - public void Normalize() - { - float length = Length(); - if (!MathUtil.IsZero(length)) - { - float inverse = 1.0f / length; - X *= inverse; - Y *= inverse; - Z *= inverse; - W *= inverse; - } - } - - /// - /// Creates an array containing the elements of the quaternion. - /// - /// A four-element array containing the components of the quaternion. - public float[] ToArray() - { - return new float[] { X, Y, Z, W }; - } - - /// - /// Adds two quaternions. - /// - /// The first quaternion to add. - /// The second quaternion to add. - /// When the method completes, contains the sum of the two quaternions. - public static void Add(ref Quaternion left, ref Quaternion right, out Quaternion result) - { - result.X = left.X + right.X; - result.Y = left.Y + right.Y; - result.Z = left.Z + right.Z; - result.W = left.W + right.W; - } - - /// - /// Adds two quaternions. - /// - /// The first quaternion to add. - /// The second quaternion to add. - /// The sum of the two quaternions. - public static Quaternion Add(Quaternion left, Quaternion right) - { - Quaternion result; - Add(ref left, ref right, out result); - return result; - } - - /// - /// Subtracts two quaternions. - /// - /// The first quaternion to subtract. - /// The second quaternion to subtract. - /// When the method completes, contains the difference of the two quaternions. - public static void Subtract(ref Quaternion left, ref Quaternion right, out Quaternion result) - { - result.X = left.X - right.X; - result.Y = left.Y - right.Y; - result.Z = left.Z - right.Z; - result.W = left.W - right.W; - } - - /// - /// Subtracts two quaternions. - /// - /// The first quaternion to subtract. - /// The second quaternion to subtract. - /// The difference of the two quaternions. - public static Quaternion Subtract(Quaternion left, Quaternion right) - { - Quaternion result; - Subtract(ref left, ref right, out result); - return result; - } - - /// - /// Scales a quaternion by the given value. - /// - /// The quaternion to scale. - /// The amount by which to scale the quaternion. - /// When the method completes, contains the scaled quaternion. - public static void Multiply(ref Quaternion value, float scale, out Quaternion result) - { - result.X = value.X * scale; - result.Y = value.Y * scale; - result.Z = value.Z * scale; - result.W = value.W * scale; - } - - /// - /// Scales a quaternion by the given value. - /// - /// The quaternion to scale. - /// The amount by which to scale the quaternion. - /// The scaled quaternion. - public static Quaternion Multiply(Quaternion value, float scale) - { - Quaternion result; - Multiply(ref value, scale, out result); - return result; - } - - /// - /// Multiplies a quaternion by another. - /// - /// The first quaternion to multiply. - /// The second quaternion to multiply. - /// When the method completes, contains the multiplied quaternion. - public static void Multiply(ref Quaternion left, ref Quaternion right, out Quaternion result) - { - float lx = left.X; - float ly = left.Y; - float lz = left.Z; - float lw = left.W; - float rx = right.X; - float ry = right.Y; - float rz = right.Z; - float rw = right.W; - float a = (ly * rz - lz * ry); - float b = (lz * rx - lx * rz); - float c = (lx * ry - ly * rx); - float d = (lx * rx + ly * ry + lz * rz); - result.X = (lx * rw + rx * lw) + a; - result.Y = (ly * rw + ry * lw) + b; - result.Z = (lz * rw + rz * lw) + c; - result.W = lw * rw - d; - } - - /// - /// Multiplies a quaternion by another. - /// - /// The first quaternion to multiply. - /// The second quaternion to multiply. - /// The multiplied quaternion. - public static Quaternion Multiply(Quaternion left, Quaternion right) - { - Quaternion result; - Multiply(ref left, ref right, out result); - return result; - } - - /// - /// Reverses the direction of a given quaternion. - /// - /// The quaternion to negate. - /// When the method completes, contains a quaternion facing in the opposite direction. - public static void Negate(ref Quaternion value, out Quaternion result) - { - result.X = -value.X; - result.Y = -value.Y; - result.Z = -value.Z; - result.W = -value.W; - } - - /// - /// Reverses the direction of a given quaternion. - /// - /// The quaternion to negate. - /// A quaternion facing in the opposite direction. - public static Quaternion Negate(Quaternion value) - { - Quaternion result; - Negate(ref value, out result); - return result; - } - - /// - /// Returns a containing the 4D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 2D triangle. - /// - /// A containing the 4D Cartesian coordinates of vertex 1 of the triangle. - /// A containing the 4D Cartesian coordinates of vertex 2 of the triangle. - /// A containing the 4D Cartesian coordinates of vertex 3 of the triangle. - /// Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). - /// Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). - /// When the method completes, contains a new containing the 4D Cartesian coordinates of the specified point. - public static void Barycentric(ref Quaternion value1, ref Quaternion value2, ref Quaternion value3, float amount1, float amount2, out Quaternion result) - { - Quaternion start, end; - Slerp(ref value1, ref value2, amount1 + amount2, out start); - Slerp(ref value1, ref value3, amount1 + amount2, out end); - Slerp(ref start, ref end, amount2 / (amount1 + amount2), out result); - } - - /// - /// Returns a containing the 4D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 2D triangle. - /// - /// A containing the 4D Cartesian coordinates of vertex 1 of the triangle. - /// A containing the 4D Cartesian coordinates of vertex 2 of the triangle. - /// A containing the 4D Cartesian coordinates of vertex 3 of the triangle. - /// Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). - /// Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). - /// A new containing the 4D Cartesian coordinates of the specified point. - public static Quaternion Barycentric(Quaternion value1, Quaternion value2, Quaternion value3, float amount1, float amount2) - { - Quaternion result; - Barycentric(ref value1, ref value2, ref value3, amount1, amount2, out result); - return result; - } - - /// - /// Conjugates a quaternion. - /// - /// The quaternion to conjugate. - /// When the method completes, contains the conjugated quaternion. - public static void Conjugate(ref Quaternion value, out Quaternion result) - { - result.X = -value.X; - result.Y = -value.Y; - result.Z = -value.Z; - result.W = value.W; - } - - /// - /// Conjugates a quaternion. - /// - /// The quaternion to conjugate. - /// The conjugated quaternion. - public static Quaternion Conjugate(Quaternion value) - { - Quaternion result; - Conjugate(ref value, out result); - return result; - } - - /// - /// Calculates the dot product of two quaternions. - /// - /// First source quaternion. - /// Second source quaternion. - /// When the method completes, contains the dot product of the two quaternions. - public static void Dot(ref Quaternion left, ref Quaternion right, out float result) - { - result = (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z) + (left.W * right.W); - } - - /// - /// Calculates the dot product of two quaternions. - /// - /// First source quaternion. - /// Second source quaternion. - /// The dot product of the two quaternions. - public static float Dot(Quaternion left, Quaternion right) - { - return (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z) + (left.W * right.W); - } - - /// - /// Exponentiates a quaternion. - /// - /// The quaternion to exponentiate. - /// When the method completes, contains the exponentiated quaternion. - public static void Exponential(ref Quaternion value, out Quaternion result) - { - float angle = (float)Math.Sqrt((value.X * value.X) + (value.Y * value.Y) + (value.Z * value.Z)); - float sin = (float)Math.Sin(angle); - - if (!MathUtil.IsZero(sin)) - { - float coeff = sin / angle; - result.X = coeff * value.X; - result.Y = coeff * value.Y; - result.Z = coeff * value.Z; - } - else - { - result = value; - } - - result.W = (float)Math.Cos(angle); - } - - /// - /// Exponentiates a quaternion. - /// - /// The quaternion to exponentiate. - /// The exponentiated quaternion. - public static Quaternion Exponential(Quaternion value) - { - Quaternion result; - Exponential(ref value, out result); - return result; - } - - /// - /// Conjugates and renormalizes the quaternion. - /// - /// The quaternion to conjugate and renormalize. - /// When the method completes, contains the conjugated and renormalized quaternion. - public static void Invert(ref Quaternion value, out Quaternion result) - { - result = value; - result.Invert(); - } - - /// - /// Conjugates and renormalizes the quaternion. - /// - /// The quaternion to conjugate and renormalize. - /// The conjugated and renormalized quaternion. - public static Quaternion Invert(Quaternion value) - { - Quaternion result; - Invert(ref value, out result); - return result; - } - - /// - /// Performs a linear interpolation between two quaternions. - /// - /// Start quaternion. - /// End quaternion. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the linear interpolation of the two quaternions. - /// - /// This method performs the linear interpolation based on the following formula. - /// start + (end - start) * amount - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static void Lerp(ref Quaternion start, ref Quaternion end, float amount, out Quaternion result) - { - float inverse = 1.0f - amount; - - if (Dot(start, end) >= 0.0f) - { - result.X = (inverse * start.X) + (amount * end.X); - result.Y = (inverse * start.Y) + (amount * end.Y); - result.Z = (inverse * start.Z) + (amount * end.Z); - result.W = (inverse * start.W) + (amount * end.W); - } - else - { - result.X = (inverse * start.X) - (amount * end.X); - result.Y = (inverse * start.Y) - (amount * end.Y); - result.Z = (inverse * start.Z) - (amount * end.Z); - result.W = (inverse * start.W) - (amount * end.W); - } - - result.Normalize(); - } - - /// - /// Performs a linear interpolation between two quaternion. - /// - /// Start quaternion. - /// End quaternion. - /// Value between 0 and 1 indicating the weight of . - /// The linear interpolation of the two quaternions. - /// - /// This method performs the linear interpolation based on the following formula. - /// start + (end - start) * amount - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static Quaternion Lerp(Quaternion start, Quaternion end, float amount) - { - Quaternion result; - Lerp(ref start, ref end, amount, out result); - return result; - } - - /// - /// Calculates the natural logarithm of the specified quaternion. - /// - /// The quaternion whose logarithm will be calculated. - /// When the method completes, contains the natural logarithm of the quaternion. - public static void Logarithm(ref Quaternion value, out Quaternion result) - { - if (Math.Abs(value.W) < 1.0) - { - float angle = (float)Math.Acos(value.W); - float sin = (float)Math.Sin(angle); - - if (!MathUtil.IsZero(sin)) - { - float coeff = angle / sin; - result.X = value.X * coeff; - result.Y = value.Y * coeff; - result.Z = value.Z * coeff; - } - else - { - result = value; - } - } - else - { - result = value; - } - - result.W = 0.0f; - } - - /// - /// Calculates the natural logarithm of the specified quaternion. - /// - /// The quaternion whose logarithm will be calculated. - /// The natural logarithm of the quaternion. - public static Quaternion Logarithm(Quaternion value) - { - Quaternion result; - Logarithm(ref value, out result); - return result; - } - - /// - /// Converts the quaternion into a unit quaternion. - /// - /// The quaternion to normalize. - /// When the method completes, contains the normalized quaternion. - public static void Normalize(ref Quaternion value, out Quaternion result) - { - Quaternion temp = value; - result = temp; - result.Normalize(); - } - - /// - /// Converts the quaternion into a unit quaternion. - /// - /// The quaternion to normalize. - /// The normalized quaternion. - public static Quaternion Normalize(Quaternion value) - { - value.Normalize(); - return value; - } - - /// - /// Creates a quaternion given a rotation and an axis. - /// - /// The axis of rotation. - /// The angle of rotation. - /// When the method completes, contains the newly created quaternion. - public static void RotationAxis(ref Vector3 axis, float angle, out Quaternion result) - { - Vector3 normalized; - Vector3.Normalize(ref axis, out normalized); - - float half = angle * 0.5f; - float sin = (float)Math.Sin(half); - float cos = (float)Math.Cos(half); - - result.X = normalized.X * sin; - result.Y = normalized.Y * sin; - result.Z = normalized.Z * sin; - result.W = cos; - } - - /// - /// Creates a quaternion given a rotation and an axis. - /// - /// The axis of rotation. - /// The angle of rotation. - /// The newly created quaternion. - public static Quaternion RotationAxis(Vector3 axis, float angle) - { - Quaternion result; - RotationAxis(ref axis, angle, out result); - return result; - } - - /// - /// Creates a quaternion given a rotation matrix. - /// - /// The rotation matrix. - /// When the method completes, contains the newly created quaternion. - public static void RotationMatrix(ref Matrix matrix, out Quaternion result) - { - float sqrt; - float half; - float scale = matrix.M11 + matrix.M22 + matrix.M33; - - if (scale > 0.0f) - { - sqrt = (float)Math.Sqrt(scale + 1.0f); - result.W = sqrt * 0.5f; - sqrt = 0.5f / sqrt; - - result.X = (matrix.M23 - matrix.M32) * sqrt; - result.Y = (matrix.M31 - matrix.M13) * sqrt; - result.Z = (matrix.M12 - matrix.M21) * sqrt; - } - else if ((matrix.M11 >= matrix.M22) && (matrix.M11 >= matrix.M33)) - { - sqrt = (float)Math.Sqrt(1.0f + matrix.M11 - matrix.M22 - matrix.M33); - half = 0.5f / sqrt; - - result.X = 0.5f * sqrt; - result.Y = (matrix.M12 + matrix.M21) * half; - result.Z = (matrix.M13 + matrix.M31) * half; - result.W = (matrix.M23 - matrix.M32) * half; - } - else if (matrix.M22 > matrix.M33) - { - sqrt = (float)Math.Sqrt(1.0f + matrix.M22 - matrix.M11 - matrix.M33); - half = 0.5f / sqrt; - - result.X = (matrix.M21 + matrix.M12) * half; - result.Y = 0.5f * sqrt; - result.Z = (matrix.M32 + matrix.M23) * half; - result.W = (matrix.M31 - matrix.M13) * half; - } - else - { - sqrt = (float)Math.Sqrt(1.0f + matrix.M33 - matrix.M11 - matrix.M22); - half = 0.5f / sqrt; - - result.X = (matrix.M31 + matrix.M13) * half; - result.Y = (matrix.M32 + matrix.M23) * half; - result.Z = 0.5f * sqrt; - result.W = (matrix.M12 - matrix.M21) * half; - } - } - - /// - /// Creates a quaternion given a rotation matrix. - /// - /// The rotation matrix. - /// When the method completes, contains the newly created quaternion. - public static void RotationMatrix(ref Matrix3x3 matrix, out Quaternion result) - { - float sqrt; - float half; - float scale = matrix.M11 + matrix.M22 + matrix.M33; - - if (scale > 0.0f) - { - sqrt = (float)Math.Sqrt(scale + 1.0f); - result.W = sqrt * 0.5f; - sqrt = 0.5f / sqrt; - - result.X = (matrix.M23 - matrix.M32) * sqrt; - result.Y = (matrix.M31 - matrix.M13) * sqrt; - result.Z = (matrix.M12 - matrix.M21) * sqrt; - } - else if ((matrix.M11 >= matrix.M22) && (matrix.M11 >= matrix.M33)) - { - sqrt = (float)Math.Sqrt(1.0f + matrix.M11 - matrix.M22 - matrix.M33); - half = 0.5f / sqrt; - - result.X = 0.5f * sqrt; - result.Y = (matrix.M12 + matrix.M21) * half; - result.Z = (matrix.M13 + matrix.M31) * half; - result.W = (matrix.M23 - matrix.M32) * half; - } - else if (matrix.M22 > matrix.M33) - { - sqrt = (float)Math.Sqrt(1.0f + matrix.M22 - matrix.M11 - matrix.M33); - half = 0.5f / sqrt; - - result.X = (matrix.M21 + matrix.M12) * half; - result.Y = 0.5f * sqrt; - result.Z = (matrix.M32 + matrix.M23) * half; - result.W = (matrix.M31 - matrix.M13) * half; - } - else - { - sqrt = (float)Math.Sqrt(1.0f + matrix.M33 - matrix.M11 - matrix.M22); - half = 0.5f / sqrt; - - result.X = (matrix.M31 + matrix.M13) * half; - result.Y = (matrix.M32 + matrix.M23) * half; - result.Z = 0.5f * sqrt; - result.W = (matrix.M12 - matrix.M21) * half; - } - } - - /// - /// Creates a quaternion given forward and up vectors - /// - /// The forward vector the quaternion should look at - /// The up vector of the quaternion (must be perpendicular to forward vector) - /// The right vector of the quaternion (must be perpendicular to forward vector) - /// The newly created quaternion - public static void RotationLookAt(ref Vector3 forward, ref Vector3 up, ref Vector3 right, out Quaternion result) - { - //normalize input - forward.Normalize(); - up.Normalize(); - right.Normalize(); - //fill the 3x3 matrix with the bases for the system - Matrix3x3 m; - m.M11 = right.X; - m.M12 = right.Y; - m.M13 = right.Z; - m.M21 = up.X; - m.M22 = up.Y; - m.M23 = up.Z; - m.M31 = forward.X; - m.M32 = forward.Y; - m.M33 = forward.Z; - //create new quaternion from matrix - RotationMatrix(ref m, out result); - } - - /// - /// Creates a quaternion given forward and up vectors - /// - /// The forward vector the quaternion should look at - /// The up vector of the quaternion (must be perpendicular to forward vector) - /// The right vector of the quaternion - /// The newly created quaternion - public static Quaternion RotationLookAt(Vector3 forward, Vector3 up, Vector3 right) - { - Quaternion result; - RotationLookAt(ref forward, ref up, ref right, out result); - return result; - } - - /// - /// Creates a quaternion given left-handed forward and up vectors - /// - /// The forward vector the quaternion should look at - /// The up vector of the quaternion (must be perpendicular to forward vector) - /// The newly created quaternion - public static void RotationLookAtLH(ref Vector3 forward, ref Vector3 up, out Quaternion result) - { - Vector3 right; - Vector3.Cross(ref up, ref forward, out right); - RotationLookAt(ref forward, ref up, ref right, out result); - } - - /// - /// Creates a quaternion given left-handed forward and up vectors - /// - /// The forward vector the quaternion should look at - /// The up vector of the quaternion (must be perpendicular to forward vector) - /// The newly created quaternion - public static Quaternion RotationLookAtLH(Vector3 forward, Vector3 up) - { - Quaternion result; - RotationLookAtLH(ref forward, ref up, out result); - return result; - } - - /// - /// Creates a quaternion given right-handed forward and up vectors - /// - /// The forward vector the quaternion should look at - /// The up vector of the quaternion (must be perpendicular to forward vector) - /// The newly created quaternion - public static void RotationLookAtRH(ref Vector3 forward, ref Vector3 up, out Quaternion result) - { - Vector3 right; - Vector3.Cross(ref forward, ref up, out right); - RotationLookAt(ref forward, ref up, ref right, out result); - } - - /// - /// Creates a quaternion given right-handed forward and up vectors - /// - /// The forward vector the quaternion should look at - /// The up vector of the quaternion (must be perpendicular to forward vector) - /// The newly created quaternion - public static Quaternion RotationLookAtRH(Vector3 forward, Vector3 up) - { - Quaternion result; - RotationLookAtRH(ref forward, ref up, out result); - return result; - } - - /// - /// Creates a left-handed spherical billboard that rotates around a specified object position. - /// - /// The position of the object around which the billboard will rotate. - /// The position of the camera. - /// The up vector of the camera. - /// The forward vector of the camera. - /// When the method completes, contains the created billboard quaternion. - public static void BillboardLH(ref Vector3 objectPosition, ref Vector3 cameraPosition, ref Vector3 cameraUpVector, ref Vector3 cameraForwardVector, out Quaternion result) - { - Vector3 right; - Vector3 up; - Vector3 difference = objectPosition - cameraPosition; - - float lengthSq = difference.LengthSquared(); - if (MathUtil.IsZero(lengthSq)) - difference = -cameraForwardVector; - - Vector3.Cross(ref cameraUpVector, ref difference, out right); - Vector3.Cross(ref difference, ref right, out up); - - RotationLookAt(ref difference, ref up, ref right, out result); - } - - /// - /// Creates a left-handed spherical billboard that rotates around a specified object position. - /// - /// The position of the object around which the billboard will rotate. - /// The position of the camera. - /// The up vector of the camera. - /// The forward vector of the camera. - /// When the method completes, contains the created billboard quaternion. - public static Quaternion BillboardLH(Vector3 objectPosition, Vector3 cameraPosition, Vector3 cameraUpVector, Vector3 cameraForwardVector) - { - Quaternion result; - BillboardLH(ref objectPosition, ref cameraPosition, ref cameraUpVector, ref cameraForwardVector, out result); - return result; - } - - /// - /// Creates a left-handed spherical billboard that rotates around a specified object position. - /// - /// The position of the object around which the billboard will rotate. - /// The position of the camera. - /// The up vector of the camera. - /// The forward vector of the camera. - /// When the method completes, contains the created billboard quaternion. - public static void BillboardRH(ref Vector3 objectPosition, ref Vector3 cameraPosition, ref Vector3 cameraUpVector, ref Vector3 cameraForwardVector, out Quaternion result) - { - Vector3 right; - Vector3 up; - Vector3 difference = cameraPosition - objectPosition; - - float lengthSq = difference.LengthSquared(); - if (MathUtil.IsZero(lengthSq)) - difference = cameraForwardVector; - - Vector3.Cross(ref cameraUpVector, ref difference, out right); - Vector3.Cross(ref difference, ref right, out up); - - RotationLookAt(ref difference, ref up, ref right, out result); - } - - /// - /// Creates a left-handed spherical billboard that rotates around a specified object position. - /// - /// The position of the object around which the billboard will rotate. - /// The position of the camera. - /// The up vector of the camera. - /// The forward vector of the camera. - /// When the method completes, contains the created billboard quaternion. - public static Quaternion BillboardRH(Vector3 objectPosition, Vector3 cameraPosition, Vector3 cameraUpVector, Vector3 cameraForwardVector) - { - Quaternion result; - BillboardRH(ref objectPosition, ref cameraPosition, ref cameraUpVector, ref cameraForwardVector, out result); - return result; - } - - /// - /// Creates a quaternion given a rotation matrix. - /// - /// The rotation matrix. - /// The newly created quaternion. - public static Quaternion RotationMatrix(Matrix matrix) - { - Quaternion result; - RotationMatrix(ref matrix, out result); - return result; - } - - /// - /// Creates a quaternion given a yaw, pitch, and roll value. - /// - /// The yaw of rotation. - /// The pitch of rotation. - /// The roll of rotation. - /// When the method completes, contains the newly created quaternion. - public static void RotationYawPitchRoll(float yaw, float pitch, float roll, out Quaternion result) - { - float halfRoll = roll * 0.5f; - float halfPitch = pitch * 0.5f; - float halfYaw = yaw * 0.5f; - - float sinRoll = (float)Math.Sin(halfRoll); - float cosRoll = (float)Math.Cos(halfRoll); - float sinPitch = (float)Math.Sin(halfPitch); - float cosPitch = (float)Math.Cos(halfPitch); - float sinYaw = (float)Math.Sin(halfYaw); - float cosYaw = (float)Math.Cos(halfYaw); - - result.X = (cosYaw * sinPitch * cosRoll) + (sinYaw * cosPitch * sinRoll); - result.Y = (sinYaw * cosPitch * cosRoll) - (cosYaw * sinPitch * sinRoll); - result.Z = (cosYaw * cosPitch * sinRoll) - (sinYaw * sinPitch * cosRoll); - result.W = (cosYaw * cosPitch * cosRoll) + (sinYaw * sinPitch * sinRoll); - } - - /// - /// Creates a quaternion given a yaw, pitch, and roll value. - /// - /// The yaw of rotation. - /// The pitch of rotation. - /// The roll of rotation. - /// The newly created quaternion. - public static Quaternion RotationYawPitchRoll(float yaw, float pitch, float roll) - { - Quaternion result; - RotationYawPitchRoll(yaw, pitch, roll, out result); - return result; - } - - /// - /// Interpolates between two quaternions, using spherical linear interpolation. - /// - /// Start quaternion. - /// End quaternion. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the spherical linear interpolation of the two quaternions. - public static void Slerp(ref Quaternion start, ref Quaternion end, float amount, out Quaternion result) - { - float opposite; - float inverse; - float dot = Dot(start, end); - - if (Math.Abs(dot) > 1.0f - MathUtil.ZeroTolerance) - { - inverse = 1.0f - amount; - opposite = amount * Math.Sign(dot); - } - else - { - float acos = (float)Math.Acos(Math.Abs(dot)); - float invSin = (float)(1.0 / Math.Sin(acos)); - - inverse = (float)Math.Sin((1.0f - amount) * acos) * invSin; - opposite = (float)Math.Sin(amount * acos) * invSin * Math.Sign(dot); - } - - result.X = (inverse * start.X) + (opposite * end.X); - result.Y = (inverse * start.Y) + (opposite * end.Y); - result.Z = (inverse * start.Z) + (opposite * end.Z); - result.W = (inverse * start.W) + (opposite * end.W); - } - - /// - /// Interpolates between two quaternions, using spherical linear interpolation. - /// - /// Start quaternion. - /// End quaternion. - /// Value between 0 and 1 indicating the weight of . - /// The spherical linear interpolation of the two quaternions. - public static Quaternion Slerp(Quaternion start, Quaternion end, float amount) - { - Quaternion result; - Slerp(ref start, ref end, amount, out result); - return result; - } - - /// - /// Interpolates between quaternions, using spherical quadrangle interpolation. - /// - /// First source quaternion. - /// Second source quaternion. - /// Third source quaternion. - /// Fourth source quaternion. - /// Value between 0 and 1 indicating the weight of interpolation. - /// When the method completes, contains the spherical quadrangle interpolation of the quaternions. - public static void Squad(ref Quaternion value1, ref Quaternion value2, ref Quaternion value3, ref Quaternion value4, float amount, out Quaternion result) - { - Quaternion start, end; - Slerp(ref value1, ref value4, amount, out start); - Slerp(ref value2, ref value3, amount, out end); - Slerp(ref start, ref end, 2.0f * amount * (1.0f - amount), out result); - } - - /// - /// Interpolates between quaternions, using spherical quadrangle interpolation. - /// - /// First source quaternion. - /// Second source quaternion. - /// Third source quaternion. - /// Fourth source quaternion. - /// Value between 0 and 1 indicating the weight of interpolation. - /// The spherical quadrangle interpolation of the quaternions. - public static Quaternion Squad(Quaternion value1, Quaternion value2, Quaternion value3, Quaternion value4, float amount) - { - Quaternion result; - Squad(ref value1, ref value2, ref value3, ref value4, amount, out result); - return result; - } - - /// - /// Sets up control points for spherical quadrangle interpolation. - /// - /// First source quaternion. - /// Second source quaternion. - /// Third source quaternion. - /// Fourth source quaternion. - /// An array of three quaternions that represent control points for spherical quadrangle interpolation. - public static Quaternion[] SquadSetup(Quaternion value1, Quaternion value2, Quaternion value3, Quaternion value4) - { - Quaternion q0 = (value1 + value2).LengthSquared() < (value1 - value2).LengthSquared() ? -value1 : value1; - Quaternion q2 = (value2 + value3).LengthSquared() < (value2 - value3).LengthSquared() ? -value3 : value3; - Quaternion q3 = (value3 + value4).LengthSquared() < (value3 - value4).LengthSquared() ? -value4 : value4; - Quaternion q1 = value2; - - Quaternion q1Exp, q2Exp; - Exponential(ref q1, out q1Exp); - Exponential(ref q2, out q2Exp); - - Quaternion[] results = new Quaternion[3]; - results[0] = q1 * Exponential(-0.25f * (Logarithm(q1Exp * q2) + Logarithm(q1Exp * q0))); - results[1] = q2 * Exponential(-0.25f * (Logarithm(q2Exp * q3) + Logarithm(q2Exp * q1))); - results[2] = q2; - - return results; - } - - /// - /// Adds two quaternions. - /// - /// The first quaternion to add. - /// The second quaternion to add. - /// The sum of the two quaternions. - public static Quaternion operator +(Quaternion left, Quaternion right) - { - Quaternion result; - Add(ref left, ref right, out result); - return result; - } - - /// - /// Subtracts two quaternions. - /// - /// The first quaternion to subtract. - /// The second quaternion to subtract. - /// The difference of the two quaternions. - public static Quaternion operator -(Quaternion left, Quaternion right) - { - Quaternion result; - Subtract(ref left, ref right, out result); - return result; - } - - /// - /// Reverses the direction of a given quaternion. - /// - /// The quaternion to negate. - /// A quaternion facing in the opposite direction. - public static Quaternion operator -(Quaternion value) - { - Quaternion result; - Negate(ref value, out result); - return result; - } - - /// - /// Scales a quaternion by the given value. - /// - /// The quaternion to scale. - /// The amount by which to scale the quaternion. - /// The scaled quaternion. - public static Quaternion operator *(float scale, Quaternion value) - { - Quaternion result; - Multiply(ref value, scale, out result); - return result; - } - - /// - /// Scales a quaternion by the given value. - /// - /// The quaternion to scale. - /// The amount by which to scale the quaternion. - /// The scaled quaternion. - public static Quaternion operator *(Quaternion value, float scale) - { - Quaternion result; - Multiply(ref value, scale, out result); - return result; - } - - /// - /// Multiplies a quaternion by another. - /// - /// The first quaternion to multiply. - /// The second quaternion to multiply. - /// The multiplied quaternion. - public static Quaternion operator *(Quaternion left, Quaternion right) - { - Quaternion result; - Multiply(ref left, ref right, out result); - return result; - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has the same value as ; otherwise, false. - public static bool operator ==(Quaternion left, Quaternion right) - { - return left.Equals(ref right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has a different value than ; otherwise, false. - public static bool operator !=(Quaternion left, Quaternion right) - { - return !left.Equals(ref right); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// - /// A that represents this instance. - /// - public string ToString(string format) - { - if (format == null) - return ToString(); - - return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2} W:{3}", X.ToString(format, CultureInfo.CurrentCulture), - Y.ToString(format, CultureInfo.CurrentCulture), Z.ToString(format, CultureInfo.CurrentCulture), W.ToString(format, CultureInfo.CurrentCulture)); - } - - /// - /// Returns a that represents this instance. - /// - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(IFormatProvider formatProvider) - { - return string.Format(formatProvider, "X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - if (format == null) - return ToString(formatProvider); - - return string.Format(formatProvider, "X:{0} Y:{1} Z:{2} W:{3}", X.ToString(format, formatProvider), - Y.ToString(format, formatProvider), Z.ToString(format, formatProvider), W.ToString(format, formatProvider)); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - var hashCode = X.GetHashCode(); - hashCode = (hashCode * 397) ^ Y.GetHashCode(); - hashCode = (hashCode * 397) ^ Z.GetHashCode(); - hashCode = (hashCode * 397) ^ W.GetHashCode(); - return hashCode; - } - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(X); - serializer.Writer.Write(Y); - serializer.Writer.Write(Z); - serializer.Writer.Write(W); - } - else - { - X = serializer.Reader.ReadSingle(); - Y = serializer.Reader.ReadSingle(); - Z = serializer.Reader.ReadSingle(); - W = serializer.Reader.ReadSingle(); - } - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(ref Quaternion other) - { - return MathUtil.NearEqual(other.X, X) && MathUtil.NearEqual(other.Y, Y) && MathUtil.NearEqual(other.Z, Z) && MathUtil.NearEqual(other.W, W); - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(Quaternion other) - { - return Equals(ref other); - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object value) - { - if (!(value is Quaternion)) - return false; - - var strongValue = (Quaternion)value; - return Equals(ref strongValue); - } - -#if SlimDX1xInterop - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator SlimDX.Quaternion(Quaternion value) - { - return new SlimDX.Quaternion(value.X, value.Y, value.Z, value.W); - } - - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Quaternion(SlimDX.Quaternion value) - { - return new Quaternion(value.X, value.Y, value.Z, value.W); - } -#endif - -#if WPFInterop - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator System.Windows.Media.Media3D.Quaternion(Quaternion value) - { - return new System.Windows.Media.Media3D.Quaternion(value.X, value.Y, value.Z, value.W); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Quaternion(System.Windows.Media.Media3D.Quaternion value) - { - return new Quaternion((float)value.X, (float)value.Y, (float)value.Z, (float)value.W); - } -#endif - -#if XnaInterop - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Microsoft.Xna.Framework.Quaternion(Quaternion value) - { - return new Microsoft.Xna.Framework.Quaternion(value.X, value.Y, value.Z, value.W); - } - - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Quaternion(Microsoft.Xna.Framework.Quaternion value) - { - return new Quaternion(value.X, value.Y, value.Z, value.W); - } -#endif - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from SlimMath project. http://code.google.com/p/slimmath/ +// Greetings to SlimDX Group. Original code published with the following license: +// ----------------------------------------------------------------------------- +/* +* Copyright (c) 2007-2011 SlimDX Group +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Represents a four dimensional mathematical quaternion. + /// + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct Quaternion : IEquatable, IFormattable + { + /// + /// The size of the type, in bytes. + /// + public static readonly int SizeInBytes = Marshal.SizeOf(typeof(Quaternion)); + + /// + /// A with all of its components set to zero. + /// + public static readonly Quaternion Zero = new Quaternion(); + + /// + /// A with all of its components set to one. + /// + public static readonly Quaternion One = new Quaternion(1.0f, 1.0f, 1.0f, 1.0f); + + /// + /// The identity (0, 0, 0, 1). + /// + public static readonly Quaternion Identity = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + + /// + /// The X component of the quaternion. + /// + public float X; + + /// + /// The Y component of the quaternion. + /// + public float Y; + + /// + /// The Z component of the quaternion. + /// + public float Z; + + /// + /// The W component of the quaternion. + /// + public float W; + + /// + /// Initializes a new instance of the struct. + /// + /// The value that will be assigned to all components. + public Quaternion(float value) + { + X = value; + Y = value; + Z = value; + W = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// A vector containing the values with which to initialize the components. + public Quaternion(Vector4 value) + { + X = value.X; + Y = value.Y; + Z = value.Z; + W = value.W; + } + + /// + /// Initializes a new instance of the struct. + /// + /// A vector containing the values with which to initialize the X, Y, and Z components. + /// Initial value for the W component of the quaternion. + public Quaternion(Vector3 value, float w) + { + X = value.X; + Y = value.Y; + Z = value.Z; + W = w; + } + + /// + /// Initializes a new instance of the struct. + /// + /// A vector containing the values with which to initialize the X and Y components. + /// Initial value for the Z component of the quaternion. + /// Initial value for the W component of the quaternion. + public Quaternion(Vector2 value, float z, float w) + { + X = value.X; + Y = value.Y; + Z = z; + W = w; + } + + /// + /// Initializes a new instance of the struct. + /// + /// Initial value for the X component of the quaternion. + /// Initial value for the Y component of the quaternion. + /// Initial value for the Z component of the quaternion. + /// Initial value for the W component of the quaternion. + public Quaternion(float x, float y, float z, float w) + { + X = x; + Y = y; + Z = z; + W = w; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The values to assign to the X, Y, Z, and W components of the quaternion. This must be an array with four elements. + /// Thrown when is null. + /// Thrown when contains more or less than four elements. + public Quaternion(float[] values) + { + if (values == null) + throw new ArgumentNullException("values"); + if (values.Length != 4) + throw new ArgumentOutOfRangeException("values", "There must be four and only four input values for Quaternion."); + + X = values[0]; + Y = values[1]; + Z = values[2]; + W = values[3]; + } + + /// + /// Gets a value indicating whether this instance is equivalent to the identity quaternion. + /// + /// + /// true if this instance is an identity quaternion; otherwise, false. + /// + public bool IsIdentity + { + get { return this.Equals(Identity); } + } + + /// + /// Gets a value indicting whether this instance is normalized. + /// + public bool IsNormalized + { + get { return MathUtil.IsOne((X * X) + (Y * Y) + (Z * Z) + (W * W)); } + } + + /// + /// Gets the angle of the quaternion. + /// + /// The quaternion's angle. + public float Angle + { + get + { + float length = (X * X) + (Y * Y) + (Z * Z); + if (MathUtil.IsZero(length)) + return 0.0f; + + return (float)(2.0 * Math.Acos(MathUtil.Clamp(W, -1f, 1f))); + } + } + + /// + /// Gets the axis components of the quaternion. + /// + /// The axis components of the quaternion. + public Vector3 Axis + { + get + { + float length = (X * X) + (Y * Y) + (Z * Z); + if (MathUtil.IsZero(length)) + return Vector3.UnitX; + + float inv = 1.0f / (float)Math.Sqrt(length); + return new Vector3(X * inv, Y * inv, Z * inv); + } + } + + /// + /// Gets or sets the component at the specified index. + /// + /// The value of the X, Y, Z, or W component, depending on the index. + /// The index of the component to access. Use 0 for the X component, 1 for the Y component, 2 for the Z component, and 3 for the W component. + /// The value of the component at the specified index. + /// Thrown when the is out of the range [0, 3]. + public float this[int index] + { + get + { + switch (index) + { + case 0: return X; + case 1: return Y; + case 2: return Z; + case 3: return W; + } + + throw new ArgumentOutOfRangeException("index", "Indices for Quaternion run from 0 to 3, inclusive."); + } + + set + { + switch (index) + { + case 0: X = value; break; + case 1: Y = value; break; + case 2: Z = value; break; + case 3: W = value; break; + default: throw new ArgumentOutOfRangeException("index", "Indices for Quaternion run from 0 to 3, inclusive."); + } + } + } + + /// + /// Conjugates the quaternion. + /// + public void Conjugate() + { + X = -X; + Y = -Y; + Z = -Z; + } + + /// + /// Conjugates and renormalizes the quaternion. + /// + public void Invert() + { + float lengthSq = LengthSquared(); + if (!MathUtil.IsZero(lengthSq)) + { + lengthSq = 1.0f / lengthSq; + + X = -X * lengthSq; + Y = -Y * lengthSq; + Z = -Z * lengthSq; + W = W * lengthSq; + } + } + + /// + /// Calculates the length of the quaternion. + /// + /// The length of the quaternion. + /// + /// may be preferred when only the relative length is needed + /// and speed is of the essence. + /// + public float Length() + { + return (float)Math.Sqrt((X * X) + (Y * Y) + (Z * Z) + (W * W)); + } + + /// + /// Calculates the squared length of the quaternion. + /// + /// The squared length of the quaternion. + /// + /// This method may be preferred to when only a relative length is needed + /// and speed is of the essence. + /// + public float LengthSquared() + { + return (X * X) + (Y * Y) + (Z * Z) + (W * W); + } + + /// + /// Converts the quaternion into a unit quaternion. + /// + public void Normalize() + { + float length = Length(); + if (!MathUtil.IsZero(length)) + { + float inverse = 1.0f / length; + X *= inverse; + Y *= inverse; + Z *= inverse; + W *= inverse; + } + } + + /// + /// Creates an array containing the elements of the quaternion. + /// + /// A four-element array containing the components of the quaternion. + public float[] ToArray() + { + return new float[] { X, Y, Z, W }; + } + + /// + /// Adds two quaternions. + /// + /// The first quaternion to add. + /// The second quaternion to add. + /// When the method completes, contains the sum of the two quaternions. + public static void Add(ref Quaternion left, ref Quaternion right, out Quaternion result) + { + result.X = left.X + right.X; + result.Y = left.Y + right.Y; + result.Z = left.Z + right.Z; + result.W = left.W + right.W; + } + + /// + /// Adds two quaternions. + /// + /// The first quaternion to add. + /// The second quaternion to add. + /// The sum of the two quaternions. + public static Quaternion Add(Quaternion left, Quaternion right) + { + Quaternion result; + Add(ref left, ref right, out result); + return result; + } + + /// + /// Subtracts two quaternions. + /// + /// The first quaternion to subtract. + /// The second quaternion to subtract. + /// When the method completes, contains the difference of the two quaternions. + public static void Subtract(ref Quaternion left, ref Quaternion right, out Quaternion result) + { + result.X = left.X - right.X; + result.Y = left.Y - right.Y; + result.Z = left.Z - right.Z; + result.W = left.W - right.W; + } + + /// + /// Subtracts two quaternions. + /// + /// The first quaternion to subtract. + /// The second quaternion to subtract. + /// The difference of the two quaternions. + public static Quaternion Subtract(Quaternion left, Quaternion right) + { + Quaternion result; + Subtract(ref left, ref right, out result); + return result; + } + + /// + /// Scales a quaternion by the given value. + /// + /// The quaternion to scale. + /// The amount by which to scale the quaternion. + /// When the method completes, contains the scaled quaternion. + public static void Multiply(ref Quaternion value, float scale, out Quaternion result) + { + result.X = value.X * scale; + result.Y = value.Y * scale; + result.Z = value.Z * scale; + result.W = value.W * scale; + } + + /// + /// Scales a quaternion by the given value. + /// + /// The quaternion to scale. + /// The amount by which to scale the quaternion. + /// The scaled quaternion. + public static Quaternion Multiply(Quaternion value, float scale) + { + Quaternion result; + Multiply(ref value, scale, out result); + return result; + } + + /// + /// Multiplies a quaternion by another. + /// + /// The first quaternion to multiply. + /// The second quaternion to multiply. + /// When the method completes, contains the multiplied quaternion. + public static void Multiply(ref Quaternion left, ref Quaternion right, out Quaternion result) + { + float lx = left.X; + float ly = left.Y; + float lz = left.Z; + float lw = left.W; + float rx = right.X; + float ry = right.Y; + float rz = right.Z; + float rw = right.W; + float a = (ly * rz - lz * ry); + float b = (lz * rx - lx * rz); + float c = (lx * ry - ly * rx); + float d = (lx * rx + ly * ry + lz * rz); + result.X = (lx * rw + rx * lw) + a; + result.Y = (ly * rw + ry * lw) + b; + result.Z = (lz * rw + rz * lw) + c; + result.W = lw * rw - d; + } + + /// + /// Multiplies a quaternion by another. + /// + /// The first quaternion to multiply. + /// The second quaternion to multiply. + /// The multiplied quaternion. + public static Quaternion Multiply(Quaternion left, Quaternion right) + { + Quaternion result; + Multiply(ref left, ref right, out result); + return result; + } + + /// + /// Reverses the direction of a given quaternion. + /// + /// The quaternion to negate. + /// When the method completes, contains a quaternion facing in the opposite direction. + public static void Negate(ref Quaternion value, out Quaternion result) + { + result.X = -value.X; + result.Y = -value.Y; + result.Z = -value.Z; + result.W = -value.W; + } + + /// + /// Reverses the direction of a given quaternion. + /// + /// The quaternion to negate. + /// A quaternion facing in the opposite direction. + public static Quaternion Negate(Quaternion value) + { + Quaternion result; + Negate(ref value, out result); + return result; + } + + /// + /// Returns a containing the 4D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 2D triangle. + /// + /// A containing the 4D Cartesian coordinates of vertex 1 of the triangle. + /// A containing the 4D Cartesian coordinates of vertex 2 of the triangle. + /// A containing the 4D Cartesian coordinates of vertex 3 of the triangle. + /// Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). + /// Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). + /// When the method completes, contains a new containing the 4D Cartesian coordinates of the specified point. + public static void Barycentric(ref Quaternion value1, ref Quaternion value2, ref Quaternion value3, float amount1, float amount2, out Quaternion result) + { + Quaternion start, end; + Slerp(ref value1, ref value2, amount1 + amount2, out start); + Slerp(ref value1, ref value3, amount1 + amount2, out end); + Slerp(ref start, ref end, amount2 / (amount1 + amount2), out result); + } + + /// + /// Returns a containing the 4D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 2D triangle. + /// + /// A containing the 4D Cartesian coordinates of vertex 1 of the triangle. + /// A containing the 4D Cartesian coordinates of vertex 2 of the triangle. + /// A containing the 4D Cartesian coordinates of vertex 3 of the triangle. + /// Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). + /// Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). + /// A new containing the 4D Cartesian coordinates of the specified point. + public static Quaternion Barycentric(Quaternion value1, Quaternion value2, Quaternion value3, float amount1, float amount2) + { + Quaternion result; + Barycentric(ref value1, ref value2, ref value3, amount1, amount2, out result); + return result; + } + + /// + /// Conjugates a quaternion. + /// + /// The quaternion to conjugate. + /// When the method completes, contains the conjugated quaternion. + public static void Conjugate(ref Quaternion value, out Quaternion result) + { + result.X = -value.X; + result.Y = -value.Y; + result.Z = -value.Z; + result.W = value.W; + } + + /// + /// Conjugates a quaternion. + /// + /// The quaternion to conjugate. + /// The conjugated quaternion. + public static Quaternion Conjugate(Quaternion value) + { + Quaternion result; + Conjugate(ref value, out result); + return result; + } + + /// + /// Calculates the dot product of two quaternions. + /// + /// First source quaternion. + /// Second source quaternion. + /// When the method completes, contains the dot product of the two quaternions. + public static void Dot(ref Quaternion left, ref Quaternion right, out float result) + { + result = (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z) + (left.W * right.W); + } + + /// + /// Calculates the dot product of two quaternions. + /// + /// First source quaternion. + /// Second source quaternion. + /// The dot product of the two quaternions. + public static float Dot(Quaternion left, Quaternion right) + { + return (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z) + (left.W * right.W); + } + + /// + /// Exponentiates a quaternion. + /// + /// The quaternion to exponentiate. + /// When the method completes, contains the exponentiated quaternion. + public static void Exponential(ref Quaternion value, out Quaternion result) + { + float angle = (float)Math.Sqrt((value.X * value.X) + (value.Y * value.Y) + (value.Z * value.Z)); + float sin = (float)Math.Sin(angle); + + if (!MathUtil.IsZero(sin)) + { + float coeff = sin / angle; + result.X = coeff * value.X; + result.Y = coeff * value.Y; + result.Z = coeff * value.Z; + } + else + { + result = value; + } + + result.W = (float)Math.Cos(angle); + } + + /// + /// Exponentiates a quaternion. + /// + /// The quaternion to exponentiate. + /// The exponentiated quaternion. + public static Quaternion Exponential(Quaternion value) + { + Quaternion result; + Exponential(ref value, out result); + return result; + } + + /// + /// Conjugates and renormalizes the quaternion. + /// + /// The quaternion to conjugate and renormalize. + /// When the method completes, contains the conjugated and renormalized quaternion. + public static void Invert(ref Quaternion value, out Quaternion result) + { + result = value; + result.Invert(); + } + + /// + /// Conjugates and renormalizes the quaternion. + /// + /// The quaternion to conjugate and renormalize. + /// The conjugated and renormalized quaternion. + public static Quaternion Invert(Quaternion value) + { + Quaternion result; + Invert(ref value, out result); + return result; + } + + /// + /// Performs a linear interpolation between two quaternions. + /// + /// Start quaternion. + /// End quaternion. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the linear interpolation of the two quaternions. + /// + /// This method performs the linear interpolation based on the following formula. + /// start + (end - start) * amount + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static void Lerp(ref Quaternion start, ref Quaternion end, float amount, out Quaternion result) + { + float inverse = 1.0f - amount; + + if (Dot(start, end) >= 0.0f) + { + result.X = (inverse * start.X) + (amount * end.X); + result.Y = (inverse * start.Y) + (amount * end.Y); + result.Z = (inverse * start.Z) + (amount * end.Z); + result.W = (inverse * start.W) + (amount * end.W); + } + else + { + result.X = (inverse * start.X) - (amount * end.X); + result.Y = (inverse * start.Y) - (amount * end.Y); + result.Z = (inverse * start.Z) - (amount * end.Z); + result.W = (inverse * start.W) - (amount * end.W); + } + + result.Normalize(); + } + + /// + /// Performs a linear interpolation between two quaternion. + /// + /// Start quaternion. + /// End quaternion. + /// Value between 0 and 1 indicating the weight of . + /// The linear interpolation of the two quaternions. + /// + /// This method performs the linear interpolation based on the following formula. + /// start + (end - start) * amount + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static Quaternion Lerp(Quaternion start, Quaternion end, float amount) + { + Quaternion result; + Lerp(ref start, ref end, amount, out result); + return result; + } + + /// + /// Calculates the natural logarithm of the specified quaternion. + /// + /// The quaternion whose logarithm will be calculated. + /// When the method completes, contains the natural logarithm of the quaternion. + public static void Logarithm(ref Quaternion value, out Quaternion result) + { + if (Math.Abs(value.W) < 1.0) + { + float angle = (float)Math.Acos(value.W); + float sin = (float)Math.Sin(angle); + + if (!MathUtil.IsZero(sin)) + { + float coeff = angle / sin; + result.X = value.X * coeff; + result.Y = value.Y * coeff; + result.Z = value.Z * coeff; + } + else + { + result = value; + } + } + else + { + result = value; + } + + result.W = 0.0f; + } + + /// + /// Calculates the natural logarithm of the specified quaternion. + /// + /// The quaternion whose logarithm will be calculated. + /// The natural logarithm of the quaternion. + public static Quaternion Logarithm(Quaternion value) + { + Quaternion result; + Logarithm(ref value, out result); + return result; + } + + /// + /// Converts the quaternion into a unit quaternion. + /// + /// The quaternion to normalize. + /// When the method completes, contains the normalized quaternion. + public static void Normalize(ref Quaternion value, out Quaternion result) + { + Quaternion temp = value; + result = temp; + result.Normalize(); + } + + /// + /// Converts the quaternion into a unit quaternion. + /// + /// The quaternion to normalize. + /// The normalized quaternion. + public static Quaternion Normalize(Quaternion value) + { + value.Normalize(); + return value; + } + + /// + /// Creates a quaternion given a rotation and an axis. + /// + /// The axis of rotation. + /// The angle of rotation. + /// When the method completes, contains the newly created quaternion. + public static void RotationAxis(ref Vector3 axis, float angle, out Quaternion result) + { + Vector3 normalized; + Vector3.Normalize(ref axis, out normalized); + + float half = angle * 0.5f; + float sin = (float)Math.Sin(half); + float cos = (float)Math.Cos(half); + + result.X = normalized.X * sin; + result.Y = normalized.Y * sin; + result.Z = normalized.Z * sin; + result.W = cos; + } + + /// + /// Creates a quaternion given a rotation and an axis. + /// + /// The axis of rotation. + /// The angle of rotation. + /// The newly created quaternion. + public static Quaternion RotationAxis(Vector3 axis, float angle) + { + Quaternion result; + RotationAxis(ref axis, angle, out result); + return result; + } + + /// + /// Creates a quaternion given a rotation matrix. + /// + /// The rotation matrix. + /// When the method completes, contains the newly created quaternion. + public static void RotationMatrix(ref Matrix matrix, out Quaternion result) + { + float sqrt; + float half; + float scale = matrix.M11 + matrix.M22 + matrix.M33; + + if (scale > 0.0f) + { + sqrt = (float)Math.Sqrt(scale + 1.0f); + result.W = sqrt * 0.5f; + sqrt = 0.5f / sqrt; + + result.X = (matrix.M23 - matrix.M32) * sqrt; + result.Y = (matrix.M31 - matrix.M13) * sqrt; + result.Z = (matrix.M12 - matrix.M21) * sqrt; + } + else if ((matrix.M11 >= matrix.M22) && (matrix.M11 >= matrix.M33)) + { + sqrt = (float)Math.Sqrt(1.0f + matrix.M11 - matrix.M22 - matrix.M33); + half = 0.5f / sqrt; + + result.X = 0.5f * sqrt; + result.Y = (matrix.M12 + matrix.M21) * half; + result.Z = (matrix.M13 + matrix.M31) * half; + result.W = (matrix.M23 - matrix.M32) * half; + } + else if (matrix.M22 > matrix.M33) + { + sqrt = (float)Math.Sqrt(1.0f + matrix.M22 - matrix.M11 - matrix.M33); + half = 0.5f / sqrt; + + result.X = (matrix.M21 + matrix.M12) * half; + result.Y = 0.5f * sqrt; + result.Z = (matrix.M32 + matrix.M23) * half; + result.W = (matrix.M31 - matrix.M13) * half; + } + else + { + sqrt = (float)Math.Sqrt(1.0f + matrix.M33 - matrix.M11 - matrix.M22); + half = 0.5f / sqrt; + + result.X = (matrix.M31 + matrix.M13) * half; + result.Y = (matrix.M32 + matrix.M23) * half; + result.Z = 0.5f * sqrt; + result.W = (matrix.M12 - matrix.M21) * half; + } + } + + /// + /// Creates a quaternion given a rotation matrix. + /// + /// The rotation matrix. + /// When the method completes, contains the newly created quaternion. + public static void RotationMatrix(ref Matrix3x3 matrix, out Quaternion result) + { + float sqrt; + float half; + float scale = matrix.M11 + matrix.M22 + matrix.M33; + + if (scale > 0.0f) + { + sqrt = (float)Math.Sqrt(scale + 1.0f); + result.W = sqrt * 0.5f; + sqrt = 0.5f / sqrt; + + result.X = (matrix.M23 - matrix.M32) * sqrt; + result.Y = (matrix.M31 - matrix.M13) * sqrt; + result.Z = (matrix.M12 - matrix.M21) * sqrt; + } + else if ((matrix.M11 >= matrix.M22) && (matrix.M11 >= matrix.M33)) + { + sqrt = (float)Math.Sqrt(1.0f + matrix.M11 - matrix.M22 - matrix.M33); + half = 0.5f / sqrt; + + result.X = 0.5f * sqrt; + result.Y = (matrix.M12 + matrix.M21) * half; + result.Z = (matrix.M13 + matrix.M31) * half; + result.W = (matrix.M23 - matrix.M32) * half; + } + else if (matrix.M22 > matrix.M33) + { + sqrt = (float)Math.Sqrt(1.0f + matrix.M22 - matrix.M11 - matrix.M33); + half = 0.5f / sqrt; + + result.X = (matrix.M21 + matrix.M12) * half; + result.Y = 0.5f * sqrt; + result.Z = (matrix.M32 + matrix.M23) * half; + result.W = (matrix.M31 - matrix.M13) * half; + } + else + { + sqrt = (float)Math.Sqrt(1.0f + matrix.M33 - matrix.M11 - matrix.M22); + half = 0.5f / sqrt; + + result.X = (matrix.M31 + matrix.M13) * half; + result.Y = (matrix.M32 + matrix.M23) * half; + result.Z = 0.5f * sqrt; + result.W = (matrix.M12 - matrix.M21) * half; + } + } + + /// + /// Creates a quaternion given forward and up vectors + /// + /// The forward vector the quaternion should look at + /// The up vector of the quaternion (must be perpendicular to forward vector) + /// The right vector of the quaternion (must be perpendicular to forward vector) + /// The newly created quaternion + public static void RotationLookAt(ref Vector3 forward, ref Vector3 up, ref Vector3 right, out Quaternion result) + { + //normalize input + forward.Normalize(); + up.Normalize(); + right.Normalize(); + //fill the 3x3 matrix with the bases for the system + Matrix3x3 m; + m.M11 = right.X; + m.M12 = right.Y; + m.M13 = right.Z; + m.M21 = up.X; + m.M22 = up.Y; + m.M23 = up.Z; + m.M31 = forward.X; + m.M32 = forward.Y; + m.M33 = forward.Z; + //create new quaternion from matrix + RotationMatrix(ref m, out result); + } + + /// + /// Creates a quaternion given forward and up vectors + /// + /// The forward vector the quaternion should look at + /// The up vector of the quaternion (must be perpendicular to forward vector) + /// The right vector of the quaternion + /// The newly created quaternion + public static Quaternion RotationLookAt(Vector3 forward, Vector3 up, Vector3 right) + { + Quaternion result; + RotationLookAt(ref forward, ref up, ref right, out result); + return result; + } + + /// + /// Creates a quaternion given left-handed forward and up vectors + /// + /// The forward vector the quaternion should look at + /// The up vector of the quaternion (must be perpendicular to forward vector) + /// The newly created quaternion + public static void RotationLookAtLH(ref Vector3 forward, ref Vector3 up, out Quaternion result) + { + Vector3 right; + Vector3.Cross(ref up, ref forward, out right); + RotationLookAt(ref forward, ref up, ref right, out result); + } + + /// + /// Creates a quaternion given left-handed forward and up vectors + /// + /// The forward vector the quaternion should look at + /// The up vector of the quaternion (must be perpendicular to forward vector) + /// The newly created quaternion + public static Quaternion RotationLookAtLH(Vector3 forward, Vector3 up) + { + Quaternion result; + RotationLookAtLH(ref forward, ref up, out result); + return result; + } + + /// + /// Creates a quaternion given right-handed forward and up vectors + /// + /// The forward vector the quaternion should look at + /// The up vector of the quaternion (must be perpendicular to forward vector) + /// The newly created quaternion + public static void RotationLookAtRH(ref Vector3 forward, ref Vector3 up, out Quaternion result) + { + Vector3 right; + Vector3.Cross(ref forward, ref up, out right); + RotationLookAt(ref forward, ref up, ref right, out result); + } + + /// + /// Creates a quaternion given right-handed forward and up vectors + /// + /// The forward vector the quaternion should look at + /// The up vector of the quaternion (must be perpendicular to forward vector) + /// The newly created quaternion + public static Quaternion RotationLookAtRH(Vector3 forward, Vector3 up) + { + Quaternion result; + RotationLookAtRH(ref forward, ref up, out result); + return result; + } + + /// + /// Creates a left-handed spherical billboard that rotates around a specified object position. + /// + /// The position of the object around which the billboard will rotate. + /// The position of the camera. + /// The up vector of the camera. + /// The forward vector of the camera. + /// When the method completes, contains the created billboard quaternion. + public static void BillboardLH(ref Vector3 objectPosition, ref Vector3 cameraPosition, ref Vector3 cameraUpVector, ref Vector3 cameraForwardVector, out Quaternion result) + { + Vector3 right; + Vector3 up; + Vector3 difference = objectPosition - cameraPosition; + + float lengthSq = difference.LengthSquared(); + if (MathUtil.IsZero(lengthSq)) + difference = -cameraForwardVector; + + Vector3.Cross(ref cameraUpVector, ref difference, out right); + Vector3.Cross(ref difference, ref right, out up); + + RotationLookAt(ref difference, ref up, ref right, out result); + } + + /// + /// Creates a left-handed spherical billboard that rotates around a specified object position. + /// + /// The position of the object around which the billboard will rotate. + /// The position of the camera. + /// The up vector of the camera. + /// The forward vector of the camera. + /// When the method completes, contains the created billboard quaternion. + public static Quaternion BillboardLH(Vector3 objectPosition, Vector3 cameraPosition, Vector3 cameraUpVector, Vector3 cameraForwardVector) + { + Quaternion result; + BillboardLH(ref objectPosition, ref cameraPosition, ref cameraUpVector, ref cameraForwardVector, out result); + return result; + } + + /// + /// Creates a left-handed spherical billboard that rotates around a specified object position. + /// + /// The position of the object around which the billboard will rotate. + /// The position of the camera. + /// The up vector of the camera. + /// The forward vector of the camera. + /// When the method completes, contains the created billboard quaternion. + public static void BillboardRH(ref Vector3 objectPosition, ref Vector3 cameraPosition, ref Vector3 cameraUpVector, ref Vector3 cameraForwardVector, out Quaternion result) + { + Vector3 right; + Vector3 up; + Vector3 difference = cameraPosition - objectPosition; + + float lengthSq = difference.LengthSquared(); + if (MathUtil.IsZero(lengthSq)) + difference = cameraForwardVector; + + Vector3.Cross(ref cameraUpVector, ref difference, out right); + Vector3.Cross(ref difference, ref right, out up); + + RotationLookAt(ref difference, ref up, ref right, out result); + } + + /// + /// Creates a left-handed spherical billboard that rotates around a specified object position. + /// + /// The position of the object around which the billboard will rotate. + /// The position of the camera. + /// The up vector of the camera. + /// The forward vector of the camera. + /// When the method completes, contains the created billboard quaternion. + public static Quaternion BillboardRH(Vector3 objectPosition, Vector3 cameraPosition, Vector3 cameraUpVector, Vector3 cameraForwardVector) + { + Quaternion result; + BillboardRH(ref objectPosition, ref cameraPosition, ref cameraUpVector, ref cameraForwardVector, out result); + return result; + } + + /// + /// Creates a quaternion given a rotation matrix. + /// + /// The rotation matrix. + /// The newly created quaternion. + public static Quaternion RotationMatrix(Matrix matrix) + { + Quaternion result; + RotationMatrix(ref matrix, out result); + return result; + } + + /// + /// Creates a quaternion given a yaw, pitch, and roll value. + /// + /// The yaw of rotation. + /// The pitch of rotation. + /// The roll of rotation. + /// When the method completes, contains the newly created quaternion. + public static void RotationYawPitchRoll(float yaw, float pitch, float roll, out Quaternion result) + { + float halfRoll = roll * 0.5f; + float halfPitch = pitch * 0.5f; + float halfYaw = yaw * 0.5f; + + float sinRoll = (float)Math.Sin(halfRoll); + float cosRoll = (float)Math.Cos(halfRoll); + float sinPitch = (float)Math.Sin(halfPitch); + float cosPitch = (float)Math.Cos(halfPitch); + float sinYaw = (float)Math.Sin(halfYaw); + float cosYaw = (float)Math.Cos(halfYaw); + + result.X = (cosYaw * sinPitch * cosRoll) + (sinYaw * cosPitch * sinRoll); + result.Y = (sinYaw * cosPitch * cosRoll) - (cosYaw * sinPitch * sinRoll); + result.Z = (cosYaw * cosPitch * sinRoll) - (sinYaw * sinPitch * cosRoll); + result.W = (cosYaw * cosPitch * cosRoll) + (sinYaw * sinPitch * sinRoll); + } + + /// + /// Creates a quaternion given a yaw, pitch, and roll value. + /// + /// The yaw of rotation. + /// The pitch of rotation. + /// The roll of rotation. + /// The newly created quaternion. + public static Quaternion RotationYawPitchRoll(float yaw, float pitch, float roll) + { + Quaternion result; + RotationYawPitchRoll(yaw, pitch, roll, out result); + return result; + } + + /// + /// Interpolates between two quaternions, using spherical linear interpolation. + /// + /// Start quaternion. + /// End quaternion. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the spherical linear interpolation of the two quaternions. + public static void Slerp(ref Quaternion start, ref Quaternion end, float amount, out Quaternion result) + { + float opposite; + float inverse; + float dot = Dot(start, end); + + if (Math.Abs(dot) > 1.0f - MathUtil.ZeroTolerance) + { + inverse = 1.0f - amount; + opposite = amount * Math.Sign(dot); + } + else + { + float acos = (float)Math.Acos(Math.Abs(dot)); + float invSin = (float)(1.0 / Math.Sin(acos)); + + inverse = (float)Math.Sin((1.0f - amount) * acos) * invSin; + opposite = (float)Math.Sin(amount * acos) * invSin * Math.Sign(dot); + } + + result.X = (inverse * start.X) + (opposite * end.X); + result.Y = (inverse * start.Y) + (opposite * end.Y); + result.Z = (inverse * start.Z) + (opposite * end.Z); + result.W = (inverse * start.W) + (opposite * end.W); + } + + /// + /// Interpolates between two quaternions, using spherical linear interpolation. + /// + /// Start quaternion. + /// End quaternion. + /// Value between 0 and 1 indicating the weight of . + /// The spherical linear interpolation of the two quaternions. + public static Quaternion Slerp(Quaternion start, Quaternion end, float amount) + { + Quaternion result; + Slerp(ref start, ref end, amount, out result); + return result; + } + + /// + /// Interpolates between quaternions, using spherical quadrangle interpolation. + /// + /// First source quaternion. + /// Second source quaternion. + /// Third source quaternion. + /// Fourth source quaternion. + /// Value between 0 and 1 indicating the weight of interpolation. + /// When the method completes, contains the spherical quadrangle interpolation of the quaternions. + public static void Squad(ref Quaternion value1, ref Quaternion value2, ref Quaternion value3, ref Quaternion value4, float amount, out Quaternion result) + { + Quaternion start, end; + Slerp(ref value1, ref value4, amount, out start); + Slerp(ref value2, ref value3, amount, out end); + Slerp(ref start, ref end, 2.0f * amount * (1.0f - amount), out result); + } + + /// + /// Interpolates between quaternions, using spherical quadrangle interpolation. + /// + /// First source quaternion. + /// Second source quaternion. + /// Third source quaternion. + /// Fourth source quaternion. + /// Value between 0 and 1 indicating the weight of interpolation. + /// The spherical quadrangle interpolation of the quaternions. + public static Quaternion Squad(Quaternion value1, Quaternion value2, Quaternion value3, Quaternion value4, float amount) + { + Quaternion result; + Squad(ref value1, ref value2, ref value3, ref value4, amount, out result); + return result; + } + + /// + /// Sets up control points for spherical quadrangle interpolation. + /// + /// First source quaternion. + /// Second source quaternion. + /// Third source quaternion. + /// Fourth source quaternion. + /// An array of three quaternions that represent control points for spherical quadrangle interpolation. + public static Quaternion[] SquadSetup(Quaternion value1, Quaternion value2, Quaternion value3, Quaternion value4) + { + Quaternion q0 = (value1 + value2).LengthSquared() < (value1 - value2).LengthSquared() ? -value1 : value1; + Quaternion q2 = (value2 + value3).LengthSquared() < (value2 - value3).LengthSquared() ? -value3 : value3; + Quaternion q3 = (value3 + value4).LengthSquared() < (value3 - value4).LengthSquared() ? -value4 : value4; + Quaternion q1 = value2; + + Quaternion q1Exp, q2Exp; + Exponential(ref q1, out q1Exp); + Exponential(ref q2, out q2Exp); + + Quaternion[] results = new Quaternion[3]; + results[0] = q1 * Exponential(-0.25f * (Logarithm(q1Exp * q2) + Logarithm(q1Exp * q0))); + results[1] = q2 * Exponential(-0.25f * (Logarithm(q2Exp * q3) + Logarithm(q2Exp * q1))); + results[2] = q2; + + return results; + } + + /// + /// Adds two quaternions. + /// + /// The first quaternion to add. + /// The second quaternion to add. + /// The sum of the two quaternions. + public static Quaternion operator +(Quaternion left, Quaternion right) + { + Quaternion result; + Add(ref left, ref right, out result); + return result; + } + + /// + /// Subtracts two quaternions. + /// + /// The first quaternion to subtract. + /// The second quaternion to subtract. + /// The difference of the two quaternions. + public static Quaternion operator -(Quaternion left, Quaternion right) + { + Quaternion result; + Subtract(ref left, ref right, out result); + return result; + } + + /// + /// Reverses the direction of a given quaternion. + /// + /// The quaternion to negate. + /// A quaternion facing in the opposite direction. + public static Quaternion operator -(Quaternion value) + { + Quaternion result; + Negate(ref value, out result); + return result; + } + + /// + /// Scales a quaternion by the given value. + /// + /// The quaternion to scale. + /// The amount by which to scale the quaternion. + /// The scaled quaternion. + public static Quaternion operator *(float scale, Quaternion value) + { + Quaternion result; + Multiply(ref value, scale, out result); + return result; + } + + /// + /// Scales a quaternion by the given value. + /// + /// The quaternion to scale. + /// The amount by which to scale the quaternion. + /// The scaled quaternion. + public static Quaternion operator *(Quaternion value, float scale) + { + Quaternion result; + Multiply(ref value, scale, out result); + return result; + } + + /// + /// Multiplies a quaternion by another. + /// + /// The first quaternion to multiply. + /// The second quaternion to multiply. + /// The multiplied quaternion. + public static Quaternion operator *(Quaternion left, Quaternion right) + { + Quaternion result; + Multiply(ref left, ref right, out result); + return result; + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has the same value as ; otherwise, false. + public static bool operator ==(Quaternion left, Quaternion right) + { + return left.Equals(ref right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has a different value than ; otherwise, false. + public static bool operator !=(Quaternion left, Quaternion right) + { + return !left.Equals(ref right); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// + /// A that represents this instance. + /// + public string ToString(string format) + { + if (format == null) + return ToString(); + + return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2} W:{3}", X.ToString(format, CultureInfo.CurrentCulture), + Y.ToString(format, CultureInfo.CurrentCulture), Z.ToString(format, CultureInfo.CurrentCulture), W.ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format(formatProvider, "X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(string format, IFormatProvider formatProvider) + { + if (format == null) + return ToString(formatProvider); + + return string.Format(formatProvider, "X:{0} Y:{1} Z:{2} W:{3}", X.ToString(format, formatProvider), + Y.ToString(format, formatProvider), Z.ToString(format, formatProvider), W.ToString(format, formatProvider)); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + unchecked + { + var hashCode = X.GetHashCode(); + hashCode = (hashCode * 397) ^ Y.GetHashCode(); + hashCode = (hashCode * 397) ^ Z.GetHashCode(); + hashCode = (hashCode * 397) ^ W.GetHashCode(); + return hashCode; + } + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(ref Quaternion other) + { + return MathUtil.NearEqual(other.X, X) && MathUtil.NearEqual(other.Y, Y) && MathUtil.NearEqual(other.Z, Z) && MathUtil.NearEqual(other.W, W); + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(Quaternion other) + { + return Equals(ref other); + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object value) + { + if (!(value is Quaternion)) + return false; + + var strongValue = (Quaternion)value; + return Equals(ref strongValue); + } + +#if SlimDX1xInterop + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator SlimDX.Quaternion(Quaternion value) + { + return new SlimDX.Quaternion(value.X, value.Y, value.Z, value.W); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Quaternion(SlimDX.Quaternion value) + { + return new Quaternion(value.X, value.Y, value.Z, value.W); + } +#endif + +#if WPFInterop + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator System.Windows.Media.Media3D.Quaternion(Quaternion value) + { + return new System.Windows.Media.Media3D.Quaternion(value.X, value.Y, value.Z, value.W); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Quaternion(System.Windows.Media.Media3D.Quaternion value) + { + return new Quaternion((float)value.X, (float)value.Y, (float)value.Z, (float)value.W); + } +#endif + +#if XnaInterop + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Microsoft.Xna.Framework.Quaternion(Quaternion value) + { + return new Microsoft.Xna.Framework.Quaternion(value.X, value.Y, value.Z, value.W); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Quaternion(Microsoft.Xna.Framework.Quaternion value) + { + return new Quaternion(value.X, value.Y, value.Z, value.W); + } +#endif + } +} diff --git a/Source/SharpDX/Rectangle.cs b/Source/SharpDX/Mathematics/Rectangle.cs similarity index 72% rename from Source/SharpDX/Rectangle.cs rename to Source/SharpDX/Mathematics/Rectangle.cs index a496bacb8..2f8b50816 100644 --- a/Source/SharpDX/Rectangle.cs +++ b/Source/SharpDX/Mathematics/Rectangle.cs @@ -1,525 +1,506 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Define a Rectangle. This structure is slightly different from System.Drawing.Rectangle as it is - /// internally storing Left,Top,Right,Bottom instead of Left,Top,Width,Height. - /// - [StructLayout(LayoutKind.Sequential)] - public struct Rectangle : IEquatable, IDataSerializable - { - private int _left; - private int _top; - private int _right; - private int _bottom; - - /// - /// An empty rectangle. - /// - public static readonly Rectangle Empty; - - static Rectangle() - { - Empty = new Rectangle(); - } - - /// - /// Initializes a new instance of the struct. - /// - /// The left. - /// The top. - /// The width. - /// The height. - public Rectangle(int x, int y, int width, int height) - { - _left = x; - _top = y; - _right = x + width; - _bottom = y + height; - } - - /// - /// Gets or sets the left. - /// - /// The left. - public int Left - { - get { return _left; } - set { _left = value; } - } - - /// - /// Gets or sets the top. - /// - /// The top. - public int Top - { - get { return _top; } - set { _top = value; } - } - - /// - /// Gets or sets the right. - /// - /// The right. - public int Right - { - get { return _right; } - set { _right = value; } - } - - /// - /// Gets or sets the bottom. - /// - /// The bottom. - public int Bottom - { - get { return _bottom; } - set { _bottom = value; } - } - - /// - /// Gets or sets the X position. - /// - /// The X position. - public int X - { - get - { - return _left; - } - set - { - _right = value + Width; - _left = value; - } - } - - /// - /// Gets or sets the Y position. - /// - /// The Y position. - public int Y - { - get - { - return _top; - } - set - { - _bottom = value + Height; - _top = value; - } - } - - /// - /// Gets or sets the width. - /// - /// The width. - public int Width - { - get { return _right - _left; } - set { _right = _left + value; } - } - - /// - /// Gets or sets the height. - /// - /// The height. - public int Height - { - get { return _bottom - _top; } - set { _bottom = _top + value; } - } - - /// - /// Gets or sets the location. - /// - /// - /// The location. - /// - public Point Location - { - get - { - return new Point(X, Y); - } - set - { - X = value.X; - Y = value.Y; - } - } - - /// - /// Gets the Point that specifies the center of the rectangle. - /// - /// - /// The center. - /// - public Point Center - { - get - { - return new Point(X + (Width / 2), Y + (Height / 2)); - } - } - - /// - /// Gets a value that indicates whether the rectangle is empty. - /// - /// - /// true if [is empty]; otherwise, false. - /// - public bool IsEmpty - { - get - { - return (Width == 0) && (Height == 0) && (X == 0) && (Y == 0); - } - } - - /// - /// Gets or sets the size of the rectangle. - /// - /// The size of the rectangle. - public Size2 Size - { - get - { - return new Size2(Width, Height); - } - set - { - Width = value.Width; - Height = value.Height; - } - } - - /// - /// Gets the position of the top-left corner of the rectangle. - /// - /// The top-left corner of the rectangle. - public Point TopLeft { get { return new Point(_left, _top); } } - - /// - /// Gets the position of the top-right corner of the rectangle. - /// - /// The top-right corner of the rectangle. - public Point TopRight { get { return new Point(_right, _top); } } - - /// - /// Gets the position of the bottom-left corner of the rectangle. - /// - /// The bottom-left corner of the rectangle. - public Point BottomLeft { get { return new Point(_left, _bottom); } } - - /// - /// Gets the position of the bottom-right corner of the rectangle. - /// - /// The bottom-right corner of the rectangle. - public Point BottomRight { get { return new Point(_right, _bottom); } } - - /// Changes the position of the rectangle. - /// The values to adjust the position of the rectangle by. - public void Offset(Point amount) - { - Offset(amount.X, amount.Y); - } - - /// Changes the position of the rectangle. - /// Change in the x-position. - /// Change in the y-position. - public void Offset(int offsetX, int offsetY) - { - X += offsetX; - Y += offsetY; - } - - /// Pushes the edges of the rectangle out by the horizontal and vertical values specified. - /// Value to push the sides out by. - /// Value to push the top and bottom out by. - public void Inflate(int horizontalAmount, int verticalAmount) - { - X -= horizontalAmount; - Y -= verticalAmount; - Width += horizontalAmount * 2; - Height += verticalAmount * 2; - } - - /// Determines whether this rectangle contains a specified point represented by its x- and y-coordinates. - /// The x-coordinate of the specified point. - /// The y-coordinate of the specified point. - public bool Contains(int x, int y) - { - return (X <= x) && (x < Right) && (Y <= y) && (y < Bottom); - } - - /// Determines whether this rectangle contains a specified Point. - /// The Point to evaluate. - public bool Contains(Point value) - { - bool result; - Contains(ref value, out result); - return result; - } - - /// Determines whether this rectangle contains a specified Point. - /// The Point to evaluate. - /// [OutAttribute] true if the specified Point is contained within this rectangle; false otherwise. - public void Contains(ref Point value, out bool result) - { - result = (X <= value.X) && (value.X < Right) && (Y <= value.Y) && (value.Y < Bottom); - } - - /// Determines whether this rectangle entirely contains a specified rectangle. - /// The rectangle to evaluate. - public bool Contains(Rectangle value) - { - bool result; - Contains(ref value, out result); - return result; - } - - /// Determines whether this rectangle entirely contains a specified rectangle. - /// The rectangle to evaluate. - /// [OutAttribute] On exit, is true if this rectangle entirely contains the specified rectangle, or false if not. - public void Contains(ref Rectangle value, out bool result) - { - result = (X <= value.X) && (value.Right <= Right) && (Y <= value.Y) && (value.Bottom <= Bottom); - } - - /// - /// Checks, if specified point is inside . - /// - /// X point coordinate. - /// Y point coordinate. - /// true if point is inside , otherwise false. - public bool Contains(float x, float y) - { - return (x >= _left && x <= _right && y >= _top && y <= _bottom); - } - - /// - /// Checks, if specified is inside . - /// - /// Coordinate . - /// true if is inside , otherwise false. - public bool Contains(Vector2 vector2D) - { - return Contains(vector2D.X, vector2D.Y); - } - - /// Determines whether a specified rectangle intersects with this rectangle. - /// The rectangle to evaluate. - public bool Intersects(Rectangle value) - { - bool result; - Intersects(ref value, out result); - return result; - } - - /// - /// Determines whether a specified rectangle intersects with this rectangle. - /// - /// The rectangle to evaluate - /// [OutAttribute] true if the specified rectangle intersects with this one; false otherwise. - public void Intersects(ref Rectangle value, out bool result) - { - result = (value.X < Right) && (X < value.Right) && (value.Y < Bottom) && (Y < value.Bottom); - } - - /// - /// Creates a rectangle defining the area where one rectangle overlaps with another rectangle. - /// - /// The first rectangle to compare. - /// The second rectangle to compare. - /// The intersection rectangle. - public static Rectangle Intersect(Rectangle value1, Rectangle value2) - { - Rectangle result; - Intersect(ref value1, ref value2, out result); - return result; - } - - /// Creates a rectangle defining the area where one rectangle overlaps with another rectangle. - /// The first rectangle to compare. - /// The second rectangle to compare. - /// [OutAttribute] The area where the two first parameters overlap. - public static void Intersect(ref Rectangle value1, ref Rectangle value2, out Rectangle result) - { - int newLeft = (value1.X > value2.X) ? value1.X : value2.X; - int newTop = (value1.Y > value2.Y) ? value1.Y : value2.Y; - int newRight = (value1.Right < value2.Right) ? value1.Right : value2.Right; - int newBottom = (value1.Bottom < value2.Bottom) ? value1.Bottom : value2.Bottom; - if ((newRight > newLeft) && (newBottom > newTop)) - { - result = new Rectangle(newLeft, newTop, newRight - newLeft, newBottom - newTop); - } - else - { - result = Empty; - } - } - - /// - /// Creates a new rectangle that exactly contains two other rectangles. - /// - /// The first rectangle to contain. - /// The second rectangle to contain. - /// The union rectangle. - public static Rectangle Union(Rectangle value1, Rectangle value2) - { - Rectangle result; - Union(ref value1, ref value2, out result); - return result; - } - - /// - /// Creates a new rectangle that exactly contains two other rectangles. - /// - /// The first rectangle to contain. - /// The second rectangle to contain. - /// [OutAttribute] The rectangle that must be the union of the first two rectangles. - public static void Union(ref Rectangle value1, ref Rectangle value2, out Rectangle result) - { - var left = Math.Min(value1.Left, value2.Left); - var right = Math.Max(value1.Right, value2.Right); - var top = Math.Min(value1.Top, value2.Top); - var bottom = Math.Max(value1.Bottom, value2.Bottom); - result = new Rectangle(left, top, right - left, bottom - top); - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (obj.GetType() != typeof(Rectangle)) return false; - return Equals((Rectangle)obj); - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(Rectangle other) - { - return other._left == _left && other._top == _top && other._right == _right && other._bottom == _bottom; - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - int result = _left; - result = (result * 397) ^ _top; - result = (result * 397) ^ _right; - result = (result * 397) ^ _bottom; - return result; - } - } - - /// - /// Implements the operator ==. - /// - /// The left. - /// The right. - /// The result of the operator. - public static bool operator ==(Rectangle left, Rectangle right) - { - return left.Equals(right); - } - - /// - /// Implements the operator !=. - /// - /// The left. - /// The right. - /// The result of the operator. - public static bool operator !=(Rectangle left, Rectangle right) - { - return !(left == right); - } - - /// - /// Performs an implicit conversion to the structure. - /// - /// Performs direct converstion from int to float. - /// The source value. - /// The converted structure. - public static implicit operator RectangleF(Rectangle value) - { - return new RectangleF(value.X, value.Y, value.Width, value.Height); - } - - public override string ToString() - { - return string.Format(CultureInfo.InvariantCulture, "X:{0} Y:{1} Width:{2} Height:{3}", X, Y, Width, Height); - } - - internal void MakeXYAndWidthHeight() - { - _right = (_right - _left); - _bottom = (_bottom - _top); - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(_left); - serializer.Writer.Write(_top); - serializer.Writer.Write(_right); - serializer.Writer.Write(_bottom); - } - else - { - _left = serializer.Reader.ReadInt32(); - _top = serializer.Reader.ReadInt32(); - _right = serializer.Reader.ReadInt32(); - _bottom = serializer.Reader.ReadInt32(); - } - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Define a Rectangle. This structure is slightly different from System.Drawing.Rectangle as it is + /// internally storing Left,Top,Right,Bottom instead of Left,Top,Width,Height. + /// + [StructLayout(LayoutKind.Sequential)] + public struct Rectangle : IEquatable + { + private int _left; + private int _top; + private int _right; + private int _bottom; + + /// + /// An empty rectangle. + /// + public static readonly Rectangle Empty; + + static Rectangle() + { + Empty = new Rectangle(); + } + + /// + /// Initializes a new instance of the struct. + /// + /// The left. + /// The top. + /// The width. + /// The height. + public Rectangle(int x, int y, int width, int height) + { + _left = x; + _top = y; + _right = x + width; + _bottom = y + height; + } + + /// + /// Gets or sets the left. + /// + /// The left. + public int Left + { + get { return _left; } + set { _left = value; } + } + + /// + /// Gets or sets the top. + /// + /// The top. + public int Top + { + get { return _top; } + set { _top = value; } + } + + /// + /// Gets or sets the right. + /// + /// The right. + public int Right + { + get { return _right; } + set { _right = value; } + } + + /// + /// Gets or sets the bottom. + /// + /// The bottom. + public int Bottom + { + get { return _bottom; } + set { _bottom = value; } + } + + /// + /// Gets or sets the X position. + /// + /// The X position. + public int X + { + get + { + return _left; + } + set + { + _right = value + Width; + _left = value; + } + } + + /// + /// Gets or sets the Y position. + /// + /// The Y position. + public int Y + { + get + { + return _top; + } + set + { + _bottom = value + Height; + _top = value; + } + } + + /// + /// Gets or sets the width. + /// + /// The width. + public int Width + { + get { return _right - _left; } + set { _right = _left + value; } + } + + /// + /// Gets or sets the height. + /// + /// The height. + public int Height + { + get { return _bottom - _top; } + set { _bottom = _top + value; } + } + + + /// + /// Gets a value that indicates whether the rectangle is empty. + /// + /// + /// true if [is empty]; otherwise, false. + /// + public bool IsEmpty + { + get + { + return (Width == 0) && (Height == 0) && (X == 0) && (Y == 0); + } + } + + ///// + ///// Gets or sets the location. + ///// + ///// + ///// The location. + ///// + //public Point Location + //{ + // get + // { + // return new Point(X, Y); + // } + // set + // { + // X = value.X; + // Y = value.Y; + // } + //} + + ///// + ///// Gets the Point that specifies the center of the rectangle. + ///// + ///// + ///// The center. + ///// + //public Point Center + //{ + // get + // { + // return new Point(X + (Width / 2), Y + (Height / 2)); + // } + //} + + + ///// + ///// Gets or sets the size of the rectangle. + ///// + ///// The size of the rectangle. + //public Size2 Size + //{ + // get + // { + // return new Size2(Width, Height); + // } + // set + // { + // Width = value.Width; + // Height = value.Height; + // } + //} + + ///// + ///// Gets the position of the top-left corner of the rectangle. + ///// + ///// The top-left corner of the rectangle. + //public Point TopLeft { get { return new Point(_left, _top); } } + + ///// + ///// Gets the position of the top-right corner of the rectangle. + ///// + ///// The top-right corner of the rectangle. + //public Point TopRight { get { return new Point(_right, _top); } } + + ///// + ///// Gets the position of the bottom-left corner of the rectangle. + ///// + ///// The bottom-left corner of the rectangle. + //public Point BottomLeft { get { return new Point(_left, _bottom); } } + + ///// + ///// Gets the position of the bottom-right corner of the rectangle. + ///// + ///// The bottom-right corner of the rectangle. + //public Point BottomRight { get { return new Point(_right, _bottom); } } + + ///// Changes the position of the rectangle. + ///// The values to adjust the position of the rectangle by. + //public void Offset(Point amount) + //{ + // Offset(amount.X, amount.Y); + //} + + /// Changes the position of the rectangle. + /// Change in the x-position. + /// Change in the y-position. + public void Offset(int offsetX, int offsetY) + { + X += offsetX; + Y += offsetY; + } + + /// Pushes the edges of the rectangle out by the horizontal and vertical values specified. + /// Value to push the sides out by. + /// Value to push the top and bottom out by. + public void Inflate(int horizontalAmount, int verticalAmount) + { + X -= horizontalAmount; + Y -= verticalAmount; + Width += horizontalAmount * 2; + Height += verticalAmount * 2; + } + + /// Determines whether this rectangle contains a specified point represented by its x- and y-coordinates. + /// The x-coordinate of the specified point. + /// The y-coordinate of the specified point. + public bool Contains(int x, int y) + { + return (X <= x) && (x < Right) && (Y <= y) && (y < Bottom); + } + + ///// Determines whether this rectangle contains a specified Point. + ///// The Point to evaluate. + //public bool Contains(Point value) + //{ + // bool result; + // Contains(ref value, out result); + // return result; + //} + + ///// Determines whether this rectangle contains a specified Point. + ///// The Point to evaluate. + ///// [OutAttribute] true if the specified Point is contained within this rectangle; false otherwise. + //public void Contains(ref Point value, out bool result) + //{ + // result = (X <= value.X) && (value.X < Right) && (Y <= value.Y) && (value.Y < Bottom); + //} + + /// Determines whether this rectangle entirely contains a specified rectangle. + /// The rectangle to evaluate. + public bool Contains(Rectangle value) + { + bool result; + Contains(ref value, out result); + return result; + } + + /// Determines whether this rectangle entirely contains a specified rectangle. + /// The rectangle to evaluate. + /// [OutAttribute] On exit, is true if this rectangle entirely contains the specified rectangle, or false if not. + public void Contains(ref Rectangle value, out bool result) + { + result = (X <= value.X) && (value.Right <= Right) && (Y <= value.Y) && (value.Bottom <= Bottom); + } + + /// + /// Checks, if specified point is inside . + /// + /// X point coordinate. + /// Y point coordinate. + /// true if point is inside , otherwise false. + public bool Contains(float x, float y) + { + return (x >= _left && x <= _right && y >= _top && y <= _bottom); + } + + ///// + ///// Checks, if specified is inside . + ///// + ///// Coordinate . + ///// true if is inside , otherwise false. + //public bool Contains(Vector2 vector2D) + //{ + // return Contains(vector2D.X, vector2D.Y); + //} + + /// Determines whether a specified rectangle intersects with this rectangle. + /// The rectangle to evaluate. + public bool Intersects(Rectangle value) + { + bool result; + Intersects(ref value, out result); + return result; + } + + /// + /// Determines whether a specified rectangle intersects with this rectangle. + /// + /// The rectangle to evaluate + /// [OutAttribute] true if the specified rectangle intersects with this one; false otherwise. + public void Intersects(ref Rectangle value, out bool result) + { + result = (value.X < Right) && (X < value.Right) && (value.Y < Bottom) && (Y < value.Bottom); + } + + /// + /// Creates a rectangle defining the area where one rectangle overlaps with another rectangle. + /// + /// The first rectangle to compare. + /// The second rectangle to compare. + /// The intersection rectangle. + public static Rectangle Intersect(Rectangle value1, Rectangle value2) + { + Rectangle result; + Intersect(ref value1, ref value2, out result); + return result; + } + + /// Creates a rectangle defining the area where one rectangle overlaps with another rectangle. + /// The first rectangle to compare. + /// The second rectangle to compare. + /// [OutAttribute] The area where the two first parameters overlap. + public static void Intersect(ref Rectangle value1, ref Rectangle value2, out Rectangle result) + { + int newLeft = (value1.X > value2.X) ? value1.X : value2.X; + int newTop = (value1.Y > value2.Y) ? value1.Y : value2.Y; + int newRight = (value1.Right < value2.Right) ? value1.Right : value2.Right; + int newBottom = (value1.Bottom < value2.Bottom) ? value1.Bottom : value2.Bottom; + if ((newRight > newLeft) && (newBottom > newTop)) + { + result = new Rectangle(newLeft, newTop, newRight - newLeft, newBottom - newTop); + } + else + { + result = Empty; + } + } + + /// + /// Creates a new rectangle that exactly contains two other rectangles. + /// + /// The first rectangle to contain. + /// The second rectangle to contain. + /// The union rectangle. + public static Rectangle Union(Rectangle value1, Rectangle value2) + { + Rectangle result; + Union(ref value1, ref value2, out result); + return result; + } + + /// + /// Creates a new rectangle that exactly contains two other rectangles. + /// + /// The first rectangle to contain. + /// The second rectangle to contain. + /// [OutAttribute] The rectangle that must be the union of the first two rectangles. + public static void Union(ref Rectangle value1, ref Rectangle value2, out Rectangle result) + { + var left = Math.Min(value1.Left, value2.Left); + var right = Math.Max(value1.Right, value2.Right); + var top = Math.Min(value1.Top, value2.Top); + var bottom = Math.Max(value1.Bottom, value2.Bottom); + result = new Rectangle(left, top, right - left, bottom - top); + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (obj.GetType() != typeof(Rectangle)) return false; + return Equals((Rectangle)obj); + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(Rectangle other) + { + return other._left == _left && other._top == _top && other._right == _right && other._bottom == _bottom; + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + unchecked + { + int result = _left; + result = (result * 397) ^ _top; + result = (result * 397) ^ _right; + result = (result * 397) ^ _bottom; + return result; + } + } + + /// + /// Implements the operator ==. + /// + /// The left. + /// The right. + /// The result of the operator. + public static bool operator ==(Rectangle left, Rectangle right) + { + return left.Equals(right); + } + + /// + /// Implements the operator !=. + /// + /// The left. + /// The right. + /// The result of the operator. + public static bool operator !=(Rectangle left, Rectangle right) + { + return !(left == right); + } + + ///// + ///// Performs an implicit conversion to the structure. + ///// + ///// Performs direct converstion from int to float. + ///// The source value. + ///// The converted structure. + //public static implicit operator RectangleF(Rectangle value) + //{ + // return new RectangleF(value.X, value.Y, value.Width, value.Height); + //} + + public override string ToString() + { + return string.Format(CultureInfo.InvariantCulture, "X:{0} Y:{1} Width:{2} Height:{3}", X, Y, Width, Height); + } + + internal void MakeXYAndWidthHeight() + { + _right = (_right - _left); + _bottom = (_bottom - _top); + } + } +} diff --git a/Source/SharpDX/RectangleF.cs b/Source/SharpDX/Mathematics/RectangleF.cs similarity index 93% rename from Source/SharpDX/RectangleF.cs rename to Source/SharpDX/Mathematics/RectangleF.cs index 6bfb69979..32b607454 100644 --- a/Source/SharpDX/RectangleF.cs +++ b/Source/SharpDX/Mathematics/RectangleF.cs @@ -1,531 +1,510 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Define a RectangleF. This structure is slightly different from System.Drawing.RectangleF as it is - /// internally storing Left,Top,Right,Bottom instead of Left,Top,Width,Height. - /// - [StructLayout(LayoutKind.Sequential)] - public struct RectangleF : IEquatable, IDataSerializable - { - private float _left; - private float _top; - private float _right; - private float _bottom; - - /// - /// An empty rectangle. - /// - public static readonly RectangleF Empty; - - /// - /// An infinite rectangle. See remarks. - /// - /// - /// http://msdn.microsoft.com/en-us/library/windows/desktop/dd372261%28v=vs.85%29.aspx - /// Any properties that involve computations, like , or - /// may return incorrect results - . - /// - public static readonly RectangleF Infinite; - - static RectangleF() - { - Empty = new RectangleF(); - Infinite = new RectangleF - { - Left = float.NegativeInfinity, - Top = float.NegativeInfinity, - Right = float.PositiveInfinity, - Bottom = float.PositiveInfinity - }; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The left. - /// The top. - /// The width. - /// The height. - public RectangleF(float x, float y, float width, float height) - { - _left = x; - _top = y; - _right = x + width; - _bottom = y + height; - } - - /// - /// Gets or sets the X position of the left edge. - /// - /// The left. - public float Left - { - get { return _left; } - set { _left = value; } - } - - /// - /// Gets or sets the top. - /// - /// The top. - public float Top - { - get { return _top; } - set { _top = value; } - } - - /// - /// Gets or sets the right. - /// - /// The right. - public float Right - { - get { return _right; } - set { _right = value; } - } - - /// - /// Gets or sets the bottom. - /// - /// The bottom. - public float Bottom - { - get { return _bottom; } - set { _bottom = value; } - } - - /// - /// Gets or sets the X position. - /// - /// The X position. - public float X - { - get - { - return _left; - } - set - { - _right = value + Width; - _left = value; - } - } - - /// - /// Gets or sets the Y position. - /// - /// The Y position. - public float Y - { - get - { - return _top; - } - set - { - _bottom = value + Height; - _top = value; - } - } - - /// - /// Gets or sets the width. - /// - /// The width. - public float Width - { - get { return _right - _left; } - set { _right = _left + value; } - } - - /// - /// Gets or sets the height. - /// - /// The height. - public float Height - { - get { return _bottom - _top; } - set { _bottom = _top + value; } - } - - /// - /// Gets or sets the location. - /// - /// - /// The location. - /// - public Vector2 Location - { - get - { - return new Vector2(X, Y); - } - set - { - X = value.X; - Y = value.Y; - } - } - - /// - /// Gets the Point that specifies the center of the rectangle. - /// - /// - /// The center. - /// - public Vector2 Center - { - get - { - return new Vector2(X + (Width / 2), Y + (Height / 2)); - } - } - - /// - /// Gets a value that indicates whether the rectangle is empty. - /// - /// - /// true if [is empty]; otherwise, false. - /// - public bool IsEmpty - { - get - { - return (Width == 0.0f) && (Height == 0.0f) && (X == 0.0f) && (Y == 0.0f); - } - } - - /// - /// Gets or sets the size of the rectangle. - /// - /// The size of the rectangle. - public Size2F Size - { - get - { - return new Size2F(Width, Height); - } - set - { - Width = value.Width; - Height = value.Height; - } - } - - /// - /// Gets the position of the top-left corner of the rectangle. - /// - /// The top-left corner of the rectangle. - public Vector2 TopLeft { get { return new Vector2(_left, _top); } } - - /// - /// Gets the position of the top-right corner of the rectangle. - /// - /// The top-right corner of the rectangle. - public Vector2 TopRight { get { return new Vector2(_right, _top); } } - - /// - /// Gets the position of the bottom-left corner of the rectangle. - /// - /// The bottom-left corner of the rectangle. - public Vector2 BottomLeft { get { return new Vector2(_left, _bottom); } } - - /// - /// Gets the position of the bottom-right corner of the rectangle. - /// - /// The bottom-right corner of the rectangle. - public Vector2 BottomRight { get { return new Vector2(_right, _bottom); } } - - /// Changes the position of the rectangle. - /// The values to adjust the position of the rectangle by. - public void Offset(Point amount) - { - Offset(amount.X, amount.Y); - } - - /// Changes the position of the rectangle. - /// The values to adjust the position of the rectangle by. - public void Offset(Vector2 amount) - { - Offset(amount.X, amount.Y); - } - - /// Changes the position of the rectangle. - /// Change in the x-position. - /// Change in the y-position. - public void Offset(float offsetX, float offsetY) - { - X += offsetX; - Y += offsetY; - } - - /// Pushes the edges of the rectangle out by the horizontal and vertical values specified. - /// Value to push the sides out by. - /// Value to push the top and bottom out by. - public void Inflate(float horizontalAmount, float verticalAmount) - { - X -= horizontalAmount; - Y -= verticalAmount; - Width += horizontalAmount * 2; - Height += verticalAmount * 2; - } - - /// Determines whether this rectangle contains a specified Point. - /// The Point to evaluate. - /// [OutAttribute] true if the specified Point is contained within this rectangle; false otherwise. - public void Contains(ref Vector2 value, out bool result) - { - result = (X <= value.X) && (value.X < Right) && (Y <= value.Y) && (value.Y < Bottom); - } - - /// Determines whether this rectangle entirely contains a specified rectangle. - /// The rectangle to evaluate. - public bool Contains(Rectangle value) - { - return (X <= value.X) && (value.Right <= Right) && (Y <= value.Y) && (value.Bottom <= Bottom); - } - - /// Determines whether this rectangle entirely contains a specified rectangle. - /// The rectangle to evaluate. - /// [OutAttribute] On exit, is true if this rectangle entirely contains the specified rectangle, or false if not. - public void Contains(ref RectangleF value, out bool result) - { - result = (X <= value.X) && (value.Right <= Right) && (Y <= value.Y) && (value.Bottom <= Bottom); - } - - /// - /// Checks, if specified point is inside . - /// - /// X point coordinate. - /// Y point coordinate. - /// true if point is inside , otherwise false. - public bool Contains(float x, float y) - { - return (x >= _left && x <= _right && y >= _top && y <= _bottom); - } - - /// - /// Checks, if specified is inside . - /// - /// Coordinate . - /// true if is inside , otherwise false. - public bool Contains(Vector2 vector2D) - { - return Contains(vector2D.X, vector2D.Y); - } - - /// - /// Checks, if specified is inside . - /// - /// Coordinate . - /// true if is inside , otherwise false. - public bool Contains(Point point) - { - return Contains(point.X, point.Y); - } - - /// Determines whether a specified rectangle intersects with this rectangle. - /// The rectangle to evaluate. - public bool Intersects(RectangleF value) - { - bool result; - Intersects(ref value, out result); - return result; - } - - /// - /// Determines whether a specified rectangle intersects with this rectangle. - /// - /// The rectangle to evaluate - /// [OutAttribute] true if the specified rectangle intersects with this one; false otherwise. - public void Intersects(ref RectangleF value, out bool result) - { - result = (value.X < Right) && (X < value.Right) && (value.Y < Bottom) && (Y < value.Bottom); - } - - /// - /// Creates a rectangle defining the area where one rectangle overlaps with another rectangle. - /// - /// The first Rectangle to compare. - /// The second Rectangle to compare. - /// The intersection rectangle. - public static RectangleF Intersect(RectangleF value1, RectangleF value2) - { - RectangleF result; - Intersect(ref value1, ref value2, out result); - return result; - } - - /// Creates a rectangle defining the area where one rectangle overlaps with another rectangle. - /// The first rectangle to compare. - /// The second rectangle to compare. - /// [OutAttribute] The area where the two first parameters overlap. - public static void Intersect(ref RectangleF value1, ref RectangleF value2, out RectangleF result) - { - float newLeft = (value1.X > value2.X) ? value1.X : value2.X; - float newTop = (value1.Y > value2.Y) ? value1.Y : value2.Y; - float newRight = (value1.Right < value2.Right) ? value1.Right : value2.Right; - float newBottom = (value1.Bottom < value2.Bottom) ? value1.Bottom : value2.Bottom; - if ((newRight > newLeft) && (newBottom > newTop)) - { - result = new RectangleF(newLeft, newTop, newRight - newLeft, newBottom - newTop); - } - else - { - result = Empty; - } - } - - /// - /// Creates a new rectangle that exactly contains two other rectangles. - /// - /// The first rectangle to contain. - /// The second rectangle to contain. - /// The union rectangle. - public static RectangleF Union(RectangleF value1, RectangleF value2) - { - RectangleF result; - Union(ref value1, ref value2, out result); - return result; - } - - /// - /// Creates a new rectangle that exactly contains two other rectangles. - /// - /// The first rectangle to contain. - /// The second rectangle to contain. - /// [OutAttribute] The rectangle that must be the union of the first two rectangles. - public static void Union(ref RectangleF value1, ref RectangleF value2, out RectangleF result) - { - var left = Math.Min(value1.Left, value2.Left); - var right = Math.Max(value1.Right, value2.Right); - var top = Math.Min(value1.Top, value2.Top); - var bottom = Math.Max(value1.Bottom, value2.Bottom); - result = new RectangleF(left, top, right - left, bottom - top); - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (obj.GetType() != typeof(RectangleF)) return false; - return Equals((RectangleF)obj); - } - - /// - public bool Equals(RectangleF other) - { - return MathUtil.NearEqual(other.Left, Left) && - MathUtil.NearEqual(other.Right, Right) && - MathUtil.NearEqual(other.Top, Top) && - MathUtil.NearEqual(other.Bottom, Bottom); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - int result = _left.GetHashCode(); - result = (result * 397) ^ _top.GetHashCode(); - result = (result * 397) ^ _right.GetHashCode(); - result = (result * 397) ^ _bottom.GetHashCode(); - return result; - } - } - - public override string ToString() - { - return string.Format(CultureInfo.InvariantCulture, "X:{0} Y:{1} Width:{2} Height:{3}", X, Y, Width, Height); - } - - /// - /// Implements the operator ==. - /// - /// The left. - /// The right. - /// The result of the operator. - public static bool operator ==(RectangleF left, RectangleF right) - { - return left.Equals(right); - } - - /// - /// Implements the operator !=. - /// - /// The left. - /// The right. - /// The result of the operator. - public static bool operator !=(RectangleF left, RectangleF right) - { - return !(left == right); - } - - /// - /// Performs an explicit conversion to structure. - /// - /// Performs direct float to int conversion, any fractional data is truncated. - /// The source value. - /// A converted structure. - public static explicit operator Rectangle(RectangleF value) - { - return new Rectangle((int)value.X, (int)value.Y, (int)value.Width, (int)value.Height); - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(_left); - serializer.Writer.Write(_top); - serializer.Writer.Write(_right); - serializer.Writer.Write(_bottom); - } - else - { - _left = serializer.Reader.ReadSingle(); - _top = serializer.Reader.ReadSingle(); - _right = serializer.Reader.ReadSingle(); - _bottom = serializer.Reader.ReadSingle(); - } - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Define a RectangleF. This structure is slightly different from System.Drawing.RectangleF as it is + /// internally storing Left,Top,Right,Bottom instead of Left,Top,Width,Height. + /// + [StructLayout(LayoutKind.Sequential)] + public struct RectangleF : IEquatable + { + private float _left; + private float _top; + private float _right; + private float _bottom; + + /// + /// An empty rectangle. + /// + public static readonly RectangleF Empty; + + /// + /// An infinite rectangle. See remarks. + /// + /// + /// http://msdn.microsoft.com/en-us/library/windows/desktop/dd372261%28v=vs.85%29.aspx + /// Any properties that involve computations, like , or + /// may return incorrect results - . + /// + public static readonly RectangleF Infinite; + + static RectangleF() + { + Empty = new RectangleF(); + Infinite = new RectangleF + { + Left = float.NegativeInfinity, + Top = float.NegativeInfinity, + Right = float.PositiveInfinity, + Bottom = float.PositiveInfinity + }; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The left. + /// The top. + /// The width. + /// The height. + public RectangleF(float x, float y, float width, float height) + { + _left = x; + _top = y; + _right = x + width; + _bottom = y + height; + } + + /// + /// Gets or sets the X position of the left edge. + /// + /// The left. + public float Left + { + get { return _left; } + set { _left = value; } + } + + /// + /// Gets or sets the top. + /// + /// The top. + public float Top + { + get { return _top; } + set { _top = value; } + } + + /// + /// Gets or sets the right. + /// + /// The right. + public float Right + { + get { return _right; } + set { _right = value; } + } + + /// + /// Gets or sets the bottom. + /// + /// The bottom. + public float Bottom + { + get { return _bottom; } + set { _bottom = value; } + } + + /// + /// Gets or sets the X position. + /// + /// The X position. + public float X + { + get + { + return _left; + } + set + { + _right = value + Width; + _left = value; + } + } + + /// + /// Gets or sets the Y position. + /// + /// The Y position. + public float Y + { + get + { + return _top; + } + set + { + _bottom = value + Height; + _top = value; + } + } + + /// + /// Gets or sets the width. + /// + /// The width. + public float Width + { + get { return _right - _left; } + set { _right = _left + value; } + } + + /// + /// Gets or sets the height. + /// + /// The height. + public float Height + { + get { return _bottom - _top; } + set { _bottom = _top + value; } + } + + /// + /// Gets or sets the location. + /// + /// + /// The location. + /// + public Vector2 Location + { + get + { + return new Vector2(X, Y); + } + set + { + X = value.X; + Y = value.Y; + } + } + + /// + /// Gets the Point that specifies the center of the rectangle. + /// + /// + /// The center. + /// + public Vector2 Center + { + get + { + return new Vector2(X + (Width / 2), Y + (Height / 2)); + } + } + + /// + /// Gets a value that indicates whether the rectangle is empty. + /// + /// + /// true if [is empty]; otherwise, false. + /// + public bool IsEmpty + { + get + { + return (Width == 0.0f) && (Height == 0.0f) && (X == 0.0f) && (Y == 0.0f); + } + } + + /// + /// Gets or sets the size of the rectangle. + /// + /// The size of the rectangle. + public Size2F Size + { + get + { + return new Size2F(Width, Height); + } + set + { + Width = value.Width; + Height = value.Height; + } + } + + /// + /// Gets the position of the top-left corner of the rectangle. + /// + /// The top-left corner of the rectangle. + public Vector2 TopLeft { get { return new Vector2(_left, _top); } } + + /// + /// Gets the position of the top-right corner of the rectangle. + /// + /// The top-right corner of the rectangle. + public Vector2 TopRight { get { return new Vector2(_right, _top); } } + + /// + /// Gets the position of the bottom-left corner of the rectangle. + /// + /// The bottom-left corner of the rectangle. + public Vector2 BottomLeft { get { return new Vector2(_left, _bottom); } } + + /// + /// Gets the position of the bottom-right corner of the rectangle. + /// + /// The bottom-right corner of the rectangle. + public Vector2 BottomRight { get { return new Vector2(_right, _bottom); } } + + /// Changes the position of the rectangle. + /// The values to adjust the position of the rectangle by. + public void Offset(Point amount) + { + Offset(amount.X, amount.Y); + } + + /// Changes the position of the rectangle. + /// The values to adjust the position of the rectangle by. + public void Offset(Vector2 amount) + { + Offset(amount.X, amount.Y); + } + + /// Changes the position of the rectangle. + /// Change in the x-position. + /// Change in the y-position. + public void Offset(float offsetX, float offsetY) + { + X += offsetX; + Y += offsetY; + } + + /// Pushes the edges of the rectangle out by the horizontal and vertical values specified. + /// Value to push the sides out by. + /// Value to push the top and bottom out by. + public void Inflate(float horizontalAmount, float verticalAmount) + { + X -= horizontalAmount; + Y -= verticalAmount; + Width += horizontalAmount * 2; + Height += verticalAmount * 2; + } + + /// Determines whether this rectangle contains a specified Point. + /// The Point to evaluate. + /// [OutAttribute] true if the specified Point is contained within this rectangle; false otherwise. + public void Contains(ref Vector2 value, out bool result) + { + result = (X <= value.X) && (value.X < Right) && (Y <= value.Y) && (value.Y < Bottom); + } + + /// Determines whether this rectangle entirely contains a specified rectangle. + /// The rectangle to evaluate. + public bool Contains(Rectangle value) + { + return (X <= value.X) && (value.Right <= Right) && (Y <= value.Y) && (value.Bottom <= Bottom); + } + + /// Determines whether this rectangle entirely contains a specified rectangle. + /// The rectangle to evaluate. + /// [OutAttribute] On exit, is true if this rectangle entirely contains the specified rectangle, or false if not. + public void Contains(ref RectangleF value, out bool result) + { + result = (X <= value.X) && (value.Right <= Right) && (Y <= value.Y) && (value.Bottom <= Bottom); + } + + /// + /// Checks, if specified point is inside . + /// + /// X point coordinate. + /// Y point coordinate. + /// true if point is inside , otherwise false. + public bool Contains(float x, float y) + { + return (x >= _left && x <= _right && y >= _top && y <= _bottom); + } + + /// + /// Checks, if specified is inside . + /// + /// Coordinate . + /// true if is inside , otherwise false. + public bool Contains(Vector2 vector2D) + { + return Contains(vector2D.X, vector2D.Y); + } + + /// + /// Checks, if specified is inside . + /// + /// Coordinate . + /// true if is inside , otherwise false. + public bool Contains(Point point) + { + return Contains(point.X, point.Y); + } + + /// Determines whether a specified rectangle intersects with this rectangle. + /// The rectangle to evaluate. + public bool Intersects(RectangleF value) + { + bool result; + Intersects(ref value, out result); + return result; + } + + /// + /// Determines whether a specified rectangle intersects with this rectangle. + /// + /// The rectangle to evaluate + /// [OutAttribute] true if the specified rectangle intersects with this one; false otherwise. + public void Intersects(ref RectangleF value, out bool result) + { + result = (value.X < Right) && (X < value.Right) && (value.Y < Bottom) && (Y < value.Bottom); + } + + /// + /// Creates a rectangle defining the area where one rectangle overlaps with another rectangle. + /// + /// The first Rectangle to compare. + /// The second Rectangle to compare. + /// The intersection rectangle. + public static RectangleF Intersect(RectangleF value1, RectangleF value2) + { + RectangleF result; + Intersect(ref value1, ref value2, out result); + return result; + } + + /// Creates a rectangle defining the area where one rectangle overlaps with another rectangle. + /// The first rectangle to compare. + /// The second rectangle to compare. + /// [OutAttribute] The area where the two first parameters overlap. + public static void Intersect(ref RectangleF value1, ref RectangleF value2, out RectangleF result) + { + float newLeft = (value1.X > value2.X) ? value1.X : value2.X; + float newTop = (value1.Y > value2.Y) ? value1.Y : value2.Y; + float newRight = (value1.Right < value2.Right) ? value1.Right : value2.Right; + float newBottom = (value1.Bottom < value2.Bottom) ? value1.Bottom : value2.Bottom; + if ((newRight > newLeft) && (newBottom > newTop)) + { + result = new RectangleF(newLeft, newTop, newRight - newLeft, newBottom - newTop); + } + else + { + result = Empty; + } + } + + /// + /// Creates a new rectangle that exactly contains two other rectangles. + /// + /// The first rectangle to contain. + /// The second rectangle to contain. + /// The union rectangle. + public static RectangleF Union(RectangleF value1, RectangleF value2) + { + RectangleF result; + Union(ref value1, ref value2, out result); + return result; + } + + /// + /// Creates a new rectangle that exactly contains two other rectangles. + /// + /// The first rectangle to contain. + /// The second rectangle to contain. + /// [OutAttribute] The rectangle that must be the union of the first two rectangles. + public static void Union(ref RectangleF value1, ref RectangleF value2, out RectangleF result) + { + var left = Math.Min(value1.Left, value2.Left); + var right = Math.Max(value1.Right, value2.Right); + var top = Math.Min(value1.Top, value2.Top); + var bottom = Math.Max(value1.Bottom, value2.Bottom); + result = new RectangleF(left, top, right - left, bottom - top); + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (obj.GetType() != typeof(RectangleF)) return false; + return Equals((RectangleF)obj); + } + + /// + public bool Equals(RectangleF other) + { + return MathUtil.NearEqual(other.Left, Left) && + MathUtil.NearEqual(other.Right, Right) && + MathUtil.NearEqual(other.Top, Top) && + MathUtil.NearEqual(other.Bottom, Bottom); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + unchecked + { + int result = _left.GetHashCode(); + result = (result * 397) ^ _top.GetHashCode(); + result = (result * 397) ^ _right.GetHashCode(); + result = (result * 397) ^ _bottom.GetHashCode(); + return result; + } + } + + public override string ToString() + { + return string.Format(CultureInfo.InvariantCulture, "X:{0} Y:{1} Width:{2} Height:{3}", X, Y, Width, Height); + } + + /// + /// Implements the operator ==. + /// + /// The left. + /// The right. + /// The result of the operator. + public static bool operator ==(RectangleF left, RectangleF right) + { + return left.Equals(right); + } + + /// + /// Implements the operator !=. + /// + /// The left. + /// The right. + /// The result of the operator. + public static bool operator !=(RectangleF left, RectangleF right) + { + return !(left == right); + } + + /// + /// Performs an explicit conversion to structure. + /// + /// Performs direct float to int conversion, any fractional data is truncated. + /// The source value. + /// A converted structure. + public static explicit operator Rectangle(RectangleF value) + { + return new Rectangle((int)value.X, (int)value.Y, (int)value.Width, (int)value.Height); + } + } +} diff --git a/Source/SharpDX/Size2.cs b/Source/SharpDX/Mathematics/Size2.cs similarity index 86% rename from Source/SharpDX/Size2.cs rename to Source/SharpDX/Mathematics/Size2.cs index 3916426c2..a2d36447b 100644 --- a/Source/SharpDX/Size2.cs +++ b/Source/SharpDX/Mathematics/Size2.cs @@ -20,7 +20,6 @@ using System; using System.Runtime.InteropServices; -using SharpDX.Serialization; namespace SharpDX { @@ -28,7 +27,7 @@ namespace SharpDX /// Structure using the same layout than . /// [StructLayout(LayoutKind.Sequential)] - public struct Size2 : IEquatable, IDataSerializable + public struct Size2 : IEquatable { /// /// A zero size with (width, height) = (0,0) @@ -120,21 +119,5 @@ public override string ToString() { return string.Format("({0},{1})", Width, Height); } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(Width); - serializer.Writer.Write(Height); - } - else - { - Width = serializer.Reader.ReadInt32(); - Height = serializer.Reader.ReadInt32(); - } - } } } \ No newline at end of file diff --git a/Source/SharpDX/Size2F.cs b/Source/SharpDX/Mathematics/Size2F.cs similarity index 86% rename from Source/SharpDX/Size2F.cs rename to Source/SharpDX/Mathematics/Size2F.cs index 7ff79e99b..043298f60 100644 --- a/Source/SharpDX/Size2F.cs +++ b/Source/SharpDX/Mathematics/Size2F.cs @@ -20,7 +20,6 @@ using System; using System.Runtime.InteropServices; -using SharpDX.Serialization; namespace SharpDX { @@ -28,7 +27,7 @@ namespace SharpDX /// Structure using the same layout than . /// [StructLayout(LayoutKind.Sequential)] - public struct Size2F : IEquatable, IDataSerializable + public struct Size2F : IEquatable { /// /// A zero size with (width, height) = (0,0) @@ -120,21 +119,5 @@ public override string ToString() { return string.Format("({0},{1})", Width, Height); } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(Width); - serializer.Writer.Write(Height); - } - else - { - Width = serializer.Reader.ReadSingle(); - Height = serializer.Reader.ReadSingle(); - } - } } } \ No newline at end of file diff --git a/Source/SharpDX/Vector2.cs b/Source/SharpDX/Mathematics/Vector2.cs similarity index 97% rename from Source/SharpDX/Vector2.cs rename to Source/SharpDX/Mathematics/Vector2.cs index f67a75ff5..a66cde555 100644 --- a/Source/SharpDX/Vector2.cs +++ b/Source/SharpDX/Mathematics/Vector2.cs @@ -1,1585 +1,1567 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ----------------------------------------------------------------------------- -// Original code from SlimMath project. http://code.google.com/p/slimmath/ -// Greetings to SlimDX Group. Original code published with the following license: -// ----------------------------------------------------------------------------- -/* -* Copyright (c) 2007-2011 SlimDX Group -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Represents a two dimensional mathematical vector. - /// - [StructLayout(LayoutKind.Sequential, Pack = 4)] - [DynamicSerializer("TKV2")] - public struct Vector2 : IEquatable, IFormattable, IDataSerializable - { - /// - /// The size of the type, in bytes. - /// - public static readonly int SizeInBytes = Marshal.SizeOf(typeof(Vector2)); - - /// - /// A with all of its components set to zero. - /// - public static readonly Vector2 Zero = new Vector2(); - - /// - /// The X unit (1, 0). - /// - public static readonly Vector2 UnitX = new Vector2(1.0f, 0.0f); - - /// - /// The Y unit (0, 1). - /// - public static readonly Vector2 UnitY = new Vector2(0.0f, 1.0f); - - /// - /// A with all of its components set to one. - /// - public static readonly Vector2 One = new Vector2(1.0f, 1.0f); - - /// - /// The X component of the vector. - /// - public float X; - - /// - /// The Y component of the vector. - /// - public float Y; - - /// - /// Initializes a new instance of the struct. - /// - /// The value that will be assigned to all components. - public Vector2(float value) - { - X = value; - Y = value; - } - - /// - /// Initializes a new instance of the struct. - /// - /// Initial value for the X component of the vector. - /// Initial value for the Y component of the vector. - public Vector2(float x, float y) - { - X = x; - Y = y; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The values to assign to the X and Y components of the vector. This must be an array with two elements. - /// Thrown when is null. - /// Thrown when contains more or less than two elements. - public Vector2(float[] values) - { - if (values == null) - throw new ArgumentNullException("values"); - if (values.Length != 2) - throw new ArgumentOutOfRangeException("values", "There must be two and only two input values for Vector2."); - - X = values[0]; - Y = values[1]; - } - - /// - /// Gets a value indicting whether this instance is normalized. - /// - public bool IsNormalized - { - get { return MathUtil.IsOne((X * X) + (Y * Y)); } - } - - /// - /// Gets a value indicting whether this vector is zero - /// - public bool IsZero - { - get { return X == 0 && Y == 0; } - } - - /// - /// Gets or sets the component at the specified index. - /// - /// The value of the X or Y component, depending on the index. - /// The index of the component to access. Use 0 for the X component and 1 for the Y component. - /// The value of the component at the specified index. - /// Thrown when the is out of the range [0, 1]. - public float this[int index] - { - get - { - switch (index) - { - case 0: return X; - case 1: return Y; - } - - throw new ArgumentOutOfRangeException("index", "Indices for Vector2 run from 0 to 1, inclusive."); - } - - set - { - switch (index) - { - case 0: X = value; break; - case 1: Y = value; break; - default: throw new ArgumentOutOfRangeException("index", "Indices for Vector2 run from 0 to 1, inclusive."); - } - } - } - - /// - /// Calculates the length of the vector. - /// - /// The length of the vector. - /// - /// may be preferred when only the relative length is needed - /// and speed is of the essence. - /// - public float Length() - { - return (float)Math.Sqrt((X * X) + (Y * Y)); - } - - /// - /// Calculates the squared length of the vector. - /// - /// The squared length of the vector. - /// - /// This method may be preferred to when only a relative length is needed - /// and speed is of the essence. - /// - public float LengthSquared() - { - return (X * X) + (Y * Y); - } - - /// - /// Converts the vector into a unit vector. - /// - public void Normalize() - { - float length = Length(); - if (!MathUtil.IsZero(length)) - { - float inv = 1.0f / length; - X *= inv; - Y *= inv; - } - } - - /// - /// Creates an array containing the elements of the vector. - /// - /// A two-element array containing the components of the vector. - public float[] ToArray() - { - return new float[] { X, Y }; - } - - /// - /// Adds two vectors. - /// - /// The first vector to add. - /// The second vector to add. - /// When the method completes, contains the sum of the two vectors. - public static void Add(ref Vector2 left, ref Vector2 right, out Vector2 result) - { - result = new Vector2(left.X + right.X, left.Y + right.Y); - } - - /// - /// Adds two vectors. - /// - /// The first vector to add. - /// The second vector to add. - /// The sum of the two vectors. - public static Vector2 Add(Vector2 left, Vector2 right) - { - return new Vector2(left.X + right.X, left.Y + right.Y); - } - - /// - /// Perform a component-wise addition - /// - /// The input vector - /// The scalar value to be added to elements - /// The vector with added scalar for each element. - public static void Add(ref Vector2 left, ref float right, out Vector2 result) - { - result = new Vector2(left.X + right, left.Y + right); - } - - /// - /// Perform a component-wise addition - /// - /// The input vector - /// The scalar value to be added to elements - /// The vector with added scalar for each element. - public static Vector2 Add(Vector2 left, float right) - { - return new Vector2(left.X + right, left.Y + right); - } - - /// - /// Subtracts two vectors. - /// - /// The first vector to subtract. - /// The second vector to subtract. - /// When the method completes, contains the difference of the two vectors. - public static void Subtract(ref Vector2 left, ref Vector2 right, out Vector2 result) - { - result = new Vector2(left.X - right.X, left.Y - right.Y); - } - - /// - /// Subtracts two vectors. - /// - /// The first vector to subtract. - /// The second vector to subtract. - /// The difference of the two vectors. - public static Vector2 Subtract(Vector2 left, Vector2 right) - { - return new Vector2(left.X - right.X, left.Y - right.Y); - } - - /// - /// Perform a component-wise subtraction - /// - /// The input vector - /// The scalar value to be subtraced from elements - /// The vector with subtracted scalar for each element. - public static void Subtract(ref Vector2 left, ref float right, out Vector2 result) - { - result = new Vector2(left.X - right, left.Y - right); - } - - /// - /// Perform a component-wise subtraction - /// - /// The input vector - /// The scalar value to be subtraced from elements - /// The vector with subtracted scalar for each element. - public static Vector2 Subtract(Vector2 left, float right) - { - return new Vector2(left.X - right, left.Y - right); - } - - /// - /// Perform a component-wise subtraction - /// - /// The scalar value to be subtraced from elements - /// The input vector - /// The vector with subtracted scalar for each element. - public static void Subtract(ref float left, ref Vector2 right, out Vector2 result) - { - result = new Vector2(left - right.X, left - right.Y); - } - - /// - /// Perform a component-wise subtraction - /// - /// The scalar value to be subtraced from elements - /// The input vector - /// The vector with subtracted scalar for each element. - public static Vector2 Subtract(float left, Vector2 right) - { - return new Vector2(left - right.X, left - right.Y); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// When the method completes, contains the scaled vector. - public static void Multiply(ref Vector2 value, float scale, out Vector2 result) - { - result = new Vector2(value.X * scale, value.Y * scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector2 Multiply(Vector2 value, float scale) - { - return new Vector2(value.X * scale, value.Y * scale); - } - - /// - /// Multiplies a vector with another by performing component-wise multiplication. - /// - /// The first vector to multiply. - /// The second vector to multiply. - /// When the method completes, contains the multiplied vector. - public static void Multiply(ref Vector2 left, ref Vector2 right, out Vector2 result) - { - result = new Vector2(left.X * right.X, left.Y * right.Y); - } - - /// - /// Multiplies a vector with another by performing component-wise multiplication. - /// - /// The first vector to multiply. - /// The second vector to multiply. - /// The multiplied vector. - public static Vector2 Multiply(Vector2 left, Vector2 right) - { - return new Vector2(left.X * right.X, left.Y * right.Y); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// When the method completes, contains the scaled vector. - public static void Divide(ref Vector2 value, float scale, out Vector2 result) - { - result = new Vector2(value.X / scale, value.Y / scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector2 Divide(Vector2 value, float scale) - { - return new Vector2(value.X / scale, value.Y / scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The amount by which to scale the vector. - /// The vector to scale. - /// When the method completes, contains the scaled vector. - public static void Divide(float scale,ref Vector2 value, out Vector2 result) - { - result = new Vector2(scale / value.X, scale / value.Y); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector2 Divide(float scale, Vector2 value) - { - return new Vector2(scale / value.X, scale / value.Y); - } - - /// - /// Reverses the direction of a given vector. - /// - /// The vector to negate. - /// When the method completes, contains a vector facing in the opposite direction. - public static void Negate(ref Vector2 value, out Vector2 result) - { - result = new Vector2(-value.X, -value.Y); - } - - /// - /// Reverses the direction of a given vector. - /// - /// The vector to negate. - /// A vector facing in the opposite direction. - public static Vector2 Negate(Vector2 value) - { - return new Vector2(-value.X, -value.Y); - } - - /// - /// Returns a containing the 2D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 2D triangle. - /// - /// A containing the 2D Cartesian coordinates of vertex 1 of the triangle. - /// A containing the 2D Cartesian coordinates of vertex 2 of the triangle. - /// A containing the 2D Cartesian coordinates of vertex 3 of the triangle. - /// Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). - /// Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). - /// When the method completes, contains the 2D Cartesian coordinates of the specified point. - public static void Barycentric(ref Vector2 value1, ref Vector2 value2, ref Vector2 value3, float amount1, float amount2, out Vector2 result) - { - result = new Vector2((value1.X + (amount1 * (value2.X - value1.X))) + (amount2 * (value3.X - value1.X)), - (value1.Y + (amount1 * (value2.Y - value1.Y))) + (amount2 * (value3.Y - value1.Y))); - } - - /// - /// Returns a containing the 2D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 2D triangle. - /// - /// A containing the 2D Cartesian coordinates of vertex 1 of the triangle. - /// A containing the 2D Cartesian coordinates of vertex 2 of the triangle. - /// A containing the 2D Cartesian coordinates of vertex 3 of the triangle. - /// Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). - /// Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). - /// A new containing the 2D Cartesian coordinates of the specified point. - public static Vector2 Barycentric(Vector2 value1, Vector2 value2, Vector2 value3, float amount1, float amount2) - { - Vector2 result; - Barycentric(ref value1, ref value2, ref value3, amount1, amount2, out result); - return result; - } - - /// - /// Restricts a value to be within a specified range. - /// - /// The value to clamp. - /// The minimum value. - /// The maximum value. - /// When the method completes, contains the clamped value. - public static void Clamp(ref Vector2 value, ref Vector2 min, ref Vector2 max, out Vector2 result) - { - float x = value.X; - x = (x > max.X) ? max.X : x; - x = (x < min.X) ? min.X : x; - - float y = value.Y; - y = (y > max.Y) ? max.Y : y; - y = (y < min.Y) ? min.Y : y; - - result = new Vector2(x, y); - } - - /// - /// Restricts a value to be within a specified range. - /// - /// The value to clamp. - /// The minimum value. - /// The maximum value. - /// The clamped value. - public static Vector2 Clamp(Vector2 value, Vector2 min, Vector2 max) - { - Vector2 result; - Clamp(ref value, ref min, ref max, out result); - return result; - } - - /// - /// Saturates this instance in the range [0,1] - /// - public void Saturate() - { - X = X < 0.0f ? 0.0f : X > 1.0f ? 1.0f : X; - Y = Y < 0.0f ? 0.0f : Y > 1.0f ? 1.0f : Y; - } - - /// - /// Calculates the distance between two vectors. - /// - /// The first vector. - /// The second vector. - /// When the method completes, contains the distance between the two vectors. - /// - /// may be preferred when only the relative distance is needed - /// and speed is of the essence. - /// - public static void Distance(ref Vector2 value1, ref Vector2 value2, out float result) - { - float x = value1.X - value2.X; - float y = value1.Y - value2.Y; - - result = (float)Math.Sqrt((x * x) + (y * y)); - } - - /// - /// Calculates the distance between two vectors. - /// - /// The first vector. - /// The second vector. - /// The distance between the two vectors. - /// - /// may be preferred when only the relative distance is needed - /// and speed is of the essence. - /// - public static float Distance(Vector2 value1, Vector2 value2) - { - float x = value1.X - value2.X; - float y = value1.Y - value2.Y; - - return (float)Math.Sqrt((x * x) + (y * y)); - } - - /// - /// Calculates the squared distance between two vectors. - /// - /// The first vector. - /// The second vector - /// When the method completes, contains the squared distance between the two vectors. - /// Distance squared is the value before taking the square root. - /// Distance squared can often be used in place of distance if relative comparisons are being made. - /// For example, consider three points A, B, and C. To determine whether B or C is further from A, - /// compare the distance between A and B to the distance between A and C. Calculating the two distances - /// involves two square roots, which are computationally expensive. However, using distance squared - /// provides the same information and avoids calculating two square roots. - /// - public static void DistanceSquared(ref Vector2 value1, ref Vector2 value2, out float result) - { - float x = value1.X - value2.X; - float y = value1.Y - value2.Y; - - result = (x * x) + (y * y); - } - - /// - /// Calculates the squared distance between two vectors. - /// - /// The first vector. - /// The second vector. - /// The squared distance between the two vectors. - /// Distance squared is the value before taking the square root. - /// Distance squared can often be used in place of distance if relative comparisons are being made. - /// For example, consider three points A, B, and C. To determine whether B or C is further from A, - /// compare the distance between A and B to the distance between A and C. Calculating the two distances - /// involves two square roots, which are computationally expensive. However, using distance squared - /// provides the same information and avoids calculating two square roots. - /// - public static float DistanceSquared(Vector2 value1, Vector2 value2) - { - float x = value1.X - value2.X; - float y = value1.Y - value2.Y; - - return (x * x) + (y * y); - } - - /// - /// Calculates the dot product of two vectors. - /// - /// First source vector. - /// Second source vector. - /// When the method completes, contains the dot product of the two vectors. - public static void Dot(ref Vector2 left, ref Vector2 right, out float result) - { - result = (left.X * right.X) + (left.Y * right.Y); - } - - /// - /// Calculates the dot product of two vectors. - /// - /// First source vector. - /// Second source vector. - /// The dot product of the two vectors. - public static float Dot(Vector2 left, Vector2 right) - { - return (left.X * right.X) + (left.Y * right.Y); - } - - /// - /// Converts the vector into a unit vector. - /// - /// The vector to normalize. - /// When the method completes, contains the normalized vector. - public static void Normalize(ref Vector2 value, out Vector2 result) - { - result = value; - result.Normalize(); - } - - /// - /// Converts the vector into a unit vector. - /// - /// The vector to normalize. - /// The normalized vector. - public static Vector2 Normalize(Vector2 value) - { - value.Normalize(); - return value; - } - - /// - /// Performs a linear interpolation between two vectors. - /// - /// Start vector. - /// End vector. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the linear interpolation of the two vectors. - /// - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static void Lerp(ref Vector2 start, ref Vector2 end, float amount, out Vector2 result) - { - result.X = MathUtil.Lerp(start.X, end.X, amount); - result.Y = MathUtil.Lerp(start.Y, end.Y, amount); - } - - /// - /// Performs a linear interpolation between two vectors. - /// - /// Start vector. - /// End vector. - /// Value between 0 and 1 indicating the weight of . - /// The linear interpolation of the two vectors. - /// - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static Vector2 Lerp(Vector2 start, Vector2 end, float amount) - { - Vector2 result; - Lerp(ref start, ref end, amount, out result); - return result; - } - - /// - /// Performs a cubic interpolation between two vectors. - /// - /// Start vector. - /// End vector. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the cubic interpolation of the two vectors. - public static void SmoothStep(ref Vector2 start, ref Vector2 end, float amount, out Vector2 result) - { - amount = MathUtil.SmoothStep(amount); - Lerp(ref start, ref end, amount, out result); - } - - /// - /// Performs a cubic interpolation between two vectors. - /// - /// Start vector. - /// End vector. - /// Value between 0 and 1 indicating the weight of . - /// The cubic interpolation of the two vectors. - public static Vector2 SmoothStep(Vector2 start, Vector2 end, float amount) - { - Vector2 result; - SmoothStep(ref start, ref end, amount, out result); - return result; - } - - /// - /// Performs a Hermite spline interpolation. - /// - /// First source position vector. - /// First source tangent vector. - /// Second source position vector. - /// Second source tangent vector. - /// Weighting factor. - /// When the method completes, contains the result of the Hermite spline interpolation. - public static void Hermite(ref Vector2 value1, ref Vector2 tangent1, ref Vector2 value2, ref Vector2 tangent2, float amount, out Vector2 result) - { - float squared = amount * amount; - float cubed = amount * squared; - float part1 = ((2.0f * cubed) - (3.0f * squared)) + 1.0f; - float part2 = (-2.0f * cubed) + (3.0f * squared); - float part3 = (cubed - (2.0f * squared)) + amount; - float part4 = cubed - squared; - - result.X = (((value1.X * part1) + (value2.X * part2)) + (tangent1.X * part3)) + (tangent2.X * part4); - result.Y = (((value1.Y * part1) + (value2.Y * part2)) + (tangent1.Y * part3)) + (tangent2.Y * part4); - } - - /// - /// Performs a Hermite spline interpolation. - /// - /// First source position vector. - /// First source tangent vector. - /// Second source position vector. - /// Second source tangent vector. - /// Weighting factor. - /// The result of the Hermite spline interpolation. - public static Vector2 Hermite(Vector2 value1, Vector2 tangent1, Vector2 value2, Vector2 tangent2, float amount) - { - Vector2 result; - Hermite(ref value1, ref tangent1, ref value2, ref tangent2, amount, out result); - return result; - } - - /// - /// Performs a Catmull-Rom interpolation using the specified positions. - /// - /// The first position in the interpolation. - /// The second position in the interpolation. - /// The third position in the interpolation. - /// The fourth position in the interpolation. - /// Weighting factor. - /// When the method completes, contains the result of the Catmull-Rom interpolation. - public static void CatmullRom(ref Vector2 value1, ref Vector2 value2, ref Vector2 value3, ref Vector2 value4, float amount, out Vector2 result) - { - float squared = amount * amount; - float cubed = amount * squared; - - result.X = 0.5f * ((((2.0f * value2.X) + ((-value1.X + value3.X) * amount)) + - (((((2.0f * value1.X) - (5.0f * value2.X)) + (4.0f * value3.X)) - value4.X) * squared)) + - ((((-value1.X + (3.0f * value2.X)) - (3.0f * value3.X)) + value4.X) * cubed)); - - result.Y = 0.5f * ((((2.0f * value2.Y) + ((-value1.Y + value3.Y) * amount)) + - (((((2.0f * value1.Y) - (5.0f * value2.Y)) + (4.0f * value3.Y)) - value4.Y) * squared)) + - ((((-value1.Y + (3.0f * value2.Y)) - (3.0f * value3.Y)) + value4.Y) * cubed)); - } - - /// - /// Performs a Catmull-Rom interpolation using the specified positions. - /// - /// The first position in the interpolation. - /// The second position in the interpolation. - /// The third position in the interpolation. - /// The fourth position in the interpolation. - /// Weighting factor. - /// A vector that is the result of the Catmull-Rom interpolation. - public static Vector2 CatmullRom(Vector2 value1, Vector2 value2, Vector2 value3, Vector2 value4, float amount) - { - Vector2 result; - CatmullRom(ref value1, ref value2, ref value3, ref value4, amount, out result); - return result; - } - - /// - /// Returns a vector containing the largest components of the specified vectors. - /// - /// The first source vector. - /// The second source vector. - /// When the method completes, contains an new vector composed of the largest components of the source vectors. - public static void Max(ref Vector2 left, ref Vector2 right, out Vector2 result) - { - result.X = (left.X > right.X) ? left.X : right.X; - result.Y = (left.Y > right.Y) ? left.Y : right.Y; - } - - /// - /// Returns a vector containing the largest components of the specified vectors. - /// - /// The first source vector. - /// The second source vector. - /// A vector containing the largest components of the source vectors. - public static Vector2 Max(Vector2 left, Vector2 right) - { - Vector2 result; - Max(ref left, ref right, out result); - return result; - } - - /// - /// Returns a vector containing the smallest components of the specified vectors. - /// - /// The first source vector. - /// The second source vector. - /// When the method completes, contains an new vector composed of the smallest components of the source vectors. - public static void Min(ref Vector2 left, ref Vector2 right, out Vector2 result) - { - result.X = (left.X < right.X) ? left.X : right.X; - result.Y = (left.Y < right.Y) ? left.Y : right.Y; - } - - /// - /// Returns a vector containing the smallest components of the specified vectors. - /// - /// The first source vector. - /// The second source vector. - /// A vector containing the smallest components of the source vectors. - public static Vector2 Min(Vector2 left, Vector2 right) - { - Vector2 result; - Min(ref left, ref right, out result); - return result; - } - - /// - /// Returns the reflection of a vector off a surface that has the specified normal. - /// - /// The source vector. - /// Normal of the surface. - /// When the method completes, contains the reflected vector. - /// Reflect only gives the direction of a reflection off a surface, it does not determine - /// whether the original vector was close enough to the surface to hit it. - public static void Reflect(ref Vector2 vector, ref Vector2 normal, out Vector2 result) - { - float dot = (vector.X * normal.X) + (vector.Y * normal.Y); - - result.X = vector.X - ((2.0f * dot) * normal.X); - result.Y = vector.Y - ((2.0f * dot) * normal.Y); - } - - /// - /// Returns the reflection of a vector off a surface that has the specified normal. - /// - /// The source vector. - /// Normal of the surface. - /// The reflected vector. - /// Reflect only gives the direction of a reflection off a surface, it does not determine - /// whether the original vector was close enough to the surface to hit it. - public static Vector2 Reflect(Vector2 vector, Vector2 normal) - { - Vector2 result; - Reflect(ref vector, ref normal, out result); - return result; - } - - /// - /// Orthogonalizes a list of vectors. - /// - /// The list of orthogonalized vectors. - /// The list of vectors to orthogonalize. - /// - /// Orthogonalization is the process of making all vectors orthogonal to each other. This - /// means that any given vector in the list will be orthogonal to any other given vector in the - /// list. - /// Because this method uses the modified Gram-Schmidt process, the resulting vectors - /// tend to be numerically unstable. The numeric stability decreases according to the vectors - /// position in the list so that the first vector is the most stable and the last vector is the - /// least stable. - /// - /// Thrown when or is null. - /// Thrown when is shorter in length than . - public static void Orthogonalize(Vector2[] destination, params Vector2[] source) - { - //Uses the modified Gram-Schmidt process. - //q1 = m1 - //q2 = m2 - ((q1 ⋅ m2) / (q1 ⋅ q1)) * q1 - //q3 = m3 - ((q1 ⋅ m3) / (q1 ⋅ q1)) * q1 - ((q2 ⋅ m3) / (q2 ⋅ q2)) * q2 - //q4 = m4 - ((q1 ⋅ m4) / (q1 ⋅ q1)) * q1 - ((q2 ⋅ m4) / (q2 ⋅ q2)) * q2 - ((q3 ⋅ m4) / (q3 ⋅ q3)) * q3 - //q5 = ... - - if (source == null) - throw new ArgumentNullException("source"); - if (destination == null) - throw new ArgumentNullException("destination"); - if (destination.Length < source.Length) - throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); - - for (int i = 0; i < source.Length; ++i) - { - Vector2 newvector = source[i]; - - for (int r = 0; r < i; ++r) - { - newvector -= (Vector2.Dot(destination[r], newvector) / Vector2.Dot(destination[r], destination[r])) * destination[r]; - } - - destination[i] = newvector; - } - } - - /// - /// Orthonormalizes a list of vectors. - /// - /// The list of orthonormalized vectors. - /// The list of vectors to orthonormalize. - /// - /// Orthonormalization is the process of making all vectors orthogonal to each - /// other and making all vectors of unit length. This means that any given vector will - /// be orthogonal to any other given vector in the list. - /// Because this method uses the modified Gram-Schmidt process, the resulting vectors - /// tend to be numerically unstable. The numeric stability decreases according to the vectors - /// position in the list so that the first vector is the most stable and the last vector is the - /// least stable. - /// - /// Thrown when or is null. - /// Thrown when is shorter in length than . - public static void Orthonormalize(Vector2[] destination, params Vector2[] source) - { - //Uses the modified Gram-Schmidt process. - //Because we are making unit vectors, we can optimize the math for orthogonalization - //and simplify the projection operation to remove the division. - //q1 = m1 / |m1| - //q2 = (m2 - (q1 ⋅ m2) * q1) / |m2 - (q1 ⋅ m2) * q1| - //q3 = (m3 - (q1 ⋅ m3) * q1 - (q2 ⋅ m3) * q2) / |m3 - (q1 ⋅ m3) * q1 - (q2 ⋅ m3) * q2| - //q4 = (m4 - (q1 ⋅ m4) * q1 - (q2 ⋅ m4) * q2 - (q3 ⋅ m4) * q3) / |m4 - (q1 ⋅ m4) * q1 - (q2 ⋅ m4) * q2 - (q3 ⋅ m4) * q3| - //q5 = ... - - if (source == null) - throw new ArgumentNullException("source"); - if (destination == null) - throw new ArgumentNullException("destination"); - if (destination.Length < source.Length) - throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); - - for (int i = 0; i < source.Length; ++i) - { - Vector2 newvector = source[i]; - - for (int r = 0; r < i; ++r) - { - newvector -= Vector2.Dot(destination[r], newvector) * destination[r]; - } - - newvector.Normalize(); - destination[i] = newvector; - } - } - - /// - /// Transforms a 2D vector by the given rotation. - /// - /// The vector to rotate. - /// The rotation to apply. - /// When the method completes, contains the transformed . - public static void Transform(ref Vector2 vector, ref Quaternion rotation, out Vector2 result) - { - float x = rotation.X + rotation.X; - float y = rotation.Y + rotation.Y; - float z = rotation.Z + rotation.Z; - float wz = rotation.W * z; - float xx = rotation.X * x; - float xy = rotation.X * y; - float yy = rotation.Y * y; - float zz = rotation.Z * z; - - result = new Vector2((vector.X * (1.0f - yy - zz)) + (vector.Y * (xy - wz)), (vector.X * (xy + wz)) + (vector.Y * (1.0f - xx - zz))); - } - - /// - /// Transforms a 2D vector by the given rotation. - /// - /// The vector to rotate. - /// The rotation to apply. - /// The transformed . - public static Vector2 Transform(Vector2 vector, Quaternion rotation) - { - Vector2 result; - Transform(ref vector, ref rotation, out result); - return result; - } - - /// - /// Transforms an array of vectors by the given rotation. - /// - /// The array of vectors to transform. - /// The rotation to apply. - /// The array for which the transformed vectors are stored. - /// This array may be the same array as . - /// Thrown when or is null. - /// Thrown when is shorter in length than . - public static void Transform(Vector2[] source, ref Quaternion rotation, Vector2[] destination) - { - if (source == null) - throw new ArgumentNullException("source"); - if (destination == null) - throw new ArgumentNullException("destination"); - if (destination.Length < source.Length) - throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); - - float x = rotation.X + rotation.X; - float y = rotation.Y + rotation.Y; - float z = rotation.Z + rotation.Z; - float wz = rotation.W * z; - float xx = rotation.X * x; - float xy = rotation.X * y; - float yy = rotation.Y * y; - float zz = rotation.Z * z; - - float num1 = (1.0f - yy - zz); - float num2 = (xy - wz); - float num3 = (xy + wz); - float num4 = (1.0f - xx - zz); - - for (int i = 0; i < source.Length; ++i) - { - destination[i] = new Vector2( - (source[i].X * num1) + (source[i].Y * num2), - (source[i].X * num3) + (source[i].Y * num4)); - } - } - - /// - /// Transforms a 2D vector by the given . - /// - /// The source vector. - /// The transformation . - /// When the method completes, contains the transformed . - public static void Transform(ref Vector2 vector, ref Matrix transform, out Vector4 result) - { - result = new Vector4( - (vector.X * transform.M11) + (vector.Y * transform.M21) + transform.M41, - (vector.X * transform.M12) + (vector.Y * transform.M22) + transform.M42, - (vector.X * transform.M13) + (vector.Y * transform.M23) + transform.M43, - (vector.X * transform.M14) + (vector.Y * transform.M24) + transform.M44); - } - - /// - /// Transforms a 2D vector by the given . - /// - /// The source vector. - /// The transformation . - /// The transformed . - public static Vector4 Transform(Vector2 vector, Matrix transform) - { - Vector4 result; - Transform(ref vector, ref transform, out result); - return result; - } - - /// - /// Transforms an array of 2D vectors by the given . - /// - /// The array of vectors to transform. - /// The transformation . - /// The array for which the transformed vectors are stored. - /// Thrown when or is null. - /// Thrown when is shorter in length than . - public static void Transform(Vector2[] source, ref Matrix transform, Vector4[] destination) - { - if (source == null) - throw new ArgumentNullException("source"); - if (destination == null) - throw new ArgumentNullException("destination"); - if (destination.Length < source.Length) - throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); - - for (int i = 0; i < source.Length; ++i) - { - Transform(ref source[i], ref transform, out destination[i]); - } - } - - /// - /// Performs a coordinate transformation using the given . - /// - /// The coordinate vector to transform. - /// The transformation . - /// When the method completes, contains the transformed coordinates. - /// - /// A coordinate transform performs the transformation with the assumption that the w component - /// is one. The four dimensional vector obtained from the transformation operation has each - /// component in the vector divided by the w component. This forces the w component to be one and - /// therefore makes the vector homogeneous. The homogeneous vector is often preferred when working - /// with coordinates as the w component can safely be ignored. - /// - public static void TransformCoordinate(ref Vector2 coordinate, ref Matrix transform, out Vector2 result) - { - Vector4 vector = new Vector4(); - vector.X = (coordinate.X * transform.M11) + (coordinate.Y * transform.M21) + transform.M41; - vector.Y = (coordinate.X * transform.M12) + (coordinate.Y * transform.M22) + transform.M42; - vector.Z = (coordinate.X * transform.M13) + (coordinate.Y * transform.M23) + transform.M43; - vector.W = 1f / ((coordinate.X * transform.M14) + (coordinate.Y * transform.M24) + transform.M44); - - result = new Vector2(vector.X * vector.W, vector.Y * vector.W); - } - - /// - /// Performs a coordinate transformation using the given . - /// - /// The coordinate vector to transform. - /// The transformation . - /// The transformed coordinates. - /// - /// A coordinate transform performs the transformation with the assumption that the w component - /// is one. The four dimensional vector obtained from the transformation operation has each - /// component in the vector divided by the w component. This forces the w component to be one and - /// therefore makes the vector homogeneous. The homogeneous vector is often preferred when working - /// with coordinates as the w component can safely be ignored. - /// - public static Vector2 TransformCoordinate(Vector2 coordinate, Matrix transform) - { - Vector2 result; - TransformCoordinate(ref coordinate, ref transform, out result); - return result; - } - - /// - /// Performs a coordinate transformation on an array of vectors using the given . - /// - /// The array of coordinate vectors to transform. - /// The transformation . - /// The array for which the transformed vectors are stored. - /// This array may be the same array as . - /// Thrown when or is null. - /// Thrown when is shorter in length than . - /// - /// A coordinate transform performs the transformation with the assumption that the w component - /// is one. The four dimensional vector obtained from the transformation operation has each - /// component in the vector divided by the w component. This forces the w component to be one and - /// therefore makes the vector homogeneous. The homogeneous vector is often preferred when working - /// with coordinates as the w component can safely be ignored. - /// - public static void TransformCoordinate(Vector2[] source, ref Matrix transform, Vector2[] destination) - { - if (source == null) - throw new ArgumentNullException("source"); - if (destination == null) - throw new ArgumentNullException("destination"); - if (destination.Length < source.Length) - throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); - - for (int i = 0; i < source.Length; ++i) - { - TransformCoordinate(ref source[i], ref transform, out destination[i]); - } - } - - /// - /// Performs a normal transformation using the given . - /// - /// The normal vector to transform. - /// The transformation . - /// When the method completes, contains the transformed normal. - /// - /// A normal transform performs the transformation with the assumption that the w component - /// is zero. This causes the fourth row and fourth column of the matrix to be unused. The - /// end result is a vector that is not translated, but all other transformation properties - /// apply. This is often preferred for normal vectors as normals purely represent direction - /// rather than location because normal vectors should not be translated. - /// - public static void TransformNormal(ref Vector2 normal, ref Matrix transform, out Vector2 result) - { - result = new Vector2( - (normal.X * transform.M11) + (normal.Y * transform.M21), - (normal.X * transform.M12) + (normal.Y * transform.M22)); - } - - /// - /// Performs a normal transformation using the given . - /// - /// The normal vector to transform. - /// The transformation . - /// The transformed normal. - /// - /// A normal transform performs the transformation with the assumption that the w component - /// is zero. This causes the fourth row and fourth column of the matrix to be unused. The - /// end result is a vector that is not translated, but all other transformation properties - /// apply. This is often preferred for normal vectors as normals purely represent direction - /// rather than location because normal vectors should not be translated. - /// - public static Vector2 TransformNormal(Vector2 normal, Matrix transform) - { - Vector2 result; - TransformNormal(ref normal, ref transform, out result); - return result; - } - - /// - /// Performs a normal transformation on an array of vectors using the given . - /// - /// The array of normal vectors to transform. - /// The transformation . - /// The array for which the transformed vectors are stored. - /// This array may be the same array as . - /// Thrown when or is null. - /// Thrown when is shorter in length than . - /// - /// A normal transform performs the transformation with the assumption that the w component - /// is zero. This causes the fourth row and fourth column of the matrix to be unused. The - /// end result is a vector that is not translated, but all other transformation properties - /// apply. This is often preferred for normal vectors as normals purely represent direction - /// rather than location because normal vectors should not be translated. - /// - public static void TransformNormal(Vector2[] source, ref Matrix transform, Vector2[] destination) - { - if (source == null) - throw new ArgumentNullException("source"); - if (destination == null) - throw new ArgumentNullException("destination"); - if (destination.Length < source.Length) - throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); - - for (int i = 0; i < source.Length; ++i) - { - TransformNormal(ref source[i], ref transform, out destination[i]); - } - } - - /// - /// Adds two vectors. - /// - /// The first vector to add. - /// The second vector to add. - /// The sum of the two vectors. - public static Vector2 operator +(Vector2 left, Vector2 right) - { - return new Vector2(left.X + right.X, left.Y + right.Y); - } - - /// - /// Multiplies a vector with another by performing component-wise multiplication equivalent to . - /// - /// The first vector to multiply. - /// The second vector to multiply. - /// The multiplication of the two vectors. - public static Vector2 operator *(Vector2 left, Vector2 right) - { - return new Vector2(left.X * right.X, left.Y * right.Y); - } - - /// - /// Assert a vector (return it unchanged). - /// - /// The vector to assert (unchanged). - /// The asserted (unchanged) vector. - public static Vector2 operator +(Vector2 value) - { - return value; - } - - /// - /// Subtracts two vectors. - /// - /// The first vector to subtract. - /// The second vector to subtract. - /// The difference of the two vectors. - public static Vector2 operator -(Vector2 left, Vector2 right) - { - return new Vector2(left.X - right.X, left.Y - right.Y); - } - - /// - /// Reverses the direction of a given vector. - /// - /// The vector to negate. - /// A vector facing in the opposite direction. - public static Vector2 operator -(Vector2 value) - { - return new Vector2(-value.X, -value.Y); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector2 operator *(float scale, Vector2 value) - { - return new Vector2(value.X * scale, value.Y * scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector2 operator *(Vector2 value, float scale) - { - return new Vector2(value.X * scale, value.Y * scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector2 operator /(Vector2 value, float scale) - { - return new Vector2(value.X / scale, value.Y / scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The amount by which to scale the vector. - /// The vector to scale. - /// The scaled vector. - public static Vector2 operator /(float scale , Vector2 value) - { - return new Vector2(scale / value.X, scale / value.Y); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector2 operator /(Vector2 value, Vector2 scale) - { - return new Vector2(value.X / scale.X, value.Y / scale.Y); - } - - /// - /// Perform a component-wise addition - /// - /// The input vector. - /// The scalar value to be added on elements - /// The vector with added scalar for each element. - public static Vector2 operator +(Vector2 value, float scalar) - { - return new Vector2(value.X + scalar, value.Y + scalar); - } - - /// - /// Perform a component-wise addition - /// - /// The input vector. - /// The scalar value to be added on elements - /// The vector with added scalar for each element. - public static Vector2 operator +(float scalar, Vector2 value) - { - return new Vector2(scalar + value.X, scalar + value.Y); - } - - /// - /// Perform a component-wise subtraction - /// - /// The input vector. - /// The scalar value to be subtraced from elements - /// The vector with subtraced scalar from each element. - public static Vector2 operator -(Vector2 value, float scalar) - { - return new Vector2(value.X - scalar, value.Y - scalar); - } - - /// - /// Perform a component-wise subtraction - /// - /// The input vector. - /// The scalar value to be subtraced from elements - /// The vector with subtraced scalar from each element. - public static Vector2 operator -(float scalar, Vector2 value) - { - return new Vector2(scalar - value.X, scalar - value.Y); - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has the same value as ; otherwise, false. - public static bool operator ==(Vector2 left, Vector2 right) - { - return left.Equals(ref right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has a different value than ; otherwise, false. - public static bool operator !=(Vector2 left, Vector2 right) - { - return !left.Equals(ref right); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Vector3(Vector2 value) - { - return new Vector3(value, 0.0f); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Vector4(Vector2 value) - { - return new Vector4(value, 0.0f, 0.0f); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1}", X, Y); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// - /// A that represents this instance. - /// - public string ToString(string format) - { - if (format == null) - return ToString(); - - return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1}", X.ToString(format, CultureInfo.CurrentCulture), Y.ToString(format, CultureInfo.CurrentCulture)); - } - - /// - /// Returns a that represents this instance. - /// - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(IFormatProvider formatProvider) - { - return string.Format(formatProvider, "X:{0} Y:{1}", X, Y); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - if (format == null) - ToString(formatProvider); - - return string.Format(formatProvider, "X:{0} Y:{1}", X.ToString(format, formatProvider), Y.ToString(format, formatProvider)); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - return (X.GetHashCode() * 397) ^ Y.GetHashCode(); - } - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(X); - serializer.Writer.Write(Y); - } - else - { - X = serializer.Reader.ReadSingle(); - Y = serializer.Reader.ReadSingle(); - } - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(ref Vector2 other) - { - return MathUtil.NearEqual(other.X, X) && MathUtil.NearEqual(other.Y, Y); - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(Vector2 other) - { - return Equals(ref other); - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object value) - { - if (!(value is Vector2)) - return false; - - var strongValue = (Vector2)value; - return Equals(ref strongValue); - } - -#if WPFInterop - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator System.Windows.Point(Vector2 value) - { - return new System.Windows.Point(value.X, value.Y); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Vector2(System.Windows.Point value) - { - return new Vector2((float)value.X, (float)value.Y); - } -#endif - -#if XnaInterop - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Microsoft.Xna.Framework.Vector2(Vector2 value) - { - return new Microsoft.Xna.Framework.Vector2(value.X, value.Y); - } - - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Vector2(Microsoft.Xna.Framework.Vector2 value) - { - return new Vector2(value.X, value.Y); - } -#endif - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from SlimMath project. http://code.google.com/p/slimmath/ +// Greetings to SlimDX Group. Original code published with the following license: +// ----------------------------------------------------------------------------- +/* +* Copyright (c) 2007-2011 SlimDX Group +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Represents a two dimensional mathematical vector. + /// + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct Vector2 : IEquatable, IFormattable + { + /// + /// The size of the type, in bytes. + /// + public static readonly int SizeInBytes = Marshal.SizeOf(typeof(Vector2)); + + /// + /// A with all of its components set to zero. + /// + public static readonly Vector2 Zero = new Vector2(); + + /// + /// The X unit (1, 0). + /// + public static readonly Vector2 UnitX = new Vector2(1.0f, 0.0f); + + /// + /// The Y unit (0, 1). + /// + public static readonly Vector2 UnitY = new Vector2(0.0f, 1.0f); + + /// + /// A with all of its components set to one. + /// + public static readonly Vector2 One = new Vector2(1.0f, 1.0f); + + /// + /// The X component of the vector. + /// + public float X; + + /// + /// The Y component of the vector. + /// + public float Y; + + /// + /// Initializes a new instance of the struct. + /// + /// The value that will be assigned to all components. + public Vector2(float value) + { + X = value; + Y = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// Initial value for the X component of the vector. + /// Initial value for the Y component of the vector. + public Vector2(float x, float y) + { + X = x; + Y = y; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The values to assign to the X and Y components of the vector. This must be an array with two elements. + /// Thrown when is null. + /// Thrown when contains more or less than two elements. + public Vector2(float[] values) + { + if (values == null) + throw new ArgumentNullException("values"); + if (values.Length != 2) + throw new ArgumentOutOfRangeException("values", "There must be two and only two input values for Vector2."); + + X = values[0]; + Y = values[1]; + } + + /// + /// Gets a value indicting whether this instance is normalized. + /// + public bool IsNormalized + { + get { return MathUtil.IsOne((X * X) + (Y * Y)); } + } + + /// + /// Gets a value indicting whether this vector is zero + /// + public bool IsZero + { + get { return X == 0 && Y == 0; } + } + + /// + /// Gets or sets the component at the specified index. + /// + /// The value of the X or Y component, depending on the index. + /// The index of the component to access. Use 0 for the X component and 1 for the Y component. + /// The value of the component at the specified index. + /// Thrown when the is out of the range [0, 1]. + public float this[int index] + { + get + { + switch (index) + { + case 0: return X; + case 1: return Y; + } + + throw new ArgumentOutOfRangeException("index", "Indices for Vector2 run from 0 to 1, inclusive."); + } + + set + { + switch (index) + { + case 0: X = value; break; + case 1: Y = value; break; + default: throw new ArgumentOutOfRangeException("index", "Indices for Vector2 run from 0 to 1, inclusive."); + } + } + } + + /// + /// Calculates the length of the vector. + /// + /// The length of the vector. + /// + /// may be preferred when only the relative length is needed + /// and speed is of the essence. + /// + public float Length() + { + return (float)Math.Sqrt((X * X) + (Y * Y)); + } + + /// + /// Calculates the squared length of the vector. + /// + /// The squared length of the vector. + /// + /// This method may be preferred to when only a relative length is needed + /// and speed is of the essence. + /// + public float LengthSquared() + { + return (X * X) + (Y * Y); + } + + /// + /// Converts the vector into a unit vector. + /// + public void Normalize() + { + float length = Length(); + if (!MathUtil.IsZero(length)) + { + float inv = 1.0f / length; + X *= inv; + Y *= inv; + } + } + + /// + /// Creates an array containing the elements of the vector. + /// + /// A two-element array containing the components of the vector. + public float[] ToArray() + { + return new float[] { X, Y }; + } + + /// + /// Adds two vectors. + /// + /// The first vector to add. + /// The second vector to add. + /// When the method completes, contains the sum of the two vectors. + public static void Add(ref Vector2 left, ref Vector2 right, out Vector2 result) + { + result = new Vector2(left.X + right.X, left.Y + right.Y); + } + + /// + /// Adds two vectors. + /// + /// The first vector to add. + /// The second vector to add. + /// The sum of the two vectors. + public static Vector2 Add(Vector2 left, Vector2 right) + { + return new Vector2(left.X + right.X, left.Y + right.Y); + } + + /// + /// Perform a component-wise addition + /// + /// The input vector + /// The scalar value to be added to elements + /// The vector with added scalar for each element. + public static void Add(ref Vector2 left, ref float right, out Vector2 result) + { + result = new Vector2(left.X + right, left.Y + right); + } + + /// + /// Perform a component-wise addition + /// + /// The input vector + /// The scalar value to be added to elements + /// The vector with added scalar for each element. + public static Vector2 Add(Vector2 left, float right) + { + return new Vector2(left.X + right, left.Y + right); + } + + /// + /// Subtracts two vectors. + /// + /// The first vector to subtract. + /// The second vector to subtract. + /// When the method completes, contains the difference of the two vectors. + public static void Subtract(ref Vector2 left, ref Vector2 right, out Vector2 result) + { + result = new Vector2(left.X - right.X, left.Y - right.Y); + } + + /// + /// Subtracts two vectors. + /// + /// The first vector to subtract. + /// The second vector to subtract. + /// The difference of the two vectors. + public static Vector2 Subtract(Vector2 left, Vector2 right) + { + return new Vector2(left.X - right.X, left.Y - right.Y); + } + + /// + /// Perform a component-wise subtraction + /// + /// The input vector + /// The scalar value to be subtraced from elements + /// The vector with subtracted scalar for each element. + public static void Subtract(ref Vector2 left, ref float right, out Vector2 result) + { + result = new Vector2(left.X - right, left.Y - right); + } + + /// + /// Perform a component-wise subtraction + /// + /// The input vector + /// The scalar value to be subtraced from elements + /// The vector with subtracted scalar for each element. + public static Vector2 Subtract(Vector2 left, float right) + { + return new Vector2(left.X - right, left.Y - right); + } + + /// + /// Perform a component-wise subtraction + /// + /// The scalar value to be subtraced from elements + /// The input vector + /// The vector with subtracted scalar for each element. + public static void Subtract(ref float left, ref Vector2 right, out Vector2 result) + { + result = new Vector2(left - right.X, left - right.Y); + } + + /// + /// Perform a component-wise subtraction + /// + /// The scalar value to be subtraced from elements + /// The input vector + /// The vector with subtracted scalar for each element. + public static Vector2 Subtract(float left, Vector2 right) + { + return new Vector2(left - right.X, left - right.Y); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// When the method completes, contains the scaled vector. + public static void Multiply(ref Vector2 value, float scale, out Vector2 result) + { + result = new Vector2(value.X * scale, value.Y * scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector2 Multiply(Vector2 value, float scale) + { + return new Vector2(value.X * scale, value.Y * scale); + } + + /// + /// Multiplies a vector with another by performing component-wise multiplication. + /// + /// The first vector to multiply. + /// The second vector to multiply. + /// When the method completes, contains the multiplied vector. + public static void Multiply(ref Vector2 left, ref Vector2 right, out Vector2 result) + { + result = new Vector2(left.X * right.X, left.Y * right.Y); + } + + /// + /// Multiplies a vector with another by performing component-wise multiplication. + /// + /// The first vector to multiply. + /// The second vector to multiply. + /// The multiplied vector. + public static Vector2 Multiply(Vector2 left, Vector2 right) + { + return new Vector2(left.X * right.X, left.Y * right.Y); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// When the method completes, contains the scaled vector. + public static void Divide(ref Vector2 value, float scale, out Vector2 result) + { + result = new Vector2(value.X / scale, value.Y / scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector2 Divide(Vector2 value, float scale) + { + return new Vector2(value.X / scale, value.Y / scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The amount by which to scale the vector. + /// The vector to scale. + /// When the method completes, contains the scaled vector. + public static void Divide(float scale,ref Vector2 value, out Vector2 result) + { + result = new Vector2(scale / value.X, scale / value.Y); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector2 Divide(float scale, Vector2 value) + { + return new Vector2(scale / value.X, scale / value.Y); + } + + /// + /// Reverses the direction of a given vector. + /// + /// The vector to negate. + /// When the method completes, contains a vector facing in the opposite direction. + public static void Negate(ref Vector2 value, out Vector2 result) + { + result = new Vector2(-value.X, -value.Y); + } + + /// + /// Reverses the direction of a given vector. + /// + /// The vector to negate. + /// A vector facing in the opposite direction. + public static Vector2 Negate(Vector2 value) + { + return new Vector2(-value.X, -value.Y); + } + + /// + /// Returns a containing the 2D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 2D triangle. + /// + /// A containing the 2D Cartesian coordinates of vertex 1 of the triangle. + /// A containing the 2D Cartesian coordinates of vertex 2 of the triangle. + /// A containing the 2D Cartesian coordinates of vertex 3 of the triangle. + /// Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). + /// Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). + /// When the method completes, contains the 2D Cartesian coordinates of the specified point. + public static void Barycentric(ref Vector2 value1, ref Vector2 value2, ref Vector2 value3, float amount1, float amount2, out Vector2 result) + { + result = new Vector2((value1.X + (amount1 * (value2.X - value1.X))) + (amount2 * (value3.X - value1.X)), + (value1.Y + (amount1 * (value2.Y - value1.Y))) + (amount2 * (value3.Y - value1.Y))); + } + + /// + /// Returns a containing the 2D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 2D triangle. + /// + /// A containing the 2D Cartesian coordinates of vertex 1 of the triangle. + /// A containing the 2D Cartesian coordinates of vertex 2 of the triangle. + /// A containing the 2D Cartesian coordinates of vertex 3 of the triangle. + /// Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). + /// Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). + /// A new containing the 2D Cartesian coordinates of the specified point. + public static Vector2 Barycentric(Vector2 value1, Vector2 value2, Vector2 value3, float amount1, float amount2) + { + Vector2 result; + Barycentric(ref value1, ref value2, ref value3, amount1, amount2, out result); + return result; + } + + /// + /// Restricts a value to be within a specified range. + /// + /// The value to clamp. + /// The minimum value. + /// The maximum value. + /// When the method completes, contains the clamped value. + public static void Clamp(ref Vector2 value, ref Vector2 min, ref Vector2 max, out Vector2 result) + { + float x = value.X; + x = (x > max.X) ? max.X : x; + x = (x < min.X) ? min.X : x; + + float y = value.Y; + y = (y > max.Y) ? max.Y : y; + y = (y < min.Y) ? min.Y : y; + + result = new Vector2(x, y); + } + + /// + /// Restricts a value to be within a specified range. + /// + /// The value to clamp. + /// The minimum value. + /// The maximum value. + /// The clamped value. + public static Vector2 Clamp(Vector2 value, Vector2 min, Vector2 max) + { + Vector2 result; + Clamp(ref value, ref min, ref max, out result); + return result; + } + + /// + /// Saturates this instance in the range [0,1] + /// + public void Saturate() + { + X = X < 0.0f ? 0.0f : X > 1.0f ? 1.0f : X; + Y = Y < 0.0f ? 0.0f : Y > 1.0f ? 1.0f : Y; + } + + /// + /// Calculates the distance between two vectors. + /// + /// The first vector. + /// The second vector. + /// When the method completes, contains the distance between the two vectors. + /// + /// may be preferred when only the relative distance is needed + /// and speed is of the essence. + /// + public static void Distance(ref Vector2 value1, ref Vector2 value2, out float result) + { + float x = value1.X - value2.X; + float y = value1.Y - value2.Y; + + result = (float)Math.Sqrt((x * x) + (y * y)); + } + + /// + /// Calculates the distance between two vectors. + /// + /// The first vector. + /// The second vector. + /// The distance between the two vectors. + /// + /// may be preferred when only the relative distance is needed + /// and speed is of the essence. + /// + public static float Distance(Vector2 value1, Vector2 value2) + { + float x = value1.X - value2.X; + float y = value1.Y - value2.Y; + + return (float)Math.Sqrt((x * x) + (y * y)); + } + + /// + /// Calculates the squared distance between two vectors. + /// + /// The first vector. + /// The second vector + /// When the method completes, contains the squared distance between the two vectors. + /// Distance squared is the value before taking the square root. + /// Distance squared can often be used in place of distance if relative comparisons are being made. + /// For example, consider three points A, B, and C. To determine whether B or C is further from A, + /// compare the distance between A and B to the distance between A and C. Calculating the two distances + /// involves two square roots, which are computationally expensive. However, using distance squared + /// provides the same information and avoids calculating two square roots. + /// + public static void DistanceSquared(ref Vector2 value1, ref Vector2 value2, out float result) + { + float x = value1.X - value2.X; + float y = value1.Y - value2.Y; + + result = (x * x) + (y * y); + } + + /// + /// Calculates the squared distance between two vectors. + /// + /// The first vector. + /// The second vector. + /// The squared distance between the two vectors. + /// Distance squared is the value before taking the square root. + /// Distance squared can often be used in place of distance if relative comparisons are being made. + /// For example, consider three points A, B, and C. To determine whether B or C is further from A, + /// compare the distance between A and B to the distance between A and C. Calculating the two distances + /// involves two square roots, which are computationally expensive. However, using distance squared + /// provides the same information and avoids calculating two square roots. + /// + public static float DistanceSquared(Vector2 value1, Vector2 value2) + { + float x = value1.X - value2.X; + float y = value1.Y - value2.Y; + + return (x * x) + (y * y); + } + + /// + /// Calculates the dot product of two vectors. + /// + /// First source vector. + /// Second source vector. + /// When the method completes, contains the dot product of the two vectors. + public static void Dot(ref Vector2 left, ref Vector2 right, out float result) + { + result = (left.X * right.X) + (left.Y * right.Y); + } + + /// + /// Calculates the dot product of two vectors. + /// + /// First source vector. + /// Second source vector. + /// The dot product of the two vectors. + public static float Dot(Vector2 left, Vector2 right) + { + return (left.X * right.X) + (left.Y * right.Y); + } + + /// + /// Converts the vector into a unit vector. + /// + /// The vector to normalize. + /// When the method completes, contains the normalized vector. + public static void Normalize(ref Vector2 value, out Vector2 result) + { + result = value; + result.Normalize(); + } + + /// + /// Converts the vector into a unit vector. + /// + /// The vector to normalize. + /// The normalized vector. + public static Vector2 Normalize(Vector2 value) + { + value.Normalize(); + return value; + } + + /// + /// Performs a linear interpolation between two vectors. + /// + /// Start vector. + /// End vector. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the linear interpolation of the two vectors. + /// + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static void Lerp(ref Vector2 start, ref Vector2 end, float amount, out Vector2 result) + { + result.X = MathUtil.Lerp(start.X, end.X, amount); + result.Y = MathUtil.Lerp(start.Y, end.Y, amount); + } + + /// + /// Performs a linear interpolation between two vectors. + /// + /// Start vector. + /// End vector. + /// Value between 0 and 1 indicating the weight of . + /// The linear interpolation of the two vectors. + /// + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static Vector2 Lerp(Vector2 start, Vector2 end, float amount) + { + Vector2 result; + Lerp(ref start, ref end, amount, out result); + return result; + } + + /// + /// Performs a cubic interpolation between two vectors. + /// + /// Start vector. + /// End vector. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the cubic interpolation of the two vectors. + public static void SmoothStep(ref Vector2 start, ref Vector2 end, float amount, out Vector2 result) + { + amount = MathUtil.SmoothStep(amount); + Lerp(ref start, ref end, amount, out result); + } + + /// + /// Performs a cubic interpolation between two vectors. + /// + /// Start vector. + /// End vector. + /// Value between 0 and 1 indicating the weight of . + /// The cubic interpolation of the two vectors. + public static Vector2 SmoothStep(Vector2 start, Vector2 end, float amount) + { + Vector2 result; + SmoothStep(ref start, ref end, amount, out result); + return result; + } + + /// + /// Performs a Hermite spline interpolation. + /// + /// First source position vector. + /// First source tangent vector. + /// Second source position vector. + /// Second source tangent vector. + /// Weighting factor. + /// When the method completes, contains the result of the Hermite spline interpolation. + public static void Hermite(ref Vector2 value1, ref Vector2 tangent1, ref Vector2 value2, ref Vector2 tangent2, float amount, out Vector2 result) + { + float squared = amount * amount; + float cubed = amount * squared; + float part1 = ((2.0f * cubed) - (3.0f * squared)) + 1.0f; + float part2 = (-2.0f * cubed) + (3.0f * squared); + float part3 = (cubed - (2.0f * squared)) + amount; + float part4 = cubed - squared; + + result.X = (((value1.X * part1) + (value2.X * part2)) + (tangent1.X * part3)) + (tangent2.X * part4); + result.Y = (((value1.Y * part1) + (value2.Y * part2)) + (tangent1.Y * part3)) + (tangent2.Y * part4); + } + + /// + /// Performs a Hermite spline interpolation. + /// + /// First source position vector. + /// First source tangent vector. + /// Second source position vector. + /// Second source tangent vector. + /// Weighting factor. + /// The result of the Hermite spline interpolation. + public static Vector2 Hermite(Vector2 value1, Vector2 tangent1, Vector2 value2, Vector2 tangent2, float amount) + { + Vector2 result; + Hermite(ref value1, ref tangent1, ref value2, ref tangent2, amount, out result); + return result; + } + + /// + /// Performs a Catmull-Rom interpolation using the specified positions. + /// + /// The first position in the interpolation. + /// The second position in the interpolation. + /// The third position in the interpolation. + /// The fourth position in the interpolation. + /// Weighting factor. + /// When the method completes, contains the result of the Catmull-Rom interpolation. + public static void CatmullRom(ref Vector2 value1, ref Vector2 value2, ref Vector2 value3, ref Vector2 value4, float amount, out Vector2 result) + { + float squared = amount * amount; + float cubed = amount * squared; + + result.X = 0.5f * ((((2.0f * value2.X) + ((-value1.X + value3.X) * amount)) + + (((((2.0f * value1.X) - (5.0f * value2.X)) + (4.0f * value3.X)) - value4.X) * squared)) + + ((((-value1.X + (3.0f * value2.X)) - (3.0f * value3.X)) + value4.X) * cubed)); + + result.Y = 0.5f * ((((2.0f * value2.Y) + ((-value1.Y + value3.Y) * amount)) + + (((((2.0f * value1.Y) - (5.0f * value2.Y)) + (4.0f * value3.Y)) - value4.Y) * squared)) + + ((((-value1.Y + (3.0f * value2.Y)) - (3.0f * value3.Y)) + value4.Y) * cubed)); + } + + /// + /// Performs a Catmull-Rom interpolation using the specified positions. + /// + /// The first position in the interpolation. + /// The second position in the interpolation. + /// The third position in the interpolation. + /// The fourth position in the interpolation. + /// Weighting factor. + /// A vector that is the result of the Catmull-Rom interpolation. + public static Vector2 CatmullRom(Vector2 value1, Vector2 value2, Vector2 value3, Vector2 value4, float amount) + { + Vector2 result; + CatmullRom(ref value1, ref value2, ref value3, ref value4, amount, out result); + return result; + } + + /// + /// Returns a vector containing the largest components of the specified vectors. + /// + /// The first source vector. + /// The second source vector. + /// When the method completes, contains an new vector composed of the largest components of the source vectors. + public static void Max(ref Vector2 left, ref Vector2 right, out Vector2 result) + { + result.X = (left.X > right.X) ? left.X : right.X; + result.Y = (left.Y > right.Y) ? left.Y : right.Y; + } + + /// + /// Returns a vector containing the largest components of the specified vectors. + /// + /// The first source vector. + /// The second source vector. + /// A vector containing the largest components of the source vectors. + public static Vector2 Max(Vector2 left, Vector2 right) + { + Vector2 result; + Max(ref left, ref right, out result); + return result; + } + + /// + /// Returns a vector containing the smallest components of the specified vectors. + /// + /// The first source vector. + /// The second source vector. + /// When the method completes, contains an new vector composed of the smallest components of the source vectors. + public static void Min(ref Vector2 left, ref Vector2 right, out Vector2 result) + { + result.X = (left.X < right.X) ? left.X : right.X; + result.Y = (left.Y < right.Y) ? left.Y : right.Y; + } + + /// + /// Returns a vector containing the smallest components of the specified vectors. + /// + /// The first source vector. + /// The second source vector. + /// A vector containing the smallest components of the source vectors. + public static Vector2 Min(Vector2 left, Vector2 right) + { + Vector2 result; + Min(ref left, ref right, out result); + return result; + } + + /// + /// Returns the reflection of a vector off a surface that has the specified normal. + /// + /// The source vector. + /// Normal of the surface. + /// When the method completes, contains the reflected vector. + /// Reflect only gives the direction of a reflection off a surface, it does not determine + /// whether the original vector was close enough to the surface to hit it. + public static void Reflect(ref Vector2 vector, ref Vector2 normal, out Vector2 result) + { + float dot = (vector.X * normal.X) + (vector.Y * normal.Y); + + result.X = vector.X - ((2.0f * dot) * normal.X); + result.Y = vector.Y - ((2.0f * dot) * normal.Y); + } + + /// + /// Returns the reflection of a vector off a surface that has the specified normal. + /// + /// The source vector. + /// Normal of the surface. + /// The reflected vector. + /// Reflect only gives the direction of a reflection off a surface, it does not determine + /// whether the original vector was close enough to the surface to hit it. + public static Vector2 Reflect(Vector2 vector, Vector2 normal) + { + Vector2 result; + Reflect(ref vector, ref normal, out result); + return result; + } + + /// + /// Orthogonalizes a list of vectors. + /// + /// The list of orthogonalized vectors. + /// The list of vectors to orthogonalize. + /// + /// Orthogonalization is the process of making all vectors orthogonal to each other. This + /// means that any given vector in the list will be orthogonal to any other given vector in the + /// list. + /// Because this method uses the modified Gram-Schmidt process, the resulting vectors + /// tend to be numerically unstable. The numeric stability decreases according to the vectors + /// position in the list so that the first vector is the most stable and the last vector is the + /// least stable. + /// + /// Thrown when or is null. + /// Thrown when is shorter in length than . + public static void Orthogonalize(Vector2[] destination, params Vector2[] source) + { + //Uses the modified Gram-Schmidt process. + //q1 = m1 + //q2 = m2 - ((q1 ⋅ m2) / (q1 ⋅ q1)) * q1 + //q3 = m3 - ((q1 ⋅ m3) / (q1 ⋅ q1)) * q1 - ((q2 ⋅ m3) / (q2 ⋅ q2)) * q2 + //q4 = m4 - ((q1 ⋅ m4) / (q1 ⋅ q1)) * q1 - ((q2 ⋅ m4) / (q2 ⋅ q2)) * q2 - ((q3 ⋅ m4) / (q3 ⋅ q3)) * q3 + //q5 = ... + + if (source == null) + throw new ArgumentNullException("source"); + if (destination == null) + throw new ArgumentNullException("destination"); + if (destination.Length < source.Length) + throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); + + for (int i = 0; i < source.Length; ++i) + { + Vector2 newvector = source[i]; + + for (int r = 0; r < i; ++r) + { + newvector -= (Vector2.Dot(destination[r], newvector) / Vector2.Dot(destination[r], destination[r])) * destination[r]; + } + + destination[i] = newvector; + } + } + + /// + /// Orthonormalizes a list of vectors. + /// + /// The list of orthonormalized vectors. + /// The list of vectors to orthonormalize. + /// + /// Orthonormalization is the process of making all vectors orthogonal to each + /// other and making all vectors of unit length. This means that any given vector will + /// be orthogonal to any other given vector in the list. + /// Because this method uses the modified Gram-Schmidt process, the resulting vectors + /// tend to be numerically unstable. The numeric stability decreases according to the vectors + /// position in the list so that the first vector is the most stable and the last vector is the + /// least stable. + /// + /// Thrown when or is null. + /// Thrown when is shorter in length than . + public static void Orthonormalize(Vector2[] destination, params Vector2[] source) + { + //Uses the modified Gram-Schmidt process. + //Because we are making unit vectors, we can optimize the math for orthogonalization + //and simplify the projection operation to remove the division. + //q1 = m1 / |m1| + //q2 = (m2 - (q1 ⋅ m2) * q1) / |m2 - (q1 ⋅ m2) * q1| + //q3 = (m3 - (q1 ⋅ m3) * q1 - (q2 ⋅ m3) * q2) / |m3 - (q1 ⋅ m3) * q1 - (q2 ⋅ m3) * q2| + //q4 = (m4 - (q1 ⋅ m4) * q1 - (q2 ⋅ m4) * q2 - (q3 ⋅ m4) * q3) / |m4 - (q1 ⋅ m4) * q1 - (q2 ⋅ m4) * q2 - (q3 ⋅ m4) * q3| + //q5 = ... + + if (source == null) + throw new ArgumentNullException("source"); + if (destination == null) + throw new ArgumentNullException("destination"); + if (destination.Length < source.Length) + throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); + + for (int i = 0; i < source.Length; ++i) + { + Vector2 newvector = source[i]; + + for (int r = 0; r < i; ++r) + { + newvector -= Vector2.Dot(destination[r], newvector) * destination[r]; + } + + newvector.Normalize(); + destination[i] = newvector; + } + } + + /// + /// Transforms a 2D vector by the given rotation. + /// + /// The vector to rotate. + /// The rotation to apply. + /// When the method completes, contains the transformed . + public static void Transform(ref Vector2 vector, ref Quaternion rotation, out Vector2 result) + { + float x = rotation.X + rotation.X; + float y = rotation.Y + rotation.Y; + float z = rotation.Z + rotation.Z; + float wz = rotation.W * z; + float xx = rotation.X * x; + float xy = rotation.X * y; + float yy = rotation.Y * y; + float zz = rotation.Z * z; + + result = new Vector2((vector.X * (1.0f - yy - zz)) + (vector.Y * (xy - wz)), (vector.X * (xy + wz)) + (vector.Y * (1.0f - xx - zz))); + } + + /// + /// Transforms a 2D vector by the given rotation. + /// + /// The vector to rotate. + /// The rotation to apply. + /// The transformed . + public static Vector2 Transform(Vector2 vector, Quaternion rotation) + { + Vector2 result; + Transform(ref vector, ref rotation, out result); + return result; + } + + /// + /// Transforms an array of vectors by the given rotation. + /// + /// The array of vectors to transform. + /// The rotation to apply. + /// The array for which the transformed vectors are stored. + /// This array may be the same array as . + /// Thrown when or is null. + /// Thrown when is shorter in length than . + public static void Transform(Vector2[] source, ref Quaternion rotation, Vector2[] destination) + { + if (source == null) + throw new ArgumentNullException("source"); + if (destination == null) + throw new ArgumentNullException("destination"); + if (destination.Length < source.Length) + throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); + + float x = rotation.X + rotation.X; + float y = rotation.Y + rotation.Y; + float z = rotation.Z + rotation.Z; + float wz = rotation.W * z; + float xx = rotation.X * x; + float xy = rotation.X * y; + float yy = rotation.Y * y; + float zz = rotation.Z * z; + + float num1 = (1.0f - yy - zz); + float num2 = (xy - wz); + float num3 = (xy + wz); + float num4 = (1.0f - xx - zz); + + for (int i = 0; i < source.Length; ++i) + { + destination[i] = new Vector2( + (source[i].X * num1) + (source[i].Y * num2), + (source[i].X * num3) + (source[i].Y * num4)); + } + } + + /// + /// Transforms a 2D vector by the given . + /// + /// The source vector. + /// The transformation . + /// When the method completes, contains the transformed . + public static void Transform(ref Vector2 vector, ref Matrix transform, out Vector4 result) + { + result = new Vector4( + (vector.X * transform.M11) + (vector.Y * transform.M21) + transform.M41, + (vector.X * transform.M12) + (vector.Y * transform.M22) + transform.M42, + (vector.X * transform.M13) + (vector.Y * transform.M23) + transform.M43, + (vector.X * transform.M14) + (vector.Y * transform.M24) + transform.M44); + } + + /// + /// Transforms a 2D vector by the given . + /// + /// The source vector. + /// The transformation . + /// The transformed . + public static Vector4 Transform(Vector2 vector, Matrix transform) + { + Vector4 result; + Transform(ref vector, ref transform, out result); + return result; + } + + /// + /// Transforms an array of 2D vectors by the given . + /// + /// The array of vectors to transform. + /// The transformation . + /// The array for which the transformed vectors are stored. + /// Thrown when or is null. + /// Thrown when is shorter in length than . + public static void Transform(Vector2[] source, ref Matrix transform, Vector4[] destination) + { + if (source == null) + throw new ArgumentNullException("source"); + if (destination == null) + throw new ArgumentNullException("destination"); + if (destination.Length < source.Length) + throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); + + for (int i = 0; i < source.Length; ++i) + { + Transform(ref source[i], ref transform, out destination[i]); + } + } + + /// + /// Performs a coordinate transformation using the given . + /// + /// The coordinate vector to transform. + /// The transformation . + /// When the method completes, contains the transformed coordinates. + /// + /// A coordinate transform performs the transformation with the assumption that the w component + /// is one. The four dimensional vector obtained from the transformation operation has each + /// component in the vector divided by the w component. This forces the w component to be one and + /// therefore makes the vector homogeneous. The homogeneous vector is often preferred when working + /// with coordinates as the w component can safely be ignored. + /// + public static void TransformCoordinate(ref Vector2 coordinate, ref Matrix transform, out Vector2 result) + { + Vector4 vector = new Vector4(); + vector.X = (coordinate.X * transform.M11) + (coordinate.Y * transform.M21) + transform.M41; + vector.Y = (coordinate.X * transform.M12) + (coordinate.Y * transform.M22) + transform.M42; + vector.Z = (coordinate.X * transform.M13) + (coordinate.Y * transform.M23) + transform.M43; + vector.W = 1f / ((coordinate.X * transform.M14) + (coordinate.Y * transform.M24) + transform.M44); + + result = new Vector2(vector.X * vector.W, vector.Y * vector.W); + } + + /// + /// Performs a coordinate transformation using the given . + /// + /// The coordinate vector to transform. + /// The transformation . + /// The transformed coordinates. + /// + /// A coordinate transform performs the transformation with the assumption that the w component + /// is one. The four dimensional vector obtained from the transformation operation has each + /// component in the vector divided by the w component. This forces the w component to be one and + /// therefore makes the vector homogeneous. The homogeneous vector is often preferred when working + /// with coordinates as the w component can safely be ignored. + /// + public static Vector2 TransformCoordinate(Vector2 coordinate, Matrix transform) + { + Vector2 result; + TransformCoordinate(ref coordinate, ref transform, out result); + return result; + } + + /// + /// Performs a coordinate transformation on an array of vectors using the given . + /// + /// The array of coordinate vectors to transform. + /// The transformation . + /// The array for which the transformed vectors are stored. + /// This array may be the same array as . + /// Thrown when or is null. + /// Thrown when is shorter in length than . + /// + /// A coordinate transform performs the transformation with the assumption that the w component + /// is one. The four dimensional vector obtained from the transformation operation has each + /// component in the vector divided by the w component. This forces the w component to be one and + /// therefore makes the vector homogeneous. The homogeneous vector is often preferred when working + /// with coordinates as the w component can safely be ignored. + /// + public static void TransformCoordinate(Vector2[] source, ref Matrix transform, Vector2[] destination) + { + if (source == null) + throw new ArgumentNullException("source"); + if (destination == null) + throw new ArgumentNullException("destination"); + if (destination.Length < source.Length) + throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); + + for (int i = 0; i < source.Length; ++i) + { + TransformCoordinate(ref source[i], ref transform, out destination[i]); + } + } + + /// + /// Performs a normal transformation using the given . + /// + /// The normal vector to transform. + /// The transformation . + /// When the method completes, contains the transformed normal. + /// + /// A normal transform performs the transformation with the assumption that the w component + /// is zero. This causes the fourth row and fourth column of the matrix to be unused. The + /// end result is a vector that is not translated, but all other transformation properties + /// apply. This is often preferred for normal vectors as normals purely represent direction + /// rather than location because normal vectors should not be translated. + /// + public static void TransformNormal(ref Vector2 normal, ref Matrix transform, out Vector2 result) + { + result = new Vector2( + (normal.X * transform.M11) + (normal.Y * transform.M21), + (normal.X * transform.M12) + (normal.Y * transform.M22)); + } + + /// + /// Performs a normal transformation using the given . + /// + /// The normal vector to transform. + /// The transformation . + /// The transformed normal. + /// + /// A normal transform performs the transformation with the assumption that the w component + /// is zero. This causes the fourth row and fourth column of the matrix to be unused. The + /// end result is a vector that is not translated, but all other transformation properties + /// apply. This is often preferred for normal vectors as normals purely represent direction + /// rather than location because normal vectors should not be translated. + /// + public static Vector2 TransformNormal(Vector2 normal, Matrix transform) + { + Vector2 result; + TransformNormal(ref normal, ref transform, out result); + return result; + } + + /// + /// Performs a normal transformation on an array of vectors using the given . + /// + /// The array of normal vectors to transform. + /// The transformation . + /// The array for which the transformed vectors are stored. + /// This array may be the same array as . + /// Thrown when or is null. + /// Thrown when is shorter in length than . + /// + /// A normal transform performs the transformation with the assumption that the w component + /// is zero. This causes the fourth row and fourth column of the matrix to be unused. The + /// end result is a vector that is not translated, but all other transformation properties + /// apply. This is often preferred for normal vectors as normals purely represent direction + /// rather than location because normal vectors should not be translated. + /// + public static void TransformNormal(Vector2[] source, ref Matrix transform, Vector2[] destination) + { + if (source == null) + throw new ArgumentNullException("source"); + if (destination == null) + throw new ArgumentNullException("destination"); + if (destination.Length < source.Length) + throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); + + for (int i = 0; i < source.Length; ++i) + { + TransformNormal(ref source[i], ref transform, out destination[i]); + } + } + + /// + /// Adds two vectors. + /// + /// The first vector to add. + /// The second vector to add. + /// The sum of the two vectors. + public static Vector2 operator +(Vector2 left, Vector2 right) + { + return new Vector2(left.X + right.X, left.Y + right.Y); + } + + /// + /// Multiplies a vector with another by performing component-wise multiplication equivalent to . + /// + /// The first vector to multiply. + /// The second vector to multiply. + /// The multiplication of the two vectors. + public static Vector2 operator *(Vector2 left, Vector2 right) + { + return new Vector2(left.X * right.X, left.Y * right.Y); + } + + /// + /// Assert a vector (return it unchanged). + /// + /// The vector to assert (unchanged). + /// The asserted (unchanged) vector. + public static Vector2 operator +(Vector2 value) + { + return value; + } + + /// + /// Subtracts two vectors. + /// + /// The first vector to subtract. + /// The second vector to subtract. + /// The difference of the two vectors. + public static Vector2 operator -(Vector2 left, Vector2 right) + { + return new Vector2(left.X - right.X, left.Y - right.Y); + } + + /// + /// Reverses the direction of a given vector. + /// + /// The vector to negate. + /// A vector facing in the opposite direction. + public static Vector2 operator -(Vector2 value) + { + return new Vector2(-value.X, -value.Y); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector2 operator *(float scale, Vector2 value) + { + return new Vector2(value.X * scale, value.Y * scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector2 operator *(Vector2 value, float scale) + { + return new Vector2(value.X * scale, value.Y * scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector2 operator /(Vector2 value, float scale) + { + return new Vector2(value.X / scale, value.Y / scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The amount by which to scale the vector. + /// The vector to scale. + /// The scaled vector. + public static Vector2 operator /(float scale , Vector2 value) + { + return new Vector2(scale / value.X, scale / value.Y); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector2 operator /(Vector2 value, Vector2 scale) + { + return new Vector2(value.X / scale.X, value.Y / scale.Y); + } + + /// + /// Perform a component-wise addition + /// + /// The input vector. + /// The scalar value to be added on elements + /// The vector with added scalar for each element. + public static Vector2 operator +(Vector2 value, float scalar) + { + return new Vector2(value.X + scalar, value.Y + scalar); + } + + /// + /// Perform a component-wise addition + /// + /// The input vector. + /// The scalar value to be added on elements + /// The vector with added scalar for each element. + public static Vector2 operator +(float scalar, Vector2 value) + { + return new Vector2(scalar + value.X, scalar + value.Y); + } + + /// + /// Perform a component-wise subtraction + /// + /// The input vector. + /// The scalar value to be subtraced from elements + /// The vector with subtraced scalar from each element. + public static Vector2 operator -(Vector2 value, float scalar) + { + return new Vector2(value.X - scalar, value.Y - scalar); + } + + /// + /// Perform a component-wise subtraction + /// + /// The input vector. + /// The scalar value to be subtraced from elements + /// The vector with subtraced scalar from each element. + public static Vector2 operator -(float scalar, Vector2 value) + { + return new Vector2(scalar - value.X, scalar - value.Y); + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has the same value as ; otherwise, false. + public static bool operator ==(Vector2 left, Vector2 right) + { + return left.Equals(ref right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has a different value than ; otherwise, false. + public static bool operator !=(Vector2 left, Vector2 right) + { + return !left.Equals(ref right); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Vector3(Vector2 value) + { + return new Vector3(value, 0.0f); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Vector4(Vector2 value) + { + return new Vector4(value, 0.0f, 0.0f); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1}", X, Y); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// + /// A that represents this instance. + /// + public string ToString(string format) + { + if (format == null) + return ToString(); + + return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1}", X.ToString(format, CultureInfo.CurrentCulture), Y.ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format(formatProvider, "X:{0} Y:{1}", X, Y); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(string format, IFormatProvider formatProvider) + { + if (format == null) + ToString(formatProvider); + + return string.Format(formatProvider, "X:{0} Y:{1}", X.ToString(format, formatProvider), Y.ToString(format, formatProvider)); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + unchecked + { + return (X.GetHashCode() * 397) ^ Y.GetHashCode(); + } + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(ref Vector2 other) + { + return MathUtil.NearEqual(other.X, X) && MathUtil.NearEqual(other.Y, Y); + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(Vector2 other) + { + return Equals(ref other); + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object value) + { + if (!(value is Vector2)) + return false; + + var strongValue = (Vector2)value; + return Equals(ref strongValue); + } + +#if WPFInterop + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator System.Windows.Point(Vector2 value) + { + return new System.Windows.Point(value.X, value.Y); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Vector2(System.Windows.Point value) + { + return new Vector2((float)value.X, (float)value.Y); + } +#endif + +#if XnaInterop + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Microsoft.Xna.Framework.Vector2(Vector2 value) + { + return new Microsoft.Xna.Framework.Vector2(value.X, value.Y); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Vector2(Microsoft.Xna.Framework.Vector2 value) + { + return new Vector2(value.X, value.Y); + } +#endif + } +} diff --git a/Source/SharpDX/Vector3.cs b/Source/SharpDX/Mathematics/Vector3.cs similarity index 97% rename from Source/SharpDX/Vector3.cs rename to Source/SharpDX/Mathematics/Vector3.cs index 4f194c096..9d0a2decc 100644 --- a/Source/SharpDX/Vector3.cs +++ b/Source/SharpDX/Mathematics/Vector3.cs @@ -1,1864 +1,1844 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ----------------------------------------------------------------------------- -// Original code from SlimMath project. http://code.google.com/p/slimmath/ -// Greetings to SlimDX Group. Original code published with the following license: -// ----------------------------------------------------------------------------- -/* -* Copyright (c) 2007-2011 SlimDX Group -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Represents a three dimensional mathematical vector. - /// - [StructLayout(LayoutKind.Sequential, Pack = 4)] - [DynamicSerializer("TKV3")] - public struct Vector3 : IEquatable, IFormattable, IDataSerializable - { - /// - /// The size of the type, in bytes. - /// - public static readonly int SizeInBytes = Marshal.SizeOf(typeof(Vector3)); - - /// - /// A with all of its components set to zero. - /// - public static readonly Vector3 Zero = new Vector3(); - - /// - /// The X unit (1, 0, 0). - /// - public static readonly Vector3 UnitX = new Vector3(1.0f, 0.0f, 0.0f); - - /// - /// The Y unit (0, 1, 0). - /// - public static readonly Vector3 UnitY = new Vector3(0.0f, 1.0f, 0.0f); - - /// - /// The Z unit (0, 0, 1). - /// - public static readonly Vector3 UnitZ = new Vector3(0.0f, 0.0f, 1.0f); - - /// - /// A with all of its components set to one. - /// - public static readonly Vector3 One = new Vector3(1.0f, 1.0f, 1.0f); - - /// - /// A unit designating up (0, 1, 0). - /// - public static readonly Vector3 Up = new Vector3(0.0f, 1.0f, 0.0f); - - /// - /// A unit designating down (0, -1, 0). - /// - public static readonly Vector3 Down = new Vector3(0.0f, -1.0f, 0.0f); - - /// - /// A unit designating left (-1, 0, 0). - /// - public static readonly Vector3 Left = new Vector3(-1.0f, 0.0f, 0.0f); - - /// - /// A unit designating right (1, 0, 0). - /// - public static readonly Vector3 Right = new Vector3(1.0f, 0.0f, 0.0f); - - /// - /// A unit designating forward in a right-handed coordinate system (0, 0, -1). - /// - public static readonly Vector3 ForwardRH = new Vector3(0.0f, 0.0f, -1.0f); - - /// - /// A unit designating forward in a left-handed coordinate system (0, 0, 1). - /// - public static readonly Vector3 ForwardLH = new Vector3(0.0f, 0.0f, 1.0f); - - /// - /// A unit designating backward in a right-handed coordinate system (0, 0, 1). - /// - public static readonly Vector3 BackwardRH = new Vector3(0.0f, 0.0f, 1.0f); - - /// - /// A unit designating backward in a left-handed coordinate system (0, 0, -1). - /// - public static readonly Vector3 BackwardLH = new Vector3(0.0f, 0.0f, -1.0f); - - /// - /// The X component of the vector. - /// - public float X; - - /// - /// The Y component of the vector. - /// - public float Y; - - /// - /// The Z component of the vector. - /// - public float Z; - - /// - /// Initializes a new instance of the struct. - /// - /// The value that will be assigned to all components. - public Vector3(float value) - { - X = value; - Y = value; - Z = value; - } - - /// - /// Initializes a new instance of the struct. - /// - /// Initial value for the X component of the vector. - /// Initial value for the Y component of the vector. - /// Initial value for the Z component of the vector. - public Vector3(float x, float y, float z) - { - X = x; - Y = y; - Z = z; - } - - /// - /// Initializes a new instance of the struct. - /// - /// A vector containing the values with which to initialize the X and Y components. - /// Initial value for the Z component of the vector. - public Vector3(Vector2 value, float z) - { - X = value.X; - Y = value.Y; - Z = z; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The values to assign to the X, Y, and Z components of the vector. This must be an array with three elements. - /// Thrown when is null. - /// Thrown when contains more or less than three elements. - public Vector3(float[] values) - { - if (values == null) - throw new ArgumentNullException("values"); - if (values.Length != 3) - throw new ArgumentOutOfRangeException("values", "There must be three and only three input values for Vector3."); - - X = values[0]; - Y = values[1]; - Z = values[2]; - } - - /// - /// Gets a value indicting whether this instance is normalized. - /// - public bool IsNormalized - { - get { return MathUtil.IsOne((X * X) + (Y * Y) + (Z * Z)); } - } - - /// - /// Gets a value indicting whether this vector is zero - /// - public bool IsZero - { - get { return X == 0 && Y == 0 && Z == 0; } - } - - /// - /// Gets or sets the component at the specified index. - /// - /// The value of the X, Y, or Z component, depending on the index. - /// The index of the component to access. Use 0 for the X component, 1 for the Y component, and 2 for the Z component. - /// The value of the component at the specified index. - /// Thrown when the is out of the range [0, 2]. - public float this[int index] - { - get - { - switch (index) - { - case 0: return X; - case 1: return Y; - case 2: return Z; - } - - throw new ArgumentOutOfRangeException("index", "Indices for Vector3 run from 0 to 2, inclusive."); - } - - set - { - switch (index) - { - case 0: X = value; break; - case 1: Y = value; break; - case 2: Z = value; break; - default: throw new ArgumentOutOfRangeException("index", "Indices for Vector3 run from 0 to 2, inclusive."); - } - } - } - - /// - /// Calculates the length of the vector. - /// - /// The length of the vector. - /// - /// may be preferred when only the relative length is needed - /// and speed is of the essence. - /// - public float Length() - { - return (float)Math.Sqrt((X * X) + (Y * Y) + (Z * Z)); - } - - /// - /// Calculates the squared length of the vector. - /// - /// The squared length of the vector. - /// - /// This method may be preferred to when only a relative length is needed - /// and speed is of the essence. - /// - public float LengthSquared() - { - return (X * X) + (Y * Y) + (Z * Z); - } - - /// - /// Converts the vector into a unit vector. - /// - public void Normalize() - { - float length = Length(); - if (!MathUtil.IsZero(length)) - { - float inv = 1.0f / length; - X *= inv; - Y *= inv; - Z *= inv; - } - } - - /// - /// Creates an array containing the elements of the vector. - /// - /// A three-element array containing the components of the vector. - public float[] ToArray() - { - return new float[] { X, Y, Z }; - } - - /// - /// Adds two vectors. - /// - /// The first vector to add. - /// The second vector to add. - /// When the method completes, contains the sum of the two vectors. - public static void Add(ref Vector3 left, ref Vector3 right, out Vector3 result) - { - result = new Vector3(left.X + right.X, left.Y + right.Y, left.Z + right.Z); - } - - /// - /// Adds two vectors. - /// - /// The first vector to add. - /// The second vector to add. - /// The sum of the two vectors. - public static Vector3 Add(Vector3 left, Vector3 right) - { - return new Vector3(left.X + right.X, left.Y + right.Y, left.Z + right.Z); - } - - /// - /// Perform a component-wise addition - /// - /// The input vector - /// The scalar value to be added to elements - /// The vector with added scalar for each element. - public static void Add(ref Vector3 left, ref float right, out Vector3 result) - { - result = new Vector3(left.X + right, left.Y + right, left.Z + right); - } - - /// - /// Perform a component-wise addition - /// - /// The input vector - /// The scalar value to be added to elements - /// The vector with added scalar for each element. - public static Vector3 Add(Vector3 left, float right) - { - return new Vector3(left.X + right, left.Y + right, left.Z + right); - } - - /// - /// Subtracts two vectors. - /// - /// The first vector to subtract. - /// The second vector to subtract. - /// When the method completes, contains the difference of the two vectors. - public static void Subtract(ref Vector3 left, ref Vector3 right, out Vector3 result) - { - result = new Vector3(left.X - right.X, left.Y - right.Y, left.Z - right.Z); - } - - /// - /// Subtracts two vectors. - /// - /// The first vector to subtract. - /// The second vector to subtract. - /// The difference of the two vectors. - public static Vector3 Subtract(Vector3 left, Vector3 right) - { - return new Vector3(left.X - right.X, left.Y - right.Y, left.Z - right.Z); - } - - /// - /// Perform a component-wise subtraction - /// - /// The input vector - /// The scalar value to be subtraced from elements - /// The vector with subtracted scalar for each element. - public static void Subtract(ref Vector3 left, ref float right, out Vector3 result) - { - result = new Vector3(left.X - right, left.Y - right, left.Z - right); - } - - /// - /// Perform a component-wise subtraction - /// - /// The input vector - /// The scalar value to be subtraced from elements - /// The vector with subtracted scalar for each element. - public static Vector3 Subtract(Vector3 left, float right) - { - return new Vector3(left.X - right, left.Y - right, left.Z - right); - } - - /// - /// Perform a component-wise subtraction - /// - /// The scalar value to be subtraced from elements - /// The input vector. - /// The vector with subtracted scalar for each element. - public static void Subtract(ref float left, ref Vector3 right, out Vector3 result) - { - result = new Vector3(left - right.X, left - right.Y, left - right.Z); - } - - /// - /// Perform a component-wise subtraction - /// - /// The scalar value to be subtraced from elements - /// The input vector. - /// The vector with subtracted scalar for each element. - public static Vector3 Subtract(float left, Vector3 right) - { - return new Vector3(left - right.X, left - right.Y, left - right.Z); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// When the method completes, contains the scaled vector. - public static void Multiply(ref Vector3 value, float scale, out Vector3 result) - { - result = new Vector3(value.X * scale, value.Y * scale, value.Z * scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector3 Multiply(Vector3 value, float scale) - { - return new Vector3(value.X * scale, value.Y * scale, value.Z * scale); - } - - /// - /// Multiply a vector with another by performing component-wise multiplication. - /// - /// The first vector to multiply. - /// The second vector to multiply. - /// When the method completes, contains the multiplied vector. - public static void Multiply(ref Vector3 left, ref Vector3 right, out Vector3 result) - { - result = new Vector3(left.X * right.X, left.Y * right.Y, left.Z * right.Z); - } - - /// - /// Multiply a vector with another by performing component-wise multiplication. - /// - /// The first vector to Multiply. - /// The second vector to multiply. - /// The multiplied vector. - public static Vector3 Multiply(Vector3 left, Vector3 right) - { - return new Vector3(left.X * right.X, left.Y * right.Y, left.Z * right.Z); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// When the method completes, contains the scaled vector. - public static void Divide(ref Vector3 value, float scale, out Vector3 result) - { - result = new Vector3(value.X / scale, value.Y / scale, value.Z / scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector3 Divide(Vector3 value, float scale) - { - return new Vector3(value.X / scale, value.Y / scale, value.Z / scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The amount by which to scale the vector. - /// The vector to scale. - /// When the method completes, contains the scaled vector. - public static void Divide(float scale, ref Vector3 value, out Vector3 result) - { - result = new Vector3(scale / value.X, scale / value.Y, scale / value.Z); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector3 Divide(float scale, Vector3 value) - { - return new Vector3(scale / value.X, scale / value.Y, scale / value.Z); - } - - /// - /// Reverses the direction of a given vector. - /// - /// The vector to negate. - /// When the method completes, contains a vector facing in the opposite direction. - public static void Negate(ref Vector3 value, out Vector3 result) - { - result = new Vector3(-value.X, -value.Y, -value.Z); - } - - /// - /// Reverses the direction of a given vector. - /// - /// The vector to negate. - /// A vector facing in the opposite direction. - public static Vector3 Negate(Vector3 value) - { - return new Vector3(-value.X, -value.Y, -value.Z); - } - - /// - /// Returns a containing the 3D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 3D triangle. - /// - /// A containing the 3D Cartesian coordinates of vertex 1 of the triangle. - /// A containing the 3D Cartesian coordinates of vertex 2 of the triangle. - /// A containing the 3D Cartesian coordinates of vertex 3 of the triangle. - /// Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). - /// Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). - /// When the method completes, contains the 3D Cartesian coordinates of the specified point. - public static void Barycentric(ref Vector3 value1, ref Vector3 value2, ref Vector3 value3, float amount1, float amount2, out Vector3 result) - { - result = new Vector3((value1.X + (amount1 * (value2.X - value1.X))) + (amount2 * (value3.X - value1.X)), - (value1.Y + (amount1 * (value2.Y - value1.Y))) + (amount2 * (value3.Y - value1.Y)), - (value1.Z + (amount1 * (value2.Z - value1.Z))) + (amount2 * (value3.Z - value1.Z))); - } - - /// - /// Returns a containing the 3D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 3D triangle. - /// - /// A containing the 3D Cartesian coordinates of vertex 1 of the triangle. - /// A containing the 3D Cartesian coordinates of vertex 2 of the triangle. - /// A containing the 3D Cartesian coordinates of vertex 3 of the triangle. - /// Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). - /// Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). - /// A new containing the 3D Cartesian coordinates of the specified point. - public static Vector3 Barycentric(Vector3 value1, Vector3 value2, Vector3 value3, float amount1, float amount2) - { - Vector3 result; - Barycentric(ref value1, ref value2, ref value3, amount1, amount2, out result); - return result; - } - - /// - /// Restricts a value to be within a specified range. - /// - /// The value to clamp. - /// The minimum value. - /// The maximum value. - /// When the method completes, contains the clamped value. - public static void Clamp(ref Vector3 value, ref Vector3 min, ref Vector3 max, out Vector3 result) - { - float x = value.X; - x = (x > max.X) ? max.X : x; - x = (x < min.X) ? min.X : x; - - float y = value.Y; - y = (y > max.Y) ? max.Y : y; - y = (y < min.Y) ? min.Y : y; - - float z = value.Z; - z = (z > max.Z) ? max.Z : z; - z = (z < min.Z) ? min.Z : z; - - result = new Vector3(x, y, z); - } - - /// - /// Restricts a value to be within a specified range. - /// - /// The value to clamp. - /// The minimum value. - /// The maximum value. - /// The clamped value. - public static Vector3 Clamp(Vector3 value, Vector3 min, Vector3 max) - { - Vector3 result; - Clamp(ref value, ref min, ref max, out result); - return result; - } - - /// - /// Calculates the cross product of two vectors. - /// - /// First source vector. - /// Second source vector. - /// When the method completes, contains he cross product of the two vectors. - public static void Cross(ref Vector3 left, ref Vector3 right, out Vector3 result) - { - result = new Vector3( - (left.Y * right.Z) - (left.Z * right.Y), - (left.Z * right.X) - (left.X * right.Z), - (left.X * right.Y) - (left.Y * right.X)); - } - - /// - /// Calculates the cross product of two vectors. - /// - /// First source vector. - /// Second source vector. - /// The cross product of the two vectors. - public static Vector3 Cross(Vector3 left, Vector3 right) - { - Vector3 result; - Cross(ref left, ref right, out result); - return result; - } - - /// - /// Calculates the distance between two vectors. - /// - /// The first vector. - /// The second vector. - /// When the method completes, contains the distance between the two vectors. - /// - /// may be preferred when only the relative distance is needed - /// and speed is of the essence. - /// - public static void Distance(ref Vector3 value1, ref Vector3 value2, out float result) - { - float x = value1.X - value2.X; - float y = value1.Y - value2.Y; - float z = value1.Z - value2.Z; - - result = (float)Math.Sqrt((x * x) + (y * y) + (z * z)); - } - - /// - /// Calculates the distance between two vectors. - /// - /// The first vector. - /// The second vector. - /// The distance between the two vectors. - /// - /// may be preferred when only the relative distance is needed - /// and speed is of the essence. - /// - public static float Distance(Vector3 value1, Vector3 value2) - { - float x = value1.X - value2.X; - float y = value1.Y - value2.Y; - float z = value1.Z - value2.Z; - - return (float)Math.Sqrt((x * x) + (y * y) + (z * z)); - } - - /// - /// Calculates the squared distance between two vectors. - /// - /// The first vector. - /// The second vector. - /// When the method completes, contains the squared distance between the two vectors. - /// Distance squared is the value before taking the square root. - /// Distance squared can often be used in place of distance if relative comparisons are being made. - /// For example, consider three points A, B, and C. To determine whether B or C is further from A, - /// compare the distance between A and B to the distance between A and C. Calculating the two distances - /// involves two square roots, which are computationally expensive. However, using distance squared - /// provides the same information and avoids calculating two square roots. - /// - public static void DistanceSquared(ref Vector3 value1, ref Vector3 value2, out float result) - { - float x = value1.X - value2.X; - float y = value1.Y - value2.Y; - float z = value1.Z - value2.Z; - - result = (x * x) + (y * y) + (z * z); - } - - /// - /// Calculates the squared distance between two vectors. - /// - /// The first vector. - /// The second vector. - /// The squared distance between the two vectors. - /// Distance squared is the value before taking the square root. - /// Distance squared can often be used in place of distance if relative comparisons are being made. - /// For example, consider three points A, B, and C. To determine whether B or C is further from A, - /// compare the distance between A and B to the distance between A and C. Calculating the two distances - /// involves two square roots, which are computationally expensive. However, using distance squared - /// provides the same information and avoids calculating two square roots. - /// - public static float DistanceSquared(Vector3 value1, Vector3 value2) - { - float x = value1.X - value2.X; - float y = value1.Y - value2.Y; - float z = value1.Z - value2.Z; - - return (x * x) + (y * y) + (z * z); - } - - /// - /// Tests whether one 3D vector is near another 3D vector. - /// - /// The left vector. - /// The right vector. - /// The epsilon. - /// true if left and right are near another 3D, false otherwise - public static bool NearEqual(Vector3 left, Vector3 right, Vector3 epsilon) - { - return NearEqual(ref left, ref right, ref epsilon); - } - - /// - /// Tests whether one 3D vector is near another 3D vector. - /// - /// The left vector. - /// The right vector. - /// The epsilon. - /// true if left and right are near another 3D, false otherwise - public static bool NearEqual(ref Vector3 left, ref Vector3 right, ref Vector3 epsilon) - { - return MathUtil.WithinEpsilon(left.X, right.X, epsilon.X) && - MathUtil.WithinEpsilon(left.Y, right.Y, epsilon.Y) && - MathUtil.WithinEpsilon(left.Z, right.Z, epsilon.Z); - } - - /// - /// Calculates the dot product of two vectors. - /// - /// First source vector. - /// Second source vector. - /// When the method completes, contains the dot product of the two vectors. - public static void Dot(ref Vector3 left, ref Vector3 right, out float result) - { - result = (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z); - } - - /// - /// Calculates the dot product of two vectors. - /// - /// First source vector. - /// Second source vector. - /// The dot product of the two vectors. - public static float Dot(Vector3 left, Vector3 right) - { - return (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z); - } - - /// - /// Converts the vector into a unit vector. - /// - /// The vector to normalize. - /// When the method completes, contains the normalized vector. - public static void Normalize(ref Vector3 value, out Vector3 result) - { - result = value; - result.Normalize(); - } - - /// - /// Converts the vector into a unit vector. - /// - /// The vector to normalize. - /// The normalized vector. - public static Vector3 Normalize(Vector3 value) - { - value.Normalize(); - return value; - } - - /// - /// Performs a linear interpolation between two vectors. - /// - /// Start vector. - /// End vector. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the linear interpolation of the two vectors. - /// - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static void Lerp(ref Vector3 start, ref Vector3 end, float amount, out Vector3 result) - { - result.X = MathUtil.Lerp(start.X, end.X, amount); - result.Y = MathUtil.Lerp(start.Y, end.Y, amount); - result.Z = MathUtil.Lerp(start.Z, end.Z, amount); - } - - /// - /// Performs a linear interpolation between two vectors. - /// - /// Start vector. - /// End vector. - /// Value between 0 and 1 indicating the weight of . - /// The linear interpolation of the two vectors. - /// - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static Vector3 Lerp(Vector3 start, Vector3 end, float amount) - { - Vector3 result; - Lerp(ref start, ref end, amount, out result); - return result; - } - - /// - /// Performs a cubic interpolation between two vectors. - /// - /// Start vector. - /// End vector. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the cubic interpolation of the two vectors. - public static void SmoothStep(ref Vector3 start, ref Vector3 end, float amount, out Vector3 result) - { - amount = MathUtil.SmoothStep(amount); - Lerp(ref start, ref end, amount, out result); - } - - /// - /// Performs a cubic interpolation between two vectors. - /// - /// Start vector. - /// End vector. - /// Value between 0 and 1 indicating the weight of . - /// The cubic interpolation of the two vectors. - public static Vector3 SmoothStep(Vector3 start, Vector3 end, float amount) - { - Vector3 result; - SmoothStep(ref start, ref end, amount, out result); - return result; - } - - /// - /// Performs a Hermite spline interpolation. - /// - /// First source position vector. - /// First source tangent vector. - /// Second source position vector. - /// Second source tangent vector. - /// Weighting factor. - /// When the method completes, contains the result of the Hermite spline interpolation. - public static void Hermite(ref Vector3 value1, ref Vector3 tangent1, ref Vector3 value2, ref Vector3 tangent2, float amount, out Vector3 result) - { - float squared = amount * amount; - float cubed = amount * squared; - float part1 = ((2.0f * cubed) - (3.0f * squared)) + 1.0f; - float part2 = (-2.0f * cubed) + (3.0f * squared); - float part3 = (cubed - (2.0f * squared)) + amount; - float part4 = cubed - squared; - - result.X = (((value1.X * part1) + (value2.X * part2)) + (tangent1.X * part3)) + (tangent2.X * part4); - result.Y = (((value1.Y * part1) + (value2.Y * part2)) + (tangent1.Y * part3)) + (tangent2.Y * part4); - result.Z = (((value1.Z * part1) + (value2.Z * part2)) + (tangent1.Z * part3)) + (tangent2.Z * part4); - } - - /// - /// Performs a Hermite spline interpolation. - /// - /// First source position vector. - /// First source tangent vector. - /// Second source position vector. - /// Second source tangent vector. - /// Weighting factor. - /// The result of the Hermite spline interpolation. - public static Vector3 Hermite(Vector3 value1, Vector3 tangent1, Vector3 value2, Vector3 tangent2, float amount) - { - Vector3 result; - Hermite(ref value1, ref tangent1, ref value2, ref tangent2, amount, out result); - return result; - } - - /// - /// Performs a Catmull-Rom interpolation using the specified positions. - /// - /// The first position in the interpolation. - /// The second position in the interpolation. - /// The third position in the interpolation. - /// The fourth position in the interpolation. - /// Weighting factor. - /// When the method completes, contains the result of the Catmull-Rom interpolation. - public static void CatmullRom(ref Vector3 value1, ref Vector3 value2, ref Vector3 value3, ref Vector3 value4, float amount, out Vector3 result) - { - float squared = amount * amount; - float cubed = amount * squared; - - result.X = 0.5f * ((((2.0f * value2.X) + ((-value1.X + value3.X) * amount)) + - (((((2.0f * value1.X) - (5.0f * value2.X)) + (4.0f * value3.X)) - value4.X) * squared)) + - ((((-value1.X + (3.0f * value2.X)) - (3.0f * value3.X)) + value4.X) * cubed)); - - result.Y = 0.5f * ((((2.0f * value2.Y) + ((-value1.Y + value3.Y) * amount)) + - (((((2.0f * value1.Y) - (5.0f * value2.Y)) + (4.0f * value3.Y)) - value4.Y) * squared)) + - ((((-value1.Y + (3.0f * value2.Y)) - (3.0f * value3.Y)) + value4.Y) * cubed)); - - result.Z = 0.5f * ((((2.0f * value2.Z) + ((-value1.Z + value3.Z) * amount)) + - (((((2.0f * value1.Z) - (5.0f * value2.Z)) + (4.0f * value3.Z)) - value4.Z) * squared)) + - ((((-value1.Z + (3.0f * value2.Z)) - (3.0f * value3.Z)) + value4.Z) * cubed)); - } - - /// - /// Performs a Catmull-Rom interpolation using the specified positions. - /// - /// The first position in the interpolation. - /// The second position in the interpolation. - /// The third position in the interpolation. - /// The fourth position in the interpolation. - /// Weighting factor. - /// A vector that is the result of the Catmull-Rom interpolation. - public static Vector3 CatmullRom(Vector3 value1, Vector3 value2, Vector3 value3, Vector3 value4, float amount) - { - Vector3 result; - CatmullRom(ref value1, ref value2, ref value3, ref value4, amount, out result); - return result; - } - - /// - /// Returns a vector containing the largest components of the specified vectors. - /// - /// The first source vector. - /// The second source vector. - /// When the method completes, contains an new vector composed of the largest components of the source vectors. - public static void Max(ref Vector3 left, ref Vector3 right, out Vector3 result) - { - result.X = (left.X > right.X) ? left.X : right.X; - result.Y = (left.Y > right.Y) ? left.Y : right.Y; - result.Z = (left.Z > right.Z) ? left.Z : right.Z; - } - - /// - /// Returns a vector containing the largest components of the specified vectors. - /// - /// The first source vector. - /// The second source vector. - /// A vector containing the largest components of the source vectors. - public static Vector3 Max(Vector3 left, Vector3 right) - { - Vector3 result; - Max(ref left, ref right, out result); - return result; - } - - /// - /// Returns a vector containing the smallest components of the specified vectors. - /// - /// The first source vector. - /// The second source vector. - /// When the method completes, contains an new vector composed of the smallest components of the source vectors. - public static void Min(ref Vector3 left, ref Vector3 right, out Vector3 result) - { - result.X = (left.X < right.X) ? left.X : right.X; - result.Y = (left.Y < right.Y) ? left.Y : right.Y; - result.Z = (left.Z < right.Z) ? left.Z : right.Z; - } - - /// - /// Returns a vector containing the smallest components of the specified vectors. - /// - /// The first source vector. - /// The second source vector. - /// A vector containing the smallest components of the source vectors. - public static Vector3 Min(Vector3 left, Vector3 right) - { - Vector3 result; - Min(ref left, ref right, out result); - return result; - } - - /// - /// Projects a 3D vector from object space into screen space. - /// - /// The vector to project. - /// The X position of the viewport. - /// The Y position of the viewport. - /// The width of the viewport. - /// The height of the viewport. - /// The minimum depth of the viewport. - /// The maximum depth of the viewport. - /// The combined world-view-projection matrix. - /// When the method completes, contains the vector in screen space. - public static void Project(ref Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, ref Matrix worldViewProjection, out Vector3 result) - { - Vector3 v = new Vector3(); - TransformCoordinate(ref vector, ref worldViewProjection, out v); - - result = new Vector3(((1.0f + v.X) * 0.5f * width) + x, ((1.0f - v.Y) * 0.5f * height) + y, (v.Z * (maxZ - minZ)) + minZ); - } - - /// - /// Projects a 3D vector from object space into screen space. - /// - /// The vector to project. - /// The X position of the viewport. - /// The Y position of the viewport. - /// The width of the viewport. - /// The height of the viewport. - /// The minimum depth of the viewport. - /// The maximum depth of the viewport. - /// The combined world-view-projection matrix. - /// The vector in screen space. - public static Vector3 Project(Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, Matrix worldViewProjection) - { - Vector3 result; - Project(ref vector, x, y, width, height, minZ, maxZ, ref worldViewProjection, out result); - return result; - } - - /// - /// Projects a 3D vector from screen space into object space. - /// - /// The vector to project. - /// The X position of the viewport. - /// The Y position of the viewport. - /// The width of the viewport. - /// The height of the viewport. - /// The minimum depth of the viewport. - /// The maximum depth of the viewport. - /// The combined world-view-projection matrix. - /// When the method completes, contains the vector in object space. - public static void Unproject(ref Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, ref Matrix worldViewProjection, out Vector3 result) - { - Vector3 v = new Vector3(); - Matrix matrix = new Matrix(); - Matrix.Invert(ref worldViewProjection, out matrix); - - v.X = (((vector.X - x) / width) * 2.0f) - 1.0f; - v.Y = -((((vector.Y - y) / height) * 2.0f) - 1.0f); - v.Z = (vector.Z - minZ) / (maxZ - minZ); - - TransformCoordinate(ref v, ref matrix, out result); - } - - /// - /// Projects a 3D vector from screen space into object space. - /// - /// The vector to project. - /// The X position of the viewport. - /// The Y position of the viewport. - /// The width of the viewport. - /// The height of the viewport. - /// The minimum depth of the viewport. - /// The maximum depth of the viewport. - /// The combined world-view-projection matrix. - /// The vector in object space. - public static Vector3 Unproject(Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, Matrix worldViewProjection) - { - Vector3 result; - Unproject(ref vector, x, y, width, height, minZ, maxZ, ref worldViewProjection, out result); - return result; - } - - /// - /// Returns the reflection of a vector off a surface that has the specified normal. - /// - /// The source vector. - /// Normal of the surface. - /// When the method completes, contains the reflected vector. - /// Reflect only gives the direction of a reflection off a surface, it does not determine - /// whether the original vector was close enough to the surface to hit it. - public static void Reflect(ref Vector3 vector, ref Vector3 normal, out Vector3 result) - { - float dot = (vector.X * normal.X) + (vector.Y * normal.Y) + (vector.Z * normal.Z); - - result.X = vector.X - ((2.0f * dot) * normal.X); - result.Y = vector.Y - ((2.0f * dot) * normal.Y); - result.Z = vector.Z - ((2.0f * dot) * normal.Z); - } - - /// - /// Returns the reflection of a vector off a surface that has the specified normal. - /// - /// The source vector. - /// Normal of the surface. - /// The reflected vector. - /// Reflect only gives the direction of a reflection off a surface, it does not determine - /// whether the original vector was close enough to the surface to hit it. - public static Vector3 Reflect(Vector3 vector, Vector3 normal) - { - Vector3 result; - Reflect(ref vector, ref normal, out result); - return result; - } - - /// - /// Orthogonalizes a list of vectors. - /// - /// The list of orthogonalized vectors. - /// The list of vectors to orthogonalize. - /// - /// Orthogonalization is the process of making all vectors orthogonal to each other. This - /// means that any given vector in the list will be orthogonal to any other given vector in the - /// list. - /// Because this method uses the modified Gram-Schmidt process, the resulting vectors - /// tend to be numerically unstable. The numeric stability decreases according to the vectors - /// position in the list so that the first vector is the most stable and the last vector is the - /// least stable. - /// - /// Thrown when or is null. - /// Thrown when is shorter in length than . - public static void Orthogonalize(Vector3[] destination, params Vector3[] source) - { - //Uses the modified Gram-Schmidt process. - //q1 = m1 - //q2 = m2 - ((q1 ⋅ m2) / (q1 ⋅ q1)) * q1 - //q3 = m3 - ((q1 ⋅ m3) / (q1 ⋅ q1)) * q1 - ((q2 ⋅ m3) / (q2 ⋅ q2)) * q2 - //q4 = m4 - ((q1 ⋅ m4) / (q1 ⋅ q1)) * q1 - ((q2 ⋅ m4) / (q2 ⋅ q2)) * q2 - ((q3 ⋅ m4) / (q3 ⋅ q3)) * q3 - //q5 = ... - - if (source == null) - throw new ArgumentNullException("source"); - if (destination == null) - throw new ArgumentNullException("destination"); - if (destination.Length < source.Length) - throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); - - for (int i = 0; i < source.Length; ++i) - { - Vector3 newvector = source[i]; - - for (int r = 0; r < i; ++r) - { - newvector -= (Vector3.Dot(destination[r], newvector) / Vector3.Dot(destination[r], destination[r])) * destination[r]; - } - - destination[i] = newvector; - } - } - - /// - /// Orthonormalizes a list of vectors. - /// - /// The list of orthonormalized vectors. - /// The list of vectors to orthonormalize. - /// - /// Orthonormalization is the process of making all vectors orthogonal to each - /// other and making all vectors of unit length. This means that any given vector will - /// be orthogonal to any other given vector in the list. - /// Because this method uses the modified Gram-Schmidt process, the resulting vectors - /// tend to be numerically unstable. The numeric stability decreases according to the vectors - /// position in the list so that the first vector is the most stable and the last vector is the - /// least stable. - /// - /// Thrown when or is null. - /// Thrown when is shorter in length than . - public static void Orthonormalize(Vector3[] destination, params Vector3[] source) - { - //Uses the modified Gram-Schmidt process. - //Because we are making unit vectors, we can optimize the math for orthogonalization - //and simplify the projection operation to remove the division. - //q1 = m1 / |m1| - //q2 = (m2 - (q1 ⋅ m2) * q1) / |m2 - (q1 ⋅ m2) * q1| - //q3 = (m3 - (q1 ⋅ m3) * q1 - (q2 ⋅ m3) * q2) / |m3 - (q1 ⋅ m3) * q1 - (q2 ⋅ m3) * q2| - //q4 = (m4 - (q1 ⋅ m4) * q1 - (q2 ⋅ m4) * q2 - (q3 ⋅ m4) * q3) / |m4 - (q1 ⋅ m4) * q1 - (q2 ⋅ m4) * q2 - (q3 ⋅ m4) * q3| - //q5 = ... - - if (source == null) - throw new ArgumentNullException("source"); - if (destination == null) - throw new ArgumentNullException("destination"); - if (destination.Length < source.Length) - throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); - - for (int i = 0; i < source.Length; ++i) - { - Vector3 newvector = source[i]; - - for (int r = 0; r < i; ++r) - { - newvector -= Vector3.Dot(destination[r], newvector) * destination[r]; - } - - newvector.Normalize(); - destination[i] = newvector; - } - } - - /// - /// Transforms a 3D vector by the given rotation. - /// - /// The vector to rotate. - /// The rotation to apply. - /// When the method completes, contains the transformed . - public static void Transform(ref Vector3 vector, ref Quaternion rotation, out Vector3 result) - { - float x = rotation.X + rotation.X; - float y = rotation.Y + rotation.Y; - float z = rotation.Z + rotation.Z; - float wx = rotation.W * x; - float wy = rotation.W * y; - float wz = rotation.W * z; - float xx = rotation.X * x; - float xy = rotation.X * y; - float xz = rotation.X * z; - float yy = rotation.Y * y; - float yz = rotation.Y * z; - float zz = rotation.Z * z; - - result = new Vector3( - ((vector.X * ((1.0f - yy) - zz)) + (vector.Y * (xy - wz))) + (vector.Z * (xz + wy)), - ((vector.X * (xy + wz)) + (vector.Y * ((1.0f - xx) - zz))) + (vector.Z * (yz - wx)), - ((vector.X * (xz - wy)) + (vector.Y * (yz + wx))) + (vector.Z * ((1.0f - xx) - yy))); - } - - /// - /// Transforms a 3D vector by the given rotation. - /// - /// The vector to rotate. - /// The rotation to apply. - /// The transformed . - public static Vector3 Transform(Vector3 vector, Quaternion rotation) - { - Vector3 result; - Transform(ref vector, ref rotation, out result); - return result; - } - - /// - /// Transforms an array of vectors by the given rotation. - /// - /// The array of vectors to transform. - /// The rotation to apply. - /// The array for which the transformed vectors are stored. - /// This array may be the same array as . - /// Thrown when or is null. - /// Thrown when is shorter in length than . - public static void Transform(Vector3[] source, ref Quaternion rotation, Vector3[] destination) - { - if (source == null) - throw new ArgumentNullException("source"); - if (destination == null) - throw new ArgumentNullException("destination"); - if (destination.Length < source.Length) - throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); - - float x = rotation.X + rotation.X; - float y = rotation.Y + rotation.Y; - float z = rotation.Z + rotation.Z; - float wx = rotation.W * x; - float wy = rotation.W * y; - float wz = rotation.W * z; - float xx = rotation.X * x; - float xy = rotation.X * y; - float xz = rotation.X * z; - float yy = rotation.Y * y; - float yz = rotation.Y * z; - float zz = rotation.Z * z; - - float num1 = ((1.0f - yy) - zz); - float num2 = (xy - wz); - float num3 = (xz + wy); - float num4 = (xy + wz); - float num5 = ((1.0f - xx) - zz); - float num6 = (yz - wx); - float num7 = (xz - wy); - float num8 = (yz + wx); - float num9 = ((1.0f - xx) - yy); - - for (int i = 0; i < source.Length; ++i) - { - destination[i] = new Vector3( - ((source[i].X * num1) + (source[i].Y * num2)) + (source[i].Z * num3), - ((source[i].X * num4) + (source[i].Y * num5)) + (source[i].Z * num6), - ((source[i].X * num7) + (source[i].Y * num8)) + (source[i].Z * num9)); - } - } - - - /// - /// Transforms a 3D vector by the given . - /// - /// The source vector. - /// The transformation . - /// When the method completes, contains the transformed . - public static void Transform(ref Vector3 vector, ref Matrix3x3 transform, out Vector3 result) - { - result = new Vector3( (vector.X * transform.M11) + (vector.Y * transform.M21) + (vector.Z * transform.M31), - (vector.X * transform.M12) + (vector.Y * transform.M22) + (vector.Z * transform.M32), - (vector.X * transform.M13) + (vector.Y * transform.M23) + (vector.Z * transform.M33) - ); - } - - /// - /// Transforms a 3D vector by the given . - /// - /// The source vector. - /// The transformation . - /// The transformed . - public static Vector3 Transform(Vector3 vector, Matrix3x3 transform) - { - Vector3 result; - Transform(ref vector, ref transform, out result); - return result; - } - - /// - /// Transforms a 3D vector by the given . - /// - /// The source vector. - /// The transformation . - /// When the method completes, contains the transformed . - public static void Transform(ref Vector3 vector, ref Matrix transform, out Vector3 result) - { - Vector4 intermediate; - Transform(ref vector, ref transform, out intermediate); - result = (Vector3)intermediate; - } - - /// - /// Transforms a 3D vector by the given . - /// - /// The source vector. - /// The transformation . - /// When the method completes, contains the transformed . - public static void Transform(ref Vector3 vector, ref Matrix transform, out Vector4 result) - { - result = new Vector4( - (vector.X * transform.M11) + (vector.Y * transform.M21) + (vector.Z * transform.M31) + transform.M41, - (vector.X * transform.M12) + (vector.Y * transform.M22) + (vector.Z * transform.M32) + transform.M42, - (vector.X * transform.M13) + (vector.Y * transform.M23) + (vector.Z * transform.M33) + transform.M43, - (vector.X * transform.M14) + (vector.Y * transform.M24) + (vector.Z * transform.M34) + transform.M44); - } - - /// - /// Transforms a 3D vector by the given . - /// - /// The source vector. - /// The transformation . - /// The transformed . - public static Vector4 Transform(Vector3 vector, Matrix transform) - { - Vector4 result; - Transform(ref vector, ref transform, out result); - return result; - } - - /// - /// Transforms an array of 3D vectors by the given . - /// - /// The array of vectors to transform. - /// The transformation . - /// The array for which the transformed vectors are stored. - /// Thrown when or is null. - /// Thrown when is shorter in length than . - public static void Transform(Vector3[] source, ref Matrix transform, Vector4[] destination) - { - if (source == null) - throw new ArgumentNullException("source"); - if (destination == null) - throw new ArgumentNullException("destination"); - if (destination.Length < source.Length) - throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); - - for (int i = 0; i < source.Length; ++i) - { - Transform(ref source[i], ref transform, out destination[i]); - } - } - - /// - /// Performs a coordinate transformation using the given . - /// - /// The coordinate vector to transform. - /// The transformation . - /// When the method completes, contains the transformed coordinates. - /// - /// A coordinate transform performs the transformation with the assumption that the w component - /// is one. The four dimensional vector obtained from the transformation operation has each - /// component in the vector divided by the w component. This forces the w component to be one and - /// therefore makes the vector homogeneous. The homogeneous vector is often preferred when working - /// with coordinates as the w component can safely be ignored. - /// - public static void TransformCoordinate(ref Vector3 coordinate, ref Matrix transform, out Vector3 result) - { - Vector4 vector = new Vector4(); - vector.X = (coordinate.X * transform.M11) + (coordinate.Y * transform.M21) + (coordinate.Z * transform.M31) + transform.M41; - vector.Y = (coordinate.X * transform.M12) + (coordinate.Y * transform.M22) + (coordinate.Z * transform.M32) + transform.M42; - vector.Z = (coordinate.X * transform.M13) + (coordinate.Y * transform.M23) + (coordinate.Z * transform.M33) + transform.M43; - vector.W = 1f / ((coordinate.X * transform.M14) + (coordinate.Y * transform.M24) + (coordinate.Z * transform.M34) + transform.M44); - - result = new Vector3(vector.X * vector.W, vector.Y * vector.W, vector.Z * vector.W); - } - - /// - /// Performs a coordinate transformation using the given . - /// - /// The coordinate vector to transform. - /// The transformation . - /// The transformed coordinates. - /// - /// A coordinate transform performs the transformation with the assumption that the w component - /// is one. The four dimensional vector obtained from the transformation operation has each - /// component in the vector divided by the w component. This forces the w component to be one and - /// therefore makes the vector homogeneous. The homogeneous vector is often preferred when working - /// with coordinates as the w component can safely be ignored. - /// - public static Vector3 TransformCoordinate(Vector3 coordinate, Matrix transform) - { - Vector3 result; - TransformCoordinate(ref coordinate, ref transform, out result); - return result; - } - - /// - /// Performs a coordinate transformation on an array of vectors using the given . - /// - /// The array of coordinate vectors to transform. - /// The transformation . - /// The array for which the transformed vectors are stored. - /// This array may be the same array as . - /// Thrown when or is null. - /// Thrown when is shorter in length than . - /// - /// A coordinate transform performs the transformation with the assumption that the w component - /// is one. The four dimensional vector obtained from the transformation operation has each - /// component in the vector divided by the w component. This forces the w component to be one and - /// therefore makes the vector homogeneous. The homogeneous vector is often preferred when working - /// with coordinates as the w component can safely be ignored. - /// - public static void TransformCoordinate(Vector3[] source, ref Matrix transform, Vector3[] destination) - { - if (source == null) - throw new ArgumentNullException("source"); - if (destination == null) - throw new ArgumentNullException("destination"); - if (destination.Length < source.Length) - throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); - - for (int i = 0; i < source.Length; ++i) - { - TransformCoordinate(ref source[i], ref transform, out destination[i]); - } - } - - /// - /// Performs a normal transformation using the given . - /// - /// The normal vector to transform. - /// The transformation . - /// When the method completes, contains the transformed normal. - /// - /// A normal transform performs the transformation with the assumption that the w component - /// is zero. This causes the fourth row and fourth column of the matrix to be unused. The - /// end result is a vector that is not translated, but all other transformation properties - /// apply. This is often preferred for normal vectors as normals purely represent direction - /// rather than location because normal vectors should not be translated. - /// - public static void TransformNormal(ref Vector3 normal, ref Matrix transform, out Vector3 result) - { - result = new Vector3( - (normal.X * transform.M11) + (normal.Y * transform.M21) + (normal.Z * transform.M31), - (normal.X * transform.M12) + (normal.Y * transform.M22) + (normal.Z * transform.M32), - (normal.X * transform.M13) + (normal.Y * transform.M23) + (normal.Z * transform.M33)); - } - - /// - /// Performs a normal transformation using the given . - /// - /// The normal vector to transform. - /// The transformation . - /// The transformed normal. - /// - /// A normal transform performs the transformation with the assumption that the w component - /// is zero. This causes the fourth row and fourth column of the matrix to be unused. The - /// end result is a vector that is not translated, but all other transformation properties - /// apply. This is often preferred for normal vectors as normals purely represent direction - /// rather than location because normal vectors should not be translated. - /// - public static Vector3 TransformNormal(Vector3 normal, Matrix transform) - { - Vector3 result; - TransformNormal(ref normal, ref transform, out result); - return result; - } - - /// - /// Performs a normal transformation on an array of vectors using the given . - /// - /// The array of normal vectors to transform. - /// The transformation . - /// The array for which the transformed vectors are stored. - /// This array may be the same array as . - /// Thrown when or is null. - /// Thrown when is shorter in length than . - /// - /// A normal transform performs the transformation with the assumption that the w component - /// is zero. This causes the fourth row and fourth column of the matrix to be unused. The - /// end result is a vector that is not translated, but all other transformation properties - /// apply. This is often preferred for normal vectors as normals purely represent direction - /// rather than location because normal vectors should not be translated. - /// - public static void TransformNormal(Vector3[] source, ref Matrix transform, Vector3[] destination) - { - if (source == null) - throw new ArgumentNullException("source"); - if (destination == null) - throw new ArgumentNullException("destination"); - if (destination.Length < source.Length) - throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); - - for (int i = 0; i < source.Length; ++i) - { - TransformNormal(ref source[i], ref transform, out destination[i]); - } - } - - /// - /// Adds two vectors. - /// - /// The first vector to add. - /// The second vector to add. - /// The sum of the two vectors. - public static Vector3 operator +(Vector3 left, Vector3 right) - { - return new Vector3(left.X + right.X, left.Y + right.Y, left.Z + right.Z); - } - - /// - /// Multiplies a vector with another by performing component-wise multiplication equivalent to . - /// - /// The first vector to multiply. - /// The second vector to multiply. - /// The multiplication of the two vectors. - public static Vector3 operator *(Vector3 left, Vector3 right) - { - return new Vector3(left.X * right.X, left.Y * right.Y, left.Z * right.Z); - } - - /// - /// Assert a vector (return it unchanged). - /// - /// The vector to assert (unchanged). - /// The asserted (unchanged) vector. - public static Vector3 operator +(Vector3 value) - { - return value; - } - - /// - /// Subtracts two vectors. - /// - /// The first vector to subtract. - /// The second vector to subtract. - /// The difference of the two vectors. - public static Vector3 operator -(Vector3 left, Vector3 right) - { - return new Vector3(left.X - right.X, left.Y - right.Y, left.Z - right.Z); - } - - /// - /// Reverses the direction of a given vector. - /// - /// The vector to negate. - /// A vector facing in the opposite direction. - public static Vector3 operator -(Vector3 value) - { - return new Vector3(-value.X, -value.Y, -value.Z); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector3 operator *(float scale, Vector3 value) - { - return new Vector3(value.X * scale, value.Y * scale, value.Z * scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector3 operator *(Vector3 value, float scale) - { - return new Vector3(value.X * scale, value.Y * scale, value.Z * scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector3 operator /(Vector3 value, float scale) - { - return new Vector3(value.X / scale, value.Y / scale, value.Z / scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The amount by which to scale the vector. - /// The vector to scale. - /// The scaled vector. - public static Vector3 operator /(float scale, Vector3 value) - { - return new Vector3(scale / value.X, scale / value.Y, scale / value.Z); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector3 operator /(Vector3 value, Vector3 scale) - { - return new Vector3(value.X / scale.X, value.Y / scale.Y, value.Z / scale.Z); - } - - /// - /// Perform a component-wise addition - /// - /// The input vector. - /// The scalar value to be added on elements - /// The vector with added scalar for each element. - public static Vector3 operator +(Vector3 value, float scalar) - { - return new Vector3(value.X + scalar, value.Y + scalar, value.Z + scalar); - } - - /// - /// Perform a component-wise addition - /// - /// The input vector. - /// The scalar value to be added on elements - /// The vector with added scalar for each element. - public static Vector3 operator +(float scalar, Vector3 value) - { - return new Vector3(scalar + value.X, scalar + value.Y, scalar + value.Z); - } - - /// - /// Perform a component-wise subtraction - /// - /// The input vector. - /// The scalar value to be subtraced from elements - /// The vector with added scalar from each element. - public static Vector3 operator -(Vector3 value, float scalar) - { - return new Vector3(value.X - scalar, value.Y - scalar, value.Z - scalar); - } - - /// - /// Perform a component-wise subtraction - /// - /// The input vector. - /// The scalar value to be subtraced from elements - /// The vector with subtraced scalar from each element. - public static Vector3 operator -(float scalar, Vector3 value) - { - return new Vector3(scalar - value.X, scalar - value.Y, scalar - value.Z); - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has the same value as ; otherwise, false. - public static bool operator ==(Vector3 left, Vector3 right) - { - return left.Equals(ref right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has a different value than ; otherwise, false. - public static bool operator !=(Vector3 left, Vector3 right) - { - return !left.Equals(ref right); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Vector2(Vector3 value) - { - return new Vector2(value.X, value.Y); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Vector4(Vector3 value) - { - return new Vector4(value, 0.0f); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2}", X, Y, Z); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// - /// A that represents this instance. - /// - public string ToString(string format) - { - if (format == null) - return ToString(); - - return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2}", X.ToString(format, CultureInfo.CurrentCulture), - Y.ToString(format, CultureInfo.CurrentCulture), Z.ToString(format, CultureInfo.CurrentCulture)); - } - - /// - /// Returns a that represents this instance. - /// - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(IFormatProvider formatProvider) - { - return string.Format(formatProvider, "X:{0} Y:{1} Z:{2}", X, Y, Z); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - if (format == null) - return ToString(formatProvider); - - return string.Format(formatProvider, "X:{0} Y:{1} Z:{2}", X.ToString(format, formatProvider), - Y.ToString(format, formatProvider), Z.ToString(format, formatProvider)); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - var hashCode = X.GetHashCode(); - hashCode = (hashCode * 397) ^ Y.GetHashCode(); - hashCode = (hashCode * 397) ^ Z.GetHashCode(); - return hashCode; - } - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(X); - serializer.Writer.Write(Y); - serializer.Writer.Write(Z); - } - else - { - X = serializer.Reader.ReadSingle(); - Y = serializer.Reader.ReadSingle(); - Z = serializer.Reader.ReadSingle(); - } - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(ref Vector3 other) - { - return MathUtil.NearEqual(other.X, X) && MathUtil.NearEqual(other.Y, Y) && MathUtil.NearEqual(other.Z, Z); - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(Vector3 other) - { - return Equals(ref other); - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object value) - { - if (!(value is Vector3)) - return false; - - var strongValue = (Vector3)value; - return Equals(ref strongValue); - } -#if WPFInterop - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator System.Windows.Media.Media3D.Vector3D(Vector3 value) - { - return new System.Windows.Media.Media3D.Vector3D(value.X, value.Y, value.Z); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Vector3(System.Windows.Media.Media3D.Vector3D value) - { - return new Vector3((float)value.X, (float)value.Y, (float)value.Z); - } -#endif - -#if XnaInterop - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Microsoft.Xna.Framework.Vector3(Vector3 value) - { - return new Microsoft.Xna.Framework.Vector3(value.X, value.Y, value.Z); - } - - /// - /// Performs an implicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static implicit operator Vector3(Microsoft.Xna.Framework.Vector3 value) - { - return new Vector3(value.X, value.Y, value.Z); - } -#endif - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from SlimMath project. http://code.google.com/p/slimmath/ +// Greetings to SlimDX Group. Original code published with the following license: +// ----------------------------------------------------------------------------- +/* +* Copyright (c) 2007-2011 SlimDX Group +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Represents a three dimensional mathematical vector. + /// + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct Vector3 : IEquatable, IFormattable + { + /// + /// The size of the type, in bytes. + /// + public static readonly int SizeInBytes = Marshal.SizeOf(typeof(Vector3)); + + /// + /// A with all of its components set to zero. + /// + public static readonly Vector3 Zero = new Vector3(); + + /// + /// The X unit (1, 0, 0). + /// + public static readonly Vector3 UnitX = new Vector3(1.0f, 0.0f, 0.0f); + + /// + /// The Y unit (0, 1, 0). + /// + public static readonly Vector3 UnitY = new Vector3(0.0f, 1.0f, 0.0f); + + /// + /// The Z unit (0, 0, 1). + /// + public static readonly Vector3 UnitZ = new Vector3(0.0f, 0.0f, 1.0f); + + /// + /// A with all of its components set to one. + /// + public static readonly Vector3 One = new Vector3(1.0f, 1.0f, 1.0f); + + /// + /// A unit designating up (0, 1, 0). + /// + public static readonly Vector3 Up = new Vector3(0.0f, 1.0f, 0.0f); + + /// + /// A unit designating down (0, -1, 0). + /// + public static readonly Vector3 Down = new Vector3(0.0f, -1.0f, 0.0f); + + /// + /// A unit designating left (-1, 0, 0). + /// + public static readonly Vector3 Left = new Vector3(-1.0f, 0.0f, 0.0f); + + /// + /// A unit designating right (1, 0, 0). + /// + public static readonly Vector3 Right = new Vector3(1.0f, 0.0f, 0.0f); + + /// + /// A unit designating forward in a right-handed coordinate system (0, 0, -1). + /// + public static readonly Vector3 ForwardRH = new Vector3(0.0f, 0.0f, -1.0f); + + /// + /// A unit designating forward in a left-handed coordinate system (0, 0, 1). + /// + public static readonly Vector3 ForwardLH = new Vector3(0.0f, 0.0f, 1.0f); + + /// + /// A unit designating backward in a right-handed coordinate system (0, 0, 1). + /// + public static readonly Vector3 BackwardRH = new Vector3(0.0f, 0.0f, 1.0f); + + /// + /// A unit designating backward in a left-handed coordinate system (0, 0, -1). + /// + public static readonly Vector3 BackwardLH = new Vector3(0.0f, 0.0f, -1.0f); + + /// + /// The X component of the vector. + /// + public float X; + + /// + /// The Y component of the vector. + /// + public float Y; + + /// + /// The Z component of the vector. + /// + public float Z; + + /// + /// Initializes a new instance of the struct. + /// + /// The value that will be assigned to all components. + public Vector3(float value) + { + X = value; + Y = value; + Z = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// Initial value for the X component of the vector. + /// Initial value for the Y component of the vector. + /// Initial value for the Z component of the vector. + public Vector3(float x, float y, float z) + { + X = x; + Y = y; + Z = z; + } + + /// + /// Initializes a new instance of the struct. + /// + /// A vector containing the values with which to initialize the X and Y components. + /// Initial value for the Z component of the vector. + public Vector3(Vector2 value, float z) + { + X = value.X; + Y = value.Y; + Z = z; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The values to assign to the X, Y, and Z components of the vector. This must be an array with three elements. + /// Thrown when is null. + /// Thrown when contains more or less than three elements. + public Vector3(float[] values) + { + if (values == null) + throw new ArgumentNullException("values"); + if (values.Length != 3) + throw new ArgumentOutOfRangeException("values", "There must be three and only three input values for Vector3."); + + X = values[0]; + Y = values[1]; + Z = values[2]; + } + + /// + /// Gets a value indicting whether this instance is normalized. + /// + public bool IsNormalized + { + get { return MathUtil.IsOne((X * X) + (Y * Y) + (Z * Z)); } + } + + /// + /// Gets a value indicting whether this vector is zero + /// + public bool IsZero + { + get { return X == 0 && Y == 0 && Z == 0; } + } + + /// + /// Gets or sets the component at the specified index. + /// + /// The value of the X, Y, or Z component, depending on the index. + /// The index of the component to access. Use 0 for the X component, 1 for the Y component, and 2 for the Z component. + /// The value of the component at the specified index. + /// Thrown when the is out of the range [0, 2]. + public float this[int index] + { + get + { + switch (index) + { + case 0: return X; + case 1: return Y; + case 2: return Z; + } + + throw new ArgumentOutOfRangeException("index", "Indices for Vector3 run from 0 to 2, inclusive."); + } + + set + { + switch (index) + { + case 0: X = value; break; + case 1: Y = value; break; + case 2: Z = value; break; + default: throw new ArgumentOutOfRangeException("index", "Indices for Vector3 run from 0 to 2, inclusive."); + } + } + } + + /// + /// Calculates the length of the vector. + /// + /// The length of the vector. + /// + /// may be preferred when only the relative length is needed + /// and speed is of the essence. + /// + public float Length() + { + return (float)Math.Sqrt((X * X) + (Y * Y) + (Z * Z)); + } + + /// + /// Calculates the squared length of the vector. + /// + /// The squared length of the vector. + /// + /// This method may be preferred to when only a relative length is needed + /// and speed is of the essence. + /// + public float LengthSquared() + { + return (X * X) + (Y * Y) + (Z * Z); + } + + /// + /// Converts the vector into a unit vector. + /// + public void Normalize() + { + float length = Length(); + if (!MathUtil.IsZero(length)) + { + float inv = 1.0f / length; + X *= inv; + Y *= inv; + Z *= inv; + } + } + + /// + /// Creates an array containing the elements of the vector. + /// + /// A three-element array containing the components of the vector. + public float[] ToArray() + { + return new float[] { X, Y, Z }; + } + + /// + /// Adds two vectors. + /// + /// The first vector to add. + /// The second vector to add. + /// When the method completes, contains the sum of the two vectors. + public static void Add(ref Vector3 left, ref Vector3 right, out Vector3 result) + { + result = new Vector3(left.X + right.X, left.Y + right.Y, left.Z + right.Z); + } + + /// + /// Adds two vectors. + /// + /// The first vector to add. + /// The second vector to add. + /// The sum of the two vectors. + public static Vector3 Add(Vector3 left, Vector3 right) + { + return new Vector3(left.X + right.X, left.Y + right.Y, left.Z + right.Z); + } + + /// + /// Perform a component-wise addition + /// + /// The input vector + /// The scalar value to be added to elements + /// The vector with added scalar for each element. + public static void Add(ref Vector3 left, ref float right, out Vector3 result) + { + result = new Vector3(left.X + right, left.Y + right, left.Z + right); + } + + /// + /// Perform a component-wise addition + /// + /// The input vector + /// The scalar value to be added to elements + /// The vector with added scalar for each element. + public static Vector3 Add(Vector3 left, float right) + { + return new Vector3(left.X + right, left.Y + right, left.Z + right); + } + + /// + /// Subtracts two vectors. + /// + /// The first vector to subtract. + /// The second vector to subtract. + /// When the method completes, contains the difference of the two vectors. + public static void Subtract(ref Vector3 left, ref Vector3 right, out Vector3 result) + { + result = new Vector3(left.X - right.X, left.Y - right.Y, left.Z - right.Z); + } + + /// + /// Subtracts two vectors. + /// + /// The first vector to subtract. + /// The second vector to subtract. + /// The difference of the two vectors. + public static Vector3 Subtract(Vector3 left, Vector3 right) + { + return new Vector3(left.X - right.X, left.Y - right.Y, left.Z - right.Z); + } + + /// + /// Perform a component-wise subtraction + /// + /// The input vector + /// The scalar value to be subtraced from elements + /// The vector with subtracted scalar for each element. + public static void Subtract(ref Vector3 left, ref float right, out Vector3 result) + { + result = new Vector3(left.X - right, left.Y - right, left.Z - right); + } + + /// + /// Perform a component-wise subtraction + /// + /// The input vector + /// The scalar value to be subtraced from elements + /// The vector with subtracted scalar for each element. + public static Vector3 Subtract(Vector3 left, float right) + { + return new Vector3(left.X - right, left.Y - right, left.Z - right); + } + + /// + /// Perform a component-wise subtraction + /// + /// The scalar value to be subtraced from elements + /// The input vector. + /// The vector with subtracted scalar for each element. + public static void Subtract(ref float left, ref Vector3 right, out Vector3 result) + { + result = new Vector3(left - right.X, left - right.Y, left - right.Z); + } + + /// + /// Perform a component-wise subtraction + /// + /// The scalar value to be subtraced from elements + /// The input vector. + /// The vector with subtracted scalar for each element. + public static Vector3 Subtract(float left, Vector3 right) + { + return new Vector3(left - right.X, left - right.Y, left - right.Z); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// When the method completes, contains the scaled vector. + public static void Multiply(ref Vector3 value, float scale, out Vector3 result) + { + result = new Vector3(value.X * scale, value.Y * scale, value.Z * scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector3 Multiply(Vector3 value, float scale) + { + return new Vector3(value.X * scale, value.Y * scale, value.Z * scale); + } + + /// + /// Multiply a vector with another by performing component-wise multiplication. + /// + /// The first vector to multiply. + /// The second vector to multiply. + /// When the method completes, contains the multiplied vector. + public static void Multiply(ref Vector3 left, ref Vector3 right, out Vector3 result) + { + result = new Vector3(left.X * right.X, left.Y * right.Y, left.Z * right.Z); + } + + /// + /// Multiply a vector with another by performing component-wise multiplication. + /// + /// The first vector to Multiply. + /// The second vector to multiply. + /// The multiplied vector. + public static Vector3 Multiply(Vector3 left, Vector3 right) + { + return new Vector3(left.X * right.X, left.Y * right.Y, left.Z * right.Z); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// When the method completes, contains the scaled vector. + public static void Divide(ref Vector3 value, float scale, out Vector3 result) + { + result = new Vector3(value.X / scale, value.Y / scale, value.Z / scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector3 Divide(Vector3 value, float scale) + { + return new Vector3(value.X / scale, value.Y / scale, value.Z / scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The amount by which to scale the vector. + /// The vector to scale. + /// When the method completes, contains the scaled vector. + public static void Divide(float scale, ref Vector3 value, out Vector3 result) + { + result = new Vector3(scale / value.X, scale / value.Y, scale / value.Z); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector3 Divide(float scale, Vector3 value) + { + return new Vector3(scale / value.X, scale / value.Y, scale / value.Z); + } + + /// + /// Reverses the direction of a given vector. + /// + /// The vector to negate. + /// When the method completes, contains a vector facing in the opposite direction. + public static void Negate(ref Vector3 value, out Vector3 result) + { + result = new Vector3(-value.X, -value.Y, -value.Z); + } + + /// + /// Reverses the direction of a given vector. + /// + /// The vector to negate. + /// A vector facing in the opposite direction. + public static Vector3 Negate(Vector3 value) + { + return new Vector3(-value.X, -value.Y, -value.Z); + } + + /// + /// Returns a containing the 3D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 3D triangle. + /// + /// A containing the 3D Cartesian coordinates of vertex 1 of the triangle. + /// A containing the 3D Cartesian coordinates of vertex 2 of the triangle. + /// A containing the 3D Cartesian coordinates of vertex 3 of the triangle. + /// Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). + /// Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). + /// When the method completes, contains the 3D Cartesian coordinates of the specified point. + public static void Barycentric(ref Vector3 value1, ref Vector3 value2, ref Vector3 value3, float amount1, float amount2, out Vector3 result) + { + result = new Vector3((value1.X + (amount1 * (value2.X - value1.X))) + (amount2 * (value3.X - value1.X)), + (value1.Y + (amount1 * (value2.Y - value1.Y))) + (amount2 * (value3.Y - value1.Y)), + (value1.Z + (amount1 * (value2.Z - value1.Z))) + (amount2 * (value3.Z - value1.Z))); + } + + /// + /// Returns a containing the 3D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 3D triangle. + /// + /// A containing the 3D Cartesian coordinates of vertex 1 of the triangle. + /// A containing the 3D Cartesian coordinates of vertex 2 of the triangle. + /// A containing the 3D Cartesian coordinates of vertex 3 of the triangle. + /// Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). + /// Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). + /// A new containing the 3D Cartesian coordinates of the specified point. + public static Vector3 Barycentric(Vector3 value1, Vector3 value2, Vector3 value3, float amount1, float amount2) + { + Vector3 result; + Barycentric(ref value1, ref value2, ref value3, amount1, amount2, out result); + return result; + } + + /// + /// Restricts a value to be within a specified range. + /// + /// The value to clamp. + /// The minimum value. + /// The maximum value. + /// When the method completes, contains the clamped value. + public static void Clamp(ref Vector3 value, ref Vector3 min, ref Vector3 max, out Vector3 result) + { + float x = value.X; + x = (x > max.X) ? max.X : x; + x = (x < min.X) ? min.X : x; + + float y = value.Y; + y = (y > max.Y) ? max.Y : y; + y = (y < min.Y) ? min.Y : y; + + float z = value.Z; + z = (z > max.Z) ? max.Z : z; + z = (z < min.Z) ? min.Z : z; + + result = new Vector3(x, y, z); + } + + /// + /// Restricts a value to be within a specified range. + /// + /// The value to clamp. + /// The minimum value. + /// The maximum value. + /// The clamped value. + public static Vector3 Clamp(Vector3 value, Vector3 min, Vector3 max) + { + Vector3 result; + Clamp(ref value, ref min, ref max, out result); + return result; + } + + /// + /// Calculates the cross product of two vectors. + /// + /// First source vector. + /// Second source vector. + /// When the method completes, contains he cross product of the two vectors. + public static void Cross(ref Vector3 left, ref Vector3 right, out Vector3 result) + { + result = new Vector3( + (left.Y * right.Z) - (left.Z * right.Y), + (left.Z * right.X) - (left.X * right.Z), + (left.X * right.Y) - (left.Y * right.X)); + } + + /// + /// Calculates the cross product of two vectors. + /// + /// First source vector. + /// Second source vector. + /// The cross product of the two vectors. + public static Vector3 Cross(Vector3 left, Vector3 right) + { + Vector3 result; + Cross(ref left, ref right, out result); + return result; + } + + /// + /// Calculates the distance between two vectors. + /// + /// The first vector. + /// The second vector. + /// When the method completes, contains the distance between the two vectors. + /// + /// may be preferred when only the relative distance is needed + /// and speed is of the essence. + /// + public static void Distance(ref Vector3 value1, ref Vector3 value2, out float result) + { + float x = value1.X - value2.X; + float y = value1.Y - value2.Y; + float z = value1.Z - value2.Z; + + result = (float)Math.Sqrt((x * x) + (y * y) + (z * z)); + } + + /// + /// Calculates the distance between two vectors. + /// + /// The first vector. + /// The second vector. + /// The distance between the two vectors. + /// + /// may be preferred when only the relative distance is needed + /// and speed is of the essence. + /// + public static float Distance(Vector3 value1, Vector3 value2) + { + float x = value1.X - value2.X; + float y = value1.Y - value2.Y; + float z = value1.Z - value2.Z; + + return (float)Math.Sqrt((x * x) + (y * y) + (z * z)); + } + + /// + /// Calculates the squared distance between two vectors. + /// + /// The first vector. + /// The second vector. + /// When the method completes, contains the squared distance between the two vectors. + /// Distance squared is the value before taking the square root. + /// Distance squared can often be used in place of distance if relative comparisons are being made. + /// For example, consider three points A, B, and C. To determine whether B or C is further from A, + /// compare the distance between A and B to the distance between A and C. Calculating the two distances + /// involves two square roots, which are computationally expensive. However, using distance squared + /// provides the same information and avoids calculating two square roots. + /// + public static void DistanceSquared(ref Vector3 value1, ref Vector3 value2, out float result) + { + float x = value1.X - value2.X; + float y = value1.Y - value2.Y; + float z = value1.Z - value2.Z; + + result = (x * x) + (y * y) + (z * z); + } + + /// + /// Calculates the squared distance between two vectors. + /// + /// The first vector. + /// The second vector. + /// The squared distance between the two vectors. + /// Distance squared is the value before taking the square root. + /// Distance squared can often be used in place of distance if relative comparisons are being made. + /// For example, consider three points A, B, and C. To determine whether B or C is further from A, + /// compare the distance between A and B to the distance between A and C. Calculating the two distances + /// involves two square roots, which are computationally expensive. However, using distance squared + /// provides the same information and avoids calculating two square roots. + /// + public static float DistanceSquared(Vector3 value1, Vector3 value2) + { + float x = value1.X - value2.X; + float y = value1.Y - value2.Y; + float z = value1.Z - value2.Z; + + return (x * x) + (y * y) + (z * z); + } + + /// + /// Tests whether one 3D vector is near another 3D vector. + /// + /// The left vector. + /// The right vector. + /// The epsilon. + /// true if left and right are near another 3D, false otherwise + public static bool NearEqual(Vector3 left, Vector3 right, Vector3 epsilon) + { + return NearEqual(ref left, ref right, ref epsilon); + } + + /// + /// Tests whether one 3D vector is near another 3D vector. + /// + /// The left vector. + /// The right vector. + /// The epsilon. + /// true if left and right are near another 3D, false otherwise + public static bool NearEqual(ref Vector3 left, ref Vector3 right, ref Vector3 epsilon) + { + return MathUtil.WithinEpsilon(left.X, right.X, epsilon.X) && + MathUtil.WithinEpsilon(left.Y, right.Y, epsilon.Y) && + MathUtil.WithinEpsilon(left.Z, right.Z, epsilon.Z); + } + + /// + /// Calculates the dot product of two vectors. + /// + /// First source vector. + /// Second source vector. + /// When the method completes, contains the dot product of the two vectors. + public static void Dot(ref Vector3 left, ref Vector3 right, out float result) + { + result = (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z); + } + + /// + /// Calculates the dot product of two vectors. + /// + /// First source vector. + /// Second source vector. + /// The dot product of the two vectors. + public static float Dot(Vector3 left, Vector3 right) + { + return (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z); + } + + /// + /// Converts the vector into a unit vector. + /// + /// The vector to normalize. + /// When the method completes, contains the normalized vector. + public static void Normalize(ref Vector3 value, out Vector3 result) + { + result = value; + result.Normalize(); + } + + /// + /// Converts the vector into a unit vector. + /// + /// The vector to normalize. + /// The normalized vector. + public static Vector3 Normalize(Vector3 value) + { + value.Normalize(); + return value; + } + + /// + /// Performs a linear interpolation between two vectors. + /// + /// Start vector. + /// End vector. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the linear interpolation of the two vectors. + /// + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static void Lerp(ref Vector3 start, ref Vector3 end, float amount, out Vector3 result) + { + result.X = MathUtil.Lerp(start.X, end.X, amount); + result.Y = MathUtil.Lerp(start.Y, end.Y, amount); + result.Z = MathUtil.Lerp(start.Z, end.Z, amount); + } + + /// + /// Performs a linear interpolation between two vectors. + /// + /// Start vector. + /// End vector. + /// Value between 0 and 1 indicating the weight of . + /// The linear interpolation of the two vectors. + /// + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static Vector3 Lerp(Vector3 start, Vector3 end, float amount) + { + Vector3 result; + Lerp(ref start, ref end, amount, out result); + return result; + } + + /// + /// Performs a cubic interpolation between two vectors. + /// + /// Start vector. + /// End vector. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the cubic interpolation of the two vectors. + public static void SmoothStep(ref Vector3 start, ref Vector3 end, float amount, out Vector3 result) + { + amount = MathUtil.SmoothStep(amount); + Lerp(ref start, ref end, amount, out result); + } + + /// + /// Performs a cubic interpolation between two vectors. + /// + /// Start vector. + /// End vector. + /// Value between 0 and 1 indicating the weight of . + /// The cubic interpolation of the two vectors. + public static Vector3 SmoothStep(Vector3 start, Vector3 end, float amount) + { + Vector3 result; + SmoothStep(ref start, ref end, amount, out result); + return result; + } + + /// + /// Performs a Hermite spline interpolation. + /// + /// First source position vector. + /// First source tangent vector. + /// Second source position vector. + /// Second source tangent vector. + /// Weighting factor. + /// When the method completes, contains the result of the Hermite spline interpolation. + public static void Hermite(ref Vector3 value1, ref Vector3 tangent1, ref Vector3 value2, ref Vector3 tangent2, float amount, out Vector3 result) + { + float squared = amount * amount; + float cubed = amount * squared; + float part1 = ((2.0f * cubed) - (3.0f * squared)) + 1.0f; + float part2 = (-2.0f * cubed) + (3.0f * squared); + float part3 = (cubed - (2.0f * squared)) + amount; + float part4 = cubed - squared; + + result.X = (((value1.X * part1) + (value2.X * part2)) + (tangent1.X * part3)) + (tangent2.X * part4); + result.Y = (((value1.Y * part1) + (value2.Y * part2)) + (tangent1.Y * part3)) + (tangent2.Y * part4); + result.Z = (((value1.Z * part1) + (value2.Z * part2)) + (tangent1.Z * part3)) + (tangent2.Z * part4); + } + + /// + /// Performs a Hermite spline interpolation. + /// + /// First source position vector. + /// First source tangent vector. + /// Second source position vector. + /// Second source tangent vector. + /// Weighting factor. + /// The result of the Hermite spline interpolation. + public static Vector3 Hermite(Vector3 value1, Vector3 tangent1, Vector3 value2, Vector3 tangent2, float amount) + { + Vector3 result; + Hermite(ref value1, ref tangent1, ref value2, ref tangent2, amount, out result); + return result; + } + + /// + /// Performs a Catmull-Rom interpolation using the specified positions. + /// + /// The first position in the interpolation. + /// The second position in the interpolation. + /// The third position in the interpolation. + /// The fourth position in the interpolation. + /// Weighting factor. + /// When the method completes, contains the result of the Catmull-Rom interpolation. + public static void CatmullRom(ref Vector3 value1, ref Vector3 value2, ref Vector3 value3, ref Vector3 value4, float amount, out Vector3 result) + { + float squared = amount * amount; + float cubed = amount * squared; + + result.X = 0.5f * ((((2.0f * value2.X) + ((-value1.X + value3.X) * amount)) + + (((((2.0f * value1.X) - (5.0f * value2.X)) + (4.0f * value3.X)) - value4.X) * squared)) + + ((((-value1.X + (3.0f * value2.X)) - (3.0f * value3.X)) + value4.X) * cubed)); + + result.Y = 0.5f * ((((2.0f * value2.Y) + ((-value1.Y + value3.Y) * amount)) + + (((((2.0f * value1.Y) - (5.0f * value2.Y)) + (4.0f * value3.Y)) - value4.Y) * squared)) + + ((((-value1.Y + (3.0f * value2.Y)) - (3.0f * value3.Y)) + value4.Y) * cubed)); + + result.Z = 0.5f * ((((2.0f * value2.Z) + ((-value1.Z + value3.Z) * amount)) + + (((((2.0f * value1.Z) - (5.0f * value2.Z)) + (4.0f * value3.Z)) - value4.Z) * squared)) + + ((((-value1.Z + (3.0f * value2.Z)) - (3.0f * value3.Z)) + value4.Z) * cubed)); + } + + /// + /// Performs a Catmull-Rom interpolation using the specified positions. + /// + /// The first position in the interpolation. + /// The second position in the interpolation. + /// The third position in the interpolation. + /// The fourth position in the interpolation. + /// Weighting factor. + /// A vector that is the result of the Catmull-Rom interpolation. + public static Vector3 CatmullRom(Vector3 value1, Vector3 value2, Vector3 value3, Vector3 value4, float amount) + { + Vector3 result; + CatmullRom(ref value1, ref value2, ref value3, ref value4, amount, out result); + return result; + } + + /// + /// Returns a vector containing the largest components of the specified vectors. + /// + /// The first source vector. + /// The second source vector. + /// When the method completes, contains an new vector composed of the largest components of the source vectors. + public static void Max(ref Vector3 left, ref Vector3 right, out Vector3 result) + { + result.X = (left.X > right.X) ? left.X : right.X; + result.Y = (left.Y > right.Y) ? left.Y : right.Y; + result.Z = (left.Z > right.Z) ? left.Z : right.Z; + } + + /// + /// Returns a vector containing the largest components of the specified vectors. + /// + /// The first source vector. + /// The second source vector. + /// A vector containing the largest components of the source vectors. + public static Vector3 Max(Vector3 left, Vector3 right) + { + Vector3 result; + Max(ref left, ref right, out result); + return result; + } + + /// + /// Returns a vector containing the smallest components of the specified vectors. + /// + /// The first source vector. + /// The second source vector. + /// When the method completes, contains an new vector composed of the smallest components of the source vectors. + public static void Min(ref Vector3 left, ref Vector3 right, out Vector3 result) + { + result.X = (left.X < right.X) ? left.X : right.X; + result.Y = (left.Y < right.Y) ? left.Y : right.Y; + result.Z = (left.Z < right.Z) ? left.Z : right.Z; + } + + /// + /// Returns a vector containing the smallest components of the specified vectors. + /// + /// The first source vector. + /// The second source vector. + /// A vector containing the smallest components of the source vectors. + public static Vector3 Min(Vector3 left, Vector3 right) + { + Vector3 result; + Min(ref left, ref right, out result); + return result; + } + + /// + /// Projects a 3D vector from object space into screen space. + /// + /// The vector to project. + /// The X position of the viewport. + /// The Y position of the viewport. + /// The width of the viewport. + /// The height of the viewport. + /// The minimum depth of the viewport. + /// The maximum depth of the viewport. + /// The combined world-view-projection matrix. + /// When the method completes, contains the vector in screen space. + public static void Project(ref Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, ref Matrix worldViewProjection, out Vector3 result) + { + Vector3 v = new Vector3(); + TransformCoordinate(ref vector, ref worldViewProjection, out v); + + result = new Vector3(((1.0f + v.X) * 0.5f * width) + x, ((1.0f - v.Y) * 0.5f * height) + y, (v.Z * (maxZ - minZ)) + minZ); + } + + /// + /// Projects a 3D vector from object space into screen space. + /// + /// The vector to project. + /// The X position of the viewport. + /// The Y position of the viewport. + /// The width of the viewport. + /// The height of the viewport. + /// The minimum depth of the viewport. + /// The maximum depth of the viewport. + /// The combined world-view-projection matrix. + /// The vector in screen space. + public static Vector3 Project(Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, Matrix worldViewProjection) + { + Vector3 result; + Project(ref vector, x, y, width, height, minZ, maxZ, ref worldViewProjection, out result); + return result; + } + + /// + /// Projects a 3D vector from screen space into object space. + /// + /// The vector to project. + /// The X position of the viewport. + /// The Y position of the viewport. + /// The width of the viewport. + /// The height of the viewport. + /// The minimum depth of the viewport. + /// The maximum depth of the viewport. + /// The combined world-view-projection matrix. + /// When the method completes, contains the vector in object space. + public static void Unproject(ref Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, ref Matrix worldViewProjection, out Vector3 result) + { + Vector3 v = new Vector3(); + Matrix matrix = new Matrix(); + Matrix.Invert(ref worldViewProjection, out matrix); + + v.X = (((vector.X - x) / width) * 2.0f) - 1.0f; + v.Y = -((((vector.Y - y) / height) * 2.0f) - 1.0f); + v.Z = (vector.Z - minZ) / (maxZ - minZ); + + TransformCoordinate(ref v, ref matrix, out result); + } + + /// + /// Projects a 3D vector from screen space into object space. + /// + /// The vector to project. + /// The X position of the viewport. + /// The Y position of the viewport. + /// The width of the viewport. + /// The height of the viewport. + /// The minimum depth of the viewport. + /// The maximum depth of the viewport. + /// The combined world-view-projection matrix. + /// The vector in object space. + public static Vector3 Unproject(Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, Matrix worldViewProjection) + { + Vector3 result; + Unproject(ref vector, x, y, width, height, minZ, maxZ, ref worldViewProjection, out result); + return result; + } + + /// + /// Returns the reflection of a vector off a surface that has the specified normal. + /// + /// The source vector. + /// Normal of the surface. + /// When the method completes, contains the reflected vector. + /// Reflect only gives the direction of a reflection off a surface, it does not determine + /// whether the original vector was close enough to the surface to hit it. + public static void Reflect(ref Vector3 vector, ref Vector3 normal, out Vector3 result) + { + float dot = (vector.X * normal.X) + (vector.Y * normal.Y) + (vector.Z * normal.Z); + + result.X = vector.X - ((2.0f * dot) * normal.X); + result.Y = vector.Y - ((2.0f * dot) * normal.Y); + result.Z = vector.Z - ((2.0f * dot) * normal.Z); + } + + /// + /// Returns the reflection of a vector off a surface that has the specified normal. + /// + /// The source vector. + /// Normal of the surface. + /// The reflected vector. + /// Reflect only gives the direction of a reflection off a surface, it does not determine + /// whether the original vector was close enough to the surface to hit it. + public static Vector3 Reflect(Vector3 vector, Vector3 normal) + { + Vector3 result; + Reflect(ref vector, ref normal, out result); + return result; + } + + /// + /// Orthogonalizes a list of vectors. + /// + /// The list of orthogonalized vectors. + /// The list of vectors to orthogonalize. + /// + /// Orthogonalization is the process of making all vectors orthogonal to each other. This + /// means that any given vector in the list will be orthogonal to any other given vector in the + /// list. + /// Because this method uses the modified Gram-Schmidt process, the resulting vectors + /// tend to be numerically unstable. The numeric stability decreases according to the vectors + /// position in the list so that the first vector is the most stable and the last vector is the + /// least stable. + /// + /// Thrown when or is null. + /// Thrown when is shorter in length than . + public static void Orthogonalize(Vector3[] destination, params Vector3[] source) + { + //Uses the modified Gram-Schmidt process. + //q1 = m1 + //q2 = m2 - ((q1 ⋅ m2) / (q1 ⋅ q1)) * q1 + //q3 = m3 - ((q1 ⋅ m3) / (q1 ⋅ q1)) * q1 - ((q2 ⋅ m3) / (q2 ⋅ q2)) * q2 + //q4 = m4 - ((q1 ⋅ m4) / (q1 ⋅ q1)) * q1 - ((q2 ⋅ m4) / (q2 ⋅ q2)) * q2 - ((q3 ⋅ m4) / (q3 ⋅ q3)) * q3 + //q5 = ... + + if (source == null) + throw new ArgumentNullException("source"); + if (destination == null) + throw new ArgumentNullException("destination"); + if (destination.Length < source.Length) + throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); + + for (int i = 0; i < source.Length; ++i) + { + Vector3 newvector = source[i]; + + for (int r = 0; r < i; ++r) + { + newvector -= (Vector3.Dot(destination[r], newvector) / Vector3.Dot(destination[r], destination[r])) * destination[r]; + } + + destination[i] = newvector; + } + } + + /// + /// Orthonormalizes a list of vectors. + /// + /// The list of orthonormalized vectors. + /// The list of vectors to orthonormalize. + /// + /// Orthonormalization is the process of making all vectors orthogonal to each + /// other and making all vectors of unit length. This means that any given vector will + /// be orthogonal to any other given vector in the list. + /// Because this method uses the modified Gram-Schmidt process, the resulting vectors + /// tend to be numerically unstable. The numeric stability decreases according to the vectors + /// position in the list so that the first vector is the most stable and the last vector is the + /// least stable. + /// + /// Thrown when or is null. + /// Thrown when is shorter in length than . + public static void Orthonormalize(Vector3[] destination, params Vector3[] source) + { + //Uses the modified Gram-Schmidt process. + //Because we are making unit vectors, we can optimize the math for orthogonalization + //and simplify the projection operation to remove the division. + //q1 = m1 / |m1| + //q2 = (m2 - (q1 ⋅ m2) * q1) / |m2 - (q1 ⋅ m2) * q1| + //q3 = (m3 - (q1 ⋅ m3) * q1 - (q2 ⋅ m3) * q2) / |m3 - (q1 ⋅ m3) * q1 - (q2 ⋅ m3) * q2| + //q4 = (m4 - (q1 ⋅ m4) * q1 - (q2 ⋅ m4) * q2 - (q3 ⋅ m4) * q3) / |m4 - (q1 ⋅ m4) * q1 - (q2 ⋅ m4) * q2 - (q3 ⋅ m4) * q3| + //q5 = ... + + if (source == null) + throw new ArgumentNullException("source"); + if (destination == null) + throw new ArgumentNullException("destination"); + if (destination.Length < source.Length) + throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); + + for (int i = 0; i < source.Length; ++i) + { + Vector3 newvector = source[i]; + + for (int r = 0; r < i; ++r) + { + newvector -= Vector3.Dot(destination[r], newvector) * destination[r]; + } + + newvector.Normalize(); + destination[i] = newvector; + } + } + + /// + /// Transforms a 3D vector by the given rotation. + /// + /// The vector to rotate. + /// The rotation to apply. + /// When the method completes, contains the transformed . + public static void Transform(ref Vector3 vector, ref Quaternion rotation, out Vector3 result) + { + float x = rotation.X + rotation.X; + float y = rotation.Y + rotation.Y; + float z = rotation.Z + rotation.Z; + float wx = rotation.W * x; + float wy = rotation.W * y; + float wz = rotation.W * z; + float xx = rotation.X * x; + float xy = rotation.X * y; + float xz = rotation.X * z; + float yy = rotation.Y * y; + float yz = rotation.Y * z; + float zz = rotation.Z * z; + + result = new Vector3( + ((vector.X * ((1.0f - yy) - zz)) + (vector.Y * (xy - wz))) + (vector.Z * (xz + wy)), + ((vector.X * (xy + wz)) + (vector.Y * ((1.0f - xx) - zz))) + (vector.Z * (yz - wx)), + ((vector.X * (xz - wy)) + (vector.Y * (yz + wx))) + (vector.Z * ((1.0f - xx) - yy))); + } + + /// + /// Transforms a 3D vector by the given rotation. + /// + /// The vector to rotate. + /// The rotation to apply. + /// The transformed . + public static Vector3 Transform(Vector3 vector, Quaternion rotation) + { + Vector3 result; + Transform(ref vector, ref rotation, out result); + return result; + } + + /// + /// Transforms an array of vectors by the given rotation. + /// + /// The array of vectors to transform. + /// The rotation to apply. + /// The array for which the transformed vectors are stored. + /// This array may be the same array as . + /// Thrown when or is null. + /// Thrown when is shorter in length than . + public static void Transform(Vector3[] source, ref Quaternion rotation, Vector3[] destination) + { + if (source == null) + throw new ArgumentNullException("source"); + if (destination == null) + throw new ArgumentNullException("destination"); + if (destination.Length < source.Length) + throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); + + float x = rotation.X + rotation.X; + float y = rotation.Y + rotation.Y; + float z = rotation.Z + rotation.Z; + float wx = rotation.W * x; + float wy = rotation.W * y; + float wz = rotation.W * z; + float xx = rotation.X * x; + float xy = rotation.X * y; + float xz = rotation.X * z; + float yy = rotation.Y * y; + float yz = rotation.Y * z; + float zz = rotation.Z * z; + + float num1 = ((1.0f - yy) - zz); + float num2 = (xy - wz); + float num3 = (xz + wy); + float num4 = (xy + wz); + float num5 = ((1.0f - xx) - zz); + float num6 = (yz - wx); + float num7 = (xz - wy); + float num8 = (yz + wx); + float num9 = ((1.0f - xx) - yy); + + for (int i = 0; i < source.Length; ++i) + { + destination[i] = new Vector3( + ((source[i].X * num1) + (source[i].Y * num2)) + (source[i].Z * num3), + ((source[i].X * num4) + (source[i].Y * num5)) + (source[i].Z * num6), + ((source[i].X * num7) + (source[i].Y * num8)) + (source[i].Z * num9)); + } + } + + + /// + /// Transforms a 3D vector by the given . + /// + /// The source vector. + /// The transformation . + /// When the method completes, contains the transformed . + public static void Transform(ref Vector3 vector, ref Matrix3x3 transform, out Vector3 result) + { + result = new Vector3( (vector.X * transform.M11) + (vector.Y * transform.M21) + (vector.Z * transform.M31), + (vector.X * transform.M12) + (vector.Y * transform.M22) + (vector.Z * transform.M32), + (vector.X * transform.M13) + (vector.Y * transform.M23) + (vector.Z * transform.M33) + ); + } + + /// + /// Transforms a 3D vector by the given . + /// + /// The source vector. + /// The transformation . + /// The transformed . + public static Vector3 Transform(Vector3 vector, Matrix3x3 transform) + { + Vector3 result; + Transform(ref vector, ref transform, out result); + return result; + } + + /// + /// Transforms a 3D vector by the given . + /// + /// The source vector. + /// The transformation . + /// When the method completes, contains the transformed . + public static void Transform(ref Vector3 vector, ref Matrix transform, out Vector3 result) + { + Vector4 intermediate; + Transform(ref vector, ref transform, out intermediate); + result = (Vector3)intermediate; + } + + /// + /// Transforms a 3D vector by the given . + /// + /// The source vector. + /// The transformation . + /// When the method completes, contains the transformed . + public static void Transform(ref Vector3 vector, ref Matrix transform, out Vector4 result) + { + result = new Vector4( + (vector.X * transform.M11) + (vector.Y * transform.M21) + (vector.Z * transform.M31) + transform.M41, + (vector.X * transform.M12) + (vector.Y * transform.M22) + (vector.Z * transform.M32) + transform.M42, + (vector.X * transform.M13) + (vector.Y * transform.M23) + (vector.Z * transform.M33) + transform.M43, + (vector.X * transform.M14) + (vector.Y * transform.M24) + (vector.Z * transform.M34) + transform.M44); + } + + /// + /// Transforms a 3D vector by the given . + /// + /// The source vector. + /// The transformation . + /// The transformed . + public static Vector4 Transform(Vector3 vector, Matrix transform) + { + Vector4 result; + Transform(ref vector, ref transform, out result); + return result; + } + + /// + /// Transforms an array of 3D vectors by the given . + /// + /// The array of vectors to transform. + /// The transformation . + /// The array for which the transformed vectors are stored. + /// Thrown when or is null. + /// Thrown when is shorter in length than . + public static void Transform(Vector3[] source, ref Matrix transform, Vector4[] destination) + { + if (source == null) + throw new ArgumentNullException("source"); + if (destination == null) + throw new ArgumentNullException("destination"); + if (destination.Length < source.Length) + throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); + + for (int i = 0; i < source.Length; ++i) + { + Transform(ref source[i], ref transform, out destination[i]); + } + } + + /// + /// Performs a coordinate transformation using the given . + /// + /// The coordinate vector to transform. + /// The transformation . + /// When the method completes, contains the transformed coordinates. + /// + /// A coordinate transform performs the transformation with the assumption that the w component + /// is one. The four dimensional vector obtained from the transformation operation has each + /// component in the vector divided by the w component. This forces the w component to be one and + /// therefore makes the vector homogeneous. The homogeneous vector is often preferred when working + /// with coordinates as the w component can safely be ignored. + /// + public static void TransformCoordinate(ref Vector3 coordinate, ref Matrix transform, out Vector3 result) + { + Vector4 vector = new Vector4(); + vector.X = (coordinate.X * transform.M11) + (coordinate.Y * transform.M21) + (coordinate.Z * transform.M31) + transform.M41; + vector.Y = (coordinate.X * transform.M12) + (coordinate.Y * transform.M22) + (coordinate.Z * transform.M32) + transform.M42; + vector.Z = (coordinate.X * transform.M13) + (coordinate.Y * transform.M23) + (coordinate.Z * transform.M33) + transform.M43; + vector.W = 1f / ((coordinate.X * transform.M14) + (coordinate.Y * transform.M24) + (coordinate.Z * transform.M34) + transform.M44); + + result = new Vector3(vector.X * vector.W, vector.Y * vector.W, vector.Z * vector.W); + } + + /// + /// Performs a coordinate transformation using the given . + /// + /// The coordinate vector to transform. + /// The transformation . + /// The transformed coordinates. + /// + /// A coordinate transform performs the transformation with the assumption that the w component + /// is one. The four dimensional vector obtained from the transformation operation has each + /// component in the vector divided by the w component. This forces the w component to be one and + /// therefore makes the vector homogeneous. The homogeneous vector is often preferred when working + /// with coordinates as the w component can safely be ignored. + /// + public static Vector3 TransformCoordinate(Vector3 coordinate, Matrix transform) + { + Vector3 result; + TransformCoordinate(ref coordinate, ref transform, out result); + return result; + } + + /// + /// Performs a coordinate transformation on an array of vectors using the given . + /// + /// The array of coordinate vectors to transform. + /// The transformation . + /// The array for which the transformed vectors are stored. + /// This array may be the same array as . + /// Thrown when or is null. + /// Thrown when is shorter in length than . + /// + /// A coordinate transform performs the transformation with the assumption that the w component + /// is one. The four dimensional vector obtained from the transformation operation has each + /// component in the vector divided by the w component. This forces the w component to be one and + /// therefore makes the vector homogeneous. The homogeneous vector is often preferred when working + /// with coordinates as the w component can safely be ignored. + /// + public static void TransformCoordinate(Vector3[] source, ref Matrix transform, Vector3[] destination) + { + if (source == null) + throw new ArgumentNullException("source"); + if (destination == null) + throw new ArgumentNullException("destination"); + if (destination.Length < source.Length) + throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); + + for (int i = 0; i < source.Length; ++i) + { + TransformCoordinate(ref source[i], ref transform, out destination[i]); + } + } + + /// + /// Performs a normal transformation using the given . + /// + /// The normal vector to transform. + /// The transformation . + /// When the method completes, contains the transformed normal. + /// + /// A normal transform performs the transformation with the assumption that the w component + /// is zero. This causes the fourth row and fourth column of the matrix to be unused. The + /// end result is a vector that is not translated, but all other transformation properties + /// apply. This is often preferred for normal vectors as normals purely represent direction + /// rather than location because normal vectors should not be translated. + /// + public static void TransformNormal(ref Vector3 normal, ref Matrix transform, out Vector3 result) + { + result = new Vector3( + (normal.X * transform.M11) + (normal.Y * transform.M21) + (normal.Z * transform.M31), + (normal.X * transform.M12) + (normal.Y * transform.M22) + (normal.Z * transform.M32), + (normal.X * transform.M13) + (normal.Y * transform.M23) + (normal.Z * transform.M33)); + } + + /// + /// Performs a normal transformation using the given . + /// + /// The normal vector to transform. + /// The transformation . + /// The transformed normal. + /// + /// A normal transform performs the transformation with the assumption that the w component + /// is zero. This causes the fourth row and fourth column of the matrix to be unused. The + /// end result is a vector that is not translated, but all other transformation properties + /// apply. This is often preferred for normal vectors as normals purely represent direction + /// rather than location because normal vectors should not be translated. + /// + public static Vector3 TransformNormal(Vector3 normal, Matrix transform) + { + Vector3 result; + TransformNormal(ref normal, ref transform, out result); + return result; + } + + /// + /// Performs a normal transformation on an array of vectors using the given . + /// + /// The array of normal vectors to transform. + /// The transformation . + /// The array for which the transformed vectors are stored. + /// This array may be the same array as . + /// Thrown when or is null. + /// Thrown when is shorter in length than . + /// + /// A normal transform performs the transformation with the assumption that the w component + /// is zero. This causes the fourth row and fourth column of the matrix to be unused. The + /// end result is a vector that is not translated, but all other transformation properties + /// apply. This is often preferred for normal vectors as normals purely represent direction + /// rather than location because normal vectors should not be translated. + /// + public static void TransformNormal(Vector3[] source, ref Matrix transform, Vector3[] destination) + { + if (source == null) + throw new ArgumentNullException("source"); + if (destination == null) + throw new ArgumentNullException("destination"); + if (destination.Length < source.Length) + throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); + + for (int i = 0; i < source.Length; ++i) + { + TransformNormal(ref source[i], ref transform, out destination[i]); + } + } + + /// + /// Adds two vectors. + /// + /// The first vector to add. + /// The second vector to add. + /// The sum of the two vectors. + public static Vector3 operator +(Vector3 left, Vector3 right) + { + return new Vector3(left.X + right.X, left.Y + right.Y, left.Z + right.Z); + } + + /// + /// Multiplies a vector with another by performing component-wise multiplication equivalent to . + /// + /// The first vector to multiply. + /// The second vector to multiply. + /// The multiplication of the two vectors. + public static Vector3 operator *(Vector3 left, Vector3 right) + { + return new Vector3(left.X * right.X, left.Y * right.Y, left.Z * right.Z); + } + + /// + /// Assert a vector (return it unchanged). + /// + /// The vector to assert (unchanged). + /// The asserted (unchanged) vector. + public static Vector3 operator +(Vector3 value) + { + return value; + } + + /// + /// Subtracts two vectors. + /// + /// The first vector to subtract. + /// The second vector to subtract. + /// The difference of the two vectors. + public static Vector3 operator -(Vector3 left, Vector3 right) + { + return new Vector3(left.X - right.X, left.Y - right.Y, left.Z - right.Z); + } + + /// + /// Reverses the direction of a given vector. + /// + /// The vector to negate. + /// A vector facing in the opposite direction. + public static Vector3 operator -(Vector3 value) + { + return new Vector3(-value.X, -value.Y, -value.Z); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector3 operator *(float scale, Vector3 value) + { + return new Vector3(value.X * scale, value.Y * scale, value.Z * scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector3 operator *(Vector3 value, float scale) + { + return new Vector3(value.X * scale, value.Y * scale, value.Z * scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector3 operator /(Vector3 value, float scale) + { + return new Vector3(value.X / scale, value.Y / scale, value.Z / scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The amount by which to scale the vector. + /// The vector to scale. + /// The scaled vector. + public static Vector3 operator /(float scale, Vector3 value) + { + return new Vector3(scale / value.X, scale / value.Y, scale / value.Z); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector3 operator /(Vector3 value, Vector3 scale) + { + return new Vector3(value.X / scale.X, value.Y / scale.Y, value.Z / scale.Z); + } + + /// + /// Perform a component-wise addition + /// + /// The input vector. + /// The scalar value to be added on elements + /// The vector with added scalar for each element. + public static Vector3 operator +(Vector3 value, float scalar) + { + return new Vector3(value.X + scalar, value.Y + scalar, value.Z + scalar); + } + + /// + /// Perform a component-wise addition + /// + /// The input vector. + /// The scalar value to be added on elements + /// The vector with added scalar for each element. + public static Vector3 operator +(float scalar, Vector3 value) + { + return new Vector3(scalar + value.X, scalar + value.Y, scalar + value.Z); + } + + /// + /// Perform a component-wise subtraction + /// + /// The input vector. + /// The scalar value to be subtraced from elements + /// The vector with added scalar from each element. + public static Vector3 operator -(Vector3 value, float scalar) + { + return new Vector3(value.X - scalar, value.Y - scalar, value.Z - scalar); + } + + /// + /// Perform a component-wise subtraction + /// + /// The input vector. + /// The scalar value to be subtraced from elements + /// The vector with subtraced scalar from each element. + public static Vector3 operator -(float scalar, Vector3 value) + { + return new Vector3(scalar - value.X, scalar - value.Y, scalar - value.Z); + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has the same value as ; otherwise, false. + public static bool operator ==(Vector3 left, Vector3 right) + { + return left.Equals(ref right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has a different value than ; otherwise, false. + public static bool operator !=(Vector3 left, Vector3 right) + { + return !left.Equals(ref right); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Vector2(Vector3 value) + { + return new Vector2(value.X, value.Y); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Vector4(Vector3 value) + { + return new Vector4(value, 0.0f); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2}", X, Y, Z); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// + /// A that represents this instance. + /// + public string ToString(string format) + { + if (format == null) + return ToString(); + + return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2}", X.ToString(format, CultureInfo.CurrentCulture), + Y.ToString(format, CultureInfo.CurrentCulture), Z.ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format(formatProvider, "X:{0} Y:{1} Z:{2}", X, Y, Z); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(string format, IFormatProvider formatProvider) + { + if (format == null) + return ToString(formatProvider); + + return string.Format(formatProvider, "X:{0} Y:{1} Z:{2}", X.ToString(format, formatProvider), + Y.ToString(format, formatProvider), Z.ToString(format, formatProvider)); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + unchecked + { + var hashCode = X.GetHashCode(); + hashCode = (hashCode * 397) ^ Y.GetHashCode(); + hashCode = (hashCode * 397) ^ Z.GetHashCode(); + return hashCode; + } + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(ref Vector3 other) + { + return MathUtil.NearEqual(other.X, X) && MathUtil.NearEqual(other.Y, Y) && MathUtil.NearEqual(other.Z, Z); + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(Vector3 other) + { + return Equals(ref other); + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object value) + { + if (!(value is Vector3)) + return false; + + var strongValue = (Vector3)value; + return Equals(ref strongValue); + } +#if WPFInterop + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator System.Windows.Media.Media3D.Vector3D(Vector3 value) + { + return new System.Windows.Media.Media3D.Vector3D(value.X, value.Y, value.Z); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Vector3(System.Windows.Media.Media3D.Vector3D value) + { + return new Vector3((float)value.X, (float)value.Y, (float)value.Z); + } +#endif + +#if XnaInterop + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Microsoft.Xna.Framework.Vector3(Vector3 value) + { + return new Microsoft.Xna.Framework.Vector3(value.X, value.Y, value.Z); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static implicit operator Vector3(Microsoft.Xna.Framework.Vector3 value) + { + return new Vector3(value.X, value.Y, value.Z); + } +#endif + } +} diff --git a/Source/SharpDX/Vector4.cs b/Source/SharpDX/Mathematics/Vector4.cs similarity index 96% rename from Source/SharpDX/Vector4.cs rename to Source/SharpDX/Mathematics/Vector4.cs index b45699b62..42c93315f 100644 --- a/Source/SharpDX/Vector4.cs +++ b/Source/SharpDX/Mathematics/Vector4.cs @@ -1,1501 +1,1479 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ----------------------------------------------------------------------------- -// Original code from SlimMath project. http://code.google.com/p/slimmath/ -// Greetings to SlimDX Group. Original code published with the following license: -// ----------------------------------------------------------------------------- -/* -* Copyright (c) 2007-2011 SlimDX Group -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ -using System; -using System.Globalization; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Represents a four dimensional mathematical vector. - /// - [StructLayout(LayoutKind.Sequential, Pack = 4)] - [DynamicSerializer("TKV4")] - public struct Vector4 : IEquatable, IFormattable, IDataSerializable - { - /// - /// The size of the type, in bytes. - /// - public static readonly int SizeInBytes = Marshal.SizeOf(typeof(Vector4)); - - /// - /// A with all of its components set to zero. - /// - public static readonly Vector4 Zero = new Vector4(); - - /// - /// The X unit (1, 0, 0, 0). - /// - public static readonly Vector4 UnitX = new Vector4(1.0f, 0.0f, 0.0f, 0.0f); - - /// - /// The Y unit (0, 1, 0, 0). - /// - public static readonly Vector4 UnitY = new Vector4(0.0f, 1.0f, 0.0f, 0.0f); - - /// - /// The Z unit (0, 0, 1, 0). - /// - public static readonly Vector4 UnitZ = new Vector4(0.0f, 0.0f, 1.0f, 0.0f); - - /// - /// The W unit (0, 0, 0, 1). - /// - public static readonly Vector4 UnitW = new Vector4(0.0f, 0.0f, 0.0f, 1.0f); - - /// - /// A with all of its components set to one. - /// - public static readonly Vector4 One = new Vector4(1.0f, 1.0f, 1.0f, 1.0f); - - /// - /// The X component of the vector. - /// - public float X; - - /// - /// The Y component of the vector. - /// - public float Y; - - /// - /// The Z component of the vector. - /// - public float Z; - - /// - /// The W component of the vector. - /// - public float W; - - /// - /// Initializes a new instance of the struct. - /// - /// The value that will be assigned to all components. - public Vector4(float value) - { - X = value; - Y = value; - Z = value; - W = value; - } - - /// - /// Initializes a new instance of the struct. - /// - /// Initial value for the X component of the vector. - /// Initial value for the Y component of the vector. - /// Initial value for the Z component of the vector. - /// Initial value for the W component of the vector. - public Vector4(float x, float y, float z, float w) - { - X = x; - Y = y; - Z = z; - W = w; - } - - /// - /// Initializes a new instance of the struct. - /// - /// A vector containing the values with which to initialize the X, Y, and Z components. - /// Initial value for the W component of the vector. - public Vector4(Vector3 value, float w) - { - X = value.X; - Y = value.Y; - Z = value.Z; - W = w; - } - - /// - /// Initializes a new instance of the struct. - /// - /// A vector containing the values with which to initialize the X and Y components. - /// Initial value for the Z component of the vector. - /// Initial value for the W component of the vector. - public Vector4(Vector2 value, float z, float w) - { - X = value.X; - Y = value.Y; - Z = z; - W = w; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The values to assign to the X, Y, Z, and W components of the vector. This must be an array with four elements. - /// Thrown when is null. - /// Thrown when contains more or less than four elements. - public Vector4(float[] values) - { - if (values == null) - throw new ArgumentNullException("values"); - if (values.Length != 4) - throw new ArgumentOutOfRangeException("values", "There must be four and only four input values for Vector4."); - - X = values[0]; - Y = values[1]; - Z = values[2]; - W = values[3]; - } - - /// - /// Gets a value indicting whether this instance is normalized. - /// - public bool IsNormalized - { - get { return MathUtil.IsOne((X * X) + (Y * Y) + (Z * Z) + (W * W)); } - } - - /// - /// Gets a value indicting whether this vector is zero - /// - public bool IsZero - { - get { return X == 0 && Y == 0 && Z == 0 && W == 0; } - } - - /// - /// Gets or sets the component at the specified index. - /// - /// The value of the X, Y, Z, or W component, depending on the index. - /// The index of the component to access. Use 0 for the X component, 1 for the Y component, 2 for the Z component, and 3 for the W component. - /// The value of the component at the specified index. - /// Thrown when the is out of the range [0, 3]. - public float this[int index] - { - get - { - switch (index) - { - case 0: return X; - case 1: return Y; - case 2: return Z; - case 3: return W; - } - - throw new ArgumentOutOfRangeException("index", "Indices for Vector4 run from 0 to 3, inclusive."); - } - - set - { - switch (index) - { - case 0: X = value; break; - case 1: Y = value; break; - case 2: Z = value; break; - case 3: W = value; break; - default: throw new ArgumentOutOfRangeException("index", "Indices for Vector4 run from 0 to 3, inclusive."); - } - } - } - - /// - /// Calculates the length of the vector. - /// - /// The length of the vector. - /// - /// may be preferred when only the relative length is needed - /// and speed is of the essence. - /// - public float Length() - { - return (float)Math.Sqrt((X * X) + (Y * Y) + (Z * Z) + (W * W)); - } - - /// - /// Calculates the squared length of the vector. - /// - /// The squared length of the vector. - /// - /// This method may be preferred to when only a relative length is needed - /// and speed is of the essence. - /// - public float LengthSquared() - { - return (X * X) + (Y * Y) + (Z * Z) + (W * W); - } - - /// - /// Converts the vector into a unit vector. - /// - public void Normalize() - { - float length = Length(); - if (!MathUtil.IsZero(length)) - { - float inverse = 1.0f / length; - X *= inverse; - Y *= inverse; - Z *= inverse; - W *= inverse; - } - } - - /// - /// Creates an array containing the elements of the vector. - /// - /// A four-element array containing the components of the vector. - public float[] ToArray() - { - return new float[] { X, Y, Z, W }; - } - - /// - /// Adds two vectors. - /// - /// The first vector to add. - /// The second vector to add. - /// When the method completes, contains the sum of the two vectors. - public static void Add(ref Vector4 left, ref Vector4 right, out Vector4 result) - { - result = new Vector4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W); - } - - /// - /// Adds two vectors. - /// - /// The first vector to add. - /// The second vector to add. - /// The sum of the two vectors. - public static Vector4 Add(Vector4 left, Vector4 right) - { - return new Vector4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W); - } - - /// - /// Perform a component-wise addition - /// - /// The input vector - /// The scalar value to be added to elements - /// The vector with added scalar for each element. - public static void Add(ref Vector4 left, ref float right, out Vector4 result) - { - result = new Vector4(left.X + right, left.Y + right, left.Z + right, left.W + right); - } - - /// - /// Perform a component-wise addition - /// - /// The input vector - /// The scalar value to be added to elements - /// The vector with added scalar for each element. - public static Vector4 Add(Vector4 left, float right) - { - return new Vector4(left.X + right, left.Y + right, left.Z + right, left.W + right); - } - - /// - /// Subtracts two vectors. - /// - /// The first vector to subtract. - /// The second vector to subtract. - /// When the method completes, contains the difference of the two vectors. - public static void Subtract(ref Vector4 left, ref Vector4 right, out Vector4 result) - { - result = new Vector4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W); - } - - /// - /// Subtracts two vectors. - /// - /// The first vector to subtract. - /// The second vector to subtract. - /// The difference of the two vectors. - public static Vector4 Subtract(Vector4 left, Vector4 right) - { - return new Vector4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W); - } - - /// - /// Perform a component-wise subtraction - /// - /// The input vector - /// The scalar value to be subtraced from elements - /// The vector with subtracted scalar for each element. - public static void Subtract(ref Vector4 left, ref float right, out Vector4 result) - { - result = new Vector4(left.X - right, left.Y - right, left.Z - right, left.W - right); - } - - /// - /// Perform a component-wise subtraction - /// - /// The input vector - /// The scalar value to be subtraced from elements - /// The vector with subtracted scalar for each element. - public static Vector4 Subtract(Vector4 left, float right) - { - return new Vector4(left.X - right, left.Y - right, left.Z - right, left.W - right); - } - - /// - /// Perform a component-wise subtraction - /// - /// The scalar value to be subtraced from elements - /// The input vector. - /// The vector with subtracted scalar for each element. - public static void Subtract(ref float left, ref Vector4 right, out Vector4 result) - { - result = new Vector4(left - right.X, left - right.Y, left - right.Z, left - right.W); - } - - /// - /// Perform a component-wise subtraction - /// - /// The scalar value to be subtraced from elements - /// The input vector. - /// The vector with subtracted scalar for each element. - public static Vector4 Subtract(float left, Vector4 right) - { - return new Vector4(left - right.X, left - right.Y, left - right.Z, left - right.W); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// When the method completes, contains the scaled vector. - public static void Multiply(ref Vector4 value, float scale, out Vector4 result) - { - result = new Vector4(value.X * scale, value.Y * scale, value.Z * scale, value.W * scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector4 Multiply(Vector4 value, float scale) - { - return new Vector4(value.X * scale, value.Y * scale, value.Z * scale, value.W * scale); - } - - /// - /// Multiplies a vector with another by performing component-wise multiplication. - /// - /// The first vector to multiply. - /// The second vector to multiply. - /// When the method completes, contains the multiplied vector. - public static void Multiply(ref Vector4 left, ref Vector4 right, out Vector4 result) - { - result = new Vector4(left.X * right.X, left.Y * right.Y, left.Z * right.Z, left.W * right.W); - } - - /// - /// Multiplies a vector with another by performing component-wise multiplication. - /// - /// The first vector to multiply. - /// The second vector to multiply. - /// The multiplied vector. - public static Vector4 Multiply(Vector4 left, Vector4 right) - { - return new Vector4(left.X * right.X, left.Y * right.Y, left.Z * right.Z, left.W * right.W); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// When the method completes, contains the scaled vector. - public static void Divide(ref Vector4 value, float scale, out Vector4 result) - { - result = new Vector4(value.X / scale, value.Y / scale, value.Z / scale, value.W / scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector4 Divide(Vector4 value, float scale) - { - return new Vector4(value.X / scale, value.Y / scale, value.Z / scale, value.W / scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The amount by which to scale the vector. - /// The vector to scale. - /// When the method completes, contains the scaled vector. - public static void Divide(float scale, ref Vector4 value, out Vector4 result) - { - result = new Vector4(scale / value.X, scale / value.Y, scale / value.Z, scale / value.W); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector4 Divide(float scale, Vector4 value) - { - return new Vector4(scale / value.X, scale / value.Y, scale / value.Z, scale / value.W); - } - - /// - /// Reverses the direction of a given vector. - /// - /// The vector to negate. - /// When the method completes, contains a vector facing in the opposite direction. - public static void Negate(ref Vector4 value, out Vector4 result) - { - result = new Vector4(-value.X, -value.Y, -value.Z, -value.W); - } - - /// - /// Reverses the direction of a given vector. - /// - /// The vector to negate. - /// A vector facing in the opposite direction. - public static Vector4 Negate(Vector4 value) - { - return new Vector4(-value.X, -value.Y, -value.Z, -value.W); - } - - /// - /// Returns a containing the 4D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 4D triangle. - /// - /// A containing the 4D Cartesian coordinates of vertex 1 of the triangle. - /// A containing the 4D Cartesian coordinates of vertex 2 of the triangle. - /// A containing the 4D Cartesian coordinates of vertex 3 of the triangle. - /// Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). - /// Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). - /// When the method completes, contains the 4D Cartesian coordinates of the specified point. - public static void Barycentric(ref Vector4 value1, ref Vector4 value2, ref Vector4 value3, float amount1, float amount2, out Vector4 result) - { - result = new Vector4((value1.X + (amount1 * (value2.X - value1.X))) + (amount2 * (value3.X - value1.X)), - (value1.Y + (amount1 * (value2.Y - value1.Y))) + (amount2 * (value3.Y - value1.Y)), - (value1.Z + (amount1 * (value2.Z - value1.Z))) + (amount2 * (value3.Z - value1.Z)), - (value1.W + (amount1 * (value2.W - value1.W))) + (amount2 * (value3.W - value1.W))); - } - - /// - /// Returns a containing the 4D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 4D triangle. - /// - /// A containing the 4D Cartesian coordinates of vertex 1 of the triangle. - /// A containing the 4D Cartesian coordinates of vertex 2 of the triangle. - /// A containing the 4D Cartesian coordinates of vertex 3 of the triangle. - /// Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). - /// Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). - /// A new containing the 4D Cartesian coordinates of the specified point. - public static Vector4 Barycentric(Vector4 value1, Vector4 value2, Vector4 value3, float amount1, float amount2) - { - Vector4 result; - Barycentric(ref value1, ref value2, ref value3, amount1, amount2, out result); - return result; - } - - /// - /// Restricts a value to be within a specified range. - /// - /// The value to clamp. - /// The minimum value. - /// The maximum value. - /// When the method completes, contains the clamped value. - public static void Clamp(ref Vector4 value, ref Vector4 min, ref Vector4 max, out Vector4 result) - { - float x = value.X; - x = (x > max.X) ? max.X : x; - x = (x < min.X) ? min.X : x; - - float y = value.Y; - y = (y > max.Y) ? max.Y : y; - y = (y < min.Y) ? min.Y : y; - - float z = value.Z; - z = (z > max.Z) ? max.Z : z; - z = (z < min.Z) ? min.Z : z; - - float w = value.W; - w = (w > max.W) ? max.W : w; - w = (w < min.W) ? min.W : w; - - result = new Vector4(x, y, z, w); - } - - /// - /// Restricts a value to be within a specified range. - /// - /// The value to clamp. - /// The minimum value. - /// The maximum value. - /// The clamped value. - public static Vector4 Clamp(Vector4 value, Vector4 min, Vector4 max) - { - Vector4 result; - Clamp(ref value, ref min, ref max, out result); - return result; - } - - /// - /// Calculates the distance between two vectors. - /// - /// The first vector. - /// The second vector. - /// When the method completes, contains the distance between the two vectors. - /// - /// may be preferred when only the relative distance is needed - /// and speed is of the essence. - /// - public static void Distance(ref Vector4 value1, ref Vector4 value2, out float result) - { - float x = value1.X - value2.X; - float y = value1.Y - value2.Y; - float z = value1.Z - value2.Z; - float w = value1.W - value2.W; - - result = (float)Math.Sqrt((x * x) + (y * y) + (z * z) + (w * w)); - } - - /// - /// Calculates the distance between two vectors. - /// - /// The first vector. - /// The second vector. - /// The distance between the two vectors. - /// - /// may be preferred when only the relative distance is needed - /// and speed is of the essence. - /// - public static float Distance(Vector4 value1, Vector4 value2) - { - float x = value1.X - value2.X; - float y = value1.Y - value2.Y; - float z = value1.Z - value2.Z; - float w = value1.W - value2.W; - - return (float)Math.Sqrt((x * x) + (y * y) + (z * z) + (w * w)); - } - - /// - /// Calculates the squared distance between two vectors. - /// - /// The first vector. - /// The second vector. - /// When the method completes, contains the squared distance between the two vectors. - /// Distance squared is the value before taking the square root. - /// Distance squared can often be used in place of distance if relative comparisons are being made. - /// For example, consider three points A, B, and C. To determine whether B or C is further from A, - /// compare the distance between A and B to the distance between A and C. Calculating the two distances - /// involves two square roots, which are computationally expensive. However, using distance squared - /// provides the same information and avoids calculating two square roots. - /// - public static void DistanceSquared(ref Vector4 value1, ref Vector4 value2, out float result) - { - float x = value1.X - value2.X; - float y = value1.Y - value2.Y; - float z = value1.Z - value2.Z; - float w = value1.W - value2.W; - - result = (x * x) + (y * y) + (z * z) + (w * w); - } - - /// - /// Calculates the squared distance between two vectors. - /// - /// The first vector. - /// The second vector. - /// The squared distance between the two vectors. - /// Distance squared is the value before taking the square root. - /// Distance squared can often be used in place of distance if relative comparisons are being made. - /// For example, consider three points A, B, and C. To determine whether B or C is further from A, - /// compare the distance between A and B to the distance between A and C. Calculating the two distances - /// involves two square roots, which are computationally expensive. However, using distance squared - /// provides the same information and avoids calculating two square roots. - /// - public static float DistanceSquared(Vector4 value1, Vector4 value2) - { - float x = value1.X - value2.X; - float y = value1.Y - value2.Y; - float z = value1.Z - value2.Z; - float w = value1.W - value2.W; - - return (x * x) + (y * y) + (z * z) + (w * w); - } - - /// - /// Calculates the dot product of two vectors. - /// - /// First source vector - /// Second source vector. - /// When the method completes, contains the dot product of the two vectors. - public static void Dot(ref Vector4 left, ref Vector4 right, out float result) - { - result = (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z) + (left.W * right.W); - } - - /// - /// Calculates the dot product of two vectors. - /// - /// First source vector. - /// Second source vector. - /// The dot product of the two vectors. - public static float Dot(Vector4 left, Vector4 right) - { - return (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z) + (left.W * right.W); - } - - /// - /// Converts the vector into a unit vector. - /// - /// The vector to normalize. - /// When the method completes, contains the normalized vector. - public static void Normalize(ref Vector4 value, out Vector4 result) - { - Vector4 temp = value; - result = temp; - result.Normalize(); - } - - /// - /// Converts the vector into a unit vector. - /// - /// The vector to normalize. - /// The normalized vector. - public static Vector4 Normalize(Vector4 value) - { - value.Normalize(); - return value; - } - - /// - /// Performs a linear interpolation between two vectors. - /// - /// Start vector. - /// End vector. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the linear interpolation of the two vectors. - /// - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static void Lerp(ref Vector4 start, ref Vector4 end, float amount, out Vector4 result) - { - result.X = MathUtil.Lerp(start.X, end.X, amount); - result.Y = MathUtil.Lerp(start.Y, end.Y, amount); - result.Z = MathUtil.Lerp(start.Z, end.Z, amount); - result.W = MathUtil.Lerp(start.W, end.W, amount); - } - - /// - /// Performs a linear interpolation between two vectors. - /// - /// Start vector. - /// End vector. - /// Value between 0 and 1 indicating the weight of . - /// The linear interpolation of the two vectors. - /// - /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. - /// - public static Vector4 Lerp(Vector4 start, Vector4 end, float amount) - { - Vector4 result; - Lerp(ref start, ref end, amount, out result); - return result; - } - - /// - /// Performs a cubic interpolation between two vectors. - /// - /// Start vector. - /// End vector. - /// Value between 0 and 1 indicating the weight of . - /// When the method completes, contains the cubic interpolation of the two vectors. - public static void SmoothStep(ref Vector4 start, ref Vector4 end, float amount, out Vector4 result) - { - amount = MathUtil.SmoothStep(amount); - Lerp(ref start, ref end, amount, out result); - } - - /// - /// Performs a cubic interpolation between two vectors. - /// - /// Start vector. - /// End vector. - /// Value between 0 and 1 indicating the weight of . - /// The cubic interpolation of the two vectors. - public static Vector4 SmoothStep(Vector4 start, Vector4 end, float amount) - { - Vector4 result; - SmoothStep(ref start, ref end, amount, out result); - return result; - } - - /// - /// Performs a Hermite spline interpolation. - /// - /// First source position vector. - /// First source tangent vector. - /// Second source position vector. - /// Second source tangent vector. - /// Weighting factor. - /// When the method completes, contains the result of the Hermite spline interpolation. - public static void Hermite(ref Vector4 value1, ref Vector4 tangent1, ref Vector4 value2, ref Vector4 tangent2, float amount, out Vector4 result) - { - float squared = amount * amount; - float cubed = amount * squared; - float part1 = ((2.0f * cubed) - (3.0f * squared)) + 1.0f; - float part2 = (-2.0f * cubed) + (3.0f * squared); - float part3 = (cubed - (2.0f * squared)) + amount; - float part4 = cubed - squared; - - result = new Vector4((((value1.X * part1) + (value2.X * part2)) + (tangent1.X * part3)) + (tangent2.X * part4), - (((value1.Y * part1) + (value2.Y * part2)) + (tangent1.Y * part3)) + (tangent2.Y * part4), - (((value1.Z * part1) + (value2.Z * part2)) + (tangent1.Z * part3)) + (tangent2.Z * part4), - (((value1.W * part1) + (value2.W * part2)) + (tangent1.W * part3)) + (tangent2.W * part4)); - } - - /// - /// Performs a Hermite spline interpolation. - /// - /// First source position vector. - /// First source tangent vector. - /// Second source position vector. - /// Second source tangent vector. - /// Weighting factor. - /// The result of the Hermite spline interpolation. - public static Vector4 Hermite(Vector4 value1, Vector4 tangent1, Vector4 value2, Vector4 tangent2, float amount) - { - Vector4 result; - Hermite(ref value1, ref tangent1, ref value2, ref tangent2, amount, out result); - return result; - } - - /// - /// Performs a Catmull-Rom interpolation using the specified positions. - /// - /// The first position in the interpolation. - /// The second position in the interpolation. - /// The third position in the interpolation. - /// The fourth position in the interpolation. - /// Weighting factor. - /// When the method completes, contains the result of the Catmull-Rom interpolation. - public static void CatmullRom(ref Vector4 value1, ref Vector4 value2, ref Vector4 value3, ref Vector4 value4, float amount, out Vector4 result) - { - float squared = amount * amount; - float cubed = amount * squared; - - result.X = 0.5f * ((((2.0f * value2.X) + ((-value1.X + value3.X) * amount)) + (((((2.0f * value1.X) - (5.0f * value2.X)) + (4.0f * value3.X)) - value4.X) * squared)) + ((((-value1.X + (3.0f * value2.X)) - (3.0f * value3.X)) + value4.X) * cubed)); - result.Y = 0.5f * ((((2.0f * value2.Y) + ((-value1.Y + value3.Y) * amount)) + (((((2.0f * value1.Y) - (5.0f * value2.Y)) + (4.0f * value3.Y)) - value4.Y) * squared)) + ((((-value1.Y + (3.0f * value2.Y)) - (3.0f * value3.Y)) + value4.Y) * cubed)); - result.Z = 0.5f * ((((2.0f * value2.Z) + ((-value1.Z + value3.Z) * amount)) + (((((2.0f * value1.Z) - (5.0f * value2.Z)) + (4.0f * value3.Z)) - value4.Z) * squared)) + ((((-value1.Z + (3.0f * value2.Z)) - (3.0f * value3.Z)) + value4.Z) * cubed)); - result.W = 0.5f * ((((2.0f * value2.W) + ((-value1.W + value3.W) * amount)) + (((((2.0f * value1.W) - (5.0f * value2.W)) + (4.0f * value3.W)) - value4.W) * squared)) + ((((-value1.W + (3.0f * value2.W)) - (3.0f * value3.W)) + value4.W) * cubed)); - } - - /// - /// Performs a Catmull-Rom interpolation using the specified positions. - /// - /// The first position in the interpolation. - /// The second position in the interpolation. - /// The third position in the interpolation. - /// The fourth position in the interpolation. - /// Weighting factor. - /// A vector that is the result of the Catmull-Rom interpolation. - public static Vector4 CatmullRom(Vector4 value1, Vector4 value2, Vector4 value3, Vector4 value4, float amount) - { - Vector4 result; - CatmullRom(ref value1, ref value2, ref value3, ref value4, amount, out result); - return result; - } - - /// - /// Returns a vector containing the largest components of the specified vectors. - /// - /// The first source vector. - /// The second source vector. - /// When the method completes, contains an new vector composed of the largest components of the source vectors. - public static void Max(ref Vector4 left, ref Vector4 right, out Vector4 result) - { - result.X = (left.X > right.X) ? left.X : right.X; - result.Y = (left.Y > right.Y) ? left.Y : right.Y; - result.Z = (left.Z > right.Z) ? left.Z : right.Z; - result.W = (left.W > right.W) ? left.W : right.W; - } - - /// - /// Returns a vector containing the largest components of the specified vectors. - /// - /// The first source vector. - /// The second source vector. - /// A vector containing the largest components of the source vectors. - public static Vector4 Max(Vector4 left, Vector4 right) - { - Vector4 result; - Max(ref left, ref right, out result); - return result; - } - - /// - /// Returns a vector containing the smallest components of the specified vectors. - /// - /// The first source vector. - /// The second source vector. - /// When the method completes, contains an new vector composed of the smallest components of the source vectors. - public static void Min(ref Vector4 left, ref Vector4 right, out Vector4 result) - { - result.X = (left.X < right.X) ? left.X : right.X; - result.Y = (left.Y < right.Y) ? left.Y : right.Y; - result.Z = (left.Z < right.Z) ? left.Z : right.Z; - result.W = (left.W < right.W) ? left.W : right.W; - } - - /// - /// Returns a vector containing the smallest components of the specified vectors. - /// - /// The first source vector. - /// The second source vector. - /// A vector containing the smallest components of the source vectors. - public static Vector4 Min(Vector4 left, Vector4 right) - { - Vector4 result; - Min(ref left, ref right, out result); - return result; - } - - /// - /// Orthogonalizes a list of vectors. - /// - /// The list of orthogonalized vectors. - /// The list of vectors to orthogonalize. - /// - /// Orthogonalization is the process of making all vectors orthogonal to each other. This - /// means that any given vector in the list will be orthogonal to any other given vector in the - /// list. - /// Because this method uses the modified Gram-Schmidt process, the resulting vectors - /// tend to be numerically unstable. The numeric stability decreases according to the vectors - /// position in the list so that the first vector is the most stable and the last vector is the - /// least stable. - /// - /// Thrown when or is null. - /// Thrown when is shorter in length than . - public static void Orthogonalize(Vector4[] destination, params Vector4[] source) - { - //Uses the modified Gram-Schmidt process. - //q1 = m1 - //q2 = m2 - ((q1 ⋅ m2) / (q1 ⋅ q1)) * q1 - //q3 = m3 - ((q1 ⋅ m3) / (q1 ⋅ q1)) * q1 - ((q2 ⋅ m3) / (q2 ⋅ q2)) * q2 - //q4 = m4 - ((q1 ⋅ m4) / (q1 ⋅ q1)) * q1 - ((q2 ⋅ m4) / (q2 ⋅ q2)) * q2 - ((q3 ⋅ m4) / (q3 ⋅ q3)) * q3 - //q5 = ... - - if (source == null) - throw new ArgumentNullException("source"); - if (destination == null) - throw new ArgumentNullException("destination"); - if (destination.Length < source.Length) - throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); - - for (int i = 0; i < source.Length; ++i) - { - Vector4 newvector = source[i]; - - for (int r = 0; r < i; ++r) - { - newvector -= (Vector4.Dot(destination[r], newvector) / Vector4.Dot(destination[r], destination[r])) * destination[r]; - } - - destination[i] = newvector; - } - } - - /// - /// Orthonormalizes a list of vectors. - /// - /// The list of orthonormalized vectors. - /// The list of vectors to orthonormalize. - /// - /// Orthonormalization is the process of making all vectors orthogonal to each - /// other and making all vectors of unit length. This means that any given vector will - /// be orthogonal to any other given vector in the list. - /// Because this method uses the modified Gram-Schmidt process, the resulting vectors - /// tend to be numerically unstable. The numeric stability decreases according to the vectors - /// position in the list so that the first vector is the most stable and the last vector is the - /// least stable. - /// - /// Thrown when or is null. - /// Thrown when is shorter in length than . - public static void Orthonormalize(Vector4[] destination, params Vector4[] source) - { - //Uses the modified Gram-Schmidt process. - //Because we are making unit vectors, we can optimize the math for orthogonalization - //and simplify the projection operation to remove the division. - //q1 = m1 / |m1| - //q2 = (m2 - (q1 ⋅ m2) * q1) / |m2 - (q1 ⋅ m2) * q1| - //q3 = (m3 - (q1 ⋅ m3) * q1 - (q2 ⋅ m3) * q2) / |m3 - (q1 ⋅ m3) * q1 - (q2 ⋅ m3) * q2| - //q4 = (m4 - (q1 ⋅ m4) * q1 - (q2 ⋅ m4) * q2 - (q3 ⋅ m4) * q3) / |m4 - (q1 ⋅ m4) * q1 - (q2 ⋅ m4) * q2 - (q3 ⋅ m4) * q3| - //q5 = ... - - if (source == null) - throw new ArgumentNullException("source"); - if (destination == null) - throw new ArgumentNullException("destination"); - if (destination.Length < source.Length) - throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); - - for (int i = 0; i < source.Length; ++i) - { - Vector4 newvector = source[i]; - - for (int r = 0; r < i; ++r) - { - newvector -= Vector4.Dot(destination[r], newvector) * destination[r]; - } - - newvector.Normalize(); - destination[i] = newvector; - } - } - - /// - /// Transforms a 4D vector by the given rotation. - /// - /// The vector to rotate. - /// The rotation to apply. - /// When the method completes, contains the transformed . - public static void Transform(ref Vector4 vector, ref Quaternion rotation, out Vector4 result) - { - float x = rotation.X + rotation.X; - float y = rotation.Y + rotation.Y; - float z = rotation.Z + rotation.Z; - float wx = rotation.W * x; - float wy = rotation.W * y; - float wz = rotation.W * z; - float xx = rotation.X * x; - float xy = rotation.X * y; - float xz = rotation.X * z; - float yy = rotation.Y * y; - float yz = rotation.Y * z; - float zz = rotation.Z * z; - - result = new Vector4( - ((vector.X * ((1.0f - yy) - zz)) + (vector.Y * (xy - wz))) + (vector.Z * (xz + wy)), - ((vector.X * (xy + wz)) + (vector.Y * ((1.0f - xx) - zz))) + (vector.Z * (yz - wx)), - ((vector.X * (xz - wy)) + (vector.Y * (yz + wx))) + (vector.Z * ((1.0f - xx) - yy)), - vector.W); - } - - /// - /// Transforms a 4D vector by the given rotation. - /// - /// The vector to rotate. - /// The rotation to apply. - /// The transformed . - public static Vector4 Transform(Vector4 vector, Quaternion rotation) - { - Vector4 result; - Transform(ref vector, ref rotation, out result); - return result; - } - - /// - /// Transforms an array of vectors by the given rotation. - /// - /// The array of vectors to transform. - /// The rotation to apply. - /// The array for which the transformed vectors are stored. - /// This array may be the same array as . - /// Thrown when or is null. - /// Thrown when is shorter in length than . - public static void Transform(Vector4[] source, ref Quaternion rotation, Vector4[] destination) - { - if (source == null) - throw new ArgumentNullException("source"); - if (destination == null) - throw new ArgumentNullException("destination"); - if (destination.Length < source.Length) - throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); - - float x = rotation.X + rotation.X; - float y = rotation.Y + rotation.Y; - float z = rotation.Z + rotation.Z; - float wx = rotation.W * x; - float wy = rotation.W * y; - float wz = rotation.W * z; - float xx = rotation.X * x; - float xy = rotation.X * y; - float xz = rotation.X * z; - float yy = rotation.Y * y; - float yz = rotation.Y * z; - float zz = rotation.Z * z; - - float num1 = ((1.0f - yy) - zz); - float num2 = (xy - wz); - float num3 = (xz + wy); - float num4 = (xy + wz); - float num5 = ((1.0f - xx) - zz); - float num6 = (yz - wx); - float num7 = (xz - wy); - float num8 = (yz + wx); - float num9 = ((1.0f - xx) - yy); - - for (int i = 0; i < source.Length; ++i) - { - destination[i] = new Vector4( - ((source[i].X * num1) + (source[i].Y * num2)) + (source[i].Z * num3), - ((source[i].X * num4) + (source[i].Y * num5)) + (source[i].Z * num6), - ((source[i].X * num7) + (source[i].Y * num8)) + (source[i].Z * num9), - source[i].W); - } - } - - /// - /// Transforms a 4D vector by the given . - /// - /// The source vector. - /// The transformation . - /// When the method completes, contains the transformed . - public static void Transform(ref Vector4 vector, ref Matrix transform, out Vector4 result) - { - result = new Vector4( - (vector.X * transform.M11) + (vector.Y * transform.M21) + (vector.Z * transform.M31) + (vector.W * transform.M41), - (vector.X * transform.M12) + (vector.Y * transform.M22) + (vector.Z * transform.M32) + (vector.W * transform.M42), - (vector.X * transform.M13) + (vector.Y * transform.M23) + (vector.Z * transform.M33) + (vector.W * transform.M43), - (vector.X * transform.M14) + (vector.Y * transform.M24) + (vector.Z * transform.M34) + (vector.W * transform.M44)); - } - - /// - /// Transforms a 4D vector by the given . - /// - /// The source vector. - /// The transformation . - /// The transformed . - public static Vector4 Transform(Vector4 vector, Matrix transform) - { - Vector4 result; - Transform(ref vector, ref transform, out result); - return result; - } - - /// - /// Transforms a 4D vector by the given . - /// - /// The source vector. - /// The transformation . - /// When the method completes, contains the transformed . - public static void Transform(ref Vector4 vector, ref Matrix5x4 transform, out Vector4 result) - { - result = new Vector4( - (vector.X * transform.M11) + (vector.Y * transform.M21) + (vector.Z * transform.M31) + (vector.W * transform.M41) + transform.M51, - (vector.X * transform.M12) + (vector.Y * transform.M22) + (vector.Z * transform.M32) + (vector.W * transform.M42) + transform.M52, - (vector.X * transform.M13) + (vector.Y * transform.M23) + (vector.Z * transform.M33) + (vector.W * transform.M43) + transform.M53, - (vector.X * transform.M14) + (vector.Y * transform.M24) + (vector.Z * transform.M34) + (vector.W * transform.M44) + transform.M54); - } - - /// - /// Transforms a 4D vector by the given . - /// - /// The source vector. - /// The transformation . - /// The transformed . - public static Vector4 Transform(Vector4 vector, Matrix5x4 transform) - { - Vector4 result; - Transform(ref vector, ref transform, out result); - return result; - } - - /// - /// Transforms an array of 4D vectors by the given . - /// - /// The array of vectors to transform. - /// The transformation . - /// The array for which the transformed vectors are stored. - /// This array may be the same array as . - /// Thrown when or is null. - /// Thrown when is shorter in length than . - public static void Transform(Vector4[] source, ref Matrix transform, Vector4[] destination) - { - if (source == null) - throw new ArgumentNullException("source"); - if (destination == null) - throw new ArgumentNullException("destination"); - if (destination.Length < source.Length) - throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); - - for (int i = 0; i < source.Length; ++i) - { - Transform(ref source[i], ref transform, out destination[i]); - } - } - - /// - /// Adds two vectors. - /// - /// The first vector to add. - /// The second vector to add. - /// The sum of the two vectors. - public static Vector4 operator +(Vector4 left, Vector4 right) - { - return new Vector4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W); - } - - /// - /// Multiplies a vector with another by performing component-wise multiplication equivalent to . - /// - /// The first vector to multiply. - /// The second vector to multiply. - /// The multiplication of the two vectors. - public static Vector4 operator *(Vector4 left, Vector4 right) - { - return new Vector4(left.X * right.X, left.Y * right.Y, left.Z * right.Z, left.W * right.W); - } - - /// - /// Assert a vector (return it unchanged). - /// - /// The vector to assert (unchanged). - /// The asserted (unchanged) vector. - public static Vector4 operator +(Vector4 value) - { - return value; - } - - /// - /// Subtracts two vectors. - /// - /// The first vector to subtract. - /// The second vector to subtract. - /// The difference of the two vectors. - public static Vector4 operator -(Vector4 left, Vector4 right) - { - return new Vector4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W); - } - - /// - /// Reverses the direction of a given vector. - /// - /// The vector to negate. - /// A vector facing in the opposite direction. - public static Vector4 operator -(Vector4 value) - { - return new Vector4(-value.X, -value.Y, -value.Z, -value.W); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector4 operator *(float scale, Vector4 value) - { - return new Vector4(value.X * scale, value.Y * scale, value.Z * scale, value.W * scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector4 operator *(Vector4 value, float scale) - { - return new Vector4(value.X * scale, value.Y * scale, value.Z * scale, value.W * scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector4 operator /(Vector4 value, float scale) - { - return new Vector4(value.X / scale, value.Y / scale, value.Z / scale, value.W / scale); - } - - /// - /// Scales a vector by the given value. - /// - /// The amount by which to scale the vector. - /// The vector to scale. - /// The scaled vector. - public static Vector4 operator /(float scale,Vector4 value) - { - return new Vector4(scale / value.X, scale / value.Y, scale / value.Z, scale / value.W); - } - - /// - /// Scales a vector by the given value. - /// - /// The vector to scale. - /// The amount by which to scale the vector. - /// The scaled vector. - public static Vector4 operator /(Vector4 value, Vector4 scale) - { - return new Vector4(value.X / scale.X, value.Y / scale.Y, value.Z / scale.Z, value.W / scale.W); - } - - /// - /// Perform a component-wise addition - /// - /// The input vector. - /// The scalar value to be added on elements - /// The vector with added scalar for each element. - public static Vector4 operator +(Vector4 value, float scalar) - { - return new Vector4(value.X + scalar, value.Y + scalar, value.Z + scalar, value.W + scalar); - } - - /// - /// Perform a component-wise addition - /// - /// The input vector. - /// The scalar value to be added on elements - /// The vector with added scalar for each element. - public static Vector4 operator +(float scalar, Vector4 value) - { - return new Vector4(scalar + value.X, scalar + value.Y, scalar + value.Z, scalar + value.W); - } - - /// - /// Perform a component-wise subtraction - /// - /// The input vector. - /// The scalar value to be subtraced from elements - /// The vector with subtraced scalar from each element. - public static Vector4 operator -(Vector4 value, float scalar) - { - return new Vector4(value.X - scalar, value.Y - scalar, value.Z - scalar, value.W - scalar); - } - - /// - /// Perform a component-wise subtraction - /// - /// The input vector. - /// The scalar value to be subtraced from elements - /// The vector with subtraced scalar from each element. - public static Vector4 operator -(float scalar, Vector4 value) - { - return new Vector4(scalar - value.X, scalar - value.Y, scalar - value.Z, scalar - value.W); - } - - /// - /// Tests for equality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has the same value as ; otherwise, false. - public static bool operator ==(Vector4 left, Vector4 right) - { - return left.Equals(ref right); - } - - /// - /// Tests for inequality between two objects. - /// - /// The first value to compare. - /// The second value to compare. - /// true if has a different value than ; otherwise, false. - public static bool operator !=(Vector4 left, Vector4 right) - { - return !left.Equals(ref right); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Vector2(Vector4 value) - { - return new Vector2(value.X, value.Y); - } - - /// - /// Performs an explicit conversion from to . - /// - /// The value. - /// The result of the conversion. - public static explicit operator Vector3(Vector4 value) - { - return new Vector3(value.X, value.Y, value.Z); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// - /// A that represents this instance. - /// - public string ToString(string format) - { - if (format == null) - return ToString(); - - return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2} W:{3}", X.ToString(format, CultureInfo.CurrentCulture), - Y.ToString(format, CultureInfo.CurrentCulture), Z.ToString(format, CultureInfo.CurrentCulture), W.ToString(format, CultureInfo.CurrentCulture)); - } - - /// - /// Returns a that represents this instance. - /// - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(IFormatProvider formatProvider) - { - return string.Format(formatProvider, "X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W); - } - - /// - /// Returns a that represents this instance. - /// - /// The format. - /// The format provider. - /// - /// A that represents this instance. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - if (format == null) - ToString(formatProvider); - - return string.Format(formatProvider, "X:{0} Y:{1} Z:{2} W:{3}", X.ToString(format, formatProvider), - Y.ToString(format, formatProvider), Z.ToString(format, formatProvider), W.ToString(format, formatProvider)); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - unchecked - { - var hashCode = X.GetHashCode(); - hashCode = (hashCode * 397) ^ Y.GetHashCode(); - hashCode = (hashCode * 397) ^ Z.GetHashCode(); - hashCode = (hashCode * 397) ^ W.GetHashCode(); - return hashCode; - } - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(X); - serializer.Writer.Write(Y); - serializer.Writer.Write(Z); - serializer.Writer.Write(W); - } - else - { - X = serializer.Reader.ReadSingle(); - Y = serializer.Reader.ReadSingle(); - Z = serializer.Reader.ReadSingle(); - W = serializer.Reader.ReadSingle(); - } - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(ref Vector4 other) - { - return (MathUtil.NearEqual(other.X, X) && - MathUtil.NearEqual(other.Y, Y) && - MathUtil.NearEqual(other.Z, Z) && - MathUtil.NearEqual(other.W, W)); - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public bool Equals(Vector4 other) - { - return Equals(ref other); - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object value) - { - if (!(value is Vector4)) - return false; - - var strongValue = (Vector4)value; - return Equals(ref strongValue); - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from SlimMath project. http://code.google.com/p/slimmath/ +// Greetings to SlimDX Group. Original code published with the following license: +// ----------------------------------------------------------------------------- +/* +* Copyright (c) 2007-2011 SlimDX Group +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Represents a four dimensional mathematical vector. + /// + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct Vector4 : IEquatable, IFormattable + { + /// + /// The size of the type, in bytes. + /// + public static readonly int SizeInBytes = Marshal.SizeOf(typeof(Vector4)); + + /// + /// A with all of its components set to zero. + /// + public static readonly Vector4 Zero = new Vector4(); + + /// + /// The X unit (1, 0, 0, 0). + /// + public static readonly Vector4 UnitX = new Vector4(1.0f, 0.0f, 0.0f, 0.0f); + + /// + /// The Y unit (0, 1, 0, 0). + /// + public static readonly Vector4 UnitY = new Vector4(0.0f, 1.0f, 0.0f, 0.0f); + + /// + /// The Z unit (0, 0, 1, 0). + /// + public static readonly Vector4 UnitZ = new Vector4(0.0f, 0.0f, 1.0f, 0.0f); + + /// + /// The W unit (0, 0, 0, 1). + /// + public static readonly Vector4 UnitW = new Vector4(0.0f, 0.0f, 0.0f, 1.0f); + + /// + /// A with all of its components set to one. + /// + public static readonly Vector4 One = new Vector4(1.0f, 1.0f, 1.0f, 1.0f); + + /// + /// The X component of the vector. + /// + public float X; + + /// + /// The Y component of the vector. + /// + public float Y; + + /// + /// The Z component of the vector. + /// + public float Z; + + /// + /// The W component of the vector. + /// + public float W; + + /// + /// Initializes a new instance of the struct. + /// + /// The value that will be assigned to all components. + public Vector4(float value) + { + X = value; + Y = value; + Z = value; + W = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// Initial value for the X component of the vector. + /// Initial value for the Y component of the vector. + /// Initial value for the Z component of the vector. + /// Initial value for the W component of the vector. + public Vector4(float x, float y, float z, float w) + { + X = x; + Y = y; + Z = z; + W = w; + } + + /// + /// Initializes a new instance of the struct. + /// + /// A vector containing the values with which to initialize the X, Y, and Z components. + /// Initial value for the W component of the vector. + public Vector4(Vector3 value, float w) + { + X = value.X; + Y = value.Y; + Z = value.Z; + W = w; + } + + /// + /// Initializes a new instance of the struct. + /// + /// A vector containing the values with which to initialize the X and Y components. + /// Initial value for the Z component of the vector. + /// Initial value for the W component of the vector. + public Vector4(Vector2 value, float z, float w) + { + X = value.X; + Y = value.Y; + Z = z; + W = w; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The values to assign to the X, Y, Z, and W components of the vector. This must be an array with four elements. + /// Thrown when is null. + /// Thrown when contains more or less than four elements. + public Vector4(float[] values) + { + if (values == null) + throw new ArgumentNullException("values"); + if (values.Length != 4) + throw new ArgumentOutOfRangeException("values", "There must be four and only four input values for Vector4."); + + X = values[0]; + Y = values[1]; + Z = values[2]; + W = values[3]; + } + + /// + /// Gets a value indicting whether this instance is normalized. + /// + public bool IsNormalized + { + get { return MathUtil.IsOne((X * X) + (Y * Y) + (Z * Z) + (W * W)); } + } + + /// + /// Gets a value indicting whether this vector is zero + /// + public bool IsZero + { + get { return X == 0 && Y == 0 && Z == 0 && W == 0; } + } + + /// + /// Gets or sets the component at the specified index. + /// + /// The value of the X, Y, Z, or W component, depending on the index. + /// The index of the component to access. Use 0 for the X component, 1 for the Y component, 2 for the Z component, and 3 for the W component. + /// The value of the component at the specified index. + /// Thrown when the is out of the range [0, 3]. + public float this[int index] + { + get + { + switch (index) + { + case 0: return X; + case 1: return Y; + case 2: return Z; + case 3: return W; + } + + throw new ArgumentOutOfRangeException("index", "Indices for Vector4 run from 0 to 3, inclusive."); + } + + set + { + switch (index) + { + case 0: X = value; break; + case 1: Y = value; break; + case 2: Z = value; break; + case 3: W = value; break; + default: throw new ArgumentOutOfRangeException("index", "Indices for Vector4 run from 0 to 3, inclusive."); + } + } + } + + /// + /// Calculates the length of the vector. + /// + /// The length of the vector. + /// + /// may be preferred when only the relative length is needed + /// and speed is of the essence. + /// + public float Length() + { + return (float)Math.Sqrt((X * X) + (Y * Y) + (Z * Z) + (W * W)); + } + + /// + /// Calculates the squared length of the vector. + /// + /// The squared length of the vector. + /// + /// This method may be preferred to when only a relative length is needed + /// and speed is of the essence. + /// + public float LengthSquared() + { + return (X * X) + (Y * Y) + (Z * Z) + (W * W); + } + + /// + /// Converts the vector into a unit vector. + /// + public void Normalize() + { + float length = Length(); + if (!MathUtil.IsZero(length)) + { + float inverse = 1.0f / length; + X *= inverse; + Y *= inverse; + Z *= inverse; + W *= inverse; + } + } + + /// + /// Creates an array containing the elements of the vector. + /// + /// A four-element array containing the components of the vector. + public float[] ToArray() + { + return new float[] { X, Y, Z, W }; + } + + /// + /// Adds two vectors. + /// + /// The first vector to add. + /// The second vector to add. + /// When the method completes, contains the sum of the two vectors. + public static void Add(ref Vector4 left, ref Vector4 right, out Vector4 result) + { + result = new Vector4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W); + } + + /// + /// Adds two vectors. + /// + /// The first vector to add. + /// The second vector to add. + /// The sum of the two vectors. + public static Vector4 Add(Vector4 left, Vector4 right) + { + return new Vector4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W); + } + + /// + /// Perform a component-wise addition + /// + /// The input vector + /// The scalar value to be added to elements + /// The vector with added scalar for each element. + public static void Add(ref Vector4 left, ref float right, out Vector4 result) + { + result = new Vector4(left.X + right, left.Y + right, left.Z + right, left.W + right); + } + + /// + /// Perform a component-wise addition + /// + /// The input vector + /// The scalar value to be added to elements + /// The vector with added scalar for each element. + public static Vector4 Add(Vector4 left, float right) + { + return new Vector4(left.X + right, left.Y + right, left.Z + right, left.W + right); + } + + /// + /// Subtracts two vectors. + /// + /// The first vector to subtract. + /// The second vector to subtract. + /// When the method completes, contains the difference of the two vectors. + public static void Subtract(ref Vector4 left, ref Vector4 right, out Vector4 result) + { + result = new Vector4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W); + } + + /// + /// Subtracts two vectors. + /// + /// The first vector to subtract. + /// The second vector to subtract. + /// The difference of the two vectors. + public static Vector4 Subtract(Vector4 left, Vector4 right) + { + return new Vector4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W); + } + + /// + /// Perform a component-wise subtraction + /// + /// The input vector + /// The scalar value to be subtraced from elements + /// The vector with subtracted scalar for each element. + public static void Subtract(ref Vector4 left, ref float right, out Vector4 result) + { + result = new Vector4(left.X - right, left.Y - right, left.Z - right, left.W - right); + } + + /// + /// Perform a component-wise subtraction + /// + /// The input vector + /// The scalar value to be subtraced from elements + /// The vector with subtracted scalar for each element. + public static Vector4 Subtract(Vector4 left, float right) + { + return new Vector4(left.X - right, left.Y - right, left.Z - right, left.W - right); + } + + /// + /// Perform a component-wise subtraction + /// + /// The scalar value to be subtraced from elements + /// The input vector. + /// The vector with subtracted scalar for each element. + public static void Subtract(ref float left, ref Vector4 right, out Vector4 result) + { + result = new Vector4(left - right.X, left - right.Y, left - right.Z, left - right.W); + } + + /// + /// Perform a component-wise subtraction + /// + /// The scalar value to be subtraced from elements + /// The input vector. + /// The vector with subtracted scalar for each element. + public static Vector4 Subtract(float left, Vector4 right) + { + return new Vector4(left - right.X, left - right.Y, left - right.Z, left - right.W); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// When the method completes, contains the scaled vector. + public static void Multiply(ref Vector4 value, float scale, out Vector4 result) + { + result = new Vector4(value.X * scale, value.Y * scale, value.Z * scale, value.W * scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector4 Multiply(Vector4 value, float scale) + { + return new Vector4(value.X * scale, value.Y * scale, value.Z * scale, value.W * scale); + } + + /// + /// Multiplies a vector with another by performing component-wise multiplication. + /// + /// The first vector to multiply. + /// The second vector to multiply. + /// When the method completes, contains the multiplied vector. + public static void Multiply(ref Vector4 left, ref Vector4 right, out Vector4 result) + { + result = new Vector4(left.X * right.X, left.Y * right.Y, left.Z * right.Z, left.W * right.W); + } + + /// + /// Multiplies a vector with another by performing component-wise multiplication. + /// + /// The first vector to multiply. + /// The second vector to multiply. + /// The multiplied vector. + public static Vector4 Multiply(Vector4 left, Vector4 right) + { + return new Vector4(left.X * right.X, left.Y * right.Y, left.Z * right.Z, left.W * right.W); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// When the method completes, contains the scaled vector. + public static void Divide(ref Vector4 value, float scale, out Vector4 result) + { + result = new Vector4(value.X / scale, value.Y / scale, value.Z / scale, value.W / scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector4 Divide(Vector4 value, float scale) + { + return new Vector4(value.X / scale, value.Y / scale, value.Z / scale, value.W / scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The amount by which to scale the vector. + /// The vector to scale. + /// When the method completes, contains the scaled vector. + public static void Divide(float scale, ref Vector4 value, out Vector4 result) + { + result = new Vector4(scale / value.X, scale / value.Y, scale / value.Z, scale / value.W); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector4 Divide(float scale, Vector4 value) + { + return new Vector4(scale / value.X, scale / value.Y, scale / value.Z, scale / value.W); + } + + /// + /// Reverses the direction of a given vector. + /// + /// The vector to negate. + /// When the method completes, contains a vector facing in the opposite direction. + public static void Negate(ref Vector4 value, out Vector4 result) + { + result = new Vector4(-value.X, -value.Y, -value.Z, -value.W); + } + + /// + /// Reverses the direction of a given vector. + /// + /// The vector to negate. + /// A vector facing in the opposite direction. + public static Vector4 Negate(Vector4 value) + { + return new Vector4(-value.X, -value.Y, -value.Z, -value.W); + } + + /// + /// Returns a containing the 4D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 4D triangle. + /// + /// A containing the 4D Cartesian coordinates of vertex 1 of the triangle. + /// A containing the 4D Cartesian coordinates of vertex 2 of the triangle. + /// A containing the 4D Cartesian coordinates of vertex 3 of the triangle. + /// Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). + /// Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). + /// When the method completes, contains the 4D Cartesian coordinates of the specified point. + public static void Barycentric(ref Vector4 value1, ref Vector4 value2, ref Vector4 value3, float amount1, float amount2, out Vector4 result) + { + result = new Vector4((value1.X + (amount1 * (value2.X - value1.X))) + (amount2 * (value3.X - value1.X)), + (value1.Y + (amount1 * (value2.Y - value1.Y))) + (amount2 * (value3.Y - value1.Y)), + (value1.Z + (amount1 * (value2.Z - value1.Z))) + (amount2 * (value3.Z - value1.Z)), + (value1.W + (amount1 * (value2.W - value1.W))) + (amount2 * (value3.W - value1.W))); + } + + /// + /// Returns a containing the 4D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 4D triangle. + /// + /// A containing the 4D Cartesian coordinates of vertex 1 of the triangle. + /// A containing the 4D Cartesian coordinates of vertex 2 of the triangle. + /// A containing the 4D Cartesian coordinates of vertex 3 of the triangle. + /// Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). + /// Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). + /// A new containing the 4D Cartesian coordinates of the specified point. + public static Vector4 Barycentric(Vector4 value1, Vector4 value2, Vector4 value3, float amount1, float amount2) + { + Vector4 result; + Barycentric(ref value1, ref value2, ref value3, amount1, amount2, out result); + return result; + } + + /// + /// Restricts a value to be within a specified range. + /// + /// The value to clamp. + /// The minimum value. + /// The maximum value. + /// When the method completes, contains the clamped value. + public static void Clamp(ref Vector4 value, ref Vector4 min, ref Vector4 max, out Vector4 result) + { + float x = value.X; + x = (x > max.X) ? max.X : x; + x = (x < min.X) ? min.X : x; + + float y = value.Y; + y = (y > max.Y) ? max.Y : y; + y = (y < min.Y) ? min.Y : y; + + float z = value.Z; + z = (z > max.Z) ? max.Z : z; + z = (z < min.Z) ? min.Z : z; + + float w = value.W; + w = (w > max.W) ? max.W : w; + w = (w < min.W) ? min.W : w; + + result = new Vector4(x, y, z, w); + } + + /// + /// Restricts a value to be within a specified range. + /// + /// The value to clamp. + /// The minimum value. + /// The maximum value. + /// The clamped value. + public static Vector4 Clamp(Vector4 value, Vector4 min, Vector4 max) + { + Vector4 result; + Clamp(ref value, ref min, ref max, out result); + return result; + } + + /// + /// Calculates the distance between two vectors. + /// + /// The first vector. + /// The second vector. + /// When the method completes, contains the distance between the two vectors. + /// + /// may be preferred when only the relative distance is needed + /// and speed is of the essence. + /// + public static void Distance(ref Vector4 value1, ref Vector4 value2, out float result) + { + float x = value1.X - value2.X; + float y = value1.Y - value2.Y; + float z = value1.Z - value2.Z; + float w = value1.W - value2.W; + + result = (float)Math.Sqrt((x * x) + (y * y) + (z * z) + (w * w)); + } + + /// + /// Calculates the distance between two vectors. + /// + /// The first vector. + /// The second vector. + /// The distance between the two vectors. + /// + /// may be preferred when only the relative distance is needed + /// and speed is of the essence. + /// + public static float Distance(Vector4 value1, Vector4 value2) + { + float x = value1.X - value2.X; + float y = value1.Y - value2.Y; + float z = value1.Z - value2.Z; + float w = value1.W - value2.W; + + return (float)Math.Sqrt((x * x) + (y * y) + (z * z) + (w * w)); + } + + /// + /// Calculates the squared distance between two vectors. + /// + /// The first vector. + /// The second vector. + /// When the method completes, contains the squared distance between the two vectors. + /// Distance squared is the value before taking the square root. + /// Distance squared can often be used in place of distance if relative comparisons are being made. + /// For example, consider three points A, B, and C. To determine whether B or C is further from A, + /// compare the distance between A and B to the distance between A and C. Calculating the two distances + /// involves two square roots, which are computationally expensive. However, using distance squared + /// provides the same information and avoids calculating two square roots. + /// + public static void DistanceSquared(ref Vector4 value1, ref Vector4 value2, out float result) + { + float x = value1.X - value2.X; + float y = value1.Y - value2.Y; + float z = value1.Z - value2.Z; + float w = value1.W - value2.W; + + result = (x * x) + (y * y) + (z * z) + (w * w); + } + + /// + /// Calculates the squared distance between two vectors. + /// + /// The first vector. + /// The second vector. + /// The squared distance between the two vectors. + /// Distance squared is the value before taking the square root. + /// Distance squared can often be used in place of distance if relative comparisons are being made. + /// For example, consider three points A, B, and C. To determine whether B or C is further from A, + /// compare the distance between A and B to the distance between A and C. Calculating the two distances + /// involves two square roots, which are computationally expensive. However, using distance squared + /// provides the same information and avoids calculating two square roots. + /// + public static float DistanceSquared(Vector4 value1, Vector4 value2) + { + float x = value1.X - value2.X; + float y = value1.Y - value2.Y; + float z = value1.Z - value2.Z; + float w = value1.W - value2.W; + + return (x * x) + (y * y) + (z * z) + (w * w); + } + + /// + /// Calculates the dot product of two vectors. + /// + /// First source vector + /// Second source vector. + /// When the method completes, contains the dot product of the two vectors. + public static void Dot(ref Vector4 left, ref Vector4 right, out float result) + { + result = (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z) + (left.W * right.W); + } + + /// + /// Calculates the dot product of two vectors. + /// + /// First source vector. + /// Second source vector. + /// The dot product of the two vectors. + public static float Dot(Vector4 left, Vector4 right) + { + return (left.X * right.X) + (left.Y * right.Y) + (left.Z * right.Z) + (left.W * right.W); + } + + /// + /// Converts the vector into a unit vector. + /// + /// The vector to normalize. + /// When the method completes, contains the normalized vector. + public static void Normalize(ref Vector4 value, out Vector4 result) + { + Vector4 temp = value; + result = temp; + result.Normalize(); + } + + /// + /// Converts the vector into a unit vector. + /// + /// The vector to normalize. + /// The normalized vector. + public static Vector4 Normalize(Vector4 value) + { + value.Normalize(); + return value; + } + + /// + /// Performs a linear interpolation between two vectors. + /// + /// Start vector. + /// End vector. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the linear interpolation of the two vectors. + /// + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static void Lerp(ref Vector4 start, ref Vector4 end, float amount, out Vector4 result) + { + result.X = MathUtil.Lerp(start.X, end.X, amount); + result.Y = MathUtil.Lerp(start.Y, end.Y, amount); + result.Z = MathUtil.Lerp(start.Z, end.Z, amount); + result.W = MathUtil.Lerp(start.W, end.W, amount); + } + + /// + /// Performs a linear interpolation between two vectors. + /// + /// Start vector. + /// End vector. + /// Value between 0 and 1 indicating the weight of . + /// The linear interpolation of the two vectors. + /// + /// Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + /// + public static Vector4 Lerp(Vector4 start, Vector4 end, float amount) + { + Vector4 result; + Lerp(ref start, ref end, amount, out result); + return result; + } + + /// + /// Performs a cubic interpolation between two vectors. + /// + /// Start vector. + /// End vector. + /// Value between 0 and 1 indicating the weight of . + /// When the method completes, contains the cubic interpolation of the two vectors. + public static void SmoothStep(ref Vector4 start, ref Vector4 end, float amount, out Vector4 result) + { + amount = MathUtil.SmoothStep(amount); + Lerp(ref start, ref end, amount, out result); + } + + /// + /// Performs a cubic interpolation between two vectors. + /// + /// Start vector. + /// End vector. + /// Value between 0 and 1 indicating the weight of . + /// The cubic interpolation of the two vectors. + public static Vector4 SmoothStep(Vector4 start, Vector4 end, float amount) + { + Vector4 result; + SmoothStep(ref start, ref end, amount, out result); + return result; + } + + /// + /// Performs a Hermite spline interpolation. + /// + /// First source position vector. + /// First source tangent vector. + /// Second source position vector. + /// Second source tangent vector. + /// Weighting factor. + /// When the method completes, contains the result of the Hermite spline interpolation. + public static void Hermite(ref Vector4 value1, ref Vector4 tangent1, ref Vector4 value2, ref Vector4 tangent2, float amount, out Vector4 result) + { + float squared = amount * amount; + float cubed = amount * squared; + float part1 = ((2.0f * cubed) - (3.0f * squared)) + 1.0f; + float part2 = (-2.0f * cubed) + (3.0f * squared); + float part3 = (cubed - (2.0f * squared)) + amount; + float part4 = cubed - squared; + + result = new Vector4((((value1.X * part1) + (value2.X * part2)) + (tangent1.X * part3)) + (tangent2.X * part4), + (((value1.Y * part1) + (value2.Y * part2)) + (tangent1.Y * part3)) + (tangent2.Y * part4), + (((value1.Z * part1) + (value2.Z * part2)) + (tangent1.Z * part3)) + (tangent2.Z * part4), + (((value1.W * part1) + (value2.W * part2)) + (tangent1.W * part3)) + (tangent2.W * part4)); + } + + /// + /// Performs a Hermite spline interpolation. + /// + /// First source position vector. + /// First source tangent vector. + /// Second source position vector. + /// Second source tangent vector. + /// Weighting factor. + /// The result of the Hermite spline interpolation. + public static Vector4 Hermite(Vector4 value1, Vector4 tangent1, Vector4 value2, Vector4 tangent2, float amount) + { + Vector4 result; + Hermite(ref value1, ref tangent1, ref value2, ref tangent2, amount, out result); + return result; + } + + /// + /// Performs a Catmull-Rom interpolation using the specified positions. + /// + /// The first position in the interpolation. + /// The second position in the interpolation. + /// The third position in the interpolation. + /// The fourth position in the interpolation. + /// Weighting factor. + /// When the method completes, contains the result of the Catmull-Rom interpolation. + public static void CatmullRom(ref Vector4 value1, ref Vector4 value2, ref Vector4 value3, ref Vector4 value4, float amount, out Vector4 result) + { + float squared = amount * amount; + float cubed = amount * squared; + + result.X = 0.5f * ((((2.0f * value2.X) + ((-value1.X + value3.X) * amount)) + (((((2.0f * value1.X) - (5.0f * value2.X)) + (4.0f * value3.X)) - value4.X) * squared)) + ((((-value1.X + (3.0f * value2.X)) - (3.0f * value3.X)) + value4.X) * cubed)); + result.Y = 0.5f * ((((2.0f * value2.Y) + ((-value1.Y + value3.Y) * amount)) + (((((2.0f * value1.Y) - (5.0f * value2.Y)) + (4.0f * value3.Y)) - value4.Y) * squared)) + ((((-value1.Y + (3.0f * value2.Y)) - (3.0f * value3.Y)) + value4.Y) * cubed)); + result.Z = 0.5f * ((((2.0f * value2.Z) + ((-value1.Z + value3.Z) * amount)) + (((((2.0f * value1.Z) - (5.0f * value2.Z)) + (4.0f * value3.Z)) - value4.Z) * squared)) + ((((-value1.Z + (3.0f * value2.Z)) - (3.0f * value3.Z)) + value4.Z) * cubed)); + result.W = 0.5f * ((((2.0f * value2.W) + ((-value1.W + value3.W) * amount)) + (((((2.0f * value1.W) - (5.0f * value2.W)) + (4.0f * value3.W)) - value4.W) * squared)) + ((((-value1.W + (3.0f * value2.W)) - (3.0f * value3.W)) + value4.W) * cubed)); + } + + /// + /// Performs a Catmull-Rom interpolation using the specified positions. + /// + /// The first position in the interpolation. + /// The second position in the interpolation. + /// The third position in the interpolation. + /// The fourth position in the interpolation. + /// Weighting factor. + /// A vector that is the result of the Catmull-Rom interpolation. + public static Vector4 CatmullRom(Vector4 value1, Vector4 value2, Vector4 value3, Vector4 value4, float amount) + { + Vector4 result; + CatmullRom(ref value1, ref value2, ref value3, ref value4, amount, out result); + return result; + } + + /// + /// Returns a vector containing the largest components of the specified vectors. + /// + /// The first source vector. + /// The second source vector. + /// When the method completes, contains an new vector composed of the largest components of the source vectors. + public static void Max(ref Vector4 left, ref Vector4 right, out Vector4 result) + { + result.X = (left.X > right.X) ? left.X : right.X; + result.Y = (left.Y > right.Y) ? left.Y : right.Y; + result.Z = (left.Z > right.Z) ? left.Z : right.Z; + result.W = (left.W > right.W) ? left.W : right.W; + } + + /// + /// Returns a vector containing the largest components of the specified vectors. + /// + /// The first source vector. + /// The second source vector. + /// A vector containing the largest components of the source vectors. + public static Vector4 Max(Vector4 left, Vector4 right) + { + Vector4 result; + Max(ref left, ref right, out result); + return result; + } + + /// + /// Returns a vector containing the smallest components of the specified vectors. + /// + /// The first source vector. + /// The second source vector. + /// When the method completes, contains an new vector composed of the smallest components of the source vectors. + public static void Min(ref Vector4 left, ref Vector4 right, out Vector4 result) + { + result.X = (left.X < right.X) ? left.X : right.X; + result.Y = (left.Y < right.Y) ? left.Y : right.Y; + result.Z = (left.Z < right.Z) ? left.Z : right.Z; + result.W = (left.W < right.W) ? left.W : right.W; + } + + /// + /// Returns a vector containing the smallest components of the specified vectors. + /// + /// The first source vector. + /// The second source vector. + /// A vector containing the smallest components of the source vectors. + public static Vector4 Min(Vector4 left, Vector4 right) + { + Vector4 result; + Min(ref left, ref right, out result); + return result; + } + + /// + /// Orthogonalizes a list of vectors. + /// + /// The list of orthogonalized vectors. + /// The list of vectors to orthogonalize. + /// + /// Orthogonalization is the process of making all vectors orthogonal to each other. This + /// means that any given vector in the list will be orthogonal to any other given vector in the + /// list. + /// Because this method uses the modified Gram-Schmidt process, the resulting vectors + /// tend to be numerically unstable. The numeric stability decreases according to the vectors + /// position in the list so that the first vector is the most stable and the last vector is the + /// least stable. + /// + /// Thrown when or is null. + /// Thrown when is shorter in length than . + public static void Orthogonalize(Vector4[] destination, params Vector4[] source) + { + //Uses the modified Gram-Schmidt process. + //q1 = m1 + //q2 = m2 - ((q1 ⋅ m2) / (q1 ⋅ q1)) * q1 + //q3 = m3 - ((q1 ⋅ m3) / (q1 ⋅ q1)) * q1 - ((q2 ⋅ m3) / (q2 ⋅ q2)) * q2 + //q4 = m4 - ((q1 ⋅ m4) / (q1 ⋅ q1)) * q1 - ((q2 ⋅ m4) / (q2 ⋅ q2)) * q2 - ((q3 ⋅ m4) / (q3 ⋅ q3)) * q3 + //q5 = ... + + if (source == null) + throw new ArgumentNullException("source"); + if (destination == null) + throw new ArgumentNullException("destination"); + if (destination.Length < source.Length) + throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); + + for (int i = 0; i < source.Length; ++i) + { + Vector4 newvector = source[i]; + + for (int r = 0; r < i; ++r) + { + newvector -= (Vector4.Dot(destination[r], newvector) / Vector4.Dot(destination[r], destination[r])) * destination[r]; + } + + destination[i] = newvector; + } + } + + /// + /// Orthonormalizes a list of vectors. + /// + /// The list of orthonormalized vectors. + /// The list of vectors to orthonormalize. + /// + /// Orthonormalization is the process of making all vectors orthogonal to each + /// other and making all vectors of unit length. This means that any given vector will + /// be orthogonal to any other given vector in the list. + /// Because this method uses the modified Gram-Schmidt process, the resulting vectors + /// tend to be numerically unstable. The numeric stability decreases according to the vectors + /// position in the list so that the first vector is the most stable and the last vector is the + /// least stable. + /// + /// Thrown when or is null. + /// Thrown when is shorter in length than . + public static void Orthonormalize(Vector4[] destination, params Vector4[] source) + { + //Uses the modified Gram-Schmidt process. + //Because we are making unit vectors, we can optimize the math for orthogonalization + //and simplify the projection operation to remove the division. + //q1 = m1 / |m1| + //q2 = (m2 - (q1 ⋅ m2) * q1) / |m2 - (q1 ⋅ m2) * q1| + //q3 = (m3 - (q1 ⋅ m3) * q1 - (q2 ⋅ m3) * q2) / |m3 - (q1 ⋅ m3) * q1 - (q2 ⋅ m3) * q2| + //q4 = (m4 - (q1 ⋅ m4) * q1 - (q2 ⋅ m4) * q2 - (q3 ⋅ m4) * q3) / |m4 - (q1 ⋅ m4) * q1 - (q2 ⋅ m4) * q2 - (q3 ⋅ m4) * q3| + //q5 = ... + + if (source == null) + throw new ArgumentNullException("source"); + if (destination == null) + throw new ArgumentNullException("destination"); + if (destination.Length < source.Length) + throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); + + for (int i = 0; i < source.Length; ++i) + { + Vector4 newvector = source[i]; + + for (int r = 0; r < i; ++r) + { + newvector -= Vector4.Dot(destination[r], newvector) * destination[r]; + } + + newvector.Normalize(); + destination[i] = newvector; + } + } + + /// + /// Transforms a 4D vector by the given rotation. + /// + /// The vector to rotate. + /// The rotation to apply. + /// When the method completes, contains the transformed . + public static void Transform(ref Vector4 vector, ref Quaternion rotation, out Vector4 result) + { + float x = rotation.X + rotation.X; + float y = rotation.Y + rotation.Y; + float z = rotation.Z + rotation.Z; + float wx = rotation.W * x; + float wy = rotation.W * y; + float wz = rotation.W * z; + float xx = rotation.X * x; + float xy = rotation.X * y; + float xz = rotation.X * z; + float yy = rotation.Y * y; + float yz = rotation.Y * z; + float zz = rotation.Z * z; + + result = new Vector4( + ((vector.X * ((1.0f - yy) - zz)) + (vector.Y * (xy - wz))) + (vector.Z * (xz + wy)), + ((vector.X * (xy + wz)) + (vector.Y * ((1.0f - xx) - zz))) + (vector.Z * (yz - wx)), + ((vector.X * (xz - wy)) + (vector.Y * (yz + wx))) + (vector.Z * ((1.0f - xx) - yy)), + vector.W); + } + + /// + /// Transforms a 4D vector by the given rotation. + /// + /// The vector to rotate. + /// The rotation to apply. + /// The transformed . + public static Vector4 Transform(Vector4 vector, Quaternion rotation) + { + Vector4 result; + Transform(ref vector, ref rotation, out result); + return result; + } + + /// + /// Transforms an array of vectors by the given rotation. + /// + /// The array of vectors to transform. + /// The rotation to apply. + /// The array for which the transformed vectors are stored. + /// This array may be the same array as . + /// Thrown when or is null. + /// Thrown when is shorter in length than . + public static void Transform(Vector4[] source, ref Quaternion rotation, Vector4[] destination) + { + if (source == null) + throw new ArgumentNullException("source"); + if (destination == null) + throw new ArgumentNullException("destination"); + if (destination.Length < source.Length) + throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); + + float x = rotation.X + rotation.X; + float y = rotation.Y + rotation.Y; + float z = rotation.Z + rotation.Z; + float wx = rotation.W * x; + float wy = rotation.W * y; + float wz = rotation.W * z; + float xx = rotation.X * x; + float xy = rotation.X * y; + float xz = rotation.X * z; + float yy = rotation.Y * y; + float yz = rotation.Y * z; + float zz = rotation.Z * z; + + float num1 = ((1.0f - yy) - zz); + float num2 = (xy - wz); + float num3 = (xz + wy); + float num4 = (xy + wz); + float num5 = ((1.0f - xx) - zz); + float num6 = (yz - wx); + float num7 = (xz - wy); + float num8 = (yz + wx); + float num9 = ((1.0f - xx) - yy); + + for (int i = 0; i < source.Length; ++i) + { + destination[i] = new Vector4( + ((source[i].X * num1) + (source[i].Y * num2)) + (source[i].Z * num3), + ((source[i].X * num4) + (source[i].Y * num5)) + (source[i].Z * num6), + ((source[i].X * num7) + (source[i].Y * num8)) + (source[i].Z * num9), + source[i].W); + } + } + + /// + /// Transforms a 4D vector by the given . + /// + /// The source vector. + /// The transformation . + /// When the method completes, contains the transformed . + public static void Transform(ref Vector4 vector, ref Matrix transform, out Vector4 result) + { + result = new Vector4( + (vector.X * transform.M11) + (vector.Y * transform.M21) + (vector.Z * transform.M31) + (vector.W * transform.M41), + (vector.X * transform.M12) + (vector.Y * transform.M22) + (vector.Z * transform.M32) + (vector.W * transform.M42), + (vector.X * transform.M13) + (vector.Y * transform.M23) + (vector.Z * transform.M33) + (vector.W * transform.M43), + (vector.X * transform.M14) + (vector.Y * transform.M24) + (vector.Z * transform.M34) + (vector.W * transform.M44)); + } + + /// + /// Transforms a 4D vector by the given . + /// + /// The source vector. + /// The transformation . + /// The transformed . + public static Vector4 Transform(Vector4 vector, Matrix transform) + { + Vector4 result; + Transform(ref vector, ref transform, out result); + return result; + } + + /// + /// Transforms a 4D vector by the given . + /// + /// The source vector. + /// The transformation . + /// When the method completes, contains the transformed . + public static void Transform(ref Vector4 vector, ref Matrix5x4 transform, out Vector4 result) + { + result = new Vector4( + (vector.X * transform.M11) + (vector.Y * transform.M21) + (vector.Z * transform.M31) + (vector.W * transform.M41) + transform.M51, + (vector.X * transform.M12) + (vector.Y * transform.M22) + (vector.Z * transform.M32) + (vector.W * transform.M42) + transform.M52, + (vector.X * transform.M13) + (vector.Y * transform.M23) + (vector.Z * transform.M33) + (vector.W * transform.M43) + transform.M53, + (vector.X * transform.M14) + (vector.Y * transform.M24) + (vector.Z * transform.M34) + (vector.W * transform.M44) + transform.M54); + } + + /// + /// Transforms a 4D vector by the given . + /// + /// The source vector. + /// The transformation . + /// The transformed . + public static Vector4 Transform(Vector4 vector, Matrix5x4 transform) + { + Vector4 result; + Transform(ref vector, ref transform, out result); + return result; + } + + /// + /// Transforms an array of 4D vectors by the given . + /// + /// The array of vectors to transform. + /// The transformation . + /// The array for which the transformed vectors are stored. + /// This array may be the same array as . + /// Thrown when or is null. + /// Thrown when is shorter in length than . + public static void Transform(Vector4[] source, ref Matrix transform, Vector4[] destination) + { + if (source == null) + throw new ArgumentNullException("source"); + if (destination == null) + throw new ArgumentNullException("destination"); + if (destination.Length < source.Length) + throw new ArgumentOutOfRangeException("destination", "The destination array must be of same length or larger length than the source array."); + + for (int i = 0; i < source.Length; ++i) + { + Transform(ref source[i], ref transform, out destination[i]); + } + } + + /// + /// Adds two vectors. + /// + /// The first vector to add. + /// The second vector to add. + /// The sum of the two vectors. + public static Vector4 operator +(Vector4 left, Vector4 right) + { + return new Vector4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W); + } + + /// + /// Multiplies a vector with another by performing component-wise multiplication equivalent to . + /// + /// The first vector to multiply. + /// The second vector to multiply. + /// The multiplication of the two vectors. + public static Vector4 operator *(Vector4 left, Vector4 right) + { + return new Vector4(left.X * right.X, left.Y * right.Y, left.Z * right.Z, left.W * right.W); + } + + /// + /// Assert a vector (return it unchanged). + /// + /// The vector to assert (unchanged). + /// The asserted (unchanged) vector. + public static Vector4 operator +(Vector4 value) + { + return value; + } + + /// + /// Subtracts two vectors. + /// + /// The first vector to subtract. + /// The second vector to subtract. + /// The difference of the two vectors. + public static Vector4 operator -(Vector4 left, Vector4 right) + { + return new Vector4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W); + } + + /// + /// Reverses the direction of a given vector. + /// + /// The vector to negate. + /// A vector facing in the opposite direction. + public static Vector4 operator -(Vector4 value) + { + return new Vector4(-value.X, -value.Y, -value.Z, -value.W); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector4 operator *(float scale, Vector4 value) + { + return new Vector4(value.X * scale, value.Y * scale, value.Z * scale, value.W * scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector4 operator *(Vector4 value, float scale) + { + return new Vector4(value.X * scale, value.Y * scale, value.Z * scale, value.W * scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector4 operator /(Vector4 value, float scale) + { + return new Vector4(value.X / scale, value.Y / scale, value.Z / scale, value.W / scale); + } + + /// + /// Scales a vector by the given value. + /// + /// The amount by which to scale the vector. + /// The vector to scale. + /// The scaled vector. + public static Vector4 operator /(float scale,Vector4 value) + { + return new Vector4(scale / value.X, scale / value.Y, scale / value.Z, scale / value.W); + } + + /// + /// Scales a vector by the given value. + /// + /// The vector to scale. + /// The amount by which to scale the vector. + /// The scaled vector. + public static Vector4 operator /(Vector4 value, Vector4 scale) + { + return new Vector4(value.X / scale.X, value.Y / scale.Y, value.Z / scale.Z, value.W / scale.W); + } + + /// + /// Perform a component-wise addition + /// + /// The input vector. + /// The scalar value to be added on elements + /// The vector with added scalar for each element. + public static Vector4 operator +(Vector4 value, float scalar) + { + return new Vector4(value.X + scalar, value.Y + scalar, value.Z + scalar, value.W + scalar); + } + + /// + /// Perform a component-wise addition + /// + /// The input vector. + /// The scalar value to be added on elements + /// The vector with added scalar for each element. + public static Vector4 operator +(float scalar, Vector4 value) + { + return new Vector4(scalar + value.X, scalar + value.Y, scalar + value.Z, scalar + value.W); + } + + /// + /// Perform a component-wise subtraction + /// + /// The input vector. + /// The scalar value to be subtraced from elements + /// The vector with subtraced scalar from each element. + public static Vector4 operator -(Vector4 value, float scalar) + { + return new Vector4(value.X - scalar, value.Y - scalar, value.Z - scalar, value.W - scalar); + } + + /// + /// Perform a component-wise subtraction + /// + /// The input vector. + /// The scalar value to be subtraced from elements + /// The vector with subtraced scalar from each element. + public static Vector4 operator -(float scalar, Vector4 value) + { + return new Vector4(scalar - value.X, scalar - value.Y, scalar - value.Z, scalar - value.W); + } + + /// + /// Tests for equality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has the same value as ; otherwise, false. + public static bool operator ==(Vector4 left, Vector4 right) + { + return left.Equals(ref right); + } + + /// + /// Tests for inequality between two objects. + /// + /// The first value to compare. + /// The second value to compare. + /// true if has a different value than ; otherwise, false. + public static bool operator !=(Vector4 left, Vector4 right) + { + return !left.Equals(ref right); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Vector2(Vector4 value) + { + return new Vector2(value.X, value.Y); + } + + /// + /// Performs an explicit conversion from to . + /// + /// The value. + /// The result of the conversion. + public static explicit operator Vector3(Vector4 value) + { + return new Vector3(value.X, value.Y, value.Z); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// + /// A that represents this instance. + /// + public string ToString(string format) + { + if (format == null) + return ToString(); + + return string.Format(CultureInfo.CurrentCulture, "X:{0} Y:{1} Z:{2} W:{3}", X.ToString(format, CultureInfo.CurrentCulture), + Y.ToString(format, CultureInfo.CurrentCulture), Z.ToString(format, CultureInfo.CurrentCulture), W.ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format(formatProvider, "X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(string format, IFormatProvider formatProvider) + { + if (format == null) + ToString(formatProvider); + + return string.Format(formatProvider, "X:{0} Y:{1} Z:{2} W:{3}", X.ToString(format, formatProvider), + Y.ToString(format, formatProvider), Z.ToString(format, formatProvider), W.ToString(format, formatProvider)); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + unchecked + { + var hashCode = X.GetHashCode(); + hashCode = (hashCode * 397) ^ Y.GetHashCode(); + hashCode = (hashCode * 397) ^ Z.GetHashCode(); + hashCode = (hashCode * 397) ^ W.GetHashCode(); + return hashCode; + } + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(ref Vector4 other) + { + return (MathUtil.NearEqual(other.X, X) && + MathUtil.NearEqual(other.Y, Y) && + MathUtil.NearEqual(other.Z, Z) && + MathUtil.NearEqual(other.W, W)); + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(Vector4 other) + { + return Equals(ref other); + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object value) + { + if (!(value is Vector4)) + return false; + + var strongValue = (Vector4)value; + return Equals(ref strongValue); + } + } +} diff --git a/Source/SharpDX/Viewport.cs b/Source/SharpDX/Mathematics/Viewport.cs similarity index 92% rename from Source/SharpDX/Viewport.cs rename to Source/SharpDX/Mathematics/Viewport.cs index a9b3c6490..1aa7d8595 100644 --- a/Source/SharpDX/Viewport.cs +++ b/Source/SharpDX/Mathematics/Viewport.cs @@ -22,15 +22,13 @@ using System.Globalization; using System.Runtime.InteropServices; -using SharpDX.Serialization; - namespace SharpDX { /// /// Defines the viewport dimensions. /// [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct Viewport : IEquatable, IDataSerializable + public struct Viewport : IEquatable { /// /// Position of the pixel coordinate of the upper-left corner of the viewport. @@ -307,28 +305,5 @@ public float AspectRatio return 0f; } } - - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(X); - serializer.Writer.Write(Y); - serializer.Writer.Write(Width); - serializer.Writer.Write(Height); - serializer.Writer.Write(MinDepth); - serializer.Writer.Write(MaxDepth); - } - else - { - X = serializer.Reader.ReadInt32(); - Y = serializer.Reader.ReadInt32(); - Width = serializer.Reader.ReadInt32(); - Height = serializer.Reader.ReadInt32(); - MinDepth = serializer.Reader.ReadSingle(); - MaxDepth = serializer.Reader.ReadSingle(); - } - } } } diff --git a/Source/SharpDX/ViewportF.cs b/Source/SharpDX/Mathematics/ViewportF.cs similarity index 92% rename from Source/SharpDX/ViewportF.cs rename to Source/SharpDX/Mathematics/ViewportF.cs index 01e95e8fd..27b9ba8ef 100644 --- a/Source/SharpDX/ViewportF.cs +++ b/Source/SharpDX/Mathematics/ViewportF.cs @@ -22,15 +22,13 @@ using System.Globalization; using System.Runtime.InteropServices; -using SharpDX.Serialization; - namespace SharpDX { /// /// Defines the viewport dimensions using float coordinates for (X,Y,Width,Height). /// [StructLayout(LayoutKind.Sequential, Pack = 4)] - public struct ViewportF : IEquatable, IDataSerializable + public struct ViewportF : IEquatable { /// /// Position of the pixel coordinate of the upper-left corner of the viewport. @@ -318,28 +316,5 @@ public static implicit operator ViewportF(Viewport value) { return new ViewportF(value.X, value.Y, value.Width, value.Height, value.MinDepth, value.MaxDepth); } - - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Write optimized version without using Serialize methods - if (serializer.Mode == SerializerMode.Write) - { - serializer.Writer.Write(X); - serializer.Writer.Write(Y); - serializer.Writer.Write(Width); - serializer.Writer.Write(Height); - serializer.Writer.Write(MinDepth); - serializer.Writer.Write(MaxDepth); - } - else - { - X = serializer.Reader.ReadSingle(); - Y = serializer.Reader.ReadSingle(); - Width = serializer.Reader.ReadSingle(); - Height = serializer.Reader.ReadSingle(); - MinDepth = serializer.Reader.ReadSingle(); - MaxDepth = serializer.Reader.ReadSingle(); - } - } } } diff --git a/Source/SharpDX/Multimedia/FourCC.cs b/Source/SharpDX/Multimedia/FourCC.cs index dc16b61d7..77bb004dd 100644 --- a/Source/SharpDX/Multimedia/FourCC.cs +++ b/Source/SharpDX/Multimedia/FourCC.cs @@ -20,15 +20,13 @@ using System; using System.Runtime.InteropServices; -using SharpDX.Serialization; - namespace SharpDX.Multimedia { /// /// A FourCC descriptor. /// [StructLayout(LayoutKind.Sequential, Size = 4)] - public struct FourCC : IEquatable, IDataSerializable + public struct FourCC : IEquatable { /// /// Empty FourCC. @@ -177,11 +175,6 @@ public override int GetHashCode() return (int) value; } - public void Serialize(BinarySerializer serializer) - { - serializer.Serialize(ref value); - } - public static bool operator ==(FourCC left, FourCC right) { return left.Equals(right); diff --git a/Source/SharpDX/Multimedia/Mapping.xml b/Source/SharpDX/Multimedia/Mapping.xml index ef9b8dc02..37c938eec 100644 --- a/Source/SharpDX/Multimedia/Mapping.xml +++ b/Source/SharpDX/Multimedia/Mapping.xml @@ -1,121 +1,121 @@ - - - - sharpdx-core - - SharpDX.Multimedia - SharpDX - - - - - - // Additionnals HID_USAGE_PAGES* - #define HID_USAGE_PAGE_MEDICAL 0x40 - #define HID_USAGE_PAGE_MONITOR_PAGE0 0x80 - #define HID_USAGE_PAGE_MONITOR_PAGE1 0x81 - #define HID_USAGE_PAGE_MONITOR_PAGE2 0x82 - #define HID_USAGE_PAGE_MONITOR_PAGE3 0x83 - #define HID_USAGE_PAGE_POWER_PAGE0 0x84 - #define HID_USAGE_PAGE_POWER_PAGE1 0x85 - #define HID_USAGE_PAGE_POWER_PAGE2 0x86 - #define HID_USAGE_PAGE_POWER_PAGE3 0x87 - #define HID_USAGE_PAGE_BARCODE 0x8C - #define HID_USAGE_PAGE_SCALE 0x8D - #define HID_USAGE_PAGE_MSR 0x8E - - - - - - - -
-      #define WAVE_FORMAT_PCM     1
-    
-
- - - - - - - - - - sharpdx-core-multimedia - sharpdx-core-multimedia-ext - hidusage - audiodefs - audiosessiontypes - mmreg - - - - - - - - - - - - - - - - - - sharpdx-core-multimedia-ext - hidusage - audiodefs - audiosessiontypes - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + sharpdx-core + + SharpDX.Multimedia + SharpDX + + + + + + // Additionnals HID_USAGE_PAGES* + #define HID_USAGE_PAGE_MEDICAL 0x40 + #define HID_USAGE_PAGE_MONITOR_PAGE0 0x80 + #define HID_USAGE_PAGE_MONITOR_PAGE1 0x81 + #define HID_USAGE_PAGE_MONITOR_PAGE2 0x82 + #define HID_USAGE_PAGE_MONITOR_PAGE3 0x83 + #define HID_USAGE_PAGE_POWER_PAGE0 0x84 + #define HID_USAGE_PAGE_POWER_PAGE1 0x85 + #define HID_USAGE_PAGE_POWER_PAGE2 0x86 + #define HID_USAGE_PAGE_POWER_PAGE3 0x87 + #define HID_USAGE_PAGE_BARCODE 0x8C + #define HID_USAGE_PAGE_SCALE 0x8D + #define HID_USAGE_PAGE_MSR 0x8E + + + + + + + +
+      #define WAVE_FORMAT_PCM     1
+    
+
+ + + + + + + + + + sharpdx-core-multimedia + sharpdx-core-multimedia-ext + hidusage + audiodefs + audiosessiontypes + mmreg + + + + + + + + + + + + + + + + + + sharpdx-core-multimedia-ext + hidusage + audiodefs + audiosessiontypes + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/Source/SharpDX/Multimedia/WaveFormat.cs b/Source/SharpDX/Multimedia/WaveFormat.cs index 0ca507ad5..5fe2f9146 100644 --- a/Source/SharpDX/Multimedia/WaveFormat.cs +++ b/Source/SharpDX/Multimedia/WaveFormat.cs @@ -1,537 +1,500 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ----------------------------------------------------------------------------- -// Original code from NAudio project. http://naudio.codeplex.com/ -// Greetings to Mark Heath. -// ----------------------------------------------------------------------------- - -using System; -using System.Globalization; -using System.IO; -using System.Runtime.InteropServices; - -using SharpDX.Serialization; - -namespace SharpDX.Multimedia -{ - /// - /// Represents a Wave file format - /// - /// WAVEFORMATEX - public class WaveFormat : IDataSerializable - { - /// format type - protected WaveFormatEncoding waveFormatTag; - /// number of channels - protected short channels; - /// sample rate - protected int sampleRate; - /// for buffer estimation - protected int averageBytesPerSecond; - /// block size of data - protected short blockAlign; - /// number of bits per sample of mono data - protected short bitsPerSample; - /// number of following bytes - protected short extraSize; - - [StructLayout(LayoutKind.Sequential, Pack = 2)] - internal struct __Native : IDataSerializable - { - public __PcmNative pcmWaveFormat; - /// number of following bytes - public short extraSize; - // Method to free native struct - internal unsafe void __MarshalFree() - { - } - - public void Serialize(BinarySerializer serializer) - { - serializer.Serialize(ref pcmWaveFormat); - serializer.Serialize(ref extraSize); - } - } - - internal unsafe void __MarshalFree(ref __Native @ref) - { - @ref.__MarshalFree(); - } - - // Method to marshal from native to managed struct - internal unsafe void __MarshalFrom(ref __Native @ref) - { - this.waveFormatTag = @ref.pcmWaveFormat.waveFormatTag; - this.channels = @ref.pcmWaveFormat.channels; - this.sampleRate = @ref.pcmWaveFormat.sampleRate; - this.averageBytesPerSecond = @ref.pcmWaveFormat.averageBytesPerSecond; - this.blockAlign = @ref.pcmWaveFormat.blockAlign; - this.bitsPerSample = @ref.pcmWaveFormat.bitsPerSample; - this.extraSize = @ref.extraSize; - } - // Method to marshal from managed struct tot native - internal unsafe void __MarshalTo(ref __Native @ref) - { - @ref.pcmWaveFormat.waveFormatTag = this.waveFormatTag; - @ref.pcmWaveFormat.channels = this.channels; - @ref.pcmWaveFormat.sampleRate = this.sampleRate; - @ref.pcmWaveFormat.averageBytesPerSecond = this.averageBytesPerSecond; - @ref.pcmWaveFormat.blockAlign = this.blockAlign; - @ref.pcmWaveFormat.bitsPerSample = this.bitsPerSample; - @ref.extraSize = this.extraSize; - } - - [StructLayout(LayoutKind.Sequential, Pack = 2)] - internal struct __PcmNative : IDataSerializable - { - /// format type - public WaveFormatEncoding waveFormatTag; - /// number of channels - public short channels; - /// sample rate - public int sampleRate; - /// for buffer estimation - public int averageBytesPerSecond; - /// block size of data - public short blockAlign; - /// number of bits per sample of mono data - public short bitsPerSample; - - // Method to free native struct - internal unsafe void __MarshalFree() - { - } - - public void Serialize(BinarySerializer serializer) - { - serializer.SerializeEnum(ref waveFormatTag); - serializer.Serialize(ref channels); - serializer.Serialize(ref sampleRate); - serializer.Serialize(ref averageBytesPerSecond); - serializer.Serialize(ref blockAlign); - serializer.Serialize(ref bitsPerSample); - } - } - - internal unsafe void __MarshalFree(ref __PcmNative @ref) - { - @ref.__MarshalFree(); - } - - // Method to marshal from native to managed struct - internal unsafe void __MarshalFrom(ref __PcmNative @ref) - { - this.waveFormatTag = @ref.waveFormatTag; - this.channels = @ref.channels; - this.sampleRate = @ref.sampleRate; - this.averageBytesPerSecond = @ref.averageBytesPerSecond; - this.blockAlign = @ref.blockAlign; - this.bitsPerSample = @ref.bitsPerSample; - this.extraSize = 0; - } - // Method to marshal from managed struct tot native - internal unsafe void __MarshalTo(ref __PcmNative @ref) - { - @ref.waveFormatTag = this.waveFormatTag; - @ref.channels = this.channels; - @ref.sampleRate = this.sampleRate; - @ref.averageBytesPerSecond = this.averageBytesPerSecond; - @ref.blockAlign = this.blockAlign; - @ref.bitsPerSample = this.bitsPerSample; - } - - - /// - /// Creates a new PCM 44.1Khz stereo 16 bit format - /// - public WaveFormat() - : this(44100, 16, 2) - { - - } - - /// - /// Creates a new 16 bit wave format with the specified sample - /// rate and channel count - /// - /// Sample Rate - /// Number of channels - public WaveFormat(int sampleRate, int channels) - : this(sampleRate, 16, channels) - { - } - - /// - /// Gets the size of a wave buffer equivalent to the latency in milliseconds. - /// - /// The milliseconds. - /// - public int ConvertLatencyToByteSize(int milliseconds) - { - int bytes = (int)((AverageBytesPerSecond / 1000.0) * milliseconds); - if ((bytes % BlockAlign) != 0) - { - // Return the upper BlockAligned - bytes = bytes + BlockAlign - (bytes % BlockAlign); - } - return bytes; - } - - /// - /// Creates a WaveFormat with custom members - /// - /// The encoding - /// Sample Rate - /// Number of channels - /// Average Bytes Per Second - /// Block Align - /// Bits Per Sample - /// - public static WaveFormat CreateCustomFormat(WaveFormatEncoding tag, int sampleRate, int channels, int averageBytesPerSecond, int blockAlign, int bitsPerSample) - { - var waveFormat = new WaveFormat - { - waveFormatTag = tag, - channels = (short) channels, - sampleRate = sampleRate, - averageBytesPerSecond = averageBytesPerSecond, - blockAlign = (short) blockAlign, - bitsPerSample = (short) bitsPerSample, - extraSize = 0 - }; - return waveFormat; - } - - /// - /// Creates an A-law wave format - /// - /// Sample Rate - /// Number of Channels - /// Wave Format - public static WaveFormat CreateALawFormat(int sampleRate, int channels) - { - return CreateCustomFormat(WaveFormatEncoding.Alaw, sampleRate, channels, sampleRate * channels, 1, 8); - } - - /// - /// Creates a Mu-law wave format - /// - /// Sample Rate - /// Number of Channels - /// Wave Format - public static WaveFormat CreateMuLawFormat(int sampleRate, int channels) - { - return CreateCustomFormat(WaveFormatEncoding.Mulaw, sampleRate, channels, sampleRate * channels, 1, 8); - } - - /// - /// Creates a new PCM format with the specified sample rate, bit depth and channels - /// - public WaveFormat(int rate, int bits, int channels) - { - if (channels < 1) - { - throw new ArgumentOutOfRangeException("channels", "Channels must be 1 or greater"); - } - // minimum 16 bytes, sometimes 18 for PCM - this.waveFormatTag = bits<32?WaveFormatEncoding.Pcm:WaveFormatEncoding.IeeeFloat; - this.channels = (short)channels; - this.sampleRate = rate; - this.bitsPerSample = (short)bits; - this.extraSize = 0; - - this.blockAlign = (short)(channels * (bits / 8)); - this.averageBytesPerSecond = this.sampleRate * this.blockAlign; - } - - /// - /// Creates a new 32 bit IEEE floating point wave format - /// - /// sample rate - /// number of channels - public static WaveFormat CreateIeeeFloatWaveFormat(int sampleRate, int channels) - { - var wf = new WaveFormat - { - waveFormatTag = WaveFormatEncoding.IeeeFloat, - channels = (short) channels, - bitsPerSample = 32, - sampleRate = sampleRate, - blockAlign = (short) (4*channels) - }; - wf.averageBytesPerSecond = sampleRate * wf.blockAlign; - wf.extraSize = 0; - return wf; - } - - /// - /// Helper function to retrieve a WaveFormat structure from a pointer - /// - /// Buffer to the WaveFormat rawdata - /// WaveFormat structure - public unsafe static WaveFormat MarshalFrom(byte[] rawdata) - { - fixed (void* pRawData = rawdata) - return MarshalFrom((IntPtr)pRawData); - } - - /// - /// Helper function to retrieve a WaveFormat structure from a pointer - /// - /// Pointer to the WaveFormat rawdata - /// WaveFormat structure - public unsafe static WaveFormat MarshalFrom(IntPtr pointer) - { - if (pointer == IntPtr.Zero) return null; - - var pcmWaveFormat = *(__PcmNative*)pointer; - var encoding = pcmWaveFormat.waveFormatTag; - - // Load simple PcmWaveFormat if channels <= 2 and encoding is Pcm, IeeFloat, Wmaudio2, Wmaudio3 - // See http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.xaudio2.waveformatex%28v=vs.85%29.aspx - if (pcmWaveFormat.channels <= 2 && (encoding == WaveFormatEncoding.Pcm || encoding == WaveFormatEncoding.IeeeFloat || encoding == WaveFormatEncoding.Wmaudio2 || encoding == WaveFormatEncoding.Wmaudio3)) - { - var waveFormat = new WaveFormat(); - waveFormat.__MarshalFrom(ref pcmWaveFormat); - return waveFormat; - } - - if (encoding == WaveFormatEncoding.Extensible) - { - var waveFormat = new WaveFormatExtensible(); - waveFormat.__MarshalFrom(ref *(WaveFormatExtensible.__Native*)pointer); - return waveFormat; - } - - if (encoding == WaveFormatEncoding.Adpcm) - { - var waveFormat = new WaveFormatAdpcm(); - waveFormat.__MarshalFrom(ref *(WaveFormatAdpcm.__Native*)pointer); - return waveFormat; - } - - throw new InvalidOperationException(string.Format("Unsupported WaveFormat [{0}]", encoding)); - } - - protected unsafe virtual IntPtr MarshalToPtr() - { - var result = Marshal.AllocHGlobal(Utilities.SizeOf()); - __MarshalTo(ref *(WaveFormat.__Native*)result); - return result; - } - - /// - /// Helper function to marshal WaveFormat to an IntPtr - /// - /// WaveFormat - /// IntPtr to WaveFormat structure (needs to be freed by callee) - public static IntPtr MarshalToPtr(WaveFormat format) - { - if (format == null) return IntPtr.Zero; - return format.MarshalToPtr(); - } - - /// - /// Reads a new WaveFormat object from a stream - /// - /// A binary reader that wraps the stream - public WaveFormat(BinaryReader br) - { - int formatChunkLength = br.ReadInt32(); - if (formatChunkLength < 16) - throw new SharpDXException("Invalid WaveFormat Structure"); - this.waveFormatTag = (WaveFormatEncoding)br.ReadUInt16(); - this.channels = br.ReadInt16(); - this.sampleRate = br.ReadInt32(); - this.averageBytesPerSecond = br.ReadInt32(); - this.blockAlign = br.ReadInt16(); - this.bitsPerSample = br.ReadInt16(); - this.extraSize = 0; - if (formatChunkLength > 16) - { - - this.extraSize = br.ReadInt16(); - if (this.extraSize > formatChunkLength - 18) - { -#if !W8CORE - Console.WriteLine("Format chunk mismatch"); -#endif - //RRL GSM exhibits this bug. Don't throw an exception - //throw new ApplicationException("Format chunk length mismatch"); - - this.extraSize = (short)(formatChunkLength - 18); - } - - // read any extra data - // br.ReadBytes(extraSize); - - } - } - - /// - /// Reports this WaveFormat as a string - /// - /// String describing the wave format - public override string ToString() - { - switch (this.waveFormatTag) - { - case WaveFormatEncoding.Pcm: - case WaveFormatEncoding.Extensible: - // extensible just has some extra bits after the PCM header - return string.Format(CultureInfo.InvariantCulture, "{0} bit PCM: {1}kHz {2} channels", - bitsPerSample, sampleRate / 1000, channels); - default: - return this.waveFormatTag.ToString(); - } - } - - /// - /// Compares with another WaveFormat object - /// - /// Object to compare to - /// True if the objects are the same - public override bool Equals(object obj) - { - if (!(obj is WaveFormat)) - return false; - - WaveFormat other = (WaveFormat)obj; - return waveFormatTag == other.waveFormatTag && - channels == other.channels && - sampleRate == other.sampleRate && - averageBytesPerSecond == other.averageBytesPerSecond && - blockAlign == other.blockAlign && - bitsPerSample == other.bitsPerSample; - } - - /// - /// Provides a hash code for this WaveFormat - /// - /// A hash code - public override int GetHashCode() - { - return (int)waveFormatTag ^ - (int)channels ^ - sampleRate ^ - averageBytesPerSecond ^ - (int)blockAlign ^ - (int)bitsPerSample; - } - - /// - /// Reads or writes data from/to the given binary serializer. - /// - /// The binary serializer. - public virtual void Serialize(BinarySerializer serializer) - { - __Native nativeFormat = default(__Native); - if (serializer.Mode == SerializerMode.Read) - { - serializer.Serialize(ref nativeFormat); - this.__MarshalFrom(ref nativeFormat); - } - else - { - this.__MarshalTo(ref nativeFormat); - serializer.Serialize(ref nativeFormat); - } - } - - /// - /// Returns the encoding type used - /// - public WaveFormatEncoding Encoding - { - get - { - return waveFormatTag; - } - } - - /// - /// Returns the number of channels (1=mono,2=stereo etc) - /// - public int Channels - { - get - { - return channels; - } - } - - /// - /// Returns the sample rate (samples per second) - /// - public int SampleRate - { - get - { - return sampleRate; - } - } - - /// - /// Returns the average number of bytes used per second - /// - public int AverageBytesPerSecond - { - get - { - return averageBytesPerSecond; - } - } - - /// - /// Returns the block alignment - /// - public int BlockAlign - { - get - { - return blockAlign; - } - } - - /// - /// Returns the number of bits per sample (usually 16 or 32, sometimes 24 or 8) - /// Can be 0 for some codecs - /// - public int BitsPerSample - { - get - { - return bitsPerSample; - } - } - - /// - /// Returns the number of extra bytes used by this waveformat. Often 0, - /// except for compressed formats which store extra data after the WAVEFORMATEX header - /// - public int ExtraSize - { - get - { - return extraSize; - } - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from NAudio project. http://naudio.codeplex.com/ +// Greetings to Mark Heath. +// ----------------------------------------------------------------------------- + +using System; +using System.Globalization; +using System.IO; +using System.Runtime.InteropServices; + +namespace SharpDX.Multimedia +{ + /// + /// Represents a Wave file format + /// + /// WAVEFORMATEX + public class WaveFormat + { + /// format type + protected WaveFormatEncoding waveFormatTag; + /// number of channels + protected short channels; + /// sample rate + protected int sampleRate; + /// for buffer estimation + protected int averageBytesPerSecond; + /// block size of data + protected short blockAlign; + /// number of bits per sample of mono data + protected short bitsPerSample; + /// number of following bytes + protected short extraSize; + + [StructLayout(LayoutKind.Sequential, Pack = 2)] + internal struct __Native + { + public __PcmNative pcmWaveFormat; + /// number of following bytes + public short extraSize; + // Method to free native struct + internal unsafe void __MarshalFree() + { + } + } + + internal unsafe void __MarshalFree(ref __Native @ref) + { + @ref.__MarshalFree(); + } + + // Method to marshal from native to managed struct + internal unsafe void __MarshalFrom(ref __Native @ref) + { + this.waveFormatTag = @ref.pcmWaveFormat.waveFormatTag; + this.channels = @ref.pcmWaveFormat.channels; + this.sampleRate = @ref.pcmWaveFormat.sampleRate; + this.averageBytesPerSecond = @ref.pcmWaveFormat.averageBytesPerSecond; + this.blockAlign = @ref.pcmWaveFormat.blockAlign; + this.bitsPerSample = @ref.pcmWaveFormat.bitsPerSample; + this.extraSize = @ref.extraSize; + } + // Method to marshal from managed struct tot native + internal unsafe void __MarshalTo(ref __Native @ref) + { + @ref.pcmWaveFormat.waveFormatTag = this.waveFormatTag; + @ref.pcmWaveFormat.channels = this.channels; + @ref.pcmWaveFormat.sampleRate = this.sampleRate; + @ref.pcmWaveFormat.averageBytesPerSecond = this.averageBytesPerSecond; + @ref.pcmWaveFormat.blockAlign = this.blockAlign; + @ref.pcmWaveFormat.bitsPerSample = this.bitsPerSample; + @ref.extraSize = this.extraSize; + } + + [StructLayout(LayoutKind.Sequential, Pack = 2)] + internal struct __PcmNative + { + /// format type + public WaveFormatEncoding waveFormatTag; + /// number of channels + public short channels; + /// sample rate + public int sampleRate; + /// for buffer estimation + public int averageBytesPerSecond; + /// block size of data + public short blockAlign; + /// number of bits per sample of mono data + public short bitsPerSample; + + // Method to free native struct + internal unsafe void __MarshalFree() + { + } + } + + internal unsafe void __MarshalFree(ref __PcmNative @ref) + { + @ref.__MarshalFree(); + } + + // Method to marshal from native to managed struct + internal unsafe void __MarshalFrom(ref __PcmNative @ref) + { + this.waveFormatTag = @ref.waveFormatTag; + this.channels = @ref.channels; + this.sampleRate = @ref.sampleRate; + this.averageBytesPerSecond = @ref.averageBytesPerSecond; + this.blockAlign = @ref.blockAlign; + this.bitsPerSample = @ref.bitsPerSample; + this.extraSize = 0; + } + // Method to marshal from managed struct tot native + internal unsafe void __MarshalTo(ref __PcmNative @ref) + { + @ref.waveFormatTag = this.waveFormatTag; + @ref.channels = this.channels; + @ref.sampleRate = this.sampleRate; + @ref.averageBytesPerSecond = this.averageBytesPerSecond; + @ref.blockAlign = this.blockAlign; + @ref.bitsPerSample = this.bitsPerSample; + } + + + /// + /// Creates a new PCM 44.1Khz stereo 16 bit format + /// + public WaveFormat() + : this(44100, 16, 2) + { + + } + + /// + /// Creates a new 16 bit wave format with the specified sample + /// rate and channel count + /// + /// Sample Rate + /// Number of channels + public WaveFormat(int sampleRate, int channels) + : this(sampleRate, 16, channels) + { + } + + /// + /// Gets the size of a wave buffer equivalent to the latency in milliseconds. + /// + /// The milliseconds. + /// + public int ConvertLatencyToByteSize(int milliseconds) + { + int bytes = (int)((AverageBytesPerSecond / 1000.0) * milliseconds); + if ((bytes % BlockAlign) != 0) + { + // Return the upper BlockAligned + bytes = bytes + BlockAlign - (bytes % BlockAlign); + } + return bytes; + } + + /// + /// Creates a WaveFormat with custom members + /// + /// The encoding + /// Sample Rate + /// Number of channels + /// Average Bytes Per Second + /// Block Align + /// Bits Per Sample + /// + public static WaveFormat CreateCustomFormat(WaveFormatEncoding tag, int sampleRate, int channels, int averageBytesPerSecond, int blockAlign, int bitsPerSample) + { + var waveFormat = new WaveFormat + { + waveFormatTag = tag, + channels = (short) channels, + sampleRate = sampleRate, + averageBytesPerSecond = averageBytesPerSecond, + blockAlign = (short) blockAlign, + bitsPerSample = (short) bitsPerSample, + extraSize = 0 + }; + return waveFormat; + } + + /// + /// Creates an A-law wave format + /// + /// Sample Rate + /// Number of Channels + /// Wave Format + public static WaveFormat CreateALawFormat(int sampleRate, int channels) + { + return CreateCustomFormat(WaveFormatEncoding.Alaw, sampleRate, channels, sampleRate * channels, 1, 8); + } + + /// + /// Creates a Mu-law wave format + /// + /// Sample Rate + /// Number of Channels + /// Wave Format + public static WaveFormat CreateMuLawFormat(int sampleRate, int channels) + { + return CreateCustomFormat(WaveFormatEncoding.Mulaw, sampleRate, channels, sampleRate * channels, 1, 8); + } + + /// + /// Creates a new PCM format with the specified sample rate, bit depth and channels + /// + public WaveFormat(int rate, int bits, int channels) + { + if (channels < 1) + { + throw new ArgumentOutOfRangeException("channels", "Channels must be 1 or greater"); + } + // minimum 16 bytes, sometimes 18 for PCM + this.waveFormatTag = bits<32?WaveFormatEncoding.Pcm:WaveFormatEncoding.IeeeFloat; + this.channels = (short)channels; + this.sampleRate = rate; + this.bitsPerSample = (short)bits; + this.extraSize = 0; + + this.blockAlign = (short)(channels * (bits / 8)); + this.averageBytesPerSecond = this.sampleRate * this.blockAlign; + } + + /// + /// Creates a new 32 bit IEEE floating point wave format + /// + /// sample rate + /// number of channels + public static WaveFormat CreateIeeeFloatWaveFormat(int sampleRate, int channels) + { + var wf = new WaveFormat + { + waveFormatTag = WaveFormatEncoding.IeeeFloat, + channels = (short) channels, + bitsPerSample = 32, + sampleRate = sampleRate, + blockAlign = (short) (4*channels) + }; + wf.averageBytesPerSecond = sampleRate * wf.blockAlign; + wf.extraSize = 0; + return wf; + } + + /// + /// Helper function to retrieve a WaveFormat structure from a pointer + /// + /// Buffer to the WaveFormat rawdata + /// WaveFormat structure + public unsafe static WaveFormat MarshalFrom(byte[] rawdata) + { + fixed (void* pRawData = rawdata) + return MarshalFrom((IntPtr)pRawData); + } + + /// + /// Helper function to retrieve a WaveFormat structure from a pointer + /// + /// Pointer to the WaveFormat rawdata + /// WaveFormat structure + public unsafe static WaveFormat MarshalFrom(IntPtr pointer) + { + if (pointer == IntPtr.Zero) return null; + + var pcmWaveFormat = *(__PcmNative*)pointer; + var encoding = pcmWaveFormat.waveFormatTag; + + // Load simple PcmWaveFormat if channels <= 2 and encoding is Pcm, IeeFloat, Wmaudio2, Wmaudio3 + // See http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.xaudio2.waveformatex%28v=vs.85%29.aspx + if (pcmWaveFormat.channels <= 2 && (encoding == WaveFormatEncoding.Pcm || encoding == WaveFormatEncoding.IeeeFloat || encoding == WaveFormatEncoding.Wmaudio2 || encoding == WaveFormatEncoding.Wmaudio3)) + { + var waveFormat = new WaveFormat(); + waveFormat.__MarshalFrom(ref pcmWaveFormat); + return waveFormat; + } + + if (encoding == WaveFormatEncoding.Extensible) + { + var waveFormat = new WaveFormatExtensible(); + waveFormat.__MarshalFrom(ref *(WaveFormatExtensible.__Native*)pointer); + return waveFormat; + } + + if (encoding == WaveFormatEncoding.Adpcm) + { + var waveFormat = new WaveFormatAdpcm(); + waveFormat.__MarshalFrom(ref *(WaveFormatAdpcm.__Native*)pointer); + return waveFormat; + } + + throw new InvalidOperationException(string.Format("Unsupported WaveFormat [{0}]", encoding)); + } + + protected unsafe virtual IntPtr MarshalToPtr() + { + var result = Marshal.AllocHGlobal(Utilities.SizeOf()); + __MarshalTo(ref *(WaveFormat.__Native*)result); + return result; + } + + /// + /// Helper function to marshal WaveFormat to an IntPtr + /// + /// WaveFormat + /// IntPtr to WaveFormat structure (needs to be freed by callee) + public static IntPtr MarshalToPtr(WaveFormat format) + { + if (format == null) return IntPtr.Zero; + return format.MarshalToPtr(); + } + + /// + /// Reads a new WaveFormat object from a stream + /// + /// A binary reader that wraps the stream + public WaveFormat(BinaryReader br) + { + int formatChunkLength = br.ReadInt32(); + if (formatChunkLength < 16) + throw new SharpDXException("Invalid WaveFormat Structure"); + this.waveFormatTag = (WaveFormatEncoding)br.ReadUInt16(); + this.channels = br.ReadInt16(); + this.sampleRate = br.ReadInt32(); + this.averageBytesPerSecond = br.ReadInt32(); + this.blockAlign = br.ReadInt16(); + this.bitsPerSample = br.ReadInt16(); + this.extraSize = 0; + if (formatChunkLength > 16) + { + + this.extraSize = br.ReadInt16(); + if (this.extraSize > formatChunkLength - 18) + { +#if !W8CORE + Console.WriteLine("Format chunk mismatch"); +#endif + //RRL GSM exhibits this bug. Don't throw an exception + //throw new ApplicationException("Format chunk length mismatch"); + + this.extraSize = (short)(formatChunkLength - 18); + } + + // read any extra data + // br.ReadBytes(extraSize); + + } + } + + /// + /// Reports this WaveFormat as a string + /// + /// String describing the wave format + public override string ToString() + { + switch (this.waveFormatTag) + { + case WaveFormatEncoding.Pcm: + case WaveFormatEncoding.Extensible: + // extensible just has some extra bits after the PCM header + return string.Format(CultureInfo.InvariantCulture, "{0} bit PCM: {1}kHz {2} channels", + bitsPerSample, sampleRate / 1000, channels); + default: + return this.waveFormatTag.ToString(); + } + } + + /// + /// Compares with another WaveFormat object + /// + /// Object to compare to + /// True if the objects are the same + public override bool Equals(object obj) + { + if (!(obj is WaveFormat)) + return false; + + WaveFormat other = (WaveFormat)obj; + return waveFormatTag == other.waveFormatTag && + channels == other.channels && + sampleRate == other.sampleRate && + averageBytesPerSecond == other.averageBytesPerSecond && + blockAlign == other.blockAlign && + bitsPerSample == other.bitsPerSample; + } + + /// + /// Provides a hash code for this WaveFormat + /// + /// A hash code + public override int GetHashCode() + { + return (int)waveFormatTag ^ + (int)channels ^ + sampleRate ^ + averageBytesPerSecond ^ + (int)blockAlign ^ + (int)bitsPerSample; + } + + /// + /// Returns the encoding type used + /// + public WaveFormatEncoding Encoding + { + get + { + return waveFormatTag; + } + } + + /// + /// Returns the number of channels (1=mono,2=stereo etc) + /// + public int Channels + { + get + { + return channels; + } + } + + /// + /// Returns the sample rate (samples per second) + /// + public int SampleRate + { + get + { + return sampleRate; + } + } + + /// + /// Returns the average number of bytes used per second + /// + public int AverageBytesPerSecond + { + get + { + return averageBytesPerSecond; + } + } + + /// + /// Returns the block alignment + /// + public int BlockAlign + { + get + { + return blockAlign; + } + } + + /// + /// Returns the number of bits per sample (usually 16 or 32, sometimes 24 or 8) + /// Can be 0 for some codecs + /// + public int BitsPerSample + { + get + { + return bitsPerSample; + } + } + + /// + /// Returns the number of extra bytes used by this waveformat. Often 0, + /// except for compressed formats which store extra data after the WAVEFORMATEX header + /// + public int ExtraSize + { + get + { + return extraSize; + } + } + } +} diff --git a/Source/SharpDX/Multimedia/WaveFormatExtensible.cs b/Source/SharpDX/Multimedia/WaveFormatExtensible.cs index a03e792af..27882987b 100644 --- a/Source/SharpDX/Multimedia/WaveFormatExtensible.cs +++ b/Source/SharpDX/Multimedia/WaveFormatExtensible.cs @@ -1,138 +1,138 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ----------------------------------------------------------------------------- -// Original code from NAudio project. http://naudio.codeplex.com/ -// Greetings to Mark Heath. -// ----------------------------------------------------------------------------- - -using System; -using System.Globalization; -using System.Runtime.InteropServices; - -namespace SharpDX.Multimedia -{ - /// - /// WaveFormatExtensible - /// http://www.microsoft.com/whdc/device/audio/multichaud.mspx - /// - /// WAVEFORMATEXTENSIBLE - public class WaveFormatExtensible : WaveFormat - { - short wValidBitsPerSample; // bits of precision, or is wSamplesPerBlock if wBitsPerSample==0 - - /// - /// Guid of the subformat. - /// - public Guid GuidSubFormat; - - /// - /// Speaker configuration - /// - public Speakers ChannelMask; // which channels are present in stream - - - /// - /// Parameterless constructor for marshalling - /// - internal WaveFormatExtensible() - { - } - - /// - /// Creates a new WaveFormatExtensible for PCM or IEEE - /// - public WaveFormatExtensible(int rate, int bits, int channels) - : base(rate, bits, channels) - { - waveFormatTag = WaveFormatEncoding.Extensible; - extraSize = 22; - wValidBitsPerSample = (short)bits; - int dwChannelMask = 0; - for (int n = 0; n < channels; n++) - dwChannelMask |= (1 << n); - ChannelMask = (Speakers)dwChannelMask; - - // KSDATAFORMAT_SUBTYPE_IEEE_FLOAT // AudioMediaSubtypes.MEDIASUBTYPE_IEEE_FLOAT - // KSDATAFORMAT_SUBTYPE_PCM // AudioMediaSubtypes.MEDIASUBTYPE_PCM; - GuidSubFormat = bits == 32 ? new Guid("00000003-0000-0010-8000-00aa00389b71") : new Guid("00000001-0000-0010-8000-00aa00389b71"); - } - - protected unsafe override IntPtr MarshalToPtr() - { - var result = Marshal.AllocHGlobal(Utilities.SizeOf()); - __MarshalTo(ref *(WaveFormatExtensible.__Native*)result); - return result; - } - - [StructLayout(LayoutKind.Sequential, Pack = 2)] - internal new struct __Native - { - public WaveFormat.__Native waveFormat; - public short wValidBitsPerSample; // bits of precision, or is wSamplesPerBlock if wBitsPerSample==0 - public Speakers dwChannelMask; // which channels are present in stream - public Guid subFormat; - - // Method to free native struct - internal unsafe void __MarshalFree() - { - waveFormat.__MarshalFree(); - } - } - // Method to marshal from native to managed struct - internal unsafe void __MarshalFrom(ref __Native @ref) - { - this.__MarshalFrom(ref @ref.waveFormat); - this.wValidBitsPerSample = @ref.wValidBitsPerSample; - this.ChannelMask = @ref.dwChannelMask; - this.GuidSubFormat = @ref.subFormat; - } - // Method to marshal from managed struct tot native - internal unsafe void __MarshalTo(ref __Native @ref) - { - this.__MarshalTo(ref @ref.waveFormat); - @ref.wValidBitsPerSample = this.wValidBitsPerSample; - @ref.dwChannelMask = this.ChannelMask; - @ref.subFormat = this.GuidSubFormat; - } - - internal static __Native __NewNative() - { - unsafe - { - __Native temp = default(__Native); - temp.waveFormat.extraSize = 22; - return temp; - } - } - - /// - /// String representation - /// - public override string ToString() - { - return String.Format(CultureInfo.InvariantCulture, "{0} wBitsPerSample:{1} ChannelMask:{2} SubFormat:{3} extraSize:{4}", - base.ToString(), - wValidBitsPerSample, - ChannelMask, - GuidSubFormat, - extraSize); - } - } +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from NAudio project. http://naudio.codeplex.com/ +// Greetings to Mark Heath. +// ----------------------------------------------------------------------------- + +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SharpDX.Multimedia +{ + /// + /// WaveFormatExtensible + /// http://www.microsoft.com/whdc/device/audio/multichaud.mspx + /// + /// WAVEFORMATEXTENSIBLE + public class WaveFormatExtensible : WaveFormat + { + short wValidBitsPerSample; // bits of precision, or is wSamplesPerBlock if wBitsPerSample==0 + + /// + /// Guid of the subformat. + /// + public Guid GuidSubFormat; + + /// + /// Speaker configuration + /// + public Speakers ChannelMask; // which channels are present in stream + + + /// + /// Parameterless constructor for marshalling + /// + internal WaveFormatExtensible() + { + } + + /// + /// Creates a new WaveFormatExtensible for PCM or IEEE + /// + public WaveFormatExtensible(int rate, int bits, int channels) + : base(rate, bits, channels) + { + waveFormatTag = WaveFormatEncoding.Extensible; + extraSize = 22; + wValidBitsPerSample = (short)bits; + int dwChannelMask = 0; + for (int n = 0; n < channels; n++) + dwChannelMask |= (1 << n); + ChannelMask = (Speakers)dwChannelMask; + + // KSDATAFORMAT_SUBTYPE_IEEE_FLOAT // AudioMediaSubtypes.MEDIASUBTYPE_IEEE_FLOAT + // KSDATAFORMAT_SUBTYPE_PCM // AudioMediaSubtypes.MEDIASUBTYPE_PCM; + GuidSubFormat = bits == 32 ? new Guid("00000003-0000-0010-8000-00aa00389b71") : new Guid("00000001-0000-0010-8000-00aa00389b71"); + } + + protected unsafe override IntPtr MarshalToPtr() + { + var result = Marshal.AllocHGlobal(Utilities.SizeOf()); + __MarshalTo(ref *(WaveFormatExtensible.__Native*)result); + return result; + } + + [StructLayout(LayoutKind.Sequential, Pack = 2)] + internal new struct __Native + { + public WaveFormat.__Native waveFormat; + public short wValidBitsPerSample; // bits of precision, or is wSamplesPerBlock if wBitsPerSample==0 + public Speakers dwChannelMask; // which channels are present in stream + public Guid subFormat; + + // Method to free native struct + internal unsafe void __MarshalFree() + { + waveFormat.__MarshalFree(); + } + } + // Method to marshal from native to managed struct + internal unsafe void __MarshalFrom(ref __Native @ref) + { + this.__MarshalFrom(ref @ref.waveFormat); + this.wValidBitsPerSample = @ref.wValidBitsPerSample; + this.ChannelMask = @ref.dwChannelMask; + this.GuidSubFormat = @ref.subFormat; + } + // Method to marshal from managed struct tot native + internal unsafe void __MarshalTo(ref __Native @ref) + { + this.__MarshalTo(ref @ref.waveFormat); + @ref.wValidBitsPerSample = this.wValidBitsPerSample; + @ref.dwChannelMask = this.ChannelMask; + @ref.subFormat = this.GuidSubFormat; + } + + internal static __Native __NewNative() + { + unsafe + { + __Native temp = default(__Native); + temp.waveFormat.extraSize = 22; + return temp; + } + } + + /// + /// String representation + /// + public override string ToString() + { + return String.Format(CultureInfo.InvariantCulture, "{0} wBitsPerSample:{1} ChannelMask:{2} SubFormat:{3} extraSize:{4}", + base.ToString(), + wValidBitsPerSample, + ChannelMask, + GuidSubFormat, + extraSize); + } + } } \ No newline at end of file diff --git a/Source/SharpDX/Result.cs b/Source/SharpDX/Result.cs index 6361f7471..06cd2c543 100644 --- a/Source/SharpDX/Result.cs +++ b/Source/SharpDX/Result.cs @@ -1,311 +1,304 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Runtime.InteropServices; -using SharpDX.Serialization; - -namespace SharpDX -{ - /// - /// Result structure for COM methods. - /// - [StructLayout(LayoutKind.Sequential)] - public struct Result : IEquatable, IDataSerializable - { - private int _code; - - /// - /// Initializes a new instance of the struct. - /// - /// The HRESULT error code. - public Result(int code) - { - _code = code; - } - - /// - /// Initializes a new instance of the struct. - /// - /// The HRESULT error code. - public Result(uint code) - { - _code = unchecked((int)code); - } - - /// - /// Gets the HRESULT error code. - /// - /// The HRESULT error code. - public int Code - { - get { return _code; } - } - - /// - /// Gets a value indicating whether this is success. - /// - /// true if success; otherwise, false. - public bool Success - { - get { return Code >= 0; } - } - - /// - /// Gets a value indicating whether this is failure. - /// - /// true if failure; otherwise, false. - public bool Failure - { - get { return Code < 0; } - } - - /// - /// Performs an implicit conversion from to . - /// - /// The result. - /// The result of the conversion. - public static explicit operator int(Result result) - { - return result.Code; - } - - /// - /// Performs an implicit conversion from to . - /// - /// The result. - /// The result of the conversion. - public static explicit operator uint(Result result) - { - return unchecked((uint)result.Code); - } - - /// - /// Performs an implicit conversion from to . - /// - /// The result. - /// The result of the conversion. - public static implicit operator Result(int result) - { - return new Result(result); - } - - /// - /// Performs an implicit conversion from to . - /// - /// The result. - /// The result of the conversion. - public static implicit operator Result(uint result) - { - return new Result(result); - } - - /// - /// Indicates whether the current object is equal to another object of the same type. - /// - /// An object to compare with this object. - /// - /// true if the current object is equal to the parameter; otherwise, false. - /// - public bool Equals(Result other) - { - return this.Code == other.Code; - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object obj) - { - if (!(obj is Result)) - return false; - return Equals((Result) obj); - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - return Code; - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - serializer.Serialize(ref _code); - } - - /// - /// Implements the operator ==. - /// - /// The left. - /// The right. - /// The result of the operator. - public static bool operator ==(Result left, Result right) - { - return left.Code == right.Code; - } - - /// - /// Implements the operator !=. - /// - /// The left. - /// The right. - /// The result of the operator. - public static bool operator !=(Result left, Result right) - { - return left.Code != right.Code; - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return string.Format(System.Globalization.CultureInfo.InvariantCulture, "HRESULT = 0x{0:X}", _code); - } - - /// - /// Checks the error. - /// - public void CheckError() - { - if (_code < 0) - { - throw new SharpDXException(this); - } - } - - /// - /// Gets a from an . - /// - /// The exception - /// The associated result code - public static Result GetResultFromException(Exception ex) - { - return new Result(Marshal.GetHRForException(ex)); - } - - /// - /// Gets the result from win32 error. - /// - /// The win32Error. - /// A HRESULT. - public static Result GetResultFromWin32Error(int win32Error) - { - const int FACILITY_WIN32 = 7; - return win32Error <= 0 ? win32Error : (int)((win32Error & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000); - } - - /// - /// Result code Ok - /// - /// S_OK - public readonly static Result Ok = new Result(unchecked((int)0x00000000)); - - /// - /// Result code False - /// - /// S_FALSE - public readonly static Result False = new Result(unchecked((int)0x00000001)); - - /// - /// Result code Abort - /// - /// E_ABORT - public static readonly SharpDX.ResultDescriptor Abort = new SharpDX.ResultDescriptor(unchecked((int)0x80004004), "General", "E_ABORT", "Operation aborted"); - - /// - /// Result code AccessDenied - /// - /// E_ACCESSDENIED - public static readonly SharpDX.ResultDescriptor AccessDenied = new SharpDX.ResultDescriptor(unchecked((int)0x80070005), "General", "E_ACCESSDENIED", "General access denied error"); - - /// - /// Result code Fail - /// - /// E_FAIL - public static readonly SharpDX.ResultDescriptor Fail = new SharpDX.ResultDescriptor(unchecked((int)0x80004005), "General", "E_FAIL", "Unspecified error"); - - /// - /// Result code Handle - /// - /// E_HANDLE - public static readonly SharpDX.ResultDescriptor Handle = new SharpDX.ResultDescriptor(unchecked((int)0x80070006), "General", "E_HANDLE", "Invalid handle"); - - /// - /// Result code invalid argument - /// - /// E_INVALIDARG - public static readonly SharpDX.ResultDescriptor InvalidArg = new SharpDX.ResultDescriptor(unchecked((int)0x80070057), "General", "E_INVALIDARG", "Invalid Arguments"); - - /// - /// Result code no interface - /// - /// E_NOINTERFACE - public static readonly SharpDX.ResultDescriptor NoInterface = new SharpDX.ResultDescriptor(unchecked((int)0x80004002), "General", "E_NOINTERFACE", "No such interface supported"); - - /// - /// Result code not implemented - /// - /// E_NOTIMPL - public static readonly SharpDX.ResultDescriptor NotImplemented = new SharpDX.ResultDescriptor(unchecked((int)0x80004001), "General", "E_NOTIMPL", "Not implemented"); - - /// - /// Result code out of memory - /// - /// E_OUTOFMEMORY - public static readonly SharpDX.ResultDescriptor OutOfMemory = new SharpDX.ResultDescriptor(unchecked((int)0x8007000E), "General", "E_OUTOFMEMORY", "Out of memory"); - - /// - /// Result code Invalid pointer - /// - /// E_POINTER - public static readonly SharpDX.ResultDescriptor InvalidPointer = new SharpDX.ResultDescriptor(unchecked((int)0x80004003), "General", "E_POINTER", "Invalid pointer"); - - /// - /// Unexpected failure - /// - /// E_UNEXPECTED - public static readonly SharpDX.ResultDescriptor UnexpectedFailure = new SharpDX.ResultDescriptor(unchecked((int)0x8000FFFF), "General", "E_UNEXPECTED", "Catastrophic failure"); - - /// - /// Result of a wait abandonned. - /// - /// WAIT_ABANDONED - public static readonly SharpDX.ResultDescriptor WaitAbandoned = new SharpDX.ResultDescriptor(unchecked((int)0x00000080L), "General", "WAIT_ABANDONED", "WaitAbandoned"); - - /// - /// Result of a wait timeout. - /// - /// WAIT_TIMEOUT - public static readonly SharpDX.ResultDescriptor WaitTimeout = new SharpDX.ResultDescriptor(unchecked((int)0x00000102L), "General", "WAIT_TIMEOUT", "WaitTimeout"); - } +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Runtime.InteropServices; + +namespace SharpDX +{ + /// + /// Result structure for COM methods. + /// + [StructLayout(LayoutKind.Sequential)] + public struct Result : IEquatable + { + private int _code; + + /// + /// Initializes a new instance of the struct. + /// + /// The HRESULT error code. + public Result(int code) + { + _code = code; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The HRESULT error code. + public Result(uint code) + { + _code = unchecked((int)code); + } + + /// + /// Gets the HRESULT error code. + /// + /// The HRESULT error code. + public int Code + { + get { return _code; } + } + + /// + /// Gets a value indicating whether this is success. + /// + /// true if success; otherwise, false. + public bool Success + { + get { return Code >= 0; } + } + + /// + /// Gets a value indicating whether this is failure. + /// + /// true if failure; otherwise, false. + public bool Failure + { + get { return Code < 0; } + } + + /// + /// Performs an implicit conversion from to . + /// + /// The result. + /// The result of the conversion. + public static explicit operator int(Result result) + { + return result.Code; + } + + /// + /// Performs an implicit conversion from to . + /// + /// The result. + /// The result of the conversion. + public static explicit operator uint(Result result) + { + return unchecked((uint)result.Code); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The result. + /// The result of the conversion. + public static implicit operator Result(int result) + { + return new Result(result); + } + + /// + /// Performs an implicit conversion from to . + /// + /// The result. + /// The result of the conversion. + public static implicit operator Result(uint result) + { + return new Result(result); + } + + /// + /// Indicates whether the current object is equal to another object of the same type. + /// + /// An object to compare with this object. + /// + /// true if the current object is equal to the parameter; otherwise, false. + /// + public bool Equals(Result other) + { + return this.Code == other.Code; + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(object obj) + { + if (!(obj is Result)) + return false; + return Equals((Result) obj); + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + return Code; + } + + /// + /// Implements the operator ==. + /// + /// The left. + /// The right. + /// The result of the operator. + public static bool operator ==(Result left, Result right) + { + return left.Code == right.Code; + } + + /// + /// Implements the operator !=. + /// + /// The left. + /// The right. + /// The result of the operator. + public static bool operator !=(Result left, Result right) + { + return left.Code != right.Code; + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return string.Format(System.Globalization.CultureInfo.InvariantCulture, "HRESULT = 0x{0:X}", _code); + } + + /// + /// Checks the error. + /// + public void CheckError() + { + if (_code < 0) + { + throw new SharpDXException(this); + } + } + + /// + /// Gets a from an . + /// + /// The exception + /// The associated result code + public static Result GetResultFromException(Exception ex) + { + return new Result(Marshal.GetHRForException(ex)); + } + + /// + /// Gets the result from win32 error. + /// + /// The win32Error. + /// A HRESULT. + public static Result GetResultFromWin32Error(int win32Error) + { + const int FACILITY_WIN32 = 7; + return win32Error <= 0 ? win32Error : (int)((win32Error & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000); + } + + /// + /// Result code Ok + /// + /// S_OK + public readonly static Result Ok = new Result(unchecked((int)0x00000000)); + + /// + /// Result code False + /// + /// S_FALSE + public readonly static Result False = new Result(unchecked((int)0x00000001)); + + /// + /// Result code Abort + /// + /// E_ABORT + public static readonly SharpDX.ResultDescriptor Abort = new SharpDX.ResultDescriptor(unchecked((int)0x80004004), "General", "E_ABORT", "Operation aborted"); + + /// + /// Result code AccessDenied + /// + /// E_ACCESSDENIED + public static readonly SharpDX.ResultDescriptor AccessDenied = new SharpDX.ResultDescriptor(unchecked((int)0x80070005), "General", "E_ACCESSDENIED", "General access denied error"); + + /// + /// Result code Fail + /// + /// E_FAIL + public static readonly SharpDX.ResultDescriptor Fail = new SharpDX.ResultDescriptor(unchecked((int)0x80004005), "General", "E_FAIL", "Unspecified error"); + + /// + /// Result code Handle + /// + /// E_HANDLE + public static readonly SharpDX.ResultDescriptor Handle = new SharpDX.ResultDescriptor(unchecked((int)0x80070006), "General", "E_HANDLE", "Invalid handle"); + + /// + /// Result code invalid argument + /// + /// E_INVALIDARG + public static readonly SharpDX.ResultDescriptor InvalidArg = new SharpDX.ResultDescriptor(unchecked((int)0x80070057), "General", "E_INVALIDARG", "Invalid Arguments"); + + /// + /// Result code no interface + /// + /// E_NOINTERFACE + public static readonly SharpDX.ResultDescriptor NoInterface = new SharpDX.ResultDescriptor(unchecked((int)0x80004002), "General", "E_NOINTERFACE", "No such interface supported"); + + /// + /// Result code not implemented + /// + /// E_NOTIMPL + public static readonly SharpDX.ResultDescriptor NotImplemented = new SharpDX.ResultDescriptor(unchecked((int)0x80004001), "General", "E_NOTIMPL", "Not implemented"); + + /// + /// Result code out of memory + /// + /// E_OUTOFMEMORY + public static readonly SharpDX.ResultDescriptor OutOfMemory = new SharpDX.ResultDescriptor(unchecked((int)0x8007000E), "General", "E_OUTOFMEMORY", "Out of memory"); + + /// + /// Result code Invalid pointer + /// + /// E_POINTER + public static readonly SharpDX.ResultDescriptor InvalidPointer = new SharpDX.ResultDescriptor(unchecked((int)0x80004003), "General", "E_POINTER", "Invalid pointer"); + + /// + /// Unexpected failure + /// + /// E_UNEXPECTED + public static readonly SharpDX.ResultDescriptor UnexpectedFailure = new SharpDX.ResultDescriptor(unchecked((int)0x8000FFFF), "General", "E_UNEXPECTED", "Catastrophic failure"); + + /// + /// Result of a wait abandonned. + /// + /// WAIT_ABANDONED + public static readonly SharpDX.ResultDescriptor WaitAbandoned = new SharpDX.ResultDescriptor(unchecked((int)0x00000080L), "General", "WAIT_ABANDONED", "WaitAbandoned"); + + /// + /// Result of a wait timeout. + /// + /// WAIT_TIMEOUT + public static readonly SharpDX.ResultDescriptor WaitTimeout = new SharpDX.ResultDescriptor(unchecked((int)0x00000102L), "General", "WAIT_TIMEOUT", "WaitTimeout"); + } } \ No newline at end of file diff --git a/Source/SharpDX/SharpDX.csproj b/Source/SharpDX/SharpDX.csproj index 584ab4cff..43a0bcb3a 100644 --- a/Source/SharpDX/SharpDX.csproj +++ b/Source/SharpDX/SharpDX.csproj @@ -1,230 +1,194 @@ - - - - - 8.0.30703 - 2.0 - {D0BCD56A-41C4-4A4E-8590-26864CED07FF} - SharpDX - SharpDX - - true - - - - - - - - - - Properties\SharedAssemblyInfo.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - True - Resources.resx - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - UserControl - - - Form - - - - - - Designer - - - Designer - - - - Designer - - - Designer - - - - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - - - - - + + + + + 8.0.30703 + 2.0 + {D0BCD56A-41C4-4A4E-8590-26864CED07FF} + SharpDX + SharpDX + + true + + + + + + + + + + Properties\SharedAssemblyInfo.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Designer + + + Designer + + + + Designer + + + Designer + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + \ No newline at end of file diff --git a/Source/SharpDX/Utilities.cs b/Source/SharpDX/Utilities.cs index fba08fad8..dcdc8f423 100644 --- a/Source/SharpDX/Utilities.cs +++ b/Source/SharpDX/Utilities.cs @@ -1,1661 +1,1661 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Reflection.Emit; -using System.Runtime.InteropServices; -using System.Security; -using System.Text; -using System.Threading; - -using SharpDX.Direct3D; -using System.Reflection; -#if W8CORE -using System.Threading.Tasks; -using System.Linq; -using System.Linq.Expressions; -using SharpDX.Text; - -#endif - -namespace SharpDX -{ - -#if !NET35Plus - /// - /// Encapsulates a method that has no parameters and returns a value of the type specified by the TResult parameter. - /// - /// The type of the return value of the method that this delegate encapsulates. This type parameter is covariant. That is, you can use either the type you specified or any type that is more derived. - /// The return value of the method that this delegate encapsulates. - public delegate TResult Func(); - public delegate TResult Func(T1 paramT1); - public delegate TResult Func(T1 paramT1, T2 paramT2); - - public delegate void Action(); - public delegate void Action(T1 paramT1, T2 paramT2); -#endif - - /// - /// A Delegate to get a property value from an object. - /// - /// Type of the getter. - /// The obj to get the property from. - /// The value to get. - public delegate void GetValueFastDelegate(object obj, out T value); - - /// - /// A Delegate to set a property value to an object. - /// - /// Type of the setter. - /// The obj to set the property from. - /// The value to set. - public delegate void SetValueFastDelegate(object obj, ref T value); - - /// - /// Utility class. - /// - public static class Utilities - { - ///// - ///// Native memcpy. - ///// - ///// The destination memory location. - ///// The source memory location. - ///// The count. - ///// - //[DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, - // SetLastError = false), SuppressUnmanagedCodeSecurity] - //public static extern IntPtr CopyMemory(IntPtr dest, IntPtr src, ulong sizeInBytesToCopy); - - /// - /// Native memcpy. - /// - /// The destination memory location. - /// The source memory location. - /// The byte count. - public static void CopyMemory(IntPtr dest, IntPtr src, int sizeInBytesToCopy) - { - unsafe - { - // TODO plug in Interop a pluggable CopyMemory using cpblk or memcpy based on architecture - Interop.memcpy((void*)dest, (void*)src, sizeInBytesToCopy); - } - } - - /// - /// Compares two block of memory. - /// - /// The pointer to compare from. - /// The pointer to compare against. - /// The size in bytes to compare. - /// true if the buffers are equivalent; otherwise, false. - public unsafe static bool CompareMemory(IntPtr from, IntPtr against, int sizeToCompare) - { - var pSrc = (byte*)@from; - var pDst = (byte*)against; - - // Compare 8 bytes. - int numberOf = sizeToCompare >> 3; - while (numberOf > 0) - { - if (*(long*)pSrc != *(long*)pDst) - return false; - pSrc += 8; - pDst += 8; - numberOf--; - } - - // Compare remaining bytes. - numberOf = sizeToCompare & 7; - while (numberOf > 0) - { - if (*pSrc != *pDst) - return false; - pSrc++; - pDst++; - numberOf--; - } - - return true; - } - - /// - /// Clears the memory. - /// - /// The dest. - /// The value. - /// The size in bytes to clear. - public static void ClearMemory(IntPtr dest, byte value, int sizeInBytesToClear) - { - unsafe - { - Interop.memset((void*)dest, value, sizeInBytesToClear); - } - } - - /// - /// Return the sizeof a struct from a CLR. Equivalent to sizeof operator but works on generics too. - /// - /// A struct to evaluate. - /// Size of this struct. - public static int SizeOf() where T : struct - { - return Interop.SizeOf(); - } - - /// - /// Return the sizeof an array of struct. Equivalent to sizeof operator but works on generics too. - /// - /// A struct. - /// The array of struct to evaluate. - /// Size in bytes of this array of struct. - public static int SizeOf(T[] array) where T : struct - { - return array == null ? 0 : array.Length * Interop.SizeOf(); - } - - /// - /// Pins the specified source and call an action with the pinned pointer. - /// - /// The type of the structure to pin. - /// The source. - /// The pin action to perform on the pinned pointer. - public static void Pin(ref T source, Action pinAction) where T : struct - { - unsafe - { - pinAction((IntPtr)Interop.Fixed(ref source)); - } - } - - /// - /// Pins the specified source and call an action with the pinned pointer. - /// - /// The type of the structure to pin. - /// The source array. - /// The pin action to perform on the pinned pointer. - public static void Pin(T[] source, Action pinAction) where T : struct - { - unsafe - { - pinAction(source == null ? IntPtr.Zero : (IntPtr)Interop.Fixed(source)); - } - } - - /// - /// Converts a structured array to an equivalent byte array. - /// - /// The type of source array. - /// The source array. - /// Converted byte array. - public static byte[] ToByteArray(T[] source) where T : struct - { - if (source == null) return null; - - var buffer = new byte[SizeOf() * source.Length]; - - if (source.Length == 0) - return buffer; - - unsafe - { - fixed (void* pBuffer = buffer) - Interop.Write(pBuffer, source, 0, source.Length); - } - return buffer; - } - - /// - /// Swaps the value between two references. - /// - /// Type of a data to swap. - /// The left value. - /// The right value. - public static void Swap(ref T left, ref T right) - { - var temp = left; - left = right; - right = temp; - } - - /// - /// Reads the specified T data from a memory location. - /// - /// Type of a data to read. - /// Memory location to read from. - /// The data read from the memory location. - public static T Read(IntPtr source) where T : struct - { - unsafe - { - return Interop.ReadInline((void*)source); - } - } - - /// - /// Reads the specified T data from a memory location. - /// - /// Type of a data to read. - /// Memory location to read from. - /// The data write to. - /// source pointer + sizeof(T). - public static void Read(IntPtr source, ref T data) where T : struct - { - unsafe - { - Interop.CopyInline(ref data, (void*)source); - } - } - - /// - /// Reads the specified T data from a memory location. - /// - /// Type of a data to read. - /// Memory location to read from. - /// The data write to. - /// source pointer + sizeof(T). - public static void ReadOut(IntPtr source, out T data) where T : struct - { - unsafe - { - Interop.CopyInlineOut(out data, (void*)source); - } - } - - /// - /// Reads the specified T data from a memory location. - /// - /// Type of a data to read. - /// Memory location to read from. - /// The data write to. - /// source pointer + sizeof(T). - public static IntPtr ReadAndPosition(IntPtr source, ref T data) where T : struct - { - unsafe - { - return (IntPtr)Interop.Read((void*)source, ref data); - } - } - - /// - /// Reads the specified array T[] data from a memory location. - /// - /// Type of a data to read. - /// Memory location to read from. - /// The data write to. - /// The offset in the array to write to. - /// The number of T element to read from the memory location. - /// source pointer + sizeof(T) * count. - public static IntPtr Read(IntPtr source, T[] data, int offset, int count) where T : struct - { - unsafe - { - return (IntPtr)Interop.Read((void*)source, data, offset, count); - } - } - - /// - /// Writes the specified T data to a memory location. - /// - /// Type of a data to write. - /// Memory location to write to. - /// The data to write. - /// destination pointer + sizeof(T). - public static void Write(IntPtr destination, ref T data) where T : struct - { - unsafe - { - Interop.CopyInline((void*)destination, ref data); - } - } - - /// - /// Writes the specified T data to a memory location. - /// - /// Type of a data to write. - /// Memory location to write to. - /// The data to write. - /// destination pointer + sizeof(T). - public static IntPtr WriteAndPosition(IntPtr destination, ref T data) where T : struct - { - unsafe - { - return (IntPtr)Interop.Write((void*)destination, ref data); - } - } - - /// - /// Writes the specified array T[] data to a memory location. - /// - /// Type of a data to write. - /// Memory location to write to. - /// The array of T data to write. - /// The offset in the array to read from. - /// The number of T element to write to the memory location. - /// destination pointer + sizeof(T) * count. - public static IntPtr Write(IntPtr destination, T[] data, int offset, int count) where T : struct - { - unsafe - { - return (IntPtr)Interop.Write((void*)destination, data, offset, count); - } - } - - /// - /// Converts bool array to integer pointers array. - /// - /// The bool array. - /// The destination array of int pointers. - public unsafe static void ConvertToIntArray(bool[] array, int* dest) - { - for (int i = 0; i < array.Length; i++) - dest[i] = array[i] ? 1 : 0; - } - - /// - /// Converts bool array to array. - /// - /// The bool array. - /// Converted array of . - public static Bool[] ConvertToIntArray(bool[] array) - { - var temp = new Bool[array.Length]; - for (int i = 0; i < temp.Length; i++) - temp[i] = array[i]; - return temp; - } - - /// - /// Converts integer pointer array to bool array. - /// - /// The array of integer pointers. - /// Array size. - /// Converted array of bool. - public unsafe static bool[] ConvertToBoolArray(int* array, int length) - { - var temp = new bool[length]; - for (int i = 0; i < temp.Length; i++) - temp[i] = array[i] != 0; - return temp; - } - - /// - /// Converts array to bool array. - /// - /// The array. - /// Converted array of bool. - public static bool[] ConvertToBoolArray(Bool[] array) - { - var temp = new bool[array.Length]; - for (int i = 0; i < temp.Length; i++) - temp[i] = array[i]; - return temp; - } - - /// - /// Gets the from a type. - /// - /// The type. - /// The guid associated with this type. - public static Guid GetGuidFromType(Type type) - { -#if W8CORE - return type.GetTypeInfo().GUID; -#else - return type.GUID; -#endif - } - - /// - /// Determines whether a given type inherits from a generic type. - /// - /// Type of the class to check if it inherits from generic type. - /// Type of the generic. - /// true if [is assignable to generic type] [the specified given type]; otherwise, false. - public static bool IsAssignableToGenericType(Type givenType, Type genericType) - { -#if W8CORE - throw new NotImplementedException(); -#else - // from http://stackoverflow.com/a/1075059/1356325 - var interfaceTypes = givenType.GetInterfaces(); - - foreach (var it in interfaceTypes) - { - if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType) - return true; - } - - if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType) - return true; - - Type baseType = givenType.BaseType; - if (baseType == null) return false; - - return IsAssignableToGenericType(baseType, genericType); -#endif - } - - /// - /// Allocate an aligned memory buffer. - /// - /// Size of the buffer to allocate. - /// Alignment, 16 bytes by default. - /// A pointer to a buffer aligned. - /// - /// To free this buffer, call . - /// - public unsafe static IntPtr AllocateMemory(int sizeInBytes, int align = 16) - { - int mask = align - 1; - var memPtr = Marshal.AllocHGlobal(sizeInBytes + mask + IntPtr.Size); - var ptr = (long)((byte*)memPtr + sizeof(void*) + mask) & ~mask; - ((IntPtr*)ptr)[-1] = memPtr; - return new IntPtr(ptr); - } - - /// - /// Allocate an aligned memory buffer and clear it with a specified value (0 by default). - /// - /// Size of the buffer to allocate. - /// Default value used to clear the buffer. - /// Alignment, 16 bytes by default. - /// A pointer to a buffer aligned. - /// - /// To free this buffer, call . - /// - public static IntPtr AllocateClearedMemory(int sizeInBytes, byte clearValue = 0, int align = 16) - { - var ptr = AllocateMemory(sizeInBytes, align); - ClearMemory(ptr, clearValue, sizeInBytes); - return ptr; - } - - /// - /// Determines whether the specified memory pointer is aligned in memory. - /// - /// The memory pointer. - /// The align. - /// true if the specified memory pointer is aligned in memory; otherwise, false. - public static bool IsMemoryAligned(IntPtr memoryPtr, int align = 16) - { - return ((memoryPtr.ToInt64() & (align-1)) == 0); - } - - /// - /// Allocate an aligned memory buffer. - /// - /// A pointer to a buffer aligned. - /// - /// The buffer must have been allocated with . - /// - public unsafe static void FreeMemory(IntPtr alignedBuffer) - { - if (alignedBuffer == IntPtr.Zero) return; - Marshal.FreeHGlobal(((IntPtr*) alignedBuffer)[-1]); - } - - /// - /// Converts a pointer to a null-terminating string up to maxLength characters to a .Net string. - /// - /// The pointer to an ANSI null string. - /// Maximum length of the string. - /// The converted string. - public static string PtrToStringAnsi(IntPtr pointer, int maxLength) - { -#if W8CORE - return Marshal.PtrToStringAnsi(pointer, maxLength); -#else - unsafe - { - var pStr = (byte*)pointer; - for (int i = 0; i < maxLength; i++) - if (*pStr++ == 0 ) - return new string((sbyte*)pointer); - return new string((sbyte*)pointer, 0, maxLength); - } -#endif - } - - /// - /// Converts a pointer to a null-terminating string up to maxLength characters to a .Net string. - /// - /// The pointer to an Unicode null string. - /// Maximum length of the string. - /// The converted string. - public static string PtrToStringUni(IntPtr pointer, int maxLength) - { -#if W8CORE - return Marshal.PtrToStringUni(pointer, maxLength); -#else - unsafe - { - var pStr = (char*)pointer; - for (int i = 0; i < maxLength; i++) - if (*pStr++ == 0) - return new string((char*)pointer); - return new string((char*)pointer, 0, maxLength); - } -#endif - } - - /// - /// Copies the contents of a managed String into unmanaged memory, converting into ANSI format as it copies. - /// - /// A managed string to be copied. - /// The address, in unmanaged memory, to where s was copied, or IntPtr.Zero if s is null. - public static unsafe IntPtr StringToHGlobalAnsi(string s) - { -#if WP8 - if (s == null) - { - return IntPtr.Zero; - } - int cbNativeBuffer = (s.Length + 1) * 4; - var ptr2 = Marshal.AllocHGlobal(cbNativeBuffer); - if (ptr2 == IntPtr.Zero) - { - throw new OutOfMemoryException(); - } - fixed (char* chRef = s) - { - int count = ASCIIEncoding.ASCII.GetBytes(chRef, s.Length, (byte*) ptr2, cbNativeBuffer); - ((byte*) ptr2)[count] = 0; - } - - return ptr2; -#else - return Marshal.StringToHGlobalAnsi(s); -#endif - } - - /// - /// Copies the contents of a managed String into unmanaged memory. - /// - /// A managed string to be copied. - /// The address, in unmanaged memory, to where s was copied, or IntPtr.Zero if s is null. - public static unsafe IntPtr StringToHGlobalUni(string s) - { -#if WP8 - if (s == null) - { - return IntPtr.Zero; - } - int num = (s.Length + 1) * 2; - if (num < s.Length) - { - throw new ArgumentOutOfRangeException("s"); - } - IntPtr ptr2 = Marshal.AllocHGlobal(num); - if (ptr2 == IntPtr.Zero) - { - throw new OutOfMemoryException(); - } - CopyStringToUnmanaged(ptr2, s); - return ptr2; -#else - return Marshal.StringToHGlobalUni(s); -#endif - } - - /// - /// Copies the contents of a managed String into unmanaged memory using - /// - /// A managed string to be copied. - /// The address, in unmanaged memory, to where s was copied, or IntPtr.Zero if s is null. - public static unsafe IntPtr StringToCoTaskMemUni(string s) - { - if (s == null) - { - return IntPtr.Zero; - } - int num = (s.Length + 1) * 2; - if (num < s.Length) - { - throw new ArgumentOutOfRangeException("s"); - } - IntPtr ptr2 = Marshal.AllocCoTaskMem(num); - if (ptr2 == IntPtr.Zero) - { - throw new OutOfMemoryException(); - } - CopyStringToUnmanaged(ptr2, s); - return ptr2; - } - - private unsafe static void CopyStringToUnmanaged(IntPtr ptr, string str) - { - fixed (char* pStr = str) - { - CopyMemory(ptr, new IntPtr(pStr), (str.Length + 1 ) * 2); - } - } - - /// - /// Gets the IUnknown from object. Similar to but accept null object - /// by returning an IntPtr.Zero IUnknown pointer. - /// - /// The managed object. - /// An IUnknown pointer to a managed object. - public static IntPtr GetIUnknownForObject(object obj) - { - IntPtr objPtr = obj == null ? IntPtr.Zero : Marshal.GetIUnknownForObject(obj); - //if (obj is ComObject && ((ComObject)obj).NativePointer == IntPtr.Zero) - // (((ComObject)obj).NativePointer) = objPtr; - return objPtr; - } - - /// - /// Gets an object from an IUnknown pointer. Similar to but accept IntPtr.Zero - /// by returning a null object. - /// - /// an IUnknown pointer to a managed object. - /// The managed object. - public static object GetObjectForIUnknown(IntPtr iunknownPtr) - { - return iunknownPtr == IntPtr.Zero ? null : Marshal.GetObjectForIUnknown(iunknownPtr); - } - - /// - /// String helper join method to display an array of object as a single string. - /// - /// The separator. - /// The array. - /// A string with array elements separated by the separator. - public static string Join(string separator, T[] array) - { - var text = new StringBuilder(); - if (array != null) - { - for (int i = 0; i < array.Length; i++) - { - if (i > 0) text.Append(separator); - text.Append(array[i]); - } - } - return text.ToString(); - } - - /// - /// String helper join method to display an enumerable of object as a single string. - /// - /// The separator. - /// The enumerable. - /// A string with array elements separated by the separator. - public static string Join(string separator, IEnumerable elements) - { - var elementList = new List(); - foreach (var element in elements) - elementList.Add(element.ToString()); - - var text = new StringBuilder(); - for (int i = 0; i < elementList.Count; i++) - { - var element = elementList[i]; - if (i > 0) text.Append(separator); - text.Append(element); - } - return text.ToString(); - } - - /// - /// String helper join method to display an enumerable of object as a single string. - /// - /// The separator. - /// The enumerable. - /// A string with array elements separated by the separator. - public static string Join(string separator, IEnumerator elements) - { - var elementList = new List(); - while (elements.MoveNext()) - elementList.Add(elements.Current.ToString()); - - var text = new StringBuilder(); - for (int i = 0; i < elementList.Count; i++) - { - var element = elementList[i]; - if (i > 0) text.Append(separator); - text.Append(element); - } - return text.ToString(); - } - - /// - /// Converts a blob to a string. - /// - /// A blob. - /// A string extracted from a blob. - public static string BlobToString(Blob blob) - { - if (blob == null) return null; - string output; -#if W8CORE - output = Marshal.PtrToStringAnsi(blob.BufferPointer); -#else - unsafe - { - output = new string((sbyte*) blob.BufferPointer); - } -#endif - blob.Dispose(); - return output; - } - - /// - /// Equivalent to IntPtr.Add method from 3.5+ .NET Framework. - /// Adds an offset to the value of a pointer. - /// - /// A native pointer. - /// The offset to add (number of bytes). - /// A new pointer that reflects the addition of offset to pointer. - public unsafe static IntPtr IntPtrAdd(IntPtr ptr, int offset) - { - return new IntPtr(((byte*) ptr) + offset); - } - - /// - /// Read stream to a byte[] buffer. - /// - /// Input stream. - /// A byte[] buffer. - public static byte[] ReadStream(Stream stream) - { - int readLength = 0; - return ReadStream(stream, ref readLength); - } - - /// - /// Read stream to a byte[] buffer. - /// - /// Input stream. - /// Length to read. - /// A byte[] buffer. - public static byte[] ReadStream(Stream stream, ref int readLength) - { - Debug.Assert(stream != null); - Debug.Assert(stream.CanRead); - int num = readLength; - Debug.Assert(num <= (stream.Length - stream.Position)); - if (num == 0) - readLength = (int) (stream.Length - stream.Position); - num = readLength; - - Debug.Assert(num >= 0); - if (num == 0) - return new byte[0]; - - byte[] buffer = new byte[num]; - int bytesRead = 0; - if (num > 0) - { - do - { - bytesRead += stream.Read(buffer, bytesRead, readLength - bytesRead); - } while (bytesRead < readLength); - } - return buffer; - } - - /// - /// Compares two collection, element by elements. - /// - /// A "from" enumerator. - /// A "to" enumerator. - /// true if lists are identical, false otherwise. - public static bool Compare(IEnumerable left, IEnumerable right) - { - if (ReferenceEquals(left, right)) - return true; - if (ReferenceEquals(left, null) || ReferenceEquals(right, null)) - return false; - - return Compare(left.GetEnumerator(), right.GetEnumerator()); - } - - /// - /// Compares two collection, element by elements. - /// - /// A "from" enumerator. - /// A "to" enumerator. - /// true if lists are identical; otherwise, false. - public static bool Compare(IEnumerator leftIt, IEnumerator rightIt) - { - if (ReferenceEquals(leftIt, rightIt)) - return true; - if (ReferenceEquals(leftIt, null) || ReferenceEquals(rightIt, null)) - return false; - - bool hasLeftNext; - bool hasRightNext; - while (true) - { - hasLeftNext = leftIt.MoveNext(); - hasRightNext = rightIt.MoveNext(); - if (!hasLeftNext || !hasRightNext) - break; - - if (!Equals(leftIt.Current, rightIt.Current)) - return false; - } - - // If there is any left element - if (hasLeftNext != hasRightNext) - return false; - - return true; - } - - /// - /// Compares two collection, element by elements. - /// - /// The collection to compare from. - /// The collection to compare to. - /// true if lists are identical (but not necessarily of the same time); otherwise , false. - public static bool Compare(ICollection left, ICollection right) - { - if (ReferenceEquals(left, right)) - return true; - if (ReferenceEquals(left, null) || ReferenceEquals(right, null)) - return false; - - if (left.Count != right.Count) - return false; - - int count = 0; - var leftIt = left.GetEnumerator(); - var rightIt = right.GetEnumerator(); - while (leftIt.MoveNext() && rightIt.MoveNext()) - { - if (!Equals(leftIt.Current, rightIt.Current)) - return false; - count++; - } - - // Just double check to make sure that the iterator actually returns - // the exact number of elements - if (count != left.Count) - return false; - - return true; - } - - /// - /// Gets the custom attribute. - /// - /// Type of the custom attribute. - /// The member info. - /// if set to true [inherited]. - /// The custom attribute or null if not found. - public static T GetCustomAttribute(MemberInfo memberInfo, bool inherited = false) where T : Attribute - { -#if W8CORE - return memberInfo.GetCustomAttribute(inherited); -#else - var result = memberInfo.GetCustomAttributes(typeof(T), inherited); - if (result.Length == 0) - return default(T); - return (T)result[0]; -#endif - } - - /// - /// Gets the custom attributes. - /// - /// Type of the custom attribute. - /// The member info. - /// if set to true [inherited]. - /// The custom attribute or null if not found. - public static IEnumerable GetCustomAttributes(MemberInfo memberInfo, bool inherited = false) where T : Attribute - { -#if W8CORE - return memberInfo.GetCustomAttributes(inherited); -#else - var result = memberInfo.GetCustomAttributes(typeof(T), inherited); - if (result.Length == 0) - return new T[0]; - var typedResult = new T[result.Length]; - Array.Copy(result, typedResult, result.Length); - return typedResult; -#endif - } - - /// - /// Determines whether fromType can be assigned to toType. - /// - /// To type. - /// From type. - /// - /// true if [is assignable from] [the specified to type]; otherwise, false. - /// - public static bool IsAssignableFrom(Type toType, Type fromType) - { -#if W8CORE - return toType.GetTypeInfo().IsAssignableFrom(fromType.GetTypeInfo()); -#else - return toType.IsAssignableFrom(fromType); -#endif - } - - /// - /// Determines whether the specified type to test is an enum. - /// - /// The type to test. - /// - /// true if the specified type to test is an enum; otherwise, false. - /// - public static bool IsEnum(Type typeToTest) - { -#if W8CORE - return typeToTest.GetTypeInfo().IsEnum; -#else - return typeToTest.IsEnum; -#endif - } - - /// - /// Determines whether the specified type to test is a value type. - /// - /// The type to test. - /// - /// true if the specified type to test is a value type; otherwise, false. - /// - public static bool IsValueType(Type typeToTest) - { -#if W8CORE - return typeToTest.GetTypeInfo().IsValueType; -#else - return typeToTest.IsValueType; -#endif - } - - private static MethodInfo GetMethod(Type type, string name, Type[] typeArgs) { -#if W8CORE - - foreach( var method in type.GetTypeInfo().GetDeclaredMethods(name)) { - if ( method.GetParameters().Length == typeArgs.Length) { - var parameters = method.GetParameters(); - bool methodFound = true; - for (int i = 0; i < typeArgs.Length; i++) - { - if (parameters[i].ParameterType != typeArgs[i]) { - methodFound = false; - break; - } - } - if (methodFound) { - return method; - } - } - } - return null; -#else - return type.GetMethod(name, typeArgs); -#endif - } - - /// - /// Builds a fast property getter from a type and a property info. - /// - /// Type of the getter. - /// Type of the custom effect. - /// The property info to get the value from. - /// A compiled delegate. - public static GetValueFastDelegate BuildPropertyGetter(Type customEffectType, PropertyInfo propertyInfo) - { -#if W8CORE - - var valueParam = Expression.Parameter(typeof(T).MakeByRefType()); - var objectParam = Expression.Parameter(typeof(object)); - var castParam = Expression.Convert(objectParam, customEffectType); - var propertyAccessor = Expression.Property(castParam, propertyInfo); - - Expression convertExpression; - if (propertyInfo.PropertyType == typeof(bool)) - { - // Convert bool to int: effect.Property ? 1 : 0 - convertExpression = Expression.Condition(propertyAccessor, Expression.Constant(1), Expression.Constant(0)); - } - else - { - convertExpression = Expression.Convert(propertyAccessor, typeof(T)); - } - return Expression.Lambda>(Expression.Assign(valueParam, convertExpression), objectParam, valueParam).Compile(); -#else - var typeT = typeof(T); - var propertyType = propertyInfo.PropertyType; - var method = new DynamicMethod("GetValueDelegate", typeof(void), new[] { typeof(object), typeT.MakeByRefType() }); - - var ilGenerator = method.GetILGenerator(); - ilGenerator.Emit(OpCodes.Ldarg_1); - ilGenerator.Emit(OpCodes.Ldarg_0); - ilGenerator.Emit(OpCodes.Castclass, customEffectType); - ilGenerator.EmitCall(OpCodes.Callvirt, propertyInfo.GetGetMethod(), null); - - if (typeT == typeof(byte) || typeT == typeof(sbyte)) - { - ilGenerator.Emit(OpCodes.Stind_I1); - } - else if (typeT == typeof(short) || typeT == typeof(ushort)) - { - ilGenerator.Emit(OpCodes.Stind_I2); - } - else if (typeT == typeof(int) || typeT == typeof(uint)) - { - // If property type is bool, convert it to int first - if (propertyType == typeof(bool)) - { - ilGenerator.EmitCall(OpCodes.Call, GetMethod(typeof(Convert), "ToInt32", new[] { typeof(bool) }), null); - } - ilGenerator.Emit(OpCodes.Stind_I4); - } - else if (typeT == typeof(long) || typeT == typeof(ulong)) - { - ilGenerator.Emit(OpCodes.Stind_I8); - } - else if (typeT == typeof(float)) - { - ilGenerator.Emit(OpCodes.Stind_R4); - } - else if (typeT == typeof(double)) - { - ilGenerator.Emit(OpCodes.Stind_R8); - } - else - { - var castMethod = FindExplicitConverstion(propertyType, typeT); - if (castMethod != null) - { - ilGenerator.EmitCall(OpCodes.Call, castMethod, null); - } - ilGenerator.Emit(OpCodes.Stobj, typeof(T)); - } - ilGenerator.Emit(OpCodes.Ret); - return (GetValueFastDelegate)method.CreateDelegate(typeof(GetValueFastDelegate)); -#endif - } - - /// - /// Builds a fast property setter from a type and a property info. - /// - /// Type of the setter. - /// Type of the custom effect. - /// The property info to set the value to. - /// A compiled delegate. - public static SetValueFastDelegate BuildPropertySetter(Type customEffectType, PropertyInfo propertyInfo) - { -#if W8CORE - var valueParam = Expression.Parameter(typeof(T).MakeByRefType()); - var objectParam = Expression.Parameter(typeof(object)); - var castParam = Expression.Convert(objectParam, customEffectType); - var propertyAccessor = Expression.Property(castParam, propertyInfo); - - Expression convertExpression; - if (propertyInfo.PropertyType == typeof(bool)) - { - // Convert int to bool: value != 0 - convertExpression = Expression.NotEqual(valueParam, Expression.Constant(0)); - } - else - { - convertExpression = Expression.Convert(valueParam, propertyInfo.PropertyType); - } - return Expression.Lambda>(Expression.Assign(propertyAccessor, convertExpression), objectParam, valueParam).Compile(); -#else - - var typeT = typeof(T); - var propertyType = propertyInfo.PropertyType; - var method = new DynamicMethod("SetValueDelegate", typeof(void), new[] { typeof(object), typeT.MakeByRefType() }); - - //L_0000: nop - //L_0001: ldarg.0 - //L_0002: castclass TestEmitGetSet.MyCustomEffect - //L_0007: ldarg.1 - //L_0008: ldind.i4 - //L_0009: callvirt instance void TestEmitGetSet.MyCustomEffect::set_Toto(int32) - //L_000e: nop - //L_000f: ret - - var ilGenerator = method.GetILGenerator(); - ilGenerator.Emit(OpCodes.Ldarg_0); - ilGenerator.Emit(OpCodes.Castclass, customEffectType); - ilGenerator.Emit(OpCodes.Ldarg_1); - - if (typeT == typeof(byte) || typeT == typeof(sbyte)) - { - ilGenerator.Emit(OpCodes.Ldind_I1); - } - else if (typeT == typeof(short) || typeT == typeof(ushort)) - { - ilGenerator.Emit(OpCodes.Ldind_I2); - } - else if (typeT == typeof(int) || typeT == typeof(uint)) - { - ilGenerator.Emit(OpCodes.Ldind_I4); - // If property type is bool, convert it to int first - if (propertyType == typeof(bool)) - { - ilGenerator.EmitCall(OpCodes.Call, GetMethod(typeof(Convert),"ToBoolean", new[] { typeT }), null); - } - } - else if (typeT == typeof(long) || typeT == typeof(ulong)) - { - ilGenerator.Emit(OpCodes.Ldind_I8); - } - else if (typeT == typeof(float)) - { - ilGenerator.Emit(OpCodes.Ldind_R4); - } - else if (typeT == typeof(double)) - { - ilGenerator.Emit(OpCodes.Ldind_R8); - } - else - { - ilGenerator.Emit(OpCodes.Ldobj, typeof(T)); - - var castMethod = FindExplicitConverstion(typeT, propertyType); - if (castMethod != null) - { - ilGenerator.EmitCall(OpCodes.Call, castMethod, null); - } - } - - ilGenerator.EmitCall(OpCodes.Callvirt, propertyInfo.GetSetMethod(), null); - - ilGenerator.Emit(OpCodes.Ret); - return (SetValueFastDelegate)method.CreateDelegate(typeof(SetValueFastDelegate)); -#endif - } - - /// - /// Suspends the current thread of a . - /// - /// The duration to sleep in milliseconds. - public static void Sleep(TimeSpan sleepTimeInMillis) - { -#if WIN8METRO - Task.Delay(sleepTimeInMillis).Wait(); -#else - Thread.Sleep(sleepTimeInMillis); -#endif - } - - /// - /// Finds an explicit conversion between a source type and a target type. - /// - /// Type of the source. - /// Type of the target. - /// The method to perform the conversion. null if not found. - private static MethodInfo FindExplicitConverstion(Type sourceType, Type targetType) - { - // No need for cast for similar source and target type - if (sourceType == targetType) - return null; - - var methods = new List(); - - var tempType = sourceType; - while (tempType != null) - { -#if W8CORE - methods.AddRange(tempType.GetTypeInfo().DeclaredMethods); //target methods will be favored in the search - tempType = tempType.GetTypeInfo().BaseType; -#else - methods.AddRange(tempType.GetMethods(BindingFlags.Static | BindingFlags.Public)); //target methods will be favored in the search - tempType = tempType.BaseType; -#endif - } - - tempType = targetType; - while (tempType != null) - { -#if W8CORE - methods.AddRange(tempType.GetTypeInfo().DeclaredMethods); //target methods will be favored in the search - tempType = tempType.GetTypeInfo().BaseType; -#else - methods.AddRange(tempType.GetMethods(BindingFlags.Static | BindingFlags.Public)); //target methods will be favored in the search - tempType = tempType.BaseType; -#endif - } - - foreach (MethodInfo mi in methods) - { - if (mi.Name == "op_Explicit") //will return target and take one parameter - if (mi.ReturnType == targetType) - if (IsAssignableFrom(mi.GetParameters()[0].ParameterType, sourceType)) - return mi; - } - - return null; - } - - [Flags] - public enum CLSCTX : uint - { - ClsctxInprocServer = 0x1, - ClsctxInprocHandler = 0x2, - ClsctxLocalServer = 0x4, - ClsctxInprocServer16 = 0x8, - ClsctxRemoteServer = 0x10, - ClsctxInprocHandler16 = 0x20, - ClsctxReserved1 = 0x40, - ClsctxReserved2 = 0x80, - ClsctxReserved3 = 0x100, - ClsctxReserved4 = 0x200, - ClsctxNoCodeDownload = 0x400, - ClsctxReserved5 = 0x800, - ClsctxNoCustomMarshal = 0x1000, - ClsctxEnableCodeDownload = 0x2000, - ClsctxNoFailureLog = 0x4000, - ClsctxDisableAaa = 0x8000, - ClsctxEnableAaa = 0x10000, - ClsctxFromDefaultContext = 0x20000, - ClsctxInproc = ClsctxInprocServer | ClsctxInprocHandler, - ClsctxServer = ClsctxInprocServer | ClsctxLocalServer | ClsctxRemoteServer, - ClsctxAll = ClsctxServer | ClsctxInprocHandler - } - -#if W8CORE - [StructLayout(LayoutKind.Sequential)] - public struct MultiQueryInterface - { - public IntPtr InterfaceIID; - public IntPtr IUnknownPointer; - public Result ResultCode; - }; - - -#if WP8 - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate Result CoCreateInstanceFromAppDelegate([In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, - IntPtr pUnkOuter, - CLSCTX dwClsContext, - IntPtr reserved, - int countMultiQuery, - ref MultiQueryInterface query); - - private static CoCreateInstanceFromAppDelegate CoCreateInstanceFromApp; - - internal unsafe static void CreateComInstance(Guid clsid, CLSCTX clsctx, Guid riid, ComObject comObject) - { - if (CoCreateInstanceFromApp == null) - { - CoCreateInstanceFromApp = - (CoCreateInstanceFromAppDelegate) - Marshal.GetDelegateForFunctionPointer(new IntPtr(SharpDX.WP8.Interop.CoCreateInstanceFromApp()), - typeof (CoCreateInstanceFromAppDelegate)); - } - - MultiQueryInterface localQuery = new MultiQueryInterface() - { - InterfaceIID = new IntPtr(&riid), - IUnknownPointer = IntPtr.Zero, - ResultCode = 0, - }; - - var result = CoCreateInstanceFromApp(clsid, IntPtr.Zero, clsctx, IntPtr.Zero, 1, ref localQuery); - result.CheckError(); - localQuery.ResultCode.CheckError(); - comObject.NativePointer = localQuery.IUnknownPointer; - } -#else - #if W8CORE - [DllImport("api-ms-win-core-com-l1-1-0.dll", ExactSpelling = true, EntryPoint = "CoCreateInstanceFromApp", PreserveSig = true)] - private static extern Result CoCreateInstanceFromApp([In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, - IntPtr pUnkOuter, - CLSCTX dwClsContext, - IntPtr reserved, - int countMultiQuery, - ref MultiQueryInterface query); - #else - [DllImport("ole32.dll", ExactSpelling = true, EntryPoint = "CoCreateInstanceFromApp", PreserveSig = true)] - private static extern Result CoCreateInstanceFromApp([In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, - IntPtr pUnkOuter, - CLSCTX dwClsContext, - IntPtr reserved, - int countMultiQuery, - ref MultiQueryInterface query); - #endif - - internal unsafe static void CreateComInstance(Guid clsid, CLSCTX clsctx, Guid riid, ComObject comObject) - { - MultiQueryInterface localQuery = new MultiQueryInterface() - { - InterfaceIID = new IntPtr(&riid), - IUnknownPointer = IntPtr.Zero, - ResultCode = 0, - }; - - var result = CoCreateInstanceFromApp(clsid, IntPtr.Zero, clsctx, IntPtr.Zero, 1, ref localQuery); - result.CheckError(); - localQuery.ResultCode.CheckError(); - comObject.NativePointer = localQuery.IUnknownPointer; - } -#endif - - - -#else - [DllImport("ole32.dll", ExactSpelling = true, EntryPoint = "CoCreateInstance", PreserveSig = true)] - private static extern Result CoCreateInstance([In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, IntPtr pUnkOuter, CLSCTX dwClsContext, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr comObject); - - internal static void CreateComInstance(Guid clsid, CLSCTX clsctx, Guid riid, ComObject comObject) - { - IntPtr pointer; - var result = CoCreateInstance(clsid, IntPtr.Zero, clsctx, riid, out pointer); - result.CheckError(); - comObject.NativePointer = pointer; - } -#endif - - /// Determines the concurrency model used for incoming calls to objects created by this thread. This concurrency model can be either apartment-threaded or multi-threaded. - public enum CoInit - { - /// - /// Initializes the thread for apartment-threaded object concurrency. - /// - MultiThreaded = 0x0, - - /// - /// Initializes the thread for multi-threaded object concurrency. - /// - ApartmentThreaded = 0x2, - - /// - /// Disables DDE for OLE1 support. - /// - DisableOle1Dde = 0x4, - - /// - /// Trade memory for speed. - /// - SpeedOverMemory = 0x8 - } - -#if WP8 - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - internal delegate bool CloseHandleDelegate(IntPtr handle); - private static CloseHandleDelegate closeHandle; - internal static CloseHandleDelegate CloseHandle - { - get { return closeHandle ?? (closeHandle = (CloseHandleDelegate)Marshal.GetDelegateForFunctionPointer(new IntPtr(SharpDX.WP8.Interop.CloseHandle()), typeof(CloseHandleDelegate))); } - } -#else -#if W8CORE - [DllImport("api-ms-win-core-handle-l1-1-0.dll", EntryPoint = "CloseHandle", SetLastError = true)] - internal static extern bool CloseHandle(IntPtr handle); -#else - [DllImport("kernel32.dll", EntryPoint = "CloseHandle", SetLastError = true)] - internal static extern bool CloseHandle(IntPtr handle); -#endif -#endif - - /// - /// Loads a native library. - /// - /// Name of the DLL. - /// If DLL was not found. - /// Handle to the module. - public static IntPtr LoadLibrary(string dllName) - { - IntPtr result = LoadLibrary_(dllName); - if (result == IntPtr.Zero) - throw new DllNotFoundException(String.Format("Unable to find [{0}] in the PATH", dllName)); - return result; - } - -#if WP8 - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate IntPtr LoadLibraryDelegate([MarshalAs(UnmanagedType.LPWStr)] string lpFileName, int reserved = 0); - private static LoadLibraryDelegate loadLibrary_; - private static LoadLibraryDelegate LoadLibrary_ - { - get { return loadLibrary_ ?? (loadLibrary_ = (LoadLibraryDelegate)Marshal.GetDelegateForFunctionPointer(new IntPtr(SharpDX.WP8.Interop.LoadPackagedLibrary()), typeof(LoadLibraryDelegate))); } - } -#elif WIN8METRO && !WP81 - [DllImport("kernel32", EntryPoint = "LoadPackagedLibrary", SetLastError = true)] - static extern IntPtr LoadLibrary_(string lpFileName, int reserved = 0); -#elif WP81 - [DllImport("PhoneAppModelHost", EntryPoint = "LoadPackagedLibrary", SetLastError = true)] - static extern IntPtr LoadLibrary_(string lpFileName, int reserved = 0); -#else - [DllImport("kernel32", EntryPoint = "LoadLibrary", SetLastError = true, CharSet = CharSet.Unicode)] - static extern IntPtr LoadLibrary_(string lpFileName); -#endif - - /// - /// Gets the proc address of a DLL. - /// - /// The handle. - /// The DLL function to import. - /// If the function was not found. - /// Pointer to address of the exported function or variable. - public static IntPtr GetProcAddress(IntPtr handle, string dllFunctionToImport) - { - IntPtr result = GetProcAddress_(handle, dllFunctionToImport); - if (result == IntPtr.Zero) - throw new SharpDXException(dllFunctionToImport); - return result; - } - -#if WP8 - // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683212%28v=vs.85%29.aspx - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate IntPtr GetProcAddressDelegate(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procName); - private static GetProcAddressDelegate getProcAddress_; - private static GetProcAddressDelegate GetProcAddress_ - { - get { return getProcAddress_ ?? (getProcAddress_ = (GetProcAddressDelegate)Marshal.GetDelegateForFunctionPointer(new IntPtr(SharpDX.WP8.Interop.GetProcAddress()), typeof(GetProcAddressDelegate))); } - } -#else -#if W8CORE - [DllImport("api-ms-win-core-libraryloader-l1-1-1.dll", EntryPoint = "GetProcAddress", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] - static extern IntPtr GetProcAddress_(IntPtr hModule, string procName); -#else - // http://www.pinvoke.net/default.aspx/kernel32.getprocaddress - // http://stackoverflow.com/questions/3754264/c-sharp-getprocaddress-returns-zero - [DllImport("kernel32", EntryPoint = "GetProcAddress", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] - static extern IntPtr GetProcAddress_(IntPtr hModule, string procName); -#endif - -#endif - - /// - /// Compute a FNV1-modified Hash from Fowler/Noll/Vo Hash improved version. - /// - /// Data to compute the hash from. - /// A hash value. - public static int ComputeHashFNVModified(byte[] data) - { - const uint p = 16777619; - uint hash = 2166136261; - foreach (byte b in data) - hash = (hash ^ b) * p; - hash += hash << 13; - hash ^= hash >> 7; - hash += hash << 3; - hash ^= hash >> 17; - hash += hash << 5; - return unchecked((int)hash); - } - - /// - /// Safely dispose a reference if not null, and set it to null after dispose. - /// - /// The type of COM interface to dispose. - /// Object to dispose. - /// - /// The reference will be set to null after dispose. - /// - public static void Dispose(ref T comObject) where T : class, IDisposable - { - if (comObject != null) - { - comObject.Dispose(); - comObject = null; - } - } - - /// - /// Transforms an to an array of T. - /// - /// Type of the element - /// The enumerable source. - /// an array of T - public static T[] ToArray(IEnumerable source) - { - return new Buffer(source).ToArray(); - } - - /// - /// Test if there is an element in this enumeration. - /// - /// Type of the element - /// The enumerable source. - /// true if there is an element in this enumeration, false otherwise - public static bool Any(IEnumerable source) - { - return source.GetEnumerator().MoveNext(); - } - - /// - /// Select elements from an enumeration. - /// - /// The type of the T source. - /// The type of the T result. - /// The source. - /// The selector. - /// A enumeration of selected values - public static IEnumerable SelectMany(IEnumerable source, Func> selector) - { - foreach (TSource sourceItem in source) - { - foreach (TResult result in selector(sourceItem)) - yield return result; - } - } - - /// - /// Selects distinct elements from an enumeration. - /// - /// The type of the T source. - /// The source. - /// The comparer. - /// A enumeration of selected values - public static IEnumerable Distinct(IEnumerable source, IEqualityComparer comparer = null) - { - if (comparer == null) - comparer = EqualityComparer.Default; - - // using Dictionary is not really efficient but easy to implement - var values = new Dictionary(comparer); - foreach (TSource sourceItem in source) - { - if (!values.ContainsKey(sourceItem)) - { - values.Add(sourceItem, null); - yield return sourceItem; - } - } - } - - internal struct Buffer - { - internal TElement[] items; - internal int count; - - internal Buffer(IEnumerable source) - { - var array = (TElement[])null; - int length = 0; - var collection = source as ICollection; - if (collection != null) - { - length = collection.Count; - if (length > 0) - { - array = new TElement[length]; - collection.CopyTo(array, 0); - } - } - else - { - foreach (TElement element in source) - { - if (array == null) - array = new TElement[4]; - else if (array.Length == length) - { - var elementArray = new TElement[checked(length * 2)]; - Array.Copy(array, 0, elementArray, 0, length); - array = elementArray; - } - array[length] = element; - ++length; - } - } - items = array; - count = length; - } - - internal TElement[] ToArray() - { - if (count == 0) - return new TElement[0]; - if (items.Length == count) - return items; - var elementArray = new TElement[count]; - Array.Copy(items, 0, elementArray, 0, count); - return elementArray; - } - } - - /// - /// Determines whether the type inherits from the specified type (used to determine a type without using an explicit type instance). - /// - /// The type. - /// Name of the parent type to find in inheritance hierarchy of type. - /// true if the type inherits from the specified type; otherwise, false. - public static bool IsTypeInheritFrom(Type type, string parentType) - { - while (type != null) - { - if (type.FullName == parentType) - { - return true; - } -#if W8CORE - type = type.GetTypeInfo().BaseType; -#else - type = type.BaseType; -#endif - } - - return false; - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Reflection.Emit; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; +using System.Threading; + +using SharpDX.Direct3D; +using System.Reflection; +#if W8CORE +using System.Threading.Tasks; +using System.Linq; +using System.Linq.Expressions; +using SharpDX.Text; + +#endif + +namespace SharpDX +{ + +#if !NET35Plus + /// + /// Encapsulates a method that has no parameters and returns a value of the type specified by the TResult parameter. + /// + /// The type of the return value of the method that this delegate encapsulates. This type parameter is covariant. That is, you can use either the type you specified or any type that is more derived. + /// The return value of the method that this delegate encapsulates. + public delegate TResult Func(); + public delegate TResult Func(T1 paramT1); + public delegate TResult Func(T1 paramT1, T2 paramT2); + + public delegate void Action(); + public delegate void Action(T1 paramT1, T2 paramT2); +#endif + + /// + /// A Delegate to get a property value from an object. + /// + /// Type of the getter. + /// The obj to get the property from. + /// The value to get. + public delegate void GetValueFastDelegate(object obj, out T value); + + /// + /// A Delegate to set a property value to an object. + /// + /// Type of the setter. + /// The obj to set the property from. + /// The value to set. + public delegate void SetValueFastDelegate(object obj, ref T value); + + /// + /// Utility class. + /// + public static class Utilities + { + ///// + ///// Native memcpy. + ///// + ///// The destination memory location. + ///// The source memory location. + ///// The count. + ///// + //[DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, + // SetLastError = false), SuppressUnmanagedCodeSecurity] + //public static extern IntPtr CopyMemory(IntPtr dest, IntPtr src, ulong sizeInBytesToCopy); + + /// + /// Native memcpy. + /// + /// The destination memory location. + /// The source memory location. + /// The byte count. + public static void CopyMemory(IntPtr dest, IntPtr src, int sizeInBytesToCopy) + { + unsafe + { + // TODO plug in Interop a pluggable CopyMemory using cpblk or memcpy based on architecture + Interop.memcpy((void*)dest, (void*)src, sizeInBytesToCopy); + } + } + + /// + /// Compares two block of memory. + /// + /// The pointer to compare from. + /// The pointer to compare against. + /// The size in bytes to compare. + /// true if the buffers are equivalent; otherwise, false. + public unsafe static bool CompareMemory(IntPtr from, IntPtr against, int sizeToCompare) + { + var pSrc = (byte*)@from; + var pDst = (byte*)against; + + // Compare 8 bytes. + int numberOf = sizeToCompare >> 3; + while (numberOf > 0) + { + if (*(long*)pSrc != *(long*)pDst) + return false; + pSrc += 8; + pDst += 8; + numberOf--; + } + + // Compare remaining bytes. + numberOf = sizeToCompare & 7; + while (numberOf > 0) + { + if (*pSrc != *pDst) + return false; + pSrc++; + pDst++; + numberOf--; + } + + return true; + } + + /// + /// Clears the memory. + /// + /// The dest. + /// The value. + /// The size in bytes to clear. + public static void ClearMemory(IntPtr dest, byte value, int sizeInBytesToClear) + { + unsafe + { + Interop.memset((void*)dest, value, sizeInBytesToClear); + } + } + + /// + /// Return the sizeof a struct from a CLR. Equivalent to sizeof operator but works on generics too. + /// + /// A struct to evaluate. + /// Size of this struct. + public static int SizeOf() where T : struct + { + return Interop.SizeOf(); + } + + /// + /// Return the sizeof an array of struct. Equivalent to sizeof operator but works on generics too. + /// + /// A struct. + /// The array of struct to evaluate. + /// Size in bytes of this array of struct. + public static int SizeOf(T[] array) where T : struct + { + return array == null ? 0 : array.Length * Interop.SizeOf(); + } + + /// + /// Pins the specified source and call an action with the pinned pointer. + /// + /// The type of the structure to pin. + /// The source. + /// The pin action to perform on the pinned pointer. + public static void Pin(ref T source, Action pinAction) where T : struct + { + unsafe + { + pinAction((IntPtr)Interop.Fixed(ref source)); + } + } + + /// + /// Pins the specified source and call an action with the pinned pointer. + /// + /// The type of the structure to pin. + /// The source array. + /// The pin action to perform on the pinned pointer. + public static void Pin(T[] source, Action pinAction) where T : struct + { + unsafe + { + pinAction(source == null ? IntPtr.Zero : (IntPtr)Interop.Fixed(source)); + } + } + + /// + /// Converts a structured array to an equivalent byte array. + /// + /// The type of source array. + /// The source array. + /// Converted byte array. + public static byte[] ToByteArray(T[] source) where T : struct + { + if (source == null) return null; + + var buffer = new byte[SizeOf() * source.Length]; + + if (source.Length == 0) + return buffer; + + unsafe + { + fixed (void* pBuffer = buffer) + Interop.Write(pBuffer, source, 0, source.Length); + } + return buffer; + } + + /// + /// Swaps the value between two references. + /// + /// Type of a data to swap. + /// The left value. + /// The right value. + public static void Swap(ref T left, ref T right) + { + var temp = left; + left = right; + right = temp; + } + + /// + /// Reads the specified T data from a memory location. + /// + /// Type of a data to read. + /// Memory location to read from. + /// The data read from the memory location. + public static T Read(IntPtr source) where T : struct + { + unsafe + { + return Interop.ReadInline((void*)source); + } + } + + /// + /// Reads the specified T data from a memory location. + /// + /// Type of a data to read. + /// Memory location to read from. + /// The data write to. + /// source pointer + sizeof(T). + public static void Read(IntPtr source, ref T data) where T : struct + { + unsafe + { + Interop.CopyInline(ref data, (void*)source); + } + } + + /// + /// Reads the specified T data from a memory location. + /// + /// Type of a data to read. + /// Memory location to read from. + /// The data write to. + /// source pointer + sizeof(T). + public static void ReadOut(IntPtr source, out T data) where T : struct + { + unsafe + { + Interop.CopyInlineOut(out data, (void*)source); + } + } + + /// + /// Reads the specified T data from a memory location. + /// + /// Type of a data to read. + /// Memory location to read from. + /// The data write to. + /// source pointer + sizeof(T). + public static IntPtr ReadAndPosition(IntPtr source, ref T data) where T : struct + { + unsafe + { + return (IntPtr)Interop.Read((void*)source, ref data); + } + } + + /// + /// Reads the specified array T[] data from a memory location. + /// + /// Type of a data to read. + /// Memory location to read from. + /// The data write to. + /// The offset in the array to write to. + /// The number of T element to read from the memory location. + /// source pointer + sizeof(T) * count. + public static IntPtr Read(IntPtr source, T[] data, int offset, int count) where T : struct + { + unsafe + { + return (IntPtr)Interop.Read((void*)source, data, offset, count); + } + } + + /// + /// Writes the specified T data to a memory location. + /// + /// Type of a data to write. + /// Memory location to write to. + /// The data to write. + /// destination pointer + sizeof(T). + public static void Write(IntPtr destination, ref T data) where T : struct + { + unsafe + { + Interop.CopyInline((void*)destination, ref data); + } + } + + /// + /// Writes the specified T data to a memory location. + /// + /// Type of a data to write. + /// Memory location to write to. + /// The data to write. + /// destination pointer + sizeof(T). + public static IntPtr WriteAndPosition(IntPtr destination, ref T data) where T : struct + { + unsafe + { + return (IntPtr)Interop.Write((void*)destination, ref data); + } + } + + /// + /// Writes the specified array T[] data to a memory location. + /// + /// Type of a data to write. + /// Memory location to write to. + /// The array of T data to write. + /// The offset in the array to read from. + /// The number of T element to write to the memory location. + /// destination pointer + sizeof(T) * count. + public static IntPtr Write(IntPtr destination, T[] data, int offset, int count) where T : struct + { + unsafe + { + return (IntPtr)Interop.Write((void*)destination, data, offset, count); + } + } + + /// + /// Converts bool array to integer pointers array. + /// + /// The bool array. + /// The destination array of int pointers. + public unsafe static void ConvertToIntArray(bool[] array, int* dest) + { + for (int i = 0; i < array.Length; i++) + dest[i] = array[i] ? 1 : 0; + } + + /// + /// Converts bool array to array. + /// + /// The bool array. + /// Converted array of . + public static Bool[] ConvertToIntArray(bool[] array) + { + var temp = new Bool[array.Length]; + for (int i = 0; i < temp.Length; i++) + temp[i] = array[i]; + return temp; + } + + /// + /// Converts integer pointer array to bool array. + /// + /// The array of integer pointers. + /// Array size. + /// Converted array of bool. + public unsafe static bool[] ConvertToBoolArray(int* array, int length) + { + var temp = new bool[length]; + for (int i = 0; i < temp.Length; i++) + temp[i] = array[i] != 0; + return temp; + } + + /// + /// Converts array to bool array. + /// + /// The array. + /// Converted array of bool. + public static bool[] ConvertToBoolArray(Bool[] array) + { + var temp = new bool[array.Length]; + for (int i = 0; i < temp.Length; i++) + temp[i] = array[i]; + return temp; + } + + /// + /// Gets the from a type. + /// + /// The type. + /// The guid associated with this type. + public static Guid GetGuidFromType(Type type) + { +#if W8CORE + return type.GetTypeInfo().GUID; +#else + return type.GUID; +#endif + } + + /// + /// Determines whether a given type inherits from a generic type. + /// + /// Type of the class to check if it inherits from generic type. + /// Type of the generic. + /// true if [is assignable to generic type] [the specified given type]; otherwise, false. + public static bool IsAssignableToGenericType(Type givenType, Type genericType) + { +#if W8CORE + throw new NotImplementedException(); +#else + // from http://stackoverflow.com/a/1075059/1356325 + var interfaceTypes = givenType.GetInterfaces(); + + foreach (var it in interfaceTypes) + { + if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType) + return true; + } + + if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType) + return true; + + Type baseType = givenType.BaseType; + if (baseType == null) return false; + + return IsAssignableToGenericType(baseType, genericType); +#endif + } + + /// + /// Allocate an aligned memory buffer. + /// + /// Size of the buffer to allocate. + /// Alignment, 16 bytes by default. + /// A pointer to a buffer aligned. + /// + /// To free this buffer, call . + /// + public unsafe static IntPtr AllocateMemory(int sizeInBytes, int align = 16) + { + int mask = align - 1; + var memPtr = Marshal.AllocHGlobal(sizeInBytes + mask + IntPtr.Size); + var ptr = (long)((byte*)memPtr + sizeof(void*) + mask) & ~mask; + ((IntPtr*)ptr)[-1] = memPtr; + return new IntPtr(ptr); + } + + /// + /// Allocate an aligned memory buffer and clear it with a specified value (0 by default). + /// + /// Size of the buffer to allocate. + /// Default value used to clear the buffer. + /// Alignment, 16 bytes by default. + /// A pointer to a buffer aligned. + /// + /// To free this buffer, call . + /// + public static IntPtr AllocateClearedMemory(int sizeInBytes, byte clearValue = 0, int align = 16) + { + var ptr = AllocateMemory(sizeInBytes, align); + ClearMemory(ptr, clearValue, sizeInBytes); + return ptr; + } + + /// + /// Determines whether the specified memory pointer is aligned in memory. + /// + /// The memory pointer. + /// The align. + /// true if the specified memory pointer is aligned in memory; otherwise, false. + public static bool IsMemoryAligned(IntPtr memoryPtr, int align = 16) + { + return ((memoryPtr.ToInt64() & (align-1)) == 0); + } + + /// + /// Allocate an aligned memory buffer. + /// + /// A pointer to a buffer aligned. + /// + /// The buffer must have been allocated with . + /// + public unsafe static void FreeMemory(IntPtr alignedBuffer) + { + if (alignedBuffer == IntPtr.Zero) return; + Marshal.FreeHGlobal(((IntPtr*) alignedBuffer)[-1]); + } + + /// + /// Converts a pointer to a null-terminating string up to maxLength characters to a .Net string. + /// + /// The pointer to an ANSI null string. + /// Maximum length of the string. + /// The converted string. + public static string PtrToStringAnsi(IntPtr pointer, int maxLength) + { +#if W8CORE + return Marshal.PtrToStringAnsi(pointer, maxLength); +#else + unsafe + { + var pStr = (byte*)pointer; + for (int i = 0; i < maxLength; i++) + if (*pStr++ == 0 ) + return new string((sbyte*)pointer); + return new string((sbyte*)pointer, 0, maxLength); + } +#endif + } + + /// + /// Converts a pointer to a null-terminating string up to maxLength characters to a .Net string. + /// + /// The pointer to an Unicode null string. + /// Maximum length of the string. + /// The converted string. + public static string PtrToStringUni(IntPtr pointer, int maxLength) + { +#if W8CORE + return Marshal.PtrToStringUni(pointer, maxLength); +#else + unsafe + { + var pStr = (char*)pointer; + for (int i = 0; i < maxLength; i++) + if (*pStr++ == 0) + return new string((char*)pointer); + return new string((char*)pointer, 0, maxLength); + } +#endif + } + + /// + /// Copies the contents of a managed String into unmanaged memory, converting into ANSI format as it copies. + /// + /// A managed string to be copied. + /// The address, in unmanaged memory, to where s was copied, or IntPtr.Zero if s is null. + public static unsafe IntPtr StringToHGlobalAnsi(string s) + { +#if WP8 + if (s == null) + { + return IntPtr.Zero; + } + int cbNativeBuffer = (s.Length + 1) * 4; + var ptr2 = Marshal.AllocHGlobal(cbNativeBuffer); + if (ptr2 == IntPtr.Zero) + { + throw new OutOfMemoryException(); + } + fixed (char* chRef = s) + { + int count = ASCIIEncoding.ASCII.GetBytes(chRef, s.Length, (byte*) ptr2, cbNativeBuffer); + ((byte*) ptr2)[count] = 0; + } + + return ptr2; +#else + return Marshal.StringToHGlobalAnsi(s); +#endif + } + + /// + /// Copies the contents of a managed String into unmanaged memory. + /// + /// A managed string to be copied. + /// The address, in unmanaged memory, to where s was copied, or IntPtr.Zero if s is null. + public static unsafe IntPtr StringToHGlobalUni(string s) + { +#if WP8 + if (s == null) + { + return IntPtr.Zero; + } + int num = (s.Length + 1) * 2; + if (num < s.Length) + { + throw new ArgumentOutOfRangeException("s"); + } + IntPtr ptr2 = Marshal.AllocHGlobal(num); + if (ptr2 == IntPtr.Zero) + { + throw new OutOfMemoryException(); + } + CopyStringToUnmanaged(ptr2, s); + return ptr2; +#else + return Marshal.StringToHGlobalUni(s); +#endif + } + + /// + /// Copies the contents of a managed String into unmanaged memory using + /// + /// A managed string to be copied. + /// The address, in unmanaged memory, to where s was copied, or IntPtr.Zero if s is null. + public static unsafe IntPtr StringToCoTaskMemUni(string s) + { + if (s == null) + { + return IntPtr.Zero; + } + int num = (s.Length + 1) * 2; + if (num < s.Length) + { + throw new ArgumentOutOfRangeException("s"); + } + IntPtr ptr2 = Marshal.AllocCoTaskMem(num); + if (ptr2 == IntPtr.Zero) + { + throw new OutOfMemoryException(); + } + CopyStringToUnmanaged(ptr2, s); + return ptr2; + } + + private unsafe static void CopyStringToUnmanaged(IntPtr ptr, string str) + { + fixed (char* pStr = str) + { + CopyMemory(ptr, new IntPtr(pStr), (str.Length + 1 ) * 2); + } + } + + /// + /// Gets the IUnknown from object. Similar to but accept null object + /// by returning an IntPtr.Zero IUnknown pointer. + /// + /// The managed object. + /// An IUnknown pointer to a managed object. + public static IntPtr GetIUnknownForObject(object obj) + { + IntPtr objPtr = obj == null ? IntPtr.Zero : Marshal.GetIUnknownForObject(obj); + //if (obj is ComObject && ((ComObject)obj).NativePointer == IntPtr.Zero) + // (((ComObject)obj).NativePointer) = objPtr; + return objPtr; + } + + /// + /// Gets an object from an IUnknown pointer. Similar to but accept IntPtr.Zero + /// by returning a null object. + /// + /// an IUnknown pointer to a managed object. + /// The managed object. + public static object GetObjectForIUnknown(IntPtr iunknownPtr) + { + return iunknownPtr == IntPtr.Zero ? null : Marshal.GetObjectForIUnknown(iunknownPtr); + } + + /// + /// String helper join method to display an array of object as a single string. + /// + /// The separator. + /// The array. + /// A string with array elements separated by the separator. + public static string Join(string separator, T[] array) + { + var text = new StringBuilder(); + if (array != null) + { + for (int i = 0; i < array.Length; i++) + { + if (i > 0) text.Append(separator); + text.Append(array[i]); + } + } + return text.ToString(); + } + + /// + /// String helper join method to display an enumerable of object as a single string. + /// + /// The separator. + /// The enumerable. + /// A string with array elements separated by the separator. + public static string Join(string separator, IEnumerable elements) + { + var elementList = new List(); + foreach (var element in elements) + elementList.Add(element.ToString()); + + var text = new StringBuilder(); + for (int i = 0; i < elementList.Count; i++) + { + var element = elementList[i]; + if (i > 0) text.Append(separator); + text.Append(element); + } + return text.ToString(); + } + + /// + /// String helper join method to display an enumerable of object as a single string. + /// + /// The separator. + /// The enumerable. + /// A string with array elements separated by the separator. + public static string Join(string separator, IEnumerator elements) + { + var elementList = new List(); + while (elements.MoveNext()) + elementList.Add(elements.Current.ToString()); + + var text = new StringBuilder(); + for (int i = 0; i < elementList.Count; i++) + { + var element = elementList[i]; + if (i > 0) text.Append(separator); + text.Append(element); + } + return text.ToString(); + } + + /// + /// Converts a blob to a string. + /// + /// A blob. + /// A string extracted from a blob. + public static string BlobToString(Blob blob) + { + if (blob == null) return null; + string output; +#if W8CORE + output = Marshal.PtrToStringAnsi(blob.BufferPointer); +#else + unsafe + { + output = new string((sbyte*) blob.BufferPointer); + } +#endif + blob.Dispose(); + return output; + } + + /// + /// Equivalent to IntPtr.Add method from 3.5+ .NET Framework. + /// Adds an offset to the value of a pointer. + /// + /// A native pointer. + /// The offset to add (number of bytes). + /// A new pointer that reflects the addition of offset to pointer. + public unsafe static IntPtr IntPtrAdd(IntPtr ptr, int offset) + { + return new IntPtr(((byte*) ptr) + offset); + } + + /// + /// Read stream to a byte[] buffer. + /// + /// Input stream. + /// A byte[] buffer. + public static byte[] ReadStream(Stream stream) + { + int readLength = 0; + return ReadStream(stream, ref readLength); + } + + /// + /// Read stream to a byte[] buffer. + /// + /// Input stream. + /// Length to read. + /// A byte[] buffer. + public static byte[] ReadStream(Stream stream, ref int readLength) + { + Debug.Assert(stream != null); + Debug.Assert(stream.CanRead); + int num = readLength; + Debug.Assert(num <= (stream.Length - stream.Position)); + if (num == 0) + readLength = (int) (stream.Length - stream.Position); + num = readLength; + + Debug.Assert(num >= 0); + if (num == 0) + return new byte[0]; + + byte[] buffer = new byte[num]; + int bytesRead = 0; + if (num > 0) + { + do + { + bytesRead += stream.Read(buffer, bytesRead, readLength - bytesRead); + } while (bytesRead < readLength); + } + return buffer; + } + + /// + /// Compares two collection, element by elements. + /// + /// A "from" enumerator. + /// A "to" enumerator. + /// true if lists are identical, false otherwise. + public static bool Compare(IEnumerable left, IEnumerable right) + { + if (ReferenceEquals(left, right)) + return true; + if (ReferenceEquals(left, null) || ReferenceEquals(right, null)) + return false; + + return Compare(left.GetEnumerator(), right.GetEnumerator()); + } + + /// + /// Compares two collection, element by elements. + /// + /// A "from" enumerator. + /// A "to" enumerator. + /// true if lists are identical; otherwise, false. + public static bool Compare(IEnumerator leftIt, IEnumerator rightIt) + { + if (ReferenceEquals(leftIt, rightIt)) + return true; + if (ReferenceEquals(leftIt, null) || ReferenceEquals(rightIt, null)) + return false; + + bool hasLeftNext; + bool hasRightNext; + while (true) + { + hasLeftNext = leftIt.MoveNext(); + hasRightNext = rightIt.MoveNext(); + if (!hasLeftNext || !hasRightNext) + break; + + if (!Equals(leftIt.Current, rightIt.Current)) + return false; + } + + // If there is any left element + if (hasLeftNext != hasRightNext) + return false; + + return true; + } + + /// + /// Compares two collection, element by elements. + /// + /// The collection to compare from. + /// The collection to compare to. + /// true if lists are identical (but not necessarily of the same time); otherwise , false. + public static bool Compare(ICollection left, ICollection right) + { + if (ReferenceEquals(left, right)) + return true; + if (ReferenceEquals(left, null) || ReferenceEquals(right, null)) + return false; + + if (left.Count != right.Count) + return false; + + int count = 0; + var leftIt = left.GetEnumerator(); + var rightIt = right.GetEnumerator(); + while (leftIt.MoveNext() && rightIt.MoveNext()) + { + if (!Equals(leftIt.Current, rightIt.Current)) + return false; + count++; + } + + // Just double check to make sure that the iterator actually returns + // the exact number of elements + if (count != left.Count) + return false; + + return true; + } + + /// + /// Gets the custom attribute. + /// + /// Type of the custom attribute. + /// The member info. + /// if set to true [inherited]. + /// The custom attribute or null if not found. + public static T GetCustomAttribute(MemberInfo memberInfo, bool inherited = false) where T : Attribute + { +#if W8CORE + return memberInfo.GetCustomAttribute(inherited); +#else + var result = memberInfo.GetCustomAttributes(typeof(T), inherited); + if (result.Length == 0) + return default(T); + return (T)result[0]; +#endif + } + + /// + /// Gets the custom attributes. + /// + /// Type of the custom attribute. + /// The member info. + /// if set to true [inherited]. + /// The custom attribute or null if not found. + public static IEnumerable GetCustomAttributes(MemberInfo memberInfo, bool inherited = false) where T : Attribute + { +#if W8CORE + return memberInfo.GetCustomAttributes(inherited); +#else + var result = memberInfo.GetCustomAttributes(typeof(T), inherited); + if (result.Length == 0) + return new T[0]; + var typedResult = new T[result.Length]; + Array.Copy(result, typedResult, result.Length); + return typedResult; +#endif + } + + /// + /// Determines whether fromType can be assigned to toType. + /// + /// To type. + /// From type. + /// + /// true if [is assignable from] [the specified to type]; otherwise, false. + /// + public static bool IsAssignableFrom(Type toType, Type fromType) + { +#if W8CORE + return toType.GetTypeInfo().IsAssignableFrom(fromType.GetTypeInfo()); +#else + return toType.IsAssignableFrom(fromType); +#endif + } + + /// + /// Determines whether the specified type to test is an enum. + /// + /// The type to test. + /// + /// true if the specified type to test is an enum; otherwise, false. + /// + public static bool IsEnum(Type typeToTest) + { +#if W8CORE + return typeToTest.GetTypeInfo().IsEnum; +#else + return typeToTest.IsEnum; +#endif + } + + /// + /// Determines whether the specified type to test is a value type. + /// + /// The type to test. + /// + /// true if the specified type to test is a value type; otherwise, false. + /// + public static bool IsValueType(Type typeToTest) + { +#if W8CORE + return typeToTest.GetTypeInfo().IsValueType; +#else + return typeToTest.IsValueType; +#endif + } + + private static MethodInfo GetMethod(Type type, string name, Type[] typeArgs) { +#if W8CORE + + foreach( var method in type.GetTypeInfo().GetDeclaredMethods(name)) { + if ( method.GetParameters().Length == typeArgs.Length) { + var parameters = method.GetParameters(); + bool methodFound = true; + for (int i = 0; i < typeArgs.Length; i++) + { + if (parameters[i].ParameterType != typeArgs[i]) { + methodFound = false; + break; + } + } + if (methodFound) { + return method; + } + } + } + return null; +#else + return type.GetMethod(name, typeArgs); +#endif + } + + /// + /// Builds a fast property getter from a type and a property info. + /// + /// Type of the getter. + /// Type of the custom effect. + /// The property info to get the value from. + /// A compiled delegate. + public static GetValueFastDelegate BuildPropertyGetter(Type customEffectType, PropertyInfo propertyInfo) + { +#if W8CORE + + var valueParam = Expression.Parameter(typeof(T).MakeByRefType()); + var objectParam = Expression.Parameter(typeof(object)); + var castParam = Expression.Convert(objectParam, customEffectType); + var propertyAccessor = Expression.Property(castParam, propertyInfo); + + Expression convertExpression; + if (propertyInfo.PropertyType == typeof(bool)) + { + // Convert bool to int: effect.Property ? 1 : 0 + convertExpression = Expression.Condition(propertyAccessor, Expression.Constant(1), Expression.Constant(0)); + } + else + { + convertExpression = Expression.Convert(propertyAccessor, typeof(T)); + } + return Expression.Lambda>(Expression.Assign(valueParam, convertExpression), objectParam, valueParam).Compile(); +#else + var typeT = typeof(T); + var propertyType = propertyInfo.PropertyType; + var method = new DynamicMethod("GetValueDelegate", typeof(void), new[] { typeof(object), typeT.MakeByRefType() }); + + var ilGenerator = method.GetILGenerator(); + ilGenerator.Emit(OpCodes.Ldarg_1); + ilGenerator.Emit(OpCodes.Ldarg_0); + ilGenerator.Emit(OpCodes.Castclass, customEffectType); + ilGenerator.EmitCall(OpCodes.Callvirt, propertyInfo.GetGetMethod(), null); + + if (typeT == typeof(byte) || typeT == typeof(sbyte)) + { + ilGenerator.Emit(OpCodes.Stind_I1); + } + else if (typeT == typeof(short) || typeT == typeof(ushort)) + { + ilGenerator.Emit(OpCodes.Stind_I2); + } + else if (typeT == typeof(int) || typeT == typeof(uint)) + { + // If property type is bool, convert it to int first + if (propertyType == typeof(bool)) + { + ilGenerator.EmitCall(OpCodes.Call, GetMethod(typeof(Convert), "ToInt32", new[] { typeof(bool) }), null); + } + ilGenerator.Emit(OpCodes.Stind_I4); + } + else if (typeT == typeof(long) || typeT == typeof(ulong)) + { + ilGenerator.Emit(OpCodes.Stind_I8); + } + else if (typeT == typeof(float)) + { + ilGenerator.Emit(OpCodes.Stind_R4); + } + else if (typeT == typeof(double)) + { + ilGenerator.Emit(OpCodes.Stind_R8); + } + else + { + var castMethod = FindExplicitConverstion(propertyType, typeT); + if (castMethod != null) + { + ilGenerator.EmitCall(OpCodes.Call, castMethod, null); + } + ilGenerator.Emit(OpCodes.Stobj, typeof(T)); + } + ilGenerator.Emit(OpCodes.Ret); + return (GetValueFastDelegate)method.CreateDelegate(typeof(GetValueFastDelegate)); +#endif + } + + /// + /// Builds a fast property setter from a type and a property info. + /// + /// Type of the setter. + /// Type of the custom effect. + /// The property info to set the value to. + /// A compiled delegate. + public static SetValueFastDelegate BuildPropertySetter(Type customEffectType, PropertyInfo propertyInfo) + { +#if W8CORE + var valueParam = Expression.Parameter(typeof(T).MakeByRefType()); + var objectParam = Expression.Parameter(typeof(object)); + var castParam = Expression.Convert(objectParam, customEffectType); + var propertyAccessor = Expression.Property(castParam, propertyInfo); + + Expression convertExpression; + if (propertyInfo.PropertyType == typeof(bool)) + { + // Convert int to bool: value != 0 + convertExpression = Expression.NotEqual(valueParam, Expression.Constant(0)); + } + else + { + convertExpression = Expression.Convert(valueParam, propertyInfo.PropertyType); + } + return Expression.Lambda>(Expression.Assign(propertyAccessor, convertExpression), objectParam, valueParam).Compile(); +#else + + var typeT = typeof(T); + var propertyType = propertyInfo.PropertyType; + var method = new DynamicMethod("SetValueDelegate", typeof(void), new[] { typeof(object), typeT.MakeByRefType() }); + + //L_0000: nop + //L_0001: ldarg.0 + //L_0002: castclass TestEmitGetSet.MyCustomEffect + //L_0007: ldarg.1 + //L_0008: ldind.i4 + //L_0009: callvirt instance void TestEmitGetSet.MyCustomEffect::set_Toto(int32) + //L_000e: nop + //L_000f: ret + + var ilGenerator = method.GetILGenerator(); + ilGenerator.Emit(OpCodes.Ldarg_0); + ilGenerator.Emit(OpCodes.Castclass, customEffectType); + ilGenerator.Emit(OpCodes.Ldarg_1); + + if (typeT == typeof(byte) || typeT == typeof(sbyte)) + { + ilGenerator.Emit(OpCodes.Ldind_I1); + } + else if (typeT == typeof(short) || typeT == typeof(ushort)) + { + ilGenerator.Emit(OpCodes.Ldind_I2); + } + else if (typeT == typeof(int) || typeT == typeof(uint)) + { + ilGenerator.Emit(OpCodes.Ldind_I4); + // If property type is bool, convert it to int first + if (propertyType == typeof(bool)) + { + ilGenerator.EmitCall(OpCodes.Call, GetMethod(typeof(Convert),"ToBoolean", new[] { typeT }), null); + } + } + else if (typeT == typeof(long) || typeT == typeof(ulong)) + { + ilGenerator.Emit(OpCodes.Ldind_I8); + } + else if (typeT == typeof(float)) + { + ilGenerator.Emit(OpCodes.Ldind_R4); + } + else if (typeT == typeof(double)) + { + ilGenerator.Emit(OpCodes.Ldind_R8); + } + else + { + ilGenerator.Emit(OpCodes.Ldobj, typeof(T)); + + var castMethod = FindExplicitConverstion(typeT, propertyType); + if (castMethod != null) + { + ilGenerator.EmitCall(OpCodes.Call, castMethod, null); + } + } + + ilGenerator.EmitCall(OpCodes.Callvirt, propertyInfo.GetSetMethod(), null); + + ilGenerator.Emit(OpCodes.Ret); + return (SetValueFastDelegate)method.CreateDelegate(typeof(SetValueFastDelegate)); +#endif + } + + /// + /// Suspends the current thread of a . + /// + /// The duration to sleep in milliseconds. + public static void Sleep(TimeSpan sleepTimeInMillis) + { +#if WIN8METRO + Task.Delay(sleepTimeInMillis).Wait(); +#else + Thread.Sleep(sleepTimeInMillis); +#endif + } + + /// + /// Finds an explicit conversion between a source type and a target type. + /// + /// Type of the source. + /// Type of the target. + /// The method to perform the conversion. null if not found. + private static MethodInfo FindExplicitConverstion(Type sourceType, Type targetType) + { + // No need for cast for similar source and target type + if (sourceType == targetType) + return null; + + var methods = new List(); + + var tempType = sourceType; + while (tempType != null) + { +#if W8CORE + methods.AddRange(tempType.GetTypeInfo().DeclaredMethods); //target methods will be favored in the search + tempType = tempType.GetTypeInfo().BaseType; +#else + methods.AddRange(tempType.GetMethods(BindingFlags.Static | BindingFlags.Public)); //target methods will be favored in the search + tempType = tempType.BaseType; +#endif + } + + tempType = targetType; + while (tempType != null) + { +#if W8CORE + methods.AddRange(tempType.GetTypeInfo().DeclaredMethods); //target methods will be favored in the search + tempType = tempType.GetTypeInfo().BaseType; +#else + methods.AddRange(tempType.GetMethods(BindingFlags.Static | BindingFlags.Public)); //target methods will be favored in the search + tempType = tempType.BaseType; +#endif + } + + foreach (MethodInfo mi in methods) + { + if (mi.Name == "op_Explicit") //will return target and take one parameter + if (mi.ReturnType == targetType) + if (IsAssignableFrom(mi.GetParameters()[0].ParameterType, sourceType)) + return mi; + } + + return null; + } + + [Flags] + public enum CLSCTX : uint + { + ClsctxInprocServer = 0x1, + ClsctxInprocHandler = 0x2, + ClsctxLocalServer = 0x4, + ClsctxInprocServer16 = 0x8, + ClsctxRemoteServer = 0x10, + ClsctxInprocHandler16 = 0x20, + ClsctxReserved1 = 0x40, + ClsctxReserved2 = 0x80, + ClsctxReserved3 = 0x100, + ClsctxReserved4 = 0x200, + ClsctxNoCodeDownload = 0x400, + ClsctxReserved5 = 0x800, + ClsctxNoCustomMarshal = 0x1000, + ClsctxEnableCodeDownload = 0x2000, + ClsctxNoFailureLog = 0x4000, + ClsctxDisableAaa = 0x8000, + ClsctxEnableAaa = 0x10000, + ClsctxFromDefaultContext = 0x20000, + ClsctxInproc = ClsctxInprocServer | ClsctxInprocHandler, + ClsctxServer = ClsctxInprocServer | ClsctxLocalServer | ClsctxRemoteServer, + ClsctxAll = ClsctxServer | ClsctxInprocHandler + } + +#if W8CORE + [StructLayout(LayoutKind.Sequential)] + public struct MultiQueryInterface + { + public IntPtr InterfaceIID; + public IntPtr IUnknownPointer; + public Result ResultCode; + }; + + +#if WP8 + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate Result CoCreateInstanceFromAppDelegate([In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, + IntPtr pUnkOuter, + CLSCTX dwClsContext, + IntPtr reserved, + int countMultiQuery, + ref MultiQueryInterface query); + + private static CoCreateInstanceFromAppDelegate CoCreateInstanceFromApp; + + internal unsafe static void CreateComInstance(Guid clsid, CLSCTX clsctx, Guid riid, ComObject comObject) + { + if (CoCreateInstanceFromApp == null) + { + CoCreateInstanceFromApp = + (CoCreateInstanceFromAppDelegate) + Marshal.GetDelegateForFunctionPointer(new IntPtr(SharpDX.WP8.Interop.CoCreateInstanceFromApp()), + typeof (CoCreateInstanceFromAppDelegate)); + } + + MultiQueryInterface localQuery = new MultiQueryInterface() + { + InterfaceIID = new IntPtr(&riid), + IUnknownPointer = IntPtr.Zero, + ResultCode = 0, + }; + + var result = CoCreateInstanceFromApp(clsid, IntPtr.Zero, clsctx, IntPtr.Zero, 1, ref localQuery); + result.CheckError(); + localQuery.ResultCode.CheckError(); + comObject.NativePointer = localQuery.IUnknownPointer; + } +#else + #if W8CORE + [DllImport("api-ms-win-core-com-l1-1-0.dll", ExactSpelling = true, EntryPoint = "CoCreateInstanceFromApp", PreserveSig = true)] + private static extern Result CoCreateInstanceFromApp([In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, + IntPtr pUnkOuter, + CLSCTX dwClsContext, + IntPtr reserved, + int countMultiQuery, + ref MultiQueryInterface query); + #else + [DllImport("ole32.dll", ExactSpelling = true, EntryPoint = "CoCreateInstanceFromApp", PreserveSig = true)] + private static extern Result CoCreateInstanceFromApp([In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, + IntPtr pUnkOuter, + CLSCTX dwClsContext, + IntPtr reserved, + int countMultiQuery, + ref MultiQueryInterface query); + #endif + + internal unsafe static void CreateComInstance(Guid clsid, CLSCTX clsctx, Guid riid, ComObject comObject) + { + MultiQueryInterface localQuery = new MultiQueryInterface() + { + InterfaceIID = new IntPtr(&riid), + IUnknownPointer = IntPtr.Zero, + ResultCode = 0, + }; + + var result = CoCreateInstanceFromApp(clsid, IntPtr.Zero, clsctx, IntPtr.Zero, 1, ref localQuery); + result.CheckError(); + localQuery.ResultCode.CheckError(); + comObject.NativePointer = localQuery.IUnknownPointer; + } +#endif + + + +#else + [DllImport("ole32.dll", ExactSpelling = true, EntryPoint = "CoCreateInstance", PreserveSig = true)] + private static extern Result CoCreateInstance([In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, IntPtr pUnkOuter, CLSCTX dwClsContext, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr comObject); + + internal static void CreateComInstance(Guid clsid, CLSCTX clsctx, Guid riid, ComObject comObject) + { + IntPtr pointer; + var result = CoCreateInstance(clsid, IntPtr.Zero, clsctx, riid, out pointer); + result.CheckError(); + comObject.NativePointer = pointer; + } +#endif + + /// Determines the concurrency model used for incoming calls to objects created by this thread. This concurrency model can be either apartment-threaded or multi-threaded. + public enum CoInit + { + /// + /// Initializes the thread for apartment-threaded object concurrency. + /// + MultiThreaded = 0x0, + + /// + /// Initializes the thread for multi-threaded object concurrency. + /// + ApartmentThreaded = 0x2, + + /// + /// Disables DDE for OLE1 support. + /// + DisableOle1Dde = 0x4, + + /// + /// Trade memory for speed. + /// + SpeedOverMemory = 0x8 + } + +#if WP8 + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate bool CloseHandleDelegate(IntPtr handle); + private static CloseHandleDelegate closeHandle; + internal static CloseHandleDelegate CloseHandle + { + get { return closeHandle ?? (closeHandle = (CloseHandleDelegate)Marshal.GetDelegateForFunctionPointer(new IntPtr(SharpDX.WP8.Interop.CloseHandle()), typeof(CloseHandleDelegate))); } + } +#else +#if W8CORE + [DllImport("api-ms-win-core-handle-l1-1-0.dll", EntryPoint = "CloseHandle", SetLastError = true)] + internal static extern bool CloseHandle(IntPtr handle); +#else + [DllImport("kernel32.dll", EntryPoint = "CloseHandle", SetLastError = true)] + internal static extern bool CloseHandle(IntPtr handle); +#endif +#endif + + /// + /// Loads a native library. + /// + /// Name of the DLL. + /// If DLL was not found. + /// Handle to the module. + public static IntPtr LoadLibrary(string dllName) + { + IntPtr result = LoadLibrary_(dllName); + if (result == IntPtr.Zero) + throw new DllNotFoundException(String.Format("Unable to find [{0}] in the PATH", dllName)); + return result; + } + +#if WP8 + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate IntPtr LoadLibraryDelegate([MarshalAs(UnmanagedType.LPWStr)] string lpFileName, int reserved = 0); + private static LoadLibraryDelegate loadLibrary_; + private static LoadLibraryDelegate LoadLibrary_ + { + get { return loadLibrary_ ?? (loadLibrary_ = (LoadLibraryDelegate)Marshal.GetDelegateForFunctionPointer(new IntPtr(SharpDX.WP8.Interop.LoadPackagedLibrary()), typeof(LoadLibraryDelegate))); } + } +#elif WIN8METRO && !WP81 + [DllImport("kernel32", EntryPoint = "LoadPackagedLibrary", SetLastError = true)] + static extern IntPtr LoadLibrary_(string lpFileName, int reserved = 0); +#elif WP81 + [DllImport("PhoneAppModelHost", EntryPoint = "LoadPackagedLibrary", SetLastError = true)] + static extern IntPtr LoadLibrary_(string lpFileName, int reserved = 0); +#else + [DllImport("kernel32", EntryPoint = "LoadLibrary", SetLastError = true, CharSet = CharSet.Unicode)] + static extern IntPtr LoadLibrary_(string lpFileName); +#endif + + /// + /// Gets the proc address of a DLL. + /// + /// The handle. + /// The DLL function to import. + /// If the function was not found. + /// Pointer to address of the exported function or variable. + public static IntPtr GetProcAddress(IntPtr handle, string dllFunctionToImport) + { + IntPtr result = GetProcAddress_(handle, dllFunctionToImport); + if (result == IntPtr.Zero) + throw new SharpDXException(dllFunctionToImport); + return result; + } + +#if WP8 + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683212%28v=vs.85%29.aspx + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate IntPtr GetProcAddressDelegate(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procName); + private static GetProcAddressDelegate getProcAddress_; + private static GetProcAddressDelegate GetProcAddress_ + { + get { return getProcAddress_ ?? (getProcAddress_ = (GetProcAddressDelegate)Marshal.GetDelegateForFunctionPointer(new IntPtr(SharpDX.WP8.Interop.GetProcAddress()), typeof(GetProcAddressDelegate))); } + } +#else +#if W8CORE + [DllImport("api-ms-win-core-libraryloader-l1-1-1.dll", EntryPoint = "GetProcAddress", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + static extern IntPtr GetProcAddress_(IntPtr hModule, string procName); +#else + // http://www.pinvoke.net/default.aspx/kernel32.getprocaddress + // http://stackoverflow.com/questions/3754264/c-sharp-getprocaddress-returns-zero + [DllImport("kernel32", EntryPoint = "GetProcAddress", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + static extern IntPtr GetProcAddress_(IntPtr hModule, string procName); +#endif + +#endif + + /// + /// Compute a FNV1-modified Hash from Fowler/Noll/Vo Hash improved version. + /// + /// Data to compute the hash from. + /// A hash value. + public static int ComputeHashFNVModified(byte[] data) + { + const uint p = 16777619; + uint hash = 2166136261; + foreach (byte b in data) + hash = (hash ^ b) * p; + hash += hash << 13; + hash ^= hash >> 7; + hash += hash << 3; + hash ^= hash >> 17; + hash += hash << 5; + return unchecked((int)hash); + } + + /// + /// Safely dispose a reference if not null, and set it to null after dispose. + /// + /// The type of COM interface to dispose. + /// Object to dispose. + /// + /// The reference will be set to null after dispose. + /// + public static void Dispose(ref T comObject) where T : class, IDisposable + { + if (comObject != null) + { + comObject.Dispose(); + comObject = null; + } + } + + /// + /// Transforms an to an array of T. + /// + /// Type of the element + /// The enumerable source. + /// an array of T + public static T[] ToArray(IEnumerable source) + { + return new Buffer(source).ToArray(); + } + + /// + /// Test if there is an element in this enumeration. + /// + /// Type of the element + /// The enumerable source. + /// true if there is an element in this enumeration, false otherwise + public static bool Any(IEnumerable source) + { + return source.GetEnumerator().MoveNext(); + } + + /// + /// Select elements from an enumeration. + /// + /// The type of the T source. + /// The type of the T result. + /// The source. + /// The selector. + /// A enumeration of selected values + public static IEnumerable SelectMany(IEnumerable source, Func> selector) + { + foreach (TSource sourceItem in source) + { + foreach (TResult result in selector(sourceItem)) + yield return result; + } + } + + /// + /// Selects distinct elements from an enumeration. + /// + /// The type of the T source. + /// The source. + /// The comparer. + /// A enumeration of selected values + public static IEnumerable Distinct(IEnumerable source, IEqualityComparer comparer = null) + { + if (comparer == null) + comparer = EqualityComparer.Default; + + // using Dictionary is not really efficient but easy to implement + var values = new Dictionary(comparer); + foreach (TSource sourceItem in source) + { + if (!values.ContainsKey(sourceItem)) + { + values.Add(sourceItem, null); + yield return sourceItem; + } + } + } + + internal struct Buffer + { + internal TElement[] items; + internal int count; + + internal Buffer(IEnumerable source) + { + var array = (TElement[])null; + int length = 0; + var collection = source as ICollection; + if (collection != null) + { + length = collection.Count; + if (length > 0) + { + array = new TElement[length]; + collection.CopyTo(array, 0); + } + } + else + { + foreach (TElement element in source) + { + if (array == null) + array = new TElement[4]; + else if (array.Length == length) + { + var elementArray = new TElement[checked(length * 2)]; + Array.Copy(array, 0, elementArray, 0, length); + array = elementArray; + } + array[length] = element; + ++length; + } + } + items = array; + count = length; + } + + internal TElement[] ToArray() + { + if (count == 0) + return new TElement[0]; + if (items.Length == count) + return items; + var elementArray = new TElement[count]; + Array.Copy(items, 0, elementArray, 0, count); + return elementArray; + } + } + + /// + /// Determines whether the type inherits from the specified type (used to determine a type without using an explicit type instance). + /// + /// The type. + /// Name of the parent type to find in inheritance hierarchy of type. + /// true if the type inherits from the specified type; otherwise, false. + public static bool IsTypeInheritFrom(Type type, string parentType) + { + while (type != null) + { + if (type.FullName == parentType) + { + return true; + } +#if W8CORE + type = type.GetTypeInfo().BaseType; +#else + type = type.BaseType; +#endif + } + + return false; + } + } +} diff --git a/Source/SharpDX/Win32/NativeMessage.cs b/Source/SharpDX/Win32/NativeMessage.cs index 57dda8428..7229b1a2a 100644 --- a/Source/SharpDX/Win32/NativeMessage.cs +++ b/Source/SharpDX/Win32/NativeMessage.cs @@ -31,7 +31,8 @@ public struct NativeMessage public IntPtr wParam; public IntPtr lParam; public uint time; - public Point p; + public int px; + public int py; } } #endif \ No newline at end of file diff --git a/Source/SharpDX/Win32Native.cs b/Source/SharpDX/Win32Native.cs index 083694aee..cc5966308 100644 --- a/Source/SharpDX/Win32Native.cs +++ b/Source/SharpDX/Win32Native.cs @@ -1,161 +1,158 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Runtime.InteropServices; -using System.Security; -using SharpDX.Win32; - -namespace SharpDX -{ - /// - /// Internal class to interact with Native Message - /// - internal partial class Win32Native - { - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - public class LogFont - { - public int lfHeight; - public int lfWidth; - public int lfEscapement; - public int lfOrientation; - public int lfWeight; - public byte lfItalic; - public byte lfUnderline; - public byte lfStrikeOut; - public byte lfCharSet; - public byte lfOutPrecision; - public byte lfClipPrecision; - public byte lfQuality; - public byte lfPitchAndFamily; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)] - public string lfFaceName; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - public struct TextMetric - { - public int tmHeight; - public int tmAscent; - public int tmDescent; - public int tmInternalLeading; - public int tmExternalLeading; - public int tmAveCharWidth; - public int tmMaxCharWidth; - public int tmWeight; - public int tmOverhang; - public int tmDigitizedAspectX; - public int tmDigitizedAspectY; - public char tmFirstChar; - public char tmLastChar; - public char tmDefaultChar; - public char tmBreakChar; - public byte tmItalic; - public byte tmUnderlined; - public byte tmStruckOut; - public byte tmPitchAndFamily; - public byte tmCharSet; - } - -#if !W8CORE - - [DllImport("user32.dll", EntryPoint = "PeekMessage"), SuppressUnmanagedCodeSecurity] - public static extern int PeekMessage(out NativeMessage lpMsg, IntPtr hWnd, int wMsgFilterMin, - int wMsgFilterMax, int wRemoveMsg); - - [DllImport("user32.dll", EntryPoint = "GetMessage"), SuppressUnmanagedCodeSecurity] - public static extern int GetMessage(out NativeMessage lpMsg, IntPtr hWnd, int wMsgFilterMin, - int wMsgFilterMax); - - [DllImport("user32.dll", EntryPoint = "TranslateMessage"), SuppressUnmanagedCodeSecurity] - public static extern int TranslateMessage(ref NativeMessage lpMsg); - - [DllImport("user32.dll", EntryPoint = "DispatchMessage"), SuppressUnmanagedCodeSecurity] - public static extern int DispatchMessage(ref NativeMessage lpMsg); - - public enum WindowLongType : int - { - WndProc = (-4), - HInstance = (-6), - HwndParent = (-8), - Style = (-16), - ExtendedStyle = (-20), - UserData = (-21), - Id = (-12) - } - - public delegate IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); - - public static IntPtr GetWindowLong(HandleRef hWnd, WindowLongType index) - { - if (IntPtr.Size == 4) - { - return GetWindowLong32(hWnd, index); - } - return GetWindowLong64(hWnd, index); - } - - [DllImport("user32.dll", EntryPoint = "GetFocus", CharSet = CharSet.Unicode)] - public static extern IntPtr GetFocus(); - - [DllImport("user32.dll", EntryPoint = "GetWindowLong", CharSet = CharSet.Unicode)] - private static extern IntPtr GetWindowLong32(HandleRef hwnd, WindowLongType index); - - [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr", CharSet = CharSet.Unicode)] - private static extern IntPtr GetWindowLong64(HandleRef hwnd, WindowLongType index); - - public static IntPtr SetWindowLong(HandleRef hwnd, WindowLongType index, IntPtr wndProcPtr) - { - if (IntPtr.Size == 4) - { - return SetWindowLong32(hwnd, index, wndProcPtr); - } - return SetWindowLongPtr64(hwnd, index, wndProcPtr); - } - - [DllImport("user32.dll", EntryPoint = "SetParent", CharSet = CharSet.Unicode)] - public static extern IntPtr SetParent(HandleRef hWnd, IntPtr hWndParent); - - [DllImport("user32.dll", EntryPoint = "SetWindowLong", CharSet = CharSet.Unicode)] - private static extern IntPtr SetWindowLong32(HandleRef hwnd, WindowLongType index, IntPtr wndProc); - - - public static bool ShowWindow(HandleRef hWnd, bool windowVisible) - { - return ShowWindow(hWnd, windowVisible ? 1 : 0); - } - - [DllImport("user32.dll", EntryPoint = "ShowWindow", CharSet = CharSet.Unicode)] - private static extern bool ShowWindow(HandleRef hWnd, int mCmdShow); - - [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", CharSet = CharSet.Unicode)] - private static extern IntPtr SetWindowLongPtr64(HandleRef hwnd, WindowLongType index, IntPtr wndProc); - - [DllImport("user32.dll", EntryPoint = "CallWindowProc", CharSet = CharSet.Unicode)] - public static extern IntPtr CallWindowProc(IntPtr wndProc, IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam); - - [DllImport("user32.dll", EntryPoint = "GetClientRect")] - public static extern bool GetClientRect(IntPtr hWnd, out Rectangle lpRect); - - [DllImport("kernel32.dll", EntryPoint = "GetModuleHandle", CharSet = CharSet.Unicode)] - public static extern IntPtr GetModuleHandle(string lpModuleName); -#endif - } +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Runtime.InteropServices; +using System.Security; +using SharpDX.Win32; + +namespace SharpDX +{ + /// + /// Internal class to interact with Native Message + /// + internal partial class Win32Native + { + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public class LogFont + { + public int lfHeight; + public int lfWidth; + public int lfEscapement; + public int lfOrientation; + public int lfWeight; + public byte lfItalic; + public byte lfUnderline; + public byte lfStrikeOut; + public byte lfCharSet; + public byte lfOutPrecision; + public byte lfClipPrecision; + public byte lfQuality; + public byte lfPitchAndFamily; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)] + public string lfFaceName; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct TextMetric + { + public int tmHeight; + public int tmAscent; + public int tmDescent; + public int tmInternalLeading; + public int tmExternalLeading; + public int tmAveCharWidth; + public int tmMaxCharWidth; + public int tmWeight; + public int tmOverhang; + public int tmDigitizedAspectX; + public int tmDigitizedAspectY; + public char tmFirstChar; + public char tmLastChar; + public char tmDefaultChar; + public char tmBreakChar; + public byte tmItalic; + public byte tmUnderlined; + public byte tmStruckOut; + public byte tmPitchAndFamily; + public byte tmCharSet; + } + +#if !W8CORE + + [DllImport("user32.dll", EntryPoint = "PeekMessage"), SuppressUnmanagedCodeSecurity] + public static extern int PeekMessage(out NativeMessage lpMsg, IntPtr hWnd, int wMsgFilterMin, + int wMsgFilterMax, int wRemoveMsg); + + [DllImport("user32.dll", EntryPoint = "GetMessage"), SuppressUnmanagedCodeSecurity] + public static extern int GetMessage(out NativeMessage lpMsg, IntPtr hWnd, int wMsgFilterMin, + int wMsgFilterMax); + + [DllImport("user32.dll", EntryPoint = "TranslateMessage"), SuppressUnmanagedCodeSecurity] + public static extern int TranslateMessage(ref NativeMessage lpMsg); + + [DllImport("user32.dll", EntryPoint = "DispatchMessage"), SuppressUnmanagedCodeSecurity] + public static extern int DispatchMessage(ref NativeMessage lpMsg); + + public enum WindowLongType : int + { + WndProc = (-4), + HInstance = (-6), + HwndParent = (-8), + Style = (-16), + ExtendedStyle = (-20), + UserData = (-21), + Id = (-12) + } + + public delegate IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); + + public static IntPtr GetWindowLong(HandleRef hWnd, WindowLongType index) + { + if (IntPtr.Size == 4) + { + return GetWindowLong32(hWnd, index); + } + return GetWindowLong64(hWnd, index); + } + + [DllImport("user32.dll", EntryPoint = "GetFocus", CharSet = CharSet.Unicode)] + public static extern IntPtr GetFocus(); + + [DllImport("user32.dll", EntryPoint = "GetWindowLong", CharSet = CharSet.Unicode)] + private static extern IntPtr GetWindowLong32(HandleRef hwnd, WindowLongType index); + + [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr", CharSet = CharSet.Unicode)] + private static extern IntPtr GetWindowLong64(HandleRef hwnd, WindowLongType index); + + public static IntPtr SetWindowLong(HandleRef hwnd, WindowLongType index, IntPtr wndProcPtr) + { + if (IntPtr.Size == 4) + { + return SetWindowLong32(hwnd, index, wndProcPtr); + } + return SetWindowLongPtr64(hwnd, index, wndProcPtr); + } + + [DllImport("user32.dll", EntryPoint = "SetParent", CharSet = CharSet.Unicode)] + public static extern IntPtr SetParent(HandleRef hWnd, IntPtr hWndParent); + + [DllImport("user32.dll", EntryPoint = "SetWindowLong", CharSet = CharSet.Unicode)] + private static extern IntPtr SetWindowLong32(HandleRef hwnd, WindowLongType index, IntPtr wndProc); + + + public static bool ShowWindow(HandleRef hWnd, bool windowVisible) + { + return ShowWindow(hWnd, windowVisible ? 1 : 0); + } + + [DllImport("user32.dll", EntryPoint = "ShowWindow", CharSet = CharSet.Unicode)] + private static extern bool ShowWindow(HandleRef hWnd, int mCmdShow); + + [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", CharSet = CharSet.Unicode)] + private static extern IntPtr SetWindowLongPtr64(HandleRef hwnd, WindowLongType index, IntPtr wndProc); + + [DllImport("user32.dll", EntryPoint = "CallWindowProc", CharSet = CharSet.Unicode)] + public static extern IntPtr CallWindowProc(IntPtr wndProc, IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam); + + [DllImport("kernel32.dll", EntryPoint = "GetModuleHandle", CharSet = CharSet.Unicode)] + public static extern IntPtr GetModuleHandle(string lpModuleName); +#endif + } } \ No newline at end of file diff --git a/Source/Toolkit/SharpDX.Toolkit.Game/Game.cs b/Source/Toolkit/SharpDX.Toolkit.Game/Game.cs index addf903e4..8e7dc622c 100644 --- a/Source/Toolkit/SharpDX.Toolkit.Game/Game.cs +++ b/Source/Toolkit/SharpDX.Toolkit.Game/Game.cs @@ -22,6 +22,7 @@ using System.Collections.Generic; using SharpDX.Collections; +using SharpDX.Toolkit.Collections; using SharpDX.Toolkit.Content; using SharpDX.Toolkit.Graphics; diff --git a/Source/Toolkit/SharpDX.Toolkit.Game/GameSystemCollection.cs b/Source/Toolkit/SharpDX.Toolkit.Game/GameSystemCollection.cs index 29a39e400..c12809e91 100644 --- a/Source/Toolkit/SharpDX.Toolkit.Game/GameSystemCollection.cs +++ b/Source/Toolkit/SharpDX.Toolkit.Game/GameSystemCollection.cs @@ -19,6 +19,7 @@ // THE SOFTWARE. using SharpDX.Collections; +using SharpDX.Toolkit.Collections; namespace SharpDX.Toolkit { diff --git a/Source/Toolkit/SharpDX.Toolkit.Graphics/EffectPool.cs b/Source/Toolkit/SharpDX.Toolkit.Graphics/EffectPool.cs index d505b6496..c30e7ae7b 100644 --- a/Source/Toolkit/SharpDX.Toolkit.Graphics/EffectPool.cs +++ b/Source/Toolkit/SharpDX.Toolkit.Graphics/EffectPool.cs @@ -25,6 +25,7 @@ using SharpDX.Collections; using SharpDX.Direct3D; using SharpDX.Direct3D11; +using SharpDX.Toolkit.Collections; using SharpDX.Toolkit.Diagnostics; namespace SharpDX.Toolkit.Graphics diff --git a/Source/Toolkit/SharpDX.Toolkit.Graphics/GraphicsDevice.cs b/Source/Toolkit/SharpDX.Toolkit.Graphics/GraphicsDevice.cs index 19605f584..ab90f5c25 100644 --- a/Source/Toolkit/SharpDX.Toolkit.Graphics/GraphicsDevice.cs +++ b/Source/Toolkit/SharpDX.Toolkit.Graphics/GraphicsDevice.cs @@ -1,1541 +1,1542 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using SharpDX.Direct3D; -using SharpDX.Direct3D11; -using System; -using System.Collections.Generic; -using Device = SharpDX.Direct3D11.Device; - -namespace SharpDX.Toolkit.Graphics -{ - /// - /// This class is a front end to and . - /// - public class GraphicsDevice : Component - { - private readonly Dictionary sharedDataPerDevice; - private readonly Dictionary sharedDataPerDeviceContext = new Dictionary(); - internal Device Device; - internal DeviceContext Context; - internal CommonShaderStage[] ShaderStages; - private readonly ViewportF[] viewports = new ViewportF[16]; - internal IntPtr ResetSlotsPointers { get; private set; } - private int maxSlotCountForVertexBuffer; - - private const int SimultaneousRenderTargetCount = OutputMergerStage.SimultaneousRenderTargetCount; - private readonly RenderTargetView[] currentRenderTargetViews = new RenderTargetView[SimultaneousRenderTargetCount]; - private RenderTargetView currentRenderTargetView; - private int actualRenderTargetViewCount; - private DepthStencilView currentDepthStencilView; - - private readonly PrimitiveQuad primitiveQuad; - - private VertexInputLayout currentVertexInputLayout; - internal EffectPass CurrentPass; - - private readonly Dictionary inputSignatureCache; - - /// - /// Gets the features supported by this . - /// - public readonly GraphicsDeviceFeatures Features; - - /// - /// Default effect pool shared between all deferred GraphicsDevice instances. - /// - public readonly EffectPool DefaultEffectPool; - - /// - /// Gets the for immediate rendering. - /// - public readonly GraphicsDevice MainDevice; - - /// - /// Gets whether this is running in debug. - /// - public readonly bool IsDebugMode; - - /// - /// Gets whether this is a deferred context. - /// - public readonly bool IsDeferred; - - /// - /// Gets the registered for this graphics device. - /// - public readonly BlendStateCollection BlendStates; - - /// - /// Gets the registered for this graphics device. - /// - public readonly DepthStencilStateCollection DepthStencilStates; - - /// - /// Gets the registered for this graphics device. - /// - public readonly SamplerStateCollection SamplerStates; - - /// - /// Gets the registered for this graphics device. - /// - public readonly RasterizerStateCollection RasterizerStates; - - internal InputAssemblerStage InputAssemblerStage; - internal VertexShaderStage VertexShaderStage; - internal DomainShaderStage DomainShaderStage; - internal HullShaderStage HullShaderStage; - internal GeometryShaderStage GeometryShaderStage; - internal RasterizerStage RasterizerStage; - internal PixelShaderStage PixelShaderStage; - internal OutputMergerStage OutputMergerStage; - internal ComputeShaderStage ComputeShaderStage; - - internal readonly bool needWorkAroundForUpdateSubResource; - - protected GraphicsDevice(DriverType type, DeviceCreationFlags flags = DeviceCreationFlags.None, params FeatureLevel[] featureLevels) - : this((featureLevels != null && featureLevels.Length > 0) ? new Device(type, flags, featureLevels) : new Device(type, flags)) - { - } - - protected GraphicsDevice(GraphicsAdapter adapter, DeviceCreationFlags flags = DeviceCreationFlags.None, params FeatureLevel[] featureLevels) - : this((featureLevels != null && featureLevels.Length > 0) ? new Device(adapter, flags, featureLevels) : new Device(adapter, flags), adapter) - { - } - - protected GraphicsDevice(SharpDX.Direct3D11.Device existingDevice, GraphicsAdapter adapter = null) - { - Device = ToDispose(existingDevice); - Adapter = adapter; - - // If the adapter is null, then try to locate back the adapter - if (adapter == null) - { - try - { - using (var dxgiDevice = Device.QueryInterface()) - { - using (var dxgiAdapter = dxgiDevice.Adapter) - { - var deviceId = dxgiAdapter.Description.DeviceId; - - foreach (var graphicsAdapter in GraphicsAdapter.Adapters) - { - if (deviceId == graphicsAdapter.Description.DeviceId) - { - Adapter = graphicsAdapter; - break; - } - } - } - } - } - catch (Exception ex) - { - } - } - - EffectPools = new SharpDX.Collections.ObservableCollection(); - - IsDebugMode = (Device.CreationFlags & DeviceCreationFlags.Debug) != 0; - MainDevice = this; - Context = Device.ImmediateContext; - IsDeferred = false; - Features = new GraphicsDeviceFeatures(Device); - AutoViewportFromRenderTargets = true; // By default - - // Global cache for all input signatures inside a GraphicsDevice. - inputSignatureCache = new Dictionary(); - sharedDataPerDevice = new Dictionary(); - - // Create default Effect pool - DefaultEffectPool = EffectPool.New(this, "Default"); - - // Create all default states - BlendStates = ToDispose(new BlendStateCollection(this)); - DepthStencilStates = ToDispose(new DepthStencilStateCollection(this)); - SamplerStates = ToDispose(new SamplerStateCollection(this)); - RasterizerStates = ToDispose(new RasterizerStateCollection(this)); - - Initialize(); - - // Create Internal Effect - primitiveQuad = ToDispose(new PrimitiveQuad(this)); - } - - protected GraphicsDevice(GraphicsDevice mainDevice, DeviceContext deferredContext) - { - Device = mainDevice.Device; - Adapter = mainDevice.Adapter; - IsDebugMode = (Device.CreationFlags & DeviceCreationFlags.Debug) != 0; - MainDevice = mainDevice; - Context = deferredContext; - IsDeferred = true; - Features = mainDevice.Features; - - // Create default Effect pool - EffectPools = mainDevice.EffectPools; - DefaultEffectPool = mainDevice.DefaultEffectPool; - - // Copy the Global cache for all input signatures inside a GraphicsDevice. - inputSignatureCache = mainDevice.inputSignatureCache; - sharedDataPerDevice = mainDevice.sharedDataPerDevice; - - // Copy the reset vertex buffer - ResetSlotsPointers = mainDevice.ResetSlotsPointers; - - // Create all default states - BlendStates = mainDevice.BlendStates; - DepthStencilStates = mainDevice.DepthStencilStates; - SamplerStates = mainDevice.SamplerStates; - RasterizerStates = mainDevice.RasterizerStates; - - // Setup the workaround flag - needWorkAroundForUpdateSubResource = IsDeferred && !Features.HasDriverCommandLists; - Initialize(); - - // Create Internal Effect - primitiveQuad = ToDispose(new PrimitiveQuad(this)); - } - - /// - /// Initializes this instance. - /// - private void Initialize() - { - // Default null VertexBuffers used to reset - if (ResetSlotsPointers == IntPtr.Zero) - { - // CommonShaderStage.InputResourceSlotCount is the maximum of resources bindable in the whole pipeline - ResetSlotsPointers = ToDispose(Utilities.AllocateClearedMemory(Utilities.SizeOf() * CommonShaderStage.InputResourceSlotCount)); - } - - InputAssemblerStage = Context.InputAssembler; - VertexShaderStage = Context.VertexShader; - DomainShaderStage = Context.DomainShader; - HullShaderStage = Context.HullShader; - GeometryShaderStage = Context.GeometryShader; - RasterizerStage = Context.Rasterizer; - PixelShaderStage = Context.PixelShader; - OutputMergerStage = Context.OutputMerger; - ComputeShaderStage = Context.ComputeShader; - - // Precompute shader stages - ShaderStages = new CommonShaderStage[] - { - Context.VertexShader, - Context.HullShader, - Context.DomainShader, - Context.GeometryShader, - Context.PixelShader, - Context.ComputeShader - }; - - Performance = new GraphicsPerformance(this); - } - - /// - /// Check if a feature level is supported by a primary adapter. - /// - /// The feature level. - /// true if the primary adapter is supporting this feature level; otherwise, false. - public static bool IsProfileSupported(FeatureLevel featureLevel) - { - return SharpDX.Direct3D11.Device.IsSupportedFeatureLevel(featureLevel); - } - - /// - /// Gets the adapter associated with this device. - /// - public readonly GraphicsAdapter Adapter; - - /// - /// Gets the effect pools. - /// - /// The effect pools. - public SharpDX.Collections.ObservableCollection EffectPools { get; private set; } - - /// - /// Gets the back buffer sets by the current setup on this device. - /// - /// The back buffer. The returned value may be null if no are setup on this device. - public RenderTarget2D BackBuffer - { - get { return Presenter != null ? Presenter.BackBuffer : null; } - } - - /// - /// Gets the depth stencil buffer sets by the current setup on this device. - /// - /// The depth stencil buffer. The returned value may be null if no are setup on this device or no depth buffer was allocated. - public DepthStencilBuffer DepthStencilBuffer - { - get { return Presenter != null ? Presenter.DepthStencilBuffer : null; } - } - - /// - /// Gets or sets the current presenter use by the method. - /// - /// The current presenter. - public GraphicsPresenter Presenter { get; set; } - - /// - /// Gets or sets a value indicating whether the viewport is automatically calculated and set when a render target is set. Default is true. - /// - /// true if the viewport is automatically calculated and set when a render target is set; otherwise, false. - public bool AutoViewportFromRenderTargets { get; set; } - - /// - /// Gets the status of this device. - /// - /// ff476526 - /// GetDeviceRemovedReason - /// GetDeviceRemovedReason - /// HRESULT ID3D11Device::GetDeviceRemovedReason() - public GraphicsDeviceStatus GraphicsDeviceStatus - { - get - { - var result = ((Device)MainDevice).DeviceRemovedReason; - if (result == DXGI.ResultCode.DeviceRemoved) - { - return GraphicsDeviceStatus.Removed; - } - - if (result == DXGI.ResultCode.DeviceReset) - { - return GraphicsDeviceStatus.Reset; - } - - if (result == DXGI.ResultCode.DeviceHung) - { - return GraphicsDeviceStatus.Hung; - } - - if (result == DXGI.ResultCode.DriverInternalError) - { - return GraphicsDeviceStatus.InternalError; - } - - if (result == DXGI.ResultCode.InvalidCall) - { - return GraphicsDeviceStatus.InvalidCall; - } - - if (result.Code < 0) - { - return GraphicsDeviceStatus.Reset; - } - - return GraphicsDeviceStatus.Normal; - } - } - - /// - /// Gets the access to performance profiler. - /// - /// The access to performance profiler. - public GraphicsPerformance Performance { get; private set; } - - /// - /// Gets the default quad primitive to issue draw commands. - /// - /// The default quad primitive to issue draw commands. - public PrimitiveQuad Quad - { - get - { - return primitiveQuad; - } - } - - /// - /// Clears the default render target and depth stencil buffer attached to the current . - /// - /// Set this color value in all buffers. - /// Cannot clear without a Presenter set on this instance - public void Clear(Color4 color) - { - var options = currentRenderTargetView != null ? ClearOptions.Target : (ClearOptions)0; - - if (currentDepthStencilView != null) - { - var depthStencilBuffer = currentDepthStencilView.Tag as DepthStencilBuffer; - if (depthStencilBuffer == null) - { - throw new InvalidOperationException("Clear on a custom DepthStencilView is not supported by this method. Use Clear(DepthStencilView) directly"); - } - - options |= depthStencilBuffer.HasStencil ? ClearOptions.DepthBuffer | ClearOptions.Stencil : ClearOptions.DepthBuffer; - - } - - Clear(options, color, 1f, 0); - } - - /// - /// Clears the default render target and depth stencil buffer attached to the current . - /// - /// Options for clearing a buffer. - /// Set this four-component color value in the buffer. - /// Set this depth value in the buffer. - /// Set this stencil value in the buffer. - public void Clear(ClearOptions options, Color4 color, float depth, int stencil) - { - if ((options & ClearOptions.Target) != 0) - { - if (currentRenderTargetView == null) - { - throw new InvalidOperationException("No default render target view setup. Call SetRenderTargets before calling this method."); - } - Clear(currentRenderTargetView, color); - } - - if ((options & (ClearOptions.Stencil | ClearOptions.DepthBuffer)) != 0) - { - if (currentDepthStencilView == null) - { - throw new InvalidOperationException("No default depth stencil view setup. Call SetRenderTargets before calling this method."); - } - - var flags = (options & ClearOptions.DepthBuffer) != 0 ? DepthStencilClearFlags.Depth : 0; - if ((options & ClearOptions.Stencil) != 0) - { - flags |= DepthStencilClearFlags.Stencil; - } - - Clear(currentDepthStencilView, flags, depth, (byte)stencil); - } - } - - /// - /// Clears the default render target and depth stencil buffer attached to the current . - /// - /// Options for clearing a buffer. - /// Set this four-component color value in the buffer. - /// Set this depth value in the buffer. - /// Set this stencil value in the buffer. - public void Clear(ClearOptions options, Vector4 color, float depth, int stencil) - { - Clear(options, (Color4)color, depth, stencil); - } - - /// - /// Clears a render target view by setting all the elements in a render target to one value. - /// - /// The render target view. - /// A 4-component array that represents the color to fill the render target with. - ///

Applications that wish to clear a render target to a specific integer value bit pattern should render a screen-aligned quad instead of using this method. The reason for this is because this method accepts as input a floating point value, which may not have the same bit pattern as the original integer.

Differences between Direct3D 9 and Direct3D 11/10:

Unlike Direct3D 9, the full extent of the resource view is always cleared. Viewport and scissor settings are not applied.

?

- /// ff476388 - /// void ID3D11DeviceContext::ClearRenderTargetView([In] ID3D11RenderTargetView* pRenderTargetView,[In] const SHARPDX_COLOR4* ColorRGBA) - /// ID3D11DeviceContext::ClearRenderTargetView - public void Clear(SharpDX.Direct3D11.RenderTargetView renderTargetView, Color4 colorRGBA) - { - Context.ClearRenderTargetView(renderTargetView, colorRGBA); - } - - /// - /// Clears the depth-stencil resource. - /// - ///

Pointer to the depth stencil to be cleared.

- ///

Identify the type of data to clear (see ).

- ///

Clear the depth buffer with this value. This value will be clamped between 0 and 1.

- ///

Clear the stencil buffer with this value.

- /// - ///

Differences between Direct3D 9 and Direct3D 11/10:

Unlike Direct3D 9, the full extent of the resource view is always cleared. Viewport and scissor settings are not applied.

?

- ///
- /// ff476387 - /// void ID3D11DeviceContext::ClearDepthStencilView([In] ID3D11DepthStencilView* pDepthStencilView,[In] D3D11_CLEAR_FLAG ClearFlags,[In] float Depth,[In] unsigned char Stencil) - /// ID3D11DeviceContext::ClearDepthStencilView - public void Clear(SharpDX.Direct3D11.DepthStencilView depthStencilView, SharpDX.Direct3D11.DepthStencilClearFlags clearFlags, float depth, byte stencil) - { - Context.ClearDepthStencilView(depthStencilView, clearFlags, depth, stencil); - } - - /// - /// Clears an unordered access resource with bit-precise values. - /// - /// The buffer to clear. - /// The value used to clear. - /// - ///

This API copies the lower ni bits from each array element i to the corresponding channel, where ni is the number of bits in the ith channel of the resource format (for example, R8G8B8_FLOAT has 8 bits for the first 3 channels). This works on any UAV with no format conversion. For a raw or structured buffer view, only the first array element value is used.

- ///
- /// ff476391 - /// void ID3D11DeviceContext::ClearUnorderedAccessViewUint([In] ID3D11UnorderedAccessView* pUnorderedAccessView,[In] const unsigned int* Values) - /// ID3D11DeviceContext::ClearUnorderedAccessViewUint - public void Clear(UnorderedAccessView view, Int4 value) - { - Context.ClearUnorderedAccessView(view, value); - } - - /// - /// Clears an unordered access resource with a float value. - /// - /// The buffer to clear. - /// The value used to clear. - /// - ///

This API works on FLOAT, UNORM, and SNORM unordered access views (UAVs), with format conversion from FLOAT to *NORM where appropriate. On other UAVs, the operation is invalid and the call will not reach the driver.

- ///
- /// ff476390 - /// void ID3D11DeviceContext::ClearUnorderedAccessViewFloat([In] ID3D11UnorderedAccessView* pUnorderedAccessView,[In] const float* Values) - /// ID3D11DeviceContext::ClearUnorderedAccessViewFloat - public void Clear(UnorderedAccessView view, Vector4 value) - { - Context.ClearUnorderedAccessView(view, value); - } - - /// - /// Copies the content of this resource to another . - /// - /// The resource to copy from. - /// The resource to copy to. - /// See the unmanaged documentation for usage and restrictions. - /// ff476392 - /// void ID3D11DeviceContext::CopyResource([In] ID3D11Resource* pDstResource,[In] ID3D11Resource* pSrcResource) - /// ID3D11DeviceContext::CopyResource - public void Copy(Direct3D11.Resource fromResource, Direct3D11.Resource toResource) - { - Context.CopyResource(fromResource, toResource); - } - - /// - /// Copy a region from a source resource to a destination resource. - /// - /// - /// The source box must be within the size of the source resource. The destination offsets, (x, y, and z) allow the source box to be offset when writing into the destination resource; however, the dimensions of the source box and the offsets must be within the size of the resource. If the resources are buffers, all coordinates are in bytes; if the resources are textures, all coordinates are in texels. {{D3D11CalcSubresource}} is a helper function for calculating subresource indexes. CopySubresourceRegion performs the copy on the GPU (similar to a memcpy by the CPU). As a consequence, the source and destination resources: Must be different subresources (although they can be from the same resource). Must be the same type. Must have compatible DXGI formats (identical or from the same type group). For example, a DXGI_FORMAT_R32G32B32_FLOAT texture can be copied to an DXGI_FORMAT_R32G32B32_UINT texture since both of these formats are in the DXGI_FORMAT_R32G32B32_TYPELESS group. May not be currently mapped. CopySubresourceRegion only supports copy; it does not support any stretch, color key, blend, or format conversions. An application that needs to copy an entire resource should use instead. CopySubresourceRegion is an asynchronous call which may be added to the command-buffer queue, this attempts to remove pipeline stalls that may occur when copying data. See performance considerations for more details. Note??If you use CopySubresourceRegion with a depth-stencil buffer or a multisampled resource, you must copy the whole subresource. In this situation, you must pass 0 to the DstX, DstY, and DstZ parameters and NULL to the pSrcBox parameter. In addition, source and destination resources, which are represented by the pSrcResource and pDstResource parameters, should have identical sample count values. Example The following code snippet copies a box (located at (120,100),(200,220)) from a source texture into a region (10,20),(90,140) in a destination texture. - /// D3D11_BOX sourceRegion; - /// sourceRegion.left = 120; - /// sourceRegion.right = 200; - /// sourceRegion.top = 100; - /// sourceRegion.bottom = 220; - /// sourceRegion.front = 0; - /// sourceRegion.back = 1; pd3dDeviceContext->CopySubresourceRegion( pDestTexture, 0, 10, 20, 0, pSourceTexture, 0, &sourceRegion ); - /// - /// Notice, that for a 2D texture, front and back are set to 0 and 1 respectively. - /// - /// A reference to the source resource (see ). - /// Source subresource index. - /// A reference to the destination resource (see ). - /// Destination subresource index. - /// The x-coordinate of the upper left corner of the destination region. - /// The y-coordinate of the upper left corner of the destination region. For a 1D subresource, this must be zero. - /// The z-coordinate of the upper left corner of the destination region. For a 1D or 2D subresource, this must be zero. - /// ff476394 - /// void ID3D11DeviceContext::CopySubresourceRegion([In] ID3D11Resource* pDstResource,[In] unsigned int DstSubresource,[In] unsigned int DstX,[In] unsigned int DstY,[In] unsigned int DstZ,[In] ID3D11Resource* pSrcResource,[In] unsigned int SrcSubresource,[In, Optional] const D3D11_BOX* pSrcBox) - /// ID3D11DeviceContext::CopySubresourceRegion - public void Copy(SharpDX.Direct3D11.Resource source, int sourceSubresource, SharpDX.Direct3D11.Resource destination, int destinationSubResource, int dstX = 0, int dstY = 0, int dstZ = 0) - { - Context.CopySubresourceRegion(source, sourceSubresource, null, destination, destinationSubResource, dstX, dstY, dstZ); - } - - /// - /// Copy a region from a source resource to a destination resource. - /// - /// - /// The source box must be within the size of the source resource. The destination offsets, (x, y, and z) allow the source box to be offset when writing into the destination resource; however, the dimensions of the source box and the offsets must be within the size of the resource. If the resources are buffers, all coordinates are in bytes; if the resources are textures, all coordinates are in texels. {{D3D11CalcSubresource}} is a helper function for calculating subresource indexes. CopySubresourceRegion performs the copy on the GPU (similar to a memcpy by the CPU). As a consequence, the source and destination resources: Must be different subresources (although they can be from the same resource). Must be the same type. Must have compatible DXGI formats (identical or from the same type group). For example, a DXGI_FORMAT_R32G32B32_FLOAT texture can be copied to an DXGI_FORMAT_R32G32B32_UINT texture since both of these formats are in the DXGI_FORMAT_R32G32B32_TYPELESS group. May not be currently mapped. CopySubresourceRegion only supports copy; it does not support any stretch, color key, blend, or format conversions. An application that needs to copy an entire resource should use instead. CopySubresourceRegion is an asynchronous call which may be added to the command-buffer queue, this attempts to remove pipeline stalls that may occur when copying data. See performance considerations for more details. Note??If you use CopySubresourceRegion with a depth-stencil buffer or a multisampled resource, you must copy the whole subresource. In this situation, you must pass 0 to the DstX, DstY, and DstZ parameters and NULL to the pSrcBox parameter. In addition, source and destination resources, which are represented by the pSrcResource and pDstResource parameters, should have identical sample count values. Example The following code snippet copies a box (located at (120,100),(200,220)) from a source texture into a region (10,20),(90,140) in a destination texture. - /// D3D11_BOX sourceRegion; - /// sourceRegion.left = 120; - /// sourceRegion.right = 200; - /// sourceRegion.top = 100; - /// sourceRegion.bottom = 220; - /// sourceRegion.front = 0; - /// sourceRegion.back = 1; pd3dDeviceContext->CopySubresourceRegion( pDestTexture, 0, 10, 20, 0, pSourceTexture, 0, &sourceRegion ); - /// - /// Notice, that for a 2D texture, front and back are set to 0 and 1 respectively. - /// - /// A reference to the source resource (see ). - /// Source subresource index. - /// A reference to a 3D box (see ) that defines the source subresources that can be copied. If NULL, the entire source subresource is copied. The box must fit within the source resource. - /// A reference to the destination resource (see ). - /// Destination subresource index. - /// The x-coordinate of the upper left corner of the destination region. - /// The y-coordinate of the upper left corner of the destination region. For a 1D subresource, this must be zero. - /// The z-coordinate of the upper left corner of the destination region. For a 1D or 2D subresource, this must be zero. - /// ff476394 - /// void ID3D11DeviceContext::CopySubresourceRegion([In] ID3D11Resource* pDstResource,[In] unsigned int DstSubresource,[In] unsigned int DstX,[In] unsigned int DstY,[In] unsigned int DstZ,[In] ID3D11Resource* pSrcResource,[In] unsigned int SrcSubresource,[In, Optional] const D3D11_BOX* pSrcBox) - /// ID3D11DeviceContext::CopySubresourceRegion - public void Copy(SharpDX.Direct3D11.Resource source, int sourceSubresource, SharpDX.Direct3D11.ResourceRegion sourceRegion, SharpDX.Direct3D11.Resource destination, int destinationSubResource, int dstX = 0, int dstY = 0, int dstZ = 0) - { - Context.CopySubresourceRegion(source, sourceSubresource, sourceRegion, destination, destinationSubResource, dstX, dstY, dstZ); - } - - /// - /// Copy a multisampled resource into a non-multisampled resource. - /// - /// - /// This API is most useful when re-using the resulting render target of one render pass as an input to a second render pass. The source and destination resources must be the same resource type and have the same dimensions. In addition, they must have compatible formats. There are three scenarios for this: ScenarioRequirements Source and destination are prestructured and typedBoth the source and destination must have identical formats and that format must be specified in the Format parameter. One resource is prestructured and typed and the other is prestructured and typelessThe typed resource must have a format that is compatible with the typeless resource (i.e. the typed resource is DXGI_FORMAT_R32_FLOAT and the typeless resource is DXGI_FORMAT_R32_TYPELESS). The format of the typed resource must be specified in the Format parameter. Source and destination are prestructured and typelessBoth the source and destination must have the same typeless format (i.e. both must have DXGI_FORMAT_R32_TYPELESS), and the Format parameter must specify a format that is compatible with the source and destination (i.e. if both are DXGI_FORMAT_R32_TYPELESS then DXGI_FORMAT_R32_FLOAT could be specified in the Format parameter). For example, given the DXGI_FORMAT_R16G16B16A16_TYPELESS format: The source (or dest) format could be DXGI_FORMAT_R16G16B16A16_UNORM The dest (or source) format could be DXGI_FORMAT_R16G16B16A16_FLOAT ? - /// - /// Source resource. Must be multisampled. - /// >The source subresource of the source resource. - /// Destination resource. Must be a created with the flag and be single-sampled. See . - /// A zero-based index, that identifies the destination subresource. Use {{D3D11CalcSubresource}} to calculate the index. - /// A that indicates how the multisampled resource will be resolved to a single-sampled resource. See remarks. - /// void ID3D11DeviceContext::ResolveSubresource([In] ID3D11Resource* pDstResource,[In] int DstSubresource,[In] ID3D11Resource* pSrcResource,[In] int SrcSubresource,[In] DXGI_FORMAT Format) - public void Copy(SharpDX.Direct3D11.Resource source, int sourceSubresource, SharpDX.Direct3D11.Resource destination, int destinationSubresource, SharpDX.DXGI.Format format) - { - Context.ResolveSubresource(source, sourceSubresource, destination, destinationSubresource, format); - } - - /// - ///

Copies data from a buffer holding variable length data.

- ///
- ///

Pointer to an of a Structured Buffer resource created with either or specified when the UAV was created. These types of resources have hidden counters tracking "how many" records have been written.

- ///

Pointer to . This can be any buffer resource that other copy commands, such as or , are able to write to.

- ///

Offset from the start of pDstBuffer to write 32-bit UINT structure (vertex) count from pSrcView.

- /// ff476393 - /// void ID3D11DeviceContext::CopyStructureCount([In] ID3D11Buffer* pDstBuffer,[In] unsigned int DstAlignedByteOffset,[In] ID3D11UnorderedAccessView* pSrcView) - /// ID3D11DeviceContext::CopyStructureCount - public void CopyCount(SharpDX.Direct3D11.UnorderedAccessView sourceView, SharpDX.Direct3D11.Buffer destinationBuffer, int offsetInBytes = 0) - { - Context.CopyStructureCount(destinationBuffer, offsetInBytes, sourceView); - } - - /// - ///

Restore all default settings.

- ///
- /// - ///

This method resets any device context to the default settings. This sets all input/output resource slots, shaders, input layouts, predications, scissor rectangles, depth-stencil state, rasterizer state, blend state, sampler state, and viewports to null. The primitive topology is set to UNDEFINED.

For a scenario where you would like to clear a list of commands recorded so far, call and throw away the resulting .

- ///
- /// ff476389 - /// void ID3D11DeviceContext::ClearState() - /// ID3D11DeviceContext::ClearState - public void ClearState() - { - Context.ClearState(); - } - - private PrimitiveTopology PrimitiveType - { - set - { - InputAssemblerStage.PrimitiveTopology = value; - } - } - - /// - ///

Draw indexed, non-instanced primitives.

- ///
- /// Type of the primitive to draw. - ///

Number of indices to draw.

- ///

The location of the first index read by the GPU from the index buffer.

- ///

A value added to each index before reading a vertex from the vertex buffer.

- /// - ///

A draw API submits work to the rendering pipeline.

If the sum of both indices is negative, the result of the function call is undefined.

- ///
- /// ff476409 - /// void ID3D11DeviceContext::DrawIndexed([In] unsigned int IndexCount,[In] unsigned int StartIndexLocation,[In] int BaseVertexLocation) - /// ID3D11DeviceContext::DrawIndexed - public void DrawIndexed(PrimitiveType primitiveType, int indexCount, int startIndexLocation = 0, int baseVertexLocation = 0) - { - SetupInputLayout(); - - PrimitiveType = primitiveType; - Context.DrawIndexed(indexCount, startIndexLocation, baseVertexLocation); - } - - /// - ///

Draw non-indexed, non-instanced primitives.

- ///
- /// Type of the primitive to draw. - ///

Number of vertices to draw.

- ///

Index of the first vertex, which is usually an offset in a vertex buffer; it could also be used as the first vertex id generated for a shader parameter marked with the SV_TargetId system-value semantic.

- /// - ///

A draw API submits work to the rendering pipeline.

The vertex data for a draw call normally comes from a vertex buffer that is bound to the pipeline. However, you could also provide the vertex data from a shader that has vertex data marked with the SV_VertexId system-value semantic.

- ///
- /// ff476407 - /// void ID3D11DeviceContext::Draw([In] unsigned int VertexCount,[In] unsigned int StartVertexLocation) - /// ID3D11DeviceContext::Draw - public void Draw(PrimitiveType primitiveType, int vertexCount, int startVertexLocation = 0) - { - SetupInputLayout(); - - PrimitiveType = primitiveType; - Context.Draw(vertexCount, startVertexLocation); - } - - /// - ///

Draw indexed, instanced primitives.

- ///
- /// Type of the primitive to draw. - ///

Number of indices read from the index buffer for each instance.

- ///

Number of instances to draw.

- ///

The location of the first index read by the GPU from the index buffer.

- ///

A value added to each index before reading a vertex from the vertex buffer.

- ///

A value added to each index before reading per-instance data from a vertex buffer.

- /// - ///

A draw API submits work to the rendering pipeline.

Instancing may extend performance by reusing the same geometry to draw multiple objects in a scene. One example of instancing could be to draw the same object with different positions and colors. Indexing requires multiple vertex buffers: at least one for per-vertex data and a second buffer for per-instance data.

- ///
- /// ff476410 - /// void ID3D11DeviceContext::DrawIndexedInstanced([In] unsigned int IndexCountPerInstance,[In] unsigned int InstanceCount,[In] unsigned int StartIndexLocation,[In] int BaseVertexLocation,[In] unsigned int StartInstanceLocation) - /// ID3D11DeviceContext::DrawIndexedInstanced - public void DrawIndexedInstanced(PrimitiveType primitiveType, int indexCountPerInstance, int instanceCount, int startIndexLocation = 0, int baseVertexLocation = 0, int startInstanceLocation = 0) - { - SetupInputLayout(); - - PrimitiveType = primitiveType; - Context.DrawIndexedInstanced(indexCountPerInstance, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation); - } - - /// - ///

Draw non-indexed, instanced primitives.

- ///
- /// Type of the primitive to draw. - ///

Number of vertices to draw.

- ///

Number of instances to draw.

- ///

Index of the first vertex.

- ///

A value added to each index before reading per-instance data from a vertex buffer.

- /// - ///

A draw API submits work to the rendering pipeline.

Instancing may extend performance by reusing the same geometry to draw multiple objects in a scene. One example of instancing could be to draw the same object with different positions and colors.

The vertex data for an instanced draw call normally comes from a vertex buffer that is bound to the pipeline. However, you could also provide the vertex data from a shader that has instanced data identified with a system-value semantic (SV_InstanceID).

- ///
- /// ff476412 - /// void ID3D11DeviceContext::DrawInstanced([In] unsigned int VertexCountPerInstance,[In] unsigned int InstanceCount,[In] unsigned int StartVertexLocation,[In] unsigned int StartInstanceLocation) - /// ID3D11DeviceContext::DrawInstanced - public void DrawInstanced(PrimitiveType primitiveType, int vertexCountPerInstance, int instanceCount, int startVertexLocation = 0, int startInstanceLocation = 0) - { - SetupInputLayout(); - - PrimitiveType = primitiveType; - Context.DrawInstanced(vertexCountPerInstance, instanceCount, startVertexLocation, startInstanceLocation); - } - - /// - ///

Draw geometry of an unknown size.

- ///
- /// Type of the primitive to draw. - /// - ///

A draw API submits work to the rendering pipeline. This API submits work of an unknown size that was processed by the input assembler, vertex shader, and stream-output stages; the work may or may not have gone through the geometry-shader stage.

After data has been streamed out to stream-output stage buffers, those buffers can be again bound to the Input Assembler stage at input slot 0 and DrawAuto will draw them without the application needing to know the amount of data that was written to the buffers. A measurement of the amount of data written to the SO stage buffers is maintained internally when the data is streamed out. This means that the CPU does not need to fetch the measurement before re-binding the data that was streamed as input data. Although this amount is tracked internally, it is still the responsibility of applications to use input layouts to describe the format of the data in the SO stage buffers so that the layouts are available when the buffers are again bound to the input assembler.

The following diagram shows the DrawAuto process.

Calling DrawAuto does not change the state of the streaming-output buffers that were bound again as inputs.

DrawAuto only works when drawing with one input buffer bound as an input to the IA stage at slot 0. Applications must create the SO buffer resource with both binding flags, and .

This API does not support indexing or instancing.

If an application needs to retrieve the size of the streaming-output buffer, it can query for statistics on streaming output by using .

- ///
- /// ff476408 - /// void ID3D11DeviceContext::DrawAuto() - /// ID3D11DeviceContext::DrawAuto - public void DrawAuto(PrimitiveType primitiveType) - { - SetupInputLayout(); - - PrimitiveType = primitiveType; - Context.DrawAuto(); - } - - /// - ///

Draw indexed, instanced, GPU-generated primitives.

- ///
- /// Type of the primitive to draw. - ///

A reference to an , which is a buffer containing the GPU generated primitives.

- ///

Offset in pBufferForArgs to the start of the GPU generated primitives.

- /// - ///

When an application creates a buffer that is associated with the interface that pBufferForArgs points to, the application must set the flag in the MiscFlags member of the structure that describes the buffer. To create the buffer, the application calls the method and in this call passes a reference to in the pDesc parameter.

- ///
- /// ff476411 - /// void ID3D11DeviceContext::DrawIndexedInstancedIndirect([In] ID3D11Buffer* pBufferForArgs,[In] unsigned int AlignedByteOffsetForArgs) - /// ID3D11DeviceContext::DrawIndexedInstancedIndirect - public void DrawIndexedInstanced(PrimitiveType primitiveType, SharpDX.Direct3D11.Buffer argumentsBuffer, int alignedByteOffsetForArgs = 0) - { - SetupInputLayout(); - - PrimitiveType = primitiveType; - Context.DrawIndexedInstancedIndirect(argumentsBuffer, alignedByteOffsetForArgs); - } - - /// - ///

Draw instanced, GPU-generated primitives.

- ///
- /// Type of the primitive to draw. - ///

A reference to an , which is a buffer containing the GPU generated primitives.

- ///

Offset in pBufferForArgs to the start of the GPU generated primitives.

- /// - ///

When an application creates a buffer that is associated with the interface that pBufferForArgs points to, the application must set the flag in the MiscFlags member of the structure that describes the buffer. To create the buffer, the application calls the method and in this call passes a reference to in the pDesc parameter.

- ///
- /// ff476413 - /// void ID3D11DeviceContext::DrawInstancedIndirect([In] ID3D11Buffer* pBufferForArgs,[In] unsigned int AlignedByteOffsetForArgs) - /// ID3D11DeviceContext::DrawInstancedIndirect - public void DrawInstanced(PrimitiveType primitiveType, SharpDX.Direct3D11.Buffer argumentsBuffer, int alignedByteOffsetForArgs = 0) - { - SetupInputLayout(); - - PrimitiveType = primitiveType; - Context.DrawInstancedIndirect(argumentsBuffer, alignedByteOffsetForArgs); - } - - /// - ///

Execute a command list from a thread group.

- ///
- ///

The number of groups dispatched in the x direction. ThreadGroupCountX must be less than (65535).

- ///

The number of groups dispatched in the y direction. ThreadGroupCountY must be less than (65535).

- ///

The number of groups dispatched in the z direction. ThreadGroupCountZ must be less than (65535). In feature level 10 the value for ThreadGroupCountZ must be 1.

- /// - ///

You call the Dispatch method to execute commands in a compute shader. A compute shader can be run on many threads in parallel, within a thread group. Index a particular thread, within a thread group using a 3D vector given by (x,y,z).

In the following illustration, assume a thread group with 50 threads where the size of the group is given by (5,5,2). A single thread is identified from a thread group with 50 threads in it, using the vector (4,1,1).

The following illustration shows the relationship between the parameters passed to , Dispatch(5,3,2), the values specified in the numthreads attribute, numthreads(10,8,3), and values that will passed to the compute shader for the thread-related system values - /// (SV_GroupIndex,SV_DispatchThreadID,SV_GroupThreadID,SV_GroupID).

- ///
- /// ff476405 - /// void ID3D11DeviceContext::Dispatch([In] unsigned int ThreadGroupCountX,[In] unsigned int ThreadGroupCountY,[In] unsigned int ThreadGroupCountZ) - /// ID3D11DeviceContext::Dispatch - public void Dispatch(int threadGroupCountX, int threadGroupCountY, int threadGroupCountZ) - { - Context.Dispatch(threadGroupCountX, threadGroupCountY, threadGroupCountZ); - } - - /// - ///

Execute a command list over one or more thread groups.

- ///
- ///

A reference to an , which must be loaded with data that matches the argument list for .

- ///

A byte-aligned offset between the start of the buffer and the arguments.

- /// - ///

You call the DispatchIndirect method to execute commands in a compute shader.

When an application creates a buffer that is associated with the interface that pBufferForArgs points to, the application must set the flag in the MiscFlags member of the structure that describes the buffer. To create the buffer, the application calls the method and in this call passes a reference to in the pDesc parameter.

- ///
- /// ff476406 - /// void ID3D11DeviceContext::DispatchIndirect([In] ID3D11Buffer* pBufferForArgs,[In] unsigned int AlignedByteOffsetForArgs) - /// ID3D11DeviceContext::DispatchIndirect - public void Dispatch(SharpDX.Direct3D11.Buffer argumentsBuffer, int alignedByteOffsetForArgs = 0) - { - Context.DispatchIndirect(argumentsBuffer, alignedByteOffsetForArgs); - } - - /// - ///

Sends queued-up commands in the command buffer to the graphics processing unit (GPU).

- ///
- /// - ///

Most applications don't need to call this method. If an application calls this method when not necessary, it incurs a performance penalty. Each call to Flush incurs a significant amount of overhead.

When Microsoft Direct3D state-setting, present, or draw commands are called by an application, those commands are queued into an internal command buffer. Flush sends those commands to the GPU for processing. Typically, the Direct3D runtime sends these commands to the GPU automatically whenever the runtime determines that they need to be sent, such as when the command buffer is full or when an application maps a resource. Flush sends the commands manually.

We recommend that you use Flush when the CPU waits for an arbitrary amount of time (such as when you call the Sleep function).

Because Flush operates asynchronously, it can return either before or after the GPU finishes executing the queued graphics commands. However, the graphics commands eventually always complete. You can call the method with the value to create an event query; you can then use that event query in a call to the method to determine when the GPU is finished processing the graphics commands. - ///

Microsoft Direct3D?11 defers the destruction of objects. Therefore, an application can't rely upon objects immediately being destroyed. By calling Flush, you destroy any objects whose destruction was deferred. If an application requires synchronous destruction of an object, we recommend that the application release all its references, call , and then call Flush.

Deferred Destruction Issues with Flip Presentation Swap Chains

Direct3D?11 defers the destruction of objects like views and resources until it can efficiently destroy them. This deferred destruction can cause problems with flip presentation model swap chains. Flip presentation model swap chains have the DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL flag set. When you create a flip presentation model swap chain, you can associate only one swap chain at a time with an , IWindow, or composition surface. If an application attempts to destroy a flip presentation model swap chain and replace it with another swap chain, the original swap chain is not destroyed when the application immediately frees all of the original swap chain's references.

Most applications typically use the method for the majority of scenarios where they replace new swap chain buffers for old swap chain buffers. However, if an application must actually destroy an old swap chain and create a new swap chain, the application must force the destruction of all objects that the application freed. To force the destruction, call (or otherwise ensure no views are bound to pipeline state), and then call Flush on the immediate context. You must force destruction before you call IDXGIFactory2::CreateSwapChainForHwnd, IDXGIFactory2::CreateSwapChainForImmersiveWindow, or IDXGIFactory2::CreateSwapChainForCompositionSurface again to create a new swap chain.

- ///
- /// ff476425 - /// void ID3D11DeviceContext::Flush() - /// ID3D11DeviceContext::Flush - public void Flush() - { - Context.Flush(); - } - - /// - /// Creates a new from an existing . - /// - /// An existing device. - /// A new instance of . - public static GraphicsDevice New(SharpDX.Direct3D11.Device existingDevice) - { - return new GraphicsDevice(existingDevice); - } - - /// - /// Creates a new using . - /// - /// The flags. - /// The feature levels. - /// A new instance of - public static GraphicsDevice New(DeviceCreationFlags flags = DeviceCreationFlags.None, params FeatureLevel[] featureLevels) - { - return New(DriverType.Hardware, flags, featureLevels); - } - - /// - /// Creates a new . - /// - /// The type. - /// The flags. - /// The feature levels. - /// A new instance of . - public static GraphicsDevice New(DriverType type, DeviceCreationFlags flags = DeviceCreationFlags.None, params FeatureLevel[] featureLevels) - { - if (type == DriverType.Hardware) - return new GraphicsDevice(GraphicsAdapter.Default, flags, featureLevels); - - return new GraphicsDevice(type, flags, featureLevels); - } - - /// - /// Creates a new . - /// - /// The graphics adapter to use. - /// The flags. - /// The feature levels. - /// A new instance of . - public static GraphicsDevice New(GraphicsAdapter adapter, DeviceCreationFlags flags = DeviceCreationFlags.None, params FeatureLevel[] featureLevels) - { - return new GraphicsDevice(adapter, flags, featureLevels); - } - - /// - /// Creates a new deferred . - /// - /// A deferred . - public GraphicsDevice NewDeferred() - { - return new GraphicsDevice(this, new DeviceContext(Device)); - } - - /// - ///

Sets the blend state of the output-merger stage.

- ///
- ///

Pointer to a blend-state interface (see ). Passing in null implies a default blend state. See remarks for further details.

- /// - ///

Blend state is used by the output-merger stage to determine how to blend together two pixel values. The two values are commonly the current pixel value and the pixel value already in the output render target. Use the blend operation to control where the two pixel values come from and how they are mathematically combined.

To create a blend-state interface, call .

Passing in null for the blend-state interface indicates to the runtime to set a default blending state. The following table indicates the default blending parameters.

StateDefault Value
AlphaToCoverageEnable
BlendEnable[8]
SrcBlend
DstBlend
BlendOp
SrcBlendAlpha
DstBlendAlpha
BlendOpAlpha
RenderTargetWriteMask[8][8]

?

A sample mask determines which samples get updated in all the active render targets. The mapping of bits in a sample mask to samples in a multisample render target is the responsibility of an individual application. A sample mask is always applied; it is independent of whether multisampling is enabled, and does not depend on whether an application uses multisample render targets.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

- ///
- /// ff476462 - /// void ID3D11DeviceContext::OMSetBlendState([In, Optional] ID3D11BlendState* pBlendState,[In, Optional] const SHARPDX_COLOR4* BlendFactor,[In] unsigned int SampleMask) - /// ID3D11DeviceContext::OMSetBlendState - public void SetBlendState(BlendState blendState) - { - if (blendState == null) - { - OutputMergerStage.SetBlendState(null, Color.White, -1); - } - else - { - OutputMergerStage.SetBlendState(blendState, blendState.BlendFactor, blendState.MultiSampleMask); - } - } - - /// - ///

Sets the blend state of the output-merger stage.

- ///
- ///

Pointer to a blend-state interface (see ). Passing in null implies a default blend state. See remarks for further details.

- ///

Array of blend factors, one for each RGBA component. This requires a blend state object that specifies the option.

- ///

32-bit sample coverage. The default value is 0xffffffff. See remarks.

- /// - ///

Blend state is used by the output-merger stage to determine how to blend together two pixel values. The two values are commonly the current pixel value and the pixel value already in the output render target. Use the blend operation to control where the two pixel values come from and how they are mathematically combined.

To create a blend-state interface, call .

Passing in null for the blend-state interface indicates to the runtime to set a default blending state. The following table indicates the default blending parameters.

StateDefault Value
AlphaToCoverageEnable
BlendEnable[8]
SrcBlend
DstBlend
BlendOp
SrcBlendAlpha
DstBlendAlpha
BlendOpAlpha
RenderTargetWriteMask[8][8]

?

A sample mask determines which samples get updated in all the active render targets. The mapping of bits in a sample mask to samples in a multisample render target is the responsibility of an individual application. A sample mask is always applied; it is independent of whether multisampling is enabled, and does not depend on whether an application uses multisample render targets.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

- ///
- /// ff476462 - /// void ID3D11DeviceContext::OMSetBlendState([In, Optional] ID3D11BlendState* pBlendState,[In, Optional] const SHARPDX_COLOR4* BlendFactor,[In] unsigned int SampleMask) - /// ID3D11DeviceContext::OMSetBlendState - public void SetBlendState(BlendState blendState, Color4 blendFactor, int multiSampleMask = -1) - { - if (blendState == null) - { - OutputMergerStage.SetBlendState(null, blendFactor, multiSampleMask); - } - else - { - OutputMergerStage.SetBlendState(blendState, blendFactor, multiSampleMask); - } - } - - /// - ///

Sets the blend state of the output-merger stage.

- ///
- ///

Pointer to a blend-state interface (see ). Passing in null implies a default blend state. See remarks for further details.

- ///

Array of blend factors, one for each RGBA component. This requires a blend state object that specifies the option.

- ///

32-bit sample coverage. The default value is 0xffffffff. See remarks.

- /// - ///

Blend state is used by the output-merger stage to determine how to blend together two pixel values. The two values are commonly the current pixel value and the pixel value already in the output render target. Use the blend operation to control where the two pixel values come from and how they are mathematically combined.

To create a blend-state interface, call .

Passing in null for the blend-state interface indicates to the runtime to set a default blending state. The following table indicates the default blending parameters.

StateDefault Value
AlphaToCoverageEnable
BlendEnable[8]
SrcBlend
DstBlend
BlendOp
SrcBlendAlpha
DstBlendAlpha
BlendOpAlpha
RenderTargetWriteMask[8][8]

?

A sample mask determines which samples get updated in all the active render targets. The mapping of bits in a sample mask to samples in a multisample render target is the responsibility of an individual application. A sample mask is always applied; it is independent of whether multisampling is enabled, and does not depend on whether an application uses multisample render targets.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

- ///
- /// ff476462 - /// void ID3D11DeviceContext::OMSetBlendState([In, Optional] ID3D11BlendState* pBlendState,[In, Optional] const SHARPDX_COLOR4* BlendFactor,[In] unsigned int SampleMask) - /// ID3D11DeviceContext::OMSetBlendState - public void SetBlendState(BlendState blendState, Color4 blendFactor, uint multiSampleMask = 0xFFFFFFFF) - { - SetBlendState(blendState, blendFactor, unchecked((int)multiSampleMask)); - } - - /// - /// Sets the depth-stencil state of the output-merger stage. - /// - ///

Pointer to a depth-stencil state interface (see ) to bind to the device. Set this to null to use the default state listed in .

- ///

Reference value to perform against when doing a depth-stencil test. See remarks.

- /// - ///

To create a depth-stencil state interface, call .

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

- ///
- /// ff476463 - /// void ID3D11DeviceContext::OMSetDepthStencilState([In, Optional] ID3D11DepthStencilState* pDepthStencilState,[In] unsigned int StencilRef) - /// ID3D11DeviceContext::OMSetDepthStencilState - public void SetDepthStencilState(DepthStencilState depthStencilState, int stencilReference = 0) - { - OutputMergerStage.SetDepthStencilState(depthStencilState, stencilReference); - } - - /// - ///

Sets the rasterizer state for the rasterizer stage of the pipeline.

- ///
- /// The rasterizer state to set on this device. - /// ff476479 - /// void ID3D11DeviceContext::RSSetState([In, Optional] ID3D11RasterizerState* pRasterizerState) - /// ID3D11DeviceContext::RSSetState - public void SetRasterizerState(RasterizerState rasterizerState) - { - RasterizerStage.State = rasterizerState; - } - - /// - /// Binds a single scissor rectangle to the rasterizer stage. - /// - /// The left. - /// The top. - /// The right. - /// The bottom. - /// - ///

All scissor rects must be set atomically as one operation. Any scissor rects not defined by the call are disabled.

The scissor rectangles will only be used if ScissorEnable is set to true in the rasterizer state (see ).

Which scissor rectangle to use is determined by the SV_ViewportArrayIndex semantic output by a geometry shader (see shader semantic syntax). If a geometry shader does not make use of the SV_ViewportArrayIndex semantic then Direct3D will use the first scissor rectangle in the array.

Each scissor rectangle in the array corresponds to a viewport in an array of viewports (see ).

- ///
- /// ff476478 - /// void ID3D11DeviceContext::RSSetScissorRects([In] unsigned int NumRects,[In, Buffer, Optional] const void* pRects) - /// ID3D11DeviceContext::RSSetScissorRects - public void SetScissorRectangles(int left, int top, int right, int bottom) - { - RasterizerStage.SetScissorRectangle(left, top, right, bottom); - } - - /// - /// Binds a set of scissor rectangles to the rasterizer stage. - /// - /// The set of scissor rectangles to bind. - /// - ///

All scissor rects must be set atomically as one operation. Any scissor rects not defined by the call are disabled.

The scissor rectangles will only be used if ScissorEnable is set to true in the rasterizer state (see ).

Which scissor rectangle to use is determined by the SV_ViewportArrayIndex semantic output by a geometry shader (see shader semantic syntax). If a geometry shader does not make use of the SV_ViewportArrayIndex semantic then Direct3D will use the first scissor rectangle in the array.

Each scissor rectangle in the array corresponds to a viewport in an array of viewports (see ).

- ///
- /// ff476478 - /// void ID3D11DeviceContext::RSSetScissorRects([In] unsigned int NumRects,[In, Buffer, Optional] const void* pRects) - /// ID3D11DeviceContext::RSSetScissorRects - public void SetScissorRectangles(params Rectangle[] scissorRectangles) - { - RasterizerStage.SetScissorRectangles(scissorRectangles); - } - - /// - /// Gets the main viewport. - /// - /// The main viewport. - public ViewportF Viewport - { - get - { - RasterizerStage.GetViewports(viewports); - return viewports[0]; - } - - set - { - SetViewport(value); - } - } - - /// - /// Gets the viewport. - /// - /// The index. - /// Returns a viewport bound to a specified render target - public ViewportF GetViewport(int index) - { - RasterizerStage.GetViewports(viewports); - return viewports[index]; - } - - /// - /// Binds a single viewport to the rasterizer stage. - /// - /// The x coordinate of the viewport. - /// The y coordinate of the viewport. - /// The width. - /// The height. - /// The min Z. - /// The max Z. - /// - ///

All viewports must be set atomically as one operation. Any viewports not defined by the call are disabled.

Which viewport to use is determined by the SV_ViewportArrayIndex semantic output by a geometry shader; if a geometry shader does not specify the semantic, Direct3D will use the first viewport in the array.

- ///
- /// ff476480 - /// void ID3D11DeviceContext::RSSetViewports([In] unsigned int NumViewports,[In, Buffer, Optional] const void* pViewports) - /// ID3D11DeviceContext::RSSetViewports - public void SetViewport(float x, float y, float width, float height, float minZ = 0.0f, float maxZ = 1.0f) - { - viewports[0] = new ViewportF(x, y, width, height, minZ, maxZ); - RasterizerStage.SetViewport(x, y, width, height, minZ, maxZ); - } - - /// - /// Binds a single viewport to the rasterizer stage. - /// - /// The viewport. - /// - ///

All viewports must be set atomically as one operation. Any viewports not defined by the call are disabled.

Which viewport to use is determined by the SV_ViewportArrayIndex semantic output by a geometry shader; if a geometry shader does not specify the semantic, Direct3D will use the first viewport in the array.

- ///
- /// ff476480 - /// void ID3D11DeviceContext::RSSetViewports([In] unsigned int NumViewports,[In, Buffer, Optional] const void* pViewports) - /// ID3D11DeviceContext::RSSetViewports - public void SetViewport(ViewportF viewport) - { - viewports[0] = viewport; - RasterizerStage.SetViewport(viewport); - } - - /// - /// Binds a set of viewports to the rasterizer stage. - /// - /// The set of viewports to bind. - /// - ///

All viewports must be set atomically as one operation. Any viewports not defined by the call are disabled.

Which viewport to use is determined by the SV_ViewportArrayIndex semantic output by a geometry shader; if a geometry shader does not specify the semantic, Direct3D will use the first viewport in the array.

- ///
- /// ff476480 - /// void ID3D11DeviceContext::RSSetViewports([In] unsigned int NumViewports,[In, Buffer, Optional] const void* pViewports) - /// ID3D11DeviceContext::RSSetViewports - public void SetViewports(params ViewportF[] viewports) - { - for (int i = 0; i < viewports.Length; i++) - this.viewports[i] = viewports[i]; - - RasterizerStage.SetViewports(this.viewports, viewports.Length); - } - - /// - /// Unbinds all depth-stencil buffer and render targets from the output-merger stage. - /// - /// ff476464 - /// void ID3D11DeviceContext::OMSetRenderTargets([In] unsigned int NumViews,[In] const void** ppRenderTargetViews,[In, Optional] ID3D11DepthStencilView* pDepthStencilView) - /// ID3D11DeviceContext::OMSetRenderTargets - public void ResetTargets() - { - for (int i = 0; i < currentRenderTargetViews.Length; i++) - currentRenderTargetViews[i] = null; - actualRenderTargetViewCount = 0; - currentRenderTargetView = null; - currentDepthStencilView = null; - OutputMergerStage.ResetTargets(); - } - - /// - /// Gets the render targets currently bound to the through this instance. - /// - /// The depth stencil view, may ne null. - /// An array of . - public RenderTargetView[] GetRenderTargets(out DepthStencilView depthStencilViewRef) - { - var renderTargets = new RenderTargetView[actualRenderTargetViewCount]; - for (int i = 0; i < actualRenderTargetViewCount; i++) - renderTargets[i] = currentRenderTargetViews[i]; - depthStencilViewRef = currentDepthStencilView; - return renderTargets; - } - - /// - ///

Bind one or more render targets atomically and the depth-stencil buffer to the output-merger stage.

- ///
- /// A set of render target views to bind. - /// - ///

The maximum number of active render targets a device can have active at any given time is set by a #define in D3D11.h called D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT. It is invalid to try to set the same subresource to multiple render target slots. Any render targets not defined by this call are set to null.

If any subresources are also currently bound for reading in a different stage or writing (perhaps in a different part of the pipeline), those bind points will be set to null, in order to prevent the same subresource from being read and written simultaneously in a single rendering operation.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

If the render-target views were created from an array resource type, then all of the render-target views must have the same array size. This restriction also applies to the depth-stencil view, its array size must match that of the render-target views being bound.

The pixel shader must be able to simultaneously render to at least eight separate render targets. All of these render targets must access the same type of resource: Buffer, Texture1D, Texture1DArray, Texture2D, Texture2DArray, Texture3D, or TextureCube. All render targets must have the same size in all dimensions (width and height, and depth for 3D or array size for *Array types). If render targets use multisample anti-aliasing, all bound render targets and depth buffer must be the same form of multisample resource (that is, the sample counts must be the same). Each render target can have a different data format. These render target formats are not required to have identical bit-per-element counts.

Any combination of the eight slots for render targets can have a render target set or not set.

The same resource view cannot be bound to multiple render target slots simultaneously. However, you can set multiple non-overlapping resource views of a single resource as simultaneous multiple render targets.

- ///
- /// ff476464 - /// void ID3D11DeviceContext::OMSetRenderTargets([In] unsigned int NumViews,[In] const void** ppRenderTargetViews,[In, Optional] ID3D11DepthStencilView* pDepthStencilView) - /// ID3D11DeviceContext::OMSetRenderTargets - public void SetRenderTargets(params RenderTargetView[] renderTargetViews) - { - if (renderTargetViews == null) - { - throw new ArgumentNullException("renderTargetViews"); - } - - CommonSetRenderTargets(renderTargetViews); - currentDepthStencilView = null; - OutputMergerStage.SetTargets(renderTargetViews); - } - - /// - /// Binds a single render target to the output-merger stage. - /// - /// A view of the render target to bind. - /// - ///

The maximum number of active render targets a device can have active at any given time is set by a #define in D3D11.h called D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT. It is invalid to try to set the same subresource to multiple render target slots. Any render targets not defined by this call are set to null.

If any subresources are also currently bound for reading in a different stage or writing (perhaps in a different part of the pipeline), those bind points will be set to null, in order to prevent the same subresource from being read and written simultaneously in a single rendering operation.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

If the render-target views were created from an array resource type, then all of the render-target views must have the same array size. This restriction also applies to the depth-stencil view, its array size must match that of the render-target views being bound.

The pixel shader must be able to simultaneously render to at least eight separate render targets. All of these render targets must access the same type of resource: Buffer, Texture1D, Texture1DArray, Texture2D, Texture2DArray, Texture3D, or TextureCube. All render targets must have the same size in all dimensions (width and height, and depth for 3D or array size for *Array types). If render targets use multisample anti-aliasing, all bound render targets and depth buffer must be the same form of multisample resource (that is, the sample counts must be the same). Each render target can have a different data format. These render target formats are not required to have identical bit-per-element counts.

Any combination of the eight slots for render targets can have a render target set or not set.

The same resource view cannot be bound to multiple render target slots simultaneously. However, you can set multiple non-overlapping resource views of a single resource as simultaneous multiple render targets.

- ///
- /// ff476464 - /// void ID3D11DeviceContext::OMSetRenderTargets([In] unsigned int NumViews,[In] const void** ppRenderTargetViews,[In, Optional] ID3D11DepthStencilView* pDepthStencilView) - /// ID3D11DeviceContext::OMSetRenderTargets - public void SetRenderTargets(RenderTargetView renderTargetView) - { - CommonSetRenderTargets(renderTargetView); - currentDepthStencilView = null; - OutputMergerStage.SetTargets(renderTargetView); - } - - /// - /// Binds a depth-stencil buffer and a set of render targets to the output-merger stage. - /// - /// A view of the depth-stencil buffer to bind. - /// A set of render target views to bind. - /// - ///

The maximum number of active render targets a device can have active at any given time is set by a #define in D3D11.h called D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT. It is invalid to try to set the same subresource to multiple render target slots. Any render targets not defined by this call are set to null.

If any subresources are also currently bound for reading in a different stage or writing (perhaps in a different part of the pipeline), those bind points will be set to null, in order to prevent the same subresource from being read and written simultaneously in a single rendering operation.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

If the render-target views were created from an array resource type, then all of the render-target views must have the same array size. This restriction also applies to the depth-stencil view, its array size must match that of the render-target views being bound.

The pixel shader must be able to simultaneously render to at least eight separate render targets. All of these render targets must access the same type of resource: Buffer, Texture1D, Texture1DArray, Texture2D, Texture2DArray, Texture3D, or TextureCube. All render targets must have the same size in all dimensions (width and height, and depth for 3D or array size for *Array types). If render targets use multisample anti-aliasing, all bound render targets and depth buffer must be the same form of multisample resource (that is, the sample counts must be the same). Each render target can have a different data format. These render target formats are not required to have identical bit-per-element counts.

Any combination of the eight slots for render targets can have a render target set or not set.

The same resource view cannot be bound to multiple render target slots simultaneously. However, you can set multiple non-overlapping resource views of a single resource as simultaneous multiple render targets.

- ///
- /// ff476464 - /// void ID3D11DeviceContext::OMSetRenderTargets([In] unsigned int NumViews,[In] const void** ppRenderTargetViews,[In, Optional] ID3D11DepthStencilView* pDepthStencilView) - /// ID3D11DeviceContext::OMSetRenderTargets - public void SetRenderTargets(DepthStencilView depthStencilView, params RenderTargetView[] renderTargetViews) - { - if (renderTargetViews == null) - { - throw new ArgumentNullException("renderTargetViews"); - } - - CommonSetRenderTargets(renderTargetViews); - currentDepthStencilView = depthStencilView; - OutputMergerStage.SetTargets(depthStencilView, renderTargetViews); - } - - /// - /// Binds a depth-stencil buffer and a single render target to the output-merger stage. - /// - /// A view of the depth-stencil buffer to bind. - /// A view of the render target to bind. - /// - ///

The maximum number of active render targets a device can have active at any given time is set by a #define in D3D11.h called D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT. It is invalid to try to set the same subresource to multiple render target slots. Any render targets not defined by this call are set to null.

If any subresources are also currently bound for reading in a different stage or writing (perhaps in a different part of the pipeline), those bind points will be set to null, in order to prevent the same subresource from being read and written simultaneously in a single rendering operation.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

If the render-target views were created from an array resource type, then all of the render-target views must have the same array size. This restriction also applies to the depth-stencil view, its array size must match that of the render-target views being bound.

The pixel shader must be able to simultaneously render to at least eight separate render targets. All of these render targets must access the same type of resource: Buffer, Texture1D, Texture1DArray, Texture2D, Texture2DArray, Texture3D, or TextureCube. All render targets must have the same size in all dimensions (width and height, and depth for 3D or array size for *Array types). If render targets use multisample anti-aliasing, all bound render targets and depth buffer must be the same form of multisample resource (that is, the sample counts must be the same). Each render target can have a different data format. These render target formats are not required to have identical bit-per-element counts.

Any combination of the eight slots for render targets can have a render target set or not set.

The same resource view cannot be bound to multiple render target slots simultaneously. However, you can set multiple non-overlapping resource views of a single resource as simultaneous multiple render targets.

- ///
- /// ff476464 - /// void ID3D11DeviceContext::OMSetRenderTargets([In] unsigned int NumViews,[In] const void** ppRenderTargetViews,[In, Optional] ID3D11DepthStencilView* pDepthStencilView) - /// ID3D11DeviceContext::OMSetRenderTargets - public void SetRenderTargets(DepthStencilView depthStencilView, RenderTargetView renderTargetView) - { - CommonSetRenderTargets(renderTargetView); - currentDepthStencilView = depthStencilView; - OutputMergerStage.SetTargets(depthStencilView, renderTargetView); - } - - /// - /// Resets the stream output targets bound to the StreamOutput stage. - /// - /// ff476484 - /// void ID3D11DeviceContext::SOSetTargets([In] unsigned int NumBuffers,[In, Buffer, Optional] const ID3D11Buffer** ppSOTargets,[In, Buffer, Optional] const unsigned int* pOffsets) - /// ID3D11DeviceContext::SOSetTargets - public void ResetStreamOutputTargets() - { - Context.StreamOutput.SetTargets(0, null, null); - } - - /// - /// Sets the stream output targets bound to the StreamOutput stage. - /// - /// The buffer to bind on the first stream output slot. - /// The offsets in bytes of the buffer. An offset of -1 will cause the stream output buffer to be appended, continuing after the last location written to the buffer in a previous stream output pass. - /// ff476484 - /// void ID3D11DeviceContext::SOSetTargets([In] unsigned int NumBuffers,[In, Buffer, Optional] const ID3D11Buffer** ppSOTargets,[In, Buffer, Optional] const unsigned int* pOffsets) - /// ID3D11DeviceContext::SOSetTargets - public unsafe void SetStreamOutputTarget(Buffer buffer, int offsets = -1) - { - Context.StreamOutput.SetTarget(buffer, offsets); - } - - /// - /// Sets the stream output targets bound to the StreamOutput stage. - /// - /// The buffers. - /// ff476484 - /// void ID3D11DeviceContext::SOSetTargets([In] unsigned int NumBuffers,[In, Buffer, Optional] const ID3D11Buffer** ppSOTargets,[In, Buffer, Optional] const unsigned int* pOffsets) - /// ID3D11DeviceContext::SOSetTargets - public void SetStreamOutputTargets(params StreamOutputBufferBinding[] buffers) - { - Context.StreamOutput.SetTargets(buffers); - } - - /// - ///

Bind an index buffer to the input-assembler stage.

- ///
- ///

A reference to an object, that contains indices. The index buffer must have been created with the flag.

- /// Set to true if indices are 32-bit values (integer size) or false if they are 16-bit values (short size) - /// Offset (in bytes) from the start of the index buffer to the first index to use. Default to 0 - /// - ///

For information about creating index buffers, see How to: Create an Index Buffer.

Calling this method using a buffer that is currently bound for writing (i.e. bound to the stream output pipeline stage) will effectively bind null instead because a buffer cannot be bound as both an input and an output at the same time.

The debug layer will generate a warning whenever a resource is prevented from being bound simultaneously as an input and an output, but this will not prevent invalid data from being used by the runtime.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

- ///
- /// ff476453 - /// void ID3D11DeviceContext::IASetIndexBuffer([In, Optional] ID3D11Buffer* pIndexBuffer,[In] DXGI_FORMAT Format,[In] unsigned int Offset) - /// ID3D11DeviceContext::IASetIndexBuffer - public void SetIndexBuffer(Buffer indexBuffer, bool is32Bit, int offset = 0) - { - InputAssemblerStage.SetIndexBuffer(indexBuffer, is32Bit ? DXGI.Format.R32_UInt : DXGI.Format.R16_UInt, offset); - } - - /// - /// Sets the vertex input layout. - /// - /// The input layout. - /// ff476454 - /// void ID3D11DeviceContext::IASetInputLayout([In, Optional] ID3D11InputLayout* pInputLayout) - /// ID3D11DeviceContext::IASetInputLayout - public void SetVertexInputLayout(VertexInputLayout inputLayout) - { - currentVertexInputLayout = inputLayout; - } - - /// - /// Bind a vertex buffer on the slot #0 of the input-assembler stage. - /// - /// The vertex buffer to bind to this slot. This vertex buffer must have been created with the flag. - /// The index is the number of vertex element between the first element of a vertex buffer and the first element that will be used. - /// - ///

For information about creating vertex buffers, see Create a Vertex Buffer.

Calling this method using a buffer that is currently bound for writing (i.e. bound to the stream output pipeline stage) will effectively bind null instead because a buffer cannot be bound as both an input and an output at the same time.

The debug layer will generate a warning whenever a resource is prevented from being bound simultaneously as an input and an output, but this will not prevent invalid data from being used by the runtime.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

- ///
- /// ff476456 - /// void ID3D11DeviceContext::IASetVertexBuffers([In] unsigned int StartSlot,[In] unsigned int NumBuffers,[In, Buffer] const void* ppVertexBuffers,[In, Buffer] const void* pStrides,[In, Buffer] const void* pOffsets) - /// ID3D11DeviceContext::IASetVertexBuffers - public void SetVertexBuffer(Buffer vertexBuffer, int vertexIndex = 0) where T : struct - { - SetVertexBuffer(0, vertexBuffer, vertexIndex); - } - - /// - /// Bind a vertex buffer to the input-assembler stage. - /// - /// The first input slot for binding. - /// The vertex buffer to bind to this slot. This vertex buffer must have been created with the flag. - /// The index is the number of vertex element between the first element of a vertex buffer and the first element that will be used. - /// - ///

For information about creating vertex buffers, see Create a Vertex Buffer.

Calling this method using a buffer that is currently bound for writing (i.e. bound to the stream output pipeline stage) will effectively bind null instead because a buffer cannot be bound as both an input and an output at the same time.

The debug layer will generate a warning whenever a resource is prevented from being bound simultaneously as an input and an output, but this will not prevent invalid data from being used by the runtime.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

- ///
- /// ff476456 - /// void ID3D11DeviceContext::IASetVertexBuffers([In] unsigned int StartSlot,[In] unsigned int NumBuffers,[In, Buffer] const void* ppVertexBuffers,[In, Buffer] const void* pStrides,[In, Buffer] const void* pOffsets) - /// ID3D11DeviceContext::IASetVertexBuffers - public unsafe void SetVertexBuffer(int slot, Buffer vertexBuffer, int vertexIndex = 0) where T : struct - { - IntPtr vertexBufferPtr = IntPtr.Zero; - int stride = Utilities.SizeOf(); - int offset = vertexIndex * stride; - if (vertexBuffer != null) - { - vertexBufferPtr = ((Direct3D11.Buffer)vertexBuffer).NativePointer; - - // Update the index of the last slot buffer bounded, used by ResetVertexBuffers - if ((slot + 1) > maxSlotCountForVertexBuffer) - maxSlotCountForVertexBuffer = slot + 1; - } - InputAssemblerStage.SetVertexBuffers(slot, 1, new IntPtr(&vertexBufferPtr), new IntPtr(&stride), new IntPtr(&offset)); - } - - /// - ///

Bind a vertex buffer to the input-assembler stage.

- ///
- /// The first input slot for binding. - /// The vertex buffer to bind to this slot. This vertex buffer must have been created with the flag. - /// The vertexStride is the size (in bytes) of the elements that are to be used from that vertex buffer. - /// The offset is the number of bytes between the first element of a vertex buffer and the first element that will be used. - /// - ///

For information about creating vertex buffers, see Create a Vertex Buffer.

Calling this method using a buffer that is currently bound for writing (i.e. bound to the stream output pipeline stage) will effectively bind null instead because a buffer cannot be bound as both an input and an output at the same time.

The debug layer will generate a warning whenever a resource is prevented from being bound simultaneously as an input and an output, but this will not prevent invalid data from being used by the runtime.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

- ///
- /// ff476456 - /// void ID3D11DeviceContext::IASetVertexBuffers([In] unsigned int StartSlot,[In] unsigned int NumBuffers,[In, Buffer] const void* ppVertexBuffers,[In, Buffer] const void* pStrides,[In, Buffer] const void* pOffsets) - /// ID3D11DeviceContext::IASetVertexBuffers - public unsafe void SetVertexBuffer(int slot, SharpDX.Direct3D11.Buffer vertexBuffer, int vertexStride, int offsetInBytes = 0) - { - IntPtr vertexBufferPtr = IntPtr.Zero; - if (vertexBuffer != null) - { - vertexBufferPtr = vertexBuffer.NativePointer; - - // Update the index of the last slot buffer bounded, used by ResetVertexBuffers - if ((slot + 1) > maxSlotCountForVertexBuffer) - maxSlotCountForVertexBuffer = slot + 1; - } - InputAssemblerStage.SetVertexBuffers(slot, 1, new IntPtr(&vertexBufferPtr), new IntPtr(&vertexStride), new IntPtr(&offsetInBytes)); - } - - /// - /// Resets all vertex buffers bounded to a slot range. By default, It clears all the bounded buffers. See remarks. - /// - /// - /// This is sometimes required to unding explicitly vertex buffers bounding to the input shader assembly, when a - /// vertex buffer is used as the output of the pipeline. - /// - /// ff476456 - /// void ID3D11DeviceContext::IASetVertexBuffers([In] unsigned int StartSlot,[In] unsigned int NumBuffers,[In, Buffer] const void* ppVertexBuffers,[In, Buffer] const void* pStrides,[In, Buffer] const void* pOffsets) - /// ID3D11DeviceContext::IASetVertexBuffers - public void ResetVertexBuffers() - { - if (maxSlotCountForVertexBuffer == 0) - return; - - InputAssemblerStage.SetVertexBuffers(0, maxSlotCountForVertexBuffer, ResetSlotsPointers, ResetSlotsPointers, ResetSlotsPointers); - - maxSlotCountForVertexBuffer = 0; - } - - /// - /// Presents the Backbuffer to the screen. - /// - /// - /// This method is only working if a is set on this device using property. - /// - /// bb174576 - /// HRESULT IDXGISwapChain::Present([In] unsigned int SyncInterval,[In] DXGI_PRESENT_FLAGS Flags) - /// IDXGISwapChain::Present - public void Present() - { - if (IsDeferred) - throw new InvalidOperationException("Cannot use Present on a deferred context"); - - if (Presenter != null) - { - try - { - Presenter.Present(); - } - catch (SharpDXException ex) - { - if (ex.ResultCode == DXGI.ResultCode.DeviceReset || ex.ResultCode == DXGI.ResultCode.DeviceRemoved) - { - // TODO: Implement device reset / removed - } - throw; - } - - } - } - - /// - /// Remove all shaders bounded to each stage. - /// - public void ResetShaderStages() - { - foreach (var commonShaderStage in ShaderStages) - { - commonShaderStage.SetShader(null, null, 0); - } - } - - public static implicit operator Device(GraphicsDevice from) - { - return from == null ? null : from.Device; - } - - public static implicit operator DeviceContext(GraphicsDevice from) - { - return from == null ? null : from.Context; - } - - private void SetupInputLayout() - { - if (CurrentPass == null) - throw new InvalidOperationException("Cannot perform a Draw/Dispatch operation without an EffectPass applied."); - - var inputLayout = CurrentPass.GetInputLayout(currentVertexInputLayout); - InputAssemblerStage.SetInputLayout(inputLayout); - } - - /// - /// A delegate called to create shareable data. See remarks. - /// - /// Type of the data to create. - /// A new instance of the data to share. - /// - /// Because this method is being called from a lock region, this method should not be time consuming. - /// - public delegate T CreateSharedData() where T : IDisposable; - - /// - /// Gets a shared data for this device context with a delegate to create the shared data if it is not present. - /// - /// Type of the shared data to get/create. - /// Type of the data to share. - /// The key of the shared data. - /// The shared data creator. - /// An instance of the shared data. The shared data will be disposed by this instance. - public T GetOrCreateSharedData(SharedDataType type, object key, CreateSharedData sharedDataCreator) where T : IDisposable - { - var dictionary = (type == SharedDataType.PerDevice) ? sharedDataPerDevice : sharedDataPerDeviceContext; - - lock (dictionary) - { - object localValue; - if (!dictionary.TryGetValue(key, out localValue)) - { - localValue = ToDispose(sharedDataCreator()); - dictionary.Add(key, localValue); - } - return (T)localValue; - } - } - - protected override void Dispose(bool disposeManagedResources) - { - if (disposeManagedResources) - { - if (Presenter != null) - { - - // Invalid for WinRT - throwing a "Value does not fall within the expected range" Exception -#if !WIN8METRO - // Make sure that the Presenter is reverted to window before shutting down - // otherwise the Direct3D11.Device will generate an exception on Dispose() - Presenter.IsFullScreen = false; -#endif - Presenter.Dispose(); - Presenter = null; - } - - // dispose EffectPools in reverse order as they will remove themselves from the list - for(var i = EffectPools.Count - 1; i >= 0; i--) - { - EffectPools[i].Dispose(); - } - - EffectPools = null; - } - - base.Dispose(disposeManagedResources); - } - - - /// - /// Gets or create an input signature manager for a particular signature. - /// - /// The signature bytecode. - /// The signature hashcode. - /// - internal InputSignatureManager GetOrCreateInputSignatureManager(byte[] signatureBytecode, int signatureHashcode) - { - var key = new InputSignatureKey(signatureBytecode, signatureHashcode); - - InputSignatureManager signatureManager; - - // Lock all input signatures, as they are shared between all shaders/graphics device instances. - lock (inputSignatureCache) - { - if (!inputSignatureCache.TryGetValue(key, out signatureManager)) - { - signatureManager = ToDispose(new InputSignatureManager(this, signatureBytecode)); - inputSignatureCache.Add(key, signatureManager); - } - } - - return signatureManager; - } - - private void CommonSetRenderTargets(RenderTargetView rtv) - { - currentRenderTargetViews[0] = rtv; - for (int i = 1; i < actualRenderTargetViewCount; i++) - currentRenderTargetViews[i] = null; - actualRenderTargetViewCount = 1; - currentRenderTargetView = rtv; - - // Setup the viewport from the rendertarget view - TextureView textureView; - if (AutoViewportFromRenderTargets && rtv != null && (textureView = rtv.Tag as TextureView) != null) - { - SetViewport(new ViewportF(0, 0, textureView.Width, textureView.Height)); - } - } - - private void CommonSetRenderTargets(RenderTargetView[] rtvs) - { - var rtv0 = rtvs.Length > 0 ? rtvs[0] : null; - for (int i = 0; i < rtvs.Length; i++) - currentRenderTargetViews[i] = rtvs[i]; - for (int i = rtvs.Length; i < actualRenderTargetViewCount; i++) - currentRenderTargetViews[i] = null; - actualRenderTargetViewCount = rtvs.Length; - currentRenderTargetView = rtv0; - - // Setup the viewport from the rendertarget view - TextureView textureView; - if (AutoViewportFromRenderTargets && rtv0 != null && (textureView = rtv0.Tag as TextureView) != null) - { - SetViewport(new ViewportF(0, 0, textureView.Width, textureView.Height)); - } - } - } -} +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using SharpDX.Direct3D; +using SharpDX.Direct3D11; +using System; +using System.Collections.Generic; +using SharpDX.Toolkit.Collections; +using Device = SharpDX.Direct3D11.Device; + +namespace SharpDX.Toolkit.Graphics +{ + /// + /// This class is a front end to and . + /// + public class GraphicsDevice : Component + { + private readonly Dictionary sharedDataPerDevice; + private readonly Dictionary sharedDataPerDeviceContext = new Dictionary(); + internal Device Device; + internal DeviceContext Context; + internal CommonShaderStage[] ShaderStages; + private readonly ViewportF[] viewports = new ViewportF[16]; + internal IntPtr ResetSlotsPointers { get; private set; } + private int maxSlotCountForVertexBuffer; + + private const int SimultaneousRenderTargetCount = OutputMergerStage.SimultaneousRenderTargetCount; + private readonly RenderTargetView[] currentRenderTargetViews = new RenderTargetView[SimultaneousRenderTargetCount]; + private RenderTargetView currentRenderTargetView; + private int actualRenderTargetViewCount; + private DepthStencilView currentDepthStencilView; + + private readonly PrimitiveQuad primitiveQuad; + + private VertexInputLayout currentVertexInputLayout; + internal EffectPass CurrentPass; + + private readonly Dictionary inputSignatureCache; + + /// + /// Gets the features supported by this . + /// + public readonly GraphicsDeviceFeatures Features; + + /// + /// Default effect pool shared between all deferred GraphicsDevice instances. + /// + public readonly EffectPool DefaultEffectPool; + + /// + /// Gets the for immediate rendering. + /// + public readonly GraphicsDevice MainDevice; + + /// + /// Gets whether this is running in debug. + /// + public readonly bool IsDebugMode; + + /// + /// Gets whether this is a deferred context. + /// + public readonly bool IsDeferred; + + /// + /// Gets the registered for this graphics device. + /// + public readonly BlendStateCollection BlendStates; + + /// + /// Gets the registered for this graphics device. + /// + public readonly DepthStencilStateCollection DepthStencilStates; + + /// + /// Gets the registered for this graphics device. + /// + public readonly SamplerStateCollection SamplerStates; + + /// + /// Gets the registered for this graphics device. + /// + public readonly RasterizerStateCollection RasterizerStates; + + internal InputAssemblerStage InputAssemblerStage; + internal VertexShaderStage VertexShaderStage; + internal DomainShaderStage DomainShaderStage; + internal HullShaderStage HullShaderStage; + internal GeometryShaderStage GeometryShaderStage; + internal RasterizerStage RasterizerStage; + internal PixelShaderStage PixelShaderStage; + internal OutputMergerStage OutputMergerStage; + internal ComputeShaderStage ComputeShaderStage; + + internal readonly bool needWorkAroundForUpdateSubResource; + + protected GraphicsDevice(DriverType type, DeviceCreationFlags flags = DeviceCreationFlags.None, params FeatureLevel[] featureLevels) + : this((featureLevels != null && featureLevels.Length > 0) ? new Device(type, flags, featureLevels) : new Device(type, flags)) + { + } + + protected GraphicsDevice(GraphicsAdapter adapter, DeviceCreationFlags flags = DeviceCreationFlags.None, params FeatureLevel[] featureLevels) + : this((featureLevels != null && featureLevels.Length > 0) ? new Device(adapter, flags, featureLevels) : new Device(adapter, flags), adapter) + { + } + + protected GraphicsDevice(SharpDX.Direct3D11.Device existingDevice, GraphicsAdapter adapter = null) + { + Device = ToDispose(existingDevice); + Adapter = adapter; + + // If the adapter is null, then try to locate back the adapter + if (adapter == null) + { + try + { + using (var dxgiDevice = Device.QueryInterface()) + { + using (var dxgiAdapter = dxgiDevice.Adapter) + { + var deviceId = dxgiAdapter.Description.DeviceId; + + foreach (var graphicsAdapter in GraphicsAdapter.Adapters) + { + if (deviceId == graphicsAdapter.Description.DeviceId) + { + Adapter = graphicsAdapter; + break; + } + } + } + } + } + catch (Exception ex) + { + } + } + + EffectPools = new ObservableCollection(); + + IsDebugMode = (Device.CreationFlags & DeviceCreationFlags.Debug) != 0; + MainDevice = this; + Context = Device.ImmediateContext; + IsDeferred = false; + Features = new GraphicsDeviceFeatures(Device); + AutoViewportFromRenderTargets = true; // By default + + // Global cache for all input signatures inside a GraphicsDevice. + inputSignatureCache = new Dictionary(); + sharedDataPerDevice = new Dictionary(); + + // Create default Effect pool + DefaultEffectPool = EffectPool.New(this, "Default"); + + // Create all default states + BlendStates = ToDispose(new BlendStateCollection(this)); + DepthStencilStates = ToDispose(new DepthStencilStateCollection(this)); + SamplerStates = ToDispose(new SamplerStateCollection(this)); + RasterizerStates = ToDispose(new RasterizerStateCollection(this)); + + Initialize(); + + // Create Internal Effect + primitiveQuad = ToDispose(new PrimitiveQuad(this)); + } + + protected GraphicsDevice(GraphicsDevice mainDevice, DeviceContext deferredContext) + { + Device = mainDevice.Device; + Adapter = mainDevice.Adapter; + IsDebugMode = (Device.CreationFlags & DeviceCreationFlags.Debug) != 0; + MainDevice = mainDevice; + Context = deferredContext; + IsDeferred = true; + Features = mainDevice.Features; + + // Create default Effect pool + EffectPools = mainDevice.EffectPools; + DefaultEffectPool = mainDevice.DefaultEffectPool; + + // Copy the Global cache for all input signatures inside a GraphicsDevice. + inputSignatureCache = mainDevice.inputSignatureCache; + sharedDataPerDevice = mainDevice.sharedDataPerDevice; + + // Copy the reset vertex buffer + ResetSlotsPointers = mainDevice.ResetSlotsPointers; + + // Create all default states + BlendStates = mainDevice.BlendStates; + DepthStencilStates = mainDevice.DepthStencilStates; + SamplerStates = mainDevice.SamplerStates; + RasterizerStates = mainDevice.RasterizerStates; + + // Setup the workaround flag + needWorkAroundForUpdateSubResource = IsDeferred && !Features.HasDriverCommandLists; + Initialize(); + + // Create Internal Effect + primitiveQuad = ToDispose(new PrimitiveQuad(this)); + } + + /// + /// Initializes this instance. + /// + private void Initialize() + { + // Default null VertexBuffers used to reset + if (ResetSlotsPointers == IntPtr.Zero) + { + // CommonShaderStage.InputResourceSlotCount is the maximum of resources bindable in the whole pipeline + ResetSlotsPointers = ToDispose(Utilities.AllocateClearedMemory(Utilities.SizeOf() * CommonShaderStage.InputResourceSlotCount)); + } + + InputAssemblerStage = Context.InputAssembler; + VertexShaderStage = Context.VertexShader; + DomainShaderStage = Context.DomainShader; + HullShaderStage = Context.HullShader; + GeometryShaderStage = Context.GeometryShader; + RasterizerStage = Context.Rasterizer; + PixelShaderStage = Context.PixelShader; + OutputMergerStage = Context.OutputMerger; + ComputeShaderStage = Context.ComputeShader; + + // Precompute shader stages + ShaderStages = new CommonShaderStage[] + { + Context.VertexShader, + Context.HullShader, + Context.DomainShader, + Context.GeometryShader, + Context.PixelShader, + Context.ComputeShader + }; + + Performance = new GraphicsPerformance(this); + } + + /// + /// Check if a feature level is supported by a primary adapter. + /// + /// The feature level. + /// true if the primary adapter is supporting this feature level; otherwise, false. + public static bool IsProfileSupported(FeatureLevel featureLevel) + { + return SharpDX.Direct3D11.Device.IsSupportedFeatureLevel(featureLevel); + } + + /// + /// Gets the adapter associated with this device. + /// + public readonly GraphicsAdapter Adapter; + + /// + /// Gets the effect pools. + /// + /// The effect pools. + public ObservableCollection EffectPools { get; private set; } + + /// + /// Gets the back buffer sets by the current setup on this device. + /// + /// The back buffer. The returned value may be null if no are setup on this device. + public RenderTarget2D BackBuffer + { + get { return Presenter != null ? Presenter.BackBuffer : null; } + } + + /// + /// Gets the depth stencil buffer sets by the current setup on this device. + /// + /// The depth stencil buffer. The returned value may be null if no are setup on this device or no depth buffer was allocated. + public DepthStencilBuffer DepthStencilBuffer + { + get { return Presenter != null ? Presenter.DepthStencilBuffer : null; } + } + + /// + /// Gets or sets the current presenter use by the method. + /// + /// The current presenter. + public GraphicsPresenter Presenter { get; set; } + + /// + /// Gets or sets a value indicating whether the viewport is automatically calculated and set when a render target is set. Default is true. + /// + /// true if the viewport is automatically calculated and set when a render target is set; otherwise, false. + public bool AutoViewportFromRenderTargets { get; set; } + + /// + /// Gets the status of this device. + /// + /// ff476526 + /// GetDeviceRemovedReason + /// GetDeviceRemovedReason + /// HRESULT ID3D11Device::GetDeviceRemovedReason() + public GraphicsDeviceStatus GraphicsDeviceStatus + { + get + { + var result = ((Device)MainDevice).DeviceRemovedReason; + if (result == DXGI.ResultCode.DeviceRemoved) + { + return GraphicsDeviceStatus.Removed; + } + + if (result == DXGI.ResultCode.DeviceReset) + { + return GraphicsDeviceStatus.Reset; + } + + if (result == DXGI.ResultCode.DeviceHung) + { + return GraphicsDeviceStatus.Hung; + } + + if (result == DXGI.ResultCode.DriverInternalError) + { + return GraphicsDeviceStatus.InternalError; + } + + if (result == DXGI.ResultCode.InvalidCall) + { + return GraphicsDeviceStatus.InvalidCall; + } + + if (result.Code < 0) + { + return GraphicsDeviceStatus.Reset; + } + + return GraphicsDeviceStatus.Normal; + } + } + + /// + /// Gets the access to performance profiler. + /// + /// The access to performance profiler. + public GraphicsPerformance Performance { get; private set; } + + /// + /// Gets the default quad primitive to issue draw commands. + /// + /// The default quad primitive to issue draw commands. + public PrimitiveQuad Quad + { + get + { + return primitiveQuad; + } + } + + /// + /// Clears the default render target and depth stencil buffer attached to the current . + /// + /// Set this color value in all buffers. + /// Cannot clear without a Presenter set on this instance + public void Clear(Color4 color) + { + var options = currentRenderTargetView != null ? ClearOptions.Target : (ClearOptions)0; + + if (currentDepthStencilView != null) + { + var depthStencilBuffer = currentDepthStencilView.Tag as DepthStencilBuffer; + if (depthStencilBuffer == null) + { + throw new InvalidOperationException("Clear on a custom DepthStencilView is not supported by this method. Use Clear(DepthStencilView) directly"); + } + + options |= depthStencilBuffer.HasStencil ? ClearOptions.DepthBuffer | ClearOptions.Stencil : ClearOptions.DepthBuffer; + + } + + Clear(options, color, 1f, 0); + } + + /// + /// Clears the default render target and depth stencil buffer attached to the current . + /// + /// Options for clearing a buffer. + /// Set this four-component color value in the buffer. + /// Set this depth value in the buffer. + /// Set this stencil value in the buffer. + public void Clear(ClearOptions options, Color4 color, float depth, int stencil) + { + if ((options & ClearOptions.Target) != 0) + { + if (currentRenderTargetView == null) + { + throw new InvalidOperationException("No default render target view setup. Call SetRenderTargets before calling this method."); + } + Clear(currentRenderTargetView, color); + } + + if ((options & (ClearOptions.Stencil | ClearOptions.DepthBuffer)) != 0) + { + if (currentDepthStencilView == null) + { + throw new InvalidOperationException("No default depth stencil view setup. Call SetRenderTargets before calling this method."); + } + + var flags = (options & ClearOptions.DepthBuffer) != 0 ? DepthStencilClearFlags.Depth : 0; + if ((options & ClearOptions.Stencil) != 0) + { + flags |= DepthStencilClearFlags.Stencil; + } + + Clear(currentDepthStencilView, flags, depth, (byte)stencil); + } + } + + /// + /// Clears the default render target and depth stencil buffer attached to the current . + /// + /// Options for clearing a buffer. + /// Set this four-component color value in the buffer. + /// Set this depth value in the buffer. + /// Set this stencil value in the buffer. + public void Clear(ClearOptions options, Vector4 color, float depth, int stencil) + { + Clear(options, (Color4)color, depth, stencil); + } + + /// + /// Clears a render target view by setting all the elements in a render target to one value. + /// + /// The render target view. + /// A 4-component array that represents the color to fill the render target with. + ///

Applications that wish to clear a render target to a specific integer value bit pattern should render a screen-aligned quad instead of using this method. The reason for this is because this method accepts as input a floating point value, which may not have the same bit pattern as the original integer.

Differences between Direct3D 9 and Direct3D 11/10:

Unlike Direct3D 9, the full extent of the resource view is always cleared. Viewport and scissor settings are not applied.

?

+ /// ff476388 + /// void ID3D11DeviceContext::ClearRenderTargetView([In] ID3D11RenderTargetView* pRenderTargetView,[In] const SHARPDX_COLOR4* ColorRGBA) + /// ID3D11DeviceContext::ClearRenderTargetView + public void Clear(SharpDX.Direct3D11.RenderTargetView renderTargetView, Color4 colorRGBA) + { + Context.ClearRenderTargetView(renderTargetView, colorRGBA); + } + + /// + /// Clears the depth-stencil resource. + /// + ///

Pointer to the depth stencil to be cleared.

+ ///

Identify the type of data to clear (see ).

+ ///

Clear the depth buffer with this value. This value will be clamped between 0 and 1.

+ ///

Clear the stencil buffer with this value.

+ /// + ///

Differences between Direct3D 9 and Direct3D 11/10:

Unlike Direct3D 9, the full extent of the resource view is always cleared. Viewport and scissor settings are not applied.

?

+ ///
+ /// ff476387 + /// void ID3D11DeviceContext::ClearDepthStencilView([In] ID3D11DepthStencilView* pDepthStencilView,[In] D3D11_CLEAR_FLAG ClearFlags,[In] float Depth,[In] unsigned char Stencil) + /// ID3D11DeviceContext::ClearDepthStencilView + public void Clear(SharpDX.Direct3D11.DepthStencilView depthStencilView, SharpDX.Direct3D11.DepthStencilClearFlags clearFlags, float depth, byte stencil) + { + Context.ClearDepthStencilView(depthStencilView, clearFlags, depth, stencil); + } + + /// + /// Clears an unordered access resource with bit-precise values. + /// + /// The buffer to clear. + /// The value used to clear. + /// + ///

This API copies the lower ni bits from each array element i to the corresponding channel, where ni is the number of bits in the ith channel of the resource format (for example, R8G8B8_FLOAT has 8 bits for the first 3 channels). This works on any UAV with no format conversion. For a raw or structured buffer view, only the first array element value is used.

+ ///
+ /// ff476391 + /// void ID3D11DeviceContext::ClearUnorderedAccessViewUint([In] ID3D11UnorderedAccessView* pUnorderedAccessView,[In] const unsigned int* Values) + /// ID3D11DeviceContext::ClearUnorderedAccessViewUint + public void Clear(UnorderedAccessView view, Int4 value) + { + Context.ClearUnorderedAccessView(view, value); + } + + /// + /// Clears an unordered access resource with a float value. + /// + /// The buffer to clear. + /// The value used to clear. + /// + ///

This API works on FLOAT, UNORM, and SNORM unordered access views (UAVs), with format conversion from FLOAT to *NORM where appropriate. On other UAVs, the operation is invalid and the call will not reach the driver.

+ ///
+ /// ff476390 + /// void ID3D11DeviceContext::ClearUnorderedAccessViewFloat([In] ID3D11UnorderedAccessView* pUnorderedAccessView,[In] const float* Values) + /// ID3D11DeviceContext::ClearUnorderedAccessViewFloat + public void Clear(UnorderedAccessView view, Vector4 value) + { + Context.ClearUnorderedAccessView(view, value); + } + + /// + /// Copies the content of this resource to another . + /// + /// The resource to copy from. + /// The resource to copy to. + /// See the unmanaged documentation for usage and restrictions. + /// ff476392 + /// void ID3D11DeviceContext::CopyResource([In] ID3D11Resource* pDstResource,[In] ID3D11Resource* pSrcResource) + /// ID3D11DeviceContext::CopyResource + public void Copy(Direct3D11.Resource fromResource, Direct3D11.Resource toResource) + { + Context.CopyResource(fromResource, toResource); + } + + /// + /// Copy a region from a source resource to a destination resource. + /// + /// + /// The source box must be within the size of the source resource. The destination offsets, (x, y, and z) allow the source box to be offset when writing into the destination resource; however, the dimensions of the source box and the offsets must be within the size of the resource. If the resources are buffers, all coordinates are in bytes; if the resources are textures, all coordinates are in texels. {{D3D11CalcSubresource}} is a helper function for calculating subresource indexes. CopySubresourceRegion performs the copy on the GPU (similar to a memcpy by the CPU). As a consequence, the source and destination resources: Must be different subresources (although they can be from the same resource). Must be the same type. Must have compatible DXGI formats (identical or from the same type group). For example, a DXGI_FORMAT_R32G32B32_FLOAT texture can be copied to an DXGI_FORMAT_R32G32B32_UINT texture since both of these formats are in the DXGI_FORMAT_R32G32B32_TYPELESS group. May not be currently mapped. CopySubresourceRegion only supports copy; it does not support any stretch, color key, blend, or format conversions. An application that needs to copy an entire resource should use instead. CopySubresourceRegion is an asynchronous call which may be added to the command-buffer queue, this attempts to remove pipeline stalls that may occur when copying data. See performance considerations for more details. Note??If you use CopySubresourceRegion with a depth-stencil buffer or a multisampled resource, you must copy the whole subresource. In this situation, you must pass 0 to the DstX, DstY, and DstZ parameters and NULL to the pSrcBox parameter. In addition, source and destination resources, which are represented by the pSrcResource and pDstResource parameters, should have identical sample count values. Example The following code snippet copies a box (located at (120,100),(200,220)) from a source texture into a region (10,20),(90,140) in a destination texture. + /// D3D11_BOX sourceRegion; + /// sourceRegion.left = 120; + /// sourceRegion.right = 200; + /// sourceRegion.top = 100; + /// sourceRegion.bottom = 220; + /// sourceRegion.front = 0; + /// sourceRegion.back = 1; pd3dDeviceContext->CopySubresourceRegion( pDestTexture, 0, 10, 20, 0, pSourceTexture, 0, &sourceRegion ); + /// + /// Notice, that for a 2D texture, front and back are set to 0 and 1 respectively. + /// + /// A reference to the source resource (see ). + /// Source subresource index. + /// A reference to the destination resource (see ). + /// Destination subresource index. + /// The x-coordinate of the upper left corner of the destination region. + /// The y-coordinate of the upper left corner of the destination region. For a 1D subresource, this must be zero. + /// The z-coordinate of the upper left corner of the destination region. For a 1D or 2D subresource, this must be zero. + /// ff476394 + /// void ID3D11DeviceContext::CopySubresourceRegion([In] ID3D11Resource* pDstResource,[In] unsigned int DstSubresource,[In] unsigned int DstX,[In] unsigned int DstY,[In] unsigned int DstZ,[In] ID3D11Resource* pSrcResource,[In] unsigned int SrcSubresource,[In, Optional] const D3D11_BOX* pSrcBox) + /// ID3D11DeviceContext::CopySubresourceRegion + public void Copy(SharpDX.Direct3D11.Resource source, int sourceSubresource, SharpDX.Direct3D11.Resource destination, int destinationSubResource, int dstX = 0, int dstY = 0, int dstZ = 0) + { + Context.CopySubresourceRegion(source, sourceSubresource, null, destination, destinationSubResource, dstX, dstY, dstZ); + } + + /// + /// Copy a region from a source resource to a destination resource. + /// + /// + /// The source box must be within the size of the source resource. The destination offsets, (x, y, and z) allow the source box to be offset when writing into the destination resource; however, the dimensions of the source box and the offsets must be within the size of the resource. If the resources are buffers, all coordinates are in bytes; if the resources are textures, all coordinates are in texels. {{D3D11CalcSubresource}} is a helper function for calculating subresource indexes. CopySubresourceRegion performs the copy on the GPU (similar to a memcpy by the CPU). As a consequence, the source and destination resources: Must be different subresources (although they can be from the same resource). Must be the same type. Must have compatible DXGI formats (identical or from the same type group). For example, a DXGI_FORMAT_R32G32B32_FLOAT texture can be copied to an DXGI_FORMAT_R32G32B32_UINT texture since both of these formats are in the DXGI_FORMAT_R32G32B32_TYPELESS group. May not be currently mapped. CopySubresourceRegion only supports copy; it does not support any stretch, color key, blend, or format conversions. An application that needs to copy an entire resource should use instead. CopySubresourceRegion is an asynchronous call which may be added to the command-buffer queue, this attempts to remove pipeline stalls that may occur when copying data. See performance considerations for more details. Note??If you use CopySubresourceRegion with a depth-stencil buffer or a multisampled resource, you must copy the whole subresource. In this situation, you must pass 0 to the DstX, DstY, and DstZ parameters and NULL to the pSrcBox parameter. In addition, source and destination resources, which are represented by the pSrcResource and pDstResource parameters, should have identical sample count values. Example The following code snippet copies a box (located at (120,100),(200,220)) from a source texture into a region (10,20),(90,140) in a destination texture. + /// D3D11_BOX sourceRegion; + /// sourceRegion.left = 120; + /// sourceRegion.right = 200; + /// sourceRegion.top = 100; + /// sourceRegion.bottom = 220; + /// sourceRegion.front = 0; + /// sourceRegion.back = 1; pd3dDeviceContext->CopySubresourceRegion( pDestTexture, 0, 10, 20, 0, pSourceTexture, 0, &sourceRegion ); + /// + /// Notice, that for a 2D texture, front and back are set to 0 and 1 respectively. + /// + /// A reference to the source resource (see ). + /// Source subresource index. + /// A reference to a 3D box (see ) that defines the source subresources that can be copied. If NULL, the entire source subresource is copied. The box must fit within the source resource. + /// A reference to the destination resource (see ). + /// Destination subresource index. + /// The x-coordinate of the upper left corner of the destination region. + /// The y-coordinate of the upper left corner of the destination region. For a 1D subresource, this must be zero. + /// The z-coordinate of the upper left corner of the destination region. For a 1D or 2D subresource, this must be zero. + /// ff476394 + /// void ID3D11DeviceContext::CopySubresourceRegion([In] ID3D11Resource* pDstResource,[In] unsigned int DstSubresource,[In] unsigned int DstX,[In] unsigned int DstY,[In] unsigned int DstZ,[In] ID3D11Resource* pSrcResource,[In] unsigned int SrcSubresource,[In, Optional] const D3D11_BOX* pSrcBox) + /// ID3D11DeviceContext::CopySubresourceRegion + public void Copy(SharpDX.Direct3D11.Resource source, int sourceSubresource, SharpDX.Direct3D11.ResourceRegion sourceRegion, SharpDX.Direct3D11.Resource destination, int destinationSubResource, int dstX = 0, int dstY = 0, int dstZ = 0) + { + Context.CopySubresourceRegion(source, sourceSubresource, sourceRegion, destination, destinationSubResource, dstX, dstY, dstZ); + } + + /// + /// Copy a multisampled resource into a non-multisampled resource. + /// + /// + /// This API is most useful when re-using the resulting render target of one render pass as an input to a second render pass. The source and destination resources must be the same resource type and have the same dimensions. In addition, they must have compatible formats. There are three scenarios for this: ScenarioRequirements Source and destination are prestructured and typedBoth the source and destination must have identical formats and that format must be specified in the Format parameter. One resource is prestructured and typed and the other is prestructured and typelessThe typed resource must have a format that is compatible with the typeless resource (i.e. the typed resource is DXGI_FORMAT_R32_FLOAT and the typeless resource is DXGI_FORMAT_R32_TYPELESS). The format of the typed resource must be specified in the Format parameter. Source and destination are prestructured and typelessBoth the source and destination must have the same typeless format (i.e. both must have DXGI_FORMAT_R32_TYPELESS), and the Format parameter must specify a format that is compatible with the source and destination (i.e. if both are DXGI_FORMAT_R32_TYPELESS then DXGI_FORMAT_R32_FLOAT could be specified in the Format parameter). For example, given the DXGI_FORMAT_R16G16B16A16_TYPELESS format: The source (or dest) format could be DXGI_FORMAT_R16G16B16A16_UNORM The dest (or source) format could be DXGI_FORMAT_R16G16B16A16_FLOAT ? + /// + /// Source resource. Must be multisampled. + /// >The source subresource of the source resource. + /// Destination resource. Must be a created with the flag and be single-sampled. See . + /// A zero-based index, that identifies the destination subresource. Use {{D3D11CalcSubresource}} to calculate the index. + /// A that indicates how the multisampled resource will be resolved to a single-sampled resource. See remarks. + /// void ID3D11DeviceContext::ResolveSubresource([In] ID3D11Resource* pDstResource,[In] int DstSubresource,[In] ID3D11Resource* pSrcResource,[In] int SrcSubresource,[In] DXGI_FORMAT Format) + public void Copy(SharpDX.Direct3D11.Resource source, int sourceSubresource, SharpDX.Direct3D11.Resource destination, int destinationSubresource, SharpDX.DXGI.Format format) + { + Context.ResolveSubresource(source, sourceSubresource, destination, destinationSubresource, format); + } + + /// + ///

Copies data from a buffer holding variable length data.

+ ///
+ ///

Pointer to an of a Structured Buffer resource created with either or specified when the UAV was created. These types of resources have hidden counters tracking "how many" records have been written.

+ ///

Pointer to . This can be any buffer resource that other copy commands, such as or , are able to write to.

+ ///

Offset from the start of pDstBuffer to write 32-bit UINT structure (vertex) count from pSrcView.

+ /// ff476393 + /// void ID3D11DeviceContext::CopyStructureCount([In] ID3D11Buffer* pDstBuffer,[In] unsigned int DstAlignedByteOffset,[In] ID3D11UnorderedAccessView* pSrcView) + /// ID3D11DeviceContext::CopyStructureCount + public void CopyCount(SharpDX.Direct3D11.UnorderedAccessView sourceView, SharpDX.Direct3D11.Buffer destinationBuffer, int offsetInBytes = 0) + { + Context.CopyStructureCount(destinationBuffer, offsetInBytes, sourceView); + } + + /// + ///

Restore all default settings.

+ ///
+ /// + ///

This method resets any device context to the default settings. This sets all input/output resource slots, shaders, input layouts, predications, scissor rectangles, depth-stencil state, rasterizer state, blend state, sampler state, and viewports to null. The primitive topology is set to UNDEFINED.

For a scenario where you would like to clear a list of commands recorded so far, call and throw away the resulting .

+ ///
+ /// ff476389 + /// void ID3D11DeviceContext::ClearState() + /// ID3D11DeviceContext::ClearState + public void ClearState() + { + Context.ClearState(); + } + + private PrimitiveTopology PrimitiveType + { + set + { + InputAssemblerStage.PrimitiveTopology = value; + } + } + + /// + ///

Draw indexed, non-instanced primitives.

+ ///
+ /// Type of the primitive to draw. + ///

Number of indices to draw.

+ ///

The location of the first index read by the GPU from the index buffer.

+ ///

A value added to each index before reading a vertex from the vertex buffer.

+ /// + ///

A draw API submits work to the rendering pipeline.

If the sum of both indices is negative, the result of the function call is undefined.

+ ///
+ /// ff476409 + /// void ID3D11DeviceContext::DrawIndexed([In] unsigned int IndexCount,[In] unsigned int StartIndexLocation,[In] int BaseVertexLocation) + /// ID3D11DeviceContext::DrawIndexed + public void DrawIndexed(PrimitiveType primitiveType, int indexCount, int startIndexLocation = 0, int baseVertexLocation = 0) + { + SetupInputLayout(); + + PrimitiveType = primitiveType; + Context.DrawIndexed(indexCount, startIndexLocation, baseVertexLocation); + } + + /// + ///

Draw non-indexed, non-instanced primitives.

+ ///
+ /// Type of the primitive to draw. + ///

Number of vertices to draw.

+ ///

Index of the first vertex, which is usually an offset in a vertex buffer; it could also be used as the first vertex id generated for a shader parameter marked with the SV_TargetId system-value semantic.

+ /// + ///

A draw API submits work to the rendering pipeline.

The vertex data for a draw call normally comes from a vertex buffer that is bound to the pipeline. However, you could also provide the vertex data from a shader that has vertex data marked with the SV_VertexId system-value semantic.

+ ///
+ /// ff476407 + /// void ID3D11DeviceContext::Draw([In] unsigned int VertexCount,[In] unsigned int StartVertexLocation) + /// ID3D11DeviceContext::Draw + public void Draw(PrimitiveType primitiveType, int vertexCount, int startVertexLocation = 0) + { + SetupInputLayout(); + + PrimitiveType = primitiveType; + Context.Draw(vertexCount, startVertexLocation); + } + + /// + ///

Draw indexed, instanced primitives.

+ ///
+ /// Type of the primitive to draw. + ///

Number of indices read from the index buffer for each instance.

+ ///

Number of instances to draw.

+ ///

The location of the first index read by the GPU from the index buffer.

+ ///

A value added to each index before reading a vertex from the vertex buffer.

+ ///

A value added to each index before reading per-instance data from a vertex buffer.

+ /// + ///

A draw API submits work to the rendering pipeline.

Instancing may extend performance by reusing the same geometry to draw multiple objects in a scene. One example of instancing could be to draw the same object with different positions and colors. Indexing requires multiple vertex buffers: at least one for per-vertex data and a second buffer for per-instance data.

+ ///
+ /// ff476410 + /// void ID3D11DeviceContext::DrawIndexedInstanced([In] unsigned int IndexCountPerInstance,[In] unsigned int InstanceCount,[In] unsigned int StartIndexLocation,[In] int BaseVertexLocation,[In] unsigned int StartInstanceLocation) + /// ID3D11DeviceContext::DrawIndexedInstanced + public void DrawIndexedInstanced(PrimitiveType primitiveType, int indexCountPerInstance, int instanceCount, int startIndexLocation = 0, int baseVertexLocation = 0, int startInstanceLocation = 0) + { + SetupInputLayout(); + + PrimitiveType = primitiveType; + Context.DrawIndexedInstanced(indexCountPerInstance, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation); + } + + /// + ///

Draw non-indexed, instanced primitives.

+ ///
+ /// Type of the primitive to draw. + ///

Number of vertices to draw.

+ ///

Number of instances to draw.

+ ///

Index of the first vertex.

+ ///

A value added to each index before reading per-instance data from a vertex buffer.

+ /// + ///

A draw API submits work to the rendering pipeline.

Instancing may extend performance by reusing the same geometry to draw multiple objects in a scene. One example of instancing could be to draw the same object with different positions and colors.

The vertex data for an instanced draw call normally comes from a vertex buffer that is bound to the pipeline. However, you could also provide the vertex data from a shader that has instanced data identified with a system-value semantic (SV_InstanceID).

+ ///
+ /// ff476412 + /// void ID3D11DeviceContext::DrawInstanced([In] unsigned int VertexCountPerInstance,[In] unsigned int InstanceCount,[In] unsigned int StartVertexLocation,[In] unsigned int StartInstanceLocation) + /// ID3D11DeviceContext::DrawInstanced + public void DrawInstanced(PrimitiveType primitiveType, int vertexCountPerInstance, int instanceCount, int startVertexLocation = 0, int startInstanceLocation = 0) + { + SetupInputLayout(); + + PrimitiveType = primitiveType; + Context.DrawInstanced(vertexCountPerInstance, instanceCount, startVertexLocation, startInstanceLocation); + } + + /// + ///

Draw geometry of an unknown size.

+ ///
+ /// Type of the primitive to draw. + /// + ///

A draw API submits work to the rendering pipeline. This API submits work of an unknown size that was processed by the input assembler, vertex shader, and stream-output stages; the work may or may not have gone through the geometry-shader stage.

After data has been streamed out to stream-output stage buffers, those buffers can be again bound to the Input Assembler stage at input slot 0 and DrawAuto will draw them without the application needing to know the amount of data that was written to the buffers. A measurement of the amount of data written to the SO stage buffers is maintained internally when the data is streamed out. This means that the CPU does not need to fetch the measurement before re-binding the data that was streamed as input data. Although this amount is tracked internally, it is still the responsibility of applications to use input layouts to describe the format of the data in the SO stage buffers so that the layouts are available when the buffers are again bound to the input assembler.

The following diagram shows the DrawAuto process.

Calling DrawAuto does not change the state of the streaming-output buffers that were bound again as inputs.

DrawAuto only works when drawing with one input buffer bound as an input to the IA stage at slot 0. Applications must create the SO buffer resource with both binding flags, and .

This API does not support indexing or instancing.

If an application needs to retrieve the size of the streaming-output buffer, it can query for statistics on streaming output by using .

+ ///
+ /// ff476408 + /// void ID3D11DeviceContext::DrawAuto() + /// ID3D11DeviceContext::DrawAuto + public void DrawAuto(PrimitiveType primitiveType) + { + SetupInputLayout(); + + PrimitiveType = primitiveType; + Context.DrawAuto(); + } + + /// + ///

Draw indexed, instanced, GPU-generated primitives.

+ ///
+ /// Type of the primitive to draw. + ///

A reference to an , which is a buffer containing the GPU generated primitives.

+ ///

Offset in pBufferForArgs to the start of the GPU generated primitives.

+ /// + ///

When an application creates a buffer that is associated with the interface that pBufferForArgs points to, the application must set the flag in the MiscFlags member of the structure that describes the buffer. To create the buffer, the application calls the method and in this call passes a reference to in the pDesc parameter.

+ ///
+ /// ff476411 + /// void ID3D11DeviceContext::DrawIndexedInstancedIndirect([In] ID3D11Buffer* pBufferForArgs,[In] unsigned int AlignedByteOffsetForArgs) + /// ID3D11DeviceContext::DrawIndexedInstancedIndirect + public void DrawIndexedInstanced(PrimitiveType primitiveType, SharpDX.Direct3D11.Buffer argumentsBuffer, int alignedByteOffsetForArgs = 0) + { + SetupInputLayout(); + + PrimitiveType = primitiveType; + Context.DrawIndexedInstancedIndirect(argumentsBuffer, alignedByteOffsetForArgs); + } + + /// + ///

Draw instanced, GPU-generated primitives.

+ ///
+ /// Type of the primitive to draw. + ///

A reference to an , which is a buffer containing the GPU generated primitives.

+ ///

Offset in pBufferForArgs to the start of the GPU generated primitives.

+ /// + ///

When an application creates a buffer that is associated with the interface that pBufferForArgs points to, the application must set the flag in the MiscFlags member of the structure that describes the buffer. To create the buffer, the application calls the method and in this call passes a reference to in the pDesc parameter.

+ ///
+ /// ff476413 + /// void ID3D11DeviceContext::DrawInstancedIndirect([In] ID3D11Buffer* pBufferForArgs,[In] unsigned int AlignedByteOffsetForArgs) + /// ID3D11DeviceContext::DrawInstancedIndirect + public void DrawInstanced(PrimitiveType primitiveType, SharpDX.Direct3D11.Buffer argumentsBuffer, int alignedByteOffsetForArgs = 0) + { + SetupInputLayout(); + + PrimitiveType = primitiveType; + Context.DrawInstancedIndirect(argumentsBuffer, alignedByteOffsetForArgs); + } + + /// + ///

Execute a command list from a thread group.

+ ///
+ ///

The number of groups dispatched in the x direction. ThreadGroupCountX must be less than (65535).

+ ///

The number of groups dispatched in the y direction. ThreadGroupCountY must be less than (65535).

+ ///

The number of groups dispatched in the z direction. ThreadGroupCountZ must be less than (65535). In feature level 10 the value for ThreadGroupCountZ must be 1.

+ /// + ///

You call the Dispatch method to execute commands in a compute shader. A compute shader can be run on many threads in parallel, within a thread group. Index a particular thread, within a thread group using a 3D vector given by (x,y,z).

In the following illustration, assume a thread group with 50 threads where the size of the group is given by (5,5,2). A single thread is identified from a thread group with 50 threads in it, using the vector (4,1,1).

The following illustration shows the relationship between the parameters passed to , Dispatch(5,3,2), the values specified in the numthreads attribute, numthreads(10,8,3), and values that will passed to the compute shader for the thread-related system values + /// (SV_GroupIndex,SV_DispatchThreadID,SV_GroupThreadID,SV_GroupID).

+ ///
+ /// ff476405 + /// void ID3D11DeviceContext::Dispatch([In] unsigned int ThreadGroupCountX,[In] unsigned int ThreadGroupCountY,[In] unsigned int ThreadGroupCountZ) + /// ID3D11DeviceContext::Dispatch + public void Dispatch(int threadGroupCountX, int threadGroupCountY, int threadGroupCountZ) + { + Context.Dispatch(threadGroupCountX, threadGroupCountY, threadGroupCountZ); + } + + /// + ///

Execute a command list over one or more thread groups.

+ ///
+ ///

A reference to an , which must be loaded with data that matches the argument list for .

+ ///

A byte-aligned offset between the start of the buffer and the arguments.

+ /// + ///

You call the DispatchIndirect method to execute commands in a compute shader.

When an application creates a buffer that is associated with the interface that pBufferForArgs points to, the application must set the flag in the MiscFlags member of the structure that describes the buffer. To create the buffer, the application calls the method and in this call passes a reference to in the pDesc parameter.

+ ///
+ /// ff476406 + /// void ID3D11DeviceContext::DispatchIndirect([In] ID3D11Buffer* pBufferForArgs,[In] unsigned int AlignedByteOffsetForArgs) + /// ID3D11DeviceContext::DispatchIndirect + public void Dispatch(SharpDX.Direct3D11.Buffer argumentsBuffer, int alignedByteOffsetForArgs = 0) + { + Context.DispatchIndirect(argumentsBuffer, alignedByteOffsetForArgs); + } + + /// + ///

Sends queued-up commands in the command buffer to the graphics processing unit (GPU).

+ ///
+ /// + ///

Most applications don't need to call this method. If an application calls this method when not necessary, it incurs a performance penalty. Each call to Flush incurs a significant amount of overhead.

When Microsoft Direct3D state-setting, present, or draw commands are called by an application, those commands are queued into an internal command buffer. Flush sends those commands to the GPU for processing. Typically, the Direct3D runtime sends these commands to the GPU automatically whenever the runtime determines that they need to be sent, such as when the command buffer is full or when an application maps a resource. Flush sends the commands manually.

We recommend that you use Flush when the CPU waits for an arbitrary amount of time (such as when you call the Sleep function).

Because Flush operates asynchronously, it can return either before or after the GPU finishes executing the queued graphics commands. However, the graphics commands eventually always complete. You can call the method with the value to create an event query; you can then use that event query in a call to the method to determine when the GPU is finished processing the graphics commands. + ///

Microsoft Direct3D?11 defers the destruction of objects. Therefore, an application can't rely upon objects immediately being destroyed. By calling Flush, you destroy any objects whose destruction was deferred. If an application requires synchronous destruction of an object, we recommend that the application release all its references, call , and then call Flush.

Deferred Destruction Issues with Flip Presentation Swap Chains

Direct3D?11 defers the destruction of objects like views and resources until it can efficiently destroy them. This deferred destruction can cause problems with flip presentation model swap chains. Flip presentation model swap chains have the DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL flag set. When you create a flip presentation model swap chain, you can associate only one swap chain at a time with an , IWindow, or composition surface. If an application attempts to destroy a flip presentation model swap chain and replace it with another swap chain, the original swap chain is not destroyed when the application immediately frees all of the original swap chain's references.

Most applications typically use the method for the majority of scenarios where they replace new swap chain buffers for old swap chain buffers. However, if an application must actually destroy an old swap chain and create a new swap chain, the application must force the destruction of all objects that the application freed. To force the destruction, call (or otherwise ensure no views are bound to pipeline state), and then call Flush on the immediate context. You must force destruction before you call IDXGIFactory2::CreateSwapChainForHwnd, IDXGIFactory2::CreateSwapChainForImmersiveWindow, or IDXGIFactory2::CreateSwapChainForCompositionSurface again to create a new swap chain.

+ ///
+ /// ff476425 + /// void ID3D11DeviceContext::Flush() + /// ID3D11DeviceContext::Flush + public void Flush() + { + Context.Flush(); + } + + /// + /// Creates a new from an existing . + /// + /// An existing device. + /// A new instance of . + public static GraphicsDevice New(SharpDX.Direct3D11.Device existingDevice) + { + return new GraphicsDevice(existingDevice); + } + + /// + /// Creates a new using . + /// + /// The flags. + /// The feature levels. + /// A new instance of + public static GraphicsDevice New(DeviceCreationFlags flags = DeviceCreationFlags.None, params FeatureLevel[] featureLevels) + { + return New(DriverType.Hardware, flags, featureLevels); + } + + /// + /// Creates a new . + /// + /// The type. + /// The flags. + /// The feature levels. + /// A new instance of . + public static GraphicsDevice New(DriverType type, DeviceCreationFlags flags = DeviceCreationFlags.None, params FeatureLevel[] featureLevels) + { + if (type == DriverType.Hardware) + return new GraphicsDevice(GraphicsAdapter.Default, flags, featureLevels); + + return new GraphicsDevice(type, flags, featureLevels); + } + + /// + /// Creates a new . + /// + /// The graphics adapter to use. + /// The flags. + /// The feature levels. + /// A new instance of . + public static GraphicsDevice New(GraphicsAdapter adapter, DeviceCreationFlags flags = DeviceCreationFlags.None, params FeatureLevel[] featureLevels) + { + return new GraphicsDevice(adapter, flags, featureLevels); + } + + /// + /// Creates a new deferred . + /// + /// A deferred . + public GraphicsDevice NewDeferred() + { + return new GraphicsDevice(this, new DeviceContext(Device)); + } + + /// + ///

Sets the blend state of the output-merger stage.

+ ///
+ ///

Pointer to a blend-state interface (see ). Passing in null implies a default blend state. See remarks for further details.

+ /// + ///

Blend state is used by the output-merger stage to determine how to blend together two pixel values. The two values are commonly the current pixel value and the pixel value already in the output render target. Use the blend operation to control where the two pixel values come from and how they are mathematically combined.

To create a blend-state interface, call .

Passing in null for the blend-state interface indicates to the runtime to set a default blending state. The following table indicates the default blending parameters.

StateDefault Value
AlphaToCoverageEnable
BlendEnable[8]
SrcBlend
DstBlend
BlendOp
SrcBlendAlpha
DstBlendAlpha
BlendOpAlpha
RenderTargetWriteMask[8][8]

?

A sample mask determines which samples get updated in all the active render targets. The mapping of bits in a sample mask to samples in a multisample render target is the responsibility of an individual application. A sample mask is always applied; it is independent of whether multisampling is enabled, and does not depend on whether an application uses multisample render targets.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

+ ///
+ /// ff476462 + /// void ID3D11DeviceContext::OMSetBlendState([In, Optional] ID3D11BlendState* pBlendState,[In, Optional] const SHARPDX_COLOR4* BlendFactor,[In] unsigned int SampleMask) + /// ID3D11DeviceContext::OMSetBlendState + public void SetBlendState(BlendState blendState) + { + if (blendState == null) + { + OutputMergerStage.SetBlendState(null, Color.White, -1); + } + else + { + OutputMergerStage.SetBlendState(blendState, blendState.BlendFactor, blendState.MultiSampleMask); + } + } + + /// + ///

Sets the blend state of the output-merger stage.

+ ///
+ ///

Pointer to a blend-state interface (see ). Passing in null implies a default blend state. See remarks for further details.

+ ///

Array of blend factors, one for each RGBA component. This requires a blend state object that specifies the option.

+ ///

32-bit sample coverage. The default value is 0xffffffff. See remarks.

+ /// + ///

Blend state is used by the output-merger stage to determine how to blend together two pixel values. The two values are commonly the current pixel value and the pixel value already in the output render target. Use the blend operation to control where the two pixel values come from and how they are mathematically combined.

To create a blend-state interface, call .

Passing in null for the blend-state interface indicates to the runtime to set a default blending state. The following table indicates the default blending parameters.

StateDefault Value
AlphaToCoverageEnable
BlendEnable[8]
SrcBlend
DstBlend
BlendOp
SrcBlendAlpha
DstBlendAlpha
BlendOpAlpha
RenderTargetWriteMask[8][8]

?

A sample mask determines which samples get updated in all the active render targets. The mapping of bits in a sample mask to samples in a multisample render target is the responsibility of an individual application. A sample mask is always applied; it is independent of whether multisampling is enabled, and does not depend on whether an application uses multisample render targets.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

+ ///
+ /// ff476462 + /// void ID3D11DeviceContext::OMSetBlendState([In, Optional] ID3D11BlendState* pBlendState,[In, Optional] const SHARPDX_COLOR4* BlendFactor,[In] unsigned int SampleMask) + /// ID3D11DeviceContext::OMSetBlendState + public void SetBlendState(BlendState blendState, Color4 blendFactor, int multiSampleMask = -1) + { + if (blendState == null) + { + OutputMergerStage.SetBlendState(null, blendFactor, multiSampleMask); + } + else + { + OutputMergerStage.SetBlendState(blendState, blendFactor, multiSampleMask); + } + } + + /// + ///

Sets the blend state of the output-merger stage.

+ ///
+ ///

Pointer to a blend-state interface (see ). Passing in null implies a default blend state. See remarks for further details.

+ ///

Array of blend factors, one for each RGBA component. This requires a blend state object that specifies the option.

+ ///

32-bit sample coverage. The default value is 0xffffffff. See remarks.

+ /// + ///

Blend state is used by the output-merger stage to determine how to blend together two pixel values. The two values are commonly the current pixel value and the pixel value already in the output render target. Use the blend operation to control where the two pixel values come from and how they are mathematically combined.

To create a blend-state interface, call .

Passing in null for the blend-state interface indicates to the runtime to set a default blending state. The following table indicates the default blending parameters.

StateDefault Value
AlphaToCoverageEnable
BlendEnable[8]
SrcBlend
DstBlend
BlendOp
SrcBlendAlpha
DstBlendAlpha
BlendOpAlpha
RenderTargetWriteMask[8][8]

?

A sample mask determines which samples get updated in all the active render targets. The mapping of bits in a sample mask to samples in a multisample render target is the responsibility of an individual application. A sample mask is always applied; it is independent of whether multisampling is enabled, and does not depend on whether an application uses multisample render targets.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

+ ///
+ /// ff476462 + /// void ID3D11DeviceContext::OMSetBlendState([In, Optional] ID3D11BlendState* pBlendState,[In, Optional] const SHARPDX_COLOR4* BlendFactor,[In] unsigned int SampleMask) + /// ID3D11DeviceContext::OMSetBlendState + public void SetBlendState(BlendState blendState, Color4 blendFactor, uint multiSampleMask = 0xFFFFFFFF) + { + SetBlendState(blendState, blendFactor, unchecked((int)multiSampleMask)); + } + + /// + /// Sets the depth-stencil state of the output-merger stage. + /// + ///

Pointer to a depth-stencil state interface (see ) to bind to the device. Set this to null to use the default state listed in .

+ ///

Reference value to perform against when doing a depth-stencil test. See remarks.

+ /// + ///

To create a depth-stencil state interface, call .

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

+ ///
+ /// ff476463 + /// void ID3D11DeviceContext::OMSetDepthStencilState([In, Optional] ID3D11DepthStencilState* pDepthStencilState,[In] unsigned int StencilRef) + /// ID3D11DeviceContext::OMSetDepthStencilState + public void SetDepthStencilState(DepthStencilState depthStencilState, int stencilReference = 0) + { + OutputMergerStage.SetDepthStencilState(depthStencilState, stencilReference); + } + + /// + ///

Sets the rasterizer state for the rasterizer stage of the pipeline.

+ ///
+ /// The rasterizer state to set on this device. + /// ff476479 + /// void ID3D11DeviceContext::RSSetState([In, Optional] ID3D11RasterizerState* pRasterizerState) + /// ID3D11DeviceContext::RSSetState + public void SetRasterizerState(RasterizerState rasterizerState) + { + RasterizerStage.State = rasterizerState; + } + + /// + /// Binds a single scissor rectangle to the rasterizer stage. + /// + /// The left. + /// The top. + /// The right. + /// The bottom. + /// + ///

All scissor rects must be set atomically as one operation. Any scissor rects not defined by the call are disabled.

The scissor rectangles will only be used if ScissorEnable is set to true in the rasterizer state (see ).

Which scissor rectangle to use is determined by the SV_ViewportArrayIndex semantic output by a geometry shader (see shader semantic syntax). If a geometry shader does not make use of the SV_ViewportArrayIndex semantic then Direct3D will use the first scissor rectangle in the array.

Each scissor rectangle in the array corresponds to a viewport in an array of viewports (see ).

+ ///
+ /// ff476478 + /// void ID3D11DeviceContext::RSSetScissorRects([In] unsigned int NumRects,[In, Buffer, Optional] const void* pRects) + /// ID3D11DeviceContext::RSSetScissorRects + public void SetScissorRectangles(int left, int top, int right, int bottom) + { + RasterizerStage.SetScissorRectangle(left, top, right, bottom); + } + + /// + /// Binds a set of scissor rectangles to the rasterizer stage. + /// + /// The set of scissor rectangles to bind. + /// + ///

All scissor rects must be set atomically as one operation. Any scissor rects not defined by the call are disabled.

The scissor rectangles will only be used if ScissorEnable is set to true in the rasterizer state (see ).

Which scissor rectangle to use is determined by the SV_ViewportArrayIndex semantic output by a geometry shader (see shader semantic syntax). If a geometry shader does not make use of the SV_ViewportArrayIndex semantic then Direct3D will use the first scissor rectangle in the array.

Each scissor rectangle in the array corresponds to a viewport in an array of viewports (see ).

+ ///
+ /// ff476478 + /// void ID3D11DeviceContext::RSSetScissorRects([In] unsigned int NumRects,[In, Buffer, Optional] const void* pRects) + /// ID3D11DeviceContext::RSSetScissorRects + public void SetScissorRectangles(params Rectangle[] scissorRectangles) + { + RasterizerStage.SetScissorRectangles(scissorRectangles); + } + + /// + /// Gets the main viewport. + /// + /// The main viewport. + public ViewportF Viewport + { + get + { + RasterizerStage.GetViewports(viewports); + return viewports[0]; + } + + set + { + SetViewport(value); + } + } + + /// + /// Gets the viewport. + /// + /// The index. + /// Returns a viewport bound to a specified render target + public ViewportF GetViewport(int index) + { + RasterizerStage.GetViewports(viewports); + return viewports[index]; + } + + /// + /// Binds a single viewport to the rasterizer stage. + /// + /// The x coordinate of the viewport. + /// The y coordinate of the viewport. + /// The width. + /// The height. + /// The min Z. + /// The max Z. + /// + ///

All viewports must be set atomically as one operation. Any viewports not defined by the call are disabled.

Which viewport to use is determined by the SV_ViewportArrayIndex semantic output by a geometry shader; if a geometry shader does not specify the semantic, Direct3D will use the first viewport in the array.

+ ///
+ /// ff476480 + /// void ID3D11DeviceContext::RSSetViewports([In] unsigned int NumViewports,[In, Buffer, Optional] const void* pViewports) + /// ID3D11DeviceContext::RSSetViewports + public void SetViewport(float x, float y, float width, float height, float minZ = 0.0f, float maxZ = 1.0f) + { + viewports[0] = new ViewportF(x, y, width, height, minZ, maxZ); + RasterizerStage.SetViewport(x, y, width, height, minZ, maxZ); + } + + /// + /// Binds a single viewport to the rasterizer stage. + /// + /// The viewport. + /// + ///

All viewports must be set atomically as one operation. Any viewports not defined by the call are disabled.

Which viewport to use is determined by the SV_ViewportArrayIndex semantic output by a geometry shader; if a geometry shader does not specify the semantic, Direct3D will use the first viewport in the array.

+ ///
+ /// ff476480 + /// void ID3D11DeviceContext::RSSetViewports([In] unsigned int NumViewports,[In, Buffer, Optional] const void* pViewports) + /// ID3D11DeviceContext::RSSetViewports + public void SetViewport(ViewportF viewport) + { + viewports[0] = viewport; + RasterizerStage.SetViewport(viewport); + } + + /// + /// Binds a set of viewports to the rasterizer stage. + /// + /// The set of viewports to bind. + /// + ///

All viewports must be set atomically as one operation. Any viewports not defined by the call are disabled.

Which viewport to use is determined by the SV_ViewportArrayIndex semantic output by a geometry shader; if a geometry shader does not specify the semantic, Direct3D will use the first viewport in the array.

+ ///
+ /// ff476480 + /// void ID3D11DeviceContext::RSSetViewports([In] unsigned int NumViewports,[In, Buffer, Optional] const void* pViewports) + /// ID3D11DeviceContext::RSSetViewports + public void SetViewports(params ViewportF[] viewports) + { + for (int i = 0; i < viewports.Length; i++) + this.viewports[i] = viewports[i]; + + RasterizerStage.SetViewports(this.viewports, viewports.Length); + } + + /// + /// Unbinds all depth-stencil buffer and render targets from the output-merger stage. + /// + /// ff476464 + /// void ID3D11DeviceContext::OMSetRenderTargets([In] unsigned int NumViews,[In] const void** ppRenderTargetViews,[In, Optional] ID3D11DepthStencilView* pDepthStencilView) + /// ID3D11DeviceContext::OMSetRenderTargets + public void ResetTargets() + { + for (int i = 0; i < currentRenderTargetViews.Length; i++) + currentRenderTargetViews[i] = null; + actualRenderTargetViewCount = 0; + currentRenderTargetView = null; + currentDepthStencilView = null; + OutputMergerStage.ResetTargets(); + } + + /// + /// Gets the render targets currently bound to the through this instance. + /// + /// The depth stencil view, may ne null. + /// An array of . + public RenderTargetView[] GetRenderTargets(out DepthStencilView depthStencilViewRef) + { + var renderTargets = new RenderTargetView[actualRenderTargetViewCount]; + for (int i = 0; i < actualRenderTargetViewCount; i++) + renderTargets[i] = currentRenderTargetViews[i]; + depthStencilViewRef = currentDepthStencilView; + return renderTargets; + } + + /// + ///

Bind one or more render targets atomically and the depth-stencil buffer to the output-merger stage.

+ ///
+ /// A set of render target views to bind. + /// + ///

The maximum number of active render targets a device can have active at any given time is set by a #define in D3D11.h called D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT. It is invalid to try to set the same subresource to multiple render target slots. Any render targets not defined by this call are set to null.

If any subresources are also currently bound for reading in a different stage or writing (perhaps in a different part of the pipeline), those bind points will be set to null, in order to prevent the same subresource from being read and written simultaneously in a single rendering operation.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

If the render-target views were created from an array resource type, then all of the render-target views must have the same array size. This restriction also applies to the depth-stencil view, its array size must match that of the render-target views being bound.

The pixel shader must be able to simultaneously render to at least eight separate render targets. All of these render targets must access the same type of resource: Buffer, Texture1D, Texture1DArray, Texture2D, Texture2DArray, Texture3D, or TextureCube. All render targets must have the same size in all dimensions (width and height, and depth for 3D or array size for *Array types). If render targets use multisample anti-aliasing, all bound render targets and depth buffer must be the same form of multisample resource (that is, the sample counts must be the same). Each render target can have a different data format. These render target formats are not required to have identical bit-per-element counts.

Any combination of the eight slots for render targets can have a render target set or not set.

The same resource view cannot be bound to multiple render target slots simultaneously. However, you can set multiple non-overlapping resource views of a single resource as simultaneous multiple render targets.

+ ///
+ /// ff476464 + /// void ID3D11DeviceContext::OMSetRenderTargets([In] unsigned int NumViews,[In] const void** ppRenderTargetViews,[In, Optional] ID3D11DepthStencilView* pDepthStencilView) + /// ID3D11DeviceContext::OMSetRenderTargets + public void SetRenderTargets(params RenderTargetView[] renderTargetViews) + { + if (renderTargetViews == null) + { + throw new ArgumentNullException("renderTargetViews"); + } + + CommonSetRenderTargets(renderTargetViews); + currentDepthStencilView = null; + OutputMergerStage.SetTargets(renderTargetViews); + } + + /// + /// Binds a single render target to the output-merger stage. + /// + /// A view of the render target to bind. + /// + ///

The maximum number of active render targets a device can have active at any given time is set by a #define in D3D11.h called D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT. It is invalid to try to set the same subresource to multiple render target slots. Any render targets not defined by this call are set to null.

If any subresources are also currently bound for reading in a different stage or writing (perhaps in a different part of the pipeline), those bind points will be set to null, in order to prevent the same subresource from being read and written simultaneously in a single rendering operation.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

If the render-target views were created from an array resource type, then all of the render-target views must have the same array size. This restriction also applies to the depth-stencil view, its array size must match that of the render-target views being bound.

The pixel shader must be able to simultaneously render to at least eight separate render targets. All of these render targets must access the same type of resource: Buffer, Texture1D, Texture1DArray, Texture2D, Texture2DArray, Texture3D, or TextureCube. All render targets must have the same size in all dimensions (width and height, and depth for 3D or array size for *Array types). If render targets use multisample anti-aliasing, all bound render targets and depth buffer must be the same form of multisample resource (that is, the sample counts must be the same). Each render target can have a different data format. These render target formats are not required to have identical bit-per-element counts.

Any combination of the eight slots for render targets can have a render target set or not set.

The same resource view cannot be bound to multiple render target slots simultaneously. However, you can set multiple non-overlapping resource views of a single resource as simultaneous multiple render targets.

+ ///
+ /// ff476464 + /// void ID3D11DeviceContext::OMSetRenderTargets([In] unsigned int NumViews,[In] const void** ppRenderTargetViews,[In, Optional] ID3D11DepthStencilView* pDepthStencilView) + /// ID3D11DeviceContext::OMSetRenderTargets + public void SetRenderTargets(RenderTargetView renderTargetView) + { + CommonSetRenderTargets(renderTargetView); + currentDepthStencilView = null; + OutputMergerStage.SetTargets(renderTargetView); + } + + /// + /// Binds a depth-stencil buffer and a set of render targets to the output-merger stage. + /// + /// A view of the depth-stencil buffer to bind. + /// A set of render target views to bind. + /// + ///

The maximum number of active render targets a device can have active at any given time is set by a #define in D3D11.h called D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT. It is invalid to try to set the same subresource to multiple render target slots. Any render targets not defined by this call are set to null.

If any subresources are also currently bound for reading in a different stage or writing (perhaps in a different part of the pipeline), those bind points will be set to null, in order to prevent the same subresource from being read and written simultaneously in a single rendering operation.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

If the render-target views were created from an array resource type, then all of the render-target views must have the same array size. This restriction also applies to the depth-stencil view, its array size must match that of the render-target views being bound.

The pixel shader must be able to simultaneously render to at least eight separate render targets. All of these render targets must access the same type of resource: Buffer, Texture1D, Texture1DArray, Texture2D, Texture2DArray, Texture3D, or TextureCube. All render targets must have the same size in all dimensions (width and height, and depth for 3D or array size for *Array types). If render targets use multisample anti-aliasing, all bound render targets and depth buffer must be the same form of multisample resource (that is, the sample counts must be the same). Each render target can have a different data format. These render target formats are not required to have identical bit-per-element counts.

Any combination of the eight slots for render targets can have a render target set or not set.

The same resource view cannot be bound to multiple render target slots simultaneously. However, you can set multiple non-overlapping resource views of a single resource as simultaneous multiple render targets.

+ ///
+ /// ff476464 + /// void ID3D11DeviceContext::OMSetRenderTargets([In] unsigned int NumViews,[In] const void** ppRenderTargetViews,[In, Optional] ID3D11DepthStencilView* pDepthStencilView) + /// ID3D11DeviceContext::OMSetRenderTargets + public void SetRenderTargets(DepthStencilView depthStencilView, params RenderTargetView[] renderTargetViews) + { + if (renderTargetViews == null) + { + throw new ArgumentNullException("renderTargetViews"); + } + + CommonSetRenderTargets(renderTargetViews); + currentDepthStencilView = depthStencilView; + OutputMergerStage.SetTargets(depthStencilView, renderTargetViews); + } + + /// + /// Binds a depth-stencil buffer and a single render target to the output-merger stage. + /// + /// A view of the depth-stencil buffer to bind. + /// A view of the render target to bind. + /// + ///

The maximum number of active render targets a device can have active at any given time is set by a #define in D3D11.h called D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT. It is invalid to try to set the same subresource to multiple render target slots. Any render targets not defined by this call are set to null.

If any subresources are also currently bound for reading in a different stage or writing (perhaps in a different part of the pipeline), those bind points will be set to null, in order to prevent the same subresource from being read and written simultaneously in a single rendering operation.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

If the render-target views were created from an array resource type, then all of the render-target views must have the same array size. This restriction also applies to the depth-stencil view, its array size must match that of the render-target views being bound.

The pixel shader must be able to simultaneously render to at least eight separate render targets. All of these render targets must access the same type of resource: Buffer, Texture1D, Texture1DArray, Texture2D, Texture2DArray, Texture3D, or TextureCube. All render targets must have the same size in all dimensions (width and height, and depth for 3D or array size for *Array types). If render targets use multisample anti-aliasing, all bound render targets and depth buffer must be the same form of multisample resource (that is, the sample counts must be the same). Each render target can have a different data format. These render target formats are not required to have identical bit-per-element counts.

Any combination of the eight slots for render targets can have a render target set or not set.

The same resource view cannot be bound to multiple render target slots simultaneously. However, you can set multiple non-overlapping resource views of a single resource as simultaneous multiple render targets.

+ ///
+ /// ff476464 + /// void ID3D11DeviceContext::OMSetRenderTargets([In] unsigned int NumViews,[In] const void** ppRenderTargetViews,[In, Optional] ID3D11DepthStencilView* pDepthStencilView) + /// ID3D11DeviceContext::OMSetRenderTargets + public void SetRenderTargets(DepthStencilView depthStencilView, RenderTargetView renderTargetView) + { + CommonSetRenderTargets(renderTargetView); + currentDepthStencilView = depthStencilView; + OutputMergerStage.SetTargets(depthStencilView, renderTargetView); + } + + /// + /// Resets the stream output targets bound to the StreamOutput stage. + /// + /// ff476484 + /// void ID3D11DeviceContext::SOSetTargets([In] unsigned int NumBuffers,[In, Buffer, Optional] const ID3D11Buffer** ppSOTargets,[In, Buffer, Optional] const unsigned int* pOffsets) + /// ID3D11DeviceContext::SOSetTargets + public void ResetStreamOutputTargets() + { + Context.StreamOutput.SetTargets(0, null, null); + } + + /// + /// Sets the stream output targets bound to the StreamOutput stage. + /// + /// The buffer to bind on the first stream output slot. + /// The offsets in bytes of the buffer. An offset of -1 will cause the stream output buffer to be appended, continuing after the last location written to the buffer in a previous stream output pass. + /// ff476484 + /// void ID3D11DeviceContext::SOSetTargets([In] unsigned int NumBuffers,[In, Buffer, Optional] const ID3D11Buffer** ppSOTargets,[In, Buffer, Optional] const unsigned int* pOffsets) + /// ID3D11DeviceContext::SOSetTargets + public unsafe void SetStreamOutputTarget(Buffer buffer, int offsets = -1) + { + Context.StreamOutput.SetTarget(buffer, offsets); + } + + /// + /// Sets the stream output targets bound to the StreamOutput stage. + /// + /// The buffers. + /// ff476484 + /// void ID3D11DeviceContext::SOSetTargets([In] unsigned int NumBuffers,[In, Buffer, Optional] const ID3D11Buffer** ppSOTargets,[In, Buffer, Optional] const unsigned int* pOffsets) + /// ID3D11DeviceContext::SOSetTargets + public void SetStreamOutputTargets(params StreamOutputBufferBinding[] buffers) + { + Context.StreamOutput.SetTargets(buffers); + } + + /// + ///

Bind an index buffer to the input-assembler stage.

+ ///
+ ///

A reference to an object, that contains indices. The index buffer must have been created with the flag.

+ /// Set to true if indices are 32-bit values (integer size) or false if they are 16-bit values (short size) + /// Offset (in bytes) from the start of the index buffer to the first index to use. Default to 0 + /// + ///

For information about creating index buffers, see How to: Create an Index Buffer.

Calling this method using a buffer that is currently bound for writing (i.e. bound to the stream output pipeline stage) will effectively bind null instead because a buffer cannot be bound as both an input and an output at the same time.

The debug layer will generate a warning whenever a resource is prevented from being bound simultaneously as an input and an output, but this will not prevent invalid data from being used by the runtime.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

+ ///
+ /// ff476453 + /// void ID3D11DeviceContext::IASetIndexBuffer([In, Optional] ID3D11Buffer* pIndexBuffer,[In] DXGI_FORMAT Format,[In] unsigned int Offset) + /// ID3D11DeviceContext::IASetIndexBuffer + public void SetIndexBuffer(Buffer indexBuffer, bool is32Bit, int offset = 0) + { + InputAssemblerStage.SetIndexBuffer(indexBuffer, is32Bit ? DXGI.Format.R32_UInt : DXGI.Format.R16_UInt, offset); + } + + /// + /// Sets the vertex input layout. + /// + /// The input layout. + /// ff476454 + /// void ID3D11DeviceContext::IASetInputLayout([In, Optional] ID3D11InputLayout* pInputLayout) + /// ID3D11DeviceContext::IASetInputLayout + public void SetVertexInputLayout(VertexInputLayout inputLayout) + { + currentVertexInputLayout = inputLayout; + } + + /// + /// Bind a vertex buffer on the slot #0 of the input-assembler stage. + /// + /// The vertex buffer to bind to this slot. This vertex buffer must have been created with the flag. + /// The index is the number of vertex element between the first element of a vertex buffer and the first element that will be used. + /// + ///

For information about creating vertex buffers, see Create a Vertex Buffer.

Calling this method using a buffer that is currently bound for writing (i.e. bound to the stream output pipeline stage) will effectively bind null instead because a buffer cannot be bound as both an input and an output at the same time.

The debug layer will generate a warning whenever a resource is prevented from being bound simultaneously as an input and an output, but this will not prevent invalid data from being used by the runtime.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

+ ///
+ /// ff476456 + /// void ID3D11DeviceContext::IASetVertexBuffers([In] unsigned int StartSlot,[In] unsigned int NumBuffers,[In, Buffer] const void* ppVertexBuffers,[In, Buffer] const void* pStrides,[In, Buffer] const void* pOffsets) + /// ID3D11DeviceContext::IASetVertexBuffers + public void SetVertexBuffer(Buffer vertexBuffer, int vertexIndex = 0) where T : struct + { + SetVertexBuffer(0, vertexBuffer, vertexIndex); + } + + /// + /// Bind a vertex buffer to the input-assembler stage. + /// + /// The first input slot for binding. + /// The vertex buffer to bind to this slot. This vertex buffer must have been created with the flag. + /// The index is the number of vertex element between the first element of a vertex buffer and the first element that will be used. + /// + ///

For information about creating vertex buffers, see Create a Vertex Buffer.

Calling this method using a buffer that is currently bound for writing (i.e. bound to the stream output pipeline stage) will effectively bind null instead because a buffer cannot be bound as both an input and an output at the same time.

The debug layer will generate a warning whenever a resource is prevented from being bound simultaneously as an input and an output, but this will not prevent invalid data from being used by the runtime.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

+ ///
+ /// ff476456 + /// void ID3D11DeviceContext::IASetVertexBuffers([In] unsigned int StartSlot,[In] unsigned int NumBuffers,[In, Buffer] const void* ppVertexBuffers,[In, Buffer] const void* pStrides,[In, Buffer] const void* pOffsets) + /// ID3D11DeviceContext::IASetVertexBuffers + public unsafe void SetVertexBuffer(int slot, Buffer vertexBuffer, int vertexIndex = 0) where T : struct + { + IntPtr vertexBufferPtr = IntPtr.Zero; + int stride = Utilities.SizeOf(); + int offset = vertexIndex * stride; + if (vertexBuffer != null) + { + vertexBufferPtr = ((Direct3D11.Buffer)vertexBuffer).NativePointer; + + // Update the index of the last slot buffer bounded, used by ResetVertexBuffers + if ((slot + 1) > maxSlotCountForVertexBuffer) + maxSlotCountForVertexBuffer = slot + 1; + } + InputAssemblerStage.SetVertexBuffers(slot, 1, new IntPtr(&vertexBufferPtr), new IntPtr(&stride), new IntPtr(&offset)); + } + + /// + ///

Bind a vertex buffer to the input-assembler stage.

+ ///
+ /// The first input slot for binding. + /// The vertex buffer to bind to this slot. This vertex buffer must have been created with the flag. + /// The vertexStride is the size (in bytes) of the elements that are to be used from that vertex buffer. + /// The offset is the number of bytes between the first element of a vertex buffer and the first element that will be used. + /// + ///

For information about creating vertex buffers, see Create a Vertex Buffer.

Calling this method using a buffer that is currently bound for writing (i.e. bound to the stream output pipeline stage) will effectively bind null instead because a buffer cannot be bound as both an input and an output at the same time.

The debug layer will generate a warning whenever a resource is prevented from being bound simultaneously as an input and an output, but this will not prevent invalid data from being used by the runtime.

The method will hold a reference to the interfaces passed in. This differs from the device state behavior in Direct3D 10.

+ ///
+ /// ff476456 + /// void ID3D11DeviceContext::IASetVertexBuffers([In] unsigned int StartSlot,[In] unsigned int NumBuffers,[In, Buffer] const void* ppVertexBuffers,[In, Buffer] const void* pStrides,[In, Buffer] const void* pOffsets) + /// ID3D11DeviceContext::IASetVertexBuffers + public unsafe void SetVertexBuffer(int slot, SharpDX.Direct3D11.Buffer vertexBuffer, int vertexStride, int offsetInBytes = 0) + { + IntPtr vertexBufferPtr = IntPtr.Zero; + if (vertexBuffer != null) + { + vertexBufferPtr = vertexBuffer.NativePointer; + + // Update the index of the last slot buffer bounded, used by ResetVertexBuffers + if ((slot + 1) > maxSlotCountForVertexBuffer) + maxSlotCountForVertexBuffer = slot + 1; + } + InputAssemblerStage.SetVertexBuffers(slot, 1, new IntPtr(&vertexBufferPtr), new IntPtr(&vertexStride), new IntPtr(&offsetInBytes)); + } + + /// + /// Resets all vertex buffers bounded to a slot range. By default, It clears all the bounded buffers. See remarks. + /// + /// + /// This is sometimes required to unding explicitly vertex buffers bounding to the input shader assembly, when a + /// vertex buffer is used as the output of the pipeline. + /// + /// ff476456 + /// void ID3D11DeviceContext::IASetVertexBuffers([In] unsigned int StartSlot,[In] unsigned int NumBuffers,[In, Buffer] const void* ppVertexBuffers,[In, Buffer] const void* pStrides,[In, Buffer] const void* pOffsets) + /// ID3D11DeviceContext::IASetVertexBuffers + public void ResetVertexBuffers() + { + if (maxSlotCountForVertexBuffer == 0) + return; + + InputAssemblerStage.SetVertexBuffers(0, maxSlotCountForVertexBuffer, ResetSlotsPointers, ResetSlotsPointers, ResetSlotsPointers); + + maxSlotCountForVertexBuffer = 0; + } + + /// + /// Presents the Backbuffer to the screen. + /// + /// + /// This method is only working if a is set on this device using property. + /// + /// bb174576 + /// HRESULT IDXGISwapChain::Present([In] unsigned int SyncInterval,[In] DXGI_PRESENT_FLAGS Flags) + /// IDXGISwapChain::Present + public void Present() + { + if (IsDeferred) + throw new InvalidOperationException("Cannot use Present on a deferred context"); + + if (Presenter != null) + { + try + { + Presenter.Present(); + } + catch (SharpDXException ex) + { + if (ex.ResultCode == DXGI.ResultCode.DeviceReset || ex.ResultCode == DXGI.ResultCode.DeviceRemoved) + { + // TODO: Implement device reset / removed + } + throw; + } + + } + } + + /// + /// Remove all shaders bounded to each stage. + /// + public void ResetShaderStages() + { + foreach (var commonShaderStage in ShaderStages) + { + commonShaderStage.SetShader(null, null, 0); + } + } + + public static implicit operator Device(GraphicsDevice from) + { + return from == null ? null : from.Device; + } + + public static implicit operator DeviceContext(GraphicsDevice from) + { + return from == null ? null : from.Context; + } + + private void SetupInputLayout() + { + if (CurrentPass == null) + throw new InvalidOperationException("Cannot perform a Draw/Dispatch operation without an EffectPass applied."); + + var inputLayout = CurrentPass.GetInputLayout(currentVertexInputLayout); + InputAssemblerStage.SetInputLayout(inputLayout); + } + + /// + /// A delegate called to create shareable data. See remarks. + /// + /// Type of the data to create. + /// A new instance of the data to share. + /// + /// Because this method is being called from a lock region, this method should not be time consuming. + /// + public delegate T CreateSharedData() where T : IDisposable; + + /// + /// Gets a shared data for this device context with a delegate to create the shared data if it is not present. + /// + /// Type of the shared data to get/create. + /// Type of the data to share. + /// The key of the shared data. + /// The shared data creator. + /// An instance of the shared data. The shared data will be disposed by this instance. + public T GetOrCreateSharedData(SharedDataType type, object key, CreateSharedData sharedDataCreator) where T : IDisposable + { + var dictionary = (type == SharedDataType.PerDevice) ? sharedDataPerDevice : sharedDataPerDeviceContext; + + lock (dictionary) + { + object localValue; + if (!dictionary.TryGetValue(key, out localValue)) + { + localValue = ToDispose(sharedDataCreator()); + dictionary.Add(key, localValue); + } + return (T)localValue; + } + } + + protected override void Dispose(bool disposeManagedResources) + { + if (disposeManagedResources) + { + if (Presenter != null) + { + + // Invalid for WinRT - throwing a "Value does not fall within the expected range" Exception +#if !WIN8METRO + // Make sure that the Presenter is reverted to window before shutting down + // otherwise the Direct3D11.Device will generate an exception on Dispose() + Presenter.IsFullScreen = false; +#endif + Presenter.Dispose(); + Presenter = null; + } + + // dispose EffectPools in reverse order as they will remove themselves from the list + for(var i = EffectPools.Count - 1; i >= 0; i--) + { + EffectPools[i].Dispose(); + } + + EffectPools = null; + } + + base.Dispose(disposeManagedResources); + } + + + /// + /// Gets or create an input signature manager for a particular signature. + /// + /// The signature bytecode. + /// The signature hashcode. + /// + internal InputSignatureManager GetOrCreateInputSignatureManager(byte[] signatureBytecode, int signatureHashcode) + { + var key = new InputSignatureKey(signatureBytecode, signatureHashcode); + + InputSignatureManager signatureManager; + + // Lock all input signatures, as they are shared between all shaders/graphics device instances. + lock (inputSignatureCache) + { + if (!inputSignatureCache.TryGetValue(key, out signatureManager)) + { + signatureManager = ToDispose(new InputSignatureManager(this, signatureBytecode)); + inputSignatureCache.Add(key, signatureManager); + } + } + + return signatureManager; + } + + private void CommonSetRenderTargets(RenderTargetView rtv) + { + currentRenderTargetViews[0] = rtv; + for (int i = 1; i < actualRenderTargetViewCount; i++) + currentRenderTargetViews[i] = null; + actualRenderTargetViewCount = 1; + currentRenderTargetView = rtv; + + // Setup the viewport from the rendertarget view + TextureView textureView; + if (AutoViewportFromRenderTargets && rtv != null && (textureView = rtv.Tag as TextureView) != null) + { + SetViewport(new ViewportF(0, 0, textureView.Width, textureView.Height)); + } + } + + private void CommonSetRenderTargets(RenderTargetView[] rtvs) + { + var rtv0 = rtvs.Length > 0 ? rtvs[0] : null; + for (int i = 0; i < rtvs.Length; i++) + currentRenderTargetViews[i] = rtvs[i]; + for (int i = rtvs.Length; i < actualRenderTargetViewCount; i++) + currentRenderTargetViews[i] = null; + actualRenderTargetViewCount = rtvs.Length; + currentRenderTargetView = rtv0; + + // Setup the viewport from the rendertarget view + TextureView textureView; + if (AutoViewportFromRenderTargets && rtv0 != null && (textureView = rtv0.Tag as TextureView) != null) + { + SetViewport(new ViewportF(0, 0, textureView.Width, textureView.Height)); + } + } + } +} diff --git a/Source/Toolkit/SharpDX.Toolkit.Graphics/Image.cs b/Source/Toolkit/SharpDX.Toolkit.Graphics/Image.cs index 0db2be997..21c45aa24 100644 --- a/Source/Toolkit/SharpDX.Toolkit.Graphics/Image.cs +++ b/Source/Toolkit/SharpDX.Toolkit.Graphics/Image.cs @@ -75,8 +75,8 @@ using System.Runtime.InteropServices; using SharpDX.DXGI; using SharpDX.IO; -using SharpDX.Serialization; using SharpDX.Toolkit.Content; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit.Graphics/ImageDescription.cs b/Source/Toolkit/SharpDX.Toolkit.Graphics/ImageDescription.cs index 79a29a4bc..fc726b083 100644 --- a/Source/Toolkit/SharpDX.Toolkit.Graphics/ImageDescription.cs +++ b/Source/Toolkit/SharpDX.Toolkit.Graphics/ImageDescription.cs @@ -20,8 +20,7 @@ using System; using System.Runtime.InteropServices; - -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit.Graphics/ModelBoneCollection.cs b/Source/Toolkit/SharpDX.Toolkit.Graphics/ModelBoneCollection.cs index 60caf178f..c06e57343 100644 --- a/Source/Toolkit/SharpDX.Toolkit.Graphics/ModelBoneCollection.cs +++ b/Source/Toolkit/SharpDX.Toolkit.Graphics/ModelBoneCollection.cs @@ -21,8 +21,6 @@ using System; using System.Collections.Generic; -using SharpDX.Serialization; - namespace SharpDX.Toolkit.Graphics { public class ModelBoneCollection : List diff --git a/Source/Toolkit/SharpDX.Toolkit.Graphics/ModelMeshCollection.cs b/Source/Toolkit/SharpDX.Toolkit.Graphics/ModelMeshCollection.cs index 975ebfd91..e4d3714bc 100644 --- a/Source/Toolkit/SharpDX.Toolkit.Graphics/ModelMeshCollection.cs +++ b/Source/Toolkit/SharpDX.Toolkit.Graphics/ModelMeshCollection.cs @@ -20,8 +20,6 @@ using System.Collections.Generic; -using SharpDX.Serialization; - namespace SharpDX.Toolkit.Graphics { public class ModelMeshCollection : List diff --git a/Source/Toolkit/SharpDX.Toolkit.Graphics/ModelReader.cs b/Source/Toolkit/SharpDX.Toolkit.Graphics/ModelReader.cs index c472aef44..d5e40df6a 100644 --- a/Source/Toolkit/SharpDX.Toolkit.Graphics/ModelReader.cs +++ b/Source/Toolkit/SharpDX.Toolkit.Graphics/ModelReader.cs @@ -28,7 +28,7 @@ using System.Text.RegularExpressions; using SharpDX.Direct3D11; -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/SharpDX/Collections/ObservableCollection.cs b/Source/Toolkit/SharpDX.Toolkit/Collections/ObservableCollection.cs similarity index 98% rename from Source/SharpDX/Collections/ObservableCollection.cs rename to Source/Toolkit/SharpDX.Toolkit/Collections/ObservableCollection.cs index 873ff799d..1fcc03448 100644 --- a/Source/SharpDX/Collections/ObservableCollection.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Collections/ObservableCollection.cs @@ -21,7 +21,7 @@ using System; using System.Collections.ObjectModel; -namespace SharpDX.Collections +namespace SharpDX.Toolkit.Collections { /// /// An observable collection. diff --git a/Source/SharpDX/Collections/ObservableCollectionEventArgs.cs b/Source/Toolkit/SharpDX.Toolkit/Collections/ObservableCollectionEventArgs.cs similarity index 98% rename from Source/SharpDX/Collections/ObservableCollectionEventArgs.cs rename to Source/Toolkit/SharpDX.Toolkit/Collections/ObservableCollectionEventArgs.cs index 4b5856073..e7eb168b4 100644 --- a/Source/SharpDX/Collections/ObservableCollectionEventArgs.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Collections/ObservableCollectionEventArgs.cs @@ -20,7 +20,7 @@ using System; -namespace SharpDX.Collections +namespace SharpDX.Toolkit.Collections { /// /// An event providing the item changed in a collection (inserted or removed). diff --git a/Source/SharpDX/Collections/ObservableDictionary.cs b/Source/Toolkit/SharpDX.Toolkit/Collections/ObservableDictionary.cs similarity index 99% rename from Source/SharpDX/Collections/ObservableDictionary.cs rename to Source/Toolkit/SharpDX.Toolkit/Collections/ObservableDictionary.cs index b71d1baa2..0cbade9c5 100644 --- a/Source/SharpDX/Collections/ObservableDictionary.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Collections/ObservableDictionary.cs @@ -22,7 +22,7 @@ using System.Collections; using System.Collections.Generic; -namespace SharpDX.Collections +namespace SharpDX.Toolkit.Collections { /// /// An observable dictionary. diff --git a/Source/SharpDX/Collections/ObservableDictionaryEventArgs.cs b/Source/Toolkit/SharpDX.Toolkit/Collections/ObservableDictionaryEventArgs.cs similarity index 98% rename from Source/SharpDX/Collections/ObservableDictionaryEventArgs.cs rename to Source/Toolkit/SharpDX.Toolkit/Collections/ObservableDictionaryEventArgs.cs index 7385b66a0..387db32d3 100644 --- a/Source/SharpDX/Collections/ObservableDictionaryEventArgs.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Collections/ObservableDictionaryEventArgs.cs @@ -21,7 +21,7 @@ using System; using System.Collections.Generic; -namespace SharpDX.Collections +namespace SharpDX.Toolkit.Collections { /// /// Event arguments for the and events. diff --git a/Source/SharpDX/Component.cs b/Source/Toolkit/SharpDX.Toolkit/Component.cs similarity index 97% rename from Source/SharpDX/Component.cs rename to Source/Toolkit/SharpDX.Toolkit/Component.cs index c8b4f6e53..92a0a8fd5 100644 --- a/Source/SharpDX/Component.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Component.cs @@ -1,146 +1,146 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; - -namespace SharpDX -{ - /// - /// A disposable component base class. - /// - public abstract class Component : ComponentBase, IDisposable - { - /// - /// Gets or sets the disposables. - /// - /// The disposables. - protected DisposeCollector DisposeCollector { get; set; } - - /// - /// Initializes a new instance of the class. - /// - protected internal Component() - { - } - - /// - /// Initializes a new instance of the class with an immutable name. - /// - /// The name. - protected Component(string name) : base(name) - { - } - - /// - /// Gets or sets a value indicating whether this instance is attached to a collector. - /// - /// - /// true if this instance is attached to a collector; otherwise, false. - /// - internal bool IsAttached { get; set; } - - /// - /// Gets a value indicating whether this instance is disposed. - /// - /// - /// true if this instance is disposed; otherwise, false. - /// - protected internal bool IsDisposed { get; private set; } - - protected internal bool IsDisposing { get; private set; } - - /// - /// Occurs when when Dispose is called. - /// - public event EventHandler Disposing; - - /// - /// Releases unmanaged and - optionally - managed resources - /// - public void Dispose() - { - if (!IsDisposed) - { - IsDisposing = true; - - // Call the disposing event. - var handler = Disposing; - if (handler != null) - { - handler(this, EventArgs.Empty); - } - - Dispose(true); - IsDisposed = true; - } - } - - /// - /// Disposes of object resources. - /// - /// If true, managed resources should be - /// disposed of in addition to unmanaged resources. - protected virtual void Dispose(bool disposeManagedResources) - { - if (disposeManagedResources) - { - // Dispose all ComObjects - if (DisposeCollector != null) - DisposeCollector.Dispose(); - DisposeCollector = null; - } - } - - /// - /// Adds a disposable object to the list of the objects to dispose. - /// - /// To dispose. - protected internal T ToDispose(T toDisposeArg) - { - if (!ReferenceEquals(toDisposeArg, null)) - { - if (DisposeCollector == null) - DisposeCollector = new DisposeCollector(); - return DisposeCollector.Collect(toDisposeArg); - } - return default(T); - } - - /// - /// Dispose a disposable object and set the reference to null. Removes this object from the ToDispose list. - /// - /// Object to dispose. - protected internal void RemoveAndDispose(ref T objectToDispose) - { - if (!ReferenceEquals(objectToDispose, null) && DisposeCollector != null) - DisposeCollector.RemoveAndDispose(ref objectToDispose); - } - - /// - /// Removes a disposable object to the list of the objects to dispose. - /// - /// - /// To dispose. - protected internal void RemoveToDispose(T toDisposeArg) - { - if (!ReferenceEquals(toDisposeArg, null) && DisposeCollector != null) - DisposeCollector.Remove(toDisposeArg); - } - } +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace SharpDX +{ + /// + /// A disposable component base class. + /// + public abstract class Component : ComponentBase, IDisposable + { + /// + /// Gets or sets the disposables. + /// + /// The disposables. + protected DisposeCollector DisposeCollector { get; set; } + + /// + /// Initializes a new instance of the class. + /// + protected internal Component() + { + } + + /// + /// Initializes a new instance of the class with an immutable name. + /// + /// The name. + protected Component(string name) : base(name) + { + } + + /// + /// Gets or sets a value indicating whether this instance is attached to a collector. + /// + /// + /// true if this instance is attached to a collector; otherwise, false. + /// + internal bool IsAttached { get; set; } + + /// + /// Gets a value indicating whether this instance is disposed. + /// + /// + /// true if this instance is disposed; otherwise, false. + /// + protected internal bool IsDisposed { get; private set; } + + protected internal bool IsDisposing { get; private set; } + + /// + /// Occurs when when Dispose is called. + /// + public event EventHandler Disposing; + + /// + /// Releases unmanaged and - optionally - managed resources + /// + public void Dispose() + { + if (!IsDisposed) + { + IsDisposing = true; + + // Call the disposing event. + var handler = Disposing; + if (handler != null) + { + handler(this, EventArgs.Empty); + } + + Dispose(true); + IsDisposed = true; + } + } + + /// + /// Disposes of object resources. + /// + /// If true, managed resources should be + /// disposed of in addition to unmanaged resources. + protected virtual void Dispose(bool disposeManagedResources) + { + if (disposeManagedResources) + { + // Dispose all ComObjects + if (DisposeCollector != null) + DisposeCollector.Dispose(); + DisposeCollector = null; + } + } + + /// + /// Adds a disposable object to the list of the objects to dispose. + /// + /// To dispose. + protected internal T ToDispose(T toDisposeArg) + { + if (!ReferenceEquals(toDisposeArg, null)) + { + if (DisposeCollector == null) + DisposeCollector = new DisposeCollector(); + return DisposeCollector.Collect(toDisposeArg); + } + return default(T); + } + + /// + /// Dispose a disposable object and set the reference to null. Removes this object from the ToDispose list. + /// + /// Object to dispose. + protected internal void RemoveAndDispose(ref T objectToDispose) + { + if (!ReferenceEquals(objectToDispose, null) && DisposeCollector != null) + DisposeCollector.RemoveAndDispose(ref objectToDispose); + } + + /// + /// Removes a disposable object to the list of the objects to dispose. + /// + /// + /// To dispose. + protected internal void RemoveToDispose(T toDisposeArg) + { + if (!ReferenceEquals(toDisposeArg, null) && DisposeCollector != null) + DisposeCollector.Remove(toDisposeArg); + } + } } \ No newline at end of file diff --git a/Source/SharpDX/ComponentBase.cs b/Source/Toolkit/SharpDX.Toolkit/ComponentBase.cs similarity index 100% rename from Source/SharpDX/ComponentBase.cs rename to Source/Toolkit/SharpDX.Toolkit/ComponentBase.cs diff --git a/Source/SharpDX/ComponentCollection.cs b/Source/Toolkit/SharpDX.Toolkit/ComponentCollection.cs similarity index 100% rename from Source/SharpDX/ComponentCollection.cs rename to Source/Toolkit/SharpDX.Toolkit/ComponentCollection.cs diff --git a/Source/Toolkit/SharpDX.Toolkit/Content/ContentManager.cs b/Source/Toolkit/SharpDX.Toolkit/Content/ContentManager.cs index 20f361b12..45f45c5ca 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Content/ContentManager.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Content/ContentManager.cs @@ -23,6 +23,7 @@ using System.IO; using System.Reflection; using SharpDX.Collections; +using SharpDX.Toolkit.Collections; namespace SharpDX.Toolkit.Content { diff --git a/Source/SharpDX/Diagnostics/CollectionDebugView.cs b/Source/Toolkit/SharpDX.Toolkit/Diagnostics/CollectionDebugView.cs similarity index 98% rename from Source/SharpDX/Diagnostics/CollectionDebugView.cs rename to Source/Toolkit/SharpDX.Toolkit/Diagnostics/CollectionDebugView.cs index 870ae5a01..3d070b368 100644 --- a/Source/SharpDX/Diagnostics/CollectionDebugView.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Diagnostics/CollectionDebugView.cs @@ -23,7 +23,7 @@ using System.Collections.Generic; using System.Diagnostics; -namespace SharpDX.Diagnostics +namespace SharpDX.Toolkit.Diagnostics { /// /// Use to provide a debug view on a custom collection. Use this by adding diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/CommonData.PropertyCollection.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/CommonData.PropertyCollection.cs index 1aa261e3e..006d9a0e4 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/CommonData.PropertyCollection.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/CommonData.PropertyCollection.cs @@ -20,8 +20,7 @@ using System; using System.Collections.Generic; - -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.CompilerArguments.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.CompilerArguments.cs index e11e80adf..f3be51cb4 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.CompilerArguments.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.CompilerArguments.cs @@ -18,8 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System.Collections.Generic; - -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ConstantBuffer.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ConstantBuffer.cs index 053b92e1c..c1c2d8527 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ConstantBuffer.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ConstantBuffer.cs @@ -20,7 +20,7 @@ using System; using System.Collections.Generic; -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Effect.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Effect.cs index 875d1562c..0f6020640 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Effect.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Effect.cs @@ -23,9 +23,9 @@ using System.IO; using SharpDX.IO; using SharpDX.Multimedia; -using SharpDX.Serialization; using SharpDX.Toolkit.Content; using SharpDX.Toolkit.Diagnostics; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Parameter.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Parameter.cs index 002c06925..f4bd0a719 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Parameter.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Parameter.cs @@ -19,7 +19,7 @@ // THE SOFTWARE. using System; -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Pass.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Pass.cs index ea928b63f..471867213 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Pass.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Pass.cs @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Pipeline.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Pipeline.cs index 8b851f89c..51d00afb6 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Pipeline.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Pipeline.cs @@ -20,7 +20,7 @@ using System.Collections; using System.Collections.Generic; -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ResourceParameter.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ResourceParameter.cs index 9914c7451..53d128f9d 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ResourceParameter.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ResourceParameter.cs @@ -19,7 +19,7 @@ // THE SOFTWARE. using System; -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Semantic.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Semantic.cs index 6c251db19..b50a2ea9d 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Semantic.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Semantic.cs @@ -19,7 +19,7 @@ // THE SOFTWARE. using System; -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Shader.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Shader.cs index 087344afc..0bdd73f59 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Shader.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Shader.cs @@ -20,7 +20,7 @@ using System.Collections.Generic; using SharpDX.Direct3D; -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ShaderLink.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ShaderLink.cs index 67390933a..4fe5ac3d6 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ShaderLink.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ShaderLink.cs @@ -21,7 +21,7 @@ using System; using SharpDX.Direct3D11; -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ShaderMacro.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ShaderMacro.cs index 76357437d..fe71e240c 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ShaderMacro.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ShaderMacro.cs @@ -19,7 +19,7 @@ // THE SOFTWARE. using System; -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Signature.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Signature.cs index 4a31c3777..9b51865b6 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Signature.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Signature.cs @@ -19,7 +19,7 @@ // THE SOFTWARE. using System; -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Technique.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Technique.cs index 7e18d6e00..6b898f3e3 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Technique.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.Technique.cs @@ -19,7 +19,7 @@ // THE SOFTWARE. using System.Collections.Generic; -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ValueTypeParameter.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ValueTypeParameter.cs index 54b3d934c..2c8f04e1a 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ValueTypeParameter.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.ValueTypeParameter.cs @@ -19,7 +19,7 @@ // THE SOFTWARE. using System; -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.cs index 0ee04cc9e..1fb456445 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/EffectData.cs @@ -23,9 +23,9 @@ using System.IO; using SharpDX.IO; using SharpDX.Multimedia; -using SharpDX.Serialization; using SharpDX.Toolkit.Content; using SharpDX.Toolkit.Diagnostics; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.Bone.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.Bone.cs index 9f45972cb..39eb21778 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.Bone.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.Bone.cs @@ -19,8 +19,7 @@ // THE SOFTWARE. using System.Collections.Generic; - -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.IndexBuffer.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.IndexBuffer.cs index 534c10137..f1bac41f6 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.IndexBuffer.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.IndexBuffer.cs @@ -19,8 +19,7 @@ // THE SOFTWARE. using System.Collections.Generic; - -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.Material.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.Material.cs index a032535a9..0320b69b0 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.Material.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.Material.cs @@ -19,8 +19,7 @@ // THE SOFTWARE. using System.Collections.Generic; - -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.MaterialTexture.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.MaterialTexture.cs index 41b634fe4..0f32e9ad5 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.MaterialTexture.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.MaterialTexture.cs @@ -19,7 +19,7 @@ // THE SOFTWARE. using SharpDX.Direct3D11; -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.Mesh.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.Mesh.cs index 8d758426e..6fb079f1c 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.Mesh.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.Mesh.cs @@ -20,8 +20,7 @@ using System.Collections.Generic; using System.ComponentModel; - -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.MeshPart.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.MeshPart.cs index d5d88f578..e08d9304f 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.MeshPart.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.MeshPart.cs @@ -20,8 +20,7 @@ using System.Collections.Generic; using System.Runtime.InteropServices; - -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.VertexBuffer.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.VertexBuffer.cs index 81f680ff9..a27cc6714 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.VertexBuffer.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.VertexBuffer.cs @@ -19,8 +19,7 @@ // THE SOFTWARE. using System.Collections.Generic; - -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.cs index e7d049044..f9a3c2316 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/ModelData.cs @@ -1,243 +1,243 @@ -// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.Collections.Generic; -using System.IO; - -using SharpDX.IO; -using SharpDX.Serialization; - -namespace SharpDX.Toolkit.Graphics -{ - /// - /// The model data used to store 3D mesh model. - /// - public sealed partial class ModelData : CommonData, IDataSerializable - { - public const string MagicCode = "TKMD"; - - public const int Version = 0x100; - - /// - /// Initializes a new instance of the class. - /// - public ModelData() - { - Textures = new List(); - Materials = new List(); - Bones = new List(); - // DISABLE_SKINNED_BONES - //SkinnedBones = new List(); - Meshes = new List(); - Attributes = new PropertyCollection(); - } - - /// - /// Gets the maximum buffer size in bytes that will be needed when loading this model. - /// - public int MaximumBufferSizeInBytes; - - /// - /// Embedded textures. - /// - public List Textures; - - /// - /// Gets the material of this model. - /// - public List Materials; - - /// - /// Gets the bones of this model. - /// - public List Bones; - - // DISABLE_SKINNED_BONES - ///// - ///// Gets the bones used to perform skinning animation with this model. - ///// - //public List SkinnedBones; - - /// - /// Gets the mesh of this model. - /// - public List Meshes; - - /// - /// Gets the attributes attached to this instance. - /// - public PropertyCollection Attributes; - - /// - /// Loads a from the specified stream. - /// - /// The stream. - /// A . Null if the stream is not a serialized . - /// - /// - public static ModelData Load(Stream stream) - { - var serializer = GetSerializer(stream, SerializerMode.Read); - try - { - return serializer.Load(); - } - catch (InvalidChunkException chunkException) - { - // If we have an exception of the magiccode, just return null - if (chunkException.ExpectedChunkId == MagicCode) - { - return null; - } - throw; - } - } - - /// - /// Loads a from the specified buffer. - /// - /// The buffer. - /// A - public static ModelData Load(byte[] buffer) - { - return Load(new MemoryStream(buffer)); - } - - /// - /// Loads an from the specified file. - /// - /// The filename. - /// A - public static ModelData Load(string fileName) - { - using (var stream = new NativeFileStream(fileName, NativeFileMode.Open, NativeFileAccess.Read)) - return Load(stream); - } - - /// - /// Saves this instance to the specified stream. - /// - /// The stream. - public void Save(Stream stream) - { - var serializer = GetSerializer(stream, SerializerMode.Write); - serializer.Save(this); - } - - /// - /// Saves this instance to the specified file. - /// - /// The output filename. - public void Save(string fileName) - { - using (var stream = new NativeFileStream(fileName, NativeFileMode.Create, NativeFileAccess.Write, NativeFileShare.Write)) - Save(stream); - } - - private static BinarySerializer GetSerializer(Stream stream, SerializerMode mode) - { - var serializer = new BinarySerializer(stream, mode, Text.Encoding.ASCII); - serializer.ArrayLengthType = ArrayLengthType.Int; - serializer.RegisterDynamicList("MATL"); - return serializer; - } - - /// - void IDataSerializable.Serialize(BinarySerializer serializer) - { - // Starts the whole ModelData by the magiccode "TKMD" - // If the serializer don't find the TKMD, It will throw an - // exception that will be caught by Load method. - - // This code should not be modified without modifying the serialize code in Model. - - serializer.BeginChunk(MagicCode); - - // Writes the version - if (serializer.Mode == SerializerMode.Read) - { - int version = serializer.Reader.ReadInt32(); - if (version != Version) - { - throw new NotSupportedException(string.Format("ModelData version [0x{0:X}] is not supported. Expecting [0x{1:X}]", version, Version)); - } - } - else - { - serializer.Writer.Write(Version); - } - - // Serialize the maximum buffer size used when loading this model. - serializer.Serialize(ref MaximumBufferSizeInBytes); - - // Texture section - serializer.BeginChunk("TEXS"); - if (serializer.Mode == SerializerMode.Read) - { - int textureCount = serializer.Reader.ReadInt32(); - Textures = new List(textureCount); - for (int i = 0; i < textureCount; i++) - { - byte[] textureData = null; - serializer.Serialize(ref textureData); - Textures.Add(textureData); - } - } - else - { - serializer.Writer.Write(Textures.Count); - for (int i = 0; i < Textures.Count; i++) - { - byte[] textureData = Textures[i]; - serializer.Serialize(ref textureData); - } - } - serializer.EndChunk(); - - // Material section - serializer.BeginChunk("MATL"); - serializer.Serialize(ref Materials); - serializer.EndChunk(); - - // Bones section - serializer.BeginChunk("BONE"); - serializer.Serialize(ref Bones); - serializer.EndChunk(); - - //// DISABLE_SKINNED_BONES - //// Skinned Bones section - //serializer.BeginChunk("SKIN"); - //serializer.Serialize(ref SkinnedBones); - //serializer.EndChunk(); - - // Mesh section - serializer.BeginChunk("MESH"); - serializer.Serialize(ref Meshes); - serializer.EndChunk(); - - // Serialize attributes - serializer.Serialize(ref Attributes); - - // Close TKMD section - serializer.EndChunk(); - } - } +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.IO; + +using SharpDX.IO; +using SharpDX.Toolkit.Serialization; + +namespace SharpDX.Toolkit.Graphics +{ + /// + /// The model data used to store 3D mesh model. + /// + public sealed partial class ModelData : CommonData, IDataSerializable + { + public const string MagicCode = "TKMD"; + + public const int Version = 0x100; + + /// + /// Initializes a new instance of the class. + /// + public ModelData() + { + Textures = new List(); + Materials = new List(); + Bones = new List(); + // DISABLE_SKINNED_BONES + //SkinnedBones = new List(); + Meshes = new List(); + Attributes = new PropertyCollection(); + } + + /// + /// Gets the maximum buffer size in bytes that will be needed when loading this model. + /// + public int MaximumBufferSizeInBytes; + + /// + /// Embedded textures. + /// + public List Textures; + + /// + /// Gets the material of this model. + /// + public List Materials; + + /// + /// Gets the bones of this model. + /// + public List Bones; + + // DISABLE_SKINNED_BONES + ///// + ///// Gets the bones used to perform skinning animation with this model. + ///// + //public List SkinnedBones; + + /// + /// Gets the mesh of this model. + /// + public List Meshes; + + /// + /// Gets the attributes attached to this instance. + /// + public PropertyCollection Attributes; + + /// + /// Loads a from the specified stream. + /// + /// The stream. + /// A . Null if the stream is not a serialized . + /// + /// + public static ModelData Load(Stream stream) + { + var serializer = GetSerializer(stream, SerializerMode.Read); + try + { + return serializer.Load(); + } + catch (InvalidChunkException chunkException) + { + // If we have an exception of the magiccode, just return null + if (chunkException.ExpectedChunkId == MagicCode) + { + return null; + } + throw; + } + } + + /// + /// Loads a from the specified buffer. + /// + /// The buffer. + /// A + public static ModelData Load(byte[] buffer) + { + return Load(new MemoryStream(buffer)); + } + + /// + /// Loads an from the specified file. + /// + /// The filename. + /// A + public static ModelData Load(string fileName) + { + using (var stream = new NativeFileStream(fileName, NativeFileMode.Open, NativeFileAccess.Read)) + return Load(stream); + } + + /// + /// Saves this instance to the specified stream. + /// + /// The stream. + public void Save(Stream stream) + { + var serializer = GetSerializer(stream, SerializerMode.Write); + serializer.Save(this); + } + + /// + /// Saves this instance to the specified file. + /// + /// The output filename. + public void Save(string fileName) + { + using (var stream = new NativeFileStream(fileName, NativeFileMode.Create, NativeFileAccess.Write, NativeFileShare.Write)) + Save(stream); + } + + private static BinarySerializer GetSerializer(Stream stream, SerializerMode mode) + { + var serializer = new BinarySerializer(stream, mode, Text.Encoding.ASCII); + serializer.ArrayLengthType = ArrayLengthType.Int; + serializer.RegisterDynamicList("MATL"); + return serializer; + } + + /// + void IDataSerializable.Serialize(BinarySerializer serializer) + { + // Starts the whole ModelData by the magiccode "TKMD" + // If the serializer don't find the TKMD, It will throw an + // exception that will be caught by Load method. + + // This code should not be modified without modifying the serialize code in Model. + + serializer.BeginChunk(MagicCode); + + // Writes the version + if (serializer.Mode == SerializerMode.Read) + { + int version = serializer.Reader.ReadInt32(); + if (version != Version) + { + throw new NotSupportedException(string.Format("ModelData version [0x{0:X}] is not supported. Expecting [0x{1:X}]", version, Version)); + } + } + else + { + serializer.Writer.Write(Version); + } + + // Serialize the maximum buffer size used when loading this model. + serializer.Serialize(ref MaximumBufferSizeInBytes); + + // Texture section + serializer.BeginChunk("TEXS"); + if (serializer.Mode == SerializerMode.Read) + { + int textureCount = serializer.Reader.ReadInt32(); + Textures = new List(textureCount); + for (int i = 0; i < textureCount; i++) + { + byte[] textureData = null; + serializer.Serialize(ref textureData); + Textures.Add(textureData); + } + } + else + { + serializer.Writer.Write(Textures.Count); + for (int i = 0; i < Textures.Count; i++) + { + byte[] textureData = Textures[i]; + serializer.Serialize(ref textureData); + } + } + serializer.EndChunk(); + + // Material section + serializer.BeginChunk("MATL"); + serializer.Serialize(ref Materials); + serializer.EndChunk(); + + // Bones section + serializer.BeginChunk("BONE"); + serializer.Serialize(ref Bones); + serializer.EndChunk(); + + //// DISABLE_SKINNED_BONES + //// Skinned Bones section + //serializer.BeginChunk("SKIN"); + //serializer.Serialize(ref SkinnedBones); + //serializer.EndChunk(); + + // Mesh section + serializer.BeginChunk("MESH"); + serializer.Serialize(ref Meshes); + serializer.EndChunk(); + + // Serialize attributes + serializer.Serialize(ref Attributes); + + // Close TKMD section + serializer.EndChunk(); + } + } } \ No newline at end of file diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.AngelCodeBMFontLoader.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.AngelCodeBMFontLoader.cs index 15bc658ae..ea4a575ce 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.AngelCodeBMFontLoader.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.AngelCodeBMFontLoader.cs @@ -20,7 +20,7 @@ using System; using System.IO; -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.Bitmap.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.Bitmap.cs index 6c9e31a04..0fdd2e390 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.Bitmap.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.Bitmap.cs @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.Glyph.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.Glyph.cs index bad3abe89..b610a3f9a 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.Glyph.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.Glyph.cs @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.Kerning.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.Kerning.cs index 9d26b31ab..dd3272249 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.Kerning.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.Kerning.cs @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.MakeSpriteFontLoader.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.MakeSpriteFontLoader.cs index 26cb892ec..60bc25cf7 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.MakeSpriteFontLoader.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.MakeSpriteFontLoader.cs @@ -21,7 +21,7 @@ using System; using SharpDX.Multimedia; -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.cs index 76b59c636..e3e99d4ad 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/SpriteFontData.cs @@ -22,8 +22,8 @@ using System.IO; using SharpDX.IO; using SharpDX.Multimedia; -using SharpDX.Serialization; using SharpDX.Toolkit.Content; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/Toolkit/SharpDX.Toolkit/Graphics/VertexElement.cs b/Source/Toolkit/SharpDX.Toolkit/Graphics/VertexElement.cs index a097d35ce..4d54959d8 100644 --- a/Source/Toolkit/SharpDX.Toolkit/Graphics/VertexElement.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Graphics/VertexElement.cs @@ -24,7 +24,7 @@ using System.Runtime.InteropServices; using System.Text.RegularExpressions; using SharpDX.DXGI; -using SharpDX.Serialization; +using SharpDX.Toolkit.Serialization; namespace SharpDX.Toolkit.Graphics { diff --git a/Source/SharpDX/IComponent.cs b/Source/Toolkit/SharpDX.Toolkit/IComponent.cs similarity index 100% rename from Source/SharpDX/IComponent.cs rename to Source/Toolkit/SharpDX.Toolkit/IComponent.cs diff --git a/Source/SharpDX/Serialization/IDataSerializable.cs b/Source/Toolkit/SharpDX.Toolkit/IDataSerializable.cs similarity index 96% rename from Source/SharpDX/Serialization/IDataSerializable.cs rename to Source/Toolkit/SharpDX.Toolkit/IDataSerializable.cs index e30e94e41..b20defa07 100644 --- a/Source/SharpDX/Serialization/IDataSerializable.cs +++ b/Source/Toolkit/SharpDX.Toolkit/IDataSerializable.cs @@ -18,7 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -namespace SharpDX.Serialization +using SharpDX.Toolkit.Serialization; + +namespace SharpDX.Toolkit { /// /// Implement this interface to serialize datas with . diff --git a/Source/SharpDX/IServiceRegistry.cs b/Source/Toolkit/SharpDX.Toolkit/IServiceRegistry.cs similarity index 100% rename from Source/SharpDX/IServiceRegistry.cs rename to Source/Toolkit/SharpDX.Toolkit/IServiceRegistry.cs diff --git a/Source/SharpDX/IdentityEqualityComparer.cs b/Source/Toolkit/SharpDX.Toolkit/IdentityEqualityComparer.cs similarity index 100% rename from Source/SharpDX/IdentityEqualityComparer.cs rename to Source/Toolkit/SharpDX.Toolkit/IdentityEqualityComparer.cs diff --git a/Source/SharpDX/Serialization/ArrayLengthType.cs b/Source/Toolkit/SharpDX.Toolkit/Serialization/ArrayLengthType.cs similarity index 98% rename from Source/SharpDX/Serialization/ArrayLengthType.cs rename to Source/Toolkit/SharpDX.Toolkit/Serialization/ArrayLengthType.cs index e26a9a9b0..fea6aa215 100644 --- a/Source/SharpDX/Serialization/ArrayLengthType.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Serialization/ArrayLengthType.cs @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -namespace SharpDX.Serialization +namespace SharpDX.Toolkit.Serialization { /// /// Specify the size used for encoding length for array while using a , just before an array is encoded. diff --git a/Source/SharpDX/Serialization/BinarySerializer.cs b/Source/Toolkit/SharpDX.Toolkit/Serialization/BinarySerializer.cs similarity index 99% rename from Source/SharpDX/Serialization/BinarySerializer.cs rename to Source/Toolkit/SharpDX.Toolkit/Serialization/BinarySerializer.cs index 26c2353a6..5cda57fcb 100644 --- a/Source/SharpDX/Serialization/BinarySerializer.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Serialization/BinarySerializer.cs @@ -17,15 +17,15 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + using System; using System.Collections.Generic; using System.IO; using System.Text; using SharpDX.IO; using SharpDX.Multimedia; -using System.Reflection; -namespace SharpDX.Serialization +namespace SharpDX.Toolkit.Serialization { /// /// Serializer action. @@ -351,7 +351,7 @@ public bool AllowIdentity /// Begin to serialize a a new chunk. /// /// The chunk id. - /// If the chuck to read is not the expecting chunk. + /// If the chuck to read is not the expecting chunk. /// /// A Chunk is an identifiable portion of data that will serialized. Chunk are useful to encapsulate a variable /// data (and check for the presence of the chunk Id). Chunk are storing a 4 bytes identifier and the length of diff --git a/Source/SharpDX/Serialization/DynamicSerializerAttribute.cs b/Source/Toolkit/SharpDX.Toolkit/Serialization/DynamicSerializerAttribute.cs similarity index 98% rename from Source/SharpDX/Serialization/DynamicSerializerAttribute.cs rename to Source/Toolkit/SharpDX.Toolkit/Serialization/DynamicSerializerAttribute.cs index e2e964879..62593f9b7 100644 --- a/Source/SharpDX/Serialization/DynamicSerializerAttribute.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Serialization/DynamicSerializerAttribute.cs @@ -17,10 +17,11 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + using System; using SharpDX.Multimedia; -namespace SharpDX.Serialization +namespace SharpDX.Toolkit.Serialization { /// /// Use this attribute to specify the id of a dynamic type with . diff --git a/Source/SharpDX/Serialization/InvalidChunkException.cs b/Source/Toolkit/SharpDX.Toolkit/Serialization/InvalidChunkException.cs similarity index 98% rename from Source/SharpDX/Serialization/InvalidChunkException.cs rename to Source/Toolkit/SharpDX.Toolkit/Serialization/InvalidChunkException.cs index 43820fd06..d841a5050 100644 --- a/Source/SharpDX/Serialization/InvalidChunkException.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Serialization/InvalidChunkException.cs @@ -21,7 +21,7 @@ using System; using SharpDX.Multimedia; -namespace SharpDX.Serialization +namespace SharpDX.Toolkit.Serialization { /// /// Exceptions thrown when an invalid chunk is decoded. diff --git a/Source/SharpDX/Serialization/NamespaceDoc.cs b/Source/Toolkit/SharpDX.Toolkit/Serialization/NamespaceDoc.cs similarity index 97% rename from Source/SharpDX/Serialization/NamespaceDoc.cs rename to Source/Toolkit/SharpDX.Toolkit/Serialization/NamespaceDoc.cs index a0e5795bc..74c56c2c1 100644 --- a/Source/SharpDX/Serialization/NamespaceDoc.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Serialization/NamespaceDoc.cs @@ -17,7 +17,7 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -namespace SharpDX.Serialization +namespace SharpDX.Toolkit.Serialization { /// /// The namespace contains a serialization API. diff --git a/Source/SharpDX/Serialization/SerializeFlags.cs b/Source/Toolkit/SharpDX.Toolkit/Serialization/SerializeFlags.cs similarity index 97% rename from Source/SharpDX/Serialization/SerializeFlags.cs rename to Source/Toolkit/SharpDX.Toolkit/Serialization/SerializeFlags.cs index a7a87ae7f..9d4cf9cf9 100644 --- a/Source/SharpDX/Serialization/SerializeFlags.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Serialization/SerializeFlags.cs @@ -18,10 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. - using System; -namespace SharpDX.Serialization +namespace SharpDX.Toolkit.Serialization { /// /// Flags used when serializing a value with a . diff --git a/Source/SharpDX/Serialization/SerializerMode.cs b/Source/Toolkit/SharpDX.Toolkit/Serialization/SerializerMode.cs similarity index 97% rename from Source/SharpDX/Serialization/SerializerMode.cs rename to Source/Toolkit/SharpDX.Toolkit/Serialization/SerializerMode.cs index 259efe431..ab647e3ea 100644 --- a/Source/SharpDX/Serialization/SerializerMode.cs +++ b/Source/Toolkit/SharpDX.Toolkit/Serialization/SerializerMode.cs @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -namespace SharpDX.Serialization +namespace SharpDX.Toolkit.Serialization { /// /// Serialization mode used by . diff --git a/Source/Toolkit/SharpDX.Toolkit/SharpDX.Toolkit.csproj b/Source/Toolkit/SharpDX.Toolkit/SharpDX.Toolkit.csproj index d99988131..5c8ebb3ef 100644 --- a/Source/Toolkit/SharpDX.Toolkit/SharpDX.Toolkit.csproj +++ b/Source/Toolkit/SharpDX.Toolkit/SharpDX.Toolkit.csproj @@ -14,6 +14,13 @@ + + + + + + + @@ -24,6 +31,7 @@ + @@ -31,6 +39,9 @@ + + + @@ -84,6 +95,16 @@ + + + + + + + + + + @@ -95,6 +116,10 @@ SharpDX.DXGI False + + {49e4485f-3a2a-4c35-a159-12eccfc00396} + SharpDX.Mathematics + {d0bcd56a-41c4-4a4e-8590-26864ced07ff} SharpDX diff --git a/Source/SharpDX/SingletonString.cs b/Source/Toolkit/SharpDX.Toolkit/SingletonString.cs similarity index 93% rename from Source/SharpDX/SingletonString.cs rename to Source/Toolkit/SharpDX.Toolkit/SingletonString.cs index 4073e1f33..e4da157c5 100644 --- a/Source/SharpDX/SingletonString.cs +++ b/Source/Toolkit/SharpDX.Toolkit/SingletonString.cs @@ -19,7 +19,6 @@ // THE SOFTWARE. using System; -using SharpDX.Serialization; namespace SharpDX { @@ -31,7 +30,7 @@ namespace SharpDX /// could be invoked frequently, and the set of strings is limited. Internally, /// string is using the method and also is precaching the hashcode of the string. /// - public struct SingletonString : IEquatable, IDataSerializable + public struct SingletonString : IEquatable { private int hashCode; private string text; @@ -67,14 +66,6 @@ public override int GetHashCode() return hashCode; } - public void Serialize(BinarySerializer serializer) - { - serializer.Serialize(ref text, SerializeFlags.Nullable); - - if (serializer.Mode == SerializerMode.Read) - hashCode = text != null ? text.GetHashCode() : 0; - } - /// /// Implements the operator ==. /// diff --git a/Source/SharpDX/Threading/TaskUtil.cs b/Source/Toolkit/SharpDX.Toolkit/Threading/TaskUtil.cs similarity index 100% rename from Source/SharpDX/Threading/TaskUtil.cs rename to Source/Toolkit/SharpDX.Toolkit/Threading/TaskUtil.cs