Replace C++/CLI components with P/Invoke components (#562)

* Replace C++/CLI components with P/Invoke

* Deleted C++/CLI projects

* Use Utf8StringHandle to marshal UTF-8 strings

* Use plaform-default calling convention

* Handle DLL preloading on Linux and macOS

* Change intermediate and output directories of native projects

* Improve P/Invoke documentation
This commit is contained in:
hozuki 2020-08-06 04:35:50 +02:00 committed by GitHub
parent 4a81c461e8
commit c76e41b1ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
80 changed files with 4608 additions and 1530 deletions

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AssetStudio.PInvoke</RootNamespace>
<AssemblyName>AssetStudio.PInvoke</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="DllLoader.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utf8StringHandle.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,123 @@
using System;
using System.ComponentModel;
using System.IO;
using System.Runtime.InteropServices;
namespace AssetStudio.PInvoke
{
public static class DllLoader
{
public static void PreloadDll(string dllName)
{
var dllDir = GetDirectedDllDirectory();
// Not using OperatingSystem.Platform.
// See: https://www.mono-project.com/docs/faq/technical/#how-to-detect-the-execution-platform
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Win32.LoadDll(dllDir, dllName);
}
else
{
Posix.LoadDll(dllDir, dllName);
}
}
private static string GetDirectedDllDirectory()
{
var localPath = new Uri(typeof(DllLoader).Assembly.CodeBase).LocalPath;
var localDir = Path.GetDirectoryName(localPath);
var subDir = Environment.Is64BitProcess ? "x64" : "x86";
var directedDllDir = Path.Combine(localDir, subDir);
return directedDllDir;
}
private static class Win32
{
internal static void LoadDll(string dllDir, string dllName)
{
var dllFileName = $"{dllName}.dll";
var directedDllPath = Path.Combine(dllDir, dllFileName);
// Specify SEARCH_DLL_LOAD_DIR to load dependent libraries located in the same platform-specific directory.
var hLibrary = LoadLibraryEx(directedDllPath, IntPtr.Zero, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
if (hLibrary == IntPtr.Zero)
{
var errorCode = Marshal.GetLastWin32Error();
var exception = new Win32Exception(errorCode);
throw new DllNotFoundException(exception.Message, exception);
}
}
// HMODULE LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
// HMODULE LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr LoadLibraryEx(string lpLibFileName, IntPtr hFile, uint dwFlags);
private const uint LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x1000;
private const uint LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x100;
}
private static class Posix
{
internal static void LoadDll(string dllDir, string dllName)
{
string dllExtension;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
dllExtension = ".so";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
dllExtension = ".dylib";
}
else
{
throw new NotSupportedException();
}
var dllFileName = $"lib{dllName}{dllExtension}";
var directedDllPath = Path.Combine(dllDir, dllFileName);
const int ldFlags = RTLD_NOW | RTLD_GLOBAL;
var hLibrary = DlOpen(directedDllPath, ldFlags);
if (hLibrary == IntPtr.Zero)
{
var pErrStr = DlError();
// `PtrToStringAnsi` always uses the specific constructor of `String` (see dotnet/core#2325),
// which in turn interprets the byte sequence with system default codepage. On OSX and Linux
// the codepage is UTF-8 so the error message should be handled correctly.
var errorMessage = Marshal.PtrToStringAnsi(pErrStr);
throw new DllNotFoundException(errorMessage);
}
}
// OSX and most Linux OS use LP64 so `int` is still 32-bit even on 64-bit platforms.
// void *dlopen(const char *filename, int flag);
[DllImport("libdl", EntryPoint = "dlopen")]
private static extern IntPtr DlOpen([MarshalAs(UnmanagedType.LPStr)] string fileName, int flags);
// char *dlerror(void);
[DllImport("libdl", EntryPoint = "dlerror")]
private static extern IntPtr DlError();
private const int RTLD_LAZY = 0x1;
private const int RTLD_NOW = 0x2;
private const int RTLD_GLOBAL = 0x100;
}
}
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("AssetStudio.PInvoke")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AssetStudio.PInvoke")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("40c796b5-88ce-4adc-acd6-2f4862b7f136")]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,100 @@
using System;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;
namespace AssetStudio.PInvoke
{
// Generally the technique from Steamworks.NET
public class Utf8StringHandle : SafeHandleZeroOrMinusOneIsInvalid
{
static Utf8StringHandle()
{
Utf8 = new UTF8Encoding(false);
}
public Utf8StringHandle(string str)
: base(true)
{
IntPtr buffer;
if (str == null)
{
buffer = IntPtr.Zero;
}
else
{
if (str.Length == 0)
{
buffer = Marshal.AllocHGlobal(1);
unsafe
{
*(byte*)buffer = 0;
}
}
else
{
var strlen = Utf8.GetByteCount(str);
var strBuffer = new byte[strlen + 1];
Utf8.GetBytes(str, 0, str.Length, strBuffer, 0);
buffer = Marshal.AllocHGlobal(strBuffer.Length);
Marshal.Copy(strBuffer, 0, buffer, strBuffer.Length);
}
}
SetHandle(buffer);
}
public static string ReadUtf8StringFromPointer(IntPtr lpstr)
{
if (lpstr == IntPtr.Zero || lpstr == new IntPtr(-1))
{
return null;
}
var byteCount = 0;
unsafe
{
var p = (byte*)lpstr.ToPointer();
while (*p != 0)
{
byteCount += 1;
p += 1;
}
}
if (byteCount == 0)
{
return string.Empty;
}
var strBuffer = new byte[byteCount];
Marshal.Copy(lpstr, strBuffer, 0, byteCount);
var str = Utf8.GetString(strBuffer);
return str;
}
protected override bool ReleaseHandle()
{
if (!IsInvalid)
{
Marshal.FreeHGlobal(handle);
}
return true;
}
private static readonly UTF8Encoding Utf8;
}
}

View File

@ -5,62 +5,122 @@ VisualStudioVersion = 16.0.29920.165
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudio", "AssetStudio\AssetStudio.csproj", "{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssetStudioFBX", "AssetStudioFBX\AssetStudioFBX.vcxproj", "{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Texture2DDecoder", "Texture2DDecoder\Texture2DDecoder.vcxproj", "{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioUtility", "AssetStudioUtility\AssetStudioUtility.csproj", "{80AEC261-21EE-4E4F-A93B-7A744DC84888}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioGUI", "AssetStudioGUI\AssetStudioGUI.csproj", "{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssetStudioFBXNative", "AssetStudioFBXNative\AssetStudioFBXNative.vcxproj", "{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioFBXWrapper", "AssetStudioFBXWrapper\AssetStudioFBXWrapper.csproj", "{BD76E63F-1517-47FA-8233-33E853A3ACEE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Texture2DDecoderNative", "Texture2DDecoderNative\Texture2DDecoderNative.vcxproj", "{29356642-C46E-4144-83D8-22DC09D0D7FD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Texture2DDecoderWrapper", "Texture2DDecoderWrapper\Texture2DDecoderWrapper.csproj", "{2AFCE830-B463-49B3-A026-877E5EAFC0A4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudio.PInvoke", "AssetStudio.PInvoke\AssetStudio.PInvoke.csproj", "{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x64.ActiveCfg = Debug|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x64.Build.0 = Debug|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x86.ActiveCfg = Debug|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x86.Build.0 = Debug|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|Any CPU.Build.0 = Release|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x64.ActiveCfg = Release|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x64.Build.0 = Release|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x86.ActiveCfg = Release|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x86.Build.0 = Release|Any CPU
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Debug|x64.ActiveCfg = Debug|x64
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Debug|x64.Build.0 = Debug|x64
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Debug|x86.ActiveCfg = Debug|Win32
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Debug|x86.Build.0 = Debug|Win32
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Release|x64.ActiveCfg = Release|x64
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Release|x64.Build.0 = Release|x64
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Release|x86.ActiveCfg = Release|Win32
{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}.Release|x86.Build.0 = Release|Win32
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Debug|x64.ActiveCfg = Debug|x64
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Debug|x64.Build.0 = Debug|x64
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Debug|x86.ActiveCfg = Debug|Win32
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Debug|x86.Build.0 = Debug|Win32
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Release|x64.ActiveCfg = Release|x64
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Release|x64.Build.0 = Release|x64
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Release|x86.ActiveCfg = Release|Win32
{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}.Release|x86.Build.0 = Release|Win32
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x64.ActiveCfg = Debug|x64
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x64.Build.0 = Debug|x64
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x86.ActiveCfg = Debug|x86
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x86.Build.0 = Debug|x86
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x64.ActiveCfg = Release|x64
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x64.Build.0 = Release|x64
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x86.ActiveCfg = Release|x86
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x86.Build.0 = Release|x86
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x64.ActiveCfg = Debug|x64
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x64.Build.0 = Debug|x64
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x86.ActiveCfg = Debug|x86
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x86.Build.0 = Debug|x86
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x64.ActiveCfg = Release|x64
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x64.Build.0 = Release|x64
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x86.ActiveCfg = Release|x86
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x86.Build.0 = Release|x86
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|Any CPU.Build.0 = Debug|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x64.ActiveCfg = Debug|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x64.Build.0 = Debug|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x86.ActiveCfg = Debug|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x86.Build.0 = Debug|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|Any CPU.ActiveCfg = Release|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|Any CPU.Build.0 = Release|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x64.ActiveCfg = Release|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x64.Build.0 = Release|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x86.ActiveCfg = Release|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x86.Build.0 = Release|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x64.ActiveCfg = Debug|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x64.Build.0 = Debug|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x86.ActiveCfg = Debug|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x86.Build.0 = Debug|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|Any CPU.Build.0 = Release|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x64.ActiveCfg = Release|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x64.Build.0 = Release|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x86.ActiveCfg = Release|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x86.Build.0 = Release|Any CPU
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|Any CPU.ActiveCfg = Debug|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x64.ActiveCfg = Debug|x64
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x64.Build.0 = Debug|x64
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x86.ActiveCfg = Debug|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x86.Build.0 = Debug|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|Any CPU.ActiveCfg = Release|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x64.ActiveCfg = Release|x64
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x64.Build.0 = Release|x64
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x86.ActiveCfg = Release|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x86.Build.0 = Release|Win32
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Debug|x64.ActiveCfg = Debug|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Debug|x64.Build.0 = Debug|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Debug|x86.ActiveCfg = Debug|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Debug|x86.Build.0 = Debug|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Release|Any CPU.Build.0 = Release|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Release|x64.ActiveCfg = Release|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Release|x64.Build.0 = Release|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Release|x86.ActiveCfg = Release|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Release|x86.Build.0 = Release|Any CPU
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|Any CPU.ActiveCfg = Debug|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x64.ActiveCfg = Debug|x64
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x64.Build.0 = Debug|x64
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x86.ActiveCfg = Debug|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x86.Build.0 = Debug|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|Any CPU.ActiveCfg = Release|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x64.ActiveCfg = Release|x64
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x64.Build.0 = Release|x64
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x86.ActiveCfg = Release|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x86.Build.0 = Release|Win32
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Debug|x64.ActiveCfg = Debug|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Debug|x64.Build.0 = Debug|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Debug|x86.ActiveCfg = Debug|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Debug|x86.Build.0 = Debug|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Release|Any CPU.Build.0 = Release|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Release|x64.ActiveCfg = Release|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Release|x64.Build.0 = Release|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Release|x86.ActiveCfg = Release|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Release|x86.Build.0 = Release|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Debug|Any CPU.Build.0 = Debug|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Debug|x64.ActiveCfg = Debug|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Debug|x64.Build.0 = Debug|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Debug|x86.ActiveCfg = Debug|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Debug|x86.Build.0 = Debug|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Release|Any CPU.ActiveCfg = Release|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Release|Any CPU.Build.0 = Release|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Release|x64.ActiveCfg = Release|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Release|x64.Build.0 = Release|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Release|x86.ActiveCfg = Release|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,20 +0,0 @@
using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;
[assembly:AssemblyTitleAttribute(L"AssetStudioFBX")];
[assembly:AssemblyDescriptionAttribute(L"")];
[assembly:AssemblyConfigurationAttribute(L"")];
[assembly:AssemblyCompanyAttribute(L"")];
[assembly:AssemblyProductAttribute(L"AssetStudioFBX")];
[assembly:AssemblyCopyrightAttribute(L"Copyright © Perfare 2018-2020")];
[assembly:AssemblyTrademarkAttribute(L"")];
[assembly:AssemblyCultureAttribute(L"")];
[assembly:AssemblyVersionAttribute("1.0.*")];
[assembly:ComVisible(false)];
[assembly:CLSCompliantAttribute(true)];

View File

@ -1,43 +0,0 @@
#include "AssetStudioFBX.h"
namespace AssetStudio
{
char* Fbx::StringToUTF8(String^ s)
{
auto bytes = Text::Encoding::UTF8->GetBytes(s);
auto chars = new char[bytes->Length + 1];
pin_ptr<unsigned char> ptr = &bytes[0];
memcpy(chars, ptr, bytes->Length);
chars[bytes->Length] = '\0';
return chars;
}
void Fbx::Init(FbxManager** pSdkManager, FbxScene** pScene)
{
*pSdkManager = FbxManager::Create();
if (!pSdkManager)
{
throw gcnew Exception(gcnew String("Unable to create the FBX SDK manager"));
}
FbxIOSettings* ios = FbxIOSettings::Create(*pSdkManager, IOSROOT);
(*pSdkManager)->SetIOSettings(ios);
*pScene = FbxScene::Create(*pSdkManager, "");
}
Vector3 Fbx::QuaternionToEuler(Quaternion q)
{
FbxAMatrix lMatrixRot;
lMatrixRot.SetQ(FbxQuaternion(q.X, q.Y, q.Z, q.W));
FbxVector4 lEuler = lMatrixRot.GetR();
return Vector3((float)lEuler[0], (float)lEuler[1], (float)lEuler[2]);
}
Quaternion Fbx::EulerToQuaternion(Vector3 v)
{
FbxAMatrix lMatrixRot;
lMatrixRot.SetR(FbxVector4(v.X, v.Y, v.Z));
FbxQuaternion lQuaternion = lMatrixRot.GetQ();
return Quaternion((float)lQuaternion[0], (float)lQuaternion[1], (float)lQuaternion[2], (float)lQuaternion[3]);
}
}

View File

@ -1,86 +0,0 @@
#pragma once
#include <fbxsdk.h>
#ifdef IOS_REF
#undef IOS_REF
#define IOS_REF (*(pSdkManager->GetIOSettings()))
#endif
using namespace System;
using namespace System::Collections::Generic;
using namespace System::IO;
#define WITH_MARSHALLED_STRING(name,str,block)\
{ \
char* name; \
try \
{ \
name = StringToUTF8(str); \
block \
} \
finally \
{ \
delete name; \
} \
}
static char* FBXVersion[] =
{
FBX_2010_00_COMPATIBLE,
FBX_2011_00_COMPATIBLE,
FBX_2012_00_COMPATIBLE,
FBX_2013_00_COMPATIBLE,
FBX_2014_00_COMPATIBLE,
FBX_2016_00_COMPATIBLE
};
namespace AssetStudio {
public ref class Fbx
{
public:
static Vector3 QuaternionToEuler(Quaternion q);
static Quaternion EulerToQuaternion(Vector3 v);
static char* StringToUTF8(String^ s);
static void Init(FbxManager** pSdkManager, FbxScene** pScene);
ref class Exporter
{
public:
static void Export(String^ path, IImported^ imported, bool eulerFilter, float filterPrecision,
bool allNodes, bool skins, bool animation, bool blendShape, bool castToBone, float boneSize, float scaleFactor, int versionIndex, bool isAscii);
private:
bool exportSkins;
float boneSize;
IImported^ imported;
HashSet<String^>^ framePaths;
Dictionary<ImportedFrame^, size_t>^ frameToNode;
List<ImportedFrame^>^ meshFrames;
char* cDest;
FbxManager* pSdkManager;
FbxScene* pScene;
FbxExporter* pExporter;
FbxArray<FbxSurfacePhong*>* pMaterials;
FbxArray<FbxFileTexture*>* pTextures;
FbxPose* pBindPose;
Exporter(String^ name, IImported^ imported, bool allNodes, bool skins, bool castToBone, float boneSize, float scaleFactor, int versionIndex, bool isAscii);
~Exporter();
void Exporter::LinkTexture(ImportedMaterialTexture^ texture, FbxFileTexture* pTexture, FbxProperty& prop);
void SetJointsNode(ImportedFrame^ frame, HashSet<String^>^ bonePaths, bool allBones);
HashSet<String^>^ SearchHierarchy();
void SearchHierarchy(ImportedFrame^ frame, HashSet<String^>^ exportFrames);
void SetJointsFromImportedMeshes(bool allBones);
void ExportFrame(FbxNode* pParentNode, ImportedFrame^ frame);
void ExportMesh(FbxNode* pFrameNode, ImportedMesh^ iMesh);
FbxFileTexture* ExportTexture(ImportedTexture^ matTex);
void ExportAnimations(bool eulerFilter, float filterValue);
void ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision);
void ExportMorphs();
};
};
}

View File

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="AssetStudioFBX.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="AssemblyInfo.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="AssetStudioFBX.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="AssetStudioFBXExporter.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -1,915 +0,0 @@
#include "AssetStudioFBX.h"
namespace AssetStudio
{
void Fbx::Exporter::Export(String^ path, IImported^ imported, bool eulerFilter, float filterPrecision,
bool allNodes, bool skins, bool animation, bool blendShape, bool castToBone, float boneSize, float scaleFactor, int versionIndex, bool isAscii)
{
FileInfo^ file = gcnew FileInfo(path);
DirectoryInfo^ dir = file->Directory;
if (!dir->Exists)
{
dir->Create();
}
String^ currentDir = Directory::GetCurrentDirectory();
Directory::SetCurrentDirectory(dir->FullName);
auto name = Path::GetFileName(path);
Exporter^ exporter = gcnew Exporter(name, imported, allNodes, skins, castToBone, boneSize, scaleFactor, versionIndex, isAscii);
if (blendShape)
{
exporter->ExportMorphs();
}
if (animation)
{
exporter->ExportAnimations(eulerFilter, filterPrecision);
}
exporter->pExporter->Export(exporter->pScene);
delete exporter;
Directory::SetCurrentDirectory(currentDir);
}
Fbx::Exporter::Exporter(String^ name, IImported^ imported, bool allNodes, bool skins, bool castToBone, float boneSize, float scaleFactor, int versionIndex, bool isAscii)
{
this->imported = imported;
exportSkins = skins;
this->boneSize = boneSize;
cDest = NULL;
pSdkManager = NULL;
pScene = NULL;
pExporter = NULL;
pMaterials = NULL;
pTextures = NULL;
pin_ptr<FbxManager*> pSdkManagerPin = &pSdkManager;
pin_ptr<FbxScene*> pScenePin = &pScene;
Init(pSdkManagerPin, pScenePin);
IOS_REF.SetBoolProp(EXP_FBX_MATERIAL, true);
IOS_REF.SetBoolProp(EXP_FBX_TEXTURE, true);
IOS_REF.SetBoolProp(EXP_FBX_EMBEDDED, false);
IOS_REF.SetBoolProp(EXP_FBX_SHAPE, true);
IOS_REF.SetBoolProp(EXP_FBX_GOBO, true);
IOS_REF.SetBoolProp(EXP_FBX_ANIMATION, true);
IOS_REF.SetBoolProp(EXP_FBX_GLOBAL_SETTINGS, true);
FbxGlobalSettings& globalSettings = pScene->GetGlobalSettings();
globalSettings.SetSystemUnit(FbxSystemUnit(scaleFactor));
if (imported->AnimationList->Count > 0)
{
auto ani = imported->AnimationList[0];
if (ani->SampleRate == 60.0f)
{
globalSettings.SetTimeMode(FbxTime::eFrames60);
}
}
cDest = StringToUTF8(name);
pExporter = FbxExporter::Create(pScene, "");
int pFileFormat = 0;
if (versionIndex == 0)
{
pFileFormat = 3;
if (isAscii)
{
pFileFormat = 4;
}
}
else
{
pExporter->SetFileExportVersion(FBXVersion[versionIndex]);
if (isAscii)
{
pFileFormat = 1;
}
}
if (!pExporter->Initialize(cDest, pFileFormat, pSdkManager->GetIOSettings()))
{
throw gcnew Exception(gcnew String("Failed to initialize FbxExporter: ") + gcnew String(pExporter->GetStatus().GetErrorString()));
}
framePaths = nullptr;
if (!allNodes)
{
framePaths = SearchHierarchy();
if (!framePaths)
{
return;
}
}
pBindPose = FbxPose::Create(pScene, "BindPose");
pScene->AddPose(pBindPose);
frameToNode = gcnew Dictionary<ImportedFrame^, size_t>();
meshFrames = imported->MeshList != nullptr ? gcnew List<ImportedFrame^>() : nullptr;
ExportFrame(pScene->GetRootNode(), imported->RootFrame);
if (imported->MeshList != nullptr)
{
SetJointsFromImportedMeshes(castToBone);
pMaterials = new FbxArray<FbxSurfacePhong*>();
pTextures = new FbxArray<FbxFileTexture*>();
pMaterials->Reserve(imported->MaterialList->Count);
pTextures->Reserve(imported->TextureList->Count);
for (int i = 0; i < meshFrames->Count; i++)
{
auto meshFram = meshFrames[i];
FbxNode* meshNode = (FbxNode*)frameToNode[meshFram];
ImportedMesh^ mesh = ImportedHelpers::FindMesh(meshFram->Path, imported->MeshList);
ExportMesh(meshNode, mesh);
}
}
else
{
SetJointsNode(imported->RootFrame, nullptr, true);
}
}
Fbx::Exporter::~Exporter()
{
imported = nullptr;
if (framePaths != nullptr)
{
framePaths->Clear();
}
if (frameToNode != nullptr)
{
frameToNode->Clear();
}
if (meshFrames != nullptr)
{
meshFrames->Clear();
}
if (pMaterials != NULL)
{
delete pMaterials;
}
if (pTextures != NULL)
{
delete pTextures;
}
if (pExporter != NULL)
{
pExporter->Destroy();
}
if (pScene != NULL)
{
pScene->Destroy();
}
if (pSdkManager != NULL)
{
pSdkManager->Destroy();
}
if (cDest != NULL)
{
delete cDest;
}
}
void Fbx::Exporter::SetJointsNode(ImportedFrame^ frame, HashSet<String^>^ bonePaths, bool castToBone)
{
size_t pointer;
if (frameToNode->TryGetValue(frame, pointer))
{
auto pNode = (FbxNode*)pointer;
if (castToBone)
{
FbxSkeleton* pJoint = FbxSkeleton::Create(pScene, "");
pJoint->Size.Set(FbxDouble(boneSize));
pJoint->SetSkeletonType(FbxSkeleton::eLimbNode);
pNode->SetNodeAttribute(pJoint);
}
else if (bonePaths->Contains(frame->Path))
{
FbxSkeleton* pJoint = FbxSkeleton::Create(pScene, "");
pJoint->Size.Set(FbxDouble(boneSize));
pJoint->SetSkeletonType(FbxSkeleton::eLimbNode);
pNode->SetNodeAttribute(pJoint);
pJoint = FbxSkeleton::Create(pScene, "");
pJoint->Size.Set(FbxDouble(boneSize));
pJoint->SetSkeletonType(FbxSkeleton::eLimbNode);
pNode->GetParent()->SetNodeAttribute(pJoint);
}
else
{
FbxNull* pNull = FbxNull::Create(pScene, "");
if (pNode->GetChildCount() > 0)
{
pNull->Look.Set(FbxNull::eNone);
}
pNode->SetNodeAttribute(pNull);
}
}
for (int i = 0; i < frame->Count; i++)
{
SetJointsNode(frame[i], bonePaths, castToBone);
}
}
HashSet<String^>^ Fbx::Exporter::SearchHierarchy()
{
if (imported->MeshList == nullptr || imported->MeshList->Count == 0)
{
return nullptr;
}
HashSet<String^>^ exportFrames = gcnew HashSet<String^>();
SearchHierarchy(imported->RootFrame, exportFrames);
return exportFrames;
}
void Fbx::Exporter::SearchHierarchy(ImportedFrame^ frame, HashSet<String^>^ exportFrames)
{
ImportedMesh^ meshListSome = ImportedHelpers::FindMesh(frame->Path, imported->MeshList);
if (meshListSome != nullptr)
{
ImportedFrame^ parent = frame;
while (parent != nullptr)
{
exportFrames->Add(parent->Path);
parent = parent->Parent;
}
List<ImportedBone^>^ boneList = meshListSome->BoneList;
if (boneList != nullptr)
{
for (int i = 0; i < boneList->Count; i++)
{
if (!exportFrames->Contains(boneList[i]->Path))
{
ImportedFrame^ boneParent = imported->RootFrame->FindFrameByPath(boneList[i]->Path);
while (boneParent != nullptr)
{
exportFrames->Add(boneParent->Path);
boneParent = boneParent->Parent;
}
}
}
}
}
for (int i = 0; i < frame->Count; i++)
{
SearchHierarchy(frame[i], exportFrames);
}
}
void Fbx::Exporter::SetJointsFromImportedMeshes(bool castToBone)
{
if (!exportSkins)
{
return;
}
HashSet<String^>^ bonePaths = gcnew HashSet<String^>();
for (int i = 0; i < imported->MeshList->Count; i++)
{
ImportedMesh^ meshList = imported->MeshList[i];
List<ImportedBone^>^ boneList = meshList->BoneList;
if (boneList != nullptr)
{
for (int j = 0; j < boneList->Count; j++)
{
ImportedBone^ bone = boneList[j];
bonePaths->Add(bone->Path);
}
}
}
SetJointsNode(imported->RootFrame, bonePaths, castToBone);
}
void Fbx::Exporter::ExportFrame(FbxNode* pParentNode, ImportedFrame^ frame)
{
if (framePaths == nullptr || framePaths->Contains(frame->Path))
{
FbxNode* pFrameNode;
WITH_MARSHALLED_STRING
(
pName,
frame->Name,
pFrameNode = FbxNode::Create(pScene, pName);
);
pFrameNode->LclScaling.Set(FbxDouble3(frame->LocalScale.X, frame->LocalScale.Y, frame->LocalScale.Z));
pFrameNode->LclRotation.Set(FbxDouble3(frame->LocalRotation.X, frame->LocalRotation.Y, frame->LocalRotation.Z));
pFrameNode->LclTranslation.Set(FbxDouble3(frame->LocalPosition.X, frame->LocalPosition.Y, frame->LocalPosition.Z));
pFrameNode->SetPreferedAngle(pFrameNode->LclRotation.Get());
pParentNode->AddChild(pFrameNode);
pBindPose->Add(pFrameNode, pFrameNode->EvaluateGlobalTransform());
if (imported->MeshList != nullptr && ImportedHelpers::FindMesh(frame->Path, imported->MeshList) != nullptr)
{
meshFrames->Add(frame);
}
frameToNode->Add(frame, (size_t)pFrameNode);
for (int i = 0; i < frame->Count; i++)
{
ExportFrame(pFrameNode, frame[i]);
}
}
}
void Fbx::Exporter::ExportMesh(FbxNode* pFrameNode, ImportedMesh^ iMesh)
{
List<ImportedBone^>^ boneList = iMesh->BoneList;
bool hasBones;
if (exportSkins && boneList != nullptr)
{
hasBones = boneList->Count > 0;
}
else
{
hasBones = false;
}
FbxArray<FbxCluster*>* pClusterArray = nullptr;
try
{
if (hasBones)
{
pClusterArray = new FbxArray<FbxCluster*>(boneList->Count);
for (int i = 0; i < boneList->Count; i++)
{
auto bone = boneList[i];
if (bone->Path != nullptr)
{
auto frame = imported->RootFrame->FindFrameByPath(bone->Path);
auto boneNode = (FbxNode*)frameToNode[frame];
FbxString lClusterName = boneNode->GetNameOnly() + FbxString("Cluster");
FbxCluster* pCluster = FbxCluster::Create(pScene, lClusterName.Buffer());
pCluster->SetLink(boneNode);
pCluster->SetLinkMode(FbxCluster::eTotalOne);
pClusterArray->Add(pCluster);
}
else
{
pClusterArray->Add(NULL);
}
}
}
FbxMesh* pMesh = FbxMesh::Create(pScene, pFrameNode->GetName());
pFrameNode->SetNodeAttribute(pMesh);
int vertexCount = 0;
for (int i = 0; i < iMesh->SubmeshList->Count; i++)
{
vertexCount += iMesh->SubmeshList[i]->VertexList->Count;
}
pMesh->InitControlPoints(vertexCount);
FbxVector4* pControlPoints = pMesh->GetControlPoints();
FbxGeometryElementNormal* lGeometryElementNormal = NULL;
if (iMesh->hasNormal)
{
lGeometryElementNormal = pMesh->CreateElementNormal();
lGeometryElementNormal->SetMappingMode(FbxGeometryElement::eByControlPoint);
lGeometryElementNormal->SetReferenceMode(FbxGeometryElement::eDirect);
}
if (iMesh->hasUV[0])
{
auto lGeometryElementUV = pMesh->CreateElementUV("UV0", FbxLayerElement::eTextureDiffuse);
lGeometryElementUV->SetMappingMode(FbxGeometryElement::eByControlPoint);
lGeometryElementUV->SetReferenceMode(FbxGeometryElement::eDirect);
}
if (iMesh->hasUV[1])
{
auto lGeometryElementUV = pMesh->CreateElementUV("UV1", FbxLayerElement::eTextureNormalMap);
lGeometryElementUV->SetMappingMode(FbxGeometryElement::eByControlPoint);
lGeometryElementUV->SetReferenceMode(FbxGeometryElement::eDirect);
}
/*for (int uv = 0; uv < 8; uv++)
{
if (iMesh->hasUV[uv])
{
auto lGeometryElementUV = pMesh->CreateElementUV(FbxString("UV") + FbxString(uv));
lGeometryElementUV->SetMappingMode(FbxGeometryElement::eByControlPoint);
lGeometryElementUV->SetReferenceMode(FbxGeometryElement::eDirect);
}
}*/
FbxGeometryElementTangent* lGeometryElementTangent = NULL;
if (iMesh->hasTangent)
{
lGeometryElementTangent = pMesh->CreateElementTangent();
lGeometryElementTangent->SetMappingMode(FbxGeometryElement::eByControlPoint);
lGeometryElementTangent->SetReferenceMode(FbxGeometryElement::eDirect);
}
FbxGeometryElementVertexColor* lGeometryElementVertexColor = NULL;
if (iMesh->hasColor)
{
lGeometryElementVertexColor = pMesh->CreateElementVertexColor();
lGeometryElementVertexColor->SetMappingMode(FbxGeometryElement::eByControlPoint);
lGeometryElementVertexColor->SetReferenceMode(FbxGeometryElement::eDirect);
}
FbxGeometryElementMaterial* lGeometryElementMaterial = pMesh->CreateElementMaterial();
lGeometryElementMaterial->SetMappingMode(FbxGeometryElement::eByPolygon);
lGeometryElementMaterial->SetReferenceMode(FbxGeometryElement::eIndexToDirect);
int firstVertex = 0;
for (int i = 0; i < iMesh->SubmeshList->Count; i++)
{
ImportedSubmesh^ meshObj = iMesh->SubmeshList[i];
List<ImportedVertex^>^ vertexList = meshObj->VertexList;
List<ImportedFace^>^ faceList = meshObj->FaceList;
int materialIndex = 0;
ImportedMaterial^ mat = ImportedHelpers::FindMaterial(meshObj->Material, imported->MaterialList);
if (mat != nullptr)
{
char* pMatName = NULL;
try
{
pMatName = StringToUTF8(mat->Name);
int foundMat = -1;
for (int j = 0; j < pMaterials->GetCount(); j++)
{
FbxSurfacePhong* pMatTemp = pMaterials->GetAt(j);
if (strcmp(pMatTemp->GetName(), pMatName) == 0)
{
foundMat = j;
break;
}
}
FbxSurfacePhong* pMat;
if (foundMat >= 0)
{
pMat = pMaterials->GetAt(foundMat);
}
else
{
FbxString lShadingName = "Phong";
Color diffuse = mat->Diffuse;
Color ambient = mat->Ambient;
Color emissive = mat->Emissive;
Color specular = mat->Specular;
Color reflection = mat->Reflection;
pMat = FbxSurfacePhong::Create(pScene, pMatName);
pMat->Diffuse.Set(FbxDouble3(diffuse.R, diffuse.G, diffuse.B));
//pMat->DiffuseFactor.Set(FbxDouble(diffuse.A));
pMat->Ambient.Set(FbxDouble3(ambient.R, ambient.G, ambient.B));
//pMat->AmbientFactor.Set(FbxDouble(ambient.A));
pMat->Emissive.Set(FbxDouble3(emissive.R, emissive.G, emissive.B));
//pMat->EmissiveFactor.Set(FbxDouble(emissive.A));
pMat->Specular.Set(FbxDouble3(specular.R, specular.G, specular.B));
//pMat->SpecularFactor.Set(FbxDouble(specular.A));
pMat->Reflection.Set(FbxDouble3(reflection.R, reflection.G, reflection.B));
//pMat->ReflectionFactor.Set(FbxDouble(reflection.A));
pMat->Shininess.Set(FbxDouble(mat->Shininess));
pMat->TransparencyFactor.Set(FbxDouble(mat->Transparency));
pMat->ShadingModel.Set(lShadingName);
pMaterials->Add(pMat);
}
materialIndex = pFrameNode->AddMaterial(pMat);
bool hasTexture = false;
for each (ImportedMaterialTexture ^ texture in mat->Textures)
{
auto pTexture = ExportTexture(ImportedHelpers::FindTexture(texture->Name, imported->TextureList));
if (pTexture != NULL)
{
if (texture->Dest == 0)
{
LinkTexture(texture, pTexture, pMat->Diffuse);
hasTexture = true;
}
else if (texture->Dest == 1)
{
LinkTexture(texture, pTexture, pMat->NormalMap);
hasTexture = true;
}
else if (texture->Dest == 2)
{
LinkTexture(texture, pTexture, pMat->Specular);
hasTexture = true;
}
else if (texture->Dest == 3)
{
LinkTexture(texture, pTexture, pMat->Bump);
hasTexture = true;
}
}
}
if (hasTexture)
{
pFrameNode->SetShadingMode(FbxNode::eTextureShading);
}
}
finally
{
delete pMatName;
}
}
for (int j = 0; j < vertexList->Count; j++)
{
ImportedVertex^ iVertex = vertexList[j];
Vector3 vertex = iVertex->Vertex;
pControlPoints[j + firstVertex] = FbxVector4(vertex.X, vertex.Y, vertex.Z, 0);
if (iMesh->hasNormal)
{
Vector3 normal = iVertex->Normal;
lGeometryElementNormal->GetDirectArray().Add(FbxVector4(normal.X, normal.Y, normal.Z, 0));
}
//for (int uv = 0; uv < 8; uv++)
for (int uv = 0; uv < 2; uv++)
{
if (iMesh->hasUV[uv])
{
auto m_UV = iVertex->UV[uv];
auto lGeometryElementUV = pMesh->GetElementUV(uv);
lGeometryElementUV->GetDirectArray().Add(FbxVector2(m_UV[0], m_UV[1]));
}
}
if (iMesh->hasTangent)
{
Vector4 tangent = iVertex->Tangent;
lGeometryElementTangent->GetDirectArray().Add(FbxVector4(tangent.X, tangent.Y, tangent.Z, tangent.W));
}
if (iMesh->hasColor)
{
auto color = iVertex->Color;
lGeometryElementVertexColor->GetDirectArray().Add(FbxColor(color.R, color.G, color.B, color.A));
}
if (hasBones && iVertex->BoneIndices != nullptr)
{
auto boneIndices = iVertex->BoneIndices;
auto weights4 = iVertex->Weights;
for (int k = 0; k < 4; k++)
{
if (boneIndices[k] < boneList->Count && weights4[k] > 0)
{
FbxCluster* pCluster = pClusterArray->GetAt(boneIndices[k]);
if (pCluster)
{
pCluster->AddControlPointIndex(j + firstVertex, weights4[k]);
}
}
}
}
}
for (int j = 0; j < faceList->Count; j++)
{
ImportedFace^ face = faceList[j];
pMesh->BeginPolygon(materialIndex);
pMesh->AddPolygon(face->VertexIndices[0] + firstVertex);
pMesh->AddPolygon(face->VertexIndices[1] + firstVertex);
pMesh->AddPolygon(face->VertexIndices[2] + firstVertex);
pMesh->EndPolygon();
}
firstVertex += vertexList->Count;
}
if (hasBones)
{
FbxSkin* pSkin = FbxSkin::Create(pScene, "");
FbxAMatrix lMeshMatrix = pFrameNode->EvaluateGlobalTransform();
for (int j = 0; j < boneList->Count; j++)
{
FbxCluster* pCluster = pClusterArray->GetAt(j);
if (pCluster)
{
auto boneMatrix = boneList[j]->Matrix;
FbxAMatrix lBoneMatrix;
for (int m = 0; m < 4; m++)
{
for (int n = 0; n < 4; n++)
{
lBoneMatrix.mData[m][n] = boneMatrix[m, n];
}
}
pCluster->SetTransformMatrix(lMeshMatrix);
pCluster->SetTransformLinkMatrix(lMeshMatrix * lBoneMatrix.Inverse());
pSkin->AddCluster(pCluster);
}
}
if (pSkin->GetClusterCount() > 0)
{
pMesh->AddDeformer(pSkin);
}
}
}
finally
{
if (pClusterArray != NULL)
{
delete pClusterArray;
}
}
}
FbxFileTexture* Fbx::Exporter::ExportTexture(ImportedTexture^ matTex)
{
FbxFileTexture* pTex = NULL;
if (matTex != nullptr)
{
String^ matTexName = matTex->Name;
char* pTexName = NULL;
try
{
pTexName = StringToUTF8(matTexName);
int foundTex = -1;
for (int i = 0; i < pTextures->GetCount(); i++)
{
FbxFileTexture* pTexTemp = pTextures->GetAt(i);
if (strcmp(pTexTemp->GetName(), pTexName) == 0)
{
foundTex = i;
break;
}
}
if (foundTex >= 0)
{
pTex = pTextures->GetAt(foundTex);
}
else
{
pTex = FbxFileTexture::Create(pScene, pTexName);
pTex->SetFileName(pTexName);
pTex->SetTextureUse(FbxTexture::eStandard);
pTex->SetMappingType(FbxTexture::eUV);
pTex->SetMaterialUse(FbxFileTexture::eModelMaterial);
pTex->SetSwapUV(false);
pTex->SetTranslation(0.0, 0.0);
pTex->SetScale(1.0, 1.0);
pTex->SetRotation(0.0, 0.0);
pTextures->Add(pTex);
FileInfo^ file = gcnew FileInfo(matTex->Name);
BinaryWriter^ writer = gcnew BinaryWriter(file->Create());
writer->Write(matTex->Data);
writer->Close();
}
}
finally
{
delete pTexName;
}
}
return pTex;
}
void Fbx::Exporter::LinkTexture(ImportedMaterialTexture^ texture, FbxFileTexture* pTexture, FbxProperty& prop)
{
pTexture->SetTranslation(texture->Offset.X, texture->Offset.Y);
pTexture->SetScale(texture->Scale.X, texture->Scale.Y);
prop.ConnectSrcObject(pTexture);
}
void Fbx::Exporter::ExportAnimations(bool eulerFilter, float filterPrecision)
{
auto importedAnimationList = imported->AnimationList;
if (importedAnimationList == nullptr)
{
return;
}
FbxAnimCurveFilterUnroll* lFilter = eulerFilter ? new FbxAnimCurveFilterUnroll() : NULL;
for (int i = 0; i < importedAnimationList->Count; i++)
{
auto importedAnimation = importedAnimationList[i];
FbxString kTakeName;
if (importedAnimation->Name)
{
WITH_MARSHALLED_STRING
(
pClipName,
importedAnimation->Name,
kTakeName = FbxString(pClipName);
);
}
else
{
kTakeName = FbxString("Take") + FbxString(i);
}
ExportKeyframedAnimation(importedAnimation, kTakeName, lFilter, filterPrecision);
}
}
void Fbx::Exporter::ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision)
{
List<ImportedAnimationKeyframedTrack^>^ pAnimationList = parser->TrackList;
char* lTakeName = kTakeName.Buffer();
FbxAnimStack* lAnimStack = FbxAnimStack::Create(pScene, lTakeName);
FbxAnimLayer* lAnimLayer = FbxAnimLayer::Create(pScene, "Base Layer");
lAnimStack->AddMember(lAnimLayer);
for (int j = 0; j < pAnimationList->Count; j++)
{
ImportedAnimationKeyframedTrack^ keyframeList = pAnimationList[j];
if (keyframeList->Path == nullptr)
{
continue;
}
auto frame = imported->RootFrame->FindFrameByPath(keyframeList->Path);
if (frame != nullptr)
{
FbxNode* pNode = (FbxNode*)frameToNode[frame];
FbxAnimCurve* lCurveSX = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
FbxAnimCurve* lCurveSY = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
FbxAnimCurve* lCurveSZ = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
FbxAnimCurve* lCurveRX = pNode->LclRotation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
FbxAnimCurve* lCurveRY = pNode->LclRotation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
FbxAnimCurve* lCurveRZ = pNode->LclRotation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
FbxAnimCurve* lCurveTX = pNode->LclTranslation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
FbxAnimCurve* lCurveTY = pNode->LclTranslation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
FbxAnimCurve* lCurveTZ = pNode->LclTranslation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
lCurveSX->KeyModifyBegin();
lCurveSY->KeyModifyBegin();
lCurveSZ->KeyModifyBegin();
lCurveRX->KeyModifyBegin();
lCurveRY->KeyModifyBegin();
lCurveRZ->KeyModifyBegin();
lCurveTX->KeyModifyBegin();
lCurveTY->KeyModifyBegin();
lCurveTZ->KeyModifyBegin();
FbxTime lTime;
for each (auto Scaling in keyframeList->Scalings)
{
lTime.SetSecondDouble(Scaling->time);
lCurveSX->KeySet(lCurveSX->KeyAdd(lTime), lTime, Scaling->value.X);
lCurveSY->KeySet(lCurveSY->KeyAdd(lTime), lTime, Scaling->value.Y);
lCurveSZ->KeySet(lCurveSZ->KeyAdd(lTime), lTime, Scaling->value.Z);
}
for each (auto Rotation in keyframeList->Rotations)
{
lTime.SetSecondDouble(Rotation->time);
lCurveRX->KeySet(lCurveRX->KeyAdd(lTime), lTime, Rotation->value.X);
lCurveRY->KeySet(lCurveRY->KeyAdd(lTime), lTime, Rotation->value.Y);
lCurveRZ->KeySet(lCurveRZ->KeyAdd(lTime), lTime, Rotation->value.Z);
}
for each (auto Translation in keyframeList->Translations)
{
lTime.SetSecondDouble(Translation->time);
lCurveTX->KeySet(lCurveTX->KeyAdd(lTime), lTime, Translation->value.X);
lCurveTY->KeySet(lCurveTY->KeyAdd(lTime), lTime, Translation->value.Y);
lCurveTZ->KeySet(lCurveTZ->KeyAdd(lTime), lTime, Translation->value.Z);
}
lCurveSX->KeyModifyEnd();
lCurveSY->KeyModifyEnd();
lCurveSZ->KeyModifyEnd();
lCurveRX->KeyModifyEnd();
lCurveRY->KeyModifyEnd();
lCurveRZ->KeyModifyEnd();
lCurveTX->KeyModifyEnd();
lCurveTY->KeyModifyEnd();
lCurveTZ->KeyModifyEnd();
if (eulerFilter)
{
FbxAnimCurve* lCurve[3];
lCurve[0] = lCurveRX;
lCurve[1] = lCurveRY;
lCurve[2] = lCurveRZ;
eulerFilter->Reset();
eulerFilter->SetQualityTolerance(filterPrecision);
eulerFilter->Apply(lCurve, 3);
}
//BlendShape
if (keyframeList->BlendShape != nullptr)
{
FbxString channelName;
WITH_MARSHALLED_STRING
(
pClipName,
keyframeList->BlendShape->ChannelName,
channelName = FbxString(pClipName);
);
auto lGeometry = (FbxGeometry*)pNode->GetNodeAttribute();
int lBlendShapeDeformerCount = lGeometry->GetDeformerCount(FbxDeformer::eBlendShape);
if (lBlendShapeDeformerCount > 0)
{
FbxBlendShape* lBlendShape = (FbxBlendShape*)lGeometry->GetDeformer(0, FbxDeformer::eBlendShape);
int lBlendShapeChannelCount = lBlendShape->GetBlendShapeChannelCount();
for (int lChannelIndex = 0; lChannelIndex < lBlendShapeChannelCount; ++lChannelIndex)
{
FbxBlendShapeChannel* lChannel = lBlendShape->GetBlendShapeChannel(lChannelIndex);
FbxString lChannelName = lChannel->GetNameOnly();
if (lChannelName == channelName)
{
FbxAnimCurve* lAnimCurve = lGeometry->GetShapeChannel(0, lChannelIndex, lAnimLayer, true);
lAnimCurve->KeyModifyBegin();
for each (auto keyframe in keyframeList->BlendShape->Keyframes)
{
lTime.SetSecondDouble(keyframe->time);
int lKeyIndex = lAnimCurve->KeyAdd(lTime);
lAnimCurve->KeySetValue(lKeyIndex, keyframe->value);
lAnimCurve->KeySetInterpolation(lKeyIndex, FbxAnimCurveDef::eInterpolationCubic);
}
lAnimCurve->KeyModifyEnd();
}
}
}
}
}
}
}
void Fbx::Exporter::ExportMorphs()
{
if (imported->MeshList == nullptr)
{
return;
}
for each (ImportedMorph ^ morph in imported->MorphList)
{
auto frame = imported->RootFrame->FindFrameByPath(morph->Path);
if (frame != nullptr)
{
FbxNode* pNode = (FbxNode*)frameToNode[frame];
FbxMesh* pMesh = pNode->GetMesh();
FbxBlendShape* lBlendShape = FbxBlendShape::Create(pScene, pMesh->GetNameOnly() + FbxString("BlendShape"));
pMesh->AddDeformer(lBlendShape);
for (int i = 0; i < morph->Channels->Count; i++)
{
auto channel = morph->Channels[i];
FbxBlendShapeChannel* lBlendShapeChannel;
WITH_MARSHALLED_STRING
(
pChannelName,
channel->Name,
lBlendShapeChannel = FbxBlendShapeChannel::Create(pScene, pChannelName);
);
lBlendShape->AddBlendShapeChannel(lBlendShapeChannel);
for each (ImportedMorphKeyframe ^ keyframe in channel->KeyframeList)
{
FbxShape* lShape = FbxShape::Create(pScene, FbxString(keyframe->Weight));
lBlendShapeChannel->AddTargetShape(lShape, keyframe->Weight);
auto vectorCount = pMesh->GetControlPointsCount();
FbxVector4* orilVector4 = pMesh->GetControlPoints();
lShape->InitControlPoints(vectorCount);
FbxVector4* lVector4 = lShape->GetControlPoints();
for (int j = 0; j < vectorCount; j++)
{
auto vertex = orilVector4[j];
lVector4[j] = FbxVector4(vertex);
}
for (int j = 0; j < keyframe->VertexList->Count; j++)
{
auto index = keyframe->VertexList[j]->Index;
auto vertex = keyframe->VertexList[j]->Vertex->Vertex;
lVector4[index] = FbxVector4(vertex.X, vertex.Y, vertex.Z, 0);
}
}
}
}
}
}
}

View File

@ -0,0 +1,99 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Language neutral resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
#pragma code_page(65001)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "000004b0"
BEGIN
VALUE "FileDescription", "AssetStudioFBXNative"
VALUE "FileVersion", "1.0.0.1"
VALUE "InternalName", "AssetStudioFBXNative.dll"
VALUE "LegalCopyright", "Copyright (C) Perfare 2018-2020; Copyright (C) hozuki 2020"
VALUE "OriginalFilename", "AssetStudioFBXNative.dll"
VALUE "ProductName", "AssetStudioFBXNative"
VALUE "ProductVersion", "1.0.0.1"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0, 1200
END
END
#endif // Language neutral resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -20,10 +20,9 @@
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{B82DD1BA-4EEC-4F29-A686-03D7F0DF39B8}</ProjectGuid>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<Keyword>ManagedCProj</Keyword>
<RootNamespace>AssetStudioFBX</RootNamespace>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{11ea25a3-ed68-40ee-a9d0-7fde3b583027}</ProjectGuid>
<RootNamespace>AssetStudioFBXNative</RootNamespace>
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
@ -31,28 +30,26 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CLRSupport>true</CLRSupport>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CLRSupport>true</CLRSupport>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
@ -73,14 +70,60 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<TargetExt>.dll</TargetExt>
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<TargetExt>.dll</TargetExt>
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<TargetExt>.dll</TargetExt>
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<TargetExt>.dll</TargetExt>
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>FBXSDK_SHARED;WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_AS_DLL;FBXSDK_SHARED;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x86\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_AS_DLL;FBXSDK_SHARED;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x86\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
@ -88,52 +131,61 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>FBXSDK_SHARED;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_AS_DLL;FBXSDK_SHARED;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x64\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>FBXSDK_SHARED;WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x86\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>FBXSDK_SHARED;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_AS_DLL;FBXSDK_SHARED;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x64\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="AssetStudioFBX.h" />
<ClCompile Include="asfbx_anim_context.cpp" />
<ClCompile Include="asfbx_context.cpp" />
<ClCompile Include="api.cpp" />
<ClCompile Include="asfbx_morph_context.cpp" />
<ClCompile Include="asfbx_skin_context.cpp" />
<ClCompile Include="utils.cpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AssemblyInfo.cpp" />
<ClCompile Include="AssetStudioFBX.cpp" />
<ClCompile Include="AssetStudioFBXExporter.cpp" />
<ClInclude Include="api.h" />
<ClInclude Include="asfbx_anim_context.h" />
<ClInclude Include="asfbx_context.h" />
<ClInclude Include="asfbx_morph_context.h" />
<ClInclude Include="asfbx_skin_context.h" />
<ClInclude Include="bool32_t.h" />
<ClInclude Include="dllexport.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="utils.h" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<None Include="cpp.hint" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj">
<Project>{7662f8c2-7bfd-442e-a948-a43b4f7eb06e}</Project>
</ProjectReference>
<ResourceCompile Include="AssetStudioFBXNative.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="utils.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="api.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="asfbx_context.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="asfbx_skin_context.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="asfbx_anim_context.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="asfbx_morph_context.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="dllexport.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="api.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="utils.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="bool32_t.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="asfbx_context.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="asfbx_skin_context.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="asfbx_anim_context.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="asfbx_morph_context.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="AssetStudioFBXNative.rc">
<Filter>资源文件</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

1136
AssetStudioFBXNative/api.cpp Normal file

File diff suppressed because it is too large Load Diff

155
AssetStudioFBXNative/api.h Normal file
View File

@ -0,0 +1,155 @@
#pragma once
#include "dllexport.h"
#include "bool32_t.h"
namespace fbxsdk
{
class FbxNode;
class FbxFileTexture;
template<typename T, const int Alignment = 16>
class FbxArray;
class FbxCluster;
class FbxMesh;
class FbxSurfacePhong;
}
struct AsFbxContext;
struct AsFbxSkinContext;
struct AsFbxAnimContext;
struct AsFbxMorphContext;
AS_API(void) AsUtilQuaternionToEuler(float qx, float qy, float qz, float qw, float* vx, float* vy, float* vz);
AS_API(void) AsUtilEulerToQuaternion(float vx, float vy, float vz, float* qx, float* qy, float* qz, float* qw);
// All strings ([const] char *) in this header are UTF-8 strings.
AS_API(AsFbxContext*) AsFbxCreateContext();
// Do not free pErrMsg
AS_API(bool32_t) AsFbxInitializeContext(AsFbxContext* pContext, const char* pFileName, float scaleFactor, int32_t versionIndex, bool32_t isAscii, bool32_t is60Fps, const char** pErrMsg);
AS_API(void) AsFbxDisposeContext(AsFbxContext** ppContext);
AS_API(void) AsFbxSetFramePaths(AsFbxContext* pContext, const char* ppPaths[], int32_t count);
AS_API(void) AsFbxExportScene(AsFbxContext* pContext);
AS_API(fbxsdk::FbxNode*) AsFbxGetSceneRootNode(AsFbxContext* pContext);
AS_API(fbxsdk::FbxNode*) AsFbxExportSingleFrame(AsFbxContext* pContext, fbxsdk::FbxNode* pParentNode, const char* pFramePath, const char* pFrameName, float localPositionX, float localPositionY, float localPositionZ, float localRotationX, float localRotationY, float localRotationZ, float localScaleX, float localScaleY, float localScaleZ);
AS_API(void) AsFbxSetJointsNode_CastToBone(AsFbxContext* pContext, fbxsdk::FbxNode* pNode, float boneSize);
AS_API(void) AsFbxSetJointsNode_BoneInPath(AsFbxContext* pContext, fbxsdk::FbxNode* pNode, float boneSize);
AS_API(void) AsFbxSetJointsNode_Generic(AsFbxContext* pContext, fbxsdk::FbxNode* pNode);
AS_API(void) AsFbxPrepareMaterials(AsFbxContext* pContext, int32_t materialCount, int32_t textureCount);
AS_API(fbxsdk::FbxFileTexture*) AsFbxCreateTexture(AsFbxContext* pContext, const char* pMatTexName);
AS_API(void) AsFbxLinkTexture(int32_t dest, fbxsdk::FbxFileTexture* pTexture, fbxsdk::FbxSurfacePhong* pMaterial, float offsetX, float offsetY, float scaleX, float scaleY);
AS_API(fbxsdk::FbxArray<fbxsdk::FbxCluster*>*) AsFbxMeshCreateClusterArray(int32_t boneCount);
AS_API(void) AsFbxMeshDisposeClusterArray(fbxsdk::FbxArray<fbxsdk::FbxCluster*>** ppArray);
AS_API(fbxsdk::FbxCluster*) AsFbxMeshCreateCluster(AsFbxContext* pContext, fbxsdk::FbxNode* pBoneNode);
AS_API(void) AsFbxMeshAddCluster(fbxsdk::FbxArray<fbxsdk::FbxCluster*>* pArray, /* CanBeNull */ fbxsdk::FbxCluster* pCluster);
AS_API(fbxsdk::FbxMesh*) AsFbxMeshCreateMesh(AsFbxContext* pContext, fbxsdk::FbxNode* pFrameNode);
AS_API(void) AsFbxMeshInitControlPoints(fbxsdk::FbxMesh* pMesh, int32_t vertexCount);
AS_API(void) AsFbxMeshCreateElementNormal(fbxsdk::FbxMesh* pMesh);
AS_API(void) AsFbxMeshCreateElementUV(fbxsdk::FbxMesh* pMesh, int32_t uv);
AS_API(void) AsFbxMeshCreateElementTangent(fbxsdk::FbxMesh* pMesh);
AS_API(void) AsFbxMeshCreateElementVertexColor(fbxsdk::FbxMesh* pMesh);
AS_API(void) AsFbxMeshCreateElementMaterial(fbxsdk::FbxMesh* pMesh);
AS_API(fbxsdk::FbxSurfacePhong*) AsFbxCreateMaterial(AsFbxContext* pContext, const char* pMatName,
float diffuseR, float diffuseG, float diffuseB,
float ambientR, float ambientG, float ambientB,
float emissiveR, float emissiveG, float emissiveB,
float specularR, float specularG, float specularB,
float reflectR, float reflectG, float reflectB,
float shininess, float transparency);
AS_API(int32_t) AsFbxAddMaterialToFrame(fbxsdk::FbxNode* pFrameNode, fbxsdk::FbxSurfacePhong* pMaterial);
AS_API(void) AsFbxSetFrameShadingModeToTextureShading(fbxsdk::FbxNode* pFrameNode);
AS_API(void) AsFbxMeshSetControlPoint(fbxsdk::FbxMesh* pMesh, int32_t index, float x, float y, float z);
AS_API(void) AsFbxMeshAddPolygon(fbxsdk::FbxMesh* pMesh, int32_t materialIndex, int32_t index0, int32_t index1, int32_t index2);
AS_API(void) AsFbxMeshElementNormalAdd(fbxsdk::FbxMesh* pMesh, int32_t elementIndex, float x, float y, float z);
AS_API(void) AsFbxMeshElementUVAdd(fbxsdk::FbxMesh* pMesh, int32_t elementIndex, float u, float v);
AS_API(void) AsFbxMeshElementTangentAdd(fbxsdk::FbxMesh* pMesh, int32_t elementIndex, float x, float y, float z, float w);
AS_API(void) AsFbxMeshElementVertexColorAdd(fbxsdk::FbxMesh* pMesh, int32_t elementIndex, float r, float g, float b, float a);
AS_API(void) AsFbxMeshSetBoneWeight(fbxsdk::FbxArray<fbxsdk::FbxCluster*>* pClusterArray, int32_t boneIndex, int32_t vertexIndex, float weight);
AS_API(AsFbxSkinContext*) AsFbxMeshCreateSkinContext(AsFbxContext* pContext, fbxsdk::FbxNode* pFrameNode);
AS_API(void) AsFbxMeshDisposeSkinContext(AsFbxSkinContext** ppSkinContext);
AS_API(bool32_t) FbxClusterArray_HasItemAt(fbxsdk::FbxArray<fbxsdk::FbxCluster*>* pClusterArray, int32_t index);
AS_API(void) AsFbxMeshSkinAddCluster(AsFbxSkinContext* pSkinContext, fbxsdk::FbxArray<fbxsdk::FbxCluster*>* pClusterArray, int32_t index, float pBoneMatrix[16]);
AS_API(void) AsFbxMeshAddDeformer(AsFbxSkinContext* pSkinContext, fbxsdk::FbxMesh* pMesh);
AS_API(AsFbxAnimContext*) AsFbxAnimCreateContext(bool32_t eulerFilter);
AS_API(void) AsFbxAnimDisposeContext(AsFbxAnimContext** ppAnimContext);
AS_API(void) AsFbxAnimPrepareStackAndLayer(AsFbxContext* pContext, AsFbxAnimContext* pAnimContext, const char* pTakeName);
AS_API(void) AsFbxAnimLoadCurves(fbxsdk::FbxNode* pNode, AsFbxAnimContext* pAnimContext);
AS_API(void) AsFbxAnimBeginKeyModify(AsFbxAnimContext* pAnimContext);
AS_API(void) AsFbxAnimEndKeyModify(AsFbxAnimContext* pAnimContext);
AS_API(void) AsFbxAnimAddScalingKey(AsFbxAnimContext* pAnimContext, float time, float x, float y, float z);
AS_API(void) AsFbxAnimAddRotationKey(AsFbxAnimContext* pAnimContext, float time, float x, float y, float z);
AS_API(void) AsFbxAnimAddTranslationKey(AsFbxAnimContext* pAnimContext, float time, float x, float y, float z);
AS_API(void) AsFbxAnimApplyEulerFilter(AsFbxAnimContext* pAnimContext, float filterPrecision);
AS_API(int32_t) AsFbxAnimGetCurrentBlendShapeChannelCount(AsFbxAnimContext* pAnimContext, fbxsdk::FbxNode* pNode);
AS_API(bool32_t) AsFbxAnimIsBlendShapeChannelMatch(AsFbxAnimContext* pAnimContext, int32_t channelIndex, const char* channelName);
AS_API(void) AsFbxAnimBeginBlendShapeAnimCurve(AsFbxAnimContext* pAnimContext, int32_t channelIndex);
AS_API(void) AsFbxAnimEndBlendShapeAnimCurve(AsFbxAnimContext* pAnimContext);
AS_API(void) AsFbxAnimAddBlendShapeKeyframe(AsFbxAnimContext* pAnimContext, float time, float value);
AS_API(AsFbxMorphContext*) AsFbxMorphCreateContext();
AS_API(void) AsFbxMorphInitializeContext(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, fbxsdk::FbxNode* pNode);
AS_API(void) AsFbxMorphDisposeContext(AsFbxMorphContext** ppMorphContext);
AS_API(void) AsFbxMorphAddBlendShapeChannel(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, const char* channelName);
AS_API(void) AsFbxMorphAddBlendShapeChannelShape(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, float weight);
AS_API(void) AsFbxMorphCopyBlendShapeControlPoints(AsFbxMorphContext* pMorphContext);
AS_API(void) AsFbxMorphSetBlendShapeVertex(AsFbxMorphContext* pMorphContext, uint32_t index, float x, float y, float z);

View File

@ -0,0 +1,27 @@
#include "asfbx_anim_context.h"
AsFbxAnimContext::AsFbxAnimContext(bool32_t eulerFilter)
: lFilter(nullptr)
{
if (eulerFilter)
{
lFilter = new FbxAnimCurveFilterUnroll();
}
lAnimStack = nullptr;
lAnimLayer = nullptr;
lCurveSX = nullptr;
lCurveSY = nullptr;
lCurveSZ = nullptr;
lCurveRX = nullptr;
lCurveRY = nullptr;
lCurveRZ = nullptr;
lCurveTX = nullptr;
lCurveTY = nullptr;
lCurveTZ = nullptr;
lGeometry = nullptr;
lBlendShape = nullptr;
lAnimCurve = nullptr;
}

View File

@ -0,0 +1,32 @@
#pragma once
#include <fbxsdk.h>
#include "bool32_t.h"
struct AsFbxAnimContext
{
FbxAnimCurveFilterUnroll* lFilter;
FbxAnimStack* lAnimStack;
FbxAnimLayer* lAnimLayer;
FbxAnimCurve* lCurveSX;
FbxAnimCurve* lCurveSY;
FbxAnimCurve* lCurveSZ;
FbxAnimCurve* lCurveRX;
FbxAnimCurve* lCurveRY;
FbxAnimCurve* lCurveRZ;
FbxAnimCurve* lCurveTX;
FbxAnimCurve* lCurveTY;
FbxAnimCurve* lCurveTZ;
FbxGeometry* lGeometry;
FbxBlendShape* lBlendShape;
FbxAnimCurve* lAnimCurve;
AsFbxAnimContext(bool32_t eulerFilter);
~AsFbxAnimContext() = default;
};

View File

@ -0,0 +1,33 @@
#include <fbxsdk.h>
#include "asfbx_context.h"
AsFbxContext::AsFbxContext()
{
pSdkManager = nullptr;
pScene = nullptr;
pTextures = nullptr;
pMaterials = nullptr;
pExporter = nullptr;
pBindPose = nullptr;
}
AsFbxContext::~AsFbxContext()
{
framePaths.clear();
delete pMaterials;
delete pTextures;
if (pExporter != nullptr) {
pExporter->Destroy();
}
if (pScene != nullptr) {
pScene->Destroy();
}
if (pSdkManager != nullptr) {
pSdkManager->Destroy();
}
}

View File

@ -0,0 +1,33 @@
#pragma once
#include <cstdint>
#include <string>
#include <unordered_set>
namespace fbxsdk
{
class FbxManager;
class FbxScene;
class FbxExporter;
template<typename T, const int Alignment = 16>
class FbxArray;
class FbxFileTexture;
class FbxSurfacePhong;
class FbxPose;
}
struct AsFbxContext
{
fbxsdk::FbxManager* pSdkManager;
fbxsdk::FbxScene* pScene;
fbxsdk::FbxArray<fbxsdk::FbxFileTexture*>* pTextures;
fbxsdk::FbxArray<fbxsdk::FbxSurfacePhong*>* pMaterials;
fbxsdk::FbxExporter* pExporter;
fbxsdk::FbxPose* pBindPose;
std::unordered_set<std::string> framePaths;
AsFbxContext();
~AsFbxContext();
};

View File

@ -0,0 +1,9 @@
#include "asfbx_morph_context.h"
AsFbxMorphContext::AsFbxMorphContext()
{
pMesh = nullptr;
lBlendShape = nullptr;
lBlendShapeChannel = nullptr;
lShape = nullptr;
}

View File

@ -0,0 +1,16 @@
#pragma once
#include <fbxsdk.h>
struct AsFbxMorphContext
{
FbxMesh* pMesh;
FbxBlendShape* lBlendShape;
FbxBlendShapeChannel* lBlendShapeChannel;
FbxShape* lShape;
AsFbxMorphContext();
~AsFbxMorphContext() = default;
};

View File

@ -0,0 +1,16 @@
#include "asfbx_skin_context.h"
#include "asfbx_context.h"
AsFbxSkinContext::AsFbxSkinContext(AsFbxContext* pContext, FbxNode* pFrameNode)
: pSkin(nullptr)
{
if (pContext != nullptr && pContext->pScene != nullptr)
{
pSkin = FbxSkin::Create(pContext->pScene, "");
}
if (pFrameNode != nullptr)
{
lMeshMatrix = pFrameNode->EvaluateGlobalTransform();
}
}

View File

@ -0,0 +1,16 @@
#pragma once
#include <fbxsdk.h>
struct AsFbxContext;
struct AsFbxSkinContext
{
FbxSkin* pSkin;
FbxAMatrix lMeshMatrix;
AsFbxSkinContext(AsFbxContext* pContext, FbxNode* pFrameNode);
~AsFbxSkinContext() = default;
};

View File

@ -0,0 +1,5 @@
#pragma once
#include <cstdint>
typedef uint32_t bool32_t;

View File

@ -0,0 +1 @@
#define AS_API(ret_type)

View File

@ -0,0 +1,56 @@
#pragma once
#if defined(_MSC_VER)
#if _MSC_VER < 1910 // MSVC 2017-
#error MSVC 2017 or later is required.
#endif
#endif
#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW__)
#ifdef _AS_DLL
#ifdef __GNUC__
#define _AS_EXPORT __attribute__ ((dllexport))
#else
#define _AS_EXPORT __declspec(dllexport)
#endif
#else
#ifdef __GNUC__
#define _AS_EXPORT __attribute__ ((dllimport))
#else
#define _AS_EXPORT __declspec(dllimport)
#endif
#endif
#define _AS_LOCAL
#else
#if __GNUC__ >= 4
#define _AS_EXPORT __attribute__ ((visibility ("default")))
#define _AS_LOCAL __attribute__ ((visibility ("hidden")))
#else
#define _AS_EXPORT
#define _AS_LOCAL
#endif
#endif
#ifdef __cplusplus
#ifndef _EXTERN_C_STMT
#define _EXTERN_C_STMT extern "C"
#endif
#else
#ifndef _EXTERN_C_STMT
#define _EXTERN_C_STMT
#endif
#endif
#ifndef _AS_CALL
#if defined(WIN32) || defined(_WIN32)
#define _AS_CALL __stdcall
#else
#define _AS_CALL /* __cdecl */
#endif
#endif
#if defined(_MSC_VER)
#define AS_API(ret_type) _EXTERN_C_STMT _AS_EXPORT ret_type _AS_CALL
#else
#define AS_API(ret_type) _EXTERN_C_STMT _AS_EXPORT _AS_CALL ret_type
#endif

View File

@ -0,0 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by AssetStudioFBXNative.rc
// 新对象的下一组默认值
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -0,0 +1,43 @@
#include <fbxsdk.h>
#include <cassert>
#include "utils.h"
Vector3::Vector3()
: X(0), Y(0), Z(0)
{
}
Vector3::Vector3(float x, float y, float z)
: X(x), Y(y), Z(z)
{
}
Quaternion::Quaternion()
: X(0), Y(0), Z(0), W(1)
{
}
Quaternion::Quaternion(float x, float y, float z)
: X(x), Y(y), Z(z), W(1)
{
}
Quaternion::Quaternion(float x, float y, float z, float w)
: X(x), Y(y), Z(z), W(w)
{
}
Vector3 QuaternionToEuler(Quaternion q) {
FbxAMatrix lMatrixRot;
lMatrixRot.SetQ(FbxQuaternion(q.X, q.Y, q.Z, q.W));
FbxVector4 lEuler = lMatrixRot.GetR();
return Vector3((float)lEuler[0], (float)lEuler[1], (float)lEuler[2]);
}
Quaternion EulerToQuaternion(Vector3 v) {
FbxAMatrix lMatrixRot;
lMatrixRot.SetR(FbxVector4(v.X, v.Y, v.Z));
FbxQuaternion lQuaternion = lMatrixRot.GetQ();
return Quaternion((float)lQuaternion[0], (float)lQuaternion[1], (float)lQuaternion[2], (float)lQuaternion[3]);
}

View File

@ -0,0 +1,29 @@
#pragma once
struct Vector3 {
float X;
float Y;
float Z;
Vector3();
Vector3(float x, float y, float z);
};
struct Quaternion {
float X;
float Y;
float Z;
float W;
Quaternion();
Quaternion(float x, float y, float z);
Quaternion(float x, float y, float z, float w);
};
Vector3 QuaternionToEuler(Quaternion q);
Quaternion EulerToQuaternion(Vector3 v);

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{BD76E63F-1517-47FA-8233-33E853A3ACEE}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AssetStudio.FbxInterop</RootNamespace>
<AssemblyName>AssetStudioFBXWrapper</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup>
<Compile Include="Fbx.PInvoke.cs" />
<Compile Include="FbxDll.cs" />
<Compile Include="FbxExporterContext.cs" />
<Compile Include="FbxExporterContext.PInvoke.cs" />
<Compile Include="Fbx.cs" />
<Compile Include="FbxExporter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj">
<Project>{40c796b5-88ce-4adc-acd6-2f4862b7f136}</Project>
<Name>AssetStudio.PInvoke</Name>
</ProjectReference>
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj">
<Project>{7662f8c2-7bfd-442e-a948-a43b4f7eb06e}</Project>
<Name>AssetStudio</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,16 @@
using System.Runtime.InteropServices;
using AssetStudio.FbxInterop;
namespace AssetStudio
{
partial class Fbx
{
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsUtilQuaternionToEuler(float qx, float qy, float qz, float qw, out float vx, out float vy, out float vz);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsUtilEulerToQuaternion(float vx, float vy, float vz, out float qx, out float qy, out float qz, out float qw);
}
}

View File

@ -0,0 +1,58 @@
using AssetStudio.FbxInterop;
using AssetStudio.PInvoke;
using System.IO;
namespace AssetStudio
{
public static partial class Fbx
{
static Fbx()
{
DllLoader.PreloadDll(FbxDll.DllName);
}
public static Vector3 QuaternionToEuler(Quaternion q)
{
AsUtilQuaternionToEuler(q.X, q.Y, q.Z, q.W, out var x, out var y, out var z);
return new Vector3(x, y, z);
}
public static Quaternion EulerToQuaternion(Vector3 v)
{
AsUtilEulerToQuaternion(v.X, v.Y, v.Z, out var x, out var y, out var z, out var w);
return new Quaternion(x, y, z, w);
}
public static class Exporter
{
public static void Export(string path, IImported imported, bool eulerFilter, float filterPrecision,
bool allNodes, bool skins, bool animation, bool blendShape, bool castToBone, float boneSize, float scaleFactor, int versionIndex, bool isAscii)
{
var file = new FileInfo(path);
var dir = file.Directory;
if (!dir.Exists)
{
dir.Create();
}
var currentDir = Directory.GetCurrentDirectory();
Directory.SetCurrentDirectory(dir.FullName);
var name = Path.GetFileName(path);
using (var exporter = new FbxExporter(name, imported, allNodes, skins, castToBone, boneSize, scaleFactor, versionIndex, isAscii))
{
exporter.Initialize();
exporter.ExportAll(blendShape, animation, eulerFilter, filterPrecision);
}
Directory.SetCurrentDirectory(currentDir);
}
}
}
}

View File

@ -0,0 +1,10 @@
namespace AssetStudio.FbxInterop
{
internal static class FbxDll
{
internal const string DllName = "AssetStudioFBXNative";
internal const string FbxsdkDllName = "libfbxsdk";
}
}

View File

@ -0,0 +1,242 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace AssetStudio.FbxInterop
{
internal sealed class FbxExporter : IDisposable
{
private FbxExporterContext _context;
private readonly string _fileName;
private readonly IImported _imported;
private readonly bool _allNodes;
private readonly bool _exportSkins;
private readonly bool _castToBone;
private readonly float _boneSize;
private readonly float _scaleFactor;
private readonly int _versionIndex;
private readonly bool _isAscii;
internal FbxExporter(string fileName, IImported imported, bool allNodes, bool exportSkins, bool castToBone, float boneSize, float scaleFactor, int versionIndex, bool isAscii)
{
_context = new FbxExporterContext();
_fileName = fileName;
_imported = imported;
_allNodes = allNodes;
_exportSkins = exportSkins;
_castToBone = castToBone;
_boneSize = boneSize;
_scaleFactor = scaleFactor;
_versionIndex = versionIndex;
_isAscii = isAscii;
}
~FbxExporter()
{
Dispose(false);
}
public void Dispose()
{
if (IsDisposed)
{
return;
}
Dispose(true);
GC.SuppressFinalize(this);
}
public bool IsDisposed { get; private set; }
private void Dispose(bool disposing)
{
if (disposing)
{
_context.Dispose();
}
IsDisposed = true;
}
internal void Initialize()
{
var is60Fps = _imported.AnimationList.Count > 0 && _imported.AnimationList[0].SampleRate.Equals(60.0f);
_context.Initialize(_fileName, _scaleFactor, _versionIndex, _isAscii, is60Fps);
if (!_allNodes)
{
var framePaths = SearchHierarchy();
_context.SetFramePaths(framePaths);
}
}
internal void ExportAll(bool blendShape, bool animation, bool eulerFilter, float filterPrecision)
{
var meshFrames = new List<ImportedFrame>();
ExportRootFrame(meshFrames);
if (_imported.MeshList != null)
{
SetJointsFromImportedMeshes();
PrepareMaterials();
ExportMeshFrames(_imported.RootFrame, meshFrames);
}
else
{
SetJointsNode(_imported.RootFrame, null, true);
}
if (blendShape)
{
ExportMorphs();
}
if (animation)
{
ExportAnimations(eulerFilter, filterPrecision);
}
ExportScene();
}
private void ExportMorphs()
{
_context.ExportMorphs(_imported.RootFrame, _imported.MorphList);
}
private void ExportAnimations(bool eulerFilter, float filterPrecision)
{
_context.ExportAnimations(_imported.RootFrame, _imported.AnimationList, eulerFilter, filterPrecision);
}
private void ExportRootFrame(List<ImportedFrame> meshFrames)
{
_context.ExportFrame(_imported.MeshList, meshFrames, _imported.RootFrame);
}
private void ExportScene()
{
_context.ExportScene();
}
private void SetJointsFromImportedMeshes()
{
if (!_exportSkins)
{
return;
}
Debug.Assert(_imported.MeshList != null);
var bonePaths = new HashSet<string>();
foreach (var mesh in _imported.MeshList)
{
var boneList = mesh.BoneList;
if (boneList != null)
{
foreach (var bone in boneList)
{
bonePaths.Add(bone.Path);
}
}
}
SetJointsNode(_imported.RootFrame, bonePaths, _castToBone);
}
private void SetJointsNode(ImportedFrame rootFrame, HashSet<string> bonePaths, bool castToBone)
{
_context.SetJointsNode(rootFrame, bonePaths, castToBone, _boneSize);
}
private void PrepareMaterials()
{
_context.PrepareMaterials(_imported.MaterialList.Count, _imported.TextureList.Count);
}
private void ExportMeshFrames(ImportedFrame rootFrame, List<ImportedFrame> meshFrames)
{
foreach (var meshFrame in meshFrames)
{
_context.ExportMeshFromFrame(rootFrame, meshFrame, _imported.MeshList, _imported.MaterialList, _imported.TextureList, _exportSkins);
}
}
private HashSet<string> SearchHierarchy()
{
if (_imported.MeshList == null || _imported.MeshList.Count == 0)
{
return null;
}
var exportFrames = new HashSet<string>();
SearchHierarchy(_imported.RootFrame, _imported.MeshList, exportFrames);
return exportFrames;
}
private static void SearchHierarchy(ImportedFrame rootFrame, List<ImportedMesh> meshList, HashSet<string> exportFrames)
{
var frameStack = new Stack<ImportedFrame>();
frameStack.Push(rootFrame);
while (frameStack.Count > 0)
{
var frame = frameStack.Pop();
var meshListSome = ImportedHelpers.FindMesh(frame.Path, meshList);
if (meshListSome != null)
{
var parent = frame;
while (parent != null)
{
exportFrames.Add(parent.Path);
parent = parent.Parent;
}
var boneList = meshListSome.BoneList;
if (boneList != null)
{
foreach (var bone in boneList)
{
if (!exportFrames.Contains(bone.Path))
{
var boneParent = rootFrame.FindFrameByPath(bone.Path);
while (boneParent != null)
{
exportFrames.Add(boneParent.Path);
boneParent = boneParent.Parent;
}
}
}
}
}
for (var i = frame.Count - 1; i >= 0; i -= 1)
{
frameStack.Push(frame[i]);
}
}
}
}
}

View File

@ -0,0 +1,308 @@
using System;
using System.Runtime.InteropServices;
using AssetStudio.PInvoke;
namespace AssetStudio.FbxInterop
{
partial class FbxExporterContext
{
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern IntPtr AsFbxCreateContext();
private static bool AsFbxInitializeContext(IntPtr context, string fileName, float scaleFactor, int versionIndex, bool isAscii, bool is60Fps, out string errorMessage)
{
bool b;
IntPtr pErrMsg;
using (var fileNameUtf8 = new Utf8StringHandle(fileName))
{
b = AsFbxInitializeContext(context, fileNameUtf8.DangerousGetHandle(), scaleFactor, versionIndex, isAscii, is60Fps, out pErrMsg);
}
errorMessage = Utf8StringHandle.ReadUtf8StringFromPointer(pErrMsg);
return b;
}
// Do not free the pointer strErrorMessage
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool AsFbxInitializeContext(IntPtr context, IntPtr strFileName, float scaleFactor, int versionIndex, [MarshalAs(UnmanagedType.Bool)] bool isAscii, [MarshalAs(UnmanagedType.Bool)] bool is60Fps, out IntPtr strErrorMessage);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxDisposeContext(ref IntPtr ppContext);
private static void AsFbxSetFramePaths(IntPtr context, string[] framePaths)
{
var framePathCount = framePaths.Length;
if (framePathCount == 0)
{
AsFbxSetFramePaths(context, Array.Empty<IntPtr>(), 0);
}
else
{
var utf8Paths = new Utf8StringHandle[framePathCount];
try
{
for (var i = 0; i < framePathCount; i += 1)
{
utf8Paths[i] = new Utf8StringHandle(framePaths[i]);
}
var pathPointers = new IntPtr[framePathCount];
for (var i = 0; i < framePathCount; i += 1)
{
pathPointers[i] = utf8Paths[i].DangerousGetHandle();
}
AsFbxSetFramePaths(context, pathPointers, framePathCount);
}
finally
{
foreach (var path in utf8Paths)
{
path?.Dispose();
}
}
}
}
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxSetFramePaths(IntPtr context, [MarshalAs(UnmanagedType.LPArray)] IntPtr[] strFramePaths, int count);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxExportScene(IntPtr context);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern IntPtr AsFbxGetSceneRootNode(IntPtr context);
private static IntPtr AsFbxExportSingleFrame(IntPtr context, IntPtr parentNode, string framePath, string frameName, in Vector3 localPosition, in Vector3 localRotation, in Vector3 localScale)
{
using (var framePathUtf8 = new Utf8StringHandle(framePath))
{
using (var frameNameUtf8 = new Utf8StringHandle(frameName))
{
return AsFbxExportSingleFrame(context, parentNode, framePathUtf8.DangerousGetHandle(), frameNameUtf8.DangerousGetHandle(), localPosition.X, localPosition.Y, localPosition.Z, localRotation.X, localRotation.Y, localRotation.Z, localScale.X, localScale.Y, localScale.Z);
}
}
}
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern IntPtr AsFbxExportSingleFrame(IntPtr context, IntPtr parentNode, IntPtr strFramePath, IntPtr strFrameName, float localPositionX, float localPositionY, float localPositionZ, float localRotationX, float localRotationY, float localRotationZ, float localScaleX, float localScaleY, float localScaleZ);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxSetJointsNode_CastToBone(IntPtr context, IntPtr node, float boneSize);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxSetJointsNode_BoneInPath(IntPtr context, IntPtr node, float boneSize);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxSetJointsNode_Generic(IntPtr context, IntPtr node);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxPrepareMaterials(IntPtr context, int materialCount, int textureCount);
private static IntPtr AsFbxCreateTexture(IntPtr context, string matTexName)
{
using (var matTexNameUtf8 = new Utf8StringHandle(matTexName))
{
return AsFbxCreateTexture(context, matTexNameUtf8.DangerousGetHandle());
}
}
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern IntPtr AsFbxCreateTexture(IntPtr context, IntPtr strMatTexName);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxLinkTexture(int dest, IntPtr texture, IntPtr material, float offsetX, float offsetY, float scaleX, float scaleY);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern IntPtr AsFbxMeshCreateClusterArray(int boneCount);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMeshDisposeClusterArray(ref IntPtr ppArray);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern IntPtr AsFbxMeshCreateCluster(IntPtr context, IntPtr boneNode);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMeshAddCluster(IntPtr array, IntPtr cluster);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern IntPtr AsFbxMeshCreateMesh(IntPtr context, IntPtr frameNode);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMeshInitControlPoints(IntPtr mesh, int vertexCount);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMeshCreateElementNormal(IntPtr mesh);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMeshCreateElementUV(IntPtr mesh, int uv);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMeshCreateElementTangent(IntPtr mesh);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMeshCreateElementVertexColor(IntPtr mesh);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMeshCreateElementMaterial(IntPtr mesh);
private static IntPtr AsFbxCreateMaterial(IntPtr pContext, string matName, in Color diffuse, in Color ambient, in Color emissive, in Color specular, in Color reflection, float shininess, float transparency)
{
using (var matNameUtf8 = new Utf8StringHandle(matName))
{
return AsFbxCreateMaterial(pContext, matNameUtf8.DangerousGetHandle(), diffuse.R, diffuse.G, diffuse.B, ambient.R, ambient.G, ambient.B, emissive.R, emissive.G, emissive.B, specular.R, specular.G, specular.B, reflection.R, reflection.G, reflection.B, shininess, transparency);
}
}
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern IntPtr AsFbxCreateMaterial(IntPtr pContext, IntPtr pMatName,
float diffuseR, float diffuseG, float diffuseB,
float ambientR, float ambientG, float ambientB,
float emissiveR, float emissiveG, float emissiveB,
float specularR, float specularG, float specularB,
float reflectR, float reflectG, float reflectB,
float shininess, float transparency);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern int AsFbxAddMaterialToFrame(IntPtr frameNode, IntPtr material);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxSetFrameShadingModeToTextureShading(IntPtr frameNode);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMeshSetControlPoint(IntPtr mesh, int index, float x, float y, float z);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMeshAddPolygon(IntPtr mesh, int materialIndex, int index0, int index1, int index2);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMeshElementNormalAdd(IntPtr mesh, int elementIndex, float x, float y, float z);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMeshElementUVAdd(IntPtr mesh, int elementIndex, float u, float v);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMeshElementTangentAdd(IntPtr mesh, int elementIndex, float x, float y, float z, float w);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMeshElementVertexColorAdd(IntPtr mesh, int elementIndex, float r, float g, float b, float a);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMeshSetBoneWeight(IntPtr pClusterArray, int boneIndex, int vertexIndex, float weight);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern IntPtr AsFbxMeshCreateSkinContext(IntPtr context, IntPtr frameNode);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMeshDisposeSkinContext(ref IntPtr ppSkinContext);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool FbxClusterArray_HasItemAt(IntPtr pClusterArray, int index);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private unsafe static extern void AsFbxMeshSkinAddCluster(IntPtr pSkinContext, IntPtr pClusterArray, int index, float* pBoneMatrix);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMeshAddDeformer(IntPtr pSkinContext, IntPtr pMesh);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern IntPtr AsFbxAnimCreateContext([MarshalAs(UnmanagedType.Bool)] bool eulerFilter);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxAnimDisposeContext(ref IntPtr ppAnimContext);
private static void AsFbxAnimPrepareStackAndLayer(IntPtr pContext, IntPtr pAnimContext, string takeName)
{
using (var takeNameUtf8 = new Utf8StringHandle(takeName))
{
AsFbxAnimPrepareStackAndLayer(pContext, pAnimContext, takeNameUtf8.DangerousGetHandle());
}
}
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxAnimPrepareStackAndLayer(IntPtr pContext, IntPtr pAnimContext, IntPtr strTakeName);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxAnimLoadCurves(IntPtr pNode, IntPtr pAnimContext);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxAnimBeginKeyModify(IntPtr pAnimContext);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxAnimEndKeyModify(IntPtr pAnimContext);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxAnimAddScalingKey(IntPtr pAnimContext, float time, float x, float y, float z);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxAnimAddRotationKey(IntPtr pAnimContext, float time, float x, float y, float z);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxAnimAddTranslationKey(IntPtr pAnimContext, float time, float x, float y, float z);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxAnimApplyEulerFilter(IntPtr pAnimContext, float filterPrecision);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern int AsFbxAnimGetCurrentBlendShapeChannelCount(IntPtr pAnimContext, IntPtr pNode);
private static bool AsFbxAnimIsBlendShapeChannelMatch(IntPtr pAnimContext, int channelIndex, string channelName)
{
using (var channelNameUtf8 = new Utf8StringHandle(channelName))
{
return AsFbxAnimIsBlendShapeChannelMatch(pAnimContext, channelIndex, channelNameUtf8.DangerousGetHandle());
}
}
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool AsFbxAnimIsBlendShapeChannelMatch(IntPtr pAnimContext, int channelIndex, IntPtr strChannelName);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxAnimBeginBlendShapeAnimCurve(IntPtr pAnimContext, int channelIndex);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxAnimEndBlendShapeAnimCurve(IntPtr pAnimContext);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxAnimAddBlendShapeKeyframe(IntPtr pAnimContext, float time, float value);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern IntPtr AsFbxMorphCreateContext();
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMorphInitializeContext(IntPtr pContext, IntPtr pMorphContext, IntPtr pNode);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMorphDisposeContext(ref IntPtr ppMorphContext);
private static void AsFbxMorphAddBlendShapeChannel(IntPtr pContext, IntPtr pMorphContext, string channelName)
{
using (var channelNameUtf8 = new Utf8StringHandle(channelName))
{
AsFbxMorphAddBlendShapeChannel(pContext, pMorphContext, channelNameUtf8.DangerousGetHandle());
}
}
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMorphAddBlendShapeChannel(IntPtr pContext, IntPtr pMorphContext, IntPtr strChannelName);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMorphAddBlendShapeChannelShape(IntPtr pContext, IntPtr pMorphContext, float weight);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMorphCopyBlendShapeControlPoints(IntPtr pMorphContext);
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void AsFbxMorphSetBlendShapeVertex(IntPtr pMorphContext, uint index, float x, float y, float z);
}
}

View File

@ -0,0 +1,629 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
namespace AssetStudio.FbxInterop
{
internal sealed partial class FbxExporterContext : IDisposable
{
private IntPtr _pContext;
private readonly Dictionary<ImportedFrame, IntPtr> _frameToNode;
private readonly List<KeyValuePair<string, IntPtr>> _createdMaterials;
private readonly Dictionary<string, IntPtr> _createdTextures;
public FbxExporterContext()
{
_pContext = AsFbxCreateContext();
_frameToNode = new Dictionary<ImportedFrame, IntPtr>();
_createdMaterials = new List<KeyValuePair<string, IntPtr>>();
_createdTextures = new Dictionary<string, IntPtr>();
}
~FbxExporterContext()
{
Dispose(false);
}
public void Dispose()
{
if (IsDisposed)
{
return;
}
Dispose(true);
GC.SuppressFinalize(this);
}
public bool IsDisposed { get; private set; }
private void Dispose(bool disposing)
{
IsDisposed = true;
_frameToNode.Clear();
_createdMaterials.Clear();
_createdTextures.Clear();
AsFbxDisposeContext(ref _pContext);
}
private void EnsureNotDisposed()
{
if (IsDisposed)
{
throw new ObjectDisposedException(nameof(FbxExporterContext));
}
}
internal void Initialize(string fileName, float scaleFactor, int versionIndex, bool isAscii, bool is60Fps)
{
EnsureNotDisposed();
var b = AsFbxInitializeContext(_pContext, fileName, scaleFactor, versionIndex, isAscii, is60Fps, out var errorMessage);
if (!b)
{
var fullMessage = $"Failed to initialize FbxExporter: {errorMessage}";
throw new ApplicationException(fullMessage);
}
}
internal void SetFramePaths(HashSet<string> framePaths)
{
EnsureNotDisposed();
if (framePaths == null || framePaths.Count == 0)
{
return;
}
var framePathList = new List<string>(framePaths);
var framePathArray = framePathList.ToArray();
AsFbxSetFramePaths(_pContext, framePathArray);
}
internal void ExportScene()
{
EnsureNotDisposed();
AsFbxExportScene(_pContext);
}
internal void ExportFrame(List<ImportedMesh> meshList, List<ImportedFrame> meshFrames, ImportedFrame rootFrame)
{
var rootNode = AsFbxGetSceneRootNode(_pContext);
Debug.Assert(rootNode != IntPtr.Zero);
var nodeStack = new Stack<IntPtr>();
var frameStack = new Stack<ImportedFrame>();
nodeStack.Push(rootNode);
frameStack.Push(rootFrame);
while (nodeStack.Count > 0)
{
var parentNode = nodeStack.Pop();
var frame = frameStack.Pop();
var childNode = AsFbxExportSingleFrame(_pContext, parentNode, frame.Path, frame.Name, frame.LocalPosition, frame.LocalRotation, frame.LocalScale);
if (meshList != null && ImportedHelpers.FindMesh(frame.Path, meshList) != null)
{
meshFrames.Add(frame);
}
_frameToNode.Add(frame, childNode);
for (var i = frame.Count - 1; i >= 0; i -= 1)
{
nodeStack.Push(childNode);
frameStack.Push(frame[i]);
}
}
}
internal void SetJointsNode(ImportedFrame rootFrame, HashSet<string> bonePaths, bool castToBone, float boneSize)
{
var frameStack = new Stack<ImportedFrame>();
frameStack.Push(rootFrame);
while (frameStack.Count > 0)
{
var frame = frameStack.Pop();
if (_frameToNode.TryGetValue(frame, out var node))
{
Debug.Assert(node != IntPtr.Zero);
if (castToBone)
{
AsFbxSetJointsNode_CastToBone(_pContext, node, boneSize);
}
else
{
Debug.Assert(bonePaths != null);
if (bonePaths.Contains(frame.Path))
{
AsFbxSetJointsNode_BoneInPath(_pContext, node, boneSize);
}
else
{
AsFbxSetJointsNode_Generic(_pContext, node);
}
}
}
for (var i = frame.Count - 1; i >= 0; i -= 1)
{
frameStack.Push(frame[i]);
}
}
}
internal void PrepareMaterials(int materialCount, int textureCount)
{
AsFbxPrepareMaterials(_pContext, materialCount, textureCount);
}
internal void ExportMeshFromFrame(ImportedFrame rootFrame, ImportedFrame meshFrame, List<ImportedMesh> meshList, List<ImportedMaterial> materialList, List<ImportedTexture> textureList, bool exportSkins)
{
var meshNode = _frameToNode[meshFrame];
var mesh = ImportedHelpers.FindMesh(meshFrame.Path, meshList);
ExportMesh(rootFrame, materialList, textureList, meshNode, mesh, exportSkins);
}
private IntPtr ExportTexture(ImportedTexture texture)
{
if (texture == null)
{
return IntPtr.Zero;
}
if (_createdTextures.ContainsKey(texture.Name))
{
return _createdTextures[texture.Name];
}
var pTex = AsFbxCreateTexture(_pContext, texture.Name);
_createdTextures.Add(texture.Name, pTex);
var file = new FileInfo(texture.Name);
using (var writer = new BinaryWriter(file.Create()))
{
writer.Write(texture.Data);
}
return pTex;
}
private void ExportMesh(ImportedFrame rootFrame, List<ImportedMaterial> materialList, List<ImportedTexture> textureList, IntPtr frameNode, ImportedMesh importedMesh, bool exportSkins)
{
var boneList = importedMesh.BoneList;
var totalBoneCount = boneList.Count;
var hasBones = exportSkins && boneList != null && totalBoneCount > 0;
var pClusterArray = IntPtr.Zero;
try
{
if (hasBones)
{
pClusterArray = AsFbxMeshCreateClusterArray(totalBoneCount);
foreach (var bone in boneList)
{
if (bone.Path != null)
{
var frame = rootFrame.FindFrameByPath(bone.Path);
var boneNode = _frameToNode[frame];
var cluster = AsFbxMeshCreateCluster(_pContext, boneNode);
AsFbxMeshAddCluster(pClusterArray, cluster);
}
else
{
AsFbxMeshAddCluster(pClusterArray, IntPtr.Zero);
}
}
}
var mesh = AsFbxMeshCreateMesh(_pContext, frameNode);
var totalVertexCount = 0;
foreach (var m in importedMesh.SubmeshList)
{
totalVertexCount += m.VertexList.Count;
}
AsFbxMeshInitControlPoints(mesh, totalVertexCount);
if (importedMesh.hasNormal)
{
AsFbxMeshCreateElementNormal(mesh);
}
for (var i = 0; i < 2; i += 1)
{
if (importedMesh.hasUV[i])
{
AsFbxMeshCreateElementUV(mesh, i);
}
}
if (importedMesh.hasTangent)
{
AsFbxMeshCreateElementTangent(mesh);
}
if (importedMesh.hasColor)
{
AsFbxMeshCreateElementVertexColor(mesh);
}
AsFbxMeshCreateElementMaterial(mesh);
var firstVertex = 0;
foreach (var meshObj in importedMesh.SubmeshList)
{
var materialIndex = 0;
var mat = ImportedHelpers.FindMaterial(meshObj.Material, materialList);
if (mat != null)
{
var foundMat = _createdMaterials.FindIndex(kv => kv.Key == mat.Name);
IntPtr pMat;
if (foundMat >= 0)
{
pMat = _createdMaterials[foundMat].Value;
}
else
{
var diffuse = mat.Diffuse;
var ambient = mat.Ambient;
var emissive = mat.Emissive;
var specular = mat.Specular;
var reflection = mat.Reflection;
pMat = AsFbxCreateMaterial(_pContext, mat.Name, in diffuse, in ambient, in emissive, in specular, in reflection, mat.Shininess, mat.Transparency);
_createdMaterials.Add(new KeyValuePair<string, IntPtr>(mat.Name, pMat));
}
materialIndex = AsFbxAddMaterialToFrame(frameNode, pMat);
var hasTexture = false;
foreach (var texture in mat.Textures)
{
var tex = ImportedHelpers.FindTexture(texture.Name, textureList);
var pTexture = ExportTexture(tex);
if (pTexture != IntPtr.Zero)
{
switch (texture.Dest)
{
case 0:
case 1:
case 2:
case 3:
{
AsFbxLinkTexture(texture.Dest, pTexture, pMat, texture.Offset.X, texture.Offset.Y, texture.Scale.X, texture.Scale.Y);
hasTexture = true;
break;
}
default:
break;
}
}
}
if (hasTexture)
{
AsFbxSetFrameShadingModeToTextureShading(frameNode);
}
}
var vertexList = meshObj.VertexList;
var vertexCount = vertexList.Count;
for (var j = 0; j < vertexCount; j += 1)
{
var importedVertex = vertexList[j];
var vertex = importedVertex.Vertex;
AsFbxMeshSetControlPoint(mesh, j + firstVertex, vertex.X, vertex.Y, vertex.Z);
if (importedMesh.hasNormal)
{
var normal = importedVertex.Normal;
AsFbxMeshElementNormalAdd(mesh, 0, normal.X, normal.Y, normal.Z);
}
for (var uvIndex = 0; uvIndex < 2; uvIndex += 1)
{
if (importedMesh.hasUV[uvIndex])
{
var uv = importedVertex.UV[uvIndex];
AsFbxMeshElementUVAdd(mesh, uvIndex, uv[0], uv[1]);
}
}
if (importedMesh.hasTangent)
{
var tangent = importedVertex.Tangent;
AsFbxMeshElementTangentAdd(mesh, 0, tangent.X, tangent.Y, tangent.Z, tangent.W);
}
if (importedMesh.hasColor)
{
var color = importedVertex.Color;
AsFbxMeshElementVertexColorAdd(mesh, 0, color.R, color.G, color.B, color.A);
}
if (hasBones && importedVertex.BoneIndices != null)
{
var boneIndices = importedVertex.BoneIndices;
var boneWeights = importedVertex.Weights;
for (var k = 0; k < 4; k += 1)
{
if (boneIndices[k] < totalBoneCount && boneWeights[k] > 0)
{
AsFbxMeshSetBoneWeight(pClusterArray, boneIndices[k], j + firstVertex, boneWeights[k]);
}
}
}
}
foreach (var face in meshObj.FaceList)
{
var index0 = face.VertexIndices[0] + firstVertex;
var index1 = face.VertexIndices[1] + firstVertex;
var index2 = face.VertexIndices[2] + firstVertex;
AsFbxMeshAddPolygon(mesh, materialIndex, index0, index1, index2);
}
firstVertex += vertexCount;
}
if (hasBones)
{
IntPtr pSkinContext = IntPtr.Zero;
try
{
pSkinContext = AsFbxMeshCreateSkinContext(_pContext, frameNode);
unsafe
{
var boneMatrix = stackalloc float[16];
for (var j = 0; j < totalBoneCount; j += 1)
{
if (!FbxClusterArray_HasItemAt(pClusterArray, j))
{
continue;
}
var m = boneList[j].Matrix;
CopyMatrix4x4(in m, boneMatrix);
AsFbxMeshSkinAddCluster(pSkinContext, pClusterArray, j, boneMatrix);
}
}
AsFbxMeshAddDeformer(pSkinContext, mesh);
}
finally
{
AsFbxMeshDisposeSkinContext(ref pSkinContext);
}
}
}
finally
{
AsFbxMeshDisposeClusterArray(ref pClusterArray);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe void CopyMatrix4x4(in Matrix4x4 matrix, float* buffer)
{
for (var m = 0; m < 4; m += 1)
{
for (var n = 0; n < 4; n += 1)
{
var index = IndexFrom4x4(m, n);
buffer[index] = matrix[m, n];
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int IndexFrom4x4(int m, int n)
{
return 4 * m + n;
}
internal void ExportAnimations(ImportedFrame rootFrame, List<ImportedKeyframedAnimation> animationList, bool eulerFilter, float filterPrecision)
{
if (animationList == null || animationList.Count == 0)
{
return;
}
var pAnimContext = IntPtr.Zero;
try
{
pAnimContext = AsFbxAnimCreateContext(eulerFilter);
for (int i = 0; i < animationList.Count; i++)
{
var importedAnimation = animationList[i];
string takeName;
if (importedAnimation.Name != null)
{
takeName = importedAnimation.Name;
}
else
{
takeName = $"Take{i.ToString()}";
}
AsFbxAnimPrepareStackAndLayer(_pContext, pAnimContext, takeName);
ExportKeyframedAnimation(rootFrame, importedAnimation, pAnimContext, filterPrecision);
}
}
finally
{
AsFbxAnimDisposeContext(ref pAnimContext);
}
}
private void ExportKeyframedAnimation(ImportedFrame rootFrame, ImportedKeyframedAnimation parser, IntPtr pAnimContext, float filterPrecision)
{
foreach (var track in parser.TrackList)
{
if (track.Path == null)
{
continue;
}
var frame = rootFrame.FindFrameByPath(track.Path);
if (frame == null)
{
continue;
}
var pNode = _frameToNode[frame];
AsFbxAnimLoadCurves(pNode, pAnimContext);
AsFbxAnimBeginKeyModify(pAnimContext);
foreach (var scaling in track.Scalings)
{
var value = scaling.value;
AsFbxAnimAddScalingKey(pAnimContext, scaling.time, value.X, value.Y, value.Z);
}
foreach (var rotation in track.Rotations)
{
var value = rotation.value;
AsFbxAnimAddRotationKey(pAnimContext, rotation.time, value.X, value.Y, value.Z);
}
foreach (var translation in track.Translations)
{
var value = translation.value;
AsFbxAnimAddTranslationKey(pAnimContext, translation.time, value.X, value.Y, value.Z);
}
AsFbxAnimEndKeyModify(pAnimContext);
AsFbxAnimApplyEulerFilter(pAnimContext, filterPrecision);
var blendShape = track.BlendShape;
if (blendShape != null)
{
var channelCount = AsFbxAnimGetCurrentBlendShapeChannelCount(pAnimContext, pNode);
if (channelCount > 0)
{
for (var channelIndex = 0; channelIndex < channelCount; channelIndex += 1)
{
if (!AsFbxAnimIsBlendShapeChannelMatch(pAnimContext, channelIndex, blendShape.ChannelName))
{
continue;
}
AsFbxAnimBeginBlendShapeAnimCurve(pAnimContext, channelIndex);
foreach (var keyframe in blendShape.Keyframes)
{
AsFbxAnimAddBlendShapeKeyframe(pAnimContext, keyframe.time, keyframe.value);
}
AsFbxAnimEndBlendShapeAnimCurve(pAnimContext);
}
}
}
}
}
internal void ExportMorphs(ImportedFrame rootFrame, List<ImportedMorph> morphList)
{
if (morphList == null || morphList.Count == 0)
{
return;
}
foreach (var morph in morphList)
{
var frame = rootFrame.FindFrameByPath(morph.Path);
if (frame == null)
{
continue;
}
var pNode = _frameToNode[frame];
var pMorphContext = IntPtr.Zero;
try
{
pMorphContext = AsFbxMorphCreateContext();
AsFbxMorphInitializeContext(_pContext, pMorphContext, pNode);
foreach (var channel in morph.Channels)
{
AsFbxMorphAddBlendShapeChannel(_pContext, pMorphContext, channel.Name);
foreach (var keyframe in channel.KeyframeList)
{
AsFbxMorphAddBlendShapeChannelShape(_pContext, pMorphContext, keyframe.Weight);
AsFbxMorphCopyBlendShapeControlPoints(pMorphContext);
foreach (var vertex in keyframe.VertexList)
{
var v = vertex.Vertex.Vertex;
AsFbxMorphSetBlendShapeVertex(pMorphContext, vertex.Index, v.X, v.Y, v.Z);
}
}
}
}
finally
{
AsFbxMorphDisposeContext(ref pMorphContext);
}
}
}
}
}

View File

@ -0,0 +1,19 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("AssetStudioFBXWrapper")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AssetStudioFBXWrapper")]
[assembly: AssemblyCopyright("Copyright © Perfare 2018-2020; Copyright © hozuki 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("bd76e63f-1517-47fa-8233-33e853a3acee")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -13,53 +13,31 @@
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="OpenTK, Version=3.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<HintPath>..\packages\OpenTK.3.1.0\lib\net20\OpenTK.dll</HintPath>
@ -144,24 +122,22 @@
<ItemGroup>
<None Include="Resources\as.ico" />
</ItemGroup>
<ItemGroup Condition="'$(Platform)' == 'x86'">
<ItemGroup>
<ContentWithTargetPath Include="Libraries\x86\fmod.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>fmod.dll</TargetPath>
<TargetPath>x86\fmod.dll</TargetPath>
</ContentWithTargetPath>
<ContentWithTargetPath Include="Libraries\x86\libfbxsdk.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>libfbxsdk.dll</TargetPath>
<TargetPath>x86\libfbxsdk.dll</TargetPath>
</ContentWithTargetPath>
</ItemGroup>
<ItemGroup Condition="'$(Platform)' == 'x64'">
<ContentWithTargetPath Include="Libraries\x64\fmod.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>fmod.dll</TargetPath>
<TargetPath>x64\fmod.dll</TargetPath>
</ContentWithTargetPath>
<ContentWithTargetPath Include="Libraries\x64\libfbxsdk.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>libfbxsdk.dll</TargetPath>
<TargetPath>x64\libfbxsdk.dll</TargetPath>
</ContentWithTargetPath>
</ItemGroup>
<ItemGroup>

View File

@ -13,42 +13,22 @@
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<PlatformTarget>AnyCPU</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<PlatformTarget>AnyCPU</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
@ -82,17 +62,21 @@
<Compile Include="Texture2DExtensions.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AssetStudioFBX\AssetStudioFBX.vcxproj">
<Project>{b82dd1ba-4eec-4f29-a686-03d7f0df39b8}</Project>
<Name>AssetStudioFBX</Name>
<ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj">
<Project>{40c796b5-88ce-4adc-acd6-2f4862b7f136}</Project>
<Name>AssetStudio.PInvoke</Name>
</ProjectReference>
<ProjectReference Include="..\AssetStudioFBXWrapper\AssetStudioFBXWrapper.csproj">
<Project>{bd76e63f-1517-47fa-8233-33e853a3acee}</Project>
<Name>AssetStudioFBXWrapper</Name>
</ProjectReference>
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj">
<Project>{7662f8c2-7bfd-442e-a948-a43b4f7eb06e}</Project>
<Name>AssetStudio</Name>
</ProjectReference>
<ProjectReference Include="..\Texture2DDecoder\Texture2DDecoder.vcxproj">
<Project>{bec7b5e6-0a7b-4824-97a7-eea04d9eba29}</Project>
<Name>Texture2DDecoder</Name>
<ProjectReference Include="..\Texture2DDecoderWrapper\Texture2DDecoderWrapper.csproj">
<Project>{2afce830-b463-49b3-a026-877e5eafc0a4}</Project>
<Name>Texture2DDecoderWrapper</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View File

@ -7,6 +7,7 @@
using System;
using System.Text;
using System.Runtime.InteropServices;
using AssetStudio.PInvoke;
namespace FMOD
{
@ -1587,6 +1588,12 @@ namespace FMOD
*/
public class Factory
{
static Factory()
{
DllLoader.PreloadDll(VERSION.dll);
}
public static RESULT System_Create(out System system)
{
system = null;

View File

@ -1,20 +0,0 @@
using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;
[assembly:AssemblyTitleAttribute(L"Texture2DDecoder")];
[assembly:AssemblyDescriptionAttribute(L"")];
[assembly:AssemblyConfigurationAttribute(L"")];
[assembly:AssemblyCompanyAttribute(L"")];
[assembly:AssemblyProductAttribute(L"Texture2DDecoder")];
[assembly:AssemblyCopyrightAttribute(L"Copyright © Perfare 2020")];
[assembly:AssemblyTrademarkAttribute(L"")];
[assembly:AssemblyCultureAttribute(L"")];
[assembly:AssemblyVersionAttribute("1.0.*")];
[assembly:ComVisible(false)];
[assembly:CLSCompliantAttribute(true)];

View File

@ -1,148 +0,0 @@
#include <string.h>
#include "Texture2DDecoder.h"
#include "bcn.h"
#include "pvrtc.h"
#include "etc.h"
#include "atc.h"
#include "astc.h"
#include "crunch.h"
#include "unitycrunch.h"
namespace Texture2DDecoder {
bool TextureDecoder::DecodeDXT1(array<Byte>^ data, long w, long h, array<Byte>^ image) {
pin_ptr<unsigned char> dataPin = &data[0];
pin_ptr<unsigned char> imagePin = &image[0];
return decode_bc1(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
}
bool TextureDecoder::DecodeDXT5(array<Byte>^ data, long w, long h, array<Byte>^ image) {
pin_ptr<unsigned char> dataPin = &data[0];
pin_ptr<unsigned char> imagePin = &image[0];
return decode_bc3(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
}
bool TextureDecoder::DecodePVRTC(array<Byte>^ data, long w, long h, array<Byte>^ image, bool is2bpp) {
pin_ptr<unsigned char> dataPin = &data[0];
pin_ptr<unsigned char> imagePin = &image[0];
return decode_pvrtc(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin), is2bpp ? 1 : 0);
}
bool TextureDecoder::DecodeETC1(array<Byte>^ data, long w, long h, array<Byte>^ image) {
pin_ptr<unsigned char> dataPin = &data[0];
pin_ptr<unsigned char> imagePin = &image[0];
return decode_etc1(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
}
bool TextureDecoder::DecodeETC2(array<Byte>^ data, long w, long h, array<Byte>^ image) {
pin_ptr<unsigned char> dataPin = &data[0];
pin_ptr<unsigned char> imagePin = &image[0];
return decode_etc2(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
}
bool TextureDecoder::DecodeETC2A1(array<Byte>^ data, long w, long h, array<Byte>^ image) {
pin_ptr<unsigned char> dataPin = &data[0];
pin_ptr<unsigned char> imagePin = &image[0];
return decode_etc2a1(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
}
bool TextureDecoder::DecodeETC2A8(array<Byte>^ data, long w, long h, array<Byte>^ image) {
pin_ptr<unsigned char> dataPin = &data[0];
pin_ptr<unsigned char> imagePin = &image[0];
return decode_etc2a8(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
}
bool TextureDecoder::DecodeEACR(array<Byte>^ data, long w, long h, array<Byte>^ image) {
pin_ptr<unsigned char> dataPin = &data[0];
pin_ptr<unsigned char> imagePin = &image[0];
return decode_eacr(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
}
bool TextureDecoder::DecodeEACRSigned(array<Byte>^ data, long w, long h, array<Byte>^ image) {
pin_ptr<unsigned char> dataPin = &data[0];
pin_ptr<unsigned char> imagePin = &image[0];
return decode_eacr_signed(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
}
bool TextureDecoder::DecodeEACRG(array<Byte>^ data, long w, long h, array<Byte>^ image) {
pin_ptr<unsigned char> dataPin = &data[0];
pin_ptr<unsigned char> imagePin = &image[0];
return decode_eacrg(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
}
bool TextureDecoder::DecodeEACRGSigned(array<Byte>^ data, long w, long h, array<Byte>^ image) {
pin_ptr<unsigned char> dataPin = &data[0];
pin_ptr<unsigned char> imagePin = &image[0];
return decode_eacrg_signed(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
}
bool TextureDecoder::DecodeBC4(array<Byte>^ data, long w, long h, array<Byte>^ image) {
pin_ptr<unsigned char> dataPin = &data[0];
pin_ptr<unsigned char> imagePin = &image[0];
return decode_bc4(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
}
bool TextureDecoder::DecodeBC5(array<Byte>^ data, long w, long h, array<Byte>^ image) {
pin_ptr<unsigned char> dataPin = &data[0];
pin_ptr<unsigned char> imagePin = &image[0];
return decode_bc5(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
}
bool TextureDecoder::DecodeBC6(array<Byte>^ data, long w, long h, array<Byte>^ image) {
pin_ptr<unsigned char> dataPin = &data[0];
pin_ptr<unsigned char> imagePin = &image[0];
return decode_bc6(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
}
bool TextureDecoder::DecodeBC7(array<Byte>^ data, long w, long h, array<Byte>^ image) {
pin_ptr<unsigned char> dataPin = &data[0];
pin_ptr<unsigned char> imagePin = &image[0];
return decode_bc7(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
}
bool TextureDecoder::DecodeATCRGB4(array<Byte>^ data, long w, long h, array<Byte>^ image) {
pin_ptr<unsigned char> dataPin = &data[0];
pin_ptr<unsigned char> imagePin = &image[0];
return decode_atc_rgb4(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
}
bool TextureDecoder::DecodeATCRGBA8(array<Byte>^ data, long w, long h, array<Byte>^ image) {
pin_ptr<unsigned char> dataPin = &data[0];
pin_ptr<unsigned char> imagePin = &image[0];
return decode_atc_rgba8(dataPin, w, h, reinterpret_cast<uint32_t*>(imagePin));
}
bool TextureDecoder::DecodeASTC(array<Byte>^ data, long w, long h, int bw, int bh, array<Byte>^ image) {
pin_ptr<unsigned char> dataPin = &data[0];
pin_ptr<unsigned char> imagePin = &image[0];
return decode_astc(dataPin, w, h, bw, bh, reinterpret_cast<uint32_t*>(imagePin));
}
array<Byte>^ TextureDecoder::UnpackCrunch(array<Byte>^ data) {
pin_ptr<unsigned char> dataPin = &data[0];
void* ret;
uint32_t retSize;
if (!crunch_unpack_level(dataPin, data->Length, 0, &ret, &retSize)) {
return nullptr;
}
auto buff = gcnew array<Byte>(retSize);
pin_ptr<unsigned char> buffPin = &buff[0];
memcpy(buffPin, ret, retSize);
delete ret;
return buff;
}
array<Byte>^ TextureDecoder::UnpackUnityCrunch(array<Byte>^ data) {
pin_ptr<unsigned char> dataPin = &data[0];
void* ret;
uint32_t retSize;
if (!unity_crunch_unpack_level(dataPin, data->Length, 0, &ret, &retSize)) {
return nullptr;
}
auto buff = gcnew array<Byte>(retSize);
pin_ptr<unsigned char> buffPin = &buff[0];
memcpy(buffPin, ret, retSize);
delete ret;
return buff;
}
}

View File

@ -1,30 +0,0 @@
#pragma once
using namespace System;
namespace Texture2DDecoder {
public ref class TextureDecoder
{
public:
static bool DecodeDXT1(array<Byte>^ data, long w, long h, array<Byte>^ image);
static bool DecodeDXT5(array<Byte>^ data, long w, long h, array<Byte>^ image);
static bool DecodePVRTC(array<Byte>^ data, long w, long h, array<Byte>^ image, bool is2bpp);
static bool DecodeETC1(array<Byte>^ data, long w, long h, array<Byte>^ image);
static bool DecodeETC2(array<Byte>^ data, long w, long h, array<Byte>^ image);
static bool DecodeETC2A1(array<Byte>^ data, long w, long h, array<Byte>^ image);
static bool DecodeETC2A8(array<Byte>^ data, long w, long h, array<Byte>^ image);
static bool DecodeEACR(array<Byte>^ data, long w, long h, array<Byte>^ image);
static bool DecodeEACRSigned(array<Byte>^ data, long w, long h, array<Byte>^ image);
static bool DecodeEACRG(array<Byte>^ data, long w, long h, array<Byte>^ image);
static bool DecodeEACRGSigned(array<Byte>^ data, long w, long h, array<Byte>^ image);
static bool DecodeBC4(array<Byte>^ data, long w, long h, array<Byte>^ image);
static bool DecodeBC5(array<Byte>^ data, long w, long h, array<Byte>^ image);
static bool DecodeBC6(array<Byte>^ data, long w, long h, array<Byte>^ image);
static bool DecodeBC7(array<Byte>^ data, long w, long h, array<Byte>^ image);
static bool DecodeATCRGB4(array<Byte>^ data, long w, long h, array<Byte>^ image);
static bool DecodeATCRGBA8(array<Byte>^ data, long w, long h, array<Byte>^ image);
static bool DecodeASTC(array<Byte>^ data, long w, long h, int bw, int bh, array<Byte>^ image);
static array<Byte>^ UnpackCrunch(array<Byte>^ data);
static array<Byte>^ UnpackUnityCrunch(array<Byte>^ data);
};
}

View File

@ -0,0 +1,99 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Language neutral resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
#pragma code_page(65001)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "000004b0"
BEGIN
VALUE "FileDescription", "Texture2DDecoderNative"
VALUE "FileVersion", "1.0.0.1"
VALUE "InternalName", "Texture2DDecoderNative.dll"
VALUE "LegalCopyright", "Copyright (C) Perfare 2020; Copyright (C) hozuki 2020"
VALUE "OriginalFilename", "Texture2DDecoderNative.dll"
VALUE "ProductName", "Texture2DDecoderNative"
VALUE "ProductVersion", "1.0.0.1"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0, 1200
END
END
#endif // Language neutral resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -18,12 +18,49 @@
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="astc.h" />
<ClInclude Include="atc.h" />
<ClInclude Include="bcn.h" />
<ClInclude Include="bool32_t.h" />
<ClInclude Include="color.h" />
<ClInclude Include="crunch.h" />
<ClInclude Include="crunch\crnlib.h" />
<ClInclude Include="crunch\crn_decomp.h" />
<ClInclude Include="dllexport.h" />
<ClInclude Include="endianness.h" />
<ClInclude Include="etc.h" />
<ClInclude Include="fp16.h" />
<ClInclude Include="fp16\bitcasts.h" />
<ClInclude Include="fp16\fp16.h" />
<ClInclude Include="pvrtc.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="unitycrunch.h" />
<ClInclude Include="unitycrunch\crnlib.h" />
<ClInclude Include="unitycrunch\crn_decomp.h" />
<ClInclude Include="unitycrunch\crn_defs.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="astc.cpp" />
<ClCompile Include="atc.cpp" />
<ClCompile Include="bcn.cpp" />
<ClCompile Include="crunch.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="etc.cpp" />
<ClCompile Include="pvrtc.cpp" />
<ClCompile Include="unitycrunch.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Texture2DDecoderNative.rc" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{BEC7B5E6-0A7B-4824-97A7-EEA04D9EBA29}</ProjectGuid>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<Keyword>ManagedCProj</Keyword>
<RootNamespace>Texture2DDecoder</RootNamespace>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{29356642-c46e-4144-83d8-22dc09d0d7fd}</ProjectGuid>
<RootNamespace>Texture2DDecoderNative</RootNamespace>
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
@ -31,28 +68,26 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CLRSupport>true</CLRSupport>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CLRSupport>true</CLRSupport>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
@ -73,74 +108,94 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_T2D_DLL;WIN32;_DEBUG;TEXTURE2DDECODERNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<AdditionalDependencies />
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies />
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_T2D_DLL;WIN32;NDEBUG;TEXTURE2DDECODERNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<AdditionalDependencies />
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_T2D_DLL;_DEBUG;TEXTURE2DDECODERNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_T2D_DLL;NDEBUG;TEXTURE2DDECODERNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<AdditionalDependencies />
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="astc.h" />
<ClInclude Include="atc.h" />
<ClInclude Include="bcn.h" />
<ClInclude Include="color.h" />
<ClInclude Include="crunch.h" />
<ClInclude Include="crunch\crnlib.h" />
<ClInclude Include="crunch\crn_decomp.h" />
<ClInclude Include="endianness.h" />
<ClInclude Include="etc.h" />
<ClInclude Include="fp16.h" />
<ClInclude Include="fp16\bitcasts.h" />
<ClInclude Include="fp16\fp16.h" />
<ClInclude Include="pvrtc.h" />
<ClInclude Include="Texture2DDecoder.h" />
<ClInclude Include="unitycrunch.h" />
<ClInclude Include="unitycrunch\crnlib.h" />
<ClInclude Include="unitycrunch\crn_decomp.h" />
<ClInclude Include="unitycrunch\crn_defs.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AssemblyInfo.cpp" />
<ClCompile Include="astc.cpp" />
<ClCompile Include="atc.cpp" />
<ClCompile Include="bcn.cpp" />
<ClCompile Include="crunch.cpp" />
<ClCompile Include="etc.cpp" />
<ClCompile Include="pvrtc.cpp" />
<ClCompile Include="Texture2DDecoder.cpp" />
<ClCompile Include="unitycrunch.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@ -15,6 +15,33 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pvrtc.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="unitycrunch.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="crunch\crnlib.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="crunch\crn_decomp.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="fp16\bitcasts.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="fp16\fp16.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="unitycrunch\crnlib.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="unitycrunch\crn_decomp.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="unitycrunch\crn_defs.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="astc.h">
<Filter>头文件</Filter>
</ClInclude>
@ -39,39 +66,18 @@
<ClInclude Include="fp16.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="pvrtc.h">
<ClInclude Include="dllexport.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="Texture2DDecoder.h">
<ClInclude Include="bool32_t.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="unitycrunch.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="crunch\crn_decomp.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="crunch\crnlib.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="fp16\bitcasts.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="fp16\fp16.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="unitycrunch\crn_decomp.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="unitycrunch\crn_defs.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="unitycrunch\crnlib.h">
<ClInclude Include="resource.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="AssemblyInfo.cpp">
<ClCompile Include="unitycrunch.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="astc.cpp">
@ -92,11 +98,16 @@
<ClCompile Include="pvrtc.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Texture2DDecoder.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="unitycrunch.cpp">
<ClCompile Include="dllmain.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Texture2DDecoderNative.rc">
<Filter>资源文件</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,5 @@
#pragma once
#include <cstdint>
typedef uint32_t bool32_t;

View File

@ -0,0 +1 @@
#define T2D_API(ret_type)

View File

@ -0,0 +1,56 @@
#pragma once
#if defined(_MSC_VER)
#if _MSC_VER < 1910 // MSVC 2017-
#error MSVC 2017 or later is required.
#endif
#endif
#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW__)
#ifdef _T2D_DLL
#ifdef __GNUC__
#define _T2D_EXPORT __attribute__ ((dllexport))
#else
#define _T2D_EXPORT __declspec(dllexport)
#endif
#else
#ifdef __GNUC__
#define _T2D_EXPORT __attribute__ ((dllimport))
#else
#define _T2D_EXPORT __declspec(dllimport)
#endif
#endif
#define _T2D_LOCAL
#else
#if __GNUC__ >= 4
#define _T2D_EXPORT __attribute__ ((visibility ("default")))
#define _T2D_LOCAL __attribute__ ((visibility ("hidden")))
#else
#define _T2D_EXPORT
#define _T2D_LOCAL
#endif
#endif
#ifdef __cplusplus
#ifndef _EXTERN_C_STMT
#define _EXTERN_C_STMT extern "C"
#endif
#else
#ifndef _EXTERN_C_STMT
#define _EXTERN_C_STMT
#endif
#endif
#ifndef _T2D_CALL
#if defined(WIN32) || defined(_WIN32)
#define _T2D_CALL __stdcall
#else
#define _T2D_CALL /* __cdecl */
#endif
#endif
#if defined(_MSC_VER)
#define T2D_API(ret_type) _EXTERN_C_STMT _T2D_EXPORT ret_type _T2D_CALL
#else
#define T2D_API(ret_type) _EXTERN_C_STMT _T2D_EXPORT _T2D_CALL ret_type
#endif

View File

@ -0,0 +1,174 @@
#include "dllexport.h"
#include "bool32_t.h"
#include "bcn.h"
#include "pvrtc.h"
#include "etc.h"
#include "atc.h"
#include "astc.h"
#include "crunch.h"
#include "unitycrunch.h"
T2D_API(bool32_t) DecodeDXT1(const void* data, int32_t width, int32_t height, void* image)
{
return decode_bc1(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
}
T2D_API(bool32_t) DecodeDXT5(const void* data, int32_t width, int32_t height, void* image)
{
return decode_bc3(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
}
T2D_API(bool32_t) DecodePVRTC(const void* data, int32_t width, int32_t height, void* image, bool32_t is2bpp)
{
return decode_pvrtc(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image), is2bpp ? 1 : 0);
}
T2D_API(bool32_t) DecodeETC1(const void* data, int32_t width, int32_t height, void* image)
{
return decode_etc1(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
}
T2D_API(bool32_t) DecodeETC2(const void* data, int32_t width, int32_t height, void* image)
{
return decode_etc2(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
}
T2D_API(bool32_t) DecodeETC2A1(const void* data, int32_t width, int32_t height, void* image)
{
return decode_etc2a1(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
}
T2D_API(bool32_t) DecodeETC2A8(const void* data, int32_t width, int32_t height, void* image)
{
return decode_etc2a8(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
}
T2D_API(bool32_t) DecodeEACR(const void* data, int32_t width, int32_t height, void* image)
{
return decode_eacr(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
}
T2D_API(bool32_t) DecodeEACRSigned(const void* data, int32_t width, int32_t height, void* image)
{
return decode_eacr_signed(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
}
T2D_API(bool32_t) DecodeEACRG(const void* data, int32_t width, int32_t height, void* image)
{
return decode_eacrg(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
}
T2D_API(bool32_t) DecodeEACRGSigned(const void* data, int32_t width, int32_t height, void* image)
{
return decode_eacrg_signed(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
}
T2D_API(bool32_t) DecodeBC4(const void* data, int32_t width, int32_t height, void* image)
{
return decode_bc4(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
}
T2D_API(bool32_t) DecodeBC5(const void* data, int32_t width, int32_t height, void* image)
{
return decode_bc5(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
}
T2D_API(bool32_t) DecodeBC6(const void* data, int32_t width, int32_t height, void* image)
{
return decode_bc6(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
}
T2D_API(bool32_t) DecodeBC7(const void* data, int32_t width, int32_t height, void* image)
{
return decode_bc7(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
}
T2D_API(bool32_t) DecodeATCRGB4(const void* data, int32_t width, int32_t height, void* image)
{
return decode_atc_rgb4(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
}
T2D_API(bool32_t) DecodeATCRGBA8(const void* data, int32_t width, int32_t height, void* image)
{
return decode_atc_rgba8(static_cast<const uint8_t*>(data), width, height, static_cast<uint32_t*>(image));
}
T2D_API(bool32_t) DecodeASTC(const void* data, int32_t width, int32_t height, int32_t blockWidth, int32_t blockHeight, void* image)
{
return decode_astc(static_cast<const uint8_t*>(data), width, height, blockWidth, blockHeight, static_cast<uint32_t*>(image));
}
T2D_API(void) DisposeBuffer(void** ppBuffer)
{
if (ppBuffer == nullptr)
{
return;
}
auto ppTypedBuffer = reinterpret_cast<uint8_t**>(ppBuffer);
delete[](*ppTypedBuffer);
*ppBuffer = nullptr;
}
T2D_API(void) UnpackCrunch(const void* data, uint32_t dataSize, void** ppResult, uint32_t* pResultSize)
{
void* result;
uint32_t resultSize;
if (ppResult != nullptr)
{
*ppResult = nullptr;
}
if (pResultSize != nullptr)
{
*pResultSize = 0;
}
if (!crunch_unpack_level(static_cast<const uint8_t*>(data), dataSize, 0, &result, &resultSize)) {
return;
}
if (ppResult != nullptr)
{
*ppResult = result;
}
if (pResultSize != nullptr)
{
*pResultSize = resultSize;
}
}
T2D_API(void) UnpackUnityCrunch(const void* data, uint32_t dataSize, void** ppResult, uint32_t* pResultSize)
{
void* result;
uint32_t resultSize;
if (ppResult != nullptr)
{
*ppResult = nullptr;
}
if (pResultSize != nullptr)
{
*pResultSize = 0;
}
if (!unity_crunch_unpack_level(static_cast<const uint8_t*>(data), dataSize, 0, &result, &resultSize)) {
return;
}
if (ppResult != nullptr)
{
*ppResult = result;
}
if (pResultSize != nullptr)
{
*pResultSize = resultSize;
}
}

View File

@ -0,0 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Texture2DDecoderNative.rc
// 新对象的下一组默认值
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -0,0 +1,19 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Texture2DDecoder")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Texture2DDecoder")]
[assembly: AssemblyCopyright("Copyright © Perfare 2020; Copyright © hozuki 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("2afce830-b463-49b3-a026-877e5eafc0a4")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,9 @@
namespace Texture2DDecoder
{
internal static class T2DDll
{
internal const string DllName = "Texture2DDecoderNative";
}
}

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{2AFCE830-B463-49B3-A026-877E5EAFC0A4}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Texture2DDecoder</RootNamespace>
<AssemblyName>Texture2DDecoderWrapper</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup>
<Compile Include="T2DDll.cs" />
<Compile Include="TextureDecoder.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TextureDecoder.PInvoke.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj">
<Project>{40c796b5-88ce-4adc-acd6-2f4862b7f136}</Project>
<Name>AssetStudio.PInvoke</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,90 @@
using System.Runtime.InteropServices;
namespace Texture2DDecoder
{
unsafe partial class TextureDecoder
{
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DecodeDXT1(void* data, int width, int height, void* image);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DecodeDXT5(void* data, int width, int height, void* image);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DecodePVRTC(void* data, int width, int height, void* image, [MarshalAs(UnmanagedType.Bool)] bool is2bpp);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DecodeETC1(void* data, int width, int height, void* image);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DecodeETC2(void* data, int width, int height, void* image);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DecodeETC2A1(void* data, int width, int height, void* image);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DecodeETC2A8(void* data, int width, int height, void* image);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DecodeEACR(void* data, int width, int height, void* image);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DecodeEACRSigned(void* data, int width, int height, void* image);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DecodeEACRG(void* data, int width, int height, void* image);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DecodeEACRGSigned(void* data, int width, int height, void* image);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DecodeBC4(void* data, int width, int height, void* image);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DecodeBC5(void* data, int width, int height, void* image);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DecodeBC6(void* data, int width, int height, void* image);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DecodeBC7(void* data, int width, int height, void* image);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DecodeATCRGB4(void* data, int width, int height, void* image);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DecodeATCRGBA8(void* data, int width, int height, void* image);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DecodeASTC(void* data, int width, int height, int blockWidth, int blockHeight, void* image);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void DisposeBuffer(ref void* ppBuffer);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void UnpackCrunch(void* data, uint dataSize, out void* result, out uint resultSize);
[DllImport(T2DDll.DllName, CallingConvention = CallingConvention.Winapi)]
private static extern void UnpackUnityCrunch(void* data, uint dataSize, out void* result, out uint resultSize);
}
}

View File

@ -0,0 +1,262 @@
using System;
using System.Runtime.InteropServices;
using AssetStudio.PInvoke;
namespace Texture2DDecoder
{
public static unsafe partial class TextureDecoder
{
static TextureDecoder()
{
DllLoader.PreloadDll(T2DDll.DllName);
}
public static bool DecodeDXT1(byte[] data, int width, int height, byte[] image)
{
fixed (byte* pData = data)
{
fixed (byte* pImage = image)
{
return DecodeDXT1(pData, width, height, pImage);
}
}
}
public static bool DecodeDXT5(byte[] data, int width, int height, byte[] image)
{
fixed (byte* pData = data)
{
fixed (byte* pImage = image)
{
return DecodeDXT5(pData, width, height, pImage);
}
}
}
public static bool DecodePVRTC(byte[] data, int width, int height, byte[] image, bool is2bpp)
{
fixed (byte* pData = data)
{
fixed (byte* pImage = image)
{
return DecodePVRTC(pData, width, height, pImage, is2bpp);
}
}
}
public static bool DecodeETC1(byte[] data, int width, int height, byte[] image)
{
fixed (byte* pData = data)
{
fixed (byte* pImage = image)
{
return DecodeETC1(pData, width, height, pImage);
}
}
}
public static bool DecodeETC2(byte[] data, int width, int height, byte[] image)
{
fixed (byte* pData = data)
{
fixed (byte* pImage = image)
{
return DecodeETC2(pData, width, height, pImage);
}
}
}
public static bool DecodeETC2A1(byte[] data, int width, int height, byte[] image)
{
fixed (byte* pData = data)
{
fixed (byte* pImage = image)
{
return DecodeETC2A1(pData, width, height, pImage);
}
}
}
public static bool DecodeETC2A8(byte[] data, int width, int height, byte[] image)
{
fixed (byte* pData = data)
{
fixed (byte* pImage = image)
{
return DecodeETC2A8(pData, width, height, pImage);
}
}
}
public static bool DecodeEACR(byte[] data, int width, int height, byte[] image)
{
fixed (byte* pData = data)
{
fixed (byte* pImage = image)
{
return DecodeEACR(pData, width, height, pImage);
}
}
}
public static bool DecodeEACRSigned(byte[] data, int width, int height, byte[] image)
{
fixed (byte* pData = data)
{
fixed (byte* pImage = image)
{
return DecodeEACRSigned(pData, width, height, pImage);
}
}
}
public static bool DecodeEACRG(byte[] data, int width, int height, byte[] image)
{
fixed (byte* pData = data)
{
fixed (byte* pImage = image)
{
return DecodeEACRG(pData, width, height, pImage);
}
}
}
public static bool DecodeEACRGSigned(byte[] data, int width, int height, byte[] image)
{
fixed (byte* pData = data)
{
fixed (byte* pImage = image)
{
return DecodeEACRGSigned(pData, width, height, pImage);
}
}
}
public static bool DecodeBC4(byte[] data, int width, int height, byte[] image)
{
fixed (byte* pData = data)
{
fixed (byte* pImage = image)
{
return DecodeBC4(pData, width, height, pImage);
}
}
}
public static bool DecodeBC5(byte[] data, int width, int height, byte[] image)
{
fixed (byte* pData = data)
{
fixed (byte* pImage = image)
{
return DecodeBC5(pData, width, height, pImage);
}
}
}
public static bool DecodeBC6(byte[] data, int width, int height, byte[] image)
{
fixed (byte* pData = data)
{
fixed (byte* pImage = image)
{
return DecodeBC6(pData, width, height, pImage);
}
}
}
public static bool DecodeBC7(byte[] data, int width, int height, byte[] image)
{
fixed (byte* pData = data)
{
fixed (byte* pImage = image)
{
return DecodeBC7(pData, width, height, pImage);
}
}
}
public static bool DecodeATCRGB4(byte[] data, int width, int height, byte[] image)
{
fixed (byte* pData = data)
{
fixed (byte* pImage = image)
{
return DecodeATCRGB4(pData, width, height, pImage);
}
}
}
public static bool DecodeATCRGBA8(byte[] data, int width, int height, byte[] image)
{
fixed (byte* pData = data)
{
fixed (byte* pImage = image)
{
return DecodeATCRGBA8(pData, width, height, pImage);
}
}
}
public static bool DecodeASTC(byte[] data, int width, int height, int blockWidth, int blockHeight, byte[] image)
{
fixed (byte* pData = data)
{
fixed (byte* pImage = image)
{
return DecodeASTC(pData, width, height, blockWidth, blockHeight, pImage);
}
}
}
public static byte[] UnpackCrunch(byte[] data)
{
void* pBuffer;
uint bufferSize;
fixed (byte* pData = data)
{
UnpackCrunch(pData, (uint)data.Length, out pBuffer, out bufferSize);
}
if (pBuffer == null)
{
return null;
}
var result = new byte[bufferSize];
Marshal.Copy(new IntPtr(pBuffer), result, 0, (int)bufferSize);
DisposeBuffer(ref pBuffer);
return result;
}
public static byte[] UnpackUnityCrunch(byte[] data)
{
void* pBuffer;
uint bufferSize;
fixed (byte* pData = data)
{
UnpackUnityCrunch(pData, (uint)data.Length, out pBuffer, out bufferSize);
}
if (pBuffer == null)
{
return null;
}
var result = new byte[bufferSize];
Marshal.Copy(new IntPtr(pBuffer), result, 0, (int)bufferSize);
DisposeBuffer(ref pBuffer);
return result;
}
}
}