diff --git a/build/Stride.sln b/build/Stride.sln index bac0ead5e1..23a5f1c92e 100644 --- a/build/Stride.sln +++ b/build/Stride.sln @@ -28,8 +28,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "00-Targets.Private", "00-Ta EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "80-Shaders", "80-Shaders", "{10D145AF-C8AE-428F-A80F-CA1B591D0DB2}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3D-Exporters", "3D-Exporters", "{47FFA9CA-781D-427E-9A41-365D789DD4B1}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "50-Presentation", "50-Presentation", "{75A820AB-0F21-40F2-9448-5D7F495B97A0}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Internals", "Internals", "{860946E4-CC77-4FDA-A4FD-3DB2A502A696}" @@ -97,8 +95,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.Core.Presentation", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.Core.Presentation.Tests", "..\sources\presentation\Stride.Core.Presentation.Tests\Stride.Core.Presentation.Tests.csproj", "{C223FCD7-CDCC-4943-9E11-9C2CC8FA9FC4}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Stride.Importer.Assimp", "..\sources\tools\Stride.Importer.Assimp\Stride.Importer.Assimp.vcxproj", "{C2306552-6C42-464C-8981-32FEF4F9458D}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Irony", "..\sources\shaders\Irony\Irony.csproj", "{D81F5C91-D7DB-46E5-BC99-49488FB6814C}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.Games", "..\sources\engine\Stride.Games\Stride.Games.csproj", "{42780CBD-3FE7-48E3-BD5B-59945EA20137}" @@ -111,14 +107,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.ProjectGenerator", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.Audio.Tests.Windows", "..\sources\engine\Stride.Audio.Tests\Stride.Audio.Tests.Windows.csproj", "{7AF4B563-AAD3-42FF-B91E-84B9D34D904A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.Assimp", "..\sources\tools\Stride.Assimp\Stride.Assimp.csproj", "{F61D86B5-7C3D-4441-957D-A0A6D2FA69CA}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.Core.BuildEngine.Tests", "..\sources\buildengine\Stride.Core.BuildEngine.Tests\Stride.Core.BuildEngine.Tests.csproj", "{09F32307-595A-4CBB-BF7C-F055DA1F70EE}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.Core.BuildEngine.Common", "..\sources\buildengine\Stride.Core.BuildEngine.Common\Stride.Core.BuildEngine.Common.csproj", "{7732CB84-A39A-4ADF-B740-FD32A352FA8A}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Stride.Assimp.Translation", "..\sources\tools\Stride.Assimp.Translation\Stride.Assimp.Translation.vcxproj", "{FCDF1B87-1C76-46EB-AD6A-D55EF5F195B8}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.Core", "..\sources\core\Stride.Core\Stride.Core.csproj", "{0E916AB7-5A6C-4820-8AB1-AA492FE66D68}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.Core.Mathematics", "..\sources\core\Stride.Core.Mathematics\Stride.Core.Mathematics.csproj", "{1677B922-CCF0-44DE-B57E-1CDD3D2B8E8A}" @@ -177,8 +169,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.Core.Design", "..\so EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.Graphics.Regression", "..\sources\engine\Stride.Graphics.Regression\Stride.Graphics.Regression.csproj", "{D002FEB1-00A6-4AB1-A83F-1F253465E64D}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Stride.Importer.Common", "..\sources\tools\Stride.Importer.Common\Stride.Importer.Common.vcxproj", "{43A6E62E-1B1C-4630-ABB8-C3F716004645}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.StorageTool", "..\sources\tools\Stride.StorageTool\Stride.StorageTool.csproj", "{942A5B1D-2B3D-4B30-98DE-336CE93F4F12}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.Core.ProjectTemplating", "..\sources\tools\Stride.Core.ProjectTemplating\Stride.Core.ProjectTemplating.csproj", "{2E2382F7-9576-49F0-AE43-93AFD7DB2368}" @@ -321,6 +311,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.NuGetLoader", "..\so EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.Engine.NoAssets.Tests.Windows", "..\sources\engine\Stride.Engine.NoAssets.Tests\Stride.Engine.NoAssets.Tests.Windows.csproj", "{1C94168A-3C0D-4C6B-883B-91627D2EF3A1}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.Importer.Assimp", "..\sources\tools\Stride.Importer.Assimp\Stride.Importer.Assimp.csproj", "{967BA05D-4AC4-4848-AEFD-894EF2309E4D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stride.Importer.Common", "..\sources\tools\Stride.Importer.Common\Stride.Importer.Common.csproj", "{806AA078-6070-4BB6-B05B-6EE6B21B1CDE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -432,16 +426,6 @@ Global {C223FCD7-CDCC-4943-9E11-9C2CC8FA9FC4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {C223FCD7-CDCC-4943-9E11-9C2CC8FA9FC4}.Release|Mixed Platforms.Build.0 = Release|Any CPU {C223FCD7-CDCC-4943-9E11-9C2CC8FA9FC4}.Release|Win32.ActiveCfg = Release|Any CPU - {C2306552-6C42-464C-8981-32FEF4F9458D}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {C2306552-6C42-464C-8981-32FEF4F9458D}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {C2306552-6C42-464C-8981-32FEF4F9458D}.Debug|Mixed Platforms.Build.0 = Debug|x64 - {C2306552-6C42-464C-8981-32FEF4F9458D}.Debug|Win32.ActiveCfg = Debug|Win32 - {C2306552-6C42-464C-8981-32FEF4F9458D}.Debug|Win32.Build.0 = Debug|Win32 - {C2306552-6C42-464C-8981-32FEF4F9458D}.Release|Any CPU.ActiveCfg = Release|Win32 - {C2306552-6C42-464C-8981-32FEF4F9458D}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {C2306552-6C42-464C-8981-32FEF4F9458D}.Release|Mixed Platforms.Build.0 = Release|x64 - {C2306552-6C42-464C-8981-32FEF4F9458D}.Release|Win32.ActiveCfg = Release|Win32 - {C2306552-6C42-464C-8981-32FEF4F9458D}.Release|Win32.Build.0 = Release|Win32 {D81F5C91-D7DB-46E5-BC99-49488FB6814C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D81F5C91-D7DB-46E5-BC99-49488FB6814C}.Debug|Any CPU.Build.0 = Debug|Any CPU {D81F5C91-D7DB-46E5-BC99-49488FB6814C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -500,14 +484,6 @@ Global {7AF4B563-AAD3-42FF-B91E-84B9D34D904A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {7AF4B563-AAD3-42FF-B91E-84B9D34D904A}.Release|Mixed Platforms.Build.0 = Release|Any CPU {7AF4B563-AAD3-42FF-B91E-84B9D34D904A}.Release|Win32.ActiveCfg = Release|Any CPU - {F61D86B5-7C3D-4441-957D-A0A6D2FA69CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F61D86B5-7C3D-4441-957D-A0A6D2FA69CA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {F61D86B5-7C3D-4441-957D-A0A6D2FA69CA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {F61D86B5-7C3D-4441-957D-A0A6D2FA69CA}.Debug|Win32.ActiveCfg = Debug|Any CPU - {F61D86B5-7C3D-4441-957D-A0A6D2FA69CA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F61D86B5-7C3D-4441-957D-A0A6D2FA69CA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {F61D86B5-7C3D-4441-957D-A0A6D2FA69CA}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {F61D86B5-7C3D-4441-957D-A0A6D2FA69CA}.Release|Win32.ActiveCfg = Release|Any CPU {09F32307-595A-4CBB-BF7C-F055DA1F70EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {09F32307-595A-4CBB-BF7C-F055DA1F70EE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {09F32307-595A-4CBB-BF7C-F055DA1F70EE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU @@ -524,16 +500,6 @@ Global {7732CB84-A39A-4ADF-B740-FD32A352FA8A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {7732CB84-A39A-4ADF-B740-FD32A352FA8A}.Release|Mixed Platforms.Build.0 = Release|Any CPU {7732CB84-A39A-4ADF-B740-FD32A352FA8A}.Release|Win32.ActiveCfg = Release|Any CPU - {FCDF1B87-1C76-46EB-AD6A-D55EF5F195B8}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {FCDF1B87-1C76-46EB-AD6A-D55EF5F195B8}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {FCDF1B87-1C76-46EB-AD6A-D55EF5F195B8}.Debug|Mixed Platforms.Build.0 = Debug|x64 - {FCDF1B87-1C76-46EB-AD6A-D55EF5F195B8}.Debug|Win32.ActiveCfg = Debug|Win32 - {FCDF1B87-1C76-46EB-AD6A-D55EF5F195B8}.Debug|Win32.Build.0 = Debug|Win32 - {FCDF1B87-1C76-46EB-AD6A-D55EF5F195B8}.Release|Any CPU.ActiveCfg = Release|Win32 - {FCDF1B87-1C76-46EB-AD6A-D55EF5F195B8}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {FCDF1B87-1C76-46EB-AD6A-D55EF5F195B8}.Release|Mixed Platforms.Build.0 = Release|x64 - {FCDF1B87-1C76-46EB-AD6A-D55EF5F195B8}.Release|Win32.ActiveCfg = Release|Win32 - {FCDF1B87-1C76-46EB-AD6A-D55EF5F195B8}.Release|Win32.Build.0 = Release|Win32 {0E916AB7-5A6C-4820-8AB1-AA492FE66D68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0E916AB7-5A6C-4820-8AB1-AA492FE66D68}.Debug|Any CPU.Build.0 = Debug|Any CPU {0E916AB7-5A6C-4820-8AB1-AA492FE66D68}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -824,16 +790,6 @@ Global {D002FEB1-00A6-4AB1-A83F-1F253465E64D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {D002FEB1-00A6-4AB1-A83F-1F253465E64D}.Release|Mixed Platforms.Build.0 = Release|Any CPU {D002FEB1-00A6-4AB1-A83F-1F253465E64D}.Release|Win32.ActiveCfg = Release|Any CPU - {43A6E62E-1B1C-4630-ABB8-C3F716004645}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {43A6E62E-1B1C-4630-ABB8-C3F716004645}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {43A6E62E-1B1C-4630-ABB8-C3F716004645}.Debug|Mixed Platforms.Build.0 = Debug|x64 - {43A6E62E-1B1C-4630-ABB8-C3F716004645}.Debug|Win32.ActiveCfg = Debug|Win32 - {43A6E62E-1B1C-4630-ABB8-C3F716004645}.Debug|Win32.Build.0 = Debug|Win32 - {43A6E62E-1B1C-4630-ABB8-C3F716004645}.Release|Any CPU.ActiveCfg = Release|Win32 - {43A6E62E-1B1C-4630-ABB8-C3F716004645}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {43A6E62E-1B1C-4630-ABB8-C3F716004645}.Release|Mixed Platforms.Build.0 = Release|x64 - {43A6E62E-1B1C-4630-ABB8-C3F716004645}.Release|Win32.ActiveCfg = Release|Win32 - {43A6E62E-1B1C-4630-ABB8-C3F716004645}.Release|Win32.Build.0 = Release|Win32 {942A5B1D-2B3D-4B30-98DE-336CE93F4F12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {942A5B1D-2B3D-4B30-98DE-336CE93F4F12}.Debug|Any CPU.Build.0 = Debug|Any CPU {942A5B1D-2B3D-4B30-98DE-336CE93F4F12}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -1422,12 +1378,35 @@ Global {1C94168A-3C0D-4C6B-883B-91627D2EF3A1}.Release|Mixed Platforms.Build.0 = Release|Any CPU {1C94168A-3C0D-4C6B-883B-91627D2EF3A1}.Release|Win32.ActiveCfg = Release|Any CPU {1C94168A-3C0D-4C6B-883B-91627D2EF3A1}.Release|Win32.Build.0 = Release|Any CPU + {967BA05D-4AC4-4848-AEFD-894EF2309E4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {967BA05D-4AC4-4848-AEFD-894EF2309E4D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {967BA05D-4AC4-4848-AEFD-894EF2309E4D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {967BA05D-4AC4-4848-AEFD-894EF2309E4D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {967BA05D-4AC4-4848-AEFD-894EF2309E4D}.Debug|Win32.ActiveCfg = Debug|Any CPU + {967BA05D-4AC4-4848-AEFD-894EF2309E4D}.Debug|Win32.Build.0 = Debug|Any CPU + {967BA05D-4AC4-4848-AEFD-894EF2309E4D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {967BA05D-4AC4-4848-AEFD-894EF2309E4D}.Release|Any CPU.Build.0 = Release|Any CPU + {967BA05D-4AC4-4848-AEFD-894EF2309E4D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {967BA05D-4AC4-4848-AEFD-894EF2309E4D}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {967BA05D-4AC4-4848-AEFD-894EF2309E4D}.Release|Win32.ActiveCfg = Release|Any CPU + {967BA05D-4AC4-4848-AEFD-894EF2309E4D}.Release|Win32.Build.0 = Release|Any CPU + {806AA078-6070-4BB6-B05B-6EE6B21B1CDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {806AA078-6070-4BB6-B05B-6EE6B21B1CDE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {806AA078-6070-4BB6-B05B-6EE6B21B1CDE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {806AA078-6070-4BB6-B05B-6EE6B21B1CDE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {806AA078-6070-4BB6-B05B-6EE6B21B1CDE}.Debug|Win32.ActiveCfg = Debug|Any CPU + {806AA078-6070-4BB6-B05B-6EE6B21B1CDE}.Debug|Win32.Build.0 = Debug|Any CPU + {806AA078-6070-4BB6-B05B-6EE6B21B1CDE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {806AA078-6070-4BB6-B05B-6EE6B21B1CDE}.Release|Any CPU.Build.0 = Release|Any CPU + {806AA078-6070-4BB6-B05B-6EE6B21B1CDE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {806AA078-6070-4BB6-B05B-6EE6B21B1CDE}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {806AA078-6070-4BB6-B05B-6EE6B21B1CDE}.Release|Win32.ActiveCfg = Release|Any CPU + {806AA078-6070-4BB6-B05B-6EE6B21B1CDE}.Release|Win32.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {47FFA9CA-781D-427E-9A41-365D789DD4B1} = {1AE1AC60-5D2F-4CA7-AE20-888F44551185} {860946E4-CC77-4FDA-A4FD-3DB2A502A696} = {1AE1AC60-5D2F-4CA7-AE20-888F44551185} {6F473FA6-4F8B-4FBA-AE33-EE5AF997D50C} = {1AE1AC60-5D2F-4CA7-AE20-888F44551185} {4A15BAAD-AA37-4754-A2BF-8D4049211E36} = {1AE1AC60-5D2F-4CA7-AE20-888F44551185} @@ -1442,17 +1421,14 @@ Global {F2D52EDB-BC17-4243-B06D-33CD20F87A7F} = {10D145AF-C8AE-428F-A80F-CA1B591D0DB2} {47AFCC2E-E9F0-47D6-9D75-9E646546A92B} = {75A820AB-0F21-40F2-9448-5D7F495B97A0} {C223FCD7-CDCC-4943-9E11-9C2CC8FA9FC4} = {52AE329E-B588-40D0-A578-8D0DB1BD83E5} - {C2306552-6C42-464C-8981-32FEF4F9458D} = {6F473FA6-4F8B-4FBA-AE33-EE5AF997D50C} {D81F5C91-D7DB-46E5-BC99-49488FB6814C} = {10D145AF-C8AE-428F-A80F-CA1B591D0DB2} {42780CBD-3FE7-48E3-BD5B-59945EA20137} = {4C142567-C42B-40F5-B092-798882190209} {7F7BFF79-C400-435F-B359-56A2EF8956E0} = {4A15BAAD-AA37-4754-A2BF-8D4049211E36} {C485CE61-3006-4C99-ACB3-A737F5CEBAE7} = {4A15BAAD-AA37-4754-A2BF-8D4049211E36} {4B299721-18EA-4B6D-AFD5-2D6E188B97BD} = {860946E4-CC77-4FDA-A4FD-3DB2A502A696} {7AF4B563-AAD3-42FF-B91E-84B9D34D904A} = {A7ED9F01-7D78-4381-90A6-D50E51C17250} - {F61D86B5-7C3D-4441-957D-A0A6D2FA69CA} = {47FFA9CA-781D-427E-9A41-365D789DD4B1} {09F32307-595A-4CBB-BF7C-F055DA1F70EE} = {B175D318-B4D0-49EA-9AEF-A54ACA2F03DC} {7732CB84-A39A-4ADF-B740-FD32A352FA8A} = {25F10A0B-7259-404C-86BE-FD2363C92F72} - {FCDF1B87-1C76-46EB-AD6A-D55EF5F195B8} = {47FFA9CA-781D-427E-9A41-365D789DD4B1} {0E916AB7-5A6C-4820-8AB1-AA492FE66D68} = {2E93E2B5-4500-4E47-9B65-E705218AB578} {1677B922-CCF0-44DE-B57E-1CDD3D2B8E8A} = {2E93E2B5-4500-4E47-9B65-E705218AB578} {5210FB81-B807-49BB-AF0D-31FB6A83A572} = {2E93E2B5-4500-4E47-9B65-E705218AB578} @@ -1482,7 +1458,6 @@ Global {0EA748AF-E1DC-4788-BA50-8BABD56F220C} = {F5F744B5-803E-4180-B82A-8B1F0BCD6579} {66581DAD-70AD-4475-AE47-C6C0DF1EC5E2} = {25F10A0B-7259-404C-86BE-FD2363C92F72} {D002FEB1-00A6-4AB1-A83F-1F253465E64D} = {A7ED9F01-7D78-4381-90A6-D50E51C17250} - {43A6E62E-1B1C-4630-ABB8-C3F716004645} = {6F473FA6-4F8B-4FBA-AE33-EE5AF997D50C} {942A5B1D-2B3D-4B30-98DE-336CE93F4F12} = {860946E4-CC77-4FDA-A4FD-3DB2A502A696} {2E2382F7-9576-49F0-AE43-93AFD7DB2368} = {860946E4-CC77-4FDA-A4FD-3DB2A502A696} {550C1B7C-B7AD-46DF-ACF3-C36AEF35D5FF} = {5D2D3BE8-9910-45CA-8E45-95660DA4C563} @@ -1543,6 +1518,8 @@ Global {D5B023BE-010F-44A8-ABF1-DB6F3BCEA392} = {1AE1AC60-5D2F-4CA7-AE20-888F44551185} {7FA381C8-8EBE-4515-969D-01369CC47D0E} = {1AE1AC60-5D2F-4CA7-AE20-888F44551185} {1C94168A-3C0D-4C6B-883B-91627D2EF3A1} = {A7ED9F01-7D78-4381-90A6-D50E51C17250} + {967BA05D-4AC4-4848-AEFD-894EF2309E4D} = {6F473FA6-4F8B-4FBA-AE33-EE5AF997D50C} + {806AA078-6070-4BB6-B05B-6EE6B21B1CDE} = {6F473FA6-4F8B-4FBA-AE33-EE5AF997D50C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {FF877973-604D-4EA7-B5F5-A129961F9EF2} diff --git a/sources/engine/Stride.Assets.Models/AssimpAssetImporter.cs b/sources/engine/Stride.Assets.Models/AssimpAssetImporter.cs index 844a43a29a..c93a2bf707 100644 --- a/sources/engine/Stride.Assets.Models/AssimpAssetImporter.cs +++ b/sources/engine/Stride.Assets.Models/AssimpAssetImporter.cs @@ -14,11 +14,6 @@ namespace Stride.Assets.Models { public class AssimpAssetImporter : ModelAssetImporter { - static AssimpAssetImporter() - { - NativeLibraryHelper.PreloadLibrary("assimp-vc140-mt", typeof(AssimpAssetImporter)); - } - // Supported file extensions for this importer internal const string FileExtensions = ".dae;.3ds;.gltf;.glb;.obj;.blend;.x;.md2;.md3;.dxf;.ply;.stl;.stp"; @@ -33,7 +28,7 @@ static AssimpAssetImporter() /// public override EntityInfo GetEntityInfo(UFile localPath, Logger logger, AssetImporterParameters importParameters) { - var meshConverter = new Importer.AssimpNET.MeshConverter(logger); + var meshConverter = new Importer.Assimp.MeshConverter(logger); if (!importParameters.InputParameters.TryGet(DeduplicateMaterialsKey, out var deduplicateMaterials)) deduplicateMaterials = true; // Dedupe is the default value @@ -45,7 +40,7 @@ public override EntityInfo GetEntityInfo(UFile localPath, Logger logger, AssetIm /// public override void GetAnimationDuration(UFile localPath, Logger logger, AssetImporterParameters importParameters, out TimeSpan startTime, out TimeSpan endTime) { - var meshConverter = new Importer.AssimpNET.MeshConverter(logger); + var meshConverter = new Importer.Assimp.MeshConverter(logger); var sceneData = meshConverter.ConvertAnimation(localPath.FullPath, ""); startTime = CompressedTimeSpan.MaxValue; // This will go down, so we start from positive infinity diff --git a/sources/engine/Stride.Assets.Models/ImportAssimpCommand.cs b/sources/engine/Stride.Assets.Models/ImportAssimpCommand.cs index a522c3e9fa..0d68167f98 100644 --- a/sources/engine/Stride.Assets.Models/ImportAssimpCommand.cs +++ b/sources/engine/Stride.Assets.Models/ImportAssimpCommand.cs @@ -32,9 +32,9 @@ public static bool IsSupportingExtensions(string ext) return supportedExtensions.Any(supExt => supExt.Equals(extToLower)); } - private Stride.Importer.AssimpNET.MeshConverter CreateMeshConverter(ICommandContext commandContext) + private Stride.Importer.Assimp.MeshConverter CreateMeshConverter(ICommandContext commandContext) { - return new Stride.Importer.AssimpNET.MeshConverter(commandContext.Logger) + return new Stride.Importer.Assimp.MeshConverter(commandContext.Logger) { AllowUnsignedBlendIndices = this.AllowUnsignedBlendIndices, }; diff --git a/sources/engine/Stride.Assets.Models/Stride.Assets.Models.csproj b/sources/engine/Stride.Assets.Models/Stride.Assets.Models.csproj index a3bc6ce336..34225584fe 100644 --- a/sources/engine/Stride.Assets.Models/Stride.Assets.Models.csproj +++ b/sources/engine/Stride.Assets.Models/Stride.Assets.Models.csproj @@ -13,10 +13,8 @@ - - - - + + @@ -34,10 +32,7 @@ - - - @@ -46,7 +41,6 @@ - diff --git a/sources/tools/Stride.Assimp.Translation/Extension.h b/sources/tools/Stride.Assimp.Translation/Extension.h deleted file mode 100644 index cf5783f4f3..0000000000 --- a/sources/tools/Stride.Assimp.Translation/Extension.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) -// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. -#pragma once - -#include - -#define _AI_MATKEY_TEXTYPE_BASE "$tex.type" -#define _AI_MATKEY_TEXCOLOR_BASE "$tex.color" -#define _AI_MATKEY_TEXALPHA_BASE "$tex.alpha" - -#define AI_MATKEY_TEXTYPE(type, N) _AI_MATKEY_TEXTYPE_BASE,type,N -#define AI_MATKEY_TEXCOLOR(type,N) _AI_MATKEY_TEXCOLOR_BASE,type,N -#define AI_MATKEY_TEXALPHA(type,N) _AI_MATKEY_TEXALPHA_BASE,type,N - -/// -/// Enumeration of the different types of node in the new Assimp's material stack. -/// Don't forget to update the dictionnary in Materials.cpp when modifying this enum. -/// -enum aiStackType { - aiStackType_ColorType, - aiStackType_TextureType, - aiStackType_BlendOpType, - aiStackType_NumberTypes -}; -/// -/// Enumeration of the new Assimp's flags. -/// -enum aiStackFlags { - aiStackFlags_Invert = 1, - aiStackFlags_ReplaceAlpha = 2 -}; -#define aiStackFlags_NumbeFlags 2 -/// -/// Enumeration of the different operations in the new Assimp's material stack. -/// Don't forget to update the dictionnary in Materials.cpp when modifying this enum. -/// -enum aiStackOperation { - aiStackOperation_Add = 0, - aiStackOperation_Add3ds, - aiStackOperation_AddMaya, - aiStackOperation_Average, - aiStackOperation_Color, - aiStackOperation_ColorBurn, - aiStackOperation_ColorDodge, - aiStackOperation_Darken3ds, - aiStackOperation_DarkenMaya, - aiStackOperation_Desaturate, - aiStackOperation_Difference3ds, - aiStackOperation_DifferenceMaya, - aiStackOperation_Divide, - aiStackOperation_Exclusion, - aiStackOperation_HardLight, - aiStackOperation_HardMix, - aiStackOperation_Hue, - aiStackOperation_Illuminate, - aiStackOperation_In, - aiStackOperation_Lighten3ds, - aiStackOperation_LightenMaya, - aiStackOperation_LinearBurn, - aiStackOperation_LinearDodge, - aiStackOperation_Multiply3ds, - aiStackOperation_MultiplyMaya, - aiStackOperation_None, - aiStackOperation_Out, - aiStackOperation_Over3ds, - aiStackOperation_Overlay3ds, - aiStackOperation_OverMaya, - aiStackOperation_PinLight, - aiStackOperation_Saturate, - aiStackOperation_Saturation, - aiStackOperation_Screen, - aiStackOperation_SoftLight, - aiStackOperation_Substract3ds, - aiStackOperation_SubstractMaya, - aiStackOperation_Value, - aiStackOperation_Mask, - aiStackOperation_Unknown, - aiStackOperation_NumberOperations -}; diff --git a/sources/tools/Stride.Assimp.Translation/Materials.cpp b/sources/tools/Stride.Assimp.Translation/Materials.cpp deleted file mode 100644 index 8361058d5a..0000000000 --- a/sources/tools/Stride.Assimp.Translation/Materials.cpp +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) -// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. -#pragma once - -#include -#include "Extension.h" - -#pragma make_public(aiMaterial) -#pragma make_public(aiTextureType) - -using namespace Stride::Core::Mathematics; -using namespace Stride::AssimpNet; -namespace Stride { - namespace AssimpNet { - namespace NetTranslation { -/// -/// Class used to translate Assimp's cpp materials datas to c#. -/// -public ref class Materials { -public: - /// - /// Converts an Assimp's material stack operation From c++ to c#. - /// - static array^ convertAssimpStackOperationCppToCs = { - Material::Operation::Add, //aiStackOperation_Add - Material::Operation::Add3ds, //aiStackOperation_Add3ds - Material::Operation::AddMaya, //aiStackOperation_AddMaya - Material::Operation::Average, //aiStackOperation_Average - Material::Operation::Color, //aiStackOperation_Color - Material::Operation::ColorBurn, //aiStackOperation_ColorBurn - Material::Operation::ColorDodge, //aiStackOperation_ColorDodge - Material::Operation::Darken3ds, //aiStackOperation_Darken3ds - Material::Operation::DarkenMaya, //aiStackOperation_DarkenMaya - Material::Operation::Desaturate, //aiStackOperation_Desaturate - Material::Operation::Difference3ds, //aiStackOperation_Difference3ds - Material::Operation::DifferenceMaya,//aiStackOperation_DifferenceMaya - Material::Operation::Divide, //aiStackOperation_Divide - Material::Operation::Exclusion, //aiStackOperation_Exclusion - Material::Operation::HardLight, //aiStackOperation_HardLight - Material::Operation::HardMix, //aiStackOperation_HardMix - Material::Operation::Hue, //aiStackOperation_Hue - Material::Operation::Illuminate, //aiStackOperation_Illuminate - Material::Operation::In, //aiStackOperation_In - Material::Operation::Lighten3ds, //aiStackOperation_Lighten3ds - Material::Operation::LightenMaya, //aiStackOperation_LightenMaya - Material::Operation::LinearBurn, //aiStackOperation_LinearBurn - Material::Operation::LinearDodge, //aiStackOperation_LinearDodge - Material::Operation::Multiply3ds, //aiStackOperation_Multiply3ds - Material::Operation::MultiplyMaya, //aiStackOperation_MultiplyMaya - Material::Operation::None, //aiStackOperation_None - Material::Operation::Out, //aiStackOperation_Out - Material::Operation::Over3ds, //aiStackOperation_Over3ds - Material::Operation::Overlay3ds, //aiStackOperation_Overlay3ds - Material::Operation::OverMaya, //aiStackOperation_OverMaya - Material::Operation::PinLight, //aiStackOperation_PinLight - Material::Operation::Saturate, //aiStackOperation_Saturate - Material::Operation::Saturation, //aiStackOperation_Saturation - Material::Operation::Screen, //aiStackOperation_Screen - Material::Operation::SoftLight, //aiStackOperation_SoftLight - Material::Operation::Substract3ds, //aiStackOperation_Substract3ds - Material::Operation::SubstractMaya, //aiStackOperation_SubstractMaya - Material::Operation::Value, //aiStackOperation_Value - Material::Operation::Mask //aiStackOperation_Mask - }; - /// - /// Converts an Assimp's material stack node type From c++ to c#. - /// - static array^ convertAssimpStackTypeCppToCs = { - Material::StackType::Color, // aiStackType_ColorType - Material::StackType::Texture, // aiStackType_TextureType - Material::StackType::Operation // aiStackType_BlemdOpType - }; - static array^ convertAssimpMappingModeCppToCs = { - Material::MappingMode::Wrap, // aiTextureMapMode_Wrap - Material::MappingMode::Clamp, // aiTextureMapMode_Clamp - Material::MappingMode::Mirror, // aiTextureMapMode_Mirror - Material::MappingMode::Decal // aiTextureMapMode_Decal - }; - /// - /// Converts an Assimp's material stack From c++ to c#. - /// - /// The material contaning the stack to convert. - /// The type of the stack to convert. - /// - static Material::Stack^ convertAssimpStackCppToCs(aiMaterial *material, const aiTextureType type) { - Material::Stack^ ret = gcnew Material::Stack; - unsigned int count = material->GetTextureCount(type); - // As it is represented now, the base color is at the bottom of the stack - - /*aiString path; - aiTextureMapping mapping; - unsigned int index; - float blend; - aiTextureOp textureOp; - aiTextureMapMode mapMode; - material->GetTexture(type, 0, &path, &mapping, &index, &blend, &textureOp, &mapMode);*/ - - /* - if (type == aiTextureType_AMBIENT) { - aiColor3D ambient; - material->Get(AI_MATKEY_COLOR_AMBIENT, ambient); - ret->Push(gcnew Material::StackColor(Color3(ambient.r, ambient.g, ambient.b), 1.f, 1.f, 0)); - } - if (type == aiTextureType_DIFFUSE) { - aiColor3D diffuse; - material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse); - ret->Push(gcnew Material::StackColor(Color3(diffuse.r, diffuse.g, diffuse.b), 1.f, 1.f, 0)); - } - if (type == aiTextureType_SPECULAR) { - aiColor3D specular; - material->Get(AI_MATKEY_COLOR_SPECULAR, specular); - ret->Push(gcnew Material::StackColor(Color3(specular.r, specular.g, specular.b), 1.f, 1.f, 0)); - } - if (type == aiTextureType_EMISSIVE) { - aiColor3D emissive; - material->Get(AI_MATKEY_COLOR_EMISSIVE, emissive); - ret->Push(gcnew Material::StackColor(Color3(emissive.r, emissive.g, emissive.b), 1.f, 1.f, 0)); - } - */ - // Process the material stack - for (int iEl = count-1; iEl >= 0; --iEl) { - Material::StackElement^ el; - // Common properties - int elType, elFlags; - float elAlpha, elBlend; - // Operation-specific properties - int elOp; - // Color-specific properties - aiColor3D elColor; - // Texture-specific properties - aiString elTexPath; - int elTexChannel, elMappingModeU, elMappingModeV; - if (AI_SUCCESS != material->Get(AI_MATKEY_TEXALPHA(type, iEl), elAlpha)) - elAlpha = 1.f; // default alpha - if (AI_SUCCESS != material->Get(AI_MATKEY_TEXBLEND(type, iEl), elBlend)) - elBlend = 1.f; // default blend - if (AI_SUCCESS != material->Get(AI_MATKEY_TEXFLAGS(type, iEl), elFlags)) - elFlags = 0; // default flags (no flags) - if (AI_SUCCESS != material->Get(AI_MATKEY_TEXTYPE(type, iEl), elType)) - elType = aiStackType_TextureType; //continue; // error ! - switch (elType) { - case aiStackType_BlendOpType: - if (AI_SUCCESS != material->Get(AI_MATKEY_TEXOP(type, iEl), elOp)) - continue; // error ! - el = gcnew Material::StackOperation(convertAssimpStackOperationCppToCs[elOp], elAlpha, elBlend, elFlags); - break; - case aiStackType_ColorType: - if (AI_SUCCESS != material->Get(AI_MATKEY_TEXCOLOR(type, iEl), elColor)) - continue; // error ! - el = gcnew Material::StackColor(Color3(elColor.r, elColor.g, elColor.b), elAlpha, elBlend, elFlags); - break; - case aiStackType_TextureType: - if (AI_SUCCESS != material->Get(AI_MATKEY_TEXTURE(type, iEl), elTexPath)) - continue; // error ! - if (AI_SUCCESS != material->Get(AI_MATKEY_UVWSRC(type, iEl), elTexChannel)) - elTexChannel = 0; // default channel - if (AI_SUCCESS != material->Get(AI_MATKEY_MAPPINGMODE_U(type, iEl), elMappingModeU)) - elMappingModeU = aiTextureMapMode_Wrap; // default mapping mode - if (AI_SUCCESS != material->Get(AI_MATKEY_MAPPINGMODE_V(type, iEl), elMappingModeV)) - elMappingModeV = aiTextureMapMode_Wrap; // default mapping mode - el = gcnew Material::StackTexture(gcnew System::String(elTexPath.C_Str()), - elTexChannel, - convertAssimpMappingModeCppToCs[elMappingModeU], - convertAssimpMappingModeCppToCs[elMappingModeV], - elAlpha, - elBlend, - elFlags); - } - ret->Push(el); - } - return ret; - } -}; - } - } -} diff --git a/sources/tools/Stride.Assimp.Translation/Stride.Assimp.Translation.vcxproj b/sources/tools/Stride.Assimp.Translation/Stride.Assimp.Translation.vcxproj deleted file mode 100644 index dfb62a2997..0000000000 --- a/sources/tools/Stride.Assimp.Translation/Stride.Assimp.Translation.vcxproj +++ /dev/null @@ -1,153 +0,0 @@ - - - - - Cpp - $(StrideEditorTargetFramework) - WindowsTools - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - {FCDF1B87-1C76-46EB-AD6A-D55EF5F195B8} - Stride.AssimpNet.NetTranslation - Stride.Assimp.Translation - 10.0 - - - - DynamicLibrary - true - v143 - MultiByte - NetCore - - - DynamicLibrary - false - v143 - true - MultiByte - NetCore - - - - - - - - - - bin\$(TargetFramework)\$(Platform)\$(Configuration)\ - obj\$(TargetFramework)\$(Platform)\$(Configuration)\ - - - bin\$(TargetFramework)\$(Platform)\$(Configuration)\ - obj\$(TargetFramework)\$(Platform)\$(Configuration)\ - - - - Level3 - Disabled - true - ..\..\..\deps\assimp\include; - NotUsing - Assimp.h - - - true - ..\..\..\deps\assimp\lib\x64\ - assimp-vc140-mt.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - Level3 - MaxSpeed - true - true - true - ..\..\..\deps\assimp\include; - NotUsing - Assimp.h - - - true - true - true - ..\..\..\deps\assimp\lib\x64\ - assimp-vc140-mt.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - Level3 - Disabled - true - ..\..\..\deps\assimp\include; - NotUsing - Assimp.h - - - true - ..\..\..\deps\assimp\lib\x64\ - assimp-vc140-mt.lib; - - - - - Level3 - MaxSpeed - true - true - true - ..\..\..\deps\assimp\include; - NotUsing - Assimp.h - - - true - true - true - ..\..\..\deps\assimp\lib\x64\ - assimp-vc140-mt.lib; - - - - - - CppHeader - NotUsing - - - - - {1677b922-ccf0-44de-b57e-1cdd3d2b8e8a} - False - - - {f61d86b5-7c3d-4441-957d-a0a6d2fa69ca} - False - - - - - - \ No newline at end of file diff --git a/sources/tools/Stride.Assimp.Translation/Stride.Assimp.Translation.vcxproj.filters b/sources/tools/Stride.Assimp.Translation/Stride.Assimp.Translation.vcxproj.filters deleted file mode 100644 index dfb4aafb47..0000000000 --- a/sources/tools/Stride.Assimp.Translation/Stride.Assimp.Translation.vcxproj.filters +++ /dev/null @@ -1,27 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - - - Source Files - - - \ No newline at end of file diff --git a/sources/tools/Stride.Assimp/MaterialStack.cs b/sources/tools/Stride.Assimp/MaterialStack.cs deleted file mode 100644 index 128e5be399..0000000000 --- a/sources/tools/Stride.Assimp/MaterialStack.cs +++ /dev/null @@ -1,302 +0,0 @@ -// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) -// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Stride.Core.Mathematics; - -namespace Stride -{ - namespace AssimpNet - { - namespace Material - { - /// - /// Enumeration of the different types of node in the new Assimp's material stack. - /// - public enum StackType - { - Color = 0, - Texture, - Operation - } - /// - /// Enumeration of the new Assimp's flags. - /// - public enum Flags - { - Invert = 1, - ReplaceAlpha = 2 - } - /// - /// Enumeration of the different operations in the new Assimp's material stack. - /// - public enum Operation - { - Add = 0, - Add3ds, - AddMaya, - Average, - Color, - ColorBurn, - ColorDodge, - Darken3ds, - DarkenMaya, - Desaturate, - Difference3ds, - DifferenceMaya, - Divide, - Exclusion, - HardLight, - HardMix, - Hue, - Illuminate, - In, - Lighten3ds, - LightenMaya, - LinearBurn, - LinearDodge, - Multiply3ds, - MultiplyMaya, - None, - Out, - Over3ds, - Overlay3ds, - OverMaya, - PinLight, - Saturate, - Saturation, - Screen, - SoftLight, - Substract3ds, - SubstractMaya, - Value, - Mask - } - /// - /// Enumeration of the different mapping modes in the new Assimp's material stack. - /// - public enum MappingMode - { - Wrap, - Clamp, - Decal, - Mirror - } - /// - /// Class representing an element in the new Assimp's material stack. - /// - public abstract class StackElement - { - /// - /// Initializes a new instance of the class. - /// - /// The alpha of the node. - /// The blending coefficient of the node. - /// The flags of the node. - /// The type of the node. - public StackElement(float Alpha, float Blend, int flags, StackType Type) - { - alpha = Alpha; - blend = Blend; - type = Type; - } - /// - /// Gets the alpha of the node. - /// - /// - /// The alpha of the node. - /// - public float alpha { get; private set; } - /// - /// Gets the blending coefficient of the node. - /// - /// - /// The blending coefficient of the node. - /// - public float blend { get; private set; } - /// - /// Gets the flags of the node. - /// - /// - /// The flags of the node. - /// - public int flags { get; private set; } - /// - /// Gets the type of the node. - /// - /// - /// The type of the node. - /// - public StackType type { get; private set; } - } - /// - /// Class representing an operation in the new Assimp's material stack. - /// - public class StackOperation : StackElement - { - /// - /// Initializes a new instance of the class. - /// - /// The operation of the node. - /// The alpha of the node. - /// The blending coefficient of the node. - /// The flags. - public StackOperation(Operation Operation, float Alpha = 1.0f, float Blend = 1.0f, int Flags = 0) - : base(Alpha, Blend, Flags, StackType.Operation) - { - operation = Operation; - } - /// - /// Gets the operation of the node. - /// - /// - /// The operation of the node. - /// - public Operation operation { get; private set; } - } - /// - /// Class representing a color in the new Assimp's material stack. - /// - public class StackColor : StackElement - { - /// - /// Initializes a new instance of the class. - /// - /// The color of the node. - /// The alpha of the node. - /// The blending coefficient of the node. - /// The flags of the node. - public StackColor(Color3 Color, float Alpha = 1.0f, float Blend = 1.0f, int Flags = 0) - : base(Alpha, Blend, Flags, StackType.Color) - { - color = Color; - } - /// - /// Gets the color of the node. - /// - /// - /// The color of the node. - /// - public Color3 color { get; private set; } - } - /// - /// Class representing a texture in the new Assimp's material stack. - /// - public class StackTexture : StackElement - { - /// - /// Initializes a new instance of the class. - /// - /// The texture path. - /// The uv channel used by the texture. - /// The U mapping mode. - /// The V mapping mode. - /// The alpha of the node. - /// The blending coefficient of the node. - /// The flags of the node. - public StackTexture(String TexturePath, int Channel, MappingMode MappingModeU, MappingMode MappingModeV, float Alpha = 1.0f, float Blend = 1.0F, int Flags = 0) - : base(Alpha, Blend, Flags, StackType.Texture) - { - texturePath = TexturePath; - channel = Channel; - mappingModeU = MappingModeU; - mappingModeV = MappingModeV; - } - /// - /// Gets the texture path. - /// - /// - /// The texture path. - /// - public String texturePath { get; private set; } - /// - /// Gets the uv channel. - /// - /// - /// The uv channel. - /// - public int channel { get; private set; } - /// - /// Gets the U mapping mode. - /// - /// - /// The U mapping mode. - /// - public MappingMode mappingModeU { get; private set; } - /// - /// Gets the Vmapping mode. - /// - /// - /// The V mapping mode. - /// - public MappingMode mappingModeV { get; private set; } - } - /// - /// Class representing the new Assimp's material stack in c#. - /// - public class Stack - { - /// - /// Initializes a new instance of the class. - /// - public Stack() - { - stack = new Stack(); - } - /// - /// The internal stack. - /// - private Stack stack; - /// - /// Gets the size of the stack. - /// - /// - /// The size of the stack. - /// - private int Count { get { return stack.Count; } } - /// - /// Gets a value indicating whether the stack is empty. - /// - /// - /// true if the stack is empty; otherwise, false. - /// - public bool IsEmpty { get { return stack.Count == 0; } } - /// - /// Pushes the specified element. - /// - /// The element. - public void Push(StackElement element) - { - stack.Push(element); - } - /// - /// Pops an element. - /// - /// The element. - public StackElement Pop() - { - return stack.Pop(); - } - /// - /// Gets the top element of the stack. - /// - /// The top element of the stack. - public StackElement Peek() - { - return stack.Peek(); - } - /// - /// Clears the stack. - /// - public void Clear() - { - stack.Clear(); - } - } - } - } -} diff --git a/sources/tools/Stride.Assimp/Properties/AssemblyInfo.cs b/sources/tools/Stride.Assimp/Properties/AssemblyInfo.cs deleted file mode 100644 index 77c6be5a94..0000000000 --- a/sources/tools/Stride.Assimp/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) -// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("52f2a331-0906-4418-ba99-87bb87e51085")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/sources/tools/Stride.Assimp/Stride.Assimp.csproj b/sources/tools/Stride.Assimp/Stride.Assimp.csproj deleted file mode 100644 index 4c1207e038..0000000000 --- a/sources/tools/Stride.Assimp/Stride.Assimp.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - $(StrideEditorTargetFramework) - WindowsTools - - - - - - - \ No newline at end of file diff --git a/sources/tools/Stride.Importer.Assimp/AssemblyInfo.cpp b/sources/tools/Stride.Importer.Assimp/AssemblyInfo.cpp deleted file mode 100644 index a36b0e9cf5..0000000000 --- a/sources/tools/Stride.Importer.Assimp/AssemblyInfo.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) -// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. -#include "stdafx.h" - -using namespace System; -using namespace System::Reflection; -using namespace System::Runtime::CompilerServices; -using namespace System::Runtime::InteropServices; -using namespace System::Security::Permissions; - -// -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -// -[assembly:AssemblyTitleAttribute("StrideImporterAssimp")]; -[assembly:AssemblyDescriptionAttribute("")]; -[assembly:AssemblyConfigurationAttribute("")]; -[assembly:AssemblyCompanyAttribute("")]; -[assembly:AssemblyProductAttribute("StrideImporterAssimp")]; -[assembly:AssemblyCopyrightAttribute("Copyright (c) 2012")]; -[assembly:AssemblyTrademarkAttribute("")]; -[assembly:AssemblyCultureAttribute("")]; - -// -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the value or you can default the Revision and Build Numbers -// by using the '*' as shown below: - -[assembly:AssemblyVersionAttribute("1.0.*")]; - -[assembly:ComVisible(false)]; - -[assembly:CLSCompliantAttribute(true)]; diff --git a/sources/tools/Stride.Importer.Assimp/Material/Flags.cs b/sources/tools/Stride.Importer.Assimp/Material/Flags.cs new file mode 100644 index 0000000000..862d9404f7 --- /dev/null +++ b/sources/tools/Stride.Importer.Assimp/Material/Flags.cs @@ -0,0 +1,18 @@ +// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; + +namespace Stride.Importer.Assimp.Material +{ + /// + /// Enumeration of the new Assimp's flags. + /// + [Flags] + public enum Flags + { + None = 0, + Invert = 1, + ReplaceAlpha = 2 + } +} diff --git a/sources/tools/Stride.Importer.Assimp/Material/MappingMode.cs b/sources/tools/Stride.Importer.Assimp/Material/MappingMode.cs new file mode 100644 index 0000000000..68aed2e39f --- /dev/null +++ b/sources/tools/Stride.Importer.Assimp/Material/MappingMode.cs @@ -0,0 +1,16 @@ +// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. + +namespace Stride.Importer.Assimp.Material +{ + /// + /// Enumeration of the different mapping modes in the new Assimp's material stack. + /// + public enum MappingMode + { + Wrap, + Clamp, + Decal, + Mirror + } +} diff --git a/sources/tools/Stride.Importer.Assimp/Material/MaterialStack.cs b/sources/tools/Stride.Importer.Assimp/Material/MaterialStack.cs new file mode 100644 index 0000000000..0e58259377 --- /dev/null +++ b/sources/tools/Stride.Importer.Assimp/Material/MaterialStack.cs @@ -0,0 +1,70 @@ +// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System.Collections.Generic; + +namespace Stride.Importer.Assimp.Material +{ + /// + /// Class representing the new Assimp's material stack in c#. + /// + public class MaterialStack + { + /// + /// Initializes a new instance of the class. + /// + public MaterialStack() + { + stack = new Stack(); + } + /// + /// The internal stack. + /// + private Stack stack; + /// + /// Gets the size of the stack. + /// + /// + /// The size of the stack. + /// + private int Count { get { return stack.Count; } } + /// + /// Gets a value indicating whether the stack is empty. + /// + /// + /// true if the stack is empty; otherwise, false. + /// + public bool IsEmpty { get { return stack.Count == 0; } } + /// + /// Pushes the specified element. + /// + /// The element. + public void Push(StackElement element) + { + stack.Push(element); + } + /// + /// Pops an element. + /// + /// The element. + public StackElement Pop() + { + return stack.Pop(); + } + /// + /// Gets the top element of the stack. + /// + /// The top element of the stack. + public StackElement Peek() + { + return stack.Peek(); + } + /// + /// Clears the stack. + /// + public void Clear() + { + stack.Clear(); + } + } +} diff --git a/sources/tools/Stride.Importer.Assimp/Material/Materials.cs b/sources/tools/Stride.Importer.Assimp/Material/Materials.cs new file mode 100644 index 0000000000..b89de8d0af --- /dev/null +++ b/sources/tools/Stride.Importer.Assimp/Material/Materials.cs @@ -0,0 +1,152 @@ +// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. + +using Silk.NET.Assimp; +using Stride.Core.Mathematics; + +namespace Stride.Importer.Assimp.Material +{ + public static unsafe class Materials + { + public const string MatKeyTexTypeBase = "$tex.type"; + public const string MatKeyTexColorBase = "$tex.color"; + public const string MatKeyTexAlphaBase = "$tex.alpha"; + + /// + /// Converts an Assimp's material stack operation From c++ to c#. + /// + public static readonly Operation[] ConvertAssimpStackOperationCppToCs = new Operation[] + { + Operation.Add, //aiStackOperation_Add + Operation.Add3ds, //aiStackOperation_Add3ds + Operation.AddMaya, //aiStackOperation_AddMaya + Operation.Average, //aiStackOperation_Average + Operation.Color, //aiStackOperation_Color + Operation.ColorBurn, //aiStackOperation_ColorBurn + Operation.ColorDodge, //aiStackOperation_ColorDodge + Operation.Darken3ds, //aiStackOperation_Darken3ds + Operation.DarkenMaya, //aiStackOperation_DarkenMaya + Operation.Desaturate, //aiStackOperation_Desaturate + Operation.Difference3ds, //aiStackOperation_Difference3ds + Operation.DifferenceMaya,//aiStackOperation_DifferenceMaya + Operation.Divide, //aiStackOperation_Divide + Operation.Exclusion, //aiStackOperation_Exclusion + Operation.HardLight, //aiStackOperation_HardLight + Operation.HardMix, //aiStackOperation_HardMix + Operation.Hue, //aiStackOperation_Hue + Operation.Illuminate, //aiStackOperation_Illuminate + Operation.In, //aiStackOperation_In + Operation.Lighten3ds, //aiStackOperation_Lighten3ds + Operation.LightenMaya, //aiStackOperation_LightenMaya + Operation.LinearBurn, //aiStackOperation_LinearBurn + Operation.LinearDodge, //aiStackOperation_LinearDodge + Operation.Multiply3ds, //aiStackOperation_Multiply3ds + Operation.MultiplyMaya, //aiStackOperation_MultiplyMaya + Operation.None, //aiStackOperation_None + Operation.Out, //aiStackOperation_Out + Operation.Over3ds, //aiStackOperation_Over3ds + Operation.Overlay3ds, //aiStackOperation_Overlay3ds + Operation.OverMaya, //aiStackOperation_OverMaya + Operation.PinLight, //aiStackOperation_PinLight + Operation.Saturate, //aiStackOperation_Saturate + Operation.Saturation, //aiStackOperation_Saturation + Operation.Screen, //aiStackOperation_Screen + Operation.SoftLight, //aiStackOperation_SoftLight + Operation.Substract3ds, //aiStackOperation_Substract3ds + Operation.SubstractMaya, //aiStackOperation_SubstractMaya + Operation.Value, //aiStackOperation_Value + Operation.Mask //aiStackOperation_Mask + }; + + /// + /// Converts an Assimp's material stack node type From c++ to c#. + /// + public static readonly StackElementType[] ConvertAssimpStackTypeCppToCs = new StackElementType[] + { + StackElementType.Color, // aiStackType_ColorType + StackElementType.Texture, // aiStackType_TextureType + StackElementType.Operation // aiStackType_BlemdOpType + }; + + public static readonly MappingMode[] ConvertAssimpMappingModeCppToCs = new MappingMode[] + { + MappingMode.Wrap, // aiTextureMapMode_Wrap + MappingMode.Clamp, // aiTextureMapMode_Clamp + MappingMode.Mirror, // aiTextureMapMode_Mirror + MappingMode.Decal // aiTextureMapMode_Decal + }; + + public static unsafe MaterialStack ConvertAssimpStackCppToCs(Silk.NET.Assimp.Assimp assimp, Silk.NET.Assimp.Material* material, Silk.NET.Assimp.TextureType type) + { + var ret = new MaterialStack(); + var count = (int)assimp.GetMaterialTextureCount(material, type); + + // Process the material stack + for (int iEl = count - 1; iEl >= 0; --iEl) + { + StackElement el; + // Common properties + int elType = 0, elFlags = 0; + float elAlpha = 0.0f, elBlend = 0.0f; + // Operation-specific properties + int elOp = 0; + // Color-specific properties + var elColor = new System.Numerics.Vector4(); + // Texture-specific properties + var elTexPath = new AssimpString(); + int elTexChannel = 0, elMappingModeU = 0, elMappingModeV = 0; + uint pMax = 0; + + if (assimp.GetMaterialFloatArray(material, MatKeyTexAlphaBase, (uint)type, (uint)iEl, ref elAlpha, ref pMax) != Return.Success) + elAlpha = 1.0f; // default alpha + if (assimp.GetMaterialFloatArray(material, Silk.NET.Assimp.Assimp.MaterialTexblendBase, (uint)type, (uint)iEl, ref elBlend, ref pMax) != Return.Success) + elBlend = 1.0f; // default blend + if (assimp.GetMaterialIntegerArray(material, Silk.NET.Assimp.Assimp.MaterialTexflagsBase, (uint)type, (uint)iEl, ref elFlags, ref pMax) != Return.Success) + elFlags = 0; // default flags (no flags) + if (assimp.GetMaterialIntegerArray(material, MatKeyTexTypeBase, (uint)type, (uint)iEl, ref elType, ref pMax) != Return.Success) + elType = (int)StackElementType.Texture;//continue; // error ! + + switch ((StackElementType)elType) + { + case StackElementType.Operation: + if (assimp.GetMaterialIntegerArray(material, Silk.NET.Assimp.Assimp.MaterialTexopBase, (uint)type, (uint)iEl, ref elOp, ref pMax) != Return.Success) + continue; // error ! + + el = new StackOperation(ConvertAssimpStackOperationCppToCs[elOp], elAlpha, elBlend, elFlags); + break; + case StackElementType.Color: + if (assimp.GetMaterialColor(material, MatKeyTexColorBase, (uint)type, (uint)iEl, ref elColor) != Return.Success) + continue; // error ! + el = new StackColor(new Color3(elColor.X, elColor.Y, elColor.Z), elAlpha, elBlend, elFlags); + break; + case StackElementType.Texture: + if (assimp.GetMaterialString(material, Silk.NET.Assimp.Assimp.MaterialTextureBase, (uint)type, (uint)iEl, ref elTexPath) != Return.Success) + continue; // error ! + if (assimp.GetMaterialIntegerArray(material, Silk.NET.Assimp.Assimp.MaterialUvwsrcBase, (uint)type, (uint)iEl, ref elTexChannel, ref pMax) != Return.Success) + elTexChannel = 0; // default channel + if (assimp.GetMaterialIntegerArray(material, Silk.NET.Assimp.Assimp.MaterialMappingmodeUBase, (uint)type, (uint)iEl, ref elMappingModeU, ref pMax) != Return.Success) + elMappingModeU = (int)TextureMapMode.Wrap; // default mapping mode + if (assimp.GetMaterialIntegerArray(material, Silk.NET.Assimp.Assimp.MaterialMappingmodeVBase, (uint)type, (uint)iEl, ref elMappingModeV, ref pMax) != Return.Success) + elMappingModeV = (int)TextureMapMode.Wrap; // default mapping mode + + el = new StackTexture( + elTexPath.AsString, + elTexChannel, + ConvertAssimpMappingModeCppToCs[elMappingModeU], + ConvertAssimpMappingModeCppToCs[elMappingModeV], + elAlpha, + elBlend, + elFlags); + break; + default: + // error ! + continue; + } + + ret.Push(el); + } + + return ret; + } + } +} diff --git a/sources/tools/Stride.Importer.Assimp/Material/Operation.cs b/sources/tools/Stride.Importer.Assimp/Material/Operation.cs new file mode 100644 index 0000000000..3dfc41ed65 --- /dev/null +++ b/sources/tools/Stride.Importer.Assimp/Material/Operation.cs @@ -0,0 +1,51 @@ +// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. + +namespace Stride.Importer.Assimp.Material +{ + /// + /// Enumeration of the different operations in the new Assimp's material stack. + /// + public enum Operation + { + Add = 0, + Add3ds, + AddMaya, + Average, + Color, + ColorBurn, + ColorDodge, + Darken3ds, + DarkenMaya, + Desaturate, + Difference3ds, + DifferenceMaya, + Divide, + Exclusion, + HardLight, + HardMix, + Hue, + Illuminate, + In, + Lighten3ds, + LightenMaya, + LinearBurn, + LinearDodge, + Multiply3ds, + MultiplyMaya, + None, + Out, + Over3ds, + Overlay3ds, + OverMaya, + PinLight, + Saturate, + Saturation, + Screen, + SoftLight, + Substract3ds, + SubstractMaya, + Value, + Mask + } +} diff --git a/sources/tools/Stride.Importer.Assimp/Material/StackColor.cs b/sources/tools/Stride.Importer.Assimp/Material/StackColor.cs new file mode 100644 index 0000000000..c1e21e0604 --- /dev/null +++ b/sources/tools/Stride.Importer.Assimp/Material/StackColor.cs @@ -0,0 +1,33 @@ +// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. + +using Stride.Core.Mathematics; + +namespace Stride.Importer.Assimp.Material +{ + /// + /// Class representing a color in the new Assimp's material stack. + /// + public class StackColor : StackElement + { + /// + /// Initializes a new instance of the class. + /// + /// The color of the node. + /// The alpha of the node. + /// The blending coefficient of the node. + /// The flags of the node. + public StackColor(Color3 color, float alpha = 1.0f, float blend = 1.0f, int flags = 0) + : base(alpha, blend, flags, StackElementType.Color) + { + Color = color; + } + /// + /// Gets the color of the node. + /// + /// + /// The color of the node. + /// + public Color3 Color { get; private set; } + } +} diff --git a/sources/tools/Stride.Importer.Assimp/Material/StackElement.cs b/sources/tools/Stride.Importer.Assimp/Material/StackElement.cs new file mode 100644 index 0000000000..f61cbb568b --- /dev/null +++ b/sources/tools/Stride.Importer.Assimp/Material/StackElement.cs @@ -0,0 +1,53 @@ +// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. + +namespace Stride.Importer.Assimp.Material +{ + /// + /// Class representing an element in the new Assimp's material stack. + /// + public abstract class StackElement + { + /// + /// Initializes a new instance of the class. + /// + /// The alpha of the node. + /// The blending coefficient of the node. + /// The flags of the node. + /// The type of the node. + public StackElement(float alpha, float blend, int flags, StackElementType type) + { + Alpha = alpha; + Blend = blend; + Type = type; + } + /// + /// Gets the alpha of the node. + /// + /// + /// The alpha of the node. + /// + public float Alpha { get; private set; } + /// + /// Gets the blending coefficient of the node. + /// + /// + /// The blending coefficient of the node. + /// + public float Blend { get; private set; } + /// + /// Gets the flags of the node. + /// + /// + /// The flags of the node. + /// + public int Flags { get; private set; } + /// + /// Gets the type of the node. + /// + /// + /// The type of the node. + /// + public StackElementType Type { get; private set; } + } +} diff --git a/sources/tools/Stride.Importer.Assimp/Material/StackElementType.cs b/sources/tools/Stride.Importer.Assimp/Material/StackElementType.cs new file mode 100644 index 0000000000..77e608cab5 --- /dev/null +++ b/sources/tools/Stride.Importer.Assimp/Material/StackElementType.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. + +namespace Stride.Importer.Assimp.Material +{ + /// + /// Enumeration of the different types of node in the new Assimp's material stack. + /// + public enum StackElementType + { + Color = 0, + Texture, + Operation + } +} diff --git a/sources/tools/Stride.Importer.Assimp/Material/StackOperation.cs b/sources/tools/Stride.Importer.Assimp/Material/StackOperation.cs new file mode 100644 index 0000000000..b2b7ae60de --- /dev/null +++ b/sources/tools/Stride.Importer.Assimp/Material/StackOperation.cs @@ -0,0 +1,31 @@ +// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. + +namespace Stride.Importer.Assimp.Material +{ + /// + /// Class representing an operation in the new Assimp's material stack. + /// + public class StackOperation : StackElement + { + /// + /// Initializes a new instance of the class. + /// + /// The operation of the node. + /// The alpha of the node. + /// The blending coefficient of the node. + /// The flags. + public StackOperation(Operation operation, float alpha = 1.0f, float blend = 1.0f, int flags = 0) + : base(alpha, blend, flags, StackElementType.Operation) + { + Operation = operation; + } + /// + /// Gets the operation of the node. + /// + /// + /// The operation of the node. + /// + public Operation Operation { get; private set; } + } +} diff --git a/sources/tools/Stride.Importer.Assimp/Material/StackTexture.cs b/sources/tools/Stride.Importer.Assimp/Material/StackTexture.cs new file mode 100644 index 0000000000..0a451cde56 --- /dev/null +++ b/sources/tools/Stride.Importer.Assimp/Material/StackTexture.cs @@ -0,0 +1,58 @@ +// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. + +namespace Stride.Importer.Assimp.Material +{ + /// + /// Class representing a texture in the new Assimp's material stack. + /// + public class StackTexture : StackElement + { + /// + /// Initializes a new instance of the class. + /// + /// The texture path. + /// The uv channel used by the texture. + /// The U mapping mode. + /// The V mapping mode. + /// The alpha of the node. + /// The blending coefficient of the node. + /// The flags of the node. + public StackTexture(string texturePath, int channel, MappingMode mappingModeU, MappingMode mappingModeV, float alpha = 1.0f, float blend = 1.0F, int flags = 0) + : base(alpha, blend, flags, StackElementType.Texture) + { + TexturePath = texturePath; + Channel = channel; + MappingModeU = mappingModeU; + MappingModeV = mappingModeV; + } + /// + /// Gets the texture path. + /// + /// + /// The texture path. + /// + public string TexturePath { get; private set; } + /// + /// Gets the uv channel. + /// + /// + /// The uv channel. + /// + public int Channel { get; private set; } + /// + /// Gets the U mapping mode. + /// + /// + /// The U mapping mode. + /// + public MappingMode MappingModeU { get; private set; } + /// + /// Gets the Vmapping mode. + /// + /// + /// The V mapping mode. + /// + public MappingMode MappingModeV { get; private set; } + } +} diff --git a/sources/tools/Stride.Importer.Assimp/MeshConverter.cs b/sources/tools/Stride.Importer.Assimp/MeshConverter.cs new file mode 100644 index 0000000000..e6f04e4fa7 --- /dev/null +++ b/sources/tools/Stride.Importer.Assimp/MeshConverter.cs @@ -0,0 +1,1378 @@ +// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using Silk.NET.Assimp; +using Stride.Animations; +using Stride.Assets.Materials; +using Stride.Core.Diagnostics; +using Stride.Core.IO; +using Stride.Core.Mathematics; +using Stride.Core.Serialization; +using Stride.Graphics; +using Stride.Graphics.Data; +using Stride.Importer.Common; +using Stride.Rendering; +using Stride.Rendering.Materials; +using Stride.Rendering.Materials.ComputeColors; +using Mesh = Stride.Rendering.Mesh; +using PrimitiveType = Stride.Graphics.PrimitiveType; + +namespace Stride.Importer.Assimp +{ + public class MeshConverter + { + private const int NumberOfBonesPerVertex = 4; + + public Logger Logger { get; set; } + + private readonly Silk.NET.Assimp.Assimp assimp = Silk.NET.Assimp.Assimp.GetApi(); + + public bool AllowUnsignedBlendIndices { get; set; } + + // Conversion data + + private string vfsInputFilename; + private string vfsOutputFilename; + private string vfsInputPath; + + private Quaternion rootOrientation; + private Quaternion rootOrientationInverse; + private Matrix rootTransform; + private Matrix rootTransformInverse; + private Model modelData; + + private readonly List nodes = new(); + private readonly Dictionary textureNameCount = new(); + + public MeshConverter(Logger logger) + { + Logger = logger ?? GlobalLogger.GetLogger("Import Assimp"); + } + + private void ResetConversionData() + { + textureNameCount.Clear(); + } + + public unsafe EntityInfo ExtractEntity(string inputFilename, string outputFilename, bool extractTextureDependencies, bool deduplicateMaterials) + { + try + { + uint importFlags = 0; + var postProcessFlags = PostProcessSteps.SortByPrimitiveType; + + if (deduplicateMaterials) + { + postProcessFlags |= PostProcessSteps.RemoveRedundantMaterials; + } + + var scene = Initialize(inputFilename, outputFilename, importFlags, (uint)postProcessFlags); + + // If scene is null, something went wrong inside Assimp + if (scene == null) + { + var error = assimp.GetErrorStringS(); + if (error.Length > 0) + { + Logger.Error($"Assimp: {error}"); + } + + return null; + } + + var materialNames = new Dictionary(); + var meshNames = new Dictionary(); + var animationNames = new Dictionary(); + var nodeNames = new Dictionary(); + + GenerateNodeNames(scene, nodeNames); + + var entityInfo = new EntityInfo + { + Materials = ExtractMaterials(scene, materialNames), + Models = ExtractModels(scene, meshNames, materialNames, nodeNames), + Nodes = ExtractNodeHierarchy(scene, nodeNames), + AnimationNodes = ExtractAnimations(scene, animationNames) + }; + + if (extractTextureDependencies) + entityInfo.TextureDependencies = ExtractTextureDependencies(scene); + + return entityInfo; + } + catch(Exception ex) + { + Logger.Error($"Exception has occured during Entity extraction : {ex.Message}"); + throw; + } + } + + public unsafe Model Convert(string inputFilename, string outputFilename, bool deduplicateMaterials) + { + uint importFlags = 0; + var postProcessFlags = + PostProcessSteps.CalculateTangentSpace + | PostProcessSteps.Triangulate + | PostProcessSteps.GenerateNormals + | PostProcessSteps.JoinIdenticalVertices + | PostProcessSteps.LimitBoneWeights + | PostProcessSteps.SortByPrimitiveType + | PostProcessSteps.FlipWindingOrder + | PostProcessSteps.FlipUVs; + + if (deduplicateMaterials) + { + postProcessFlags |= PostProcessSteps.RemoveRedundantMaterials; + } + + var scene = Initialize(inputFilename, outputFilename, importFlags, (uint)postProcessFlags); + return ConvertAssimpScene(scene); + } + + public unsafe AnimationInfo ConvertAnimation(string inputFilename, string outputFilename) + { + uint importFlags = 0; + var postProcessFlags = PostProcessSteps.None; + + var scene = Initialize(inputFilename, outputFilename, importFlags, (uint)postProcessFlags); + + return ProcessAnimations(scene); + } + + public unsafe Rendering.Skeleton ConvertSkeleton(string inputFilename, string outputFilename) + { + uint importFlags = 0; + var postProcessFlags = PostProcessSteps.None; + + var scene = Initialize(inputFilename, outputFilename, importFlags, (uint)postProcessFlags); + + return ProcessSkeleton(scene); + } + + private unsafe Scene* Initialize(string inputFilename, string outputFilename, uint importFlags, uint postProcessFlags) + { + ResetConversionData(); + + vfsInputFilename = inputFilename; + vfsOutputFilename = outputFilename; + vfsInputPath = VirtualFileSystem.GetParentFolder(inputFilename); + + var scene = assimp.ImportFile(inputFilename, importFlags); + scene = assimp.ApplyPostProcessing(scene, postProcessFlags); + + return scene; + } + + private unsafe Model ConvertAssimpScene(Scene* scene) + { + modelData = new Model(); + + var meshNames = new Dictionary(); + GenerateMeshNames(scene, meshNames); + + var nodeNames = new Dictionary(); + GenerateNodeNames(scene, nodeNames); + + // register the nodes and fill hierarchy + var meshIndexToNodeIndex = new Dictionary>(); + RegisterNodes(scene->MRootNode, -1, nodeNames, meshIndexToNodeIndex); + + // meshes + for (var i = 0; i < scene->MNumMeshes; ++i) + { + if (meshIndexToNodeIndex.ContainsKey(i)) + { + var meshInfo = ProcessMesh(scene, scene->MMeshes[i], meshNames); + + foreach (var nodeIndex in meshIndexToNodeIndex[i]) + { + var nodeMeshData = new Mesh + { + Draw = meshInfo.Draw, + Name = meshInfo.Name, + MaterialIndex = meshInfo.MaterialIndex, + NodeIndex = nodeIndex + }; + + if (meshInfo.Bones != null) + { + nodeMeshData.Skinning = new MeshSkinningDefinition + { + Bones = meshInfo.Bones.ToArray() + }; + } + + if (meshInfo.HasSkinningPosition && meshInfo.TotalClusterCount > 0) + nodeMeshData.Parameters.Set(MaterialKeys.HasSkinningPosition, true); + + if (meshInfo.HasSkinningNormal && meshInfo.TotalClusterCount > 0) + nodeMeshData.Parameters.Set(MaterialKeys.HasSkinningNormal, true); + + modelData.Meshes.Add(nodeMeshData); + } + } + } + + // embedded texture - only to log the warning for now + for (uint i = 0; i < scene->MNumTextures; ++i) + { + ExtractEmbededTexture(scene->MTextures[i]); + } + + return modelData; + } + + private unsafe Rendering.Skeleton ProcessSkeleton(Scene* scene) + { + var nodeNames = new Dictionary(); + GenerateNodeNames(scene, nodeNames); + + // register the nodes and fill hierarchy + var meshIndexToNodeIndex = new Dictionary>(); + RegisterNodes(scene->MRootNode, -1, nodeNames, meshIndexToNodeIndex); + + return new Rendering.Skeleton + { + Nodes = nodes.ToArray() + }; + } + + private unsafe AnimationInfo ProcessAnimations(Scene* scene) + { + var animationData = new AnimationInfo(); + var visitedNodeNames = new HashSet(); + + if (scene->MNumAnimations > 1) + Logger.Warning($"There are {scene->MNumAnimations} animations in this file, using only the first one."); + + var nodeNames = new Dictionary(); + GenerateNodeNames(scene, nodeNames); + + // register the nodes and fill hierarchy + var meshIndexToNodeIndex = new Dictionary>(); + RegisterNodes(scene->MRootNode, -1, nodeNames, meshIndexToNodeIndex); + + for (uint i = 0; i < Math.Min(1, scene->MNumAnimations); ++i) + { + var aiAnim = scene->MAnimations[i]; + + // animation speed + var ticksPerSec = aiAnim->MTicksPerSecond; + + animationData.Duration = Utils.AiTimeToStrideTimeSpan(aiAnim->MDuration, ticksPerSec); + + // Assimp animations have two different channels of animations ((1) on Nodes, (2) on Meshes). + // Nevertheless the second one do not seems to be usable in assimp 3.0 so it will be ignored here. + + // name of the animation (dropped) + var animName = aiAnim->MName.AsString; // used only be the logger + + // animation using meshes (not supported) + for (uint meshAnimId = 0; meshAnimId < aiAnim->MNumMeshChannels; ++meshAnimId) + { + var meshName = aiAnim->MMeshChannels[meshAnimId]->MName.AsString; + Logger.Warning($"Mesh animations are not currently supported. Animation '{animName}' on mesh {meshName} will be ignored"); + } + + // animation on nodes + for (uint nodeAnimId = 0; nodeAnimId < aiAnim->MNumChannels; ++nodeAnimId) + { + var nodeAnim = aiAnim->MChannels[nodeAnimId]; + var nodeName = nodeAnim->MNodeName.AsString; + + if (!visitedNodeNames.Contains(nodeName)) + { + visitedNodeNames.Add(nodeName); + ProcessNodeAnimation(animationData.AnimationClips, nodeAnim, ticksPerSec); + } + else + { + Logger.Error($"Animation '{animName}' uses two nodes with the same name ({nodeAnim->MNodeName.AsString}). The animation cannot be resolved."); + return null; + } + } + } + + return animationData; + } + + private unsafe void ProcessNodeAnimation(Dictionary animationClips, NodeAnim* nodeAnim, double ticksPerSec) + { + // Find the nodes on which the animation is performed + var nodeName = nodeAnim->MNodeName.AsString; + + var animationClip = new AnimationClip(); + + // The translation + ProcessAnimationCurveVector(animationClip, nodeAnim->MPositionKeys, nodeAnim->MNumPositionKeys, "Transform.Position", ticksPerSec, true); + // The rotation + ProcessAnimationCurveQuaternion(animationClip, nodeAnim->MRotationKeys, nodeAnim->MNumRotationKeys, "Transform.Rotation", ticksPerSec); + // The scales + ProcessAnimationCurveVector(animationClip, nodeAnim->MScalingKeys, nodeAnim->MNumScalingKeys, "Transform.Scale", ticksPerSec, false); + + if (animationClip.Curves.Count > 0) + animationClips.Add(nodeName, animationClip); + } + + private unsafe void ProcessAnimationCurveVector(AnimationClip animationClip, VectorKey* keys, uint nbKeys, string partialTargetName, double ticksPerSec, bool isTranslation) + { + var animationCurve = new AnimationCurve(); + + // Switch to cubic implicit interpolation mode for Vector3 + animationCurve.InterpolationType = AnimationCurveInterpolationType.Cubic; + + var lastKeyTime = new CompressedTimeSpan(); + + for (uint keyId = 0; keyId < nbKeys; ++keyId) + { + var aiKey = keys[keyId]; + + var key = new KeyFrameData + { + Time = lastKeyTime = Utils.AiTimeToStrideTimeSpan(aiKey.MTime, ticksPerSec), + Value = aiKey.MValue.ToStrideVector3() + }; + + if (isTranslation) + { + // Change of basis: key.Value = (rootTransformInverse * Matrix::Translation(key.Value) * rootTransform).TranslationVector; + Vector3.TransformCoordinate(ref key.Value, ref rootTransform, out key.Value); + } + else + { + // Change of basis: key.Value = (rootTransformInverse * Matrix::Scaling(key.Value) * rootTransform).ScaleVector; + var scale = Vector3.One; + Vector3.TransformNormal(ref scale, ref rootTransformInverse, out scale); + scale *= key.Value; + Vector3.TransformNormal(ref scale, ref rootTransform, out key.Value); + } + + animationCurve.KeyFrames.Add(key); + if (keyId == 0 || keyId == nbKeys - 1) // discontinuity at animation first and last frame + animationCurve.KeyFrames.Add(key); // add 2 times the same frame at discontinuities to have null gradient + } + + animationClip.AddCurve(partialTargetName, animationCurve, false); + + if (nbKeys > 0 && animationClip.Duration < lastKeyTime) + { + animationClip.Duration = lastKeyTime; + } + } + + private unsafe void ProcessAnimationCurveQuaternion(AnimationClip animationClip, QuatKey* keys, uint nbKeys, string partialTargetName, double ticksPerSec) + { + var animationCurve = new AnimationCurve(); + + var lastKeyTime = new CompressedTimeSpan(); + + for (uint keyId = 0; keyId < nbKeys; ++keyId) + { + var aiKey = keys[keyId]; + var key = new KeyFrameData + { + Time = lastKeyTime = Utils.AiTimeToStrideTimeSpan(aiKey.MTime, ticksPerSec), + Value = aiKey.MValue.ToStrideQuaternion() + }; + + key.Value = rootOrientationInverse * key.Value * rootOrientation; + + animationCurve.KeyFrames.Add(key); + } + + animationClip.AddCurve(partialTargetName, animationCurve, false); + + if (nbKeys > 0 && animationClip.Duration < lastKeyTime) + { + animationClip.Duration = lastKeyTime; + } + } + + private unsafe void GenerateUniqueNames(Dictionary finalNames, List baseNames, Func objectToName) + { + var itemNameTotalCount = new Dictionary(); + var itemNameCurrentCount = new Dictionary(); + var tempNames = new List(); + + for (var i = 0; i < baseNames.Count; ++i) + { + // Clean the name by removing unwanted characters + var itemName = baseNames[i]; + + var itemNameSplitPosition = itemName.IndexOf('#'); + if (itemNameSplitPosition != -1) + { + itemName = itemName.Substring(0, itemNameSplitPosition); + } + + itemNameSplitPosition = itemName.IndexOf("__"); + if (itemNameSplitPosition != -1) + { + itemName = itemName.Substring(0, itemNameSplitPosition); + } + + // remove all bad characters + itemName = itemName.Replace(':', '_'); + itemName = itemName.Replace(" ", string.Empty); + + tempNames.Add(itemName); + + // count the occurences of this name + if (!itemNameTotalCount.ContainsKey(itemName)) + itemNameTotalCount.Add(itemName, 1); + else + itemNameTotalCount[itemName]++; + } + + for (var i = 0; i < baseNames.Count; ++i) + { + var lItem = objectToName(i); + var itemName = tempNames[i]; + + if (itemNameTotalCount[itemName] > 1) + { + if (!itemNameCurrentCount.ContainsKey(itemName)) + itemNameCurrentCount.Add(itemName, 1); + else + itemNameCurrentCount[itemName]++; + + itemName = itemName + "_" + itemNameCurrentCount[itemName].ToString(CultureInfo.InvariantCulture); + } + + finalNames.Add(lItem, itemName); + } + } + + private unsafe void GenerateMeshNames(Scene* scene, Dictionary meshNames) + { + var baseNames = new List(); + for (uint i = 0; i < scene->MNumMeshes; i++) + { + var lMesh = scene->MMeshes[i]; + baseNames.Add(lMesh->MName.AsString); + } + + GenerateUniqueNames(meshNames, baseNames, i => (IntPtr)scene->MMeshes[i]); + } + + private unsafe void GenerateAnimationNames(Scene* scene, Dictionary animationNames) + { + var baseNames = new List(); + for (uint i = 0; i < scene->MNumAnimations; i++) + { + var lAnimation = scene->MAnimations[i]; + var animationName = lAnimation->MName.AsString; + baseNames.Add(animationName); + } + + GenerateUniqueNames(animationNames, baseNames, i => (IntPtr)scene->MAnimations[i]); + } + + private unsafe void GenerateNodeNames(Scene* scene, Dictionary nodeNames) + { + var baseNames = new List(); + var orderedNodes = new List(); + + GetNodeNames(scene->MRootNode, baseNames, orderedNodes); + GenerateUniqueNames(nodeNames, baseNames, i => orderedNodes[i]); + } + + private unsafe void GetNodeNames(Node* node, List nodeNames, List orderedNodes) + { + nodeNames.Add(node->MName.AsString); + orderedNodes.Add((IntPtr)node); + + for (uint i = 0; i < node->MNumChildren; ++i) + { + GetNodeNames(node->MChildren[i], nodeNames, orderedNodes); + } + } + + private unsafe void RegisterNodes(Node* fromNode, int parentIndex, Dictionary nodeNames, Dictionary> meshIndexToNodeIndex) + { + var nodeIndex = nodes.Count; + + // assign the index of the node to the index of the mesh + for (uint m = 0; m < fromNode->MNumMeshes; ++m) + { + var meshIndex = fromNode->MMeshes[m]; + + if (!meshIndexToNodeIndex.TryGetValue((int)meshIndex, out var nodeIndices)) + { + nodeIndices = new List(); + meshIndexToNodeIndex.Add((int)meshIndex, nodeIndices); + } + + nodeIndices.Add(nodeIndex); + } + + // Create node + var modelNodeDefinition = new ModelNodeDefinition + { + ParentIndex = parentIndex, + Name = nodeNames[(IntPtr)fromNode], + Flags = ModelNodeFlags.Default + }; + + // Extract scene scaling and rotation from the root node. + // Bake scaling into all node's positions and rotation into the 1st-level nodes. + if (parentIndex == -1) + { + rootTransform = fromNode->MTransformation.ToStrideMatrix(); + + rootTransform.Decompose(out var rootScaling, out rootOrientation, out var rootTranslation); + + rootTransformInverse = Matrix.Invert(rootTransform); + rootOrientationInverse = Quaternion.Invert(rootOrientation); + + modelNodeDefinition.Transform.Rotation = Quaternion.Identity; + modelNodeDefinition.Transform.Scale = Vector3.One; + } + else + { + var transform = rootTransformInverse * fromNode->MTransformation.ToStrideMatrix() * rootTransform; + transform.Decompose(out modelNodeDefinition.Transform.Scale, out modelNodeDefinition.Transform.Rotation, out modelNodeDefinition.Transform.Position); + } + + nodes.Add(modelNodeDefinition); + + // register the children + for (uint child = 0; child < fromNode->MNumChildren; ++child) + { + RegisterNodes(fromNode->MChildren[child], nodeIndex, nodeNames, meshIndexToNodeIndex); + } + } + + private unsafe MeshInfo ProcessMesh(Scene* scene, Silk.NET.Assimp.Mesh* mesh, Dictionary meshNames) + { + List bones = null; + var hasSkinningPosition = false; + var hasSkinningNormal = false; + var totalClusterCount = 0; + + // Build the bone's indices/weights and attach bones to NodeData + //(bones info are present in the mesh so that is why we have to perform that here) + + var vertexIndexToBoneIdWeight = new List>(); + if (mesh->MNumBones > 0) + { + bones = new List(); + + // TODO: change this to support shared meshes across nodes + + // size of the array is already known + vertexIndexToBoneIdWeight.Capacity = (int)mesh->MNumVertices; + for (var i = 0; i < (int)mesh->MNumVertices; i++) + { + vertexIndexToBoneIdWeight.Add(new List<(short, float)>()); + } + + // Build skinning clusters and fill controls points data stutcture + for (uint boneId = 0; boneId < mesh->MNumBones; ++boneId) + { + var bone = mesh->MBones[boneId]; + + // Fill controlPts with bone controls on the mesh + for (uint vtxWeightId = 0; vtxWeightId < bone->MNumWeights; ++vtxWeightId) + { + var vtxWeight = bone->MWeights[vtxWeightId]; + vertexIndexToBoneIdWeight[(int)vtxWeight.MVertexId].Add(((short)boneId, vtxWeight.MWeight)); + } + + // find the node where the bone is mapped - based on the name(?) + var nodeIndex = -1; + var boneName = bone->MName.AsString; + for (var nodeDefId = 0; nodeDefId < nodes.Count; ++nodeDefId) + { + var nodeDef = nodes[nodeDefId]; + if (nodeDef.Name == boneName) + { + nodeIndex = nodeDefId; + break; + } + } + + if (nodeIndex == -1) + { + Logger.Error($"No node found for name {boneId}:{boneName}"); + nodeIndex = 0; + } + + bones.Add(new MeshBoneDefinition + { + NodeIndex = nodeIndex, + LinkToMeshMatrix = rootTransformInverse * bone->MOffsetMatrix.ToStrideMatrix() * rootTransform + }); + } + + NormalizeVertexWeights(vertexIndexToBoneIdWeight, NumberOfBonesPerVertex); + + totalClusterCount = (int)mesh->MNumBones; + if (totalClusterCount > 0) + hasSkinningPosition = true; + } + + // Build the vertex declaration + var vertexElements = new List(); + var vertexStride = 0; + + var positionOffset = vertexStride; + vertexElements.Add(VertexElement.Position(0, vertexStride)); + vertexStride += sizeof(Vector3); + + var normalOffset = vertexStride; + if (mesh->MNormals != null) + { + vertexElements.Add(VertexElement.Normal(0, vertexStride)); + vertexStride += sizeof(Vector3); + } + + var uvOffset = vertexStride; + var sizeUV = sizeof(Vector2); // 3D uv not supported + for (uint uvChannel = 0; uvChannel < Utils.GetNumUVChannels(mesh); ++uvChannel) + { + vertexElements.Add(VertexElement.TextureCoordinate((int)uvChannel, vertexStride)); + vertexStride += sizeUV; + } + + var colorOffset = vertexStride; + var sizeColor = sizeof(Color); + for (uint colorChannel = 0; colorChannel < Utils.GetNumColorChannels(mesh); ++colorChannel) + { + vertexElements.Add(VertexElement.Color((int)colorChannel, vertexStride)); + vertexStride += sizeColor; + } + + var tangentOffset = vertexStride; + if (mesh->MTangents != null) + { + vertexElements.Add(VertexElement.Tangent(0, vertexStride)); + vertexStride += sizeof(Vector3); + } + + var bitangentOffset = vertexStride; + if (mesh->MTangents != null) + { + vertexElements.Add(VertexElement.BiTangent(0, vertexStride)); + vertexStride += sizeof(Vector3); + } + + var blendIndicesOffset = vertexStride; + var controlPointIndices16 = (AllowUnsignedBlendIndices && totalClusterCount > 256) || (!AllowUnsignedBlendIndices && totalClusterCount > 128); + if (vertexIndexToBoneIdWeight.Count > 0) + { + if (controlPointIndices16) + { + if (AllowUnsignedBlendIndices) + { + vertexElements.Add(new VertexElement("BLENDINDICES", 0, PixelFormat.R16G16B16A16_UInt, vertexStride)); + vertexStride += sizeof(ushort) * 4; + } + else + { + vertexElements.Add(new VertexElement("BLENDINDICES", 0, PixelFormat.R16G16B16A16_SInt, vertexStride)); + vertexStride += sizeof(short) * 4; + } + } + else + { + if (AllowUnsignedBlendIndices) + { + vertexElements.Add(new VertexElement("BLENDINDICES", 0, PixelFormat.R8G8B8A8_UInt, vertexStride)); + vertexStride += sizeof(byte) * 4; + } + else + { + vertexElements.Add(new VertexElement("BLENDINDICES", 0, PixelFormat.R8G8B8A8_SInt, vertexStride)); + vertexStride += sizeof(sbyte) * 4; + } + } + } + + var blendWeightOffset = vertexStride; + if (vertexIndexToBoneIdWeight.Count > 0) + { + vertexElements.Add(new VertexElement("BLENDWEIGHT", 0, PixelFormat.R32G32B32A32_Float, vertexStride)); + vertexStride += sizeof(float) * 4; + } + + // Build the vertices data buffer + var vertexBuffer = new byte[vertexStride * mesh->MNumVertices]; + fixed (byte* vertexBufferPtr = &vertexBuffer[0]) + { + var vbPointer = vertexBufferPtr; + for (uint i = 0; i < mesh->MNumVertices; i++) + { + var positionPointer = (Vector3*)(vbPointer + positionOffset); + *positionPointer = mesh->MVertices[i].ToStrideVector3(); + + Vector3.TransformCoordinate(ref *positionPointer, ref rootTransform, out *positionPointer); + + if (mesh->MNormals != null) + { + var normalPointer = (Vector3*)(vbPointer + normalOffset); + *normalPointer = mesh->MNormals[i].ToStrideVector3(); + + Vector3.TransformNormal(ref *normalPointer, ref rootTransform, out *normalPointer); + + if (float.IsNaN(normalPointer->X) || float.IsNaN(normalPointer->Y) || float.IsNaN(normalPointer->Z)) + *normalPointer = new Vector3(1, 0, 0); + else + normalPointer->Normalize(); + } + + for (uint uvChannel = 0; uvChannel < Utils.GetNumUVChannels(mesh); ++uvChannel) + { + var textureCoord = mesh->MTextureCoords[(int)uvChannel][i]; + *((Vector2*)(vbPointer + uvOffset + sizeUV * uvChannel)) = new Vector2(textureCoord.X, textureCoord.Y); // 3D uv not supported + } + + for (uint colorChannel = 0; colorChannel < Utils.GetNumColorChannels(mesh); ++colorChannel) + { + var color = mesh->MColors[(int)colorChannel][i].ToStrideColor(); + *((Color*)(vbPointer + colorOffset + sizeColor * colorChannel)) = color; + } + + if (mesh->MTangents != null) + { + var tangentPointer = (Vector3*)(vbPointer + tangentOffset); + var bitangentPointer = (Vector3*)(vbPointer + bitangentOffset); + *tangentPointer = mesh->MTangents[i].ToStrideVector3(); + *bitangentPointer = mesh->MBitangents[i].ToStrideVector3(); + if (float.IsNaN(tangentPointer->X) || float.IsNaN(tangentPointer->Y) || float.IsNaN(tangentPointer->Z) || + float.IsNaN(bitangentPointer->X) || float.IsNaN(bitangentPointer->Y) || float.IsNaN(bitangentPointer->Z)) + { + var normalPointer = ((Vector3*)(vbPointer + normalOffset)); + Vector3 c1 = Vector3.Cross(*normalPointer, new Vector3(0.0f, 0.0f, 1.0f)); + Vector3 c2 = Vector3.Cross(*normalPointer, new Vector3(0.0f, 1.0f, 0.0f)); + + if (c1.LengthSquared() > c2.LengthSquared()) + *tangentPointer = c1; + else + *tangentPointer = c2; + *bitangentPointer = Vector3.Cross(*normalPointer, *tangentPointer); + } + tangentPointer->Normalize(); + bitangentPointer->Normalize(); + } + + if (vertexIndexToBoneIdWeight.Count > 0) + { + for (var bone = 0; bone < NumberOfBonesPerVertex; ++bone) + { + if (controlPointIndices16) + { + if (AllowUnsignedBlendIndices) + ((ushort*)(vbPointer + blendIndicesOffset))[bone] = (ushort)vertexIndexToBoneIdWeight[(int)i][bone].Item1; + else + ((short*)(vbPointer + blendIndicesOffset))[bone] = vertexIndexToBoneIdWeight[(int)i][bone].Item1; + } + else + { + if (AllowUnsignedBlendIndices) + (vbPointer + blendIndicesOffset)[bone] = (byte)vertexIndexToBoneIdWeight[(int)i][bone].Item1; + else + ((sbyte*)(vbPointer + blendIndicesOffset))[bone] = (sbyte)vertexIndexToBoneIdWeight[(int)i][bone].Item1; + } + + ((float*)(vbPointer + blendWeightOffset))[bone] = vertexIndexToBoneIdWeight[(int)i][bone].Item2; + } + } + + vbPointer += vertexStride; + } + } + + // Build the indices data buffer + var nbIndices = 3 * mesh->MNumFaces; + byte[] indexBuffer; + var is32BitIndex = mesh->MNumVertices > 65535; + if (is32BitIndex) + indexBuffer = new byte[sizeof(uint) * nbIndices]; + else + indexBuffer = new byte[sizeof(ushort) * nbIndices]; + + fixed (byte* indexBufferPtr = &indexBuffer[0]) + { + var ibPointer = indexBufferPtr; + + for (uint i = 0; i < mesh->MNumFaces; i++) + { + if (is32BitIndex) + { + for (int j = 0; j < 3; ++j) + { + *((uint*)ibPointer) = mesh->MFaces[(int)i].MIndices[j]; + ibPointer += sizeof(uint); + } + } + else + { + for (int j = 0; j < 3; ++j) + { + *((ushort*)ibPointer) = (ushort)(mesh->MFaces[(int)i].MIndices[j]); + ibPointer += sizeof(ushort); + } + } + } + } + + // Build the mesh data + var vertexDeclaration = new VertexDeclaration(vertexElements.ToArray()); + var vertexBufferBinding = new VertexBufferBinding(GraphicsSerializerExtensions.ToSerializableVersion(new BufferData(BufferFlags.VertexBuffer, vertexBuffer)), vertexDeclaration, (int)mesh->MNumVertices, vertexDeclaration.VertexStride, 0); + var indexBufferBinding = new IndexBufferBinding(GraphicsSerializerExtensions.ToSerializableVersion(new BufferData(BufferFlags.IndexBuffer, indexBuffer)), is32BitIndex, (int)nbIndices, 0); + + var drawData = new MeshDraw + { + VertexBuffers = new VertexBufferBinding[] { vertexBufferBinding }, + IndexBuffer = indexBufferBinding, + PrimitiveType = PrimitiveType.TriangleList, + DrawCount = (int)nbIndices + }; + + return new MeshInfo + { + Draw = drawData, + Name = meshNames[(IntPtr)mesh], + Bones = bones, + MaterialIndex = (int)mesh->MMaterialIndex, + HasSkinningPosition = hasSkinningPosition, + HasSkinningNormal = hasSkinningNormal, + TotalClusterCount = totalClusterCount + }; + } + + private void NormalizeVertexWeights(List> controlPts, int nbBoneByVertex) + { + for (var vertexId = 0; vertexId < controlPts.Count; ++vertexId) + { + var curVertexWeights = controlPts[vertexId]; + + // check that one vertex has not more than 'nbBoneByVertex' associated bones + if (curVertexWeights.Count > nbBoneByVertex) + { + Logger.Warning( + $"The input file contains vertices that are associated to more than {curVertexWeights.Count} bones. In current version of the system, a single vertex can only be associated to {nbBoneByVertex} bones. Extra bones will be ignored", + new ArgumentOutOfRangeException("To much bones influencing a single vertex")); + } + + // resize the weights so that they contains exactly the number of bone weights required + while (curVertexWeights.Count < nbBoneByVertex) + { + curVertexWeights.Add((0, 0)); + } + + var totalWeight = 0.0f; + for (var boneId = 0; boneId < nbBoneByVertex; ++boneId) + totalWeight += curVertexWeights[boneId].Item2; + + if (totalWeight <= float.Epsilon) // Assimp weights are positive, so in this case all weights are nulls + continue; + + for (var boneId = 0; boneId < nbBoneByVertex; ++boneId) + curVertexWeights[boneId] = (curVertexWeights[boneId].Item1, curVertexWeights[boneId].Item2 / totalWeight); + } + } + +#pragma warning disable IDE0060 // Remove unused parameter + private unsafe void ExtractEmbededTexture(Silk.NET.Assimp.Texture* texture) +#pragma warning restore IDE0060 // Remove unused parameter + { + Logger.Warning("The input file contains embeded textures. Embeded textures are not currently supported. This texture will be ignored", + new NotImplementedException("Embeded textures extraction")); + } + + private unsafe Dictionary ExtractMaterials(Scene* scene, Dictionary materialNames) + { + GenerateMaterialNames(scene, materialNames); + + var materials = new Dictionary(); + for (uint i = 0; i < scene->MNumMaterials; i++) + { + var lMaterial = scene->MMaterials[i]; + var materialName = materialNames[(IntPtr)lMaterial]; + materials.Add(materialName, ProcessMeshMaterial(lMaterial)); + } + return materials; + } + + private unsafe void GenerateMaterialNames(Scene* scene, Dictionary materialNames) + { + var baseNames = new List(); + for (uint i = 0; i < scene->MNumMaterials; i++) + { + var lMaterial = scene->MMaterials[i]; + + var aiMaterial = new AssimpString(); + var materialName = assimp.GetMaterialString(lMaterial, Silk.NET.Assimp.Assimp.MaterialNameBase, 0, 0, ref aiMaterial) == Return.Success ? aiMaterial.AsString : "Material"; + baseNames.Add(materialName); + } + + GenerateUniqueNames(materialNames, baseNames, i => (IntPtr)scene->MMaterials[i]); + } + + private unsafe MaterialAsset ProcessMeshMaterial(Silk.NET.Assimp.Material* pMaterial) + { + var finalMaterial = new MaterialAsset(); + + float specPower = 0; + float opacity = 0; + + bool hasDiffColor = false; + bool hasSpecColor = false; + bool hasAmbientColor = false; + bool hasEmissiveColor = false; + bool hasReflectiveColor = false; + bool hasSpecPower = false; + bool hasOpacity = false; + + var diffColor = System.Numerics.Vector4.Zero; + var specColor = System.Numerics.Vector4.Zero; + var ambientColor = System.Numerics.Vector4.Zero; + var emissiveColor = System.Numerics.Vector4.Zero; + var reflectiveColor = System.Numerics.Vector4.Zero; + var dummyColor = System.Numerics.Vector4.Zero; + + SetMaterialColorFlag(pMaterial, Silk.NET.Assimp.Assimp.MaterialColorDiffuseBase, ref hasDiffColor, ref diffColor, true);// always keep black color for diffuse + SetMaterialColorFlag(pMaterial, Silk.NET.Assimp.Assimp.MaterialColorSpecularBase, ref hasSpecColor, ref specColor, IsNotBlackColor(specColor)); + SetMaterialColorFlag(pMaterial, Silk.NET.Assimp.Assimp.MaterialColorAmbientBase, ref hasAmbientColor, ref ambientColor, IsNotBlackColor(specColor)); + SetMaterialColorFlag(pMaterial, Silk.NET.Assimp.Assimp.MaterialColorEmissiveBase, ref hasEmissiveColor, ref emissiveColor, IsNotBlackColor(emissiveColor)); + SetMaterialColorFlag(pMaterial, Silk.NET.Assimp.Assimp.MaterialColorReflectiveBase, ref hasReflectiveColor, ref reflectiveColor, IsNotBlackColor(reflectiveColor)); + SetMaterialFloatArrayFlag(pMaterial, Silk.NET.Assimp.Assimp.MaterialShininessBase, ref hasSpecPower, specPower, specPower > 0); + SetMaterialFloatArrayFlag(pMaterial, Silk.NET.Assimp.Assimp.MaterialOpacityBase, ref hasOpacity, opacity, opacity < 1.0); + + BuildLayeredSurface(pMaterial, hasDiffColor, false, diffColor.ToStrideColor(), 0.0f, TextureType.Diffuse, finalMaterial); + BuildLayeredSurface(pMaterial, hasSpecColor, false, specColor.ToStrideColor(), 0.0f, TextureType.Specular, finalMaterial); + BuildLayeredSurface(pMaterial, false, false, dummyColor.ToStrideColor(), 0.0f, TextureType.Normals, finalMaterial); + BuildLayeredSurface(pMaterial, false, false, dummyColor.ToStrideColor(), 0.0f, TextureType.Displacement, finalMaterial); + BuildLayeredSurface(pMaterial, hasAmbientColor, false, ambientColor.ToStrideColor(), 0.0f, TextureType.Ambient, finalMaterial); + BuildLayeredSurface(pMaterial, false, hasOpacity, dummyColor.ToStrideColor(), opacity, TextureType.Opacity, finalMaterial); + BuildLayeredSurface(pMaterial, false, hasSpecPower, dummyColor.ToStrideColor(), specPower, TextureType.Shininess, finalMaterial); + BuildLayeredSurface(pMaterial, hasEmissiveColor, false, emissiveColor.ToStrideColor(), 0.0f, TextureType.Emissive, finalMaterial); + BuildLayeredSurface(pMaterial, false, false, dummyColor.ToStrideColor(), 0.0f, TextureType.Height, finalMaterial); + BuildLayeredSurface(pMaterial, hasReflectiveColor, false, reflectiveColor.ToStrideColor(), 0.0f, TextureType.Reflection, finalMaterial); + + return finalMaterial; + } + + private unsafe void SetMaterialColorFlag(Silk.NET.Assimp.Material* pMaterial, string materialColorBase, ref bool hasMatColor, ref System.Numerics.Vector4 matColor, bool condition) + { + if (assimp.GetMaterialColor(pMaterial, materialColorBase, 0, 0, ref matColor) == Return.Success && condition) + { + hasMatColor = true; + } + } + private unsafe void SetMaterialFloatArrayFlag(Silk.NET.Assimp.Material* pMaterial, string materialBase, ref bool hasMatProperty, float matColor, bool condition) + { + if(assimp.GetMaterialFloatArray(pMaterial, materialBase, 0, 0, &matColor, (uint*)0x0) == Return.Success && condition) + { + hasMatProperty = true; + } + } + + private bool IsNotBlackColor(System.Numerics.Vector4 diffColor) + { + return diffColor != System.Numerics.Vector4.Zero; + } + + private unsafe void BuildLayeredSurface(Silk.NET.Assimp.Material* pMat, bool hasBaseColor, bool hasBaseValue, Color4 baseColor, float baseValue, TextureType textureType, MaterialAsset finalMaterial) + { + var nbTextures = assimp.GetMaterialTextureCount(pMat, textureType); + + IComputeColor computeColorNode = null; + int textureCount = 0; + if (nbTextures == 0) + { + if (hasBaseColor) + { + computeColorNode = new ComputeColor(baseColor); + } + //else if (hasBaseValue) + //{ + // computeColorNode = gcnew MaterialFloatComputeNode(baseValue); + //} + } + else + { + computeColorNode = GenerateOneTextureTypeLayers(pMat, textureType, textureCount, finalMaterial); + } + + if (computeColorNode == null) + { + return; + } + + if (textureType == TextureType.Diffuse) + { + if (assimp.GetMaterialTextureCount(pMat, TextureType.Lightmap) > 0) + { + var lightMap = GenerateOneTextureTypeLayers(pMat, TextureType.Lightmap, textureCount, finalMaterial); + if (lightMap != null) + computeColorNode = new ComputeBinaryColor(computeColorNode, lightMap, BinaryOperator.Add); + } + + finalMaterial.Attributes.Diffuse = new MaterialDiffuseMapFeature(computeColorNode); + + // TODO TEMP: Set a default diffuse model + finalMaterial.Attributes.DiffuseModel = new MaterialDiffuseLambertModelFeature(); + } + else if (textureType == TextureType.Specular) + { + var specularFeature = new MaterialSpecularMapFeature + { + SpecularMap = computeColorNode + }; + finalMaterial.Attributes.Specular = specularFeature; + + // TODO TEMP: Set a default specular model + var specularModel = new MaterialSpecularMicrofacetModelFeature + { + Fresnel = new MaterialSpecularMicrofacetFresnelSchlick(), + Visibility = new MaterialSpecularMicrofacetVisibilityImplicit(), + NormalDistribution = new MaterialSpecularMicrofacetNormalDistributionBlinnPhong() + }; + finalMaterial.Attributes.SpecularModel = specularModel; + } + else if (textureType == TextureType.Emissive) + { + // TODO: Add support + } + else if (textureType == TextureType.Ambient) + { + // TODO: Add support + } + else if (textureType == TextureType.Reflection) + { + // TODO: Add support + } + if (textureType == TextureType.Opacity) + { + // TODO: Add support + } + else if (textureType == TextureType.Shininess) + { + // TODO: Add support + } + if (textureType == TextureType.Specular) + { + // TODO: Add support + } + else if (textureType == TextureType.Normals) + { + finalMaterial.Attributes.Surface = new MaterialNormalMapFeature(computeColorNode); + } + else if (textureType == TextureType.Displacement) + { + // TODO: Add support + } + else if (textureType == TextureType.Height) + { + // TODO: Add support + } + } + + private unsafe IComputeColor GenerateOneTextureTypeLayers(Silk.NET.Assimp.Material* pMat, TextureType textureType, int textureCount, MaterialAsset finalMaterial) + { + var stack = Material.Materials.ConvertAssimpStackCppToCs(assimp, pMat, textureType); + + var compositionFathers = new Stack(); + + var sets = new Stack(); + sets.Push(0); + + var nbTextures = assimp.GetMaterialTextureCount(pMat, textureType); + + IComputeColor curComposition = null, newCompositionFather = null; + + var isRootElement = true; + IComputeColor rootMaterial = null; + + while (!stack.IsEmpty) + { + var top = stack.Pop(); + + IComputeColor curCompositionFather = null; + if (!isRootElement) + { + if (compositionFathers.Count == 0) + Logger.Error("Texture Stack Invalid : Operand without Operation."); + + curCompositionFather = compositionFathers.Pop(); + } + + var type = top.Type; + var strength = top.Blend; + var alpha = top.Alpha; + int set = sets.Peek(); + + if (type == Material.StackElementType.Operation) + { + set = sets.Pop(); + var realTop = (Material.StackOperation)top; + var op = realTop.Operation; + var binNode = new ComputeBinaryColor(null, null, BinaryOperator.Add); + + binNode.Operator = op switch + { + Material.Operation.Add3ds or Material.Operation.AddMaya => BinaryOperator.Add, + Material.Operation.Multiply3ds or Material.Operation.MultiplyMaya => BinaryOperator.Multiply, + _ => BinaryOperator.Add, + }; + curComposition = binNode; + } + else if (type == Material.StackElementType.Color) + { + var realTop = (Material.StackColor)top; + var ol = realTop.Color; + curComposition = new ComputeColor(new Color4(ol.R, ol.G, ol.B, alpha)); + } + else if (type == Material.StackElementType.Texture) + { + var realTop = (Material.StackTexture)top; + var texPath = realTop.TexturePath; + var indexUV = realTop.Channel; + curComposition = GetTextureReferenceNode(vfsOutputFilename, texPath, (uint)indexUV, Vector2.One, ConvertTextureMode(realTop.MappingModeU), ConvertTextureMode(realTop.MappingModeV), finalMaterial); + } + + newCompositionFather = curComposition; + + if (strength != 1.0f) + { + var strengthAlpha = strength; + if (type != Material.StackElementType.Color) + strengthAlpha *= alpha; + + var factorComposition = new ComputeFloat4(new Vector4(strength, strength, strength, strengthAlpha)); + curComposition = new ComputeBinaryColor(curComposition, factorComposition, BinaryOperator.Multiply); + } + else if (alpha != 1.0f && type != Material.StackElementType.Color) + { + var factorComposition = new ComputeFloat4(new Vector4(1.0f, 1.0f, 1.0f, alpha)); + curComposition = new ComputeBinaryColor(curComposition, factorComposition, BinaryOperator.Multiply); + } + + if (isRootElement) + { + rootMaterial = curComposition; + isRootElement = false; + compositionFathers.Push(curCompositionFather); + } + else + { + if (set == 0) + { + ((ComputeBinaryColor)curCompositionFather).LeftChild = curComposition; + compositionFathers.Push(curCompositionFather); + sets.Push(1); + } + else if (set == 1) + { + ((ComputeBinaryColor)curCompositionFather).RightChild = curComposition; + } + else + { + Logger.Error($"Texture Stack Invalid : Invalid Operand Number {set}."); + } + } + + if (type == Material.StackElementType.Operation) + { + compositionFathers.Push(newCompositionFather); + sets.Push(0); + } + } + + return rootMaterial; + } + + private static TextureAddressMode ConvertTextureMode(Material.MappingMode mappingMode) + { + return mappingMode switch + { + Material.MappingMode.Clamp => TextureAddressMode.Clamp, + Material.MappingMode.Decal => TextureAddressMode.Border, + Material.MappingMode.Mirror => TextureAddressMode.Mirror, + _ => TextureAddressMode.Wrap, + }; + } + + private ComputeTextureColor GetTextureReferenceNode(string vfsOutputPath, string sourceTextureFile, uint textureUVSetIndex, Vector2 textureUVscaling, TextureAddressMode addressModeU, TextureAddressMode addressModeV, MaterialAsset finalMaterial) + { + // TODO: compare with FBX importer - see if there could be some conflict between texture names + var textureValue = TextureLayerGenerator.GenerateMaterialTextureNode(vfsOutputPath, sourceTextureFile, textureUVSetIndex, textureUVscaling, addressModeU, addressModeV, Logger); + + var attachedReference = AttachedReferenceManager.GetAttachedReference(textureValue.Texture); + var referenceName = attachedReference.Url; + + // find a new and correctName + if (!textureNameCount.ContainsKey(referenceName)) + textureNameCount.Add(referenceName, 1); + else + { + int count = textureNameCount[referenceName]; + textureNameCount[referenceName] = count + 1; + referenceName = string.Concat(referenceName, "_", count); + } + + return textureValue; + } + + private unsafe List ExtractModels(Scene* scene, Dictionary meshNames, Dictionary materialNames, Dictionary nodeNames) + { + GenerateMeshNames(scene, meshNames); + + var meshList = new List(); + for (uint i = 0; i < scene->MNumMeshes; ++i) + { + var mesh = scene->MMeshes[i]; + var lMaterial = scene->MMaterials[mesh->MMaterialIndex]; + + var meshParams = new MeshParameters + { + MeshName = meshNames[(IntPtr)mesh], + MaterialName = materialNames[(IntPtr)lMaterial], + NodeName = SearchMeshNode(scene->MRootNode, i, nodeNames) + }; + + meshList.Add(meshParams); + } + + return meshList; + } + + private unsafe string SearchMeshNode(Node* node, uint meshIndex, Dictionary nodeNames) + { + for (uint i = 0; i < node->MNumMeshes; ++i) + { + if (node->MMeshes[i] == meshIndex) + return nodeNames[(IntPtr)node]; + } + + for (uint i = 0; i < node->MNumChildren; ++i) + { + var res = SearchMeshNode(node->MChildren[i], meshIndex, nodeNames); + if (res != null) + return res; + } + + return null; + } + + private unsafe List ExtractNodeHierarchy(Scene* scene, Dictionary nodeNames) + { + var allNodes = new List(); + GetNodes(scene->MRootNode, 0, nodeNames, allNodes); + return allNodes; + } + + private unsafe void GetNodes(Node* node, int depth, Dictionary nodeNames, List allNodes) + { + var newNodeInfo = new NodeInfo + { + Name = nodeNames[(IntPtr)node], + Depth = depth, + Preserve = true + }; + + allNodes.Add(newNodeInfo); + for (uint i = 0; i < node->MNumChildren; ++i) + GetNodes(node->MChildren[i], depth + 1, nodeNames, allNodes); + } + + private unsafe List ExtractAnimations(Scene* scene, Dictionary animationNames) + { + if (scene->MNumAnimations == 0) + return null; + + GenerateAnimationNames(scene, animationNames); + + var animationList = new List(); + foreach (var animationName in animationNames) + { + animationList.Add(animationName.Value); + } + + return animationList; + } + + private unsafe List ExtractTextureDependencies(Scene* scene) + { + var textureNames = new List(); + + // texture search is done by type so we need to loop on them + var allTextureTypes = new TextureType[] + { + TextureType.Diffuse, + TextureType.Specular, + TextureType.Ambient, + TextureType.Emissive, + TextureType.Height, + TextureType.Normals, + TextureType.Shininess, + TextureType.Opacity, + TextureType.Displacement, + TextureType.Lightmap, + TextureType.Reflection + }; + + for (uint i = 0; i < scene->MNumMaterials; i++) + { + foreach (var textureType in allTextureTypes) + { + var lMaterial = scene->MMaterials[i]; + var nbTextures = assimp.GetMaterialTextureCount(lMaterial, textureType); + + for (uint j = 0; j < nbTextures; ++j) + { + var path = new AssimpString(); + var mapping = TextureMapping.UV; + uint uvIndex = 0; + var blend = 0.0f; + var textureOp = TextureOp.Multiply; + var mapMode = TextureMapMode.Wrap; + uint flags = 0; + + if (assimp.GetMaterialTexture(lMaterial, textureType, j, ref path, ref mapping, ref uvIndex, ref blend, ref textureOp, ref mapMode, ref flags) == Return.Success) + { + var relFileName = path.AsString; + var fileNameToUse = Path.Combine(vfsInputPath, relFileName); + textureNames.Add(fileNameToUse); + break; + } + } + } + } + + return textureNames; + } + } + + public class MeshInfo + { + public MeshDraw Draw; + public List Bones; + public string Name; + public int MaterialIndex; + public bool HasSkinningPosition = false; + public bool HasSkinningNormal = false; + public int TotalClusterCount = 0; + } + + public class MaterialInstantiation + { + public List Parameters; + public MaterialAsset Material; + public string MaterialName; + } + + public unsafe class MaterialInstances + { + public Silk.NET.Assimp.Material* SourceMaterial; + public List Instances = new(); + public string MaterialsName; + } +} diff --git a/sources/tools/Stride.Importer.Assimp/ReadMe.txt b/sources/tools/Stride.Importer.Assimp/ReadMe.txt deleted file mode 100644 index 0e2e9f879c..0000000000 --- a/sources/tools/Stride.Importer.Assimp/ReadMe.txt +++ /dev/null @@ -1,38 +0,0 @@ -======================================================================== - DYNAMIC LINK LIBRARY : Stride.Importer.Assimp Project Overview -======================================================================== - -AppWizard has created this Stride.Importer.Assimp DLL for you. - -This file contains a summary of what you will find in each of the files that -make up your Stride.Importer.Assimp application. - -Stride.Importer.Assimp.vcxproj - This is the main project file for VC++ projects generated using an Application Wizard. - It contains information about the version of Visual C++ that generated the file, and - information about the platforms, configurations, and project features selected with the - Application Wizard. - -Stride.Importer.Assimp.vcxproj.filters - This is the filters file for VC++ projects generated using an Application Wizard. - It contains information about the association between the files in your project - and the filters. This association is used in the IDE to show grouping of files with - similar extensions under a specific node (for e.g. ".cpp" files are associated with the - "Source Files" filter). - -Stride.Importer.Assimp.cpp - This is the main DLL source file. - -Stride.Importer.Assimp.h - This file contains a class declaration. - -AssemblyInfo.cpp - Contains custom attributes for modifying assembly metadata. - -///////////////////////////////////////////////////////////////////////////// -Other notes: - -AppWizard uses "TODO:" to indicate parts of the source code you -should add to or customize. - -///////////////////////////////////////////////////////////////////////////// diff --git a/sources/tools/Stride.Importer.Assimp/Stdafx.cpp b/sources/tools/Stride.Importer.Assimp/Stdafx.cpp deleted file mode 100644 index 84421f9104..0000000000 --- a/sources/tools/Stride.Importer.Assimp/Stdafx.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// Stride.Importer.Assimp.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" diff --git a/sources/tools/Stride.Importer.Assimp/Stdafx.h b/sources/tools/Stride.Importer.Assimp/Stdafx.h deleted file mode 100644 index 23d9648524..0000000000 --- a/sources/tools/Stride.Importer.Assimp/Stdafx.h +++ /dev/null @@ -1,21 +0,0 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, -// but are changed infrequently - -#pragma once - -#pragma warning( disable : 4945 ) - -#include "assimp/Importer.hpp" -#include "assimp/Scene.h" -#include "assimp/IOSystem.hpp" -#pragma make_public(aiScene) - -#include "assimp/PostProcess.h" - -#include - -#include "UtilityFunctions.h" - -#include -#include \ No newline at end of file diff --git a/sources/tools/Stride.Importer.Assimp/Stride.Importer.Assimp.cpp b/sources/tools/Stride.Importer.Assimp/Stride.Importer.Assimp.cpp deleted file mode 100644 index 873cd450f2..0000000000 --- a/sources/tools/Stride.Importer.Assimp/Stride.Importer.Assimp.cpp +++ /dev/null @@ -1,1529 +0,0 @@ -// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) -// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. -#include "stdafx.h" -#include "../Stride.Assimp.Translation/Extension.h" -#include "../Stride.Importer.Common/ImporterUtils.h" - -#include -#include -#include - -using namespace System; -using namespace System::Collections; -using namespace System::Collections::Generic; -using namespace System::Diagnostics; -using namespace System::IO; -using namespace Stride; -using namespace Stride::Core; -using namespace Stride::Core::Diagnostics; -using namespace Stride::Core::IO; -using namespace Stride::Core::Mathematics; -using namespace Stride::Core::Serialization; -using namespace Stride::Core::Serialization::Contents; -using namespace Stride::Assets::Materials; -using namespace Stride::Rendering; -using namespace Stride::Rendering::Materials; -using namespace Stride::Rendering::Materials::ComputeColors; -using namespace Stride::AssimpNet; -using namespace Stride::AssimpNet::Material; -using namespace Stride::Animations; -using namespace Stride::Engine; -using namespace Stride::Extensions; -using namespace Stride::Graphics; -using namespace Stride::Graphics::Data; -using namespace Stride::Shaders; - -using namespace Assimp; -using namespace Stride::Importer::Common; - -namespace Stride { namespace Importer { namespace AssimpNET { - -public ref class MaterialInstantiation -{ -public: - List^ Parameters; - MaterialAsset^ Material; - String^ MaterialName; -}; - -public ref class MaterialInstances -{ -public: - MaterialInstances() - { - Instances = gcnew List(); - } - - aiMaterial* SourceMaterial; - List^ Instances; - String^ MaterialsName; -}; - -public ref class MeshInfo -{ -public: - MeshInfo() - { - HasSkinningPosition = false; - HasSkinningNormal = false; - TotalClusterCount = 0; - } - - MeshDraw^ Draw; - List^ Bones; - String^ Name; - int MaterialIndex; - bool HasSkinningPosition; - bool HasSkinningNormal; - int TotalClusterCount; -}; - -public ref class MeshConverter -{ -public: - property Logger^ Logger; - property bool AllowUnsignedBlendIndices; - -private: - Stopwatch^ internalStopwatch; - - // ----- From here: convertion-wise data ----- // - - String^ vfsInputFilename; - String^ vfsOutputFilename; - String^ vfsInputPath; - - Vector3 rootScaling; - Quaternion rootOrientation; - Quaternion rootOrientationInverse; - Matrix rootTransform; - Matrix rootTransformInverse; - Model^ modelData; - List nodes; - Dictionary nodeMapping; - Dictionary^ textureNameCount; - - List^ effectMeshes; // array of EffectMeshes built from the aiMeshes (same order) - - -public: - MeshConverter(Core::Diagnostics::Logger^ logger) - { - if(logger == nullptr) - logger = Core::Diagnostics::GlobalLogger::GetLogger("Importer Assimp"); - - internalStopwatch = gcnew Stopwatch(); - - Logger = logger; - } - -private: - const aiScene* Initialize(String^ inputFilename, String^ outputFilename, Assimp::Importer* importer, unsigned int flags) - { - // reset all cached data for this new stream convertion - ResetConvertionData(); - - // TODO: correct this hack - auto splitString = inputFilename->Split(':'); - auto unixStyleInputFilename = "/" + splitString[0] + splitString[1]; - - this->vfsInputFilename = inputFilename; - this->vfsOutputFilename = outputFilename; - this->vfsInputPath = VirtualFileSystem::GetParentFolder(inputFilename); - - /* - auto stream = VirtualFileSystem::Drive->OpenStream(unixStyleInputFilename, VirtualFileMode::Open, VirtualFileAccess::Read, VirtualFileShare::Read, StreamFlags::None); - - // check and possibly adjust the input parameters - if(stream == nullptr) - throw gcnew ArgumentNullException("Input Stream"); - - // set file wise info - //absolutePath = absPath; - //relativePath = dstSrcRelativePath; - - // copies the all the stream in local memory - // Not the best memory-wise, need to be optimized - internalStopwatch->StartNew(); - auto memoryStream = gcnew MemoryStream(); - stream->CopyTo(memoryStream); - auto buffer = memoryStream->ToArray(); - Logger->Verbose("File Stream copied - Time taken: {0} ms.", nullptr, internalStopwatch->ElapsedMilliseconds); - - //importer->SetIOHandler(new IOSystemCustom()); - - // load the mesh from its original format to Assimp data structures - internalStopwatch->StartNew(); - - cli::pin_ptr bufferStart = &buffer[0]; - return importer->ReadFileFromMemory(bufferStart, buffer->Length, flags); - */ - - std::string unmanaged = msclr::interop::marshal_as(inputFilename); - - return importer->ReadFile(unmanaged, flags); - } - - // Reset all data related to one specific file conversion - void ResetConvertionData() - { - effectMeshes = gcnew List(); - textureNameCount = gcnew Dictionary(); - } - - void ExtractEmbededTexture(aiTexture* texture) - { - Logger->Warning("The input file contains embeded textures. Embeded textures are not currently supported. This texture will be ignored", - gcnew NotImplementedException("Embeded textures extraction"), - CallerInfo::Get(__FILEW__, __FUNCTIONW__, __LINE__)); - } - - void NormalizeVertexWeights(std::vector > >& controlPts, int nbBoneByVertex) - { - for(unsigned int vertexId=0; vertexId nbBoneByVertex) - Logger->Warning("The input file contains vertices that are associated to more than {0} bones. In current version of the system, a single vertex can only be associated to {0} bones. Extra bones will be ignored", - gcnew ArgumentOutOfRangeException("To much bones influencing a single vertex"), - CallerInfo::Get(__FILEW__, __FUNCTIONW__, __LINE__)); - - // resize the weights so that they contains exactly the number of bone weights required - curVertexWeights.resize(nbBoneByVertex, std::pair(0, 0.0f)); - - float totalWeight = 0.f; - for(int boneId=0; boneIdGet(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) - return (opacity != 1.0); - return false; - } - - MeshInfo^ ProcessMesh(const aiScene* scene, aiMesh* mesh, std::map& meshNames) - { - // constant declaration - const int nbBonesByVertex = 4; - - List^ bones = nullptr; - bool hasSkinningPosition = false; - bool hasSkinningNormal = false; - int totalClusterCount = 0; - - // Build the bone's indices/weights and attach bones to NodeData - //(bones info are present in the mesh so that is why we have to perform that here) - std::vector > > vertexIndexToBoneIdWeight; - if(mesh->HasBones()) - { - bones = gcnew List(); - - // TODO: change this to support shared meshes across nodes - - // size of the array is already known - vertexIndexToBoneIdWeight.resize(mesh->mNumVertices); - - // Build skinning clusters and fill controls points data stutcture - for(unsigned int boneId = 0; boneId < mesh->mNumBones; ++boneId) - { - auto bone = mesh->mBones[boneId]; - - // Fill controlPts with bone controls on the mesh - for(unsigned int vtxWeightId=0; vtxWeightIdmNumWeights; ++vtxWeightId) - { - auto vtxWeight = bone->mWeights[vtxWeightId]; - vertexIndexToBoneIdWeight[vtxWeight.mVertexId].push_back(std::make_pair(boneId, vtxWeight.mWeight)); - } - - // find the node where the bone is mapped - based on the name(?) - int nodeIndex = -1; - auto boneName = gcnew String(bone->mName.C_Str()); - for (int nodeDefId = 0; nodeDefId < nodes.Count; ++nodeDefId) - { - auto nodeDef = nodes[nodeDefId]; - if (nodeDef.Name->Equals(boneName)) - { - nodeIndex = nodeDefId; - break; - } - } - if (nodeIndex == -1) - { - // TODO: log an error - nodeIndex = 0; - } - - MeshBoneDefinition boneDef; - boneDef.NodeIndex = nodeIndex; - boneDef.LinkToMeshMatrix = rootTransformInverse * aiMatrixToMatrix(bone->mOffsetMatrix) * rootTransform; - bones->Add(boneDef); - } - NormalizeVertexWeights(vertexIndexToBoneIdWeight, nbBonesByVertex); - - totalClusterCount = mesh->mNumBones; - if (totalClusterCount > 0) - hasSkinningPosition = true; - } - - // Build the vertex declaration - auto vertexElements = gcnew List(); - int vertexStride = 0; - - int positionOffset = vertexStride; - vertexElements->Add(VertexElement::Position(0, vertexStride)); - vertexStride += sizeof(Vector3); - - int normalOffset = vertexStride; - if (mesh->HasNormals()) - { - vertexElements->Add(VertexElement::Normal(0, vertexStride)); - vertexStride += sizeof(Vector3); - } - - int uvOffset = vertexStride; - const int sizeUV = sizeof(Vector2); // 3D uv not supported - for (unsigned int uvChannel = 0; uvChannel < mesh->GetNumUVChannels(); ++uvChannel) - { - vertexElements->Add(VertexElement::TextureCoordinate(uvChannel, vertexStride)); - vertexStride += sizeUV; - } - - int colorOffset = vertexStride; - const int sizeColor = sizeof(Color); - for (unsigned int colorChannel=0; colorChannel< mesh->GetNumColorChannels(); ++colorChannel) - { - vertexElements->Add(VertexElement::Color(colorChannel, vertexStride)); - vertexStride += sizeColor; - } - - int tangentOffset = vertexStride; - if (mesh->HasTangentsAndBitangents()) - { - vertexElements->Add(VertexElement::Tangent(0, vertexStride)); - vertexStride += sizeof(Vector3); - } - - int bitangentOffset = vertexStride; - if (mesh->HasTangentsAndBitangents()) - { - vertexElements->Add(VertexElement::BiTangent(0, vertexStride)); - vertexStride += sizeof(Vector3); - } - - int blendIndicesOffset = vertexStride; - bool controlPointIndices16 = (AllowUnsignedBlendIndices && totalClusterCount > 256) || (!AllowUnsignedBlendIndices && totalClusterCount > 128); - if (vertexIndexToBoneIdWeight.size() > 0) - { - if (controlPointIndices16) - { - if (AllowUnsignedBlendIndices) - { - vertexElements->Add(VertexElement("BLENDINDICES", 0, PixelFormat::R16G16B16A16_UInt, vertexStride)); - vertexStride += sizeof(unsigned short) * 4; - } - else - { - vertexElements->Add(VertexElement("BLENDINDICES", 0, PixelFormat::R16G16B16A16_SInt, vertexStride)); - vertexStride += sizeof(short) * 4; - } - } - else - { - if (AllowUnsignedBlendIndices) - { - vertexElements->Add(VertexElement("BLENDINDICES", 0, PixelFormat::R8G8B8A8_UInt, vertexStride)); - vertexStride += sizeof(unsigned char) * 4; - } - else - { - vertexElements->Add(VertexElement("BLENDINDICES", 0, PixelFormat::R8G8B8A8_SInt, vertexStride)); - vertexStride += sizeof(char) * 4; - } - } - } - - int blendWeightOffset = vertexStride; - if (vertexIndexToBoneIdWeight.size() > 0) - { - vertexElements->Add(VertexElement("BLENDWEIGHT", 0, PixelFormat::R32G32B32A32_Float, vertexStride)); - vertexStride += sizeof(float) * 4; - } - - // Build the vertices data buffer - auto vertexBuffer = gcnew array(vertexStride * mesh->mNumVertices); - pin_ptr vbPointer = &vertexBuffer[0]; - for (unsigned int i = 0; i < mesh->mNumVertices; i++) - { - auto positionPointer = (Vector3*)(vbPointer + positionOffset); - *positionPointer = aiVector3ToVector3(mesh->mVertices[i]); - Vector3::TransformCoordinate(*positionPointer, rootTransform, *positionPointer); - - if (mesh->HasNormals()) - { - auto normalPointer = ((Vector3*)(vbPointer + normalOffset)); - *normalPointer = aiVector3ToVector3(mesh->mNormals[i]); - Vector3::TransformNormal(*normalPointer, rootTransform, *normalPointer); - if (isnan(normalPointer->X) || isnan(normalPointer->Y) || isnan(normalPointer->Z)) - *normalPointer = Vector3(1, 0, 0); - else - normalPointer->Normalize(); - } - - for (unsigned int uvChannel = 0; uvChannel < mesh->GetNumUVChannels(); ++uvChannel) - { - auto textureCoord = mesh->mTextureCoords[uvChannel][i]; - *((Vector2*)(vbPointer + uvOffset + sizeUV*uvChannel)) = Vector2(textureCoord.x, textureCoord.y); // 3D uv not supported - } - - for (unsigned int colorChannel=0; colorChannel< mesh->GetNumColorChannels(); ++colorChannel) - { - auto color = aiColor4ToColor(mesh->mColors[colorChannel][i]); - *((Color*)(vbPointer + colorOffset + sizeColor*colorChannel)) = color; - } - - if (mesh->HasTangentsAndBitangents()) - { - auto tangentPointer = ((Vector3*)(vbPointer + tangentOffset)); - auto bitangentPointer = ((Vector3*)(vbPointer + bitangentOffset)); - *tangentPointer = aiVector3ToVector3(mesh->mTangents[i]); - *bitangentPointer = aiVector3ToVector3(mesh->mBitangents[i]); - if (isnan(tangentPointer->X) || isnan(tangentPointer->Y) || isnan(tangentPointer->Z) || - isnan(bitangentPointer->X) || isnan(bitangentPointer->Y) || isnan(bitangentPointer->Z)) - { - //assert(mesh->HasNormals()); - auto normalPointer = ((Vector3*)(vbPointer + normalOffset)); - Vector3 c1 = Vector3::Cross(*normalPointer, Vector3(0.0, 0.0, 1.0)); - Vector3 c2 = Vector3::Cross(*normalPointer, Vector3(0.0, 1.0, 0.0)); - - if (c1.LengthSquared() > c2.LengthSquared()) - *tangentPointer = c1; - else - *tangentPointer = c2; - *bitangentPointer = Vector3::Cross(*normalPointer, *tangentPointer); - } - tangentPointer->Normalize(); - bitangentPointer->Normalize(); - } - - if (vertexIndexToBoneIdWeight.size() > 0) - { - for(int bone=0; bonemNumFaces; - array^ indexBuffer; - bool is32BitIndex = mesh->mNumVertices > 65535; - if (is32BitIndex) - indexBuffer = gcnew array(sizeof(unsigned int) * nbIndices); - else - indexBuffer = gcnew array(sizeof(unsigned short) * nbIndices); - - pin_ptr ibPointer = &indexBuffer[0]; - for (unsigned int i = 0; i < mesh->mNumFaces; i++) - { - if (is32BitIndex) - { - for (int j = 0; j < 3; ++j) - { - *((unsigned int*)ibPointer) = mesh->mFaces[i].mIndices[j]; - ibPointer += sizeof(unsigned int); - } - } - else - { - for (int j = 0; j < 3; ++j) - { - *((unsigned short*)ibPointer) = (unsigned short)(mesh->mFaces[i].mIndices[j]); - ibPointer += sizeof(unsigned short); - } - } - } - - // Build the mesh data - auto vertexDeclaration = gcnew VertexDeclaration(vertexElements->ToArray()); - auto vertexBufferBinding = VertexBufferBinding(GraphicsSerializerExtensions::ToSerializableVersion(gcnew BufferData(BufferFlags::VertexBuffer, vertexBuffer)), vertexDeclaration, mesh->mNumVertices, vertexDeclaration->VertexStride, 0); - auto indexBufferBinding = gcnew IndexBufferBinding(GraphicsSerializerExtensions::ToSerializableVersion(gcnew BufferData(BufferFlags::IndexBuffer, indexBuffer)), is32BitIndex, nbIndices, 0); - - auto drawData = gcnew MeshDraw(); - auto vbb = gcnew List(); - vbb->Add(vertexBufferBinding); - drawData->VertexBuffers = vbb->ToArray(); - drawData->IndexBuffer = indexBufferBinding; - drawData->PrimitiveType = PrimitiveType::TriangleList; - drawData->DrawCount = nbIndices; - - auto meshInfo = gcnew MeshInfo(); - meshInfo->Draw = drawData; - meshInfo->Name = gcnew String(meshNames[mesh].c_str()); - meshInfo->Bones = bones; - meshInfo->MaterialIndex = mesh->mMaterialIndex; - meshInfo->HasSkinningPosition = hasSkinningPosition; - meshInfo->HasSkinningNormal = hasSkinningNormal; - meshInfo->TotalClusterCount = totalClusterCount; - - return meshInfo; - } - - // Register all the nodes in dictionnaries - void RegisterNodes(aiNode* fromNode, int parentIndex, std::map& nodeNames, std::map*>& meshIndexToNodeIndex) - { - int nodeIndex = nodes.Count; - - // assign the index of the node to the index of the mesh - for(unsigned int m=0; mmNumMeshes; ++m) - { - int meshIndex = fromNode->mMeshes[m]; - - if (meshIndexToNodeIndex.find(meshIndex) == meshIndexToNodeIndex.end()) - meshIndexToNodeIndex[meshIndex] = new std::vector(); - meshIndexToNodeIndex[meshIndex]->push_back(nodeIndex); - } - - // Create node - ModelNodeDefinition modelNodeDefinition; - modelNodeDefinition.ParentIndex = parentIndex; - modelNodeDefinition.Name = gcnew String(nodeNames[fromNode].c_str()); - modelNodeDefinition.Flags = ModelNodeFlags::Default; - - // Extract scene scaling and rotation from the root node. - // Bake scaling into all node's positions and rotation into the 1st-level nodes. - if (parentIndex == -1) - { - Vector3 rootTranslation; - rootTransform = aiMatrixToMatrix(fromNode->mTransformation); - rootTransform.Decompose(rootScaling, rootOrientation, rootTranslation); - rootTransformInverse = Matrix::Invert(rootTransform); - rootOrientationInverse = Quaternion::Invert(rootOrientation); - - modelNodeDefinition.Transform.Rotation = Quaternion::Identity; - modelNodeDefinition.Transform.Scale = Vector3::One; - } - else - { - Vector3 scale; - Vector3 translation; - Quaternion rotation; - - auto transform = Matrix::Invert(rootTransform) * aiMatrixToMatrix(fromNode->mTransformation) * rootTransform; - transform.Decompose(modelNodeDefinition.Transform.Scale, modelNodeDefinition.Transform.Rotation, modelNodeDefinition.Transform.Position); - } - - nodes.Add(modelNodeDefinition); - - // register the children - for(unsigned int child=0; childmNumChildren; ++child) - { - RegisterNodes(fromNode->mChildren[child], nodeIndex, nodeNames, meshIndexToNodeIndex); - } - } - - void ProcessAnimationCurveVector(AnimationClip^ animationClip, const aiVectorKey* keys, unsigned int nbKeys, String^ partialTargetName, double ticksPerSec, bool isTranslation) - { - auto animationCurve = gcnew AnimationCurve(); - - // Switch to cubic implicit interpolation mode for Vector3 - animationCurve->InterpolationType = AnimationCurveInterpolationType::Cubic; - - CompressedTimeSpan lastKeyTime; - - for(unsigned int keyId=0; keyId key; - - key.Time = lastKeyTime = aiTimeToXkTimeSpan(aiKey.mTime, ticksPerSec); - key.Value = aiVector3ToVector3(aiKey.mValue); - - if (isTranslation) - { - // Change of basis: key.Value = (rootTransformInverse * Matrix::Translation(key.Value) * rootTransform).TranslationVector; - Vector3::TransformCoordinate(key.Value, rootTransform, key.Value); - } - else - { - // Change of basis: key.Value = (rootTransformInverse * Matrix::Scaling(key.Value) * rootTransform).ScaleVector; - Vector3 scale = Vector3::One; - Vector3::TransformNormal(scale, rootTransformInverse, scale); - scale *= key.Value; - Vector3::TransformNormal(scale, rootTransform, key.Value); - } - - animationCurve->KeyFrames->Add(key); - if(keyId == 0 || keyId == nbKeys-1) // discontinuity at animation first and last frame - animationCurve->KeyFrames->Add(key); // add 2 times the same frame at discontinuities to have null gradient - } - - animationClip->AddCurve(partialTargetName, animationCurve, false); - - if (nbKeys > 0) - { - if (animationClip->Duration < lastKeyTime) - animationClip->Duration = lastKeyTime; - } - } - - void ProcessAnimationCurveQuaternion(AnimationClip^ animationClip, const aiQuatKey* keys, unsigned int nbKeys, String^ partialTargetName, double ticksPerSec) - { - auto animationCurve = gcnew AnimationCurve(); - - CompressedTimeSpan lastKeyTime; - - for(unsigned int keyId=0; keyId key; - - key.Time = lastKeyTime = aiTimeToXkTimeSpan(aiKey.mTime, ticksPerSec); - key.Value = aiQuaternionToQuaternion(aiKey.mValue); - - key.Value = rootOrientationInverse * key.Value * rootOrientation; - - animationCurve->KeyFrames->Add(key); - } - - animationClip->AddCurve(partialTargetName, animationCurve, false); - - if (nbKeys > 0) - { - if (animationClip->Duration < lastKeyTime) - animationClip->Duration = lastKeyTime; - } - } - - void ProcessNodeAnimation(Dictionary^ animationClips, const aiNodeAnim* nodeAnim, double ticksPerSec) - { - // Find the nodes on which the animation is performed - auto nodeName = aiStringToString(nodeAnim->mNodeName); - - auto animationClip = gcnew AnimationClip(); - - // The translation - ProcessAnimationCurveVector(animationClip, nodeAnim->mPositionKeys, nodeAnim->mNumPositionKeys, "Transform.Position", ticksPerSec, true); - // The rotation - ProcessAnimationCurveQuaternion(animationClip, nodeAnim->mRotationKeys, nodeAnim->mNumRotationKeys, "Transform.Rotation", ticksPerSec); - // The scales - ProcessAnimationCurveVector(animationClip, nodeAnim->mScalingKeys, nodeAnim->mNumScalingKeys, "Transform.Scale", ticksPerSec, false); - - if (animationClip->Curves->Count > 0) - animationClips->Add(nodeName, animationClip); - } - - Skeleton^ ProcessSkeleton(const aiScene* scene) - { - std::map nodeNames; - GenerateNodeNames(scene, nodeNames); - - // register the nodes and fill hierarchy - std::map*> meshIndexToNodeIndex; - RegisterNodes(scene->mRootNode, -1, nodeNames, meshIndexToNodeIndex); - - auto skeleton = gcnew Skeleton(); - skeleton->Nodes = nodes.ToArray(); - - return skeleton; - } - - AnimationInfo^ ProcessAnimation(const aiScene* scene) - { - auto animationData = gcnew AnimationInfo(); - std::set visitedNodeNames; - - if (scene->mNumAnimations > 1) - Logger->Warning(String::Format("There is {0} animations in this file, using only the first one.", scene->mNumAnimations), - CallerInfo::Get(__FILEW__, __FUNCTIONW__, __LINE__)); - - std::map nodeNames; - GenerateNodeNames(scene, nodeNames); - - // register the nodes and fill hierarchy - std::map*> meshIndexToNodeIndex; - RegisterNodes(scene->mRootNode, -1, nodeNames, meshIndexToNodeIndex); - - for (unsigned int i = 0; i < min(1, scene->mNumAnimations); ++i) - { - auto aiAnim = scene->mAnimations[i]; - - // animation speed - auto ticksPerSec = aiAnim->mTicksPerSecond; - - animationData->Duration = aiTimeToXkTimeSpan(aiAnim->mDuration, ticksPerSec); - - // Assimp animations have two different channels of animations ((1) on Nodes, (2) on Meshes). - // Nevertheless the second one do not seems to be usable in assimp 3.0 so it will be ignored here. - - // name of the animation (dropped) - auto animName = aiStringToString(aiAnim->mName); // used only be the logger - - // animation using meshes (not supported) - for(unsigned int meshAnimId = 0; meshAnimIdmNumMeshChannels; ++meshAnimId) - { - auto meshName = aiStringToString(aiAnim->mMeshChannels[meshAnimId]->mName); - Logger->Warning(String::Format("Mesh animation are not currently supported. Animation '{0}' on mesh {1} will be ignored", animName, meshName), - CallerInfo::Get(__FILEW__, __FUNCTIONW__, __LINE__)); - } - - // animation on nodes - for(unsigned int nodeAnimId=0; nodeAnimIdmNumChannels; ++nodeAnimId) - { - auto nodeAnim = aiAnim->mChannels[nodeAnimId]; - auto nodeName = std::string(nodeAnim->mNodeName.C_Str()); - if (visitedNodeNames.find(nodeName) == visitedNodeNames.end()) - { - visitedNodeNames.insert(nodeName); - ProcessNodeAnimation(animationData->AnimationClips, nodeAnim, ticksPerSec); - } - else - { - Logger->Error(String::Format("Animation '{0}' uses two nodes with the same name ({1}). The animation cannot be resolved.", animName, aiStringToString(nodeAnim->mNodeName)), - CallerInfo::Get(__FILEW__, __FUNCTIONW__, __LINE__)); - return nullptr; - } - } - } - return animationData; - } - - ComputeTextureColor^ GetTextureReferenceNode(String^ vfsOutputPath, String^ sourceTextureFile, size_t textureUVSetIndex, Vector2 textureUVscaling, TextureAddressMode addressModeU, TextureAddressMode addressModeV, MaterialAsset^ finalMaterial, Stride::Core::Diagnostics::Logger^ logger) - { - // TODO: compare with FBX importer - see if there could be some conflict between texture names - auto textureValue = TextureLayerGenerator::GenerateMaterialTextureNode(vfsOutputPath, sourceTextureFile, textureUVSetIndex, textureUVscaling, addressModeU, addressModeV, Logger); - - auto attachedReference = AttachedReferenceManager::GetAttachedReference(textureValue->Texture); - auto referenceName = attachedReference->Url; - - // find a new and correctName - if (!textureNameCount->ContainsKey(referenceName)) - textureNameCount->Add(referenceName, 1); - else - { - int count = textureNameCount[referenceName]; - textureNameCount[referenceName] = count + 1; - referenceName = String::Concat(referenceName, "_", count); - } - - return textureValue; - } - - IComputeColor^ GenerateOneTextureTypeLayers(aiMaterial* pMat, aiTextureType textureType, int& textureCount, Stride::Assets::Materials::MaterialAsset^ finalMaterial) - { - AssimpNet::Material::Stack^ stack = NetTranslation::Materials::convertAssimpStackCppToCs(pMat, textureType); - int set; - System::Collections::Stack^ compositionFathers = gcnew System::Collections::Stack(); - std::stack sets; - - sets.push(0); - auto nbTextures = pMat->GetTextureCount(textureType); - IComputeColor^ curComposition = nullptr, ^ newCompositionFather = nullptr; - IComputeColor^ curCompositionFather = nullptr; - - bool isRootElement = true; - IComputeColor^ rootMaterial = nullptr; - - while (!stack->IsEmpty) - { - auto top = stack->Pop(); - - if (!isRootElement) - { - if (compositionFathers->Count == 0) - Logger->Error("Texture Stack Invalid : Operand without Operation.", (CallerInfo^)nullptr); - - curCompositionFather = (IComputeColor^)compositionFathers->Pop(); - } - - set = sets.top(); - sets.pop(); - auto type = top->type; - auto strength = top->blend; - auto alpha = top->alpha; - - if (type == AssimpNet::Material::StackType::Operation) - { - auto realTop = (AssimpNet::Material::StackOperation^) top; - AssimpNet::Material::Operation op = realTop->operation; - auto binNode = gcnew ComputeBinaryColor(nullptr, nullptr, BinaryOperator::Add); - - switch (op) - { - case AssimpNet::Material::Operation::Add3ds: - case AssimpNet::Material::Operation::AddMaya: - binNode->Operator = BinaryOperator::Add; //BinaryOperator::Add3ds; - break; - case AssimpNet::Material::Operation::Multiply3ds: - case AssimpNet::Material::Operation::MultiplyMaya: - binNode->Operator = BinaryOperator::Multiply; - break; - default: - binNode->Operator = BinaryOperator::Add; - break; - } - - curComposition = binNode; - } - else if (type == AssimpNet::Material::StackType::Color) - { - auto realTop = (AssimpNet::Material::StackColor^)top; - Color3 col = realTop->color; - curComposition = gcnew ComputeColor(Color4(col.R, col.G, col.B, alpha)); - } - else if (type == AssimpNet::Material::StackType::Texture) - { - auto realTop = (AssimpNet::Material::StackTexture^)top; - String ^texPath = realTop->texturePath; - int indexUV = realTop->channel; - auto textureValue = GetTextureReferenceNode(vfsOutputFilename, texPath, indexUV, Vector2::One, ConvertTextureMode(realTop->mappingModeU), ConvertTextureMode(realTop->mappingModeV), finalMaterial, Logger); - curComposition = textureValue; - } - - newCompositionFather = curComposition; - - if (strength != 1.f) - { - float strengthAlpha = strength; - if (type != AssimpNet::Material::StackType::Color) - strengthAlpha *= alpha; - - - auto factorComposition = gcnew ComputeFloat4(Vector4(strength, strength, strength, strengthAlpha)); - curComposition = gcnew ComputeBinaryColor(curComposition, factorComposition, BinaryOperator::Multiply); - } - else if (alpha != 1.f && type != AssimpNet::Material::StackType::Color) - { - auto factorComposition = gcnew ComputeFloat4(Vector4(1.0f, 1.0f, 1.0f, alpha)); - curComposition = gcnew ComputeBinaryColor(curComposition, factorComposition, BinaryOperator::Multiply); - } - - if (isRootElement) - { - rootMaterial = curComposition; - isRootElement = false; - compositionFathers->Push(curCompositionFather); - } - else - { - if (set == 0) - { - ((ComputeBinaryColor^)curCompositionFather)->LeftChild = curComposition; - compositionFathers->Push(curCompositionFather); - sets.push(1); - } - else if (set == 1) - { - ((ComputeBinaryColor^)curCompositionFather)->RightChild = curComposition; - } - else - { - Logger->Error(String::Format("Texture Stack Invalid : Invalid Operand Number {0}.", set), (CallerInfo^)nullptr); - } - } - - if (type == AssimpNet::Material::StackType::Operation) - { - compositionFathers->Push(newCompositionFather); - sets.push(0); - } - } - - return rootMaterial; - } - - static TextureAddressMode ConvertTextureMode(MappingMode mappingMode) - { - switch (mappingMode) - { - case MappingMode::Clamp: - return TextureAddressMode::Clamp; - case MappingMode::Decal: - return TextureAddressMode::Border; - case MappingMode::Mirror: - return TextureAddressMode::Mirror; - default: - case MappingMode::Wrap: - return TextureAddressMode::Wrap; - } - } - - void BuildLayeredSurface(aiMaterial* pMat, bool hasBaseColor, bool hasBaseValue, Color4 baseColor, float baseValue, aiTextureType textureType, Stride::Assets::Materials::MaterialAsset^ finalMaterial) - { - auto nbTextures = pMat->GetTextureCount(textureType); - - IComputeColor^ computeColorNode; - int textureCount = 0; - if (nbTextures == 0) - { - if (hasBaseColor) - { - computeColorNode = gcnew ComputeColor(baseColor); - } - //else if (hasBaseValue) - //{ - // computeColorNode = gcnew MaterialFloatComputeNode(baseValue); - //} - } - else - { - computeColorNode = GenerateOneTextureTypeLayers(pMat, textureType, textureCount, finalMaterial); - } - - if (computeColorNode == nullptr) - { - return; - } - - if (textureType == aiTextureType_DIFFUSE) - { - if (pMat->GetTextureCount(aiTextureType_LIGHTMAP) > 0) - { - auto lightMap = GenerateOneTextureTypeLayers(pMat, aiTextureType_LIGHTMAP, textureCount, finalMaterial); - if (lightMap != nullptr) - computeColorNode = gcnew ComputeBinaryColor(computeColorNode, lightMap, BinaryOperator::Add); - } - - finalMaterial->Attributes->Diffuse = gcnew MaterialDiffuseMapFeature(computeColorNode); - - // TODO TEMP: Set a default diffuse model - finalMaterial->Attributes->DiffuseModel = gcnew MaterialDiffuseLambertModelFeature(); - } - else if (textureType == aiTextureType_SPECULAR) - { - auto specularFeature = gcnew MaterialSpecularMapFeature(); - specularFeature->SpecularMap = computeColorNode; - finalMaterial->Attributes->Specular = specularFeature; - - // TODO TEMP: Set a default specular model - auto specularModel = gcnew MaterialSpecularMicrofacetModelFeature(); - specularModel->Fresnel = gcnew MaterialSpecularMicrofacetFresnelSchlick(); - specularModel->Visibility = gcnew MaterialSpecularMicrofacetVisibilityImplicit(); - specularModel->NormalDistribution = gcnew MaterialSpecularMicrofacetNormalDistributionBlinnPhong(); - finalMaterial->Attributes->SpecularModel = specularModel; - } - else if (textureType == aiTextureType_EMISSIVE) - { - // TODO: Add support - } - else if (textureType == aiTextureType_AMBIENT) - { - // TODO: Add support - } - else if (textureType == aiTextureType_REFLECTION) - { - // TODO: Add support - } - if (textureType == aiTextureType_OPACITY) - { - // TODO: Add support - } - else if (textureType == aiTextureType_SHININESS) - { - // TODO: Add support - } - if (textureType == aiTextureType_SPECULAR) - { - // TODO: Add support - } - else if (textureType == aiTextureType_NORMALS) - { - finalMaterial->Attributes->Surface = gcnew MaterialNormalMapFeature(computeColorNode); - } - else if (textureType == aiTextureType_DISPLACEMENT) - { - // TODO: Add support - } - else if (textureType == aiTextureType_SHININESS) - { - // TODO: Add support - } - else if (textureType == aiTextureType_HEIGHT) - { - // TODO: Add support - } - } - - MaterialAsset^ ProcessMeshMaterial(aiMaterial* pMaterial) - { - auto finalMaterial = gcnew MaterialAsset(); - - // Set material specular components - float specIntensity; - if (AI_SUCCESS == pMaterial->Get(AI_MATKEY_SHININESS_STRENGTH, specIntensity)) - { - if (specIntensity > 0) - { - // TODO: Add Specular Intensity - //auto specularIntensityMap = gcnew MaterialFloatComputeColor(specIntensity); - //specularIntensityMap->Key = MaterialKeys::SpecularIntensity; - //specularIntensityMap->AutoAssignKey = false; - //specularIntensityMap->IsReducible = false; - //finalMaterial->AddColorNode(MaterialParameters::SpecularIntensityMap, "specularIntensity", specularIntensityMap); - } - } - - //// --------------------------------------------------------------------------------- - // // Iterate on all custom Stride Properties and add them to the mesh. - // // Key must be in the format: Stride_KeyName - // // --------------------------------------------------------------------------------- - //for(unsigned int i = 0; imNumProperties; ++i) - //{ - // auto pProp = pMaterial->mProperties[i]; - // auto propertyName = aiStringToString(pProp->mKey); - // if (propertyName->StartsWith("PX_")) - // { - // int index = propertyName->IndexOf('_'); - // propertyName = propertyName->Substring(index); - // propertyName = propertyName->Replace('_','.'); - // // TODO Stride Change name - // propertyName = gcnew String("Stride.Rendering") + propertyName; - - // switch (pProp->mDataLength) - // { - // case sizeof(double): - // { - // auto value = *((double*)pProp->mData); -// ValueParameterKey^ key = gcnew ValueParameterKey(propertyName, 1); - // finalMaterial->SetParameter(key, (float)value); - // } - // break; - // case 3*sizeof(double): - // { - // auto value = (double*)pProp->mData; -// ValueParameterKey^ key = gcnew ValueParameterKey(propertyName, 1); - // finalMaterial->SetParameter(key, Vector3((float)value[0], (float)value[1], (float)value[2])); - // } - // break; - // default: - // Console::WriteLine("Warning, Type for property [{0}] is not supported", propertyName); - // break; - // } - // } - //} - - // Build the material Diffuse, Specular, NormalMap and DisplacementColor surfaces. - aiColor3D color; - Color4 diffColor; - Color4 specColor; - Color4 ambientColor; - Color4 emissiveColor; - Color4 reflectiveColor; - Color4 dummyColor; - float specPower; - float opacity; - - bool hasDiffColor = false; - bool hasSpecColor = false; - bool hasAmbientColor = false; - bool hasEmissiveColor = false; - bool hasReflectiveColor = false; - bool hasSpecPower = false; - bool hasOpacity = false; - - if(pMaterial->Get(AI_MATKEY_COLOR_DIFFUSE, color) == AI_SUCCESS) // always keep black color for diffuse - { - diffColor = aiColor3ToColor4(color); - hasDiffColor = true; - } - if(pMaterial->Get(AI_MATKEY_COLOR_SPECULAR, color) == AI_SUCCESS && IsNotBlackColor(color)) - { - specColor = aiColor3ToColor4(color); - hasSpecColor = true; - } - if(pMaterial->Get(AI_MATKEY_COLOR_AMBIENT, color) == AI_SUCCESS && IsNotBlackColor(color)) - { - ambientColor = aiColor3ToColor4(color); - hasAmbientColor = true; - } - if(pMaterial->Get(AI_MATKEY_COLOR_EMISSIVE, color) == AI_SUCCESS && IsNotBlackColor(color)) - { - emissiveColor = aiColor3ToColor4(color); - hasEmissiveColor = true; - } - if(pMaterial->Get(AI_MATKEY_COLOR_REFLECTIVE, color) == AI_SUCCESS && IsNotBlackColor(color)) - { - reflectiveColor = aiColor3ToColor4(color); - hasReflectiveColor = true; - } - - hasSpecPower = (AI_SUCCESS == pMaterial->Get(AI_MATKEY_SHININESS, specPower) && specPower > 0); - if(pMaterial->Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS && opacity < 1.0) - { - //finalMaterial->Parameters->Set(MaterialKeys::HasTransparency, true); - hasOpacity = true; - } - - BuildLayeredSurface(pMaterial, hasDiffColor, false, diffColor, 0.0f, aiTextureType_DIFFUSE, finalMaterial); - BuildLayeredSurface(pMaterial, hasSpecColor, false, specColor, 0.0f, aiTextureType_SPECULAR, finalMaterial); - BuildLayeredSurface(pMaterial, false, false, dummyColor, 0.0f, aiTextureType_NORMALS, finalMaterial); - BuildLayeredSurface(pMaterial, false, false, dummyColor, 0.0f, aiTextureType_DISPLACEMENT, finalMaterial); - BuildLayeredSurface(pMaterial, hasAmbientColor, false, ambientColor, 0.0f, aiTextureType_AMBIENT, finalMaterial); - BuildLayeredSurface(pMaterial, false, hasOpacity, dummyColor, opacity, aiTextureType_OPACITY, finalMaterial); - BuildLayeredSurface(pMaterial, false, hasSpecPower, dummyColor, specPower, aiTextureType_SHININESS, finalMaterial); - BuildLayeredSurface(pMaterial, hasEmissiveColor, false, emissiveColor, 0.0f, aiTextureType_EMISSIVE, finalMaterial); - BuildLayeredSurface(pMaterial, false, false, dummyColor, 0.0f, aiTextureType_HEIGHT, finalMaterial); - BuildLayeredSurface(pMaterial, hasReflectiveColor, false, reflectiveColor, 0.0f, aiTextureType_REFLECTION, finalMaterial); - - return finalMaterial; - } - - bool IsNotBlackColor(aiColor3D color) - { - return color.r != 0 || color.g != 0 || color.b != 0; - } - - template - void GenerateUniqueNames(std::map& finalNames, std::vector& baseNames, T** objectsToName) - { - std::map itemNameTotalCount; - std::map itemNameCurrentCount; - std::vector tempNames; - - for (int i = 0; i < baseNames.size(); ++i) - { - // Clean the name by removing unwanted characters - T* lItem = objectsToName[i]; - std::string itemName = baseNames[i]; - - auto itemPart = std::string(); - - size_t itemNameSplitPosition = itemName.find('#'); - if (itemNameSplitPosition != std::string::npos) - { - itemPart = itemName.substr(itemNameSplitPosition + 1); - itemName = itemName.substr(0, itemNameSplitPosition); - } - - itemNameSplitPosition = itemNameSplitPosition = itemName.find("__"); - if (itemNameSplitPosition != std::string::npos) - { - itemPart = itemName.substr(itemNameSplitPosition + 2); - itemName = itemName.substr(0, itemNameSplitPosition); - } - - // remove all bad characters - ReplaceCharacter(itemName, ':', '_'); - RemoveCharacter(itemName, ' '); - tempNames.push_back(itemName); - - // count the occurences of this name - if (itemNameTotalCount.count(itemName) == 0) - itemNameTotalCount[itemName] = 1; - else - itemNameTotalCount[itemName] = itemNameTotalCount[itemName] + 1; - } - - for (int i = 0; i < baseNames.size(); ++i) - { - T* lItem = objectsToName[i]; - auto itemName = tempNames[i]; - int currentCount = 0; - - if (itemNameTotalCount[itemName] > 1) - { - if (itemNameCurrentCount.count(itemName) == 0) - itemNameCurrentCount[itemName] = 1; - else - itemNameCurrentCount[itemName] = itemNameCurrentCount[itemName] + 1; - - itemName = itemName + "_" + std::to_string(itemNameCurrentCount[itemName]); - } - - finalNames[lItem] = itemName; - } - } - - void GenerateMaterialNames(const aiScene* scene, std::map& materialNames) - { - std::vector baseNames; - for (uint32_t i = 0; i < scene->mNumMaterials; i++) - { - auto lMaterial = scene->mMaterials[i]; - - aiString aiName; - auto materialName = (lMaterial->Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) - ? std::string(aiName.C_Str()) - : "Material"; - baseNames.push_back(materialName); - } - - GenerateUniqueNames(materialNames, baseNames, scene->mMaterials); - } - - void GenerateMeshNames(const aiScene* scene, std::map& meshNames) - { - std::vector baseNames; - for (uint32_t i = 0; i < scene->mNumMeshes; i++) - { - auto lMesh = scene->mMeshes[i]; - std::string meshName = std::string(lMesh->mName.C_Str()); - baseNames.push_back(meshName); - } - - GenerateUniqueNames(meshNames, baseNames, scene->mMeshes); - } - - void GenerateAnimationNames(const aiScene* scene, std::map& animationNames) - { - std::vector baseNames; - for (uint32_t i = 0; i < scene->mNumAnimations; i++) - { - auto lAnimation = scene->mAnimations[i]; - std::string animationName = std::string(lAnimation->mName.C_Str()); - baseNames.push_back(animationName); - } - - GenerateUniqueNames(animationNames, baseNames, scene->mAnimations); - } - - void GetNodeNames(aiNode* node, std::vector& nodeNames, std::vector& orderedNodes) - { - nodeNames.push_back(std::string(node->mName.C_Str())); - orderedNodes.push_back(node); - for (uint32_t i = 0; i < node->mNumChildren; ++i) - GetNodeNames(node->mChildren[i], nodeNames, orderedNodes); - } - - void GenerateNodeNames(const aiScene* scene, std::map& nodeNames) - { - std::vector baseNames; - std::vector orderedNodes; - GetNodeNames(scene->mRootNode, baseNames, orderedNodes); - - // Need to create the array of the nodes - size_t nodeCount = orderedNodes.size(); - aiNode** nodeArray = new aiNode*[nodeCount]; - for (size_t i = 0; i < nodeCount; ++i) - nodeArray[i] = orderedNodes[i]; - - GenerateUniqueNames(nodeNames, baseNames, nodeArray); - - delete[] nodeArray; - } - - List^ ExtractTextureDependencies(const aiScene *scene) - { - auto textureNames = gcnew List(); - - // get internal textures (not supported) - /*for(int i=0; imNumTextures; ++i) - { - auto texture = scene->mTextures[i]; - - if(texture == nullptr) - continue; - - //TODO: add material name - std::string baseName = "GenTexture"; - baseName.append(std::to_string(i)); - - textureNames->Add(gcnew String(baseName.c_str())); - }*/ - - // texture search is done by type so we need to loop on them - std::vector allTextureTypes; - allTextureTypes.push_back(aiTextureType_DIFFUSE); - allTextureTypes.push_back(aiTextureType_SPECULAR); - allTextureTypes.push_back(aiTextureType_AMBIENT); - allTextureTypes.push_back(aiTextureType_EMISSIVE); - allTextureTypes.push_back(aiTextureType_HEIGHT); - allTextureTypes.push_back(aiTextureType_NORMALS); - allTextureTypes.push_back(aiTextureType_SHININESS); - allTextureTypes.push_back(aiTextureType_OPACITY); - allTextureTypes.push_back(aiTextureType_DISPLACEMENT); - allTextureTypes.push_back(aiTextureType_LIGHTMAP); - allTextureTypes.push_back(aiTextureType_REFLECTION); - //allTextureTypes.push_back(aiTextureType_NONE); - //allTextureTypes.push_back(aiTextureType_UNKNOWN); - - for (uint32_t i = 0; i < scene->mNumMaterials; i++) - { - for (std::vector::iterator it = allTextureTypes.begin(); it != allTextureTypes.end(); ++it) - { - auto lMaterial = scene->mMaterials[i]; - auto nbTextures = lMaterial->GetTextureCount(*it); - for (uint32_t j = 0; j < nbTextures; ++j) - { - aiString path; - aiTextureMapping mapping; - unsigned int index; - float blend; - aiTextureOp textureOp; - aiTextureMapMode mapMode; - if (AI_SUCCESS == lMaterial->GetTexture(*it, 0, &path, &mapping, &index, &blend, &textureOp, &mapMode)) - { - auto relFileName = gcnew String(path.C_Str()); - String^ fileNameToUse = Path::Combine(vfsInputPath, relFileName); - textureNames->Add(fileNameToUse); - break; - } - } - } - } - - return textureNames; - } - - Dictionary^ ExtractMaterials(const aiScene *scene, std::map& materialNames) - { - GenerateMaterialNames(scene, materialNames); - - auto materials = gcnew Dictionary(); - for (uint32_t i = 0; i < scene->mNumMaterials; i++) - { - std::map dict; - auto lMaterial = scene->mMaterials[i]; - auto materialName = materialNames[lMaterial]; - materials->Add(gcnew String(materialName.c_str()), ProcessMeshMaterial(lMaterial)); - } - return materials; - } - - String^ SearchMeshNode(aiNode* node, unsigned int meshIndex, std::map& nodeNames) - { - for (uint32_t i = 0; i < node->mNumMeshes; ++i) - { - if (node->mMeshes[i] == meshIndex) - return gcnew String(nodeNames[node].c_str()); - } - - for (uint32_t i = 0; i < node->mNumChildren; ++i) - { - auto res = SearchMeshNode(node->mChildren[i], meshIndex, nodeNames); - if (res != nullptr) - return res; - } - - return nullptr; - } - - List^ ExtractModel(const aiScene* scene, std::map& meshNames, std::map& materialNames, std::map& nodeNames) - { - GenerateMeshNames(scene, meshNames); - - auto meshList = gcnew List(); - for (uint32_t i = 0; i < scene->mNumMeshes; ++i) - { - auto mesh = scene->mMeshes[i]; - auto meshParams = gcnew MeshParameters(); - meshParams->MeshName = gcnew String(meshNames[mesh].c_str()); - auto lMaterial = scene->mMaterials[mesh->mMaterialIndex]; - meshParams->MaterialName = gcnew String(materialNames[lMaterial].c_str()); - meshParams->NodeName = SearchMeshNode(scene->mRootNode, i, nodeNames); - meshList->Add(meshParams); - } - return meshList; - } - - List^ ExtractAnimations(const aiScene* scene, std::map& animationNames) - { - if (scene->mNumAnimations == 0) - return nullptr; - - GenerateAnimationNames(scene, animationNames); - - auto animationList = gcnew List(); - for (std::map::iterator it = animationNames.begin(); it != animationNames.end(); ++it) - { - animationList->Add(gcnew String(it->second.c_str())); - } - return animationList; - } - - Model^ ConvertAssimpScene(const aiScene *scene) - { - modelData = gcnew Model(); - - std::map meshNames; - GenerateMeshNames(scene, meshNames); - - std::map nodeNames; - GenerateNodeNames(scene, nodeNames); - - // register the nodes and fill hierarchy - std::map*> meshIndexToNodeIndex; - - RegisterNodes(scene->mRootNode, -1, nodeNames, meshIndexToNodeIndex); - - // meshes - for (unsigned int i = 0; i < scene->mNumMeshes; ++i) - { - if (meshIndexToNodeIndex.find(i) != meshIndexToNodeIndex.end()) - { - auto meshInfo = ProcessMesh(scene, scene->mMeshes[i], meshNames); - - for (std::vector::iterator nodeIndexPtr = meshIndexToNodeIndex[i]->begin(); nodeIndexPtr != meshIndexToNodeIndex[i]->end(); ++nodeIndexPtr) - { - auto nodeMeshData = gcnew Mesh(); - nodeMeshData->Draw = meshInfo->Draw; - nodeMeshData->Name = meshInfo->Name; - nodeMeshData->MaterialIndex = meshInfo->MaterialIndex; - nodeMeshData->NodeIndex = *nodeIndexPtr; - - if (meshInfo->Bones != nullptr) - { - nodeMeshData->Skinning = gcnew MeshSkinningDefinition(); - nodeMeshData->Skinning->Bones = meshInfo->Bones->ToArray(); - } - if (meshInfo->HasSkinningPosition || meshInfo->HasSkinningNormal || meshInfo->TotalClusterCount > 0) - { - if (meshInfo->HasSkinningPosition) - nodeMeshData->Parameters->Set(MaterialKeys::HasSkinningPosition, true); - if (meshInfo->HasSkinningNormal) - nodeMeshData->Parameters->Set(MaterialKeys::HasSkinningNormal, true); - } - modelData->Meshes->Add(nodeMeshData); - } - } - } - - // delete the vectors in the map - for (std::map*>::iterator it = meshIndexToNodeIndex.begin(); it != meshIndexToNodeIndex.end(); ++it) - { - delete it->second; - it->second = 0; - } - - // embedded texture - only to log the warning for now - for (unsigned int i = 0; i < scene->mNumTextures; ++i) - ExtractEmbededTexture(scene->mTextures[i]); - - return modelData; - } - - void GetNodes(aiNode* node, int depth, std::map& nodeNames, List^ allNodes) - { - auto currentIndex = allNodes->Count; - auto newNodeInfo = gcnew NodeInfo(); - newNodeInfo->Name = gcnew String(nodeNames[node].c_str()); - newNodeInfo->Depth = depth; - newNodeInfo->Preserve = true; - - allNodes->Add(newNodeInfo); - for (uint32_t i = 0; i < node->mNumChildren; ++i) - GetNodes(node->mChildren[i], depth + 1, nodeNames, allNodes); - } - - List^ ExtractNodeHierarchy(const aiScene *scene, std::map& nodeNames) - { - auto allNodes = gcnew List(); - GetNodes(scene->mRootNode, 0, nodeNames, allNodes); - return allNodes; - } - -public: - EntityInfo^ ExtractEntity(String^ inputFilename, String^ outputFilename, bool extractTextureDependencies, bool deduplicateMaterials) - { - try - { - // the importer is kept here since it owns the scene object. - //TODO: check the options - Assimp::Importer importer; - - auto importFlags = aiProcess_SortByPType; - if (deduplicateMaterials) - importFlags = (aiPostProcessSteps)(importFlags | aiProcess_RemoveRedundantMaterials); - auto scene = Initialize(inputFilename, outputFilename, &importer, importFlags); - - // If scene is null, something went wrong inside Assimp - if (scene == nullptr) - { - if (strlen(importer.GetErrorString()) > 0) - { - // Extract error details from Assimp - auto error = gcnew String(importer.GetErrorString()); - Logger->Error(String::Format("Assimp: {0}", error), - CallerInfo::Get(__FILEW__, __FUNCTIONW__, __LINE__)); - } - return nullptr; - } - - std::map materialNames; - std::map meshNames; - std::map animationNames; - std::map nodeNames; - - GenerateNodeNames(scene, nodeNames); - - auto entityInfo = gcnew EntityInfo(); - if (extractTextureDependencies) - entityInfo->TextureDependencies = ExtractTextureDependencies(scene); - entityInfo->Materials = ExtractMaterials(scene, materialNames); - entityInfo->Models = ExtractModel(scene, meshNames, materialNames, nodeNames); - entityInfo->Nodes = ExtractNodeHierarchy(scene, nodeNames); - entityInfo->AnimationNodes = ExtractAnimations(scene, animationNames); - - return entityInfo; - } - catch (Exception^) - { - return nullptr; - } - } - - Model^ Convert(String^ inputFilename, String^ outputFilename, bool deduplicateMaterials) - { - // the importer is kept here since it owns the scene object. - Assimp::Importer importer; - - auto importFlags = - aiProcess_CalcTangentSpace - | aiProcess_Triangulate - | aiProcess_GenNormals - | aiProcess_JoinIdenticalVertices - | aiProcess_LimitBoneWeights - | aiProcess_SortByPType - | aiProcess_FlipWindingOrder - | aiProcess_FlipUVs; - if (deduplicateMaterials) - importFlags = (aiPostProcessSteps)(importFlags | aiProcess_RemoveRedundantMaterials); - auto scene = Initialize(inputFilename, outputFilename, &importer, importFlags); - return ConvertAssimpScene(scene); - } - - AnimationInfo^ ConvertAnimation(String^ inputFilename, String^ outputFilename) - { - // the importer is kept here since it owns the scene object. - Assimp::Importer importer; - auto scene = Initialize(inputFilename, outputFilename, &importer, 0); - return ProcessAnimation(scene); - } - - Skeleton^ ConvertSkeleton(String^ inputFilename, String^ outputFilename) - { - // the importer is kept here since it owns the scene object. - Assimp::Importer importer; - auto scene = Initialize(inputFilename, outputFilename, &importer, 0); - return ProcessSkeleton(scene); - } -}; - -}}} diff --git a/sources/tools/Stride.Importer.Assimp/Stride.Importer.Assimp.csproj b/sources/tools/Stride.Importer.Assimp/Stride.Importer.Assimp.csproj new file mode 100644 index 0000000000..7349f776fa --- /dev/null +++ b/sources/tools/Stride.Importer.Assimp/Stride.Importer.Assimp.csproj @@ -0,0 +1,25 @@ + + + + true + $(StrideAssemblyProcessorDefaultOptions) + $(StrideEditorTargetFramework) + win7-x64 + false + + + + Properties\SharedAssemblyInfo.cs + + + + + + + + + + + + + \ No newline at end of file diff --git a/sources/tools/Stride.Importer.Assimp/Stride.Importer.Assimp.vcxproj b/sources/tools/Stride.Importer.Assimp/Stride.Importer.Assimp.vcxproj deleted file mode 100644 index 9670dac05b..0000000000 --- a/sources/tools/Stride.Importer.Assimp/Stride.Importer.Assimp.vcxproj +++ /dev/null @@ -1,257 +0,0 @@ - - - - - Cpp - $(StrideEditorTargetFramework) - WindowsTools - - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - {C2306552-6C42-464C-8981-32FEF4F9458D} - ManagedCProj - Stride.Importer.Assimp - 10.0 - - - - DynamicLibrary - true - NetCore - v143 - - - DynamicLibrary - false - NetCore - v143 - - - - - - - - - - true - bin\$(TargetFramework)\$(Platform)\$(Configuration)\ - obj\$(TargetFramework)\$(Platform)\$(Configuration)\ - - - false - bin\$(TargetFramework)\$(Platform)\$(Configuration)\ - obj\$(TargetFramework)\$(Platform)\$(Configuration)\ - - - - Level3 - Disabled - WIN32;_DEBUG;%(PreprocessorDefinitions) - Use - ..\..\..\deps\assimp\include - /wd 4945 %(AdditionalOptions) - - - true - assimp-vc140-mt.lib - ..\..\..\deps\assimp\lib\x64\ - /ignore:4049 %(AdditionalOptions) - - - xcopy /D /Y "..\..\..\deps\assimp\bin\x64\assimp-vc140-mt.dll" "$(TargetDir)$(Platform)\" - $(TargetDir)$(Platform)\assimp-vc140-mt.dll;%(Outputs) - ..\..\..\deps\assimp\bin\x64\assimp-vc140-mt.dll - true - - - - - Level3 - WIN32;NDEBUG;%(PreprocessorDefinitions) - Use - ..\..\..\deps\assimp\include - /wd 4945 %(AdditionalOptions) - - - true - assimp-vc140-mt.lib - ..\..\..\deps\assimp\lib\x64\ - - - xcopy /D /Y "..\..\..\deps\assimp\bin\x64\assimp-vc140-mt.dll" "$(TargetDir)$(Platform)\" - $(TargetDir)$(Platform)\assimp-vc140-mt.dll;%(Outputs) - ..\..\..\deps\assimp\bin\x64\assimp-vc140-mt.dll - true - - - - - Level3 - Disabled - _DEBUG;%(PreprocessorDefinitions) - Use - ..\..\..\deps\assimp\include - /wd 4945 %(AdditionalOptions) - - - true - assimp-vc140-mt.lib - ..\..\..\deps\assimp\lib\x64\ - /ignore:4049 %(AdditionalOptions) - - - xcopy /D /Y "..\..\..\deps\assimp\bin\x64\assimp-vc140-mt.dll" "$(TargetDir)$(Platform)\" - $(TargetDir)$(Platform)\assimp-vc140-mt.dll;%(Outputs) - ..\..\..\deps\assimp\bin\x64\assimp-vc140-mt.dll - true - - - - - Level3 - NDEBUG;%(PreprocessorDefinitions) - Use - ..\..\..\deps\assimp\include - /wd 4945 %(AdditionalOptions) - - - true - assimp-vc140-mt.lib - ..\..\..\deps\assimp\lib\x64\ - - - xcopy /D /Y "..\..\..\deps\assimp\bin\x64\assimp-vc140-mt.dll" "$(TargetDir)$(Platform)\" - $(TargetDir)$(Platform)\assimp-vc140-mt.dll;%(Outputs) - ..\..\..\deps\assimp\bin\x64\assimp-vc140-mt.dll - true - - - - - ..\..\..\deps\BulletPhysics\BulletSharp.NetStandard.dll - - - - - - - - - - - - - Create - - - - - - - - - - - - - - - runtimes\win-x64\native\%(Filename)%(Extension) - runtimes\win-x64\native\%(Filename)%(Extension) - PreserveNewest - - - - - {1e54a9a2-4439-4444-ae57-6d2ed3c0dc47} - False - - - {66581dad-70ad-4475-ae47-c6c0df1ec5e2} - False - - - {39ae9c77-e94b-404f-8768-b6261b3c1e0e} - False - - - {c121a566-555e-42b9-9b0a-1696529a9088} - False - - - {ad4fdc24-b64d-4ed7-91aa-62c9eda12fa4} - False - - - {0e916ab7-5a6c-4820-8ab1-aa492fe66d68} - False - - - {fb06c76a-6bb7-40be-9afa-fec13b045fb5} - False - - - {1de01410-22c9-489b-9796-1addab1f64e5} - False - - - {5210fb81-b807-49bb-af0d-31fb6a83a572} - False - - - {f2d52edb-bc17-4243-b06d-33cd20f87a7f} - False - - - {1677b922-ccf0-44de-b57e-1cdd3d2b8e8a} - False - - - {273bdd15-7392-4078-91f0-af23594a3d7b} - False - - - {72390339-b2a1-4f61-a800-31ed0975b515} - False - - - {fcdf1b87-1c76-46eb-ad6a-d55ef5f195b8} - False - - - {7732cb84-a39a-4adf-b740-fd32a352fa8a} - False - - - {f61d86b5-7c3d-4441-957d-a0a6d2fa69ca} - False - - - {43a6e62e-1b1c-4630-abb8-c3f716004645} - False - - - - - - diff --git a/sources/tools/Stride.Importer.Assimp/Stride.Importer.Assimp.vcxproj.filters b/sources/tools/Stride.Importer.Assimp/Stride.Importer.Assimp.vcxproj.filters deleted file mode 100644 index 942c1233f0..0000000000 --- a/sources/tools/Stride.Importer.Assimp/Stride.Importer.Assimp.vcxproj.filters +++ /dev/null @@ -1,58 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - - - - Resource Files - - - - - Resource Files - - - \ No newline at end of file diff --git a/sources/tools/Stride.Importer.Assimp/UtilityFunctions.cpp b/sources/tools/Stride.Importer.Assimp/UtilityFunctions.cpp deleted file mode 100644 index 318d728cb8..0000000000 --- a/sources/tools/Stride.Importer.Assimp/UtilityFunctions.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) -// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. -#include "Stdafx.h" - -#include "UtilityFunctions.h" - -using namespace System::Text; -using namespace Stride::Engine; - - -String^ aiStringToString(aiString str) -{ - // Assimp aiString underlying encoding is UTF-8 - // Windows String underlying encoding is UTF-16 - Encoding^ srcEncoding = Encoding::UTF8; - - const char* pAiData = str.C_Str(); // pointer to the underlying data of he aiString - // Check `str' cannot be more than the size of a int. - array^ buffer = gcnew array((int) str.length); - for(unsigned int i=0; iGetString(buffer); -} - -Color aiColor4ToColor(aiColor4D color) -{ - Color ret(color.r, color.g, color.b, color.a); - return ret; -} - -Color3 aiColor3ToColor3(aiColor3D color) -{ - Color3 ret(color.r, color.g, color.b); - return ret; -} - -Color4 aiColor3ToColor4(aiColor3D color) -{ - Color4 ret(color.r, color.g, color.b, 1.0f); - return ret; -} - -Matrix aiMatrixToMatrix(aiMatrix4x4 mat) -{ - Matrix ret( mat.a1, mat.b1, mat.c1, mat.d1, - mat.a2, mat.b2, mat.c2, mat.d2, - mat.a3, mat.b3, mat.c3, mat.d3, - mat.a4, mat.b4, mat.c4, mat.d4); - return ret; -} - -Vector2 aiVector2ToVector2(aiVector2D vec) -{ - Vector2 ret(vec.x, vec.y); - return ret; -} - -Vector3 aiVector3ToVector3(aiVector3D vec) -{ - Vector3 ret(vec.x, vec.y, vec.z); - return ret; -} - -Quaternion aiQuaternionToQuaternion(aiQuaterniont quat) -{ - Quaternion ret(quat.x, quat.y, quat.z, quat.w); - return ret; -} - -CompressedTimeSpan aiTimeToXkTimeSpan(double time, double aiTickPerSecond) -{ - double sdTime = CompressedTimeSpan::TicksPerSecond / aiTickPerSecond * time; - return CompressedTimeSpan((long)sdTime); -} - - -Vector3 QuaternionToEulerAngles(Quaternion q) -{ - Vector3 ret; - - // source wikipedia => http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Conversion - ret.X = (float)Math::Atan2(2.f * q.X * q.W + 2.f * q.Y * q.Z, 1 - 2.f * (q.X*q.X + q.Y*q.Y)); - - auto sinY = Math::Min(1.0, Math::Max(-1.0, 2.0 * ( q.W * q.Y - q.Z * q.X ))); // with approximation value can exceed 1 and lead to invalid Arcsinus. - ret.Y = (float)Math::Asin(sinY); - - ret.Z = (float)Math::Atan2(2.f * q.W * q.Z + 2.f * q.Y * q.X, 1 - 2.f * (q.Y*q.Y + q.Z*q.Z)); - - return ret; -} - - -Vector3 FlipYZAxis(Vector3 input, bool shouldFlip) -{ - if(!shouldFlip) - return input; - - return Vector3(input.X, input.Z, -input.Y); -} diff --git a/sources/tools/Stride.Importer.Assimp/UtilityFunctions.h b/sources/tools/Stride.Importer.Assimp/UtilityFunctions.h deleted file mode 100644 index 3a5872c78c..0000000000 --- a/sources/tools/Stride.Importer.Assimp/UtilityFunctions.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) -// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. -#include "Stdafx.h" - - -using namespace System; -using namespace Stride::Animations; -using namespace Stride::Core::Diagnostics; -using namespace Stride::Core::Mathematics; - -// Assimp types convertion -String^ aiStringToString(aiString str); -Color aiColor4ToColor(aiColor4D color); -Color3 aiColor3ToColor3(aiColor3D color); -Color4 aiColor3ToColor4(aiColor3D color); -Matrix aiMatrixToMatrix(aiMatrix4x4 mat); -Vector2 aiVector2ToVector2(aiVector2D vec); -Vector3 aiVector3ToVector3(aiVector3D vec); -Quaternion aiQuaternionToQuaternion(aiQuaterniont quat); -CompressedTimeSpan aiTimeToXkTimeSpan(double time, double tickPerSecond); - -// Others -Vector3 QuaternionToEulerAngles(Quaternion q); -Vector3 FlipYZAxis(Vector3 input, bool shouldFlip); diff --git a/sources/tools/Stride.Importer.Assimp/Utils.cs b/sources/tools/Stride.Importer.Assimp/Utils.cs new file mode 100644 index 0000000000..50fa77dba7 --- /dev/null +++ b/sources/tools/Stride.Importer.Assimp/Utils.cs @@ -0,0 +1,63 @@ +// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. + +using Silk.NET.Assimp; +using Stride.Animations; +using Stride.Core.Mathematics; +using System.Numerics; + +namespace Stride.Importer.Assimp +{ + public static class Utils + { + public const int AI_MAX_NUMBER_OF_TEXTURECOORDS = 8; + public const int AI_MAX_NUMBER_OF_COLOR_SETS = 8; + + public static Matrix ToStrideMatrix(this Matrix4x4 matrix) + { + // Note the order. Matrices from Assimp has to be transposed + return new Matrix( + matrix.M11, matrix.M21, matrix.M31, matrix.M41, + matrix.M12, matrix.M22, matrix.M32, matrix.M42, + matrix.M13, matrix.M23, matrix.M33, matrix.M43, + matrix.M14, matrix.M24, matrix.M34, matrix.M44); + } + + public static Core.Mathematics.Vector3 ToStrideVector3(this System.Numerics.Vector3 v) + => new Core.Mathematics.Vector3(v.X, v.Y, v.Z); + + public static Color ToStrideColor(this System.Numerics.Vector4 v) + => new Color(v.X, v.Y, v.Z, v.W); + + public static Core.Mathematics.Quaternion ToStrideQuaternion(this AssimpQuaternion q) + => new Core.Mathematics.Quaternion(q.X, q.Y, q.Z, q.W); + + public static unsafe uint GetNumUVChannels(Silk.NET.Assimp.Mesh* mesh) + { + var n = 0; + while (n < AI_MAX_NUMBER_OF_TEXTURECOORDS && mesh->MTextureCoords[n] != null) + { + ++n; + } + + return (uint)n; + } + + public static unsafe uint GetNumColorChannels(Silk.NET.Assimp.Mesh* mesh) + { + var n = 0; + while (n < AI_MAX_NUMBER_OF_COLOR_SETS && mesh->MColors[n] != null) + { + ++n; + } + + return (uint)n; + } + + public static CompressedTimeSpan AiTimeToStrideTimeSpan(double time, double aiTickPerSecond) + { + var sdTime = CompressedTimeSpan.TicksPerSecond / aiTickPerSecond * time; + return new CompressedTimeSpan((int)sdTime); + } + } +} diff --git a/sources/tools/Stride.Importer.Assimp/app.ico b/sources/tools/Stride.Importer.Assimp/app.ico deleted file mode 100644 index 301942f607..0000000000 Binary files a/sources/tools/Stride.Importer.Assimp/app.ico and /dev/null differ diff --git a/sources/tools/Stride.Importer.Assimp/app.rc b/sources/tools/Stride.Importer.Assimp/app.rc deleted file mode 100644 index eab43064f1..0000000000 Binary files a/sources/tools/Stride.Importer.Assimp/app.rc and /dev/null differ diff --git a/sources/tools/Stride.Importer.Assimp/msbuild.binlog b/sources/tools/Stride.Importer.Assimp/msbuild.binlog deleted file mode 100644 index 41249dbb1f..0000000000 Binary files a/sources/tools/Stride.Importer.Assimp/msbuild.binlog and /dev/null differ diff --git a/sources/tools/Stride.Importer.Assimp/resource.h b/sources/tools/Stride.Importer.Assimp/resource.h deleted file mode 100644 index d5ac7c42aa..0000000000 --- a/sources/tools/Stride.Importer.Assimp/resource.h +++ /dev/null @@ -1,3 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by app.rc diff --git a/sources/tools/Stride.Importer.Common/AnimationInfo.cs b/sources/tools/Stride.Importer.Common/AnimationInfo.cs new file mode 100644 index 0000000000..0a755241b4 --- /dev/null +++ b/sources/tools/Stride.Importer.Common/AnimationInfo.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System; +using System.Collections.Generic; +using Stride.Animations; + +namespace Stride.Importer.Common +{ + public class AnimationInfo + { + public TimeSpan Duration; + public Dictionary AnimationClips = new(); + } +} diff --git a/sources/tools/Stride.Importer.Common/AssemblyInfo.cpp b/sources/tools/Stride.Importer.Common/AssemblyInfo.cpp deleted file mode 100644 index 1caa248ff8..0000000000 --- a/sources/tools/Stride.Importer.Common/AssemblyInfo.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) -// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. -#include "stdafx.h" - -using namespace System; -using namespace System::Reflection; -using namespace System::Runtime::CompilerServices; -using namespace System::Runtime::InteropServices; -using namespace System::Security::Permissions; - -// -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -// -[assembly:AssemblyTitleAttribute("StrideImporterCommon")]; -[assembly:AssemblyDescriptionAttribute("")]; -[assembly:AssemblyConfigurationAttribute("")]; -[assembly:AssemblyCompanyAttribute("")]; -[assembly:AssemblyProductAttribute("StrideImporterCommon")]; -[assembly:AssemblyCopyrightAttribute("Copyright (c) 2013")]; -[assembly:AssemblyTrademarkAttribute("")]; -[assembly:AssemblyCultureAttribute("")]; - -// -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the value or you can default the Revision and Build Numbers -// by using the '*' as shown below: - -[assembly:AssemblyVersionAttribute("1.0.*")]; - -[assembly:ComVisible(false)]; - -[assembly:CLSCompliantAttribute(true)]; diff --git a/sources/tools/Stride.Importer.Common/EntityInfo.cs b/sources/tools/Stride.Importer.Common/EntityInfo.cs new file mode 100644 index 0000000000..10e7e7e5f3 --- /dev/null +++ b/sources/tools/Stride.Importer.Common/EntityInfo.cs @@ -0,0 +1,17 @@ +// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System.Collections.Generic; +using Stride.Assets.Materials; + +namespace Stride.Importer.Common +{ + public class EntityInfo + { + public List TextureDependencies; + public Dictionary Materials; + public List AnimationNodes; + public List Models; + public List Nodes; + } +} diff --git a/sources/tools/Stride.Importer.Common/MeshMaterials.cs b/sources/tools/Stride.Importer.Common/MeshMaterials.cs new file mode 100644 index 0000000000..f5c7cd03b7 --- /dev/null +++ b/sources/tools/Stride.Importer.Common/MeshMaterials.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System.Collections.Generic; +using Stride.Assets.Materials; + +namespace Stride.Importer.Common +{ + public class MeshMaterials + { + public Dictionary Materials; + public List Models; + public List BoneNodes; + } +} diff --git a/sources/tools/Stride.Importer.Common/MeshParameters.cs b/sources/tools/Stride.Importer.Common/MeshParameters.cs new file mode 100644 index 0000000000..0cf3763e11 --- /dev/null +++ b/sources/tools/Stride.Importer.Common/MeshParameters.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System.Collections.Generic; + +namespace Stride.Importer.Common +{ + public class MeshParameters + { + public string MaterialName; + public string MeshName; + public string NodeName; + public HashSet BoneNodes; + } +} diff --git a/sources/tools/Stride.Importer.Common/NodeInfo.cs b/sources/tools/Stride.Importer.Common/NodeInfo.cs new file mode 100644 index 0000000000..0bfb15b421 --- /dev/null +++ b/sources/tools/Stride.Importer.Common/NodeInfo.cs @@ -0,0 +1,12 @@ +// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. + +namespace Stride.Importer.Common +{ + public class NodeInfo + { + public string Name; + public int Depth; + public bool Preserve; + } +} diff --git a/sources/tools/Stride.Importer.Common/Stdafx.cpp b/sources/tools/Stride.Importer.Common/Stdafx.cpp deleted file mode 100644 index 84421f9104..0000000000 --- a/sources/tools/Stride.Importer.Common/Stdafx.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// Stride.Importer.Assimp.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" diff --git a/sources/tools/Stride.Importer.Common/Stdafx.h b/sources/tools/Stride.Importer.Common/Stdafx.h deleted file mode 100644 index 7e4cb2b912..0000000000 --- a/sources/tools/Stride.Importer.Common/Stdafx.h +++ /dev/null @@ -1,9 +0,0 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, -// but are changed infrequently - -#pragma once - -#pragma warning( disable : 4945 ) - -#include \ No newline at end of file diff --git a/sources/tools/Stride.Importer.Common/Stride.Importer.Common.cpp b/sources/tools/Stride.Importer.Common/Stride.Importer.Common.cpp deleted file mode 100644 index 9fe4ea6ccc..0000000000 --- a/sources/tools/Stride.Importer.Common/Stride.Importer.Common.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) -// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. -#include "stdafx.h" - -using namespace System; -using namespace System::Collections::Generic; -using namespace System::IO; -using namespace Stride::Core::Assets; -using namespace Stride::Core::Diagnostics; -using namespace Stride::Core::Mathematics; -using namespace Stride::Core::Serialization; -using namespace Stride::Animations; -using namespace Stride::Rendering; -using namespace Stride::Rendering::Materials; -using namespace Stride::Rendering::Materials::ComputeColors; -using namespace Stride::Assets::Materials; -using namespace Stride::Engine; -using namespace Stride::Graphics; -using namespace Stride::Shaders; - -namespace Stride { namespace Importer { namespace Common { - -public ref class AnimationInfo -{ -public: - AnimationInfo() - { - AnimationClips = gcnew Dictionary(); - } - - TimeSpan Duration; - Dictionary^ AnimationClips; -}; - -public ref class MeshParameters -{ -public: - MeshParameters() - { - } - - String^ MaterialName; - String^ MeshName; - String^ NodeName; - HashSet^ BoneNodes; -}; - -public ref class NodeInfo -{ -public: - String^ Name; - int Depth; - bool Preserve; -}; - -public ref class EntityInfo -{ -public: - List^ TextureDependencies; - Dictionary^ Materials; - List^ AnimationNodes; - List^ Models; - List^ Nodes; -}; - -public ref class MeshMaterials -{ -public: - Dictionary^ Materials; - List^ Models; - List^ BoneNodes; -}; - -public ref class TextureLayerGenerator -{ -public: - - static ShaderClassSource^ GenerateTextureLayer(String^ vfsOutputPath, String^ sourceTextureFile, int textureUVSetIndex, Vector2 textureUVscaling , - int& textureCount, ParameterKey^ surfaceMaterialKey, - Mesh^ meshData, Logger^ logger) - { - ParameterKey^ parameterKey; - - auto url = vfsOutputPath + "_" + Path::GetFileNameWithoutExtension(sourceTextureFile); - - if (File::Exists(sourceTextureFile)) - { - if (logger != nullptr) - { - logger->Warning(String::Format("The texture '{0}' referenced in the mesh material can not be found on the system. Loading will probably fail at run time.", sourceTextureFile), - nullptr, CallerInfo::Get(__FILEW__, __FUNCTIONW__, __LINE__)); - } - } - - parameterKey = ParameterKeys::IndexedKey(surfaceMaterialKey, textureCount++); - String^ uvSetName = "TEXCOORD"; - if (textureUVSetIndex != 0) - uvSetName += textureUVSetIndex; - //albedoMaterial->Add(gcnew ShaderClassSource("TextureStream", uvSetName, "TEXTEST" + uvSetIndex)); - auto uvScaling = textureUVscaling; - auto textureName = parameterKey->Name; - auto needScaling = uvScaling != Vector2::One; - auto currentComposition = needScaling - ? gcnew ShaderClassSource("ComputeColorTextureRepeat", textureName, uvSetName, "float2(" + uvScaling.X + ", " + uvScaling.Y + ")") - : gcnew ShaderClassSource("ComputeColorTexture", textureName, uvSetName); - - return currentComposition; - } - - static ComputeTextureColor^ GenerateMaterialTextureNode(String^ vfsOutputPath, String^ sourceTextureFile, size_t textureUVSetIndex, Vector2 textureUVscaling, TextureAddressMode addressModeU, TextureAddressMode addressModeV, Logger^ logger) - { - auto textureFileName = Path::GetFileNameWithoutExtension(sourceTextureFile); - auto url = vfsOutputPath + "_" + textureFileName; - - if (File::Exists(sourceTextureFile)) - { - if (logger != nullptr) - { - logger->Warning(String::Format("The texture '{0}' referenced in the mesh material can not be found on the system. Loading will probably fail at run time.", sourceTextureFile), - nullptr, CallerInfo::Get(__FILEW__, __FUNCTIONW__, __LINE__)); - } - } - - auto uvScaling = textureUVscaling; - auto textureName = textureFileName; - - auto texture = AttachedReferenceManager::CreateProxyObject(AssetId::Empty, textureName); - - auto currentTexture = gcnew ComputeTextureColor(texture, (TextureCoordinate)textureUVSetIndex, uvScaling, Vector2::Zero); - currentTexture->AddressModeU = addressModeU; - currentTexture->AddressModeV = addressModeV; - - return currentTexture; - } -}; -}}} diff --git a/sources/tools/Stride.Importer.Common/Stride.Importer.Common.csproj b/sources/tools/Stride.Importer.Common/Stride.Importer.Common.csproj new file mode 100644 index 0000000000..116acebec6 --- /dev/null +++ b/sources/tools/Stride.Importer.Common/Stride.Importer.Common.csproj @@ -0,0 +1,23 @@ + + + + true + $(StrideAssemblyProcessorDefaultOptions) + $(StrideEditorTargetFramework) + win7-x64 + false + + + + Properties\SharedAssemblyInfo.cs + + + + + + + + + + + \ No newline at end of file diff --git a/sources/tools/Stride.Importer.Common/Stride.Importer.Common.vcxproj b/sources/tools/Stride.Importer.Common/Stride.Importer.Common.vcxproj deleted file mode 100644 index 882240a199..0000000000 --- a/sources/tools/Stride.Importer.Common/Stride.Importer.Common.vcxproj +++ /dev/null @@ -1,161 +0,0 @@ - - - - - Cpp - $(StrideEditorTargetFramework) - WindowsTools - - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - {43A6E62E-1B1C-4630-ABB8-C3F716004645} - ManagedCProj - Stride.Importer.Common - 10.0 - - - - DynamicLibrary - true - NetCore - v143 - - - DynamicLibrary - false - NetCore - v143 - - - - - - - - - - true - bin\$(TargetFramework)\$(Platform)\$(Configuration)\ - obj\$(TargetFramework)\$(Platform)\$(Configuration)\ - - - false - bin\$(TargetFramework)\$(Platform)\$(Configuration)\ - obj\$(TargetFramework)\$(Platform)\$(Configuration)\ - - - - Level3 - Disabled - WIN32;_DEBUG;%(PreprocessorDefinitions) - Use - /wd 4945 %(AdditionalOptions) - - - - - Level3 - WIN32;NDEBUG;%(PreprocessorDefinitions) - Use - /wd 4945 %(AdditionalOptions) - - - - - Level3 - Disabled - _DEBUG;%(PreprocessorDefinitions) - Use - /wd 4945 %(AdditionalOptions) - - - - - Level3 - NDEBUG;%(PreprocessorDefinitions) - Use - /wd 4945 %(AdditionalOptions) - - - - - - - - - - - Create - - - - - - - - - - - {66581dad-70ad-4475-ae47-c6c0df1ec5e2} - False - - - {5210fb81-b807-49bb-af0d-31fb6a83a572} - False - - - {0e916ab7-5a6c-4820-8ab1-aa492fe66d68} - False - - - {39ae9c77-e94b-404f-8768-b6261b3c1e0e} - False - - - {1677b922-ccf0-44de-b57e-1cdd3d2b8e8a} - False - - - {c121a566-555e-42b9-9b0a-1696529a9088} - False - - - {ad4fdc24-b64d-4ed7-91aa-62c9eda12fa4} - False - - - {fb06c76a-6bb7-40be-9afa-fec13b045fb5} - False - - - {273bdd15-7392-4078-91f0-af23594a3d7b} - False - - - {72390339-b2a1-4f61-a800-31ed0975b515} - False - - - - - - \ No newline at end of file diff --git a/sources/tools/Stride.Importer.Common/Stride.Importer.Common.vcxproj.filters b/sources/tools/Stride.Importer.Common/Stride.Importer.Common.vcxproj.filters deleted file mode 100644 index 0c2960faaf..0000000000 --- a/sources/tools/Stride.Importer.Common/Stride.Importer.Common.vcxproj.filters +++ /dev/null @@ -1,46 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - - - Resource Files - - - - - Resource Files - - - \ No newline at end of file diff --git a/sources/tools/Stride.Importer.Common/TextureLayerGenerator.cs b/sources/tools/Stride.Importer.Common/TextureLayerGenerator.cs new file mode 100644 index 0000000000..6a1005496e --- /dev/null +++ b/sources/tools/Stride.Importer.Common/TextureLayerGenerator.cs @@ -0,0 +1,86 @@ +// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) +// Distributed under the MIT license. See the LICENSE.md file in the project root for more information. + +using System.IO; +using Stride.Core.Assets; +using Stride.Core.Diagnostics; +using Stride.Core.Mathematics; +using Stride.Core.Serialization; +using Stride.Graphics; +using Stride.Rendering; +using Stride.Rendering.Materials; +using Stride.Rendering.Materials.ComputeColors; +using Stride.Shaders; + +namespace Stride.Importer.Common +{ + public class TextureLayerGenerator + { + public static ShaderClassSource GenerateTextureLayer( + string vfsOutputPath, + string sourceTextureFile, + int textureUVSetIndex, + Vector2 textureUVscaling, + ref int textureCount, + ParameterKey surfaceMaterialKey, + Mesh meshData, + Logger logger + ) + { + ParameterKey parameterKey; + + if (File.Exists(sourceTextureFile) && logger != null) + { + logger.Warning($"The texture '{sourceTextureFile}' referenced in the mesh material can not be found on the system. Loading will probably fail at run time.", CallerInfo.Get()); + } + + parameterKey = ParameterKeys.IndexedKey(surfaceMaterialKey, textureCount++); + var uvSetName = "TEXCOORD"; + if (textureUVSetIndex != 0) + uvSetName += textureUVSetIndex; + + var uvScaling = textureUVscaling; + var textureName = parameterKey.Name; + var needScaling = uvScaling != Vector2.One; + var currentComposition = needScaling + ? new ShaderClassSource( + "ComputeColorTextureRepeat", + textureName, + uvSetName, + "float2(" + uvScaling.X + ", " + uvScaling.Y + ")" + ) + : new ShaderClassSource("ComputeColorTexture", textureName, uvSetName); + + return currentComposition; + } + + public static ComputeTextureColor GenerateMaterialTextureNode( + string vfsOutputPath, + string sourceTextureFile, + uint textureUVSetIndex, + Vector2 textureUVscaling, + TextureAddressMode addressModeU, + TextureAddressMode addressModeV, + Logger logger + ) + { + var textureFileName = Path.GetFileNameWithoutExtension(sourceTextureFile); + + if (File.Exists(sourceTextureFile) && logger != null) + { + logger.Warning($"The texture '{sourceTextureFile}' referenced in the mesh material can not be found on the system. Loading will probably fail at run time.", CallerInfo.Get()); + } + + var uvScaling = textureUVscaling; + var textureName = textureFileName; + + var texture = AttachedReferenceManager.CreateProxyObject(AssetId.Empty, textureName); + + var currentTexture = new ComputeTextureColor(texture, (TextureCoordinate)textureUVSetIndex, uvScaling, Vector2.Zero); + currentTexture.AddressModeU = addressModeU; + currentTexture.AddressModeV = addressModeV; + + return currentTexture; + } + } +} diff --git a/sources/tools/Stride.Importer.Common/app.ico b/sources/tools/Stride.Importer.Common/app.ico deleted file mode 100644 index 301942f607..0000000000 Binary files a/sources/tools/Stride.Importer.Common/app.ico and /dev/null differ diff --git a/sources/tools/Stride.Importer.Common/app.rc b/sources/tools/Stride.Importer.Common/app.rc deleted file mode 100644 index eab43064f1..0000000000 Binary files a/sources/tools/Stride.Importer.Common/app.rc and /dev/null differ diff --git a/sources/tools/Stride.Importer.Common/resource.h b/sources/tools/Stride.Importer.Common/resource.h deleted file mode 100644 index d5ac7c42aa..0000000000 --- a/sources/tools/Stride.Importer.Common/resource.h +++ /dev/null @@ -1,3 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by app.rc diff --git a/sources/tools/Stride.Importer.Common/ImporterUtils.h b/sources/tools/Stride.Importer.FBX/ImporterUtils.h similarity index 100% rename from sources/tools/Stride.Importer.Common/ImporterUtils.h rename to sources/tools/Stride.Importer.FBX/ImporterUtils.h diff --git a/sources/tools/Stride.Importer.FBX/MeshConverter.cpp b/sources/tools/Stride.Importer.FBX/MeshConverter.cpp index 737a371bac..9648f94132 100644 --- a/sources/tools/Stride.Importer.FBX/MeshConverter.cpp +++ b/sources/tools/Stride.Importer.FBX/MeshConverter.cpp @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) // Distributed under the MIT license. See the LICENSE.md file in the project root for more information. #include "stdafx.h" -#include "../Stride.Importer.Common/ImporterUtils.h" +#include "ImporterUtils.h" #include "SceneMapping.h" #include "AnimationConverter.h" diff --git a/sources/tools/Stride.Importer.FBX/Stride.Importer.FBX.vcxproj b/sources/tools/Stride.Importer.FBX/Stride.Importer.FBX.vcxproj index 8e31b1feea..f1b6046d26 100644 --- a/sources/tools/Stride.Importer.FBX/Stride.Importer.FBX.vcxproj +++ b/sources/tools/Stride.Importer.FBX/Stride.Importer.FBX.vcxproj @@ -175,7 +175,7 @@ - + @@ -243,9 +243,8 @@ {7732cb84-a39a-4adf-b740-fd32a352fa8a} False - - {43a6e62e-1b1c-4630-abb8-c3f716004645} - False + + {806aa078-6070-4bb6-b05b-6ee6b21b1cde} diff --git a/sources/tools/Stride.Importer.FBX/Stride.Importer.FBX.vcxproj.filters b/sources/tools/Stride.Importer.FBX/Stride.Importer.FBX.vcxproj.filters index 13a7082d7b..c2646e480e 100644 --- a/sources/tools/Stride.Importer.FBX/Stride.Importer.FBX.vcxproj.filters +++ b/sources/tools/Stride.Importer.FBX/Stride.Importer.FBX.vcxproj.filters @@ -11,6 +11,9 @@ - + + + + \ No newline at end of file