Merge remote-tracking branch 'upstream/development' into hultonha_LY-69118_lambda_crash
Signed-off-by: hultonha <hultonha@amazon.co.uk>
This commit is contained in:
@@ -43,11 +43,36 @@ namespace Platform
|
||||
}
|
||||
return physicalDeviceList;
|
||||
}
|
||||
|
||||
void PresentInternal(id <MTLCommandBuffer> mtlCommandBuffer, id<CAMetalDrawable> drawable, float syncInterval)
|
||||
|
||||
float GetRefreshRate()
|
||||
{
|
||||
AZ_UNUSED(syncInterval);
|
||||
[mtlCommandBuffer presentDrawable:drawable];
|
||||
CGDirectDisplayID display = CGMainDisplayID();
|
||||
CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(display);
|
||||
return CGDisplayModeGetRefreshRate(currentMode);
|
||||
}
|
||||
|
||||
void PresentInternal(id <MTLCommandBuffer> mtlCommandBuffer, id<CAMetalDrawable> drawable, float syncInterval, float refreshRate)
|
||||
{
|
||||
bool framePresented = false;
|
||||
|
||||
//seconds per frame (1/refreshrate) * num frames (sync interval)
|
||||
float presentAfterMinimumDuration = syncInterval / refreshRate;
|
||||
|
||||
#if defined(__MAC_10_15_4)
|
||||
if(@available(macOS 10.15.4, *))
|
||||
{
|
||||
if(presentAfterMinimumDuration > 0.0f)
|
||||
{
|
||||
[mtlCommandBuffer presentDrawable:drawable afterMinimumDuration:presentAfterMinimumDuration];
|
||||
framePresented = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!framePresented)
|
||||
{
|
||||
[mtlCommandBuffer presentDrawable:drawable];
|
||||
}
|
||||
}
|
||||
|
||||
CGRect GetScreenBounds(NativeWindowType* nativeWindow)
|
||||
|
||||
@@ -29,13 +29,19 @@ namespace Platform
|
||||
return physicalDeviceList;
|
||||
}
|
||||
|
||||
void PresentInternal(id <MTLCommandBuffer> mtlCommandBuffer, id<CAMetalDrawable> drawable, float syncInterval)
|
||||
float GetRefreshRate()
|
||||
{
|
||||
bool hasPresentAfterMinimumDuration = [drawable respondsToSelector:@selector(presentAfterMinimumDuration:)];
|
||||
|
||||
if (hasPresentAfterMinimumDuration && syncInterval > 0.0f)
|
||||
NativeScreenType* nativeScreen = [NativeScreenType mainScreen];
|
||||
return [nativeScreen maximumFramesPerSecond];
|
||||
}
|
||||
|
||||
void PresentInternal(id <MTLCommandBuffer> mtlCommandBuffer, id<CAMetalDrawable> drawable, float syncInterval, float refreshRate)
|
||||
{
|
||||
//seconds per frame (1/refreshrate) * num frames (sync interval)
|
||||
float presentAfterMinimumDuration = syncInterval / refreshRate;
|
||||
if (hasPresentAfterMinimumDuration > 0.0f)
|
||||
{
|
||||
[mtlCommandBuffer presentDrawable:drawable afterMinimumDuration:syncInterval];
|
||||
[mtlCommandBuffer presentDrawable:drawable afterMinimumDuration:presentAfterMinimumDuration];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -19,8 +19,9 @@ namespace Platform
|
||||
CGFloat GetScreenScale();
|
||||
void AttachViewController(NativeWindowType* nativeWindow, NativeViewControllerType* viewController, RHIMetalView* metalView);
|
||||
void UnAttachViewController(NativeWindowType* nativeWindow, NativeViewControllerType* viewController);
|
||||
void PresentInternal(id <MTLCommandBuffer> mtlCommandBuffer, id<CAMetalDrawable> drawable, float syncInterval);
|
||||
void PresentInternal(id <MTLCommandBuffer> mtlCommandBuffer, id<CAMetalDrawable> drawable, float syncInterval, float refreshRate);
|
||||
void ResizeInternal(RHIMetalView* metalView, CGSize viewSize);
|
||||
float GetRefreshRate();
|
||||
RHIMetalView* GetMetalView(NativeWindowType* nativeWindow);
|
||||
}
|
||||
|
||||
@@ -73,6 +74,15 @@ namespace AZ
|
||||
AddSubView();
|
||||
}
|
||||
|
||||
m_refreshRate = Platform::GetRefreshRate();
|
||||
|
||||
//Assume 60hz if 0 is returned.
|
||||
//Internal OSX displays have 'flexible' refresh rates, with a max of 60Hz - but report 0hz
|
||||
if (m_refreshRate < 0.1f)
|
||||
{
|
||||
m_refreshRate = 60.0f;
|
||||
}
|
||||
|
||||
m_drawables.resize(descriptor.m_dimensions.m_imageCount);
|
||||
|
||||
if (nativeDimensions)
|
||||
@@ -148,10 +158,9 @@ namespace AZ
|
||||
uint32_t SwapChain::PresentInternal()
|
||||
{
|
||||
const uint32_t currentImageIndex = GetCurrentImageIndex();
|
||||
//GFX TODO][ATOM-432] - Hardcoding to 30fps for now. Only used by ios. This needs to be driven by higher level code.
|
||||
float syncInterval = 1.0f/30.0f;
|
||||
|
||||
//Preset the drawable
|
||||
Platform::PresentInternal(m_mtlCommandBuffer, m_drawables[currentImageIndex], syncInterval);
|
||||
Platform::PresentInternal(m_mtlCommandBuffer, m_drawables[currentImageIndex], GetDescriptor().m_verticalSyncInterval, m_refreshRate);
|
||||
|
||||
[m_drawables[currentImageIndex] release];
|
||||
m_drawables[currentImageIndex] = nil;
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace AZ
|
||||
id<MTLDevice> m_mtlDevice = nil;
|
||||
NativeWindowType* m_nativeWindow = nullptr;
|
||||
AZStd::vector<id<CAMetalDrawable>> m_drawables;
|
||||
float m_refreshRate = 0.0f;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,8 +58,8 @@ namespace AZ
|
||||
RHI::ShaderResourceGroupPoolDescriptor poolDescriptor;
|
||||
poolDescriptor.m_layout = shaderAsset.FindShaderResourceGroupLayout(srgName, supervariantIndex).get();
|
||||
|
||||
|
||||
m_pool->SetName(srgName);
|
||||
m_pool->SetName(AZ::Name(AZStd::string::format("%s_%s",shaderAsset.GetName().GetCStr(),srgName.GetCStr())));
|
||||
|
||||
const RHI::ResultCode resultCode = m_pool->Init(*device, poolDescriptor);
|
||||
return resultCode;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ void OnVsyncIntervalChanged(uint32_t const& interval)
|
||||
// NOTE: On change, broadcasts the new requested vsync interval to all windows.
|
||||
// The value of the vsync interval is constrained between 0 and 4
|
||||
// Vsync intervals greater than 1 are not currently supported on the Vulkan RHI (see #2061 for discussion)
|
||||
AZ_CVAR(uint32_t, rpi_vsync_interval, 0, OnVsyncIntervalChanged, AZ::ConsoleFunctorFlags::Null, "Set swapchain vsync interval");
|
||||
AZ_CVAR(uint32_t, rpi_vsync_interval, 1, OnVsyncIntervalChanged, AZ::ConsoleFunctorFlags::Null, "Set swapchain vsync interval");
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"$type": "MotionGroup",
|
||||
"name": "idle_cwby_01",
|
||||
"selectedRootBone": "RootNode.Reference",
|
||||
"id": "{492E8A35-2647-581F-A701-F1D2A9FBB979}",
|
||||
"rules": {
|
||||
"rules": [
|
||||
{
|
||||
"$type": "MetaDataRule",
|
||||
"commands": [
|
||||
{
|
||||
"$type": "CommandSystem::CommandAdjustMotion",
|
||||
"dirtyFlag": {},
|
||||
"motionExtractionFlags": {},
|
||||
"name": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "Sync",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "GameState",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "GameState",
|
||||
"eventDatas": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "MotionSamplingRule"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"$type": "MotionGroup",
|
||||
"name": "reload",
|
||||
"selectedRootBone": "RootNode.Reference",
|
||||
"id": "{28092685-3550-5583-A666-CD60018AB2E9}",
|
||||
"rules": {
|
||||
"rules": [
|
||||
{
|
||||
"$type": "MetaDataRule",
|
||||
"commands": [
|
||||
{
|
||||
"$type": "CommandSystem::CommandAdjustMotion",
|
||||
"dirtyFlag": {},
|
||||
"motionExtractionFlags": {},
|
||||
"name": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "Sync",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "ReloadEvent",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "ReloadEvent",
|
||||
"startTime": 0.509211003780365,
|
||||
"endTime": 0.509211003780365,
|
||||
"eventDatas": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "ReloadEvent",
|
||||
"startTime": 1.2446810007095338,
|
||||
"endTime": 1.2446810007095338,
|
||||
"eventDatas": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "ReloadEvent",
|
||||
"startTime": 1.4295190572738648,
|
||||
"endTime": 1.4295190572738648,
|
||||
"eventDatas": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "MotionSamplingRule"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"$type": "MotionGroup",
|
||||
"name": "run",
|
||||
"selectedRootBone": "RootNode.Reference",
|
||||
"id": "{7D6889F1-6536-57B6-8B02-93C815D1ADA9}",
|
||||
"rules": {
|
||||
"rules": [
|
||||
{
|
||||
"$type": "MetaDataRule",
|
||||
"commands": [
|
||||
{
|
||||
"$type": "CommandSystem::CommandAdjustMotion",
|
||||
"dirtyFlag": {},
|
||||
"motionExtractionFlags": {},
|
||||
"name": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "Sync",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "Sync",
|
||||
"startTime": 0.3396751880645752,
|
||||
"endTime": 0.3396751880645752,
|
||||
"eventDatas": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "Sync",
|
||||
"startTime": 0.6319156885147095,
|
||||
"endTime": 0.6319156885147095,
|
||||
"eventDatas": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "GameState",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "GameState",
|
||||
"eventDatas": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "MotionSamplingRule"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"$type": "MotionGroup",
|
||||
"name": "shootrecoil",
|
||||
"selectedRootBone": "RootNode.Reference",
|
||||
"id": "{A1DC3BB2-3324-50F3-8C4B-BBFB61623129}",
|
||||
"rules": {
|
||||
"rules": [
|
||||
{
|
||||
"$type": "MetaDataRule",
|
||||
"commands": [
|
||||
{
|
||||
"$type": "CommandSystem::CommandAdjustMotion",
|
||||
"dirtyFlag": {},
|
||||
"motionExtractionFlags": {},
|
||||
"name": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "Sync",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "RecoilEvent",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "RecoilEvent",
|
||||
"startTime": 0.23250000178813935,
|
||||
"endTime": 0.23250000178813935,
|
||||
"eventDatas": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "MotionSamplingRule"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"$type": "MotionGroup",
|
||||
"name": "strafeback",
|
||||
"selectedRootBone": "RootNode.Reference",
|
||||
"id": "{CA0EF712-DA36-5DA8-B474-207BD250CF2F}",
|
||||
"rules": {
|
||||
"rules": [
|
||||
{
|
||||
"$type": "MetaDataRule",
|
||||
"commands": [
|
||||
{
|
||||
"$type": "CommandSystem::CommandAdjustMotion",
|
||||
"dirtyFlag": {},
|
||||
"motionExtractionFlags": {},
|
||||
"name": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "Sync",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "GameEvents",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "GameEvents",
|
||||
"eventDatas": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "MotionSamplingRule"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"$type": "MotionGroup",
|
||||
"name": "strafebackl",
|
||||
"selectedRootBone": "RootNode.Reference",
|
||||
"id": "{9433F0E6-EA1A-5473-AA21-EE4DC45387C1}",
|
||||
"rules": {
|
||||
"rules": [
|
||||
{
|
||||
"$type": "MetaDataRule",
|
||||
"commands": [
|
||||
{
|
||||
"$type": "CommandSystem::CommandAdjustMotion",
|
||||
"dirtyFlag": {},
|
||||
"motionExtractionFlags": {},
|
||||
"name": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "Sync",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "GameState",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "GameState",
|
||||
"eventDatas": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "MotionSamplingRule"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"$type": "MotionGroup",
|
||||
"name": "strafebackr",
|
||||
"selectedRootBone": "RootNode.Reference",
|
||||
"id": "{5392AC3D-FF18-51F5-984E-248CAAF09F2E}",
|
||||
"rules": {
|
||||
"rules": [
|
||||
{
|
||||
"$type": "MetaDataRule",
|
||||
"commands": [
|
||||
{
|
||||
"$type": "CommandSystem::CommandAdjustMotion",
|
||||
"dirtyFlag": {},
|
||||
"motionExtractionFlags": {},
|
||||
"name": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "Sync",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "GameState",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "GameState",
|
||||
"eventDatas": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "MotionSamplingRule"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"$type": "MotionGroup",
|
||||
"name": "strafeforward",
|
||||
"selectedRootBone": "RootNode.Reference",
|
||||
"id": "{2FB879C6-B3FB-5BD8-B52B-1012000351C2}",
|
||||
"rules": {
|
||||
"rules": [
|
||||
{
|
||||
"$type": "MetaDataRule",
|
||||
"commands": [
|
||||
{
|
||||
"$type": "CommandSystem::CommandAdjustMotion",
|
||||
"dirtyFlag": {},
|
||||
"motionExtractionFlags": {},
|
||||
"name": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "Sync",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "Sync",
|
||||
"startTime": 0.2708907127380371,
|
||||
"endTime": 0.2708907127380371,
|
||||
"eventDatas": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "Sync",
|
||||
"startTime": 0.9699265956878662,
|
||||
"endTime": 0.9699265956878662,
|
||||
"eventDatas": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "GameState",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "GameState",
|
||||
"eventDatas": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "MotionSamplingRule"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"$type": "MotionGroup",
|
||||
"name": "strafeforwardl",
|
||||
"selectedRootBone": "RootNode.Reference",
|
||||
"id": "{2D945D52-C313-57A3-B722-C6402ACC3506}",
|
||||
"rules": {
|
||||
"rules": [
|
||||
{
|
||||
"$type": "MetaDataRule",
|
||||
"commands": [
|
||||
{
|
||||
"$type": "CommandSystem::CommandAdjustMotion",
|
||||
"dirtyFlag": {},
|
||||
"motionExtractionFlags": {},
|
||||
"name": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "Sync",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "GameState",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "GameState",
|
||||
"eventDatas": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "MotionSamplingRule"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"$type": "MotionGroup",
|
||||
"name": "strafeforwardr",
|
||||
"selectedRootBone": "RootNode.Reference",
|
||||
"id": "{3E691B9F-C0D7-5BFD-BBBC-50BAE737886E}",
|
||||
"rules": {
|
||||
"rules": [
|
||||
{
|
||||
"$type": "MetaDataRule",
|
||||
"commands": [
|
||||
{
|
||||
"$type": "CommandSystem::CommandAdjustMotion",
|
||||
"dirtyFlag": {},
|
||||
"motionExtractionFlags": {},
|
||||
"name": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "Sync",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "GameState",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "GameState",
|
||||
"eventDatas": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "MotionSamplingRule"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"$type": "MotionGroup",
|
||||
"name": "strafeinplace",
|
||||
"selectedRootBone": "RootNode.Reference",
|
||||
"id": "{A2686CFC-D49B-5468-AE9F-E3F84FA75C6D}",
|
||||
"rules": {
|
||||
"rules": [
|
||||
{
|
||||
"$type": "MetaDataRule",
|
||||
"commands": [
|
||||
{
|
||||
"$type": "CommandSystem::CommandAdjustMotion",
|
||||
"dirtyFlag": {},
|
||||
"motionExtractionFlags": {},
|
||||
"name": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "Sync",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "GameState",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "GameState",
|
||||
"eventDatas": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "MotionSamplingRule"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"$type": "MotionGroup",
|
||||
"name": "strafeleft",
|
||||
"selectedRootBone": "RootNode.Reference",
|
||||
"id": "{2093C7DF-0C51-5C2B-B763-4DC1CC81D10E}",
|
||||
"rules": {
|
||||
"rules": [
|
||||
{
|
||||
"$type": "MetaDataRule",
|
||||
"commands": [
|
||||
{
|
||||
"$type": "CommandSystem::CommandAdjustMotion",
|
||||
"dirtyFlag": {},
|
||||
"motionExtractionFlags": {},
|
||||
"name": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "Sync",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "GameState",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "GameState",
|
||||
"eventDatas": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "MotionSamplingRule"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"$type": "MotionGroup",
|
||||
"name": "straferight",
|
||||
"selectedRootBone": "RootNode.Reference",
|
||||
"id": "{CE0E45E9-4B8C-5340-9521-B6290BAB24FC}",
|
||||
"rules": {
|
||||
"rules": [
|
||||
{
|
||||
"$type": "MetaDataRule",
|
||||
"commands": [
|
||||
{
|
||||
"$type": "CommandSystem::CommandAdjustMotion",
|
||||
"dirtyFlag": {},
|
||||
"motionExtractionFlags": {},
|
||||
"name": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "Sync",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEventTrack",
|
||||
"eventTrackName": "GameState",
|
||||
"eventTrackIndex": {},
|
||||
"isEnabled": {}
|
||||
},
|
||||
{
|
||||
"$type": "CommandSystem::CommandCreateMotionEvent",
|
||||
"eventTrackName": "GameState",
|
||||
"eventDatas": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"$type": "MotionSamplingRule"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -112,7 +112,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
PRIVATE
|
||||
Gem::SceneProcessing.Editor.Static
|
||||
AZ::AzTest
|
||||
AZ::SceneData
|
||||
)
|
||||
ly_add_googletest(
|
||||
NAME Gem::SceneProcessing.Editor.Tests
|
||||
|
||||
+22
-105
@@ -96,85 +96,6 @@ namespace AZ::SceneGenerationComponents
|
||||
namespace Containers = AZ::SceneAPI::Containers;
|
||||
namespace Views = Containers::Views;
|
||||
|
||||
// @brief A class to map from a mesh's vertex index to it's welded vertex index
|
||||
//
|
||||
// When the mesh optimizer runs, it welds nearby vertices (if there are no blendshapes). This class provides a
|
||||
// constant time lookup to map from an unwelded vertex index to the welded one.
|
||||
// The welding works by rounding the vertex's position to the given position tolerance, then uses that rounded
|
||||
// Vector3 as a key into a unordered_map.
|
||||
template <class MeshDataType>
|
||||
class Vector3Map
|
||||
: private AZStd::unordered_map<AZ::Vector3, AZ::u32>
|
||||
{
|
||||
public:
|
||||
Vector3Map(const MeshDataType* meshData, bool hasBlendShapes, float positionTolerance)
|
||||
: m_meshData(meshData)
|
||||
, m_hasBlendShapes(hasBlendShapes)
|
||||
, m_positionTolerance(positionTolerance)
|
||||
, m_positionToleranceReciprocal(1.0f / positionTolerance)
|
||||
{
|
||||
}
|
||||
|
||||
using AZStd::unordered_map<AZ::Vector3, AZ::u32>::reserve;
|
||||
|
||||
AZ::u32 operator[](const AZ::u32 vertexIndex)
|
||||
{
|
||||
if (m_hasBlendShapes)
|
||||
{
|
||||
// Don't attempt to weld similar vertices if there's blendshapes
|
||||
// Welding the vertices here based on position could cause the vertices of a base shape to be welded,
|
||||
// and the vertices of the blendshape to not be welded, resulting in a vertex count mismatch between
|
||||
// the two
|
||||
return m_meshData->GetUsedPointIndexForControlPoint(m_meshData->GetControlPointIndex(vertexIndex));
|
||||
}
|
||||
|
||||
const auto& [iter, didInsert] = try_emplace(GetPositionForIndex(vertexIndex), m_currentOriginalVertexIndex);
|
||||
if (didInsert)
|
||||
{
|
||||
++m_currentOriginalVertexIndex;
|
||||
}
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
[[nodiscard]] AZ::u32 at(const AZ::u32 vertexIndex) const
|
||||
{
|
||||
if (m_hasBlendShapes)
|
||||
{
|
||||
// Don't attempt to weld similar vertices if there's blendshapes
|
||||
// Welding the vertices here based on position could cause the vertices of a base shape to be welded,
|
||||
// and the vertices of the blendshape to not be welded, resulting in a vertex count mismatch between
|
||||
// the two
|
||||
return m_meshData->GetUsedPointIndexForControlPoint(m_meshData->GetControlPointIndex(vertexIndex));
|
||||
}
|
||||
|
||||
auto iter = find(GetPositionForIndex(vertexIndex));
|
||||
AZSTD_CONTAINER_ASSERT(iter != end(), "Element with key is not present");
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
AZ::Vector3 GetPositionForIndex(const AZ::u32 vertexIndex) const
|
||||
{
|
||||
// Round the vertex position so that a float comparison can be made with entires in the map
|
||||
// pos = floor( x * 10 + 0.5) * 0.1
|
||||
return AZ::Vector3(
|
||||
AZ::Simd::Vec3::Floor(
|
||||
(m_meshData->GetPosition(vertexIndex) * m_positionToleranceReciprocal + AZ::Vector3(0.5f)).GetSimdValue()
|
||||
)
|
||||
) * m_positionTolerance;
|
||||
}
|
||||
|
||||
const MeshDataType* m_meshData;
|
||||
bool m_hasBlendShapes;
|
||||
float m_positionTolerance;
|
||||
float m_positionToleranceReciprocal;
|
||||
AZ::u32 m_currentOriginalVertexIndex = 0;
|
||||
};
|
||||
|
||||
template<class MeshDataType>
|
||||
Vector3Map(const MeshDataType*) -> Vector3Map<const MeshDataType>;
|
||||
|
||||
MeshOptimizerComponent::MeshOptimizerComponent()
|
||||
{
|
||||
BindToCall(&MeshOptimizerComponent::OptimizeMeshes);
|
||||
@@ -185,7 +106,7 @@ namespace AZ::SceneGenerationComponents
|
||||
auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<MeshOptimizerComponent, GenerationComponent>()->Version(4);
|
||||
serializeContext->Class<MeshOptimizerComponent, GenerationComponent>()->Version(2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,8 +115,7 @@ namespace AZ::SceneGenerationComponents
|
||||
const MeshDataType* meshData,
|
||||
const SkinWeightDataView& skinWeights,
|
||||
AZ::u32 maxWeightsPerVertex,
|
||||
float weightThreshold,
|
||||
const Vector3Map<MeshDataType>& positionMap)
|
||||
float weightThreshold)
|
||||
{
|
||||
if (skinWeights.empty())
|
||||
{
|
||||
@@ -221,12 +141,15 @@ namespace AZ::SceneGenerationComponents
|
||||
for (size_t linkIndex = 0; linkIndex < linkCount; ++linkIndex)
|
||||
{
|
||||
const ISkinWeightData::Link& link = skinData.get().GetLink(controlPointIndex, linkIndex);
|
||||
skinningInfo->AddInfluence(positionMap.at(usedPointIndex), {aznumeric_caster(link.boneId), link.weight});
|
||||
skinningInfo->AddInfluence(usedPointIndex, {aznumeric_caster(link.boneId), link.weight});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
skinningInfo->Optimize(maxWeightsPerVertex, weightThreshold);
|
||||
if (skinningInfo)
|
||||
{
|
||||
skinningInfo->Optimize(maxWeightsPerVertex, weightThreshold);
|
||||
}
|
||||
|
||||
return skinningInfo;
|
||||
}
|
||||
@@ -269,12 +192,17 @@ namespace AZ::SceneGenerationComponents
|
||||
const AZStd::vector<AZStd::pair<const IMeshData*, NodeIndex>> meshes = [](const SceneGraph& graph)
|
||||
{
|
||||
AZStd::vector<AZStd::pair<const IMeshData*, NodeIndex>> meshes;
|
||||
const auto meshNodes = Containers::MakeDerivedFilterView<IMeshData>(graph.GetContentStorage());
|
||||
for (auto it = meshNodes.cbegin(); it != meshNodes.cend(); ++it)
|
||||
for (auto it = graph.GetContentStorage().cbegin(); it != graph.GetContentStorage().cend(); ++it)
|
||||
{
|
||||
// Skip anything that isn't a mesh.
|
||||
const auto* mesh = azdynamic_cast<const AZ::SceneAPI::DataTypes::IMeshData*>(it->get());
|
||||
if (!mesh)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the mesh data and node index and store them in the vector as a pair, so we can iterate over them later.
|
||||
// The sequential calls to GetBaseIterator unwrap the layers of FilterIterators from the MakeDerivedFilterView
|
||||
meshes.emplace_back(&(*it), graph.ConvertToNodeIndex(it.GetBaseIterator().GetBaseIterator().GetBaseIterator()));
|
||||
meshes.emplace_back(mesh, graph.ConvertToNodeIndex(it));
|
||||
}
|
||||
return meshes;
|
||||
}(graph);
|
||||
@@ -359,12 +287,6 @@ namespace AZ::SceneGenerationComponents
|
||||
|
||||
auto [optimizedMesh, optimizedUVs, optimizedTangents, optimizedBitangents, optimizedVertexColors, optimizedSkinWeights] = OptimizeMesh(mesh, mesh, uvDatas, tangentDatas, bitangentDatas, colorDatas, skinWeightDatas, meshGroup, hasBlendShapes);
|
||||
|
||||
AZ_TracePrintf(AZ::SceneAPI::Utilities::LogWindow, "Base mesh: %zu vertices, optimized mesh: %zu vertices, %0.02f%% of the original",
|
||||
mesh->GetUsedControlPointCount(),
|
||||
optimizedMesh->GetUsedControlPointCount(),
|
||||
((float)optimizedMesh->GetUsedControlPointCount() / (float)mesh->GetUsedControlPointCount()) * 100.0f
|
||||
);
|
||||
|
||||
const NodeIndex optimizedMeshNodeIndex = graph.AddChild(graph.GetNodeParent(nodeIndex), name.c_str(), AZStd::move(optimizedMesh));
|
||||
|
||||
auto addOptimizedNodes = [&graph, &optimizedMeshNodeIndex](const auto& originalNodeIndexes, auto& optimizedNodes)
|
||||
@@ -506,9 +428,10 @@ namespace AZ::SceneGenerationComponents
|
||||
const AZStd::vector<MeshBuilder::MeshBuilderVertexAttributeLayerVector3*> bitangentLayers = makeLayersForData(bitangents);
|
||||
const AZStd::vector<MeshBuilder::MeshBuilderVertexAttributeLayerColor*> vertexColorLayers = makeLayersForData(vertexColors);
|
||||
|
||||
constexpr float positionTolerance = 0.0001f;
|
||||
Vector3Map positionMap(meshData, hasBlendShapes, positionTolerance);
|
||||
positionMap.reserve(vertexCount);
|
||||
const auto* skinRule = meshGroup.GetRuleContainerConst().FindFirstByType<SceneAPI::DataTypes::ISkinRule>().get();
|
||||
const AZ::u32 maxWeightsPerVertex = skinRule ? skinRule->GetMaxWeightsPerVertex() : 4;
|
||||
const float weightThreshold = skinRule ? skinRule->GetWeightThreshold() : 0.001f;
|
||||
meshBuilder.SetSkinningInfo(ExtractSkinningInfo(meshData, skinWeights, maxWeightsPerVertex, weightThreshold));
|
||||
|
||||
// Add the vertex data to all the layers
|
||||
const AZ::u32 faceCount = meshData->GetFaceCount();
|
||||
@@ -517,8 +440,8 @@ namespace AZ::SceneGenerationComponents
|
||||
meshBuilder.BeginPolygon(baseMesh->GetFaceMaterialId(faceIndex));
|
||||
for (const AZ::u32 vertexIndex : meshData->GetFaceInfo(faceIndex).vertexIndex)
|
||||
{
|
||||
const AZ::u32 orgVertexNumber = positionMap[vertexIndex];
|
||||
|
||||
const int orgVertexNumber = meshData->GetUsedPointIndexForControlPoint(meshData->GetControlPointIndex(vertexIndex));
|
||||
AZ_Assert(orgVertexNumber >= 0, "Invalid vertex number");
|
||||
orgVtxLayer->SetCurrentVertexValue(orgVertexNumber);
|
||||
|
||||
posLayer->SetCurrentVertexValue(meshData->GetPosition(vertexIndex));
|
||||
@@ -548,12 +471,6 @@ namespace AZ::SceneGenerationComponents
|
||||
|
||||
meshBuilder.EndPolygon();
|
||||
}
|
||||
|
||||
const auto* skinRule = meshGroup.GetRuleContainerConst().FindFirstByType<SceneAPI::DataTypes::ISkinRule>().get();
|
||||
const AZ::u32 maxWeightsPerVertex = skinRule ? skinRule->GetMaxWeightsPerVertex() : 4;
|
||||
const float weightThreshold = skinRule ? skinRule->GetWeightThreshold() : 0.001f;
|
||||
meshBuilder.SetSkinningInfo(ExtractSkinningInfo(meshData, skinWeights, maxWeightsPerVertex, weightThreshold, positionMap));
|
||||
|
||||
meshBuilder.GenerateSubMeshVertexOrders();
|
||||
|
||||
// Create the resulting nodes
|
||||
|
||||
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <AzCore/Component/ComponentApplication.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/Jobs/JobManagerComponent.h>
|
||||
#include <AzCore/Memory/MemoryComponent.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzCore/std/smart_ptr/shared_ptr.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Scene.h>
|
||||
#include <SceneAPI/SceneCore/Containers/SceneGraph.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshData.h>
|
||||
#include <SceneAPI/SceneCore/DataTypes/GraphData/ISkinWeightData.h>
|
||||
#include <SceneAPI/SceneCore/Events/GenerateEventContext.h>
|
||||
#include <SceneAPI/SceneCore/Utilities/SceneGraphSelector.h>
|
||||
#include <SceneAPI/SceneData/GraphData/MeshData.h>
|
||||
#include <SceneAPI/SceneData/GraphData/SkinWeightData.h>
|
||||
#include <SceneAPI/SceneData/Groups/MeshGroup.h>
|
||||
#include <Generation/Components/MeshOptimizer/MeshOptimizerComponent.h>
|
||||
|
||||
#include <InitSceneAPIFixture.h>
|
||||
|
||||
namespace AZ::SceneAPI::DataTypes
|
||||
{
|
||||
void PrintTo(const ISkinWeightData::Link& link, ::std::ostream* os)
|
||||
{
|
||||
*os << '{' << link.boneId << ", " << link.weight << '}';
|
||||
}
|
||||
}
|
||||
|
||||
namespace SceneProcessing
|
||||
{
|
||||
class VertexDeduplicationFixture
|
||||
: public SceneProcessing::InitSceneAPIFixture
|
||||
{
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
SceneProcessing::InitSceneAPIFixture::SetUp();
|
||||
|
||||
m_systemEntity = m_app.Create({}, {});
|
||||
m_systemEntity->AddComponent(aznew AZ::MemoryComponent());
|
||||
m_systemEntity->AddComponent(aznew AZ::JobManagerComponent());
|
||||
m_systemEntity->Init();
|
||||
m_systemEntity->Activate();
|
||||
}
|
||||
void TearDown() override
|
||||
{
|
||||
m_systemEntity->Deactivate();
|
||||
SceneProcessing::InitSceneAPIFixture::TearDown();
|
||||
}
|
||||
|
||||
static AZStd::unique_ptr<AZ::SceneAPI::DataTypes::IMeshData> MakePlaneMesh()
|
||||
{
|
||||
// Create a simple plane with 2 triangles, 6 total vertices, 2 shared vertices
|
||||
// 0 --- 1
|
||||
// | / |
|
||||
// | / |
|
||||
// | / |
|
||||
// 2 --- 3
|
||||
const AZStd::array planeVertexPositions = {
|
||||
AZ::Vector3{0.0f, 0.0f, 0.0f},
|
||||
AZ::Vector3{0.0f, 0.0f, 1.0f},
|
||||
AZ::Vector3{1.0f, 0.0f, 1.0f},
|
||||
AZ::Vector3{1.0f, 0.0f, 1.0f},
|
||||
AZ::Vector3{1.0f, 0.0f, 0.0f},
|
||||
AZ::Vector3{0.0f, 0.0f, 0.0f},
|
||||
};
|
||||
|
||||
auto mesh = AZStd::make_unique<AZ::SceneData::GraphData::MeshData>();
|
||||
|
||||
int i = 0;
|
||||
for (const AZ::Vector3& position : planeVertexPositions)
|
||||
{
|
||||
mesh->AddPosition(position);
|
||||
mesh->AddNormal(AZ::Vector3::CreateAxisY());
|
||||
|
||||
// This assumes that the data coming from the import process gives a unique control point
|
||||
// index to every vertex. This follows the behavior of the AssImp library.
|
||||
mesh->SetVertexIndexToControlPointIndexMap(i, i);
|
||||
++i;
|
||||
}
|
||||
|
||||
mesh->AddFace({0, 1, 2}, 0);
|
||||
mesh->AddFace({3, 4, 5}, 0);
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
static AZStd::unique_ptr<AZ::SceneData::GraphData::SkinWeightData> MakeSkinData()
|
||||
{
|
||||
auto skinWeights = AZStd::make_unique<AZ::SceneData::GraphData::SkinWeightData>();
|
||||
|
||||
skinWeights->ResizeContainerSpace(6);
|
||||
|
||||
// Add bones 0 and 1 to the skin weights
|
||||
skinWeights->GetBoneId("0");
|
||||
skinWeights->GetBoneId("1");
|
||||
|
||||
skinWeights->AppendLink(0, {/*.boneId=*/0, /*.weight=*/1});
|
||||
skinWeights->AppendLink(1, {/*.boneId=*/0, /*.weight=*/1});
|
||||
skinWeights->AppendLink(2, {/*.boneId=*/0, /*.weight=*/1});
|
||||
skinWeights->AppendLink(3, {/*.boneId=*/1, /*.weight=*/1});
|
||||
skinWeights->AppendLink(4, {/*.boneId=*/1, /*.weight=*/1});
|
||||
skinWeights->AppendLink(5, {/*.boneId=*/1, /*.weight=*/1});
|
||||
|
||||
return skinWeights;
|
||||
}
|
||||
|
||||
private:
|
||||
AZ::ComponentApplication m_app;
|
||||
AZ::Entity* m_systemEntity;
|
||||
};
|
||||
|
||||
TEST_F(VertexDeduplicationFixture, CanDeduplicateVertices)
|
||||
{
|
||||
AZ::SceneAPI::Containers::Scene scene("testScene");
|
||||
AZ::SceneAPI::Containers::SceneGraph& graph = scene.GetGraph();
|
||||
|
||||
const auto meshNodeIndex = graph.AddChild(graph.GetRoot(), "testMesh", MakePlaneMesh());
|
||||
|
||||
// The original source mesh should have 6 vertices
|
||||
EXPECT_EQ(AZStd::rtti_pointer_cast<AZ::SceneAPI::DataTypes::IMeshData>(graph.GetNodeContent(meshNodeIndex))->GetVertexCount(), 6);
|
||||
|
||||
auto meshGroup = AZStd::make_unique<AZ::SceneAPI::SceneData::MeshGroup>();
|
||||
meshGroup->GetSceneNodeSelectionList().AddSelectedNode("testMesh");
|
||||
scene.GetManifest().AddEntry(AZStd::move(meshGroup));
|
||||
|
||||
AZ::SceneGenerationComponents::MeshOptimizerComponent component;
|
||||
AZ::SceneAPI::Events::GenerateSimplificationEventContext context(scene, "pc");
|
||||
component.OptimizeMeshes(context);
|
||||
|
||||
AZ::SceneAPI::Containers::SceneGraph::NodeIndex optimizedNodeIndex = graph.Find(AZStd::string("testMesh").append(AZ::SceneAPI::Utilities::OptimizedMeshSuffix));
|
||||
ASSERT_TRUE(optimizedNodeIndex.IsValid()) << "Mesh optimizer did not add an optimized version of the mesh";
|
||||
|
||||
const auto& optimizedMesh = AZStd::rtti_pointer_cast<AZ::SceneAPI::DataTypes::IMeshData>(graph.GetNodeContent(optimizedNodeIndex));
|
||||
ASSERT_TRUE(optimizedMesh);
|
||||
|
||||
// The optimized mesh should have 4 vertices, the 2 shared vertices are welded together
|
||||
EXPECT_EQ(optimizedMesh->GetVertexCount(), 4);
|
||||
}
|
||||
|
||||
MATCHER(VectorOfLinksEq, "")
|
||||
{
|
||||
return testing::ExplainMatchResult(
|
||||
testing::AllOf(
|
||||
testing::Field(&AZ::SceneData::GraphData::SkinWeightData::Link::boneId, testing::Eq(testing::get<0>(arg).boneId)),
|
||||
testing::Field(&AZ::SceneData::GraphData::SkinWeightData::Link::weight, testing::FloatEq(testing::get<0>(arg).weight))
|
||||
),
|
||||
testing::get<1>(arg),
|
||||
result_listener
|
||||
);
|
||||
}
|
||||
|
||||
MATCHER(VectorOfVectorOfLinksEq, "")
|
||||
{
|
||||
return testing::ExplainMatchResult(
|
||||
testing::UnorderedPointwise(VectorOfLinksEq(), testing::get<0>(arg)),
|
||||
testing::get<1>(arg),
|
||||
result_listener
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(VertexDeduplicationFixture, DeduplicatedVerticesRemapSkinning)
|
||||
{
|
||||
AZ::SceneAPI::Containers::Scene scene("testScene");
|
||||
AZ::SceneAPI::Containers::SceneGraph& graph = scene.GetGraph();
|
||||
|
||||
const auto meshNodeIndex = graph.AddChild(graph.GetRoot(), "testMesh", MakePlaneMesh());
|
||||
const auto skinDataNodeIndex = graph.AddChild(meshNodeIndex, "skinData", MakeSkinData());
|
||||
graph.MakeEndPoint(skinDataNodeIndex);
|
||||
|
||||
// The original source mesh should have 6 vertices
|
||||
EXPECT_EQ(AZStd::rtti_pointer_cast<AZ::SceneAPI::DataTypes::IMeshData>(graph.GetNodeContent(meshNodeIndex))->GetVertexCount(), 6);
|
||||
|
||||
auto meshGroup = AZStd::make_unique<AZ::SceneAPI::SceneData::MeshGroup>();
|
||||
meshGroup->GetSceneNodeSelectionList().AddSelectedNode("testMesh");
|
||||
scene.GetManifest().AddEntry(AZStd::move(meshGroup));
|
||||
|
||||
AZ::SceneGenerationComponents::MeshOptimizerComponent component;
|
||||
AZ::SceneAPI::Events::GenerateSimplificationEventContext context(scene, "pc");
|
||||
component.OptimizeMeshes(context);
|
||||
|
||||
AZ::SceneAPI::Containers::SceneGraph::NodeIndex optimizedNodeIndex = graph.Find(AZStd::string("testMesh").append(AZ::SceneAPI::Utilities::OptimizedMeshSuffix));
|
||||
ASSERT_TRUE(optimizedNodeIndex.IsValid()) << "Mesh optimizer did not add an optimized version of the mesh";
|
||||
|
||||
const auto& optimizedMesh = AZStd::rtti_pointer_cast<AZ::SceneAPI::DataTypes::IMeshData>(graph.GetNodeContent(optimizedNodeIndex));
|
||||
ASSERT_TRUE(optimizedMesh);
|
||||
|
||||
AZ::SceneAPI::Containers::SceneGraph::NodeIndex optimizedSkinDataNodeIndex = graph.Find(AZStd::string("testMesh").append(AZ::SceneAPI::Utilities::OptimizedMeshSuffix).append(".skinWeights"));
|
||||
ASSERT_TRUE(optimizedSkinDataNodeIndex.IsValid()) << "Mesh optimizer did not add an optimized version of the skin data";
|
||||
|
||||
const auto& optimizedSkinWeights = AZStd::rtti_pointer_cast<AZ::SceneAPI::DataTypes::ISkinWeightData>(graph.GetNodeContent(optimizedSkinDataNodeIndex));
|
||||
ASSERT_TRUE(optimizedSkinWeights);
|
||||
|
||||
const AZStd::vector<AZStd::vector<AZ::SceneData::GraphData::SkinWeightData::Link>> expectedLinks
|
||||
{
|
||||
/*0*/ { {0, 0.5f}, {1, 0.5f} },
|
||||
/*1*/ { {0, 1.0f} },
|
||||
/*2*/ { {0, 0.5f}, {1, 0.5f} },
|
||||
/*3*/ { {1, 1.0f} },
|
||||
};
|
||||
|
||||
AZStd::vector<AZStd::vector<AZ::SceneData::GraphData::SkinWeightData::Link>> gotLinks(optimizedMesh->GetVertexCount());
|
||||
for (unsigned int vertexIndex = 0; vertexIndex < optimizedMesh->GetVertexCount(); ++vertexIndex)
|
||||
{
|
||||
for (size_t linkIndex = 0; linkIndex < optimizedSkinWeights->GetLinkCount(vertexIndex); ++linkIndex)
|
||||
{
|
||||
gotLinks[vertexIndex].emplace_back(optimizedSkinWeights->GetLink(vertexIndex, linkIndex));
|
||||
}
|
||||
}
|
||||
EXPECT_THAT(gotLinks, testing::Pointwise(VectorOfVectorOfLinksEq(), expectedLinks));
|
||||
}
|
||||
} // namespace SceneProcessing
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
set(FILES
|
||||
Tests/InitSceneAPIFixture.h
|
||||
Tests/MeshBuilder/MeshOptimizerComponentTests.cpp
|
||||
Tests/MeshBuilder/MeshBuilderTests.cpp
|
||||
Tests/MeshBuilder/MeshVerticesTests.cpp
|
||||
Tests/MeshBuilder/SkinInfluencesTests.cpp
|
||||
|
||||
Reference in New Issue
Block a user