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
-
+
@@ -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