39 Commits

Author SHA1 Message Date
74dcea373c Allow reimporting model prefabs from Content window context menu
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2024-06-01 21:43:42 +03:00
70f8492c01 Fix missing vertices in some imported models
The Spatial Sort version was being too greedy when merging vertices
2024-06-01 21:43:42 +03:00
63acdccd43 Fix typos 2024-06-01 21:43:41 +03:00
03f74b0c50 Implement triangulation for non-convex polygons 2024-06-01 21:43:41 +03:00
0d21a3ba1b Fix compile errors in libdeflate 2024-06-01 21:43:41 +03:00
d85a5bcd36 Reapply OpenFBX patches 2024-06-01 21:43:40 +03:00
585ebceb6a Update OpenFBX
Updated to commit 365f52c1edad6bd283c8a645f1d8d2347dbd1e35
2024-06-01 21:43:40 +03:00
593c82543f Limit MSVC compiler code generation threads to one per file 2024-06-01 21:43:39 +03:00
7f1bcd91f5 Remove redundant asset waiting and reloading when saving materials 2024-06-01 21:43:39 +03:00
58214ffc35 Fix RichTextBox not drawing the last character 2024-06-01 21:43:39 +03:00
67b4b01697 _binaries 2024-06-01 21:43:21 +03:00
bd880c0e2f _lfsconfig 2024-06-01 21:43:20 +03:00
0bca21a1d4 Fix compilation errors with miniz 2024-06-01 21:28:23 +03:00
c5e3d4afd3 Update miniz for tinyexr 2024-06-01 21:28:21 +03:00
bb1bee40e4 Fix alignment issues in stack allocators 2024-05-19 23:58:44 +03:00
1b0b8998f9 Hide Visual Studio solution architectures not supported by main project 2024-05-19 23:58:43 +03:00
e4764c4d84 Skip setup of ARM64 configuration for Windows with no compiler support 2024-05-19 23:58:43 +03:00
2de756f761 Include configuration specific source files in solution configurations
Include only relevant generated source files for selected solution
configuration. Fixes Intellisense issues when both ARM64 and Win64
configurations are present in project.
2024-05-19 23:58:43 +03:00
83f40be4f5 Copy hostfxr from platform architecture specific dependencies folder 2024-05-19 23:58:43 +03:00
87a73c9b73 Add cooking support for Windows on ARM 2024-05-19 23:58:42 +03:00
7054f942f6 Update minimp3 2024-05-19 23:58:42 +03:00
227eaff9e2 Patch rapidjson for Windows on ARM 2024-05-19 23:58:42 +03:00
563a45633f Patch tracy for Windows on ARM 2024-05-19 23:58:42 +03:00
09e0754902 Compile glslang for Windows on ARM 2024-05-19 23:58:41 +03:00
3dfe0e6c5a Compile assimp for Windows on ARM 2024-05-19 23:58:41 +03:00
9e7af72046 Add dependencies to copy dbghelp and dxcompiler files from SDK 2024-05-19 23:58:41 +03:00
96eb8cb0ca Build astc for Windows on ARM 2024-05-19 23:58:41 +03:00
ff86057a0a Update OpenAL to use CMake for compilation on Windows 2024-05-19 23:58:40 +03:00
56abd82c9b Update ogg and vorbis to use CMake for compilation on Windows 2024-05-19 23:58:40 +03:00
9777bef9df Patch pix3.h for Windows on ARM 2024-05-19 23:58:40 +03:00
9fedacb404 Use VS2022 Win10 MSVC solutions in DirectX-related dependencies 2024-05-19 23:58:40 +03:00
84f7fde753 Build NvCloth for Windows on ARM 2024-05-19 23:58:39 +03:00
a5566d297f Update PhysX with Windows on ARM support 2024-05-19 23:58:39 +03:00
3f299f99cd Update curl to 7.88.1 2024-05-19 23:58:39 +03:00
741fc959e6 Update Freetype to 2.13.2 2024-05-19 23:58:38 +03:00
93fd560723 Fix rebuilding dependencies using Git with existing local folders 2024-05-19 23:58:38 +03:00
cf48ce6d93 Fallback to D3D11 devices without debug layers when unavailable 2024-05-19 23:58:38 +03:00
bdd3b754bd Support using native host MSVC binaries on ARM64 2024-05-19 23:58:38 +03:00
99c27c9c30 Support ARM64 architecture under Windows 2024-05-19 23:58:37 +03:00
342 changed files with 22801 additions and 6674 deletions

View File

@@ -1,4 +1,4 @@
# Redirect to our own Git LFS server
[lfs]
url="https://gitlab.flaxengine.com/flax/flaxengine.git/info/lfs"
#url="https://gitlab.flaxengine.com/flax/flaxengine.git/info/lfs"
locksverify = false

View File

@@ -14,8 +14,8 @@ call "Development\Scripts\Windows\CallBuildTool.bat" -genproject %*
if errorlevel 1 goto BuildToolFailed
:: Build bindings for all editor configurations
echo Building C# bindings...
Binaries\Tools\Flax.Build.exe -build -BuildBindingsOnly -arch=x64 -platform=Windows --buildTargets=FlaxEditor
::echo Building C# bindings...
::Binaries\Tools\Flax.Build.exe -build -BuildBindingsOnly -arch=x64 -platform=Windows --buildTargets=FlaxEditor
popd
echo Done!

View File

@@ -73,6 +73,16 @@ namespace FlaxEditor.Content
return targetLocation.CanHaveAssets;
}
/// <inheritdoc />
public override bool CanReimport(ContentItem item)
{
if (item is not PrefabItem prefabItem)
return base.CanReimport(item);
var prefab = FlaxEngine.Content.Load<Prefab>(prefabItem.ID);
return prefab.GetDefaultInstance().GetScript<ModelPrefab>() != null;
}
/// <inheritdoc />
public override void Create(string outputPath, object arg)
{

View File

@@ -134,6 +134,12 @@ API_ENUM() enum class BuildPlatform
/// </summary>
API_ENUM(Attributes="EditorDisplay(null, \"iOS ARM64\")")
iOSARM64 = 14,
/// <summary>
/// Windows (ARM64)
/// </summary>
API_ENUM(Attributes = "EditorDisplay(null, \"Windows ARM64\")")
WindowsARM64 = 15,
};
/// <summary>

View File

@@ -148,6 +148,8 @@ const Char* ToString(const BuildPlatform platform)
return TEXT("Mac ARM64");
case BuildPlatform::iOSARM64:
return TEXT("iOS ARM64");
case BuildPlatform::WindowsARM64:
return TEXT("Windows ARM64");
default:
return TEXT("");
}
@@ -300,6 +302,10 @@ void CookingData::GetBuildPlatformName(const Char*& platform, const Char*& archi
platform = TEXT("iOS");
architecture = TEXT("ARM64");
break;
case BuildPlatform::WindowsARM64:
platform = TEXT("Windows");
architecture = TEXT("ARM64");
break;
default:
LOG(Fatal, "Unknown or unsupported build platform.");
}
@@ -386,6 +392,9 @@ PlatformTools* GameCooker::GetTools(BuildPlatform platform)
case BuildPlatform::Windows64:
result = New<WindowsPlatformTools>(ArchitectureType::x64);
break;
case BuildPlatform::WindowsARM64:
result = New<WindowsPlatformTools>(ArchitectureType::ARM64);
break;
#endif
#if PLATFORM_TOOLS_UWP
case BuildPlatform::UWPx86:
@@ -547,7 +556,12 @@ void GameCooker::GetCurrentPlatform(PlatformType& platform, BuildPlatform& build
switch (PLATFORM_TYPE)
{
case PlatformType::Windows:
buildPlatform = PLATFORM_64BITS ? BuildPlatform::Windows64 : BuildPlatform::Windows32;
if (PLATFORM_ARCH == ArchitectureType::x64)
buildPlatform = BuildPlatform::Windows64;
else if (PLATFORM_ARCH == ArchitectureType::ARM64)
buildPlatform = BuildPlatform::WindowsARM64;
else
buildPlatform = BuildPlatform::Windows32;
break;
case PlatformType::XboxOne:
buildPlatform = BuildPlatform::XboxOne;

View File

@@ -447,6 +447,7 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass
#if PLATFORM_TOOLS_WINDOWS
case BuildPlatform::Windows32:
case BuildPlatform::Windows64:
case BuildPlatform::WindowsARM64:
{
const char* platformDefineName = "PLATFORM_WINDOWS";
const auto settings = WindowsPlatformSettings::Get();

View File

@@ -73,6 +73,7 @@ bool DeployDataStep::Perform(CookingData& data)
{
case BuildPlatform::Windows32:
case BuildPlatform::Windows64:
case BuildPlatform::WindowsARM64:
canUseSystemDotnet = PLATFORM_TYPE == PlatformType::Windows;
break;
case BuildPlatform::LinuxX64:
@@ -159,7 +160,20 @@ bool DeployDataStep::Perform(CookingData& data)
}
else
{
failed |= EditorUtilities::CopyDirectoryIfNewer(dstDotnet / TEXT("host/fxr") / version, srcDotnet / TEXT("host/fxr") / version, true);
// TODO: hostfxr for target platform should be copied from nuget package location: microsoft.netcore.app.runtime.<RID>/<VERSION>/runtimes/<RID>/native/hostfxr.dll
String dstHostfxr = dstDotnet / TEXT("host/fxr") / version;
if (!FileSystem::DirectoryExists(dstHostfxr))
FileSystem::CreateDirectory(dstHostfxr);
const Char *platformName, *archName;
data.GetBuildPlatformName(platformName, archName);
if (data.Platform == BuildPlatform::Windows64 || data.Platform == BuildPlatform::WindowsARM64 || data.Platform == BuildPlatform::Windows32)
failed |= FileSystem::CopyFile(dstHostfxr / TEXT("hostfxr.dll"), depsRoot / TEXT("ThirdParty") / archName / TEXT("hostfxr.dll"));
else if (data.Platform == BuildPlatform::LinuxX64)
failed |= FileSystem::CopyFile(dstHostfxr / TEXT("hostfxr.so"), depsRoot / TEXT("ThirdParty") / archName / TEXT("hostfxr.so"));
else if (data.Platform == BuildPlatform::MacOSx64 || data.Platform == BuildPlatform::MacOSARM64)
failed |= FileSystem::CopyFile(dstHostfxr / TEXT("hostfxr.dylib"), depsRoot / TEXT("ThirdParty") / archName / TEXT("hostfxr.dylib"));
else
failed |= true;
failed |= EditorUtilities::CopyDirectoryIfNewer(dstDotnet / TEXT("shared/Microsoft.NETCore.App") / version, srcDotnet / TEXT("shared/Microsoft.NETCore.App") / version, true);
}
if (failed)

View File

@@ -459,8 +459,7 @@ namespace FlaxEditor.Windows.Assets
/// <returns>True if failed, otherwise false.</returns>
protected virtual bool SaveToOriginal()
{
// Wait until temporary asset file be fully loaded
if (_asset.WaitForLoaded())
if (_asset.LastLoadFailed)
{
Editor.LogError(string.Format("Cannot save asset {0}. Wait for temporary asset loaded failed.", _item.Path));
return true;
@@ -494,12 +493,6 @@ namespace FlaxEditor.Windows.Assets
return true;
}
// Reload original asset
if (originalAsset)
{
originalAsset.Reload();
}
// Refresh thumbnail
_item.RefreshThumbnail();

View File

@@ -355,7 +355,6 @@ namespace FlaxEditor.Windows.Assets
Editor.LogError("Failed to save surface data");
}
_asset.Reload();
_asset.WaitForLoaded();
}
}

View File

@@ -311,6 +311,23 @@ namespace FlaxEditor.Windows
{
if (selection[i] is BinaryAssetItem binaryAssetItem)
Editor.ContentImporting.Reimport(binaryAssetItem);
else if (selection[i] is PrefabItem prefabItem)
{
var prefab = FlaxEngine.Content.Load<Prefab>(prefabItem.ID);
var modelPrefab = prefab.GetDefaultInstance().GetScript<ModelPrefab>();
if (!modelPrefab)
continue;
var importPath = modelPrefab.ImportPath;
var editor = Editor.Instance;
if (editor.ContentImporting.GetReimportPath("Model Prefab", ref importPath))
continue;
var folder = editor.ContentDatabase.Find(Path.GetDirectoryName(prefab.Path)) as ContentFolder;
if (folder == null)
continue;
var importOptions = modelPrefab.ImportOptions;
importOptions.Type = FlaxEngine.Tools.ModelTool.ModelType.Prefab;
editor.ContentImporting.Import(importPath, folder, true, importOptions);
}
}
}

View File

@@ -767,13 +767,6 @@ namespace FlaxEditor.Windows
Platform = BuildPlatform.Windows64,
Mode = BuildConfiguration.Development,
},
new BuildTarget
{
Name = "Windows 32bit",
Output = "Output\\Win32",
Platform = BuildPlatform.Windows32,
Mode = BuildConfiguration.Development,
},
}
};
_data = presets;
@@ -793,9 +786,9 @@ namespace FlaxEditor.Windows
Array.Copy(_data[_selectedPresetIndex].Targets, targets, count);
targets[count] = new BuildTarget
{
Name = "Xbox One",
Output = "Output\\XboxOne",
Platform = BuildPlatform.XboxOne,
Name = "Windows 64bit",
Output = "Output\\Win64",
Platform = BuildPlatform.Windows64,
Mode = BuildConfiguration.Development,
};
_data[_selectedPresetIndex].Targets = targets;

View File

@@ -15,7 +15,7 @@ public:
enum { HasSwap = false };
template<typename T>
class Data
class alignas(sizeof(void*)) Data
{
private:
byte _data[Capacity * sizeof(T)];
@@ -183,7 +183,7 @@ public:
enum { HasSwap = false };
template<typename T>
class Data
class alignas(sizeof(void*)) Data
{
private:
typedef typename OtherAllocator::template Data<T> OtherData;

View File

@@ -15,12 +15,12 @@
#define USE_MIKKTSPACE 1
#include "ThirdParty/MikkTSpace/mikktspace.h"
#if USE_ASSIMP
#define USE_SPARIAL_SORT 1
#define USE_SPATIAL_SORT 1
#define ASSIMP_BUILD_NO_EXPORT
#include "Engine/Tools/ModelTool/SpatialSort.h"
//#include <ThirdParty/assimp/SpatialSort.h>
#else
#define USE_SPARIAL_SORT 0
#define USE_SPATIAL_SORT 0
#endif
#include <stack>
@@ -155,18 +155,18 @@ bool MeshData::GenerateLightmapUVs()
}
int32 FindVertex(const MeshData& mesh, int32 vertexIndex, int32 startIndex, int32 searchRange, const Array<int32>& mapping
#if USE_SPARIAL_SORT
#if USE_SPATIAL_SORT
, const Assimp::SpatialSort& spatialSort
, std::vector<unsigned int>& sparialSortCache
, std::vector<unsigned int>& spatialSortCache
#endif
)
{
const float uvEpsSqr = (1.0f / 250.0f) * (1.0f / 250.0f);
#if USE_SPARIAL_SORT
#if USE_SPATIAL_SORT
const Float3 vPosition = mesh.Positions[vertexIndex];
spatialSort.FindPositions(*(aiVector3D*)&vPosition, 1e-4f, sparialSortCache);
if (sparialSortCache.empty())
spatialSort.FindPositions(*(aiVector3D*)&vPosition, 1e-5f, spatialSortCache);
if (spatialSortCache.empty())
return INVALID_INDEX;
const Float2 vUV = mesh.UVs.HasItems() ? mesh.UVs[vertexIndex] : Float2::Zero;
@@ -177,9 +177,9 @@ int32 FindVertex(const MeshData& mesh, int32 vertexIndex, int32 startIndex, int3
const int32 end = startIndex + searchRange;
for (size_t i = 0; i < sparialSortCache.size(); i++)
for (size_t i = 0; i < spatialSortCache.size(); i++)
{
const int32 v = sparialSortCache[i];
const int32 v = spatialSortCache[i];
if (v < startIndex || v >= end)
continue;
#else
@@ -247,11 +247,11 @@ void MeshData::BuildIndexBuffer()
mapping.Resize(vertexCount);
int32 newVertexCounter = 0;
#if USE_SPARIAL_SORT
#if USE_SPATIAL_SORT
// Set up a SpatialSort to quickly find all vertices close to a given position
Assimp::SpatialSort vertexFinder;
vertexFinder.Fill((const aiVector3D*)Positions.Get(), vertexCount, sizeof(Float3));
std::vector<unsigned int> sparialSortCache;
std::vector<unsigned int> spatialSortCache;
#endif
// Build index buffer
@@ -259,8 +259,8 @@ void MeshData::BuildIndexBuffer()
{
// Find duplicated vertex before the current one
const int32 reuseVertexIndex = FindVertex(*this, vertexIndex, 0, vertexIndex, mapping
#if USE_SPARIAL_SORT
, vertexFinder, sparialSortCache
#if USE_SPATIAL_SORT
, vertexFinder, spatialSortCache
#endif
);
if (reuseVertexIndex == INVALID_INDEX)
@@ -376,7 +376,7 @@ bool MeshData::GenerateNormals(float smoothingAngle)
Float3::Max(max, v3, max);
}
#if USE_SPARIAL_SORT
#if USE_SPATIAL_SORT
// Set up a SpatialSort to quickly find all vertices close to a given position
Assimp::SpatialSort vertexFinder;
vertexFinder.Fill((const aiVector3D*)Positions.Get(), vertexCount, sizeof(Float3));
@@ -399,7 +399,7 @@ bool MeshData::GenerateNormals(float smoothingAngle)
continue;
// Get all vertices that share this one
#if USE_SPARIAL_SORT
#if USE_SPATIAL_SORT
vertexFinder.FindPositions(*(aiVector3D*)&Positions[i], posEpsilon, verticesFound);
const int32 verticesFoundCount = (int32)verticesFound.size();
#else
@@ -429,7 +429,7 @@ bool MeshData::GenerateNormals(float smoothingAngle)
for (int32 i = 0; i < vertexCount; i++)
{
// Get all vertices that share this one
#if USE_SPARIAL_SORT
#if USE_SPATIAL_SORT
vertexFinder.FindPositions(*(aiVector3D*)&Positions[i], posEpsilon, verticesFound);
const int32 verticesFoundCount = (int32)verticesFound.size();
#else
@@ -623,7 +623,7 @@ bool MeshData::GenerateTangents(float smoothingAngle)
}
}
#if USE_SPARIAL_SORT
#if USE_SPATIAL_SORT
// Set up a SpatialSort to quickly find all vertices close to a given position
Assimp::SpatialSort vertexFinder;
vertexFinder.Fill((const aiVector3D*)Positions.Get(), vertexCount, sizeof(Float3));
@@ -648,7 +648,7 @@ bool MeshData::GenerateTangents(float smoothingAngle)
closeVertices.Clear();
// Find all vertices close to that position
#if USE_SPARIAL_SORT
#if USE_SPATIAL_SORT
vertexFinder.FindPositions(*(aiVector3D*)&origPos, posEpsilon, verticesFound);
const int32 verticesFoundCount = (int32)verticesFound.size();
#else

View File

@@ -71,7 +71,28 @@ static bool TryCreateDevice(IDXGIAdapter* adapter, D3D_FEATURE_LEVEL maxFeatureL
context->Release();
return true;
}
#if GPU_ENABLE_DIAGNOSTICS
deviceFlags &= ~D3D11_CREATE_DEVICE_DEBUG;
if (SUCCEEDED(D3D11CreateDevice(
adapter,
D3D_DRIVER_TYPE_UNKNOWN,
NULL,
deviceFlags,
&featureLevels[levelIndex],
ARRAY_COUNT(featureLevels) - levelIndex,
D3D11_SDK_VERSION,
&device,
featureLevel,
&context
)))
{
LOG(Warning, "Direct3D SDK debug layers were requested, but not available.");
device->Release();
context->Release();
return true;
}
#endif
return false;
}

View File

@@ -2,6 +2,20 @@
#if GRAPHICS_API_DIRECTX12
#include "Engine/Graphics/Config.h"
#if USE_PIX && GPU_ALLOW_PROFILE_EVENTS
// Include these header files before pix3
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#define NOGDI
#define NODRAWTEXT
//#define NOCTLMGR
#define NOFLATSBAPIS
#include <Windows.h>
#include <d3d12.h>
#include <ThirdParty/WinPixEventRuntime/pix3.h>
#endif
#include "GPUContextDX12.h"
#include "Engine/Core/Log.h"
#include "Engine/Core/Math/Viewport.h"
@@ -22,9 +36,6 @@
#include "Engine/Profiler/RenderStats.h"
#include "Engine/Graphics/Shaders/GPUShader.h"
#include "Engine/Threading/Threading.h"
#if USE_PIX && GPU_ALLOW_PROFILE_EVENTS
#include <pix3.h>
#endif
#define DX12_ENABLE_RESOURCE_BARRIERS_BATCHING 1
#define DX12_ENABLE_RESOURCE_BARRIERS_DEBUGGING 0

View File

@@ -6,10 +6,14 @@
// Platform description
#define PLATFORM_DESKTOP 1
#if defined(WIN64)
#if defined(WIN64) && defined(_M_X64)
#define PLATFORM_64BITS 1
#define PLATFORM_ARCH_X64 1
#define PLATFORM_ARCH ArchitectureType::x64
#elif defined(WIN64) && defined(_M_ARM64)
#define PLATFORM_64BITS 1
#define PLATFORM_ARCH_ARM64 1
#define PLATFORM_ARCH ArchitectureType::ARM64
#else
#define PLATFORM_64BITS 0
#define PLATFORM_ARCH_X86 1

View File

@@ -157,10 +157,14 @@ bool Win32Platform::Init()
CpuInfo.PageSize = siSysInfo.dwPageSize;
CpuInfo.ClockSpeed = ClockFrequency;
{
#ifdef _M_ARM64
CpuInfo.CacheLineSize = 128;
#else
int args[4];
__cpuid(args, 0x80000006);
CpuInfo.CacheLineSize = args[2] & 0xFF;
ASSERT(CpuInfo.CacheLineSize && Math::IsPowerOfTwo(CpuInfo.CacheLineSize));
#endif
}
// Setup unique device ID
@@ -226,10 +230,12 @@ void Win32Platform::MemoryBarrier()
{
_ReadWriteBarrier();
#if PLATFORM_64BITS
#ifdef _AMD64_
#if defined(_AMD64_)
__faststorefence();
#elif defined(_IA64_)
__mf();
#elif defined(_ARM64_)
__dmb(_ARM64_BARRIER_ISH);
#else
#error "Invalid platform."
#endif
@@ -243,7 +249,11 @@ void Win32Platform::MemoryBarrier()
void Win32Platform::Prefetch(void const* ptr)
{
#if _M_ARM64
__prefetch((char const*)ptr);
#else
_mm_prefetch((char const*)ptr, _MM_HINT_T0);
#endif
}
void* Win32Platform::Allocate(uint64 size, uint64 alignment)

View File

@@ -1312,6 +1312,14 @@ Array<PlatformBase::StackFrame> WindowsPlatform::GetStackFrames(int32 skipCount,
stack.AddrBStore.Mode = AddrModeFlat;
stack.AddrStack.Offset = ctx.IntSp;
stack.AddrStack.Mode = AddrModeFlat;
#elif _M_ARM64
imageType = IMAGE_FILE_MACHINE_ARM64;
stack.AddrPC.Offset = ctx.Pc;
stack.AddrPC.Mode = AddrModeFlat;
stack.AddrFrame.Offset = ctx.Fp;
stack.AddrFrame.Mode = AddrModeFlat;
stack.AddrStack.Offset = ctx.Sp;
stack.AddrStack.Mode = AddrModeFlat;
#else
#error "Platform not supported!"
#endif

View File

@@ -1777,13 +1777,18 @@ bool InitHostfxr()
{
case PlatformType::Windows:
case PlatformType::UWP:
platformStr = PLATFORM_64BITS ? "Windows x64" : "Windows x86";
if (PLATFORM_ARCH == ArchitectureType::x64)
platformStr = "Windows x64";
else if (PLATFORM_ARCH == ArchitectureType::ARM64)
platformStr = "Windows ARM64";
else
platformStr = "Windows x86";
break;
case PlatformType::Linux:
platformStr = PLATFORM_ARCH_ARM64 ? "Linux Arm64" : PLATFORM_ARCH_ARM ? "Linux Arm32" : PLATFORM_64BITS ? "Linux x64" : "Linux x86";
platformStr = PLATFORM_ARCH_ARM64 ? "Linux ARM64" : PLATFORM_ARCH_ARM ? "Linux Arm32" : PLATFORM_64BITS ? "Linux x64" : "Linux x86";
break;
case PlatformType::Mac:
platformStr = PLATFORM_ARCH_ARM || PLATFORM_ARCH_ARM64 ? "macOS Arm64" : PLATFORM_64BITS ? "macOS x64" : "macOS x86";
platformStr = PLATFORM_ARCH_ARM || PLATFORM_ARCH_ARM64 ? "macOS ARM64" : PLATFORM_64BITS ? "macOS x64" : "macOS x86";
break;
default:;
platformStr = "";

View File

@@ -493,6 +493,66 @@ FORCE_INLINE int32 GetVTableIndex(void** vtable, int32 entriesCount, void* func)
if (op == 0x20)
return 0;
return *(byte*)funcJmp / sizeof(void*);
#elif defined(_MSC_VER) && PLATFORM_ARCH_ARM64
// For MSVC ARM64, the following thunk takes a relative jump from the function pointer to the next thunk:
// adrp xip0, offset_high
// add xip0, xip0, offset_low
// br xip0
// The last thunk contains the offset to the vtable:
// ldr xip0, [x0]
// ldr xip0, [xip0, XXX]
uint32_t* op = (uint32_t*)func;
uint32_t def = *op;
if ((*op & 0x9F000000) == 0x90000000)
{
// adrp
uint32_t imm20 = (((*op & 0x60000000) >> 29) + ((*op & 0xFFFFE0) >> 3)) << 12;
op++;
// add
def = *op;
uint32_t imm12 = (*op & 0x3FFC00) >> 10;
imm12 = (*op & 0x400000) != 0 ? (imm12 << 12) : imm12;
// br
op = (uint32_t*)(((uintptr)func & ((uintptr)-1 << 12)) + imm20 + imm12) + 1;
// ldr + offset
def = *op;
uint32_t offset = ((*op & 0x3FFC00) >> 10) * ((*op & 0x40000000) != 0 ? 8 : 4);
return offset / sizeof(void*);
}
else if ((*op & 0xBFC00000) == 0xB9400000)
{
// ldr + offset
uint32_t offset = ((*op & 0x3FFC00) >> 10) * ((*op & 0x40000000) != 0 ? 8 : 4);
op++;
// ldr + offset
def = *op;
if ((*op & 0xBFE00C00) == 0xB8400400)
{
// offset is stored in the register as is
uint32_t postindex = (*op & 0x1FF000) >> 12;
offset = postindex;
return offset / sizeof(void*);
}
else if ((*op & 0xBFE00C00) == 0xB8400C00)
{
// offset is added to the value in base register... updated to the same register
uint32_t preindex = (*op & 0x1FF000) >> 12;
offset += preindex;
return offset / sizeof(void*);
}
else if ((*op & 0xBFC00000) == 0xB9400000)
{
// 20-bit offset
offset = ((*op & 0x3FFC00) >> 10) * ((*op & 0x40000000) != 0 ? 8 : 4);
return offset / sizeof(void*);
}
CRASH;
}
#elif defined(__clang__)
// On Clang member function pointer represents the offset from the vtable begin.
return (int32)(intptr)func / sizeof(void*);

View File

@@ -6,6 +6,7 @@
#include "Engine/Core/Log.h"
#include "Engine/Core/Math/Mathd.h"
#include "Engine/Core/Math/Matrix.h"
#include "Engine/Core/Math/Plane.h"
#include "Engine/Core/Collections/Sorting.h"
#include "Engine/Platform/FileSystem.h"
#include "Engine/Tools/TextureTool/TextureTool.h"
@@ -49,7 +50,7 @@ Quaternion ToQuaternion(const ofbx::Quat& v)
return Quaternion((float)v.x, (float)v.y, (float)v.z, (float)v.w);
}
Matrix ToMatrix(const ofbx::Matrix& mat)
Matrix ToMatrix(const ofbx::DMatrix& mat)
{
Matrix result;
for (int32 i = 0; i < 16; i++)
@@ -445,7 +446,7 @@ Matrix GetOffsetMatrix(OpenFbxImporterData& data, const ofbx::Mesh* mesh, const
bool IsMeshInvalid(const ofbx::Mesh* aMesh)
{
return aMesh->getGeometry()->getVertexCount() == 0;
return aMesh->getGeometry()->getGeometryData().getPositions().count == 0;
}
bool ImportBones(OpenFbxImporterData& data, String& errorMsg)
@@ -524,56 +525,201 @@ bool ImportBones(OpenFbxImporterData& data, String& errorMsg)
return false;
}
bool ProcessMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh* aMesh, MeshData& mesh, String& errorMsg, int32 triangleStart, int32 triangleEnd)
int Triangulate(const ofbx::GeometryData& geom, const ofbx::GeometryPartition::Polygon& polygon, int* triangulatedIndices)
{
if (polygon.vertex_count < 3)
return 0;
else if (polygon.vertex_count == 3)
{
triangulatedIndices[0] = polygon.from_vertex;
triangulatedIndices[1] = polygon.from_vertex + 1;
triangulatedIndices[2] = polygon.from_vertex + 2;
return 3;
}
else if (polygon.vertex_count == 4)
{
triangulatedIndices[0] = polygon.from_vertex + 0;
triangulatedIndices[1] = polygon.from_vertex + 1;
triangulatedIndices[2] = polygon.from_vertex + 2;
triangulatedIndices[3] = polygon.from_vertex + 0;
triangulatedIndices[4] = polygon.from_vertex + 2;
triangulatedIndices[5] = polygon.from_vertex + 3;
return 6;
}
const ofbx::Vec3Attributes& positions = geom.getPositions();
Float3 normal = *(Float3*)&geom.getNormals().get(polygon.from_vertex);
// Check if the polygon is convex
int lastSign = 0;
bool isConvex = true;
for (int i = 0; i < polygon.vertex_count; i++)
{
Float3 v1 = *(Float3*)&positions.get(polygon.from_vertex + i);
Float3 v2 = *(Float3*)&positions.get(polygon.from_vertex + (i + 1) % polygon.vertex_count);
Float3 v3 = *(Float3*)&positions.get(polygon.from_vertex + (i + 2) % polygon.vertex_count);
// The winding order of all triangles must be same for polygon to be considered convex
int sign;
Float3 c = Float3::Cross(v1 - v2, v3 - v2);
if (c.LengthSquared() == 0.0f)
continue;
else if (Math::NotSameSign(c.X, normal.X) || Math::NotSameSign(c.Y, normal.Y) || Math::NotSameSign(c.Z, normal.Z))
sign = 1;
else
sign = -1;
if ((sign < 0 && lastSign > 0) || (sign > 0 && lastSign < 0))
{
isConvex = false;
break;
}
lastSign += sign;
}
// Fast-path for convex case
if (isConvex)
{
for (int i = 0; i < polygon.vertex_count - 2; i++)
{
triangulatedIndices[i * 3 + 0] = polygon.from_vertex;
triangulatedIndices[i * 3 + 1] = polygon.from_vertex + (i + 1) % polygon.vertex_count;
triangulatedIndices[i * 3 + 2] = polygon.from_vertex + (i + 2) % polygon.vertex_count;
}
return 3 * (polygon.vertex_count - 2);
}
// Setup arrays for temporary data (TODO: maybe double-linked list is more optimal?)
static Array<Float2> points;
static Array<int> indices;
static Array<int> earIndices;
points.Clear();
indices.Clear();
earIndices.Clear();
points.EnsureCapacity(polygon.vertex_count, false);
indices.EnsureCapacity(polygon.vertex_count, false);
earIndices.EnsureCapacity(3 * (polygon.vertex_count - 2), false);
// Project points to a plane, choose two arbitrary axises
const Float3 u = Float3::Cross(normal, Math::Abs(normal.X) > Math::Abs(normal.Y) ? Float3::Up : Float3::Right).GetNormalized();
const Float3 v = Float3::Cross(normal, u).GetNormalized();
for (int i = 0; i < polygon.vertex_count; i++)
{
const Float3 point = *(Float3*)&positions.get(polygon.from_vertex + i);
const Float3 projectedPoint = Float3::ProjectOnPlane(point, normal);
const Float2 pointOnPlane = Float2(
projectedPoint.X * u.X + projectedPoint.Y * u.Y + projectedPoint.Z * u.Z,
projectedPoint.X * v.X + projectedPoint.Y * v.Y + projectedPoint.Z * v.Z);
points.Add(pointOnPlane);
indices.Add(i);
}
// Triangulate non-convex polygons using simple ear-clipping algorithm (https://nils-olovsson.se/articles/ear_clipping_triangulation/)
const int maxIterations = indices.Count() * 10; // Safe guard to prevent infinite loop
int index = 0;
while (indices.Count() > 3 && index < maxIterations)
{
const int i1 = index % indices.Count();
const int i2 = (index + 1) % indices.Count();
const int i3 = (index + 2) % indices.Count();
const Float2 p1 = points[indices[i1]];
const Float2 p2 = points[indices[i2]];
const Float2 p3 = points[indices[i3]];
// TODO: Skip triangles with very sharp angles?
// Skip reflex vertices
if (Float2::Cross(p2 - p1, p3 - p1) < 0.0f)
{
index++;
continue;
}
// The triangle is considered to be an "ear" when no other points reside inside the triangle
bool isEar = true;
for (int j = 0; j < indices.Count(); j++)
{
if (j == i1 || j == i2 || j == i3)
continue;
const Float2 candidate = points[indices[j]];
if (CollisionsHelper::IsPointInTriangle(candidate, p1, p2, p3))
{
isEar = false;
break;
}
}
if (!isEar)
{
index++;
continue;
}
// Add an ear and remove the tip point from evaluation
earIndices.Add(indices[i1]);
earIndices.Add(indices[i2]);
earIndices.Add(indices[i3]);
indices.RemoveAtKeepOrder(i2);
}
for (int i = 0; i < earIndices.Count(); i++)
triangulatedIndices[i] = polygon.from_vertex + (earIndices[i] % polygon.vertex_count);
triangulatedIndices[earIndices.Count() + 0] = polygon.from_vertex + (indices[0] % polygon.vertex_count);
triangulatedIndices[earIndices.Count() + 1] = polygon.from_vertex + (indices[1] % polygon.vertex_count);
triangulatedIndices[earIndices.Count() + 2] = polygon.from_vertex + (indices[2] % polygon.vertex_count);
return 3 * (polygon.vertex_count - 2);
}
bool ProcessMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh* aMesh, MeshData& mesh, String& errorMsg, int partitionIndex)
{
PROFILE_CPU();
mesh.Name = aMesh->name;
ZoneText(*mesh.Name, mesh.Name.Length());
const int32 firstVertexOffset = triangleStart * 3;
const int32 lastVertexOffset = triangleEnd * 3;
const ofbx::Geometry* aGeometry = aMesh->getGeometry();
const int vertexCount = lastVertexOffset - firstVertexOffset + 3;
ASSERT(firstVertexOffset + vertexCount <= aGeometry->getVertexCount());
const ofbx::Vec3* vertices = aGeometry->getVertices();
const ofbx::Vec3* normals = aGeometry->getNormals();
const ofbx::Vec3* tangents = aGeometry->getTangents();
const ofbx::Vec4* colors = aGeometry->getColors();
const ofbx::Vec2* uvs = aGeometry->getUVs();
const ofbx::GeometryData& geometryData = aMesh->getGeometryData();
const ofbx::GeometryPartition& partition = geometryData.getPartition(partitionIndex);
const int vertexCount = partition.triangles_count * 3;
const ofbx::Vec3Attributes& positions = geometryData.getPositions();
const ofbx::Vec2Attributes& uvs = geometryData.getUVs();
const ofbx::Vec3Attributes& normals = geometryData.getNormals();
const ofbx::Vec3Attributes& tangents = geometryData.getTangents();
const ofbx::Vec4Attributes& colors = geometryData.getColors();
const ofbx::Skin* skin = aGeometry->getSkin();
const ofbx::BlendShape* blendShape = aGeometry->getBlendShape();
static Array<int> triangulatedIndices;
triangulatedIndices.Resize(vertexCount, false);
// Properties
const ofbx::Material* aMaterial = nullptr;
if (aMesh->getMaterialCount() > 0)
{
if (aGeometry->getMaterials())
aMaterial = aMesh->getMaterial(aGeometry->getMaterials()[triangleStart]);
else
aMaterial = aMesh->getMaterial(0);
}
aMaterial = aMesh->getMaterial(partitionIndex);
mesh.MaterialSlotIndex = data.AddMaterial(result, aMaterial);
// Vertex positions
mesh.Positions.Resize(vertexCount, false);
for (int i = 0; i < vertexCount; i++)
mesh.Positions.Get()[i] = ToFloat3(vertices[i + firstVertexOffset]);
{
int numVertsProcessed = 0;
for (int i = 0; i < partition.polygon_count; i++)
{
int numVerts = Triangulate(geometryData, partition.polygons[i], &triangulatedIndices[numVertsProcessed]);
for (int j = numVertsProcessed; j < numVertsProcessed + numVerts; j++)
mesh.Positions.Get()[j] = ToFloat3(positions.get(triangulatedIndices[j]));
numVertsProcessed += numVerts;
}
}
// Indices (dummy index buffer)
if (vertexCount % 3 != 0)
{
errorMsg = TEXT("Invalid vertex count. It must be multiple of 3.");
return true;
}
mesh.Indices.Resize(vertexCount, false);
for (int i = 0; i < vertexCount; i++)
mesh.Indices.Get()[i] = i;
// Texture coordinates
if (uvs)
if (uvs.values)
{
mesh.UVs.Resize(vertexCount, false);
for (int i = 0; i < vertexCount; i++)
mesh.UVs.Get()[i] = ToFloat2(uvs[i + firstVertexOffset]);
mesh.UVs.Get()[i] = ToFloat2(uvs.get(triangulatedIndices[i]));
if (data.ConvertRH)
{
for (int32 v = 0; v < vertexCount; v++)
@@ -582,7 +728,7 @@ bool ProcessMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh*
}
// Normals
if (data.Options.CalculateNormals || !normals)
if (data.Options.CalculateNormals || !normals.values)
{
if (mesh.GenerateNormals(data.Options.SmoothingNormalsAngle))
{
@@ -590,11 +736,11 @@ bool ProcessMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh*
return true;
}
}
else if (normals)
else if (normals.values)
{
mesh.Normals.Resize(vertexCount, false);
for (int i = 0; i < vertexCount; i++)
mesh.Normals.Get()[i] = ToFloat3(normals[i + firstVertexOffset]);
mesh.Normals.Get()[i] = ToFloat3(normals.get(triangulatedIndices[i]));
if (data.ConvertRH)
{
// Mirror normals along the Z axis
@@ -604,15 +750,15 @@ bool ProcessMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh*
}
// Tangents
if ((data.Options.CalculateTangents || !tangents) && mesh.UVs.HasItems())
if ((data.Options.CalculateTangents || !tangents.values) && mesh.UVs.HasItems())
{
// Generated after full mesh data conversion
}
else if (tangents)
else if (tangents.values)
{
mesh.Tangents.Resize(vertexCount, false);
for (int i = 0; i < vertexCount; i++)
mesh.Tangents.Get()[i] = ToFloat3(tangents[i + firstVertexOffset]);
mesh.Tangents.Get()[i] = ToFloat3(tangents.get(triangulatedIndices[i]));
if (data.ConvertRH)
{
// Mirror tangents along the Z axis
@@ -658,12 +804,12 @@ bool ProcessMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh*
}
// Check if has that channel texcoords
const auto lightmapUVs = aGeometry->getUVs(inputChannelIndex);
if (lightmapUVs)
const auto lightmapUVs = geometryData.getUVs(inputChannelIndex);
if (lightmapUVs.values)
{
mesh.LightmapUVs.Resize(vertexCount, false);
for (int i = 0; i < vertexCount; i++)
mesh.LightmapUVs.Get()[i] = ToFloat2(lightmapUVs[i + firstVertexOffset]);
mesh.LightmapUVs.Get()[i] = ToFloat2(lightmapUVs.get(triangulatedIndices[i]));
if (data.ConvertRH)
{
for (int32 v = 0; v < vertexCount; v++)
@@ -677,11 +823,11 @@ bool ProcessMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh*
}
// Vertex Colors
if (data.Options.ImportVertexColors && colors)
if (data.Options.ImportVertexColors && colors.values)
{
mesh.Colors.Resize(vertexCount, false);
for (int i = 0; i < vertexCount; i++)
mesh.Colors.Get()[i] = ToColor(colors[i + firstVertexOffset]);
mesh.Colors.Get()[i] = ToColor(colors.get(triangulatedIndices[i]));
}
// Blend Indices and Blend Weights
@@ -718,7 +864,7 @@ bool ProcessMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh*
const double* clusterWeights = cluster->getWeights();
for (int j = 0; j < cluster->getIndicesCount(); j++)
{
int vtxIndex = clusterIndices[j] - firstVertexOffset;
int vtxIndex = clusterIndices[j];
float vtxWeight = (float)clusterWeights[j];
if (vtxWeight <= 0 || vtxIndex < 0 || vtxIndex >= vertexCount)
continue;
@@ -762,9 +908,9 @@ bool ProcessMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh*
continue;
const ofbx::Shape* shape = channel->getShape(targetShapeCount - 1);
if (shape->getVertexCount() != aGeometry->getVertexCount())
if (shape->getVertexCount() != vertexCount)
{
LOG(Error, "Blend shape '{0}' in mesh '{1}' has different amount of vertices ({2}) than mesh ({3})", String(shape->name), mesh.Name, shape->getVertexCount(), aGeometry->getVertexCount());
LOG(Error, "Blend shape '{0}' in mesh '{1}' has different amount of vertices ({2}) than mesh ({3})", String(shape->name), mesh.Name, shape->getVertexCount(), vertexCount);
continue;
}
@@ -779,14 +925,14 @@ bool ProcessMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh*
auto shapeVertices = shape->getVertices();
for (int32 i = 0; i < blendShapeData.Vertices.Count(); i++)
{
auto delta = ToFloat3(shapeVertices[i + firstVertexOffset]) - mesh.Positions.Get()[i];
auto delta = ToFloat3(shapeVertices[i]) - mesh.Positions.Get()[i];
blendShapeData.Vertices.Get()[i].PositionDelta = delta;
}
auto shapeNormals = shape->getNormals();
for (int32 i = 0; i < blendShapeData.Vertices.Count(); i++)
{
auto delta = ToFloat3(shapeNormals[i + firstVertexOffset]);
auto delta = ToFloat3(shapeNormals[i]);
if (data.ConvertRH)
{
// Mirror normals along the Z axis
@@ -820,7 +966,7 @@ bool ProcessMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh*
Swap(mesh.Indices.Get()[i], mesh.Indices.Get()[i + 2]);
}
if ((data.Options.CalculateTangents || !tangents) && mesh.UVs.HasItems())
if ((data.Options.CalculateTangents || !tangents.values) && mesh.UVs.HasItems())
{
if (mesh.GenerateTangents(data.Options.SmoothingTangentsAngle))
{
@@ -858,7 +1004,7 @@ bool ProcessMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh*
return false;
}
bool ImportMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh* aMesh, String& errorMsg, int32 triangleStart, int32 triangleEnd)
bool ImportMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh* aMesh, String& errorMsg, int partitionIndex)
{
PROFILE_CPU();
@@ -899,7 +1045,7 @@ bool ImportMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh*
// Import mesh data
MeshData* meshData = New<MeshData>();
if (ProcessMesh(result, data, aMesh, *meshData, errorMsg, triangleStart, triangleEnd))
if (ProcessMesh(result, data, aMesh, *meshData, errorMsg, partitionIndex))
return true;
// Link mesh
@@ -917,35 +1063,17 @@ bool ImportMesh(int32 index, ModelData& result, OpenFbxImporterData& data, Strin
{
const auto aMesh = data.Scene->getMesh(index);
const auto aGeometry = aMesh->getGeometry();
const auto trianglesCount = aGeometry->getVertexCount() / 3;
if (IsMeshInvalid(aMesh))
return false;
if (aMesh->getMaterialCount() < 2 || !aGeometry->getMaterials())
const auto& geomData = aMesh->getGeometryData();
for (int i = 0; i < geomData.getPartitionCount(); i++)
{
// Fast path if mesh is using single material for all triangles
if (ImportMesh(result, data, aMesh, errorMsg, 0, trianglesCount - 1))
return true;
}
else
{
// Create mesh for each sequence of triangles that share the same material
const auto materials = aGeometry->getMaterials();
int32 rangeStart = 0;
int32 rangeStartVal = materials[rangeStart];
for (int32 triangleIndex = 1; triangleIndex < trianglesCount; triangleIndex++)
{
if (rangeStartVal != materials[triangleIndex])
{
if (ImportMesh(result, data, aMesh, errorMsg, rangeStart, triangleIndex - 1))
return true;
const auto& partition = geomData.getPartition(i);
if (partition.polygon_count == 0)
continue;
// Start a new range
rangeStart = triangleIndex;
rangeStartVal = materials[triangleIndex];
}
}
if (ImportMesh(result, data, aMesh, errorMsg, rangeStart, trianglesCount - 1))
if (ImportMesh(result, data, aMesh, errorMsg, i))
return true;
}
return false;
@@ -962,24 +1090,24 @@ struct AnimInfo
struct Frame
{
ofbx::Vec3 Translation;
ofbx::Vec3 Rotation;
ofbx::Vec3 Scaling;
ofbx::DVec3 Translation;
ofbx::DVec3 Rotation;
ofbx::DVec3 Scaling;
};
void ExtractKeyframePosition(const ofbx::Object* bone, ofbx::Vec3& trans, const Frame& localFrame, Float3& keyframe)
void ExtractKeyframePosition(const ofbx::Object* bone, ofbx::DVec3& trans, const Frame& localFrame, Float3& keyframe)
{
const Matrix frameTrans = ToMatrix(bone->evalLocal(trans, localFrame.Rotation, localFrame.Scaling));
keyframe = frameTrans.GetTranslation();
}
void ExtractKeyframeRotation(const ofbx::Object* bone, ofbx::Vec3& trans, const Frame& localFrame, Quaternion& keyframe)
void ExtractKeyframeRotation(const ofbx::Object* bone, ofbx::DVec3& trans, const Frame& localFrame, Quaternion& keyframe)
{
const Matrix frameTrans = ToMatrix(bone->evalLocal(localFrame.Translation, trans, { 1.0, 1.0, 1.0 }));
Quaternion::RotationMatrix(frameTrans, keyframe);
}
void ExtractKeyframeScale(const ofbx::Object* bone, ofbx::Vec3& trans, const Frame& localFrame, Float3& keyframe)
void ExtractKeyframeScale(const ofbx::Object* bone, ofbx::DVec3& trans, const Frame& localFrame, Float3& keyframe)
{
// Fix empty scale case
if (Math::IsZero(trans.x) && Math::IsZero(trans.y) && Math::IsZero(trans.z))
@@ -990,7 +1118,7 @@ void ExtractKeyframeScale(const ofbx::Object* bone, ofbx::Vec3& trans, const Fra
}
template<typename T>
void ImportCurve(const ofbx::AnimationCurveNode* curveNode, LinearCurve<T>& curve, AnimInfo& info, void (*ExtractKeyframe)(const ofbx::Object*, ofbx::Vec3&, const Frame&, T&))
void ImportCurve(const ofbx::AnimationCurveNode* curveNode, LinearCurve<T>& curve, AnimInfo& info, void (*ExtractKeyframe)(const ofbx::Object*, ofbx::DVec3&, const Frame&, T&))
{
if (curveNode == nullptr)
return;
@@ -1008,7 +1136,7 @@ void ImportCurve(const ofbx::AnimationCurveNode* curveNode, LinearCurve<T>& curv
key.Time = (float)i;
ofbx::Vec3 trans = curveNode->getNodeLocalTransform(t);
ofbx::DVec3 trans = curveNode->getNodeLocalTransform(t);
ExtractKeyframe(bone, trans, localFrame, key.Value);
}
}
@@ -1125,10 +1253,9 @@ bool ModelTool::ImportDataOpenFBX(const String& path, ModelData& data, Options&
errorMsg = TEXT("Cannot load file.");
return true;
}
ofbx::u64 loadFlags = 0;
ofbx::u16 loadFlags = 0;
if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry))
{
loadFlags |= (ofbx::u64)ofbx::LoadFlags::TRIANGULATE;
if (!options.ImportBlendShapes)
loadFlags |= (ofbx::u64)ofbx::LoadFlags::IGNORE_BLEND_SHAPES;
}

View File

@@ -197,7 +197,7 @@ namespace FlaxEngine.GUI
textBlock.Range = new TextRange
{
StartIndex = start + line.FirstCharIndex,
EndIndex = start + line.LastCharIndex,
EndIndex = start + line.LastCharIndex + 1,
};
if (i != 0)
{

View File

@@ -56,6 +56,9 @@ public class FlaxEditor : EngineTarget
case TargetArchitecture.x86:
options.OutputFolder = Path.Combine(options.WorkingDirectory, "Binaries", "Editor", "Win32", options.Configuration.ToString());
break;
case TargetArchitecture.ARM64:
options.OutputFolder = Path.Combine(options.WorkingDirectory, "Binaries", "Editor", "ARM64", options.Configuration.ToString());
break;
default: throw new InvalidArchitectureException(options.Architecture, "Not supported Editor architecture.");
}
break;

Binary file not shown.

Binary file not shown.

View File

@@ -527,46 +527,6 @@
<c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
</returns>
</member>
<member name="T:Newtonsoft.Json.Converters.ExpandoObjectConverter">
<summary>
Converts an <see cref="T:System.Dynamic.ExpandoObject"/> to and from JSON.
</summary>
</member>
<member name="M:Newtonsoft.Json.Converters.ExpandoObjectConverter.WriteJson(Newtonsoft.Json.JsonWriter,System.Object,Newtonsoft.Json.JsonSerializer)">
<summary>
Writes the JSON representation of the object.
</summary>
<param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param>
<param name="value">The value.</param>
<param name="serializer">The calling serializer.</param>
</member>
<member name="M:Newtonsoft.Json.Converters.ExpandoObjectConverter.ReadJson(Newtonsoft.Json.JsonReader,System.Type,System.Object,Newtonsoft.Json.JsonSerializer)">
<summary>
Reads the JSON representation of the object.
</summary>
<param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param>
<param name="objectType">Type of the object.</param>
<param name="existingValue">The existing value of object being read.</param>
<param name="serializer">The calling serializer.</param>
<returns>The object value.</returns>
</member>
<member name="M:Newtonsoft.Json.Converters.ExpandoObjectConverter.CanConvert(System.Type)">
<summary>
Determines whether this instance can convert the specified object type.
</summary>
<param name="objectType">Type of the object.</param>
<returns>
<c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
</returns>
</member>
<member name="P:Newtonsoft.Json.Converters.ExpandoObjectConverter.CanWrite">
<summary>
Gets a value indicating whether this <see cref="T:Newtonsoft.Json.JsonConverter"/> can write JSON.
</summary>
<value>
<c>true</c> if this <see cref="T:Newtonsoft.Json.JsonConverter"/> can write JSON; otherwise, <c>false</c>.
</value>
</member>
<member name="T:Newtonsoft.Json.Converters.IsoDateTimeConverter">
<summary>
Converts a <see cref="T:System.DateTime"/> to and from the ISO 8601 date format (e.g. <c>"2008-04-12T12:53Z"</c>).
@@ -663,38 +623,6 @@
<c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
</returns>
</member>
<member name="T:Newtonsoft.Json.Converters.RegexConverter">
<summary>
Converts a <see cref="T:System.Text.RegularExpressions.Regex"/> to and from JSON and BSON.
</summary>
</member>
<member name="M:Newtonsoft.Json.Converters.RegexConverter.WriteJson(Newtonsoft.Json.JsonWriter,System.Object,Newtonsoft.Json.JsonSerializer)">
<summary>
Writes the JSON representation of the object.
</summary>
<param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param>
<param name="value">The value.</param>
<param name="serializer">The calling serializer.</param>
</member>
<member name="M:Newtonsoft.Json.Converters.RegexConverter.ReadJson(Newtonsoft.Json.JsonReader,System.Type,System.Object,Newtonsoft.Json.JsonSerializer)">
<summary>
Reads the JSON representation of the object.
</summary>
<param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param>
<param name="objectType">Type of the object.</param>
<param name="existingValue">The existing value of object being read.</param>
<param name="serializer">The calling serializer.</param>
<returns>The object value.</returns>
</member>
<member name="M:Newtonsoft.Json.Converters.RegexConverter.CanConvert(System.Type)">
<summary>
Determines whether this instance can convert the specified object type.
</summary>
<param name="objectType">Type of the object.</param>
<returns>
<c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
</returns>
</member>
<member name="T:Newtonsoft.Json.Converters.StringEnumConverter">
<summary>
Converts an <see cref="T:System.Enum"/> to and from its name string value.
@@ -6424,15 +6352,6 @@
</summary>
<param name="propertyName">Name of the property.</param>
</member>
<member name="M:Newtonsoft.Json.Linq.JObject.GetMetaObject(System.Linq.Expressions.Expression)">
<summary>
Returns the <see cref="T:System.Dynamic.DynamicMetaObject"/> responsible for binding operations performed on this object.
</summary>
<param name="parameter">The expression tree representation of the runtime value.</param>
<returns>
The <see cref="T:System.Dynamic.DynamicMetaObject"/> to bind this object.
</returns>
</member>
<member name="T:Newtonsoft.Json.Linq.JProperty">
<summary>
Represents a JSON property.
@@ -7602,24 +7521,6 @@
<param name="settings">The <see cref="T:Newtonsoft.Json.Linq.JsonSelectSettings"/> used to select tokens.</param>
<returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the selected elements.</returns>
</member>
<member name="M:Newtonsoft.Json.Linq.JToken.GetMetaObject(System.Linq.Expressions.Expression)">
<summary>
Returns the <see cref="T:System.Dynamic.DynamicMetaObject"/> responsible for binding operations performed on this object.
</summary>
<param name="parameter">The expression tree representation of the runtime value.</param>
<returns>
The <see cref="T:System.Dynamic.DynamicMetaObject"/> to bind this object.
</returns>
</member>
<member name="M:Newtonsoft.Json.Linq.JToken.System#Dynamic#IDynamicMetaObjectProvider#GetMetaObject(System.Linq.Expressions.Expression)">
<summary>
Returns the <see cref="T:System.Dynamic.DynamicMetaObject"/> responsible for binding operations performed on this object.
</summary>
<param name="parameter">The expression tree representation of the runtime value.</param>
<returns>
The <see cref="T:System.Dynamic.DynamicMetaObject"/> to bind this object.
</returns>
</member>
<member name="M:Newtonsoft.Json.Linq.JToken.DeepClone">
<summary>
Creates a new instance of the <see cref="T:Newtonsoft.Json.Linq.JToken"/>. All child tokens are recursively cloned.
@@ -8274,15 +8175,6 @@
A <see cref="T:System.String"/> that represents this instance.
</returns>
</member>
<member name="M:Newtonsoft.Json.Linq.JValue.GetMetaObject(System.Linq.Expressions.Expression)">
<summary>
Returns the <see cref="T:System.Dynamic.DynamicMetaObject"/> responsible for binding operations performed on this object.
</summary>
<param name="parameter">The expression tree representation of the runtime value.</param>
<returns>
The <see cref="T:System.Dynamic.DynamicMetaObject"/> to bind this object.
</returns>
</member>
<member name="M:Newtonsoft.Json.Linq.JValue.CompareTo(Newtonsoft.Json.Linq.JValue)">
<summary>
Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
@@ -8733,13 +8625,6 @@
<param name="objectType">Type of the object.</param>
<returns>A <see cref="T:Newtonsoft.Json.Serialization.JsonISerializableContract"/> for the given type.</returns>
</member>
<member name="M:Newtonsoft.Json.Serialization.DefaultContractResolver.CreateDynamicContract(System.Type)">
<summary>
Creates a <see cref="T:Newtonsoft.Json.Serialization.JsonDynamicContract"/> for the given type.
</summary>
<param name="objectType">Type of the object.</param>
<returns>A <see cref="T:Newtonsoft.Json.Serialization.JsonDynamicContract"/> for the given type.</returns>
</member>
<member name="M:Newtonsoft.Json.Serialization.DefaultContractResolver.CreateStringContract(System.Type)">
<summary>
Creates a <see cref="T:Newtonsoft.Json.Serialization.JsonStringContract"/> for the given type.
@@ -8845,31 +8730,6 @@
<param name="assemblyName">Specifies the <see cref="T:System.Reflection.Assembly"/> name of the serialized object.</param>
<param name="typeName">Specifies the <see cref="T:System.Type"/> name of the serialized object.</param>
</member>
<member name="T:Newtonsoft.Json.Serialization.DynamicValueProvider">
<summary>
Get and set values for a <see cref="T:System.Reflection.MemberInfo"/> using dynamic methods.
</summary>
</member>
<member name="M:Newtonsoft.Json.Serialization.DynamicValueProvider.#ctor(System.Reflection.MemberInfo)">
<summary>
Initializes a new instance of the <see cref="T:Newtonsoft.Json.Serialization.DynamicValueProvider"/> class.
</summary>
<param name="memberInfo">The member info.</param>
</member>
<member name="M:Newtonsoft.Json.Serialization.DynamicValueProvider.SetValue(System.Object,System.Object)">
<summary>
Sets the value.
</summary>
<param name="target">The target to set the value on.</param>
<param name="value">The value to set on the target.</param>
</member>
<member name="M:Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(System.Object)">
<summary>
Gets the value.
</summary>
<param name="target">The target to get the value from.</param>
<returns>The value.</returns>
</member>
<member name="T:Newtonsoft.Json.Serialization.ErrorContext">
<summary>
Provides information surrounding an error.
@@ -8929,31 +8789,6 @@
<param name="currentObject">The current object.</param>
<param name="errorContext">The error context.</param>
</member>
<member name="T:Newtonsoft.Json.Serialization.ExpressionValueProvider">
<summary>
Get and set values for a <see cref="T:System.Reflection.MemberInfo"/> using dynamic methods.
</summary>
</member>
<member name="M:Newtonsoft.Json.Serialization.ExpressionValueProvider.#ctor(System.Reflection.MemberInfo)">
<summary>
Initializes a new instance of the <see cref="T:Newtonsoft.Json.Serialization.ExpressionValueProvider"/> class.
</summary>
<param name="memberInfo">The member info.</param>
</member>
<member name="M:Newtonsoft.Json.Serialization.ExpressionValueProvider.SetValue(System.Object,System.Object)">
<summary>
Sets the value.
</summary>
<param name="target">The target to set the value on.</param>
<param name="value">The value to set on the target.</param>
</member>
<member name="M:Newtonsoft.Json.Serialization.ExpressionValueProvider.GetValue(System.Object)">
<summary>
Gets the value.
</summary>
<param name="target">The target to get the value from.</param>
<returns>The value.</returns>
</member>
<member name="T:Newtonsoft.Json.Serialization.IAttributeProvider">
<summary>
Provides methods to get attributes.
@@ -9287,29 +9122,6 @@
</summary>
<param name="underlyingType">The underlying type for the contract.</param>
</member>
<member name="T:Newtonsoft.Json.Serialization.JsonDynamicContract">
<summary>
Contract details for a <see cref="T:System.Type"/> used by the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
</summary>
</member>
<member name="P:Newtonsoft.Json.Serialization.JsonDynamicContract.Properties">
<summary>
Gets the object's properties.
</summary>
<value>The object's properties.</value>
</member>
<member name="P:Newtonsoft.Json.Serialization.JsonDynamicContract.PropertyNameResolver">
<summary>
Gets or sets the property name resolver.
</summary>
<value>The property name resolver.</value>
</member>
<member name="M:Newtonsoft.Json.Serialization.JsonDynamicContract.#ctor(System.Type)">
<summary>
Initializes a new instance of the <see cref="T:Newtonsoft.Json.Serialization.JsonDynamicContract"/> class.
</summary>
<param name="underlyingType">The underlying type for the contract.</param>
</member>
<member name="T:Newtonsoft.Json.Serialization.JsonISerializableContract">
<summary>
Contract details for a <see cref="T:System.Type"/> used by the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
@@ -10016,32 +9828,6 @@
is returned if assignable to the target type.
</returns>
</member>
<member name="M:Newtonsoft.Json.Utilities.DynamicProxyMetaObject`1.CallMethodWithResult(System.String,System.Dynamic.DynamicMetaObjectBinder,System.Collections.Generic.IEnumerable{System.Linq.Expressions.Expression},Newtonsoft.Json.Utilities.DynamicProxyMetaObject{`0}.Fallback,Newtonsoft.Json.Utilities.DynamicProxyMetaObject{`0}.Fallback)">
<summary>
Helper method for generating a MetaObject which calls a
specific method on Dynamic that returns a result
</summary>
</member>
<member name="M:Newtonsoft.Json.Utilities.DynamicProxyMetaObject`1.CallMethodReturnLast(System.String,System.Dynamic.DynamicMetaObjectBinder,System.Collections.Generic.IEnumerable{System.Linq.Expressions.Expression},Newtonsoft.Json.Utilities.DynamicProxyMetaObject{`0}.Fallback)">
<summary>
Helper method for generating a MetaObject which calls a
specific method on Dynamic, but uses one of the arguments for
the result.
</summary>
</member>
<member name="M:Newtonsoft.Json.Utilities.DynamicProxyMetaObject`1.CallMethodNoResult(System.String,System.Dynamic.DynamicMetaObjectBinder,System.Linq.Expressions.Expression[],Newtonsoft.Json.Utilities.DynamicProxyMetaObject{`0}.Fallback)">
<summary>
Helper method for generating a MetaObject which calls a
specific method on Dynamic, but uses one of the arguments for
the result.
</summary>
</member>
<member name="M:Newtonsoft.Json.Utilities.DynamicProxyMetaObject`1.GetRestrictions">
<summary>
Returns a Restrictions object which includes our current restrictions merged
with a restriction limiting our type
</summary>
</member>
<member name="T:Newtonsoft.Json.Utilities.ImmutableCollectionsUtils">
<summary>
Helper class for serializing immutable collections.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/DirectXMesh.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/DirectXMesh.pdb (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/DirectXTex.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/DirectXTex.pdb (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/FastXml_64.pdb (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/GenericCodeGen.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/HLSL.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/LowLevelAABB_64.pdb (Stored with Git LFS) vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/LowLevel_64.pdb (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/MachineIndependent.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/NvCloth_x64.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/NvCloth_x64.pdb (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/OGLCompiler.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/OSDependent.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/OpenAL32.dll (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/OpenAL32.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/PhysXTask_64.pdb (Stored with Git LFS) vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/PhysX_static_64.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/PhysX_static_64.pdb (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/SPIRV-Tools-opt.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/SPIRV-Tools.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/SPIRV.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/SceneQuery_64.pdb (Stored with Git LFS) vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/UVAtlas.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/UVAtlas.pdb (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/assimp-vc140-md.dll (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/assimp-vc140-md.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/astcenc.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/d3dcompiler_47.dll (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/d3dcompiler_47.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/dbghelp.dll (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/dbghelp.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/dxcompiler.dll (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/dxcompiler.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/dxil.dll (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/freetype.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/freetype.pdb (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/glslang.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/libcurl.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/libogg_static.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
Source/Platforms/Windows/Binaries/ThirdParty/ARM64/libvorbis_static.lib (Stored with Git LFS) vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More